systemd resource を使用して、Linux サービスの CPU、RAM、I/O、PID を的確に制御し、生産性の高いサービスを計画的に運用できるようにしています。 以下の手順では、ユニットやスライスで制限を設定し、cgroups v2を基盤として活用し、明確なルールに基づいてリソース競合を解消する方法を、実践的な例を交えて紹介します。これにより、すべての インスタンス 予測可能だ。
中心点
以下の概要は、記事の中で詳しく説明している主なポイントをまとめたものであり、手っ取り早く把握するためのものです。 ガイド.
- cgroups v2 systemdを中央管理ツールとする統一された階層構造として
- ユニットの種類 サービス、スコープ、スライスを的確に組み合わせる
- CPUクォータ そして CPUウェイト CPUのリソースを公平に配分するために
- メモリーマックス そして メモリーハイ OOMおよび帯域制限対策
- スライス サーバー運用におけるグループ制限と優先順位について
systemdとcgroups v2が連携する理由
私はすべてのプロセスをcgroups v2で管理し、systemdを 管制センター. /sys/fs/cgroup 配下の統一された階層構造により、cpu、memory、io、pids といったコントローラーが明確にまとめられています。 各ユニットには独自の cgroup が割り当てられるため、サービスファミリー全体に対して一貫して制限を適用できます。この構造により、グループ全体として扱われるため、個々の PID が制限を回避することを防ぎます。 systemd バージョン 232 以降、systemd はこの階層を排他的に管理し、リミットをカーネルインターフェースに書き込んでいます。制御をすり抜けることがないように、私は意図的にのみ委任を許可しています。このようにして、私は自分の リソース いつでも制御可能。.
ユニットの種類を理解する:サービス、スコープ、スライス
私はクラシックなデーモンを サービス-ユニットを作成し、外部から起動されたプロセスをスコープにまとめます。階層構造については、グループ全体のリソースを定義する内部ノードとしてスライスを作成します。 サービスとスコープはツリーの葉を構成し、それぞれのスライスから制限値を継承します。このようにして、各サービスを個別に扱うのではなく、ツリー全体に沿ってCPU、メモリ、I/Oの予算を配分しています。初心者の方には、以下の内容をご覧になることをお勧めします。 ホスティングサービスを効率的に管理する, 、サーバー運用におけるユニットの役割を理解し、独自の スライス を計画する。.
前提条件の確認:統一された階層構造とコントローラー
システムがユニファイドモードで動作しており、必要なすべてのコントローラがアクティブになっていることを確認します。これは、/sys/fs/cgroup(マウントポイント)の存在と、systemdがツリー構造を管理していることからも確認できます。 コントローラ(例:io)が欠落している場合は、カーネル設定を確認し、必要に応じてブートパラメータも確認します。 特に古い環境では、IOWeight、MemoryHigh、AllowedCPUsといった記述されたディレクティブが有効になるよう、意図的にv1からv2へ移行します。アカウンティングとコントローラーが機能して初めて、重み付けやクォータの微調整を行う価値が生まれます。.
CPUの管理:CPUWeightとCPUQuotaの正しい活用方法
私は以下を通じてCPUの使用率を制御しています CPUクォータ また、CPUWeight を使って相対的な優先順位を設定します。50% というクォータを設定すると、そのサービスはコア時間の半分に制限されますが、ウェイトを 200 に設定すると、ウェイトが小さいサービスよりも優先されます。これにより、インタラクティブなサービスの動作を妨げることなく、継続的に負荷をかけるジョブを調整しています。 実際には、まず適度なクォータを設定して開始し、レイテンシを監視しながら、重要なサービスのウェイトを引き上げていきます。このようにして、 計算時間 ランダムな負荷ではなく、重要度に基づいて。.
CPUアフィニティ、AllowedCPUs、およびクォータ期間
コアを固定で割り当てたい場合は、CPUAffinity または AllowedCPUs によるよりきめ細かな cpuset 制御を利用します。これにより、例えば、バッチワークロードとレイテンシに敏感なサービスを別々のコアに分離することができます。 バースト処理の場合は、CPUQuotaPeriodSec を調整します。期間を長く設定すると、同じ平均クォータの範囲内で一時的な大きな変動が許容されるため、スパイクが発生しやすいサービスにおいて P99 レイテンシが改善されます。.
[サービス]
# コア選択 (sched_affinity) 対 cpuset (cgroup v2)
CPUAffinity=0 1 2 3
AllowedCPUs=0-3
# 150% 200ms 周期での総時間(バーストの余裕拡大)
CPUQuota=150%
CPUQuotaPeriodSec=200ms
# 同一スライス内での相対重み
CPUWeight=200
MemoryMax、MemoryHigh、MemoryLow によるメモリ制限
私は次のように厳格な制限を設けています。 メモリーマックス, 、異常値によるOOM(メモリ不足)状態を防ぐためです。MemoryHigh を使用することで、メモリが限界に達する前にアクセス量を抑制し、システム全体の安定性を高めます。 MemoryLowおよびMemoryMinは、カーネルがまず他のグループのメモリを回収するように、サービスに保護領域を提供します。この段階的な設定により、複数のサービスが同時に拡大した場合の連鎖的な影響を防ぐことができます。このコントローラーに関する詳細情報をお探しの方は、 メモリコントローラの仕組み 関連する内容についてのわかりやすい入門 メカニズム.
スワップ戦略とOOM時の挙動を意図的に設定する
各ユニットがスワップを使用できるかどうか、またその使用量を明確に定義します。MemorySwapMax を使用して、RAM とスワップの合計使用量に上限を設定します。レイテンシが重要なサービスについては、ページアウトを防ぐために、スワップの使用を大幅に制限するか、あるいは無効にする場合がよくあります。 さらに、OOMScoreAdjust を使用して、カーネルが個々のプロセスを終了させる確率を調整し、OOMPolicy を使用して、ユニット内で OOM が発生した際に systemd がどのように反応するかを決定します(例:ユニット全体を停止させるか、実行を継続させるか)。.
[サービス]
# スワップを含めて最大2G;RAMのハードリミットはMemoryMaxのまま
MemoryMax=1.5G
MemorySwapMax=2G
# OOM判定の優先度(数値が小さいほど保護レベルが高い)
OOMScoreAdjust=-500
# ユニット内でOOMキラーが作動した際の対応
OOMPolicy=stop
この組み合わせにより、制御不能なスワップを防ぎ、定義済みのフェイルオーバーシナリオを確保し、データベースやインメモリキャッシュを、計画可能な枠組みの下で確実に管理しています。.
I/Oおよびプロセスリミット:IOWeight、帯域幅、TasksMax
私は以下によって読み取りおよび書き込み速度を制限しています IOReadBandwidthMax また、ディスクを共有する場合は IOWriteBandwidthMax を使用します。相対的な優先順位付けには IOWeight を使用し、中核となるワークロードがバッチストリームよりも優先されるようにしています。 TasksMax を使用して、プロセスとスレッドに明確な上限を設定することで、フォークボムを効果的に阻止しています。これらの制御により、個々のジョブが I/O 全体を独占してしまうようなマルチサーバー環境が安定化されます。特にビルドサーバーでは、これにより再現性の高い スループット より。
デバイスごとのI/Oを個別に制御する
NVMeとHDDが混在する環境では、デバイスごとに調整を行っています。これにより、高速なSSDが、HDD上の「騒がしい隣人」によってパフォーマンスが低下するのを防ぐことができます。デバイスごとの相対的な重み付けと絶対的な上限値の組み合わせにより、実運用上のほとんどのケースに対応できます。.
[サービス]
# すべてのデバイスに対する相対重み
IOWeight=300
# デバイスごとの重み(例:NVMeを優先)
IODeviceWeight=/dev/nvme0n1 500
IODeviceWeight=/dev/sda 100
# デバイスごとの絶対上限(読み取り/書き込み速度)
IOReadBandwidthMax=/dev/sda 50M
IOWriteBandwidthMax=/dev/sda 30M
重要:IOWeightはアクティブなcgroup間でのみ相対的に機能します。Maxディレクティブは絶対的な上限を設定します。私はまず重み設定から始め、確実に「Noisy Neighbors」を捕捉する必要がある場合にのみ、絶対的な上限を追加するようにしています。.
設定:Unitファイル、ドロップイン、set-property
私は制限を直接 ユニット-File を追加するか、元のファイルをそのまま残すドロップインを使用します。systemctl edit NAME.service を使って、CPUQuota、CPUWeight、MemoryMax などのディレクティブを追加する設定断片を作成します。 簡単なテストには `systemctl set-property` を使用します。systemd はこの変更をドロップインに適切に書き込みます。調整後はデーモンを再読み込みし、ステータスを確認して変更が反映されているか検証します。この作業方法により、アップデート時の競合を防ぎ、各 修正 明確な経緯がある。.
ドロップインの優先順位、プリセット、およびデフォルト設定
ドロップインの順序には注意しています。systemdは数値順に読み込むため、例えば「90-override.conf」はそれより前の「10-*.conf」を上書きします。ベンダーのプリセットには手を加えず、パッケージの更新時に問題が生じないよう、/etc内のファイルを上書きするようにしています。 DefaultTasksMax、DefaultCPUAccounting、DefaultMemoryAccounting といったシステム全体のデフォルト設定については、新しいユニットに対しても統一されたメトリクスと安全対策が確保されるよう、意図的に systemd.conf に設定しています。.
# 有効な値の確認
systemctl show NAME.service -p CPUQuota -p CPUWeight -p MemoryMax
systemd-analyze dump | grep -E "Default(TasksMax|CPUAccounting|MemoryAccounting)"
# 永続的なオーバーライドファイルを開く/作成する
systemctl edit NAME.service
Slicesの実践:グループを適切に制限する
関連するサービスをそれぞれ独自の スライス, 、例えば web.slice、db.slice、batch.slice などです。例えば batch.slice では、バックグラウンドジョブがフロントエンドの処理を圧迫することなく十分なリソースを確保できるよう、200% CPU と 4G RAM を割り当てています。 サービスは「Slice=」を使用して対象のスライスに割り当てます。これにより、制限はグループ内のすべてのメンバーに共通して適用されます。このグループ化により、ポリシー管理が大幅に簡素化されます。新しいチームプロジェクトは、そのスライスのポリシーを自動的に引き継ぎます。また、独立した顧客グループやアプリグループについては、以下を確認することも役立ちます。 cgroupsによる分離, 、分離をきれいに プラン.
標準スライス:system.slice、user.slice、machine.slice
私はシステムサービスを system.slice そして、重要なサービスがリソース不足に陥らないよう、そこでは慎重にグローバルな上限を設定しています。ユーザープロセスは user.slice に配置され、ここではシェルを完全にブロックすることなく、対話型セッションに制限を設けています。 仮想化環境とコンテナは machine.slice にまとめ、VM やコンテナごとに明確なリソース上限を設定しています。この標準的な構造は秩序をもたらし、独自のスライスを設定するための有意義な基準点となります。適切に継承を行えば、個別のルールを数多く設定する手間を省き、 透明性 高い。
コンテナおよび動的ワークロードのデリゲーション
コンテナランタイムやユーザー主導のツールにサブツリーを引き渡す際、私は意図的に、制御が必要な箇所に限り「Delegate=yes」を設定しています。これにより、systemdが統括権を維持しつつ、委任先はそのサブツリー内で独自のcgroupを作成できるようになります。 これをスコープと組み合わせることで、短命なプロセス(CIジョブなど)を、スライスを希薄化させることなく、適切に収集・制限し、再び解放することができます。.
[サービス]
# cgroupサブツリーの制御を委譲可能にする(例:コンテナランタイムによる)
Delegate=yes
Slice=machine.slice
MemoryMax=4G
CPUWeight=300
監視とトラブルシューティング:status、cgtop、cgls
まず、次のように確認します。 systemctl status NAME.service を確認し、どの制限が有効か、またサービスの動作状況を確認します。systemd-cgtop を使用すると、cgroup ごとの CPU およびメモリ使用量をリアルタイムで確認できます。systemd-cgls はツリー構造を表示し、継承関係を可視化します。 異常が見られた場合は、/sys/fs/cgroup 内のファイルを読み込み、コントローラーに設定された値を確認します。その後、クォータを段階的に調整し、メトリクスを監視しながら、各変更を記録します。 修正.
モニタリングの理解を深める:アカウンティング、PSI、および迅速なテスト
有意義なメトリクスを取得するために、CPUAccounting、MemoryAccounting、IOAccountingをユニット単位またはデフォルトで有効にしています。 さらに、カーネル内のPressure情報(PSI)を用いて負荷のピークを監視し、スロットリング(memory.high)が強化されているか、あるいはI/Oが恒常的に逼迫しているかを把握します。 再現性のあるテストを行うために、systemd-runをスコープとしてワークロードを起動し、一時的な制限を設定した上で、それを永続的なドロップインに組み込んでいます。.
# I/OおよびCPUの重み付けを設定した一時スコープ
systemd-run --scope -p IOWeight=400 -p CPUWeight=300 --unit test-batch -- dd if=/dev/zero of=/tmp/out bs=1M count=1024
既存のユニットで # アカウンティングを有効にする
systemctl set-property NAME.service CPUAccounting=yes MemoryAccounting=yes IOAccounting=yes
トラブルシューティングと典型的な障害
- Harsh Caps 対 Burst:期間を調整せずに CPUQuota を厳しすぎると、処理がカクつきます。私は CPUQuotaPeriodSec を増やすか、クォータを適度に下げるようにし、CPUWeight をより積極的に活用しています。.
- メモリスロットルの動作が早すぎる:MemoryHighの値が低すぎるのか? クリティカルパスが過度に積極的に回収されないよう、この値を上げるか、MemoryLowを定義するつもりだ。.
- I/O デバイスのアドレス設定が誤っています:IO* ディレクティブはブロックデバイスを想定しています。lsblk コマンドでデバイスパスを確認し、マウントポイントごとではなく、デバイスごとにルールを設定します。.
- スレッド数が上限に達している:TasksMaxの値が低すぎると、ワーカープールのパフォーマンスが低下する。ピーク時のスレッド数に余裕を加えた値でリソースを割り当て、systemd-cgtopで「Tasks」列を監視している。.
- 効果のないドロップイン:変更後、systemctl daemon-reload を実行し、systemctl show を使ってプロパティが実際に設定されているかを確認します。.
優先順位と境界に関するベストプラクティス
サービスを役割ごとにグループ分けし、重要度に応じてCPUWeightとIOWeightを割り当て、次のようにして厳格なメモリ制限を設定します。 メモリーマックス. 重要なデータベースには高い重み付けと比較的緩やかなクォータが設定される一方、レポートやバッチジョブにはより厳しい制限が課されます。TasksMaxは、アプリケーションが多数のワーカーを使用する場合や、スレッド爆発のリスクがある場合に設定します。 すべての調整内容はバージョン管理され、リポジトリに保存されます。これにより、変更履歴を追跡し、必要に応じてロールバックすることが可能です。ステージング環境では、負荷プロファイルに基づいて値を調整し、その後、保守的な設定で本番環境に反映します。 製造.
主要なディレクティブの一覧表
この簡潔な表には、一般的な設定がまとめられており、適切な 価値観 を選ぶ。
| 目的 | 指令 | 値の例 | 効果 |
|---|---|---|---|
| CPUシェア | CPUウェイト | 200 | ウェイトの小さいユニットよりも優先度を高め、配分する CPU 公平だ。. |
| CPU使用率 | CPUクォータ | 50% | 利用可能なコアタイムを最大限に活用;継続的な負荷がかかる業務に最適 求人. |
| ハードディスク | メモリーマックス | 1G | 絶対リミット。同じ範囲内の異常値によるOOMを防ぐ スライス. |
| ソフトメモリー | メモリーハイ | 800M | マックスの前でスロットルを絞る;これにより、 システム. |
| I/O優先度 | IOWeight | 500 | 共有リソース上の集中型サービスを優先する ディスク. |
| PID/スレッド | タスクマックス | 512 | プロセス/スレッド数を制限し、以下から保護します フォークス-雪崩。. |
ホスティングおよびサーバー運用における活用事例
私は依頼人のために独自の スライス 顧客ごとにCPUとRAMの予算を設定します。マイクロサービス環境では、APIサービスと認証サービスに高い優先度を割り当て、レポート処理は非同期で実行します。CI/CDランナーについては、ビルドがフロントエンドを圧迫しないよう、バッチスライスを作成します。 コンテナおよびVM環境では、ワークロードをmachine.slice内にカプセル化し、テナントごとの予算を明確に管理しています。この分割により、ノイジー・ネイバー効果を低減し、再現性を確保しています。 遅延時間 ピーク時。.
概要
systemd と cgroups v2 を使用して Linux サービスを管理しています 単位 個々のプロセスではなく。CPUQuota、CPUWeight、MemoryMax、MemoryHigh、IOWeight、TasksMaxが、公平な割り当てと明確な上限を設定するための私の基本セットです。 スライスは秩序をもたらし、ガイドラインを統合し、運用や新規サービスの導入を容易にします。systemctl status、cgtop、cgls によるモニタリングにより、調整が必要な箇所を早期に把握できます。これにより、パフォーマンスと可用性を計画通りに維持でき、リソースの競合も最小限に抑えることができます。 コントロール.


