systemd による cgroups v2 のリソース制限

11分で読めます - 2026年6月3日

hero section cover
目次
  • systemd における cgroups v2 のリソース制限
  • cgroups v2 の有効化
  • systemdによるcgroupの管理方法
  • CPU制限
  • cgroups v2 におけるメモリ制限
  • I/O制限
  • スライスによるマルチテナント分離
  • systemd-cgtop および PSI による監視
共有

cgroups v2とsystemdでCPU、メモリ、I/Oの制限を設定する。マルチテナント Linux ホストのための実用的な設定、PSI 監視とスライス分離。

systemd における cgroups v2 のリソース制限

cgroups v2は、Linuxカーネルの統合リソース制御フレームワークです。 これは、断片化されていた v1 の階層構造に代わり、CPU、メモリ、I/O を一貫して処理する単一のツリー構造を採用しており、Docker、Kubernetes、および systemd におけるコンテナの分離を支えています。本記事では、cgroups v2 を有効にする方法、systemd 経由で制限を設定する方法、および実際のマルチテナントホスティング環境に適用する方法について解説します。

cgroups v2 の有効化

最新のディストリビューションでは、cgroups v2 がデフォルトで有効になっています:Ubuntu 21.10 以降、Debian 11 以降、Fedora 31 以降、および RHEL/Rocky 9 以降。古いシステムでは、ハイブリッド階層が実行されているか、依然として v1 がデフォルトとなっている場合があります。以下で確認してください:

stat -fc %T /sys/fs/cgroup/

の出力 cgroup2fs の出力が v2 が有効であることを確認します。 tmpfs は通常、v1を意味します。

ハイブリッドシステムを純粋な v2 に変更するには、 /etc/default/grub を編集し、 GRUB_CMDLINE_LINUX_DEFAULT:

systemd.unified_cgroup_hierarchy=1 cgroup_no_v1=all

その後、GRUBを再生成して再起動します:

sudo update-grub
sudo reboot

本番環境では、v2用のcgroup freezerを利用できるようカーネル5.2以降を実行し、完全な cpuset Rocky Linux 8およびRHEL 8では、以下の行を /etc/systemd/system.conf:

DefaultCPUAccounting=yes
DefaultMemoryAccounting=yes
DefaultIOAccounting=yes

で再読み込みします sudo systemctl daemon-reexecで再読み込みします。再起動後、利用可能なコントローラーを確認します:

cat /sys/fs/cgroup/cgroup.controllers

次のように表示されるはずです cpu, memory, io, および pids がリストされるはずです。これらのコントローラーは、デフォルトでは子cgroupに対して有効になっていません。これらを有効にするには、ルートサブツリー制御ファイルに書き込みます:

echo "+cpu +memory +io" | sudo tee /sys/fs/cgroup/cgroup.subtree_control

v2が内部的にv1とどのように異なるかについて詳しく知りたい場合は、Michael Kerrisk氏のNDC TechTownでの講演が最も優れた情報源です:

systemdによるcgroupの管理方法

systemdは、起動するサービスごとに、そのユニットの名前を付けたcgroupを作成します。 nginx.service gets /sys/fs/cgroup/system.slice/nginx.service/、そして起動されたすべてのプロセスはその cgroup 内に存在します。3 つのユニットタイプが階層構造に直接対応しています:

ユニットタイプ役割説明
.slice内部ノード関連するサービスをグループ化し、共有リミットを定義します
.serviceターミナルノードシステムDによって開始されたプロセスを管理する
.scopeリーフノード外部から起動されたプロセス(コンテナのペイロード、ログインセッション)を追跡する

4つのデフォルトスライスが初期状態で提供されます: -.slice (root)、 system.slice, user.slice、および machine.slice。スライスに適用された制限は、その中のすべてのサービスに自動的に適用されます。

v2のルールとして覚えておくべき点:プロセスはリーフノードにのみ存在できます。子cgroupを持つcgroupはプロセスを直接ホストできないため、systemdは決してサービスをスライスのトランクに配置しません。

