同様の質問があります: Cgroups、ユーザーごとのメモリ制限 ですが、このソリューションはcgroup階層がsystemdによって管理されている「最新の」システムでは機能しません。
簡単な解決策— user-UID.sliceのテンプレート化—機能しません。サポートされていないためです https://github.com/systemd/systemd/issues/2556 を参照してください。
望ましい効果を達成する方法はありますか?ユーザーごとにCPUおよび/またはメモリリソースを管理しますか?
[〜#〜] upd [〜#〜]:履歴のためにソリューションを保持しますが、_systemctl set-property
_はログイン時に_pam_exec
_を使用して呼び出されます https://github.com/hashbang/Shell-etc/pull/18 を参照してください。このアプローチでは、ユーザーのログインと制限の設定の間に時間枠はありません。
私の解決策。 インターフェイス_org.freedesktop.login1.Manage
_ of _/org/freedesktop/login1
_オブジェクト はUserNew(u uid, o object_path)
シグナルを発行します。シグナルをリッスンする単純なデーモンを作成し、それが発行されるたびに、ログインしたユーザーのスライスに_CPUAccounting=true
_を設定しました。
[〜#〜] upd [〜#〜]:履歴のためにソリューションを保持しますが、systemctl set-property
はログイン時にpam_exec
を使用して呼び出されます。 https://github.com/hashbang/Shell-etc/pull/18 を参照してください。このアプローチでは、ユーザーのログインと制限の設定の間に時間枠はありません。
古いソリューション
これは仕事をする非常に単純なスクリプトです
#!/bin/bash
STATE=1 # 1 -- waiting for signal; 2 -- reading UID
dbus-monitor --system "interface=org.freedesktop.login1.Manager,member=UserNew" |
while read line
do
case $STATE in
1) [[ $line =~ member=UserNew ]] && STATE=2 ;;
2) read dbus_type ID <<< $line
systemctl set-property user-$ID.slice CPUAccounting=true
STATE=1
;;
esac
done
ユーザーごとのメモリ制限をサポートするように簡単に拡張できます。
VM 2 CPUと2ユーザーでテストしました。最初のユーザーはdd if=/dev/zero of=/dev/null | dd if=/dev/zero of=/dev/null
コマンドを実行し、2番目のユーザーはdd
のインスタンスを1つだけ実行します。このスクリプトなしでは実行中、dd
の各インスタンスはCPUの約70%を使用しました。
次に、スクリプトを開始し、ユーザーを再度ログインさせ、dd
コマンドに再びスターを付けました。今回は、最初のユーザーの2つのdd
プロセスがそれぞれ50%のCPUしか使用せず、2番目のユーザーのプロセスが100%のCPUを使用しました。また、systemd-cgtop
は、/user.slice/user-UID1.slice
と/user.slice/user-UID2.slice
がそれぞれCPU時間の100%を消費することを示しましたが、最初のスライスには6つのタスクがあり、2番目のスライスには5つのタスクしかありません。
2番目のユーザーのdd
タスクをkillすると、最初のユーザーがCPU時間の200%を消費し始めます。したがって、「各ユーザーが使用できるコアは1つだけ」などの人為的な制限なしに、公平なリソース割り当てが可能です。
Systemd v239以降では、ドロップインを使用できます https://github.com/systemd/systemd/commit/5396624506e155c4bc10c0ee65b939600860ab67
# mkdir -p /etc/systemd/system/user-.slice.d
# cat > /etc/systemd/system/user-.slice.d/50-memory.conf << EOF
[Slice]
MemoryMax=1G
EOF
# systemctl daemon-reload
あなたが言及した問題はまだオープンですが、これは私にとってはうまくいきます。
Sudo systemctl edit --force user-1234.slice
次に、これを入力して保存します。
[Slice]
CPUQuota=10%
なぜ機能するのかわかりません。
Cgroupsを介してCPUまたはメモリの制限を達成する別の可能性は、libpam-cgroup
を使用することです。これにより、ログイン時に/etc/cgconfig.conf
からプロファイルを選択できます。一般的に見られる例は次のとおりです。
group limited {
cpu {
cpu.cfs_period_us = "1000000";
cpu.cfs_quota_us = "500000";
}
memory {
memory.limit_in_bytes = "1G";
memory.memsw.limit_in_bytes = "1G";
}
}
これにより、リソースを1 GBのメモリとCPUコアの50%に制限するinteractive
グループが作成されます(合計CPU時間の1秒あたり500ミリ秒)。次に、/etc/cgrules.conf
ファイルを設定して、特定のグループまたはユーザーをこのグループの下に置くことができます。
root cpu,memory /
@nolimits cpu,memory /
* cpu,memory /limited
この場合、root
とnolimits
グループに属する全員がデフォルトの(無制限の)cgroupを取得しますが、他のすべてのユーザーは上記のポリシーセットによって制限されます。
最初に一致する行が使用されるため、次のように特定のユーザーまたはグループを制限しながら、デフォルトの無制限ポリシーを設定できます。
spam cpu,memory /limited
* cpu,memory /
この場合、spam
ユーザーを制限し、他のユーザーは制限しません。
これが機能するためには、たとえばpam_cgroup.so
PAMプロファイルで/etc/pam.d/sshd
を有効にする必要があります。
session optional pam_cgroup.so
最後に、cgrules.conf
ファイルを起動時に解析する必要があります。これは、シンプルなsystemdサービスで実現できます。
[Unit]
Description=Load cgroup profiles
[Service]
Type=oneshot
ExecStart=/usr/sbin/cgconfigparser -l /etc/cgconfig.conf
[Install]
WantedBy=multi-user.target
これは、たとえば/etc/systemd/system/loadcg.service
に保存して、systemctl enable loadcg
で有効にすることができます。