Cgroups (日本語) - ArchWiki

# Cgroups (日本語)

関連記事

- Linux Containers
- Arch systemd container
- Docker

cgroups (別名 control groups) は特定のプロセス (プロセスグループ) のリソースの使用量を制限・監視する Linux カーネルの機能です。'nice' コマンドや `/etc/security/limits.conf` などの他の方法と比べて、cgroups は柔軟性が優れています。

Control groups には使い方が複数存在します:

- cgcreate, cgexec, cgclassify などのツールを使ってオンザフライでグループを作成・管理する
- 特定のユーザーやグループ、コマンドを自動的にグループに移動する"ルールエンジンデーモン" (`/etc/cgrules.conf` と `/usr/lib/systemd/system/cgconfig.service`)
- Linux Containers (LXC) 仮想化など他のソフトウェアで使う

残念ながら"ハウツー"方式の簡単なドキュメントが存在しないため、この機能はあまり評価を受けていません。この記事ではその穴を埋める説明を行います。

## インストール

まず、cgroups を管理するためのユーティリティをインストールしてください。AUR から libcgroup パッケージをインストールする必要があります。

クライアントスクリプトの `cgm` を使いたい場合は、`cgmanager` デーモンを起動する必要があります。

`cgmanager` デーモンは以下のような systemd ユニットを使うことで起動できます:

    /usr/lib/systemd/system/cgmanager.service

    [Unit]
    Description=Control Group manager

    [Service]
    Type=simple
    ExecStart=/usr/bin/cgmanager

    [Install]
    WantedBy=sysinit.target

## Systemd でリソースグループを管理する

systemd を使って cgconfig サービスを有効にすることができます:

    # systemctl enable cgconfig.service

次のコマンドを使えば `cgconfig.conf` ファイルにエラーがないか簡単に調べることができます:

    $ systemctl status cgconfig.service

## シンプルな使い方

### 一時的なグループ

cgroups を使って即座に"一時的な"グループを作成することができます。実際に、通常ユーザーにカスタムグループを作成する権限を与えることも可能です。次のコマンドを root で実行してください ($USER はあなたのユーザー名に、groupname は cgroup に付けたい名前に置き換えてください):

    # cgcreate -a $USER -g memory,cpu:groupname

ユーザーによってグループ groupname の全ての設定を書き換えることができます:

    $ ls -l /sys/fs/cgroup/memory/groupname
    total 0
    -rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.event_control
    -rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.procs
    -rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_period_us
    -rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_runtime_us
    -rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.shares
    -rwxrwxr-x 1 user root 0 Sep 25 00:39 notify_on_release
    -rwxrwxr-x 1 user root 0 Sep 25 00:39 tasks

Cgroups は階層式なので、好きなだけサブグループを作成することができます。例えば、通常ユーザーとして、bash シェルを新しいサブグループ 'foo' 下で動作させたい場合:

    $ cgcreate -g memory,cpu:groupname/foo
    $ cgexec   -g memory,cpu:groupname/foo bash

さあ、確認してみましょう:

    $ cat /proc/self/cgroup
    11:memory:/groupname/foo
    6:cpu:/groupname/foo

このグループの新しいサブディレクトリが作成されています。このグループ内の全てのプロセスのメモリ使用量を 10 MB に制限するには、次を実行します:

    $ echo 10000000 > /sys/fs/cgroup/memory/groupname/foo/memory.limit_in_bytes

メモリ制限は RAM の使用にしか適用されないので注意してください -- タスクが制限に達すると、スワップを始めます。しかしながら他のプロセスのパフォーマンスにはあまり影響を与えません。

同じようにこのグループの CPU 優先度 ("shares") を変更することもできます。デフォルトでは全てのグループは 1024 shares になっています。100 shares のグループは CPU 時間の ~10% だけを使うようになります:

    $ echo 100 > /sys/fs/cgroup/cpu/groupname/foo/cpu.shares

cgroup ディレクトリを表示することで他の設定や統計を見ることができます。