制限は、 /sys/fs/cgroup/ に直接書き込むのではなく、常に systemd を通じてリミットを設定してください。手動での書き込みは再起動後も維持されず、階層に対する systemd の排他的な所有権と競合します。 systemctl set-property を使用し、恒久的な変更にはsystemctl edit nginx.service)を使用してください。

CPU制限

cgroups v2 では、2 つの CPU 制御機能を提供します。ハードキャップ(cpu.max、systemd では CPUQuota として公開)と、比例ウェイト(cpu.weight / CPUWeight).

CPUQuota は絶対的な上限です。 CPUQuota=50% は半コア分、 CPUQuota=200% は2コア分の時間を割り当てます。それ以上を使用しようとすると、CPUの他の部分がどれほどアイドル状態であっても、サービスはスロットリングされます。

CPUWeight は競合が発生している場合にのみ意味を持ちます。範囲は1から10,000で、デフォルトは100です。重みがそれぞれ150、100、50の3つのサービスが同時にCPU時間を要求した場合、それぞれ約50%、33%、17%のCPU時間を割り当てられます。 それ以外の場合、CPUがアイドル状態であれば、重みは一切制約となりません。

レイテンシに敏感なワークロードの場合、 AllowedCPUs=。これによりコンテキストスイッチが削減され、コアごとのキャッシュがホットな状態を維持されます:

[Service]
CPUQuota=200%
CPUWeight=150
AllowedCPUs=0-3

予測可能なコストが必要な場合(マルチテナント課金、ノイジーネイバーの隔離など)は、ハードクォータを使用してください。ハードウェアの利用率を最大化し、負荷のピーク時にのみ優先順位付けが必要な場合は、重みを使用してください。

cgroups v2 におけるメモリ制限

メモリには2つの階層があります: memory.high (ソフト、スロットリング)と memory.max (ハード、OOM)です。スワップ、ページ回収、およびカーネルの OOM キラーに関する背景については、Linux メモリ管理に関する関連記事をご覧ください。

メモリ制限を memory.highmemory.maxに設定します。この閾値を超えると、カーネルはページの回収と割り当てのスロットリングを開始します memory.high を超えると、カーネルはページの回収と割り当てのスロットリングを開始します。これにより、通常はOOMキラーが作動する前にワークロードが回復します。使用率が memory.maxに達すると、カーネルはcgroup内のプロセスを強制終了します。

一般的な設定例:

[Service]
MemoryHigh=400M
MemoryMax=512M
MemorySwapMax=0

MemorySwapMax=0 この cgroup ではスワップを無効にします。スワップ I/O がテールレイテンシを著しく悪化させるような、レイテンシに敏感なワークロード(データベース、リアルタイムストリーミング)では、この設定を行う価値があります。

孤立した兄弟プロセスを残すと共有状態が破損するワーカープールの場合、 1 cgroupの memory.oom.group ファイルに書き込んでください。1つのプロセスがOOMキルされた際、カーネルはcgroup内のすべてのプロセスをまとめて終了させます。

ファイルを確認して memory.events を確認して、サービスがどのくらいの頻度でスロットリングされたりOOMキルされたりしているかを確認します:

cat /sys/fs/cgroup/system.slice/nginx.service/memory.events

The high および oom_kill カウンターは、制限値が適切に設定されているかを示します。ゼロ以外の値が持続的に表示される場合は、ワークロードにさらなる余裕が必要であることを意味します。

I/O制限

I/O コントローラも同様の 2 モード設計を採用しています。 io.max による比例配分 io.weight.

制限はブロックデバイスごとに設定され、major:minor 番号で識別されます。これらは lsblk -o NAME,MAJ:MINで特定できます。典型的な systemd 設定:

[Service]
IOReadBandwidthMax=/dev/sda 50M
IOWriteBandwidthMax=/dev/sda 30M
IOReadIOPSMax=/dev/sda 1000
IOWriteIOPSMax=/dev/sda 500

io.weight は次のように機能します cpu.weight:範囲は1~10,000で、デフォルトは100です。ユーザー向けサービスに500を割り当て、夜間バックアップに50を割り当てることで、ピーク時にバックアップがディスクを飽和させるのを防ぎつつ、他に需要がない時はフル帯域幅を使用できるようにします。

