第10章 カーネルのコントロールグループ

目次

10.1. 技術概要と用語定義
10.2. シナリオ
10.3. コントロールグループサブシステム
10.4. コントローラグループの使用
10.5. さらなる情報

概要

カーネルのコントロールグループ (cgroups と略して表記します) は、タスク (プロセス) をまとめたり分割したりすることのできるカーネルの機能で、 子プロセスを階層構造でまとめたグループとして扱うこともできる仕組みです。 これらの階層構造は、利用可能なハードウエアやネットワーク資源を有効に活用する ため、システムチューニングを支援するよう設定することができます。

10.1. 技術概要と用語定義

本章では下記のような用語を使用します:

  • cgroup はコントロールグループの略称です。

  • cgroup 内では複数のタスク (プロセス) が関連づけられていて、それらの タスク向けに構成されたパラメータをもとに動作する、各種のサブシステム が存在しています。

  • サブシステムは cpuset や freezer 、メモリやディスクの I/O などを割り当て たり設定したりするパラメータを提供します。より一般的な書き方をすると、 資源コントローラ と呼びます。

  • cgroup は木構造で階層管理されています。システム内には複数の木構造を持つ ことができるようになっていて、特定の環境に適応するよう異なる木構造を 利用することもできます。

  • システム内で動作するすべてのタスクは、必ずいずれかの cgroup の木構造に 属します。

10.2. シナリオ

理解を深めるため、下記の資源計画シナリオをお読みください (ソース: /usr/src/linux/Documentation/cgroups/cgroups.txt):

図10.1 資源計画

資源計画

Firefox のような Web ブラウザの場合は Web ネットワーククラスに分類されます し、 (k)nfsd のような NFS デーモンであれば NFS ネットワーククラスに分類 されます。一方、 Firefox は誰がそれを起動したのかに依存して、適切な CPU またはメモリクラスを共有します。

10.3. コントロールグループサブシステム

それぞれ下記のようなサブシステムが存在していて、それらは 2 種類に 分類することができます:

分離と特殊コントローラ

cpuset, freezer, devices, checkpoint/restart

資源コントローラ

cpu (スケジューラ), cpuacct, メモリ, ディスク I/O, ネットワーク

サブシステムのマウントは、下記のようにして別々に行なうこともできます:

mount -t cgroup -o cpu none /cpu
mount -t cgroup -o cpuset none /cpuset
  

一括で行なう場合は下記のようにします。なお、デバイス名に (下記で none と設定されている箇所) ついては、任意の名前を 設定することができます。ここで指定した名前は、 /proc/mounts で表示することができます:

mount -t cgroup none /sys/fs/cgroup
  

サブシステムに関する追加情報は下記の通りです:

cpuset (分離)

cpuset を使用することで、プロセスをシステム内の CPU のサブセットや メモリ (メモリノード) に結びつけることができます。 たとえば 10.4.3項 「例: cpuset」 をお読みください。

freezer (制御)

freezer サブシステムは、高性能計算機クラスタ (HPC クラスタ) を利用する際に 便利な仕組みで、事前に設定されたチェックポイントに到達した際にグループ内に あるすべてのタスクをフリーズ (停止) させたりタスク群を停止させたりすることが できるものです。詳しくは /usr/src/linux/Documentation/cgroups/freezer-subsystem.txt をお読みください。

下記に示すのは、 freezer サブシステムの使用方法を説明するための 基本的なコマンド群です:

mount -t cgroup -o freezer freezer /freezer
# 子 cgroup を作成:
mkdir /freezer/0
# 作成した cgroup にタスクを投入する:
echo $task_pid > /freezer/0/tasks
# フリーズさせる:
echo FROZEN > /freezer/0/freezer.state
# フリーズ状態を解除する:
echo THAWED > /freezer/0/freezer.state
Checkpoint/Restart (制御)

cgroup に属するすべてのプロセスに対して、それらの状態をダンプファイルに 保存します。これを利用することで、後から実行を再開することができます (もちろん保存後にそのまま実行し続けることもできます) 。

また、 保存されたコンテナ について、物理マシン間を 起動することもできます (仮想マシンで行なうことができるのと同じ機能を 提供します) 。

