7 リソースの管理

この章では、Oracle Linuxシステムでリソースの使用を管理する方法について説明します。

制御グループについて

Oracle Linuxの制御グループ(cgroups)機能を使用すると、CPUやメモリーなどの独自のシステム・リソースのグループを、選択した使用設定で作成できます。cgroupsを作成すると、プロセスおよびシステム要件に従って各cgroupにプロセスを割り当てることができます。たとえば、CPU時間を150:100:50の比率で割り当てる必要がある3セットのプロセスを特定した場合は、3つのcgroupsを作成し、それぞれに比率の3つの値のいずれかに対応するCPUの重みを割り当て、各cgroupに適切なプロセスを割り当てることができます。

制御グループは、複数の仮想マシン、Kubernetesクラスタなどをホストし、そのアプリケーションがリソースの使用について競合するシステム構成では重要です。

cgroup機能は/sys/fs/cgroupに仮想ファイル・システムとしてマウントされています。/sys/fs/cgroupファイル・システムは、より効率的なシステム・パフォーマンスを得るために、サブディレクトリおよびファイルを作成して、リソース割当てを細かいレベルで制御できる階層構造を提供します。

Oracle Linuxには、次の2つのタイプの制御グループがあります:

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

これらのグループは、リソースごとのコントローラ階層を提供します。CPU、メモリー、I/Oなどの各リソースには、独自の制御グループ階層があります。このグループの短所は、異なるプロセス階層に属する可能性のあるグループ間でリソース使用を適切に調整することが困難なことです。

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

これらのグループは、すべてのリソース・コントローラがマウントされる単一の制御グループ階層を提供します。この階層では、異なるリソース・コントローラ間でのリソース使用をより適切に調整できます。このバージョンは、柔軟性が高すぎてシステム利用者間のリソース利用の適切な調整を妨げていたcgroups v1の改良版です。

どちらのバージョンもOracle Linuxに存在します。ただし、デフォルトでは、cgroups v2機能が有効になっており、Oracle Linux 9システムにマウントされています。

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

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

制御グループは、カーネル・リソース・コントローラを介してリソースの使用を管理します。カーネル・リソース・コントローラは、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 v1cgroups v2の両方のカーネル・リソース・コントローラの詳細な説明は、cgroups(7)マニュアル・ページを参照してください。

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

この項では、cgroup機能が/sys/fs/cgroupで階層ファイル・システムとしてどのようにマウントされているかを説明します。

ディレクトリ/sys/fs/cgroupは、ルート制御グループとも呼ばれます。ルート制御グループ・ディレクトリの内容は、システムにマウントされている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

ノート:

ベスト・プラクティスは、/sys/fs/cgroup内に少なくとも2つのレベルの子cgroupsを作成することです。前述のリストの例では、最初の子グループ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

制御グループおよびsystemdについて

制御グループは、リソース管理のためにsystemdシステムおよびサービス・マネージャで使用できます。systemdは、これらのグループを使用して、リソースを消費するユニットおよびサービスを編成します。systemdの詳細は、systemdサービス・マネージャについてを参照してください。

systemdは様々なユニット・タイプを提供しており、そのうちの3つはリソース制御を目的としたものです:

  • サービス: ユニット構成ファイルに基づく設定を持つプロセスまたはプロセスのグループ。サービスは、systemdが1つのセットとしてプロセスを開始または停止できるように、指定されたプロセスを「コレクション」に包含します。サービス名はname.serviceの形式に従います。

  • スコープ: ユーザー・セッション、コンテナ、仮想マシンなど、外部で作成されたプロセスのグループ。サービスと同様に、スコープはこれらの作成されたプロセスをカプセル化し、任意のプロセスによって起動または停止され、実行時にsystemdによって登録されます。スコープ名はname.scopeの形式に従います。

  • スライス: サービスとスコープが配置される、階層的に編成されたユニットのグループ。したがって、スライス自体にはプロセスが含まれていません。かわりに、スライス内のスコープおよびサービスによってプロセスが定義されます。スライス・ユニットのすべての名前が、階層内の場所へのパスに対応します。ルート・スライス(通常、すべてのユーザーベースのプロセスの場合はuser.slice、システムベースのプロセスの場合はsystem.slice)が、階層内に自動的に作成されます。親スライスがルート・スライスのすぐ下に存在し、parent-name.sliceという形式に従います。これらのルート・スライスは、複数のレベルのサブスライスを持つことができます。

サービス、スコープおよびスライス・ユニットは、制御グループ階層内のオブジェクトに直接マップされます。これらのユニットがアクティブ化されると、ユニット名から構築される制御グループ・パスに直接マップされます。systemdリソース・ユニット・タイプと制御グループの間のマッピングを表示するには、次のように入力します。

