コントロール・グループを使用したリソースの管理

制御グループがプロセスを編成する方法、systemdによるリソース・ポリシーの適用方法、およびcgroupを手動で管理するタイミングについて説明します。

cgroupsと呼ばれる制御グループは、systemdサービスを編成し、必要に応じて個々のプロセス(PIDs)を、CPU、メモリー、I/Oなどのシステム・リソースを割り当てるための階層グループに編成するOracle Linuxカーネル機能です。

たとえば、CPU時間の割当てが必要な3つのプロセスを150:100:50の比率で特定した場合は、3つcgroupsを作成し、それぞれに比率の3つ値のいずれかに対応するCPUの重みを割り当て、各cgroupに適切なプロセスを割り当てます。

重要

systemdを使用して、cgroupを構成します。

/sys/fs/cgroup仮想ファイル・システム(このトピックで説明)でcgroupディレクトリを手動で作成すると、基礎となる概念を説明するのに役立ちます。ただし、一時的なデバッグやテストなどの特定のシナリオでは、このアプローチを使用します。ほとんどのユース・ケースでは、systemdを使用してcgroupsを構成し、正確で永続的なリソース管理を確保します。

デフォルトでは、systemdは次のものに対してcgroupを作成します:

  • ホストに設定された各systemdサービス。

    たとえば、サーバーには、NetworkManagerサービスによって所有されるプロセスをグループ化する制御グループNetworkManager.serviceと、firewalldサービスによって所有されるプロセスをグループ化する制御グループfirewalld.serviceなどがあります。

  • ホストの各ユーザー(UID)。

cgroup機能は/sys/fs/cgroupに仮想ファイル・システムとしてマウントされています。各cgroupには、/sys/fs/cgroupファイル・システム内の対応するディレクトリがあります。たとえば、管理するサービスに対してsystemdによって作成されたcgroupsは、次のサンプル・コード・ブロックに示すように、コマンドls -l /sys/fs/cgroup/system.slice | grep ".service"を実行することで確認できます。

ls -l /sys/fs/cgroup/system.slice | grep ".service"
            ...root root 0 Mar 22 10:47 atd.service
            ...root root 0 Mar 22 10:47 auditd.service
            ...root root 0 Mar 22 10:47 chronyd.service
            ...root root 0 Mar 22 10:47 crond.service
            ...root root 0 Mar 22 10:47 dbus-broker.service
            ...root root 0 Mar 22 10:47 dtprobed.service
            ...root root 0 Mar 22 10:47 firewalld.service
            ...root root 0 Mar 22 10:47 httpd.service
            ...

また、/sys/fs/cgroup仮想ファイル・システムの下にディレクトリを作成し、システム要件に従ってプロセスID (PIDs)を異なるcgroupsに割り当てることで、カスタムcgroupsを作成することもできます。ただし、/sys/fs/cgroup.の下に手動でcgroupsを作成するのではなく、systemdを使用してcgroupsを構成することをお薦めします。

cgroupssystemdで管理する推奨方法は、Systemdを使用した制御グループの管理を参照してください。

Linuxカーネルでは、2つのバージョンの制御グループを使用できます。

制御グループ・バージョン1 (cgroups v1)

リソース単位のコントローラ階層を提供します。各リソース(CPU、メモリー、I/Oなど)には、独自の制御グループ・ツリーがあります。これにより、リソース間の調整が困難になる可能性があります。レガシーAPIを使用します。現在は非推奨と見なされましたが、サポートされているシステムでは互換性があります。

制御グループ・バージョン2 (cgroups v2)

すべてのコントローラに統一された単一の階層を使用することで、リソース間の調整を改善し、管理を簡素化できます。最新の簡略化されたAPIを使用します。これは、推奨され、積極的に開発された実装です。

次の表に、Oracle Linuxリリースごとの可用性をまとめます。

Oracle Linuxリリースによるcgroupsバージョンのサポート
Oracle Linuxリリース cgroups v1 cgroups v2
Oracle Linux 8 使用可能(デフォルト) 使用可能(手動で有効化)
Oracle Linux 9 使用可能(互換性) 使用可能(デフォルト)
Oracle Linux 10 使用不可(非推奨) 使用可能(デフォルト)

コントロール・グループの詳細は、cgroups(7)およびsysfs(5)のマニュアル・ページを参照してください。