I/O制限は、適切なデバイスを指定した場合にのみ適用されます。カーネルはブロックデバイス単位でI/Oを追跡するため、 /dev/sda への制限は、 /dev/nvme0n1へのI/Oには効果がありません。複数のディスクがあるホストでは、デバイスごとに制限を設定してください。

スライスによるマルチテナント分離

共有環境では、テナントごとにスライスを定義します。 /etc/systemd/system/tenant-a.slice:

[Slice]
CPUQuota=200%
CPUWeight=150
MemoryHigh=3584M
MemoryMax=4096M
MemorySwapMax=0
IOReadBandwidthMax=/dev/sda 200M
TasksMax=512

TasksMax=512 caps を使用することでプロセスとスレッドの総数を制限し、あるテナントでのフォークボムがホストをダウンさせるのを防ぎます。テナントのサービスをこのスライスに配置し( Slice=tenant-a.slice ユニットファイル内で)配置することで、それらはすべてを自動的に継承します。

このパターンは、ノイズの多いバックグラウンド作業をユーザー向けサービスから分離する場合にも有効です。バックアップ、ログのローテーション、バッチジョブを background.slice リソース使用量の少ない CPUWeight および io.weight 値を設定したに配置します。これらはシステムがアイドル状態のときにリソースをフルに利用し、本番トラフィックが到着すると処理を控えます。

DockerPodman などのコンテナランタイムでは、 Delegate=yes をシステムdユニットファイルに追加します。これにより、root権限なしで独自のサブcgroupを管理できるようになり、親スライスに設定された制限は下位のすべてのプロセスに適用されます。

systemd-cgtop および PSI による監視

cgroup ごとの CPU、メモリ、I/O のリアルタイムな top スタイルの表示を行うには、以下を実行します:

systemd-cgtop

静的な階層構造や各プロセスの配置を確認するには、以下を使用します systemd-cgls.

本番環境の監視において、v2で最も有用な機能はPressure Stall Information(PSI)です。PSIは、cgroup内のタスクがリソース待ちでストールしていた時間の割合を報告し、cgroupごとに3つのファイルとして公開されます:

cat /sys/fs/cgroup/tenant-a.slice/cpu.pressure
cat /sys/fs/cgroup/tenant-a.slice/memory.pressure
cat /sys/fs/cgroup/tenant-a.slice/io.pressure

利用率が100%でプレッシャーが0%のCPUは健全な状態です。CPUを必要とするすべてのタスクが、それを取得できていることを意味します。同じCPUでも、利用率が80%でプレッシャーが30%の場合は、タスクが実行時間を待ってキューに入っていることを意味します。利用率ではなくPSIでアラートを出してください。利用率のメトリクスでは完全に見逃されてしまう競合を、PSIは捕捉できるからです。

再起動なしで動的に制限値を調整できます:

sudo systemctl set-property tenant-a.slice MemoryMax=6144M

変更は即座に適用され、再起動後も維持されます。PSI ベースのアラートと組み合わせることで、OOM キルや制御不能なレイテンシに発展する前に、負荷の変動に対応できます。

高密度のマルチテナントワークロードを実行しており、これらのポリシーを確実に適用できる余裕のあるホストが必要な場合、当社の専用サーバーはまさにそのために設計されています。

ブログ

今週の特集

その他の記事
パワフルで無制限のVPSが重要な理由

パワフルで無制限のVPSが重要な理由

無制限VPSは固定ポート速度で定額帯域幅を提供します。従量制プランとの違いや、どのような場合にお得なのか、購入前に確認すべきことなどについて説明します。

7分で読めます - 2025年5月9日

Linuxのメモリ管理:スワップ、OOMキラー、Cグループ

12分で読めます - 2026年5月31日

その他の記事
background image

ご質問またはカスタムソリューションが必要ですか?

icon

柔軟なオプション

icon

グローバル・リーチ

icon

即時展開

icon

柔軟なオプション

icon

グローバル・リーチ

icon

即時展開