sudo systemd-cgls
Working directory /sys/fs/cgroup:
├─user.slice (#1243)
│ → trusted.invocation_id: 50ce3909b2644f919ee420adc39edb4b
│ ├─user-1001.slice (#4167)
│ │ → trusted.invocation_id: 02e80a960d4549a7a9c69ce0fb546c26
│ │ ├─session-2.scope (#4405)
│ │ │ ├─2417 sshd: alice [priv]
│ │ │ ├─2430 sshd: alice@pts/0
│ │ │ ├─2431 -bash
│ │ │ ├─2689 sudo systemd-cgls
│ │ │ ├─2691 systemd-cgls
│ │ │ └─2692 less
...
│   └─user@984.service … (#3827)
│     → trusted.delegate: 1
│     → trusted.invocation_id: 09b47ce9f3124239b75814114353f3f2
│     └─init.scope (#3861)
│       ├─2058 /usr/lib/systemd/systemd --user
│       └─2099 (sd-pam)
├─init.scope (#19)
│ └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 17
└─system.slice (#53)
...
  ├─chronyd.service (#2467)
  │ → trusted.invocation_id: c0f77aaa9c7844e6bef6a6898ae4dd56
  │ └─1358 /usr/sbin/chronyd -F 2
  ├─auditd.service (#2331)
  │ → trusted.invocation_id: 756808add6a348609316c9e8c1801846
  │ └─1310 /sbin/auditd
  ├─tuned.service (#3079)
  │ → trusted.invocation_id: 2c358135fc46464d862b05550338d4f4
  │ └─1415 /usr/bin/python3 -Es /usr/sbin/tuned -l -P
  ├─systemd-journald.service (#1651)
  │ → trusted.invocation_id: 7cb7ccb14e044a899aadf47bbb583ada
  │ └─977 /usr/lib/systemd/systemd-journald
  ├─atd.service (#3623)
  │ → trusted.invocation_id: 597a7a4e5646468db407801b8562d869
  │ └─1915 /usr/sbin/atd -f
  ├─sshd.service (#3419)
  │ → trusted.invocation_id: 490504a683fc4311ab0fbeb0864a1a34
  │ └─1871 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
...

systemctlなどのsystemdコマンドを使用してリソースを管理する方法の例は、システム・リソースへのアクセスの制御を参照してください。技術的な詳細は、systemctl(1)systemd-cgls(1)、およびsystemd.resource-control(5)の各マニュアル・ページを参照してください。

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

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

重み

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

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

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

制限

制御グループは、構成済のリソース量を使用できます。ただし、リソースをオーバーコミットすることもできます。したがって、サブグループの制限の合計が親グループの制限を超える可能性があります。

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

保護

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

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

割当て

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

cgroups v2を使用したアプリケーションのリソースの管理

この項では、システムで実行されているプロセス間でのリソースの分散を管理するためにcgroupsを作成および構成できるように、cgroups v2機能を有効にする方法を示します。

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

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

cgroups v2の有効化

ブート時に、Oracle Linux 9はデフォルトでcgroups v2をマウントします。

  1. cgroups v2が有効で、システムにマウントされていることを確認します。

    sudo mount -l | grep cgroup
    cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate,memory_recursiveprot)
  2. 必要に応じて、ルート制御グループとも呼ばれる/sys/fs/cgroupディレクトリの内容を確認します。

    ll /sys/fs/cgroup/

    cgroups v2の場合、ディレクトリ内のファイルには、cgroup.*、cpu.*、memory.*などのファイル名への接頭辞が必要です。制御グループ・ファイル・システムについてを参照してください。

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

  1. /sys/fs/cgroup/cgroup.controllersファイルの内容を画面に出力して、cpuコントローラが階層の最上部(ルート制御グループ)で使用可能であることを確認します。

    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コントローラが期待どおりに存在することを確認します。

    ll /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の重みの設定

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

  • 次の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/Example/g1/cgroup.procs
    echo "33302" | sudo tee /sys/fs/cgroup/Example/g2/cgroup.procs
    echo "33303" | sudo /sys/fs/cgroup/Example/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
    ...

cgroups v2を使用したユーザーのリソースの管理

前述のサンプル手順では、アプリケーションによるシステム・リソースの使用を管理する方法について説明します。システムにログインするユーザーにリソース・フィルタを直接実装して、リソースの使用を管理することもできます。

Oracle LinuxでのControl Groups Version 2の実行は、ユーザーによるシステム・リソースの使用を制御する方法の例を示すチュートリアルです。さらに、このチュートリアルでは、ユーザーがリソース消費を規制するためのステップをリアルタイムで実行できるラボ環境を提供しています。