Oracle Linux 8でのcgroups v2の有効化

  1. 現在のマウントを確認します。
    sudo mount -l | grep cgroup

    出力に/sys/fs/cgroup上のcgroup2がすでに表示されている場合は、それ以上のアクションは必要ありません。

  2. 統合階層ブート・パラメータを追加します。
    sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"

    このコマンドは、systemd.unified_cgroup_hierarchy=1を各カーネル・エントリに追加して、version2がブート時にマウントされるようにします。

  3. 再起動して変更を適用します。
  4. cgroups v2がマウントされていることを確認します。
    sudo mount -l | grep cgroup

    出力でcgroup2 on /sys/fs/cgroupを探します。

Oracle Linux 9およびOracle Linux 10でのcgroups v2の確認

マウント・ポイントを確認します。
sudo mount -l | grep cgroup
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate,memory_recursiveprot)

カーネル・リソース・コントローラについて

制御グループは、カーネル・リソース・コントローラを介してリソースの使用を管理します。カーネル・リソース・コントローラは、CPU時間、メモリー、ネットワーク帯域幅、ディスクI/Oなどの単一のリソースを表します。

システムにマウントされたリソース・コントローラを識別するには、/procs/cgroupsファイルの内容を確認します。次に例を示します:

less /proc/cgroups
#subsys_name    hierarchy       num_cgroups     enabled
cpuset  0       103     1
cpu     0       103     1
cpuacct 0       103     1
blkio   0       103     1
memory  0       103     1
devices 0       103     1
freezer 0       103     1
net_cls 0       103     1
perf_event      0       103     1
net_prio        0       103     1
hugetlb 0       103     1
pids    0       103     1
rdma    0       103     1
misc    0       103     1

cgroupsのカーネル・リソース・コントローラの詳細な説明は、cgroups(7)マニュアル・ページをご覧ください。

制御グループ・ファイル・システムについて

cgroup機能は、/sys/fs/cgroupに階層ファイル・システムとしてマウントされています。

ディレクトリ/sys/fs/cgroupは、ルート制御グループとも呼ばれます。

ルート制御グループのディレクトリの内容は、マウントされたバージョンによって若干異なりますが、cgroups v2を使用するシステムでは、通常、次のようなエントリが表示されます。

ls /sys/fs/cgroup
cgroup.controllers      cpuset.mems.effective  memory.stat
cgroup.max.depth        cpu.stat               misc.capacity
cgroup.max.descendants  dev-hugepages.mount    sys-fs-fuse-connections.mount
cgroup.procs            dev-mqueue.mount       sys-kernel-config.mount
cgroup.stat             init.scope             sys-kernel-debug.mount
cgroup.subtree_control  io.pressure            sys-kernel-tracing.mount
cgroup.threads          io.stat                system.slice
cpu.pressure            memory.numa_stat       user.slice
cpuset.cpus.effective   memory.pressure
mkdirコマンドを使用して、ルート制御グループ内にcgroupサブディレクトリを作成できます。たとえば、次のcgroupサブディレクトリを作成します。
  • /sys/fs/cgroup/MyGroups/

  • /sys/fs/cgroup/MyGroups/cgroup1

  • /sys/fs/cgroup/MyGroups/cgroup2

Note

Best design practice is for child cgroups to be at least 2 levels deep inside the /sys/fs/cgroup. 前述のリストの例では、最初の子グループMyGroupsを、システムに必要な様々なcgroupsを含む親として使用することで、このプラクティスに従っています。

階層内の各cgroupには、次のファイルが含まれます。

cgroup.controllers

この読取り専用ファイルには、現在のcgroupで使用可能なコントローラがリストされます。このファイルの内容は、親のcgroup内のcgroup.subtree_control ファイルの内容と一致します。

cgroup.subtree_control

このファイルには、現在のcgroupの直下の子cgroupsに対して有効になっているcgroup.controllersファイル内のコントローラが含まれています。

コントローラ(pidsなど)が cgroup.subtree_controlファイルに存在する場合、対応するコントローラ・インタフェース・ファイル(pids.maxなど)は、現在のcgroupの直下の子に自動的に作成されます。

アプリケーションのリソース管理を実装できる子グループを作成する手順の例は、CPUの重みの設定によるCPU時間配分の制御を参照してください。

cgroupを削除するには、cgroupに他の子グループが含まれていないことを確認してから、ディレクトリを削除します。たとえば、子グループ/sys/fs/cgroup/MyGroups/cgroup1を削除するには、次のコマンドを実行します。

sudo rmdir /sys/fs/cgroup/MyGroups/cgroup1

リソース配分モデルについて

次の配分モデルでは、cgroups v2で使用するリソースを配分するときに制御または規制を実装する方法について説明します:

加重

このモデルでは、すべての制御グループの重みが合計されます。各グループは、合計の重みに対するグループの重みの比率に基づいて、リソースの一部を受け取ります。

