背景
場景:
- 遊戲、SaaS行業. serverless 場景: 在一個企業内部, 業務線非常多,
- 在同一個執行個體中有多個業務共同使用時,
- 分析師、DBA或者營運人員有偶爾使用資料庫的需求.
挑戰:
- 為每個業務配置設定一個資料庫執行個體存在的問題: 資源浪費(每個執行個體在記憶體、空間方面的浪費)、彈性較差(建立資源慢、擴容縮容慢).
- 多個業務共享一個執行個體存在的問題: 資源争搶、幹擾、抖動、安全風險增加,
- DBA或分析師人為的大查詢可能将資源耗光, 影響線上業務
PG 方案:
- 按來源IP、USER、DBNAME、application_name等資訊來區分使用者和業務
- 結合cgroup隔離業務的cpu、io、網絡等資源使用率, 防止幹擾
例子
cgroup 配置舉例
限制組cgroupA的任務最多可以使用8核資源
限制組cgroupB的任務最多可以使用16核資源
加載CPU子系統,建立子資源分區
mount -t cgroup -o cpu cpu /cgroup/cpu
cd /cgroup/cpu
mkdir cgroupA
mkdir cgroupB
配置資源配比(以100為基數,核數乘以100即得到cpu.shares)
echo 800 > cpu.shares
echo 1000000 > cpu.cfs_period_us
echo 8000000 > cpu.cfs_quota_us
cd ../cgroupB
echo 1600 > cpu.shares
echo 1000000 > cpu.cfs_period_us
echo 16000000 > cpu.cfs_quota_us
将PID放入某個cgroup組
建立一個shell将PID放入某個cgroup組
腳本内容略
配置允許PG程序的啟動賬号sudo執行該指令
202011/20201107_03.md 《Linux : 使用sudoedit 配置- 允許普通使用者a以另一個使用者b或組g執行某些特定指令》
在資料庫中建立plpythonu, 調用shell, 将目前會話PID放入對應cgroup
create or replace function exec_cmd2(cmd text) returns setof text as $$
import os
v = os.popen('/home/digoal/cpu_cgroup.sh ' + cmd)
return v
$$ language plpythonu;
以下例子, 簡單粗暴的邏輯,
- postgres 使用者登陸後, 會話對應的backend PID 會塞入cgroupA
- digoal 使用者登陸後, 會話對應的backend PID 會塞入cgroupB
實際使用中可以配置一個映射表,從映射表裡面擷取規則.
declare
pid int := pg_backend_pid();
begin
case current_user
when 'postgres' then perform exec_cmd2(format('%s %s',pid, 'cgroupA'));
when 'digoal' then perform exec_cmd2(format('%s %s',pid, 'cgroupB'));
else raise notice 'not mapping users cgroup';
end case;
end;
$$ language plpgsql strict;
配置login hook, 建立會話時, 自動執行以上函數
session_preload_libraries = 'session_exec'
session_exec.login_name = 'exec_cmd'
postgres 使用者登陸後, 會話對應的backend PID 會塞入cgroupA
digoal 使用者登陸後, 會話對應的backend PID 會塞入cgroupB
更複雜的邏輯
限制邏輯還可以更複雜一點, 例如, 根據:
- 來源IP
- 登陸的使用者
- 登陸的資料庫
- application_name(使用者在連接配接URL裡面可以設定, 用來區分不同的業務)
- 登陸的時間
- 目前執行個體級資源使用率
- 目前各個cgroup的資源使用率
- 目前映射的cgroup的資源使用率
實施動作:
- 将目前會話的PID放入某個cgoup組進行限制
- 擴大或縮小某個cgroup的限制上限. 例如淩晨放大BI業務的限制, 白天縮小BI業務的限制.
其他cgoup可以限制的名額:
- io, 讀寫吞吐, 網絡流量, 記憶體等