tl;dr
会社から借りっぱなしの Software Design 2020 年 2 月号で特集されている Docker コンテナランタイムについての記事を読んでみたメモです.
読みながら気になる単語や内容をマインドマップにまとめていきたいと思います.
今回は cgroup について手を動かしてみたいと思います.
マインドマップ
ハンズオンメモ
検証環境
ホスト側の OS は以下の通り.
$ cat /etc/os-release NAME="Ubuntu" VERSION="18.04.4 LTS (Bionic Beaver)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 18.04.4 LTS" VERSION_ID="18.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=bionic UBUNTU_CODENAME=bionic
各種ツールのバージョンは以下の通り.
$ runc --version runc version spec: 1.0.1-dev $ unshare --version unshare from util-linux 2.31.1 $ taskset --version taskset from util-linux 2.34
事前準備
隔離環境の Alpine Linux に taskset をインストールする
巣の Alpine Linux には taskset ユーティリティはインストールされていなかったので, util-linux パッケージをインストールします.
尚, インストールに際しては, 改めて docker コンテナを起動してパッケージをインストールしてから rootfs を再作成することになります.
$ docker run --rm -d --name rootfs alpine tail -f /dev/null $ docker exec -t -i rootfs /bin/sh / # apk update && apk add bash util-linux / # exit $ docker export rootfs > rootfs.tar $ tar xvf rootfs.tar -C bundle/rootfs
taskset の動作確認
taskset を動かしてみる. 以下のように隔離環境において 0 及び 1 のプロセッサが利用出来ることが判ります.
$ unshare -pfmur chroot bundle/rootfs /bin/sh / # taskset -c 0 echo 'test 0' test 0 / # taskset -c 1 echo 'test 1' test 1 / #
隔離環境にて CPU (プロセッサ) 利用を制限する
利用可能なプロセッサの確認
ホスト上で以下のように実行して利用可能なプロセッサを確認します.
$ cat /sys/fs/cgroup/cpuset/cpuset.cpus 0-1
0
と 1
の二つのプロセッサが利用可能であることが判ります. また, この値は, 以下のように /proc/cpuinfo
の processor
項目に該当します.
$ cat /proc/cpuinfo | grep 'processor' processor : 0 processor : 1
隔離環境にて 0 番のプロセッサのみ利用可能にする
まずはホスト側で以下を実行する. (すでに隔離環境は unshare -pfmur chroot bundle/rootfs /bin/sh
で起動している前提.)
$ sudo mkdir /sys/fs/cgroup/cpuset/demo $ cd /sys/fs/cgroup/cpuset/demo # -> 利用可能なプロセッサの設定 0 番のプロセッサのみを利用する $ sudo su - # echo 0 > cpuset.cpus # -> 既存の設定を継承 # echo 0 > cpuset.mems # -> 隔離環境で実行されるプロセスのホスト側から見える PID を tasks に書き込む # ps ao pid,cmd | grep '[/]bin/sh' | grep -v unshare | awk '{print $1}' > tasks
隔離環境で実行されるプロセスのホスト側から見える PID を書き込むことで, そのプロセスから作られるすべての子プロセスに対して, 0 番の CPU のみを利用するように制限が掛かることになります.
実際に確認してみます.
/ # / # taskset -c 0 echo 'test 0' test 0 / # taskset -c 1 echo 'test 1' taskset: failed to set pid 3's affinity: Invalid argument / #
確かに 1 番のプロセッサを利用しようとすると, taskset: failed to set pid 3's affinity: Invalid argument
というエラーが出力され, 期待通りに 0 番のプロセッサのみが利用可能な状態を確認出来ました.
参考
以上
namespace, cgroup と触ってきて, あれ, コンテナのランタイムどこ行った!って思ってしまうほど, runc については Linux の環境隔離の仕組みをゴリゴリと使って実現していることを実感出来ました. Kubernetes や Docker のような上モノを触るのも楽しいけど, コンテナランタイムを通してコンテナの深淵に触れてみることで, このレイヤーのことについて何も知らないことに愕然となりましたが, 今後も引き続き, このあたりのインプットはやっていきたいなと思います.
とても面白い記事でした. 借りっぱなしなってしまい本当に申し訳ございません.