10個の制御グループについて考えてみます。それぞれの重みは100で、合計は1000です。この場合、各グループは、指定されたリソースの10分の1を使用できます。

通常、重みはステートレス・リソースの配分に使用されます。このリソースを適用するには、CPUWeightオプションが使用されます。

制限

このモデルでは、グループは最大でリソースの構成量を使用できます。プロセスのメモリー使用量などのリソースが制限を超えた場合、カーネルはメモリー不足(oom)メッセージでプロセスを停止することがあります。

また、サブグループの制限の合計が親グループの制限を超えることができるように、リソースをオーバーコミットすることもできます。過剰コミットメントは、すべてのサブグループのリソースが同時にすべてのリソースが制限に達する可能性が低いことを前提としています。

この配分モデルを実装するには、MemoryMaxオプションが使用されます。

保護

このモデルでは、グループに保護された境界が割り当てられます。グループのリソース使用量が保護された量に収まっている場合、カーネルは、同じリソースについて競合する他のグループのためにリソースの使用を奪うことはできません。このモデルでは、リソースのオーバーコミットが許可されます。

このモデルを実装するには、MemoryLowオプションが使用されます。

割当て

このモデルでは、リアルタイム予算など、有限タイプのリソースの使用に対して特定の絶対金額が割り当てられます。

sysfsを使用したcgroups v2の管理

トラブルシューティングまたは一時テストのために、/sys/fs/cgroupでcgroups v2階層を直接作成およびチューニングする方法を示します。

重要

systemdを使用して、可能なかぎりすべてのリソース管理を処理します。詳細は、「Systemdを使用した制御グループの管理」を参照してください。

ここに示す例では、systemdがシステムで実行し、systemd以外の機能を表示するアクションのコンテキストを示します。提供される情報は、cgroupsの問題をデバッグする際に役に立ちます。

この手順の例では、それぞれに異なるアプリケーションPIDを割り当てられたcgroups間でCPU時間を割り当てています。CPU時間およびアプリケーションPID値は、各グループのCPU.weightおよびcgroup.procsファイルに設定されています。

また、この例には、cpuコントローラおよびそれに関連付けられたファイル(cpu.weightファイルを含む)を、 /sys/fs/cgroupの下に作成する必要のあるcgroupsで使用できるようにするために必要な手順も含まれています。

CPU時間の配分のための制御グループの準備

この手順では、CPU時間の分布を管理するために制御グループを手動で準備する方法について説明します。制御グループを構成するための推奨方法は、systemdを使用することです。

  1. cpuコントローラが階層の最上位のルート・コントロール・グループで使用できることを確認します。

    /sys/fs/cgroup/cgroup.controllersファイルの内容を画面に出力します。

    sudo cat /sys/fs/cgroup/cgroup.controllers
    cpuset cpu io memory hugetlb pids rdma misc

    cgroup.controllersファイルにリストされているコントローラを同じディレクトリのcgroup.subtree_controlファイルに追加して、グループの直下の子cgroupsで使用できるようにすることができます。

  2. cpuコントローラをcgroup.subtree_controlファイルに追加して、その直下の子cgroupsで使用できるようにします。

    デフォルトでは、memoryおよびpidsコントローラのみがファイルに含まれます。cpuコントローラを追加するには、次のように入力します。

    echo "+cpu" | sudo tee /sys/fs/cgroup/cgroup.subtree_control
    
  3. オプションで、cpuコントローラが期待どおりに追加されたことを確認します。
    sudo cat /sys/fs/cgroup/cgroup.subtree_control
    cpu memory pids
  4. ルート制御グループの下に、アプリケーションのCPUリソースを管理するための新しい制御グループになる子グループを作成します。
    sudo mkdir /sys/fs/cgroup/MyGroups
  5. 必要に応じて、新しいサブディレクトリまたは子グループの内容をリストし、cpuコントローラが期待どおりに存在することを確認します。
    ls -l /sys/fs/cgroup/MyGroups
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 cgroup.controllers
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 cgroup.events
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.freeze
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.max.depth
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.max.descendants
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.procs
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 cgroup.stat
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.subtree_control
    …​
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 cpu.stat
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cpu.weight
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cpu.weight.nice
    …​
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 memory.events.local
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 memory.high
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 memory.low
    …​
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 pids.current
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 pids.events
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 pids.max
  6. MyGroupsディレクトリのcgroup.subtree_controlファイルでcpuコントローラを有効にして、その直下の子cgroupsで使用できるようにします。
    echo "+cpu" | sudo tee /sys/fs/cgroup/MyGroups/cgroup.subtree_control
  7. 必要に応じて、cpuコントローラがMyGroupsの子グループに対して有効になっていることを確認します。
    sudo cat /sys/fs/cgroup/MyGroups/cgroup.subtree_control
    cpu