すべてのプロセスのイメージは、ファイルに出力されます。

デバイス (分離)

システム管理者は、 cgroup 内のプロセスからアクセスできるデバイスに ついて、その一覧を設定することができます。

これにより、そのデバイスに対してのアクセスを指定した cgroup に属する タスクに対してのみ許可するように制限することができます。詳しくは /usr/src/linux/Documentation/cgroups/devices.txt をお読みください。

cpuacct (制御)

cpuacct は CPU の使用量を計算するコントローラで、 cgroup を利用すること でタスクをグループ化し、それらのグループに対する CPU 使用率を計算します。 詳しくは /usr/src/linux/Documentation/cgroups/cpuacct.txt をお読みください。

CPU (資源制御)

CFS (スケジューラ) のグループスケジュール機能を利用して、グループ間での CPU 帯域の共有を行ないます。かなり複雑な処理を行ないます。

メモリ (資源制御)
  • ユーザスペースのプログラムに対して、メモリの使用量を制限します。

  • カーネルの起動パラメータに対して swapaccount=1 を指定すると、スワップの使用方法を制御することができます。

  • LRU (Least Recently Used; 使用率の低い) ページを制限します。

  • 匿名ページとファイルキャッシュを対象とします。

  • カーネルのメモリに対しては制限を行ないません。

  • 必要であれば他のシステムでも利用されます。

詳しくは /usr/src/linux/Documentation/cgroups/memory.txt をお読みください。

ブロック I/O (資源制御)

blkio (ブロック IO) コントローラは、ディスクの I/O コントローラとして 利用できる仕組みです。 blkio コントローラでは、ディスクの使用帯域を 制御するためのポリシーを設定することができます。

blkio.weight の値で重さ (weight) を設定し、 帯域の重み付けを設定する場合は、基本コマンドで設定することができます:

# /sys/fs/cgroup 内の準備
mkdir /sys/fs/cgroup/blkio
mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
# 2 つの cgroup の開始
mkdir -p /sys/fs/cgroup/blkio/group1 /sys/fs/cgroup/blkio/group2
# 重み付けの設定
echo 1000 > /sys/fs/cgroup/blkio/group1/blkio.weight
echo  500 > /sys/fs/cgroup/blkio/group2/blkio.weight
# それぞれのグループに対して、制御下に置くプロセスの
# PID を書き込む
command1 &
echo $! > /sys/fs/cgroup/blkio/group1/tasks

command2 &
echo $! > /sys/fs/cgroup/blkio/group2/tasks

下記の例は、 blkio.throttle.read_bps_device で 読み込み量の上限を、 blkio.throttle.write_bps_device で書き込み量の制限を行なう場合の基本的なコマンド例です:

# /sys/fs/cgroup 内の準備
mkdir /sys/fs/cgroup/blkio
mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
# ルートグループに対するデバイスの帯域幅の指定; 書式:
# <major>:<minor>  <byes_per_second>
echo "8:16  1048576" > /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device

注意事項やシナリオ、追加のパラメータについて、詳しくは /usr/src/linux/Documentation/cgroups/blkio-controller.txt をお読みください。

ネットワーク I/O (資源制御) (Draft)

現在議論中。

10.4. コントローラグループの使用

10.4.1. 要件

cgroup を便利に使用するには、下記の追加パッケージをインストール してください:

  • libcgroup1: 資源管理を簡略化するための 基本的なユーザスペースツールが含まれています。

  • cpuset: CPU セットを管理するための cset ツールが含まれています。

  • libcpuset1: CPU セットを操作するための C 言語 API が含まれています。

  • kernel-source: ドキュメントを読む場合に 必要なパッケージです。

  • lxc: Linux のコンテナ実装です。

10.4.2. 環境の確認

openSUSE に同梱されているカーネルであれば、 cgroup に対応しています。 特に追加の修正を適用する必要はありません。 lxc-checkconfig を実行すると、下記のような形式で cgroup の環境を表示することができます:

--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled
Multiple /dev/pts instances: enabled

--- Control groups ---
Cgroup: enabled
Cgroup namespace: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled

--- Misc ---
Veth pair device: enabled
Macvlan: enabled
Vlan: enabled
File capabilities: enabled

どのサブシステムが利用可能なのかを知るには、下記を実行します:

mkdir /cgroups
mount -t cgroup none /cgroups
grep cgroup /proc/mounts

それぞれ下記のサブシステムが利用できます: perf_event, blkio, net_cls, freezer, devices, memory, cpuacct, cpu, cpuset.

10.4.3. 例: cpuset

コマンドラインを利用する場合は下記のようにします:

  1. CPU 数を判別したり、メモリノードを確認したりするには、 それぞれ /proc/cpuinfo/proc/zoneinfo ファイルの内容を表示します。

  2. 仮想ファイルシステム内に cpuset 用の構造を作成します (情報源: /usr/src/linux/Documentation/cgroups/cpusets.txt):

    mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
    cd /sys/fs/cgroup/cpuset
    mkdir Charlie
    cd Charlie
    # この cpuset で使用する CPU の一覧を設定します:
    echo 2-3 > cpuset.cpus
    # この cpuset で使用するメモリノードを設定します:
    echo 1 > cpuset.mems
    echo $$ > tasks
    # これでサブシェル 'sh' が Charie という名前の cpuset に
    # 設定されます。下記を実行すると '/Charlie' と表示されるはずです:
    cat /proc/self/cpuset
    
  3. cpuset の削除は下記のようなシェルコマンドを実行することで行ないます:

    rmdir /sys/fs/cgroup/cpuset/Charlie
       

    上記のコマンドは、 cpuset が使用中の場合には失敗します。削除を行なう 前に、それらに属する内部 cpuset やタスク (プロセス) を取り除いてください。 下記のように実行すると、それらを確認することができます:

    cat /sys/fs/cgroup/cpuset/Charlie/tasks

背景となる情報や追加の設定フラグについて、詳しくは /usr/src/linux/Documentation/cgroups/cpusets.txt をお読みください。

cset ツールを利用する場合は下記のようにします:

# CPU 数とメモリノードの表示
cset set --list
# cpuset 構造の作成
cset set --cpu=2-3 --mem=1 --set=Charlie
# cpuset 内でプロセスを起動
cset proc --set Charlie --exec -- stress -c 1 &
# 既存のプロセスを cpuset に移動
cset proc --move --pid PID --toset=Charlie
# cpuset 内のタスク一覧を表示
cset proc --list --set Charlie
# cpuset の削除
cset set --destroy Charlie
 

10.4.4. 例: cgroup

コマンドラインを利用する場合は下記のようにします:

  1. cgroup の構造を作成します:

    mount -t cgroup cgroup /sys/fs/cgroup
    cd /sys/fs/cgroup/cpuset/cgroup
    mkdir priority
    cd priority
    cat cpu.shares
    
  2. cpu.shares の値は下記のような意味があります:

    • 1024 が既定値 (詳しくは /Documentation/scheduler/sched-design-CFS.txt を参照) = 50% の使用率

    • 1524 = 60% の使用率

    • 2048 = 67% の使用率

    • 512 = 40% の使用率

  3. cpu.shares を変更します:

    echo 1024 > cpu.shares

10.5. さらなる情報

  • カーネルのドキュメンテーション: (kernel-source パッケージ内) /usr/src/linux/Documentation/cgroups ディレクトリ内:

    • /usr/src/linux/Documentation/cgroups/blkio-controller.txt

    • /usr/src/linux/Documentation/cgroups/cgroups.txt

    • /usr/src/linux/Documentation/cgroups/cpuacct.txt

    • /usr/src/linux/Documentation/cgroups/cpusets.txt

    • /usr/src/linux/Documentation/cgroups/devices.txt

    • /usr/src/linux/Documentation/cgroups/freezer-subsystem.txt

    • /usr/src/linux/Documentation/cgroups/memcg_test.txt

    • /usr/src/linux/Documentation/cgroups/memory.txt

    • /usr/src/linux/Documentation/cgroups/resource_counter.txt

  • http://lwn.net/Articles/243795/—Corbet, Jonathan: Controlling memory use in containers (2007).

  • http://lwn.net/Articles/236038/—Corbet, Jonathan: Process containers (2007).


openSUSE システム分析とチューニングガイド 13.1