また、既に実行中のプロセスの cgroup を変更することも可能です。全ての 'bash' コマンドをこのグループに移動するには:

    $ pidof bash
    13244 13266
    $ cgclassify -g memory,cpu:groupname/foo `pidof bash`
    $ cat /proc/13244/cgroup
    11:memory:/groupname/foo
    6:cpu:/groupname/foo

### 永続的なグループ設定

Note: Systemd 205 以上を使って cgroups を管理する場合、このファイルは完全に無視することができます。

起動時に cgroup が作成されるようにしたい場合、代わりに `/etc/cgconfig.conf` でグループを定義することができます。例えば、"groupname" に制限を管理しタスクを追加する $USER のパーミッションとグループ $GROUP の users を定義します。サブグループの "groupname/foo" グループの定義は以下のようになります。

    /etc/cgconfig.conf

    group groupname {
      perm {
    # who can manage limits
        admin {
          uid = $USER;
          gid = $GROUP;
        }
    # who can add tasks to this group
        task {
          uid = $USER;
          gid = $GROUP;
        }
      }
    # create this group in cpu and memory controllers
      cpu { }
      memory { }
    }

    group groupname/foo {
      cpu {
        cpu.shares = 100;
      }
      memory {
        memory.limit_in_bytes = 10000000;
      }
    }

Note:

- コメントは行の初めに置いて下さい。そうしないと、cgconfigparser が解析するときに問題が発生しますが、cgconfig を Systemd で起動しない限り、エラーとしては `cgroup change of group failed` しか報告されません。
- permissions セクションは任意です。
- `/sys/fs/cgroup/` ディレクトリ階層には controllers サブディレクトリが全て含まれ、起動時に仮想ファイルシステムとして作成・マウントされます。`$CONTROLLER-NAME { }` コマンドを使って新しいグループエントリを作成することが可能です。何らかの理由で他の場所に階層を作成・マウントしたいときは、`/etc/cgconfig.conf` に以下のようにふたつ目のエントリを書く必要があります:

     mount {
       cpuset = /your/path/groupname;
    }

これは以下のシェルコマンドと同等です:

    # mkdir /your/path/groupname
    # mount -t /your/path -o cpuset groupname /your/path/groupname

## 活用例

### Matlab

Matlab にはマシンのメモリや CPU が全て使われるのに対するプロテクトがありません。膨大な計算を始めてしまうとシステムが使えなくなる可能性があります。以下はそれを防止するために `/etc/cgconfig.conf` に配置するファイルです ($USER はあなたのユーザー名に置き換えてください):

    /etc/cgconfig.conf

    # Prevent Matlab from taking all memory
    group matlab {
        perm {
            admin {
                uid = $USER;
            }
            task {
                uid = $USER;
            }
        }

        cpuset {
            cpuset.mems="0";
            cpuset.cpus="0-5";
        }
        memory {
    # 5 GiB limit
            memory.limit_in_bytes = 5368709120;
        }
    }

Note: $USER を実際に Matlab を動かすユーザーの名前に変えるのを忘れないで下さい。

この cgroup は Matlab が使えるコアをコア0から5までに (Matlab には6つのコアだけが認識されます) そしてメモリの使用量を 5 GiB に制限します。"cpu" リソースの強制を使って CPU 使用量の制限も定義することが可能ですが、"cpuset" で十分だと思われます。

matlab を次のようにして起動します:

    $ cgexec -g memory,cpuset:matlab /opt/MATLAB/2012b/bin/matlab -desktop

正しい実行可能ファイルのパスを使って下さい。

## ドキュメント

- コントローラーや特定のスイッチ・オプションに関する情報はカーネルの Documentation/cgroup を参照してください (または linux-docs をインストールして `/usr/src/linux/Documentation/cgroup` を見て下さい)。
- 詳細かつ完全なリソース管理ガイドが fedora プロジェクトのドキュメント にあります。

コマンドや設定ファイルについては、`man cgcreate` や `man cgrules.conf` などの該当する man ページを見て下さい。

Categories:

- Kernel (日本語)
- Virtualization (日本語)