CPU時間の配分を調整するためのCPU重量の設定

この手順では、制御グループを使用してCPU時間の分布を管理することによって、3つの異なるプロセスのCPUウェイトを設定する方法について説明します。制御グループを構成するための推奨方法は、systemdを使用することです。

この手順は、次の仮定に基づいています。

  • 次のtopコマンドの出力例に示すように、CPUリソースを過度に消費しているアプリケーションはsha1sumです:

    sudo top
    ...
    PID   USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
    33301 root      20   0   18720   1756   1468 R  99.0   0.0   0:31.09 sha1sum
    33302 root      20   0   18720   1772   1480 R  99.0   0.0   0:30.54 sha1sum
    33303 root      20   0   18720   1772   1480 R  99.0   0.0   0:30.54 sha1sum
    1 root      20   0  109724  17196  11032 S   0.0   0.1   0:03.28 systemd                     
    2 root      20   0       0      0      0 S   0.0   0.0   0:00.00 kthreadd                    
    3 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_gp                      
    4 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_par_gp                  
              ...
  • 前述のサンプル出力に示されているように、sha1sumプロセスには、PID 33301、33302および33303があります。

重要

以降の手順の前提条件として、CPU時間の配分のための制御グループの準備の説明に従って、cgroup-v2の準備を完了する必要があります。これらの準備をスキップした場合、この手順は完了できません。

  1. MyGroupsサブディレクトリに3つの子グループを作成します。
    sudo mkdir /sys/fs/cgroup/MyGroups/g1
    sudo mkdir /sys/fs/cgroup/MyGroups/g2
    sudo mkdir /sys/fs/cgroup/MyGroups/g3
  2. 子グループごとにCPUの重みを構成します。
    echo "150" | sudo tee /sys/fs/cgroup/MyGroups/g1/cpu.weight
    echo "100" | sudo tee /sys/fs/cgroup/MyGroups/g2/cpu.weight
    echo "50" | sudo tee /sys/fs/cgroup/MyGroups/g3/cpu.weight
  3. アプリケーションPIDを対応する子グループに適用します。
    echo "33301" | sudo tee /sys/fs/cgroup/MyGroups/g1/cgroup.procs
    echo "33302" | sudo tee /sys/fs/cgroup/MyGroups/g2/cgroup.procs
    echo "33303" | sudo /sys/fs/cgroup/MyGroups/g3/cgroup.procs

    これらのコマンドは、選択したアプリケーションをMyGroups/g*/制御グループのメンバーになるように設定します。各sha1sumプロセスのCPU時間は、各グループに対して構成されたCPU時間配分によって異なります。

    実行中のプロセスを持つg1g2およびg3グループの重みは、親制御グループであるMyGroupsのレベルで合計されます。

    この構成では、すべてのプロセスが同時に実行されると、カーネルは、次のように、それぞれのcgroupcpu.weightファイルに基づいて比例するCPU時間を各sha1sumプロセスに割り当てます。

    子グループ cpu.weight設定 CPU時間割当ての割合
    g1 150 ~50% (150/300)
    g2 100 ~33% (100/300)
    g3 50 ~16% (50/300)

    ある子グループに実行中のプロセスがない場合、実行中のプロセスのCPU時間割当ては、実行中のプロセスを持つ残りの子グループの合計の重みに基づいて再計算されます。たとえば、g2子グループに実行中のプロセスがない場合、合計の重みはg1+g3の重みである200になります。この場合、g1のCPU時間は150/200 (~75%)になり、g3の場合は50/200 (~25%)になります。

  4. 指定した制御グループでアプリケーションが実行されていることを確認します。
    sudo cat /proc/33301/cgroup /proc/33302/cgroup /proc/33303/cgroup
    0::/MyGroups/g1
    0::/MyGroups/g2
    0::/MyGroups/g3
  5. CPUの重みを設定した後で、現在のCPU消費を確認します。
    top
    ...
    PID   USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
    33301 root      20   0   18720   1748   1460 R  49.5   0.0 415:05.87 sha1sum
    33302 root      20   0   18720   1756   1464 R  32.9   0.0 412:58.33 sha1sum
    33303 root      20   0   18720   1860   1568 R  16.3   0.0 411:03.12 sha1sum
    760 root      20   0  416620  28540  15296 S   0.3   0.7   0:10.23 tuned
    1 root      20   0  186328  14108   9484 S   0.0   0.4   0:02.00 systemd
    2 root      20   0       0      0      0 S   0.0   0.0   0:00.01 kthread
    ...