先月、私はApacheConで登壇し、Cgroupsについて話しました。Cgroupsとその強力な機能について知っているLinuxユーザーは非常に少ないようです(少し前までの私自身も含めて)。これは残念なことです。なぜなら、Cgroupsは非常に強力であり、Linuxツールキットで利用可能な他のどのツールよりもはるかにきめ細かな方法でサーバー上のリソースを割り当てることができるからです。さらに、カーネルに直接組み込まれており、ほとんどのLinuxディストリビューションで標準で提供されています。
この記事では、私がDocker Meetup(テキサス州オースティン)で行った別の講演のフォローアップとして、DockerでCgroupsを使用する方法について説明します。
この記事では、Cgroupsに関する基本的な理解が必要です。Cgroupsを全く知らない場合は、私のスライド資料(ApacheConのもの)と、最後にあるリソースに目を通すことをお勧めします。心配しないでください、それほど深くは掘り下げません。スライド資料をざっと見るだけでも、基本的な概念を理解できるはずです。
DockerとCgroups
Dockerには、LXCとlibcontainerという2つの異なるドライバーが付属しています。LXCドライバーはレガシードライバーであり、libcontainerは新しくデフォルトのドライバーです。ほとんどの場合、libcontainerが推奨されるドライバーです。なぜなら、そこでイノベーションが起きているからです(例えば、docker execはLXCドライバーでは動作しません)。
ただし、すべてのCgroup機能がまだlibcontainerに移植されているわけではない(あるいは、少なくともDockerに公開されているわけではない)ため、2つの異なるドライバーが存在することに注意することが重要です。LXCドライバーを使用する場合は、LXC引数を直接渡すだけですが、libcontainerを使用する場合は、Dockerに公開されている明示的なCgroupポリシー引数があります。Dockerデーモンを起動するときにドライバーを明示的に設定する必要があるため、2つのドライバーを同時に実行することはできません。
確認方法の例を以下に示します。
[bash light=”true”] # LXCドライバーの場合$ docker run -d –name=’lxc_test’ \
–lxc-conf="lxc.cgroup.cpu.shares=50" \
busybox
# libcontainerドライバーの場合
$ docker run -d –name=’libcontainer_test’ \
–cpu-shares=50 \
busybox
[/bash]
以下は、いくつかのCgroup機能と、それらが2つのドライバー間でどのようにマッピングされるかの概要です。
| 機能 | Libcontainer | LXC |
|---|---|---|
| 相対CPUシェア | -c, –cpu-shares | –lxc-conf=”lxc.cgroup.cpu.shares” |
| CPUコアへの固定 | –cpuset-cpus | –lxc-conf=”lxc.cgroup.cpuset.cpus” |
| メモリ制限 | -m, –memory | –lxc-conf=”lxc.cgroup.cpuset.mems” |
LXC
DockerでLXCドライバーを使用する場合は、まずそれを有効にする必要があります。これを行う方法はLinuxディストリビューションによって異なりますが、以下はUbuntu 14.04でLXCドライバーを有効にする方法.
上述の通り、これを行うと多くの機能を諦めることになります。したがって、libcontainerを使用したDockerでまだ公開されていない機能が本当に必要でない限り、デフォルトのドライバーを使い続けるべきです。
libcontainerでまだ公開されていない便利なCgroupポリシーには、I/Oスロットリング(プレゼンテーションスライドで説明されています)などがあり、特定のアプリケーションで非常に役立ちます。
LXCドライバーを使用することに決めた場合、引数の追加は簡単です。必要なのは、引数--lxc-confを追加し、設定したいCgroupポリシーを渡すことだけです。
Libcontainer
上の表からわかるように、基本的なCgroupポリシーは、現在のバージョンのDocker(本稿執筆時点では1.6)ですでに公開されています。
これらのポリシーの使用は非常に簡単です。例えば、Dockerコンテナを最初のCPUコアに固定したい場合は、--cpuset-cpus=0をdocker runコマンドに追加します。
また、--cgroup-parent引数をlibcontainerで使用し、よりきめ細かなリソース制限を手動で設定することもできます。その後、その引数を使用してそのグループにマッピングします。
デモ:DockerとCgroups
以下のスクリーンキャストでは、2つのDockerコンテナ(‘low_prio’と‘high_prio’)を使用します。ベースコンテナとして‘busybox’を使用し、md5sum /dev/urandomを実行してCPUを大量に消費するプロセスをシミュレートします。デフォルトでは、これにより利用可能なすべてのCPUリソースが消費されます。ただし、リソースを管理するために2つのCgroupポリシーを適用します。まず、‘cpuset.cpus’を使用して、コンテナを同じCPUコア(コア0)に固定します。
次に、‘cpu.shares’を使用して相対的なCPUシェアを割り当てます。‘low_prio’コンテナに20、‘high_prio’に80の値を設定します。これは、CPUの20%が‘low_prio’コンテナに割り当てられ、CPUの80%が‘high_prio’コンテナに割り当てられることを意味します。ただし、相対シェアは任意のスケールであることに注意してください(値として2と8を使用することもできました)。
リソース管理が実際に機能することを示した後、Cgroupポリシーを適用せずに同じコンテナセットを起動し、それらがどのように動作するかを確認します。
参考までに、コンテナの起動に使用したコマンドを以下に示します。
[bash light=”true”] $ docker run -d \–name=’low_prio’ \
–cpuset-cpus=0 \
–cpu-shares=20 \
busybox md5sum /dev/urandom
$ docker run -d \
–name=’high_prio’ \
–cpuset-cpus=0 \
–cpu-shares=80 \
busybox md5sum /dev/urandom
[/bash]
まとめ
同じホスト上で複数のDockerコンテナを管理している場合、Cgroupsを使用してコンテナ間のリソースを管理することは非常に理にかなっています。たとえば、あるコンテナでバックグラウンド処理タスクを実行し、別のコンテナでユーザーコンテンツを提供しているとします。その場合、新しく得た知識を活用して、バックグラウンドタスクよりもユーザー向けのコンテナを確実に優先させることができます。
コメント
コメントはまだありません。最初のコメントを投稿しましょう。