コンテナの仕組みについての学習の一貫で、以下の記事を読みながらControl groups、Namespace、Capabilitiesを使ってコンテナを作って動かしてみる。
コンテナで使うファイルシステムの準備
/tmp
以下に適当なディレクトリを作成する。 次の手順でここにファイルを展開する。
$ ROOTFS=$(mktemp -d)
CentOS7のイメージを取得する。Dockerコマンドを使っているが、コンテナを作るためでなく、このイメージからファイルシステムを抽出するために使用する。
$ CID=$(sudo docker container create centos:centos7)
取得したイメージからファイルシステムを抽出し、/tmp
以下にディレクトリへ展開する。
$ sudo docker container export $CID | tar -x -C $ROOTFS
以下のようにファイルが展開されている。
$ ls -lht /tmp/tmp.D4ipCfPw3e/ 合計 68K drwxr-xr-x 4 hogehoge hogehoge 4.0K 7月 11 05:00 dev drwxr-xr-x 47 hogehoge hogehoge 4.0K 7月 11 05:00 etc -rw-r--r-- 1 hogehoge hogehoge 12K 5月 4 15:37 anaconda-post.log dr-xr-x--- 2 hogehoge hogehoge 4.0K 5月 4 15:37 root drwxr-xr-x 11 hogehoge hogehoge 4.0K 5月 4 15:37 run drwxrwxr-x 7 hogehoge hogehoge 4.0K 5月 4 15:37 tmp drwxr-xr-x 18 hogehoge hogehoge 4.0K 5月 4 15:36 var lrwxrwxrwx 1 hogehoge hogehoge 7 5月 4 15:35 bin -> usr/bin lrwxrwxrwx 1 hogehoge hogehoge 7 5月 4 15:35 lib -> usr/lib lrwxrwxrwx 1 hogehoge hogehoge 9 5月 4 15:35 lib64 -> usr/lib64 lrwxrwxrwx 1 hogehoge hogehoge 8 5月 4 15:35 sbin -> usr/sbin drwxr-xr-x 13 hogehoge hogehoge 4.0K 5月 4 15:35 usr drwxr-xr-x 2 hogehoge hogehoge 4.0K 5月 4 15:35 proc drwxr-xr-x 2 hogehoge hogehoge 4.0K 5月 4 15:35 sys drwxr-xr-x 2 hogehoge hogehoge 4.0K 4月 11 2018 home drwxr-xr-x 2 hogehoge hogehoge 4.0K 4月 11 2018 media drwxr-xr-x 2 hogehoge hogehoge 4.0K 4月 11 2018 mnt drwxr-xr-x 2 hogehoge hogehoge 4.0K 4月 11 2018 opt drwxr-xr-x 2 hogehoge hogehoge 4.0K 4月 11 2018 srv
Dockerコマンドで取得したコンテナイメージは不要なので消す。
$ sudo docker container rm $CID af28f3a824658aae61673120265b28fb63c6e60e62526bd47d3c9dcdaa1551fc
コントロールグループ作成
適当な名前をつけるためにUUIDを使う。
$ UUID=$(uuidgen)
cpu,memoryのコントロールグループを作成する。名称にUUIDを利用する。
$ sudo cgcreate -t $(id -un):$(id -gn) -a $(id -un):$(id -gn) -g cpu,memory:$UUID
以下で確認できる。
$ cat /proc/self/cgroup
このグループ内の全てのプロセスのメモリ使用量を 10 MB に設定する。
$ cgset -r memory.limit_in_bytes=10000000 $UUID
CPUを利用可能な時間の上限値を1秒に設定する。
$ cgset -r cpu.cfs_period_us=1000000 $UUID
$ cgset -r cpu.cfs_quota_us=300000 $UUID
cgexec で指定したcgroupの設定に対して、 unshare で新しいシェルを呼び出し、その中で、現在使っているttyとptmxをコンテナ側のファイルシステムにマウント&リンクを張ったり(これによってコンテナを現在の疑似端末を使って制御できる)、/dev/null を作成したりホスト名を設定する。 unshare は親プロセスのNamespace(名前空間)を共有せずにプログラムを実行するためのコマンド。
$ cgexec -g cpu,memory:$UUID \ unshare -muinpfr /bin/sh -c " mount -t proc proc $ROOTFS/proc && touch $ROOTFS$(tty); mount --bind $(tty) $ROOTFS$(tty) && touch $ROOTFS/dev/pts/ptmx; mount --bind /dev/pts/ptmx $ROOTFS/dev/pts/ptmx && ln -sf /dev/pts/ptmx $ROOTFS/dev/ptmx && touch $ROOTFS/dev/null && mount --bind /dev/null $ROOTFS/dev/null && /bin/hostname $UUID && exec capsh --chroot=$ROOTFS --drop=cap_sys_chroot -- -c 'exec /bin/sh' "
これで以下のようなプロンプトが表示される。
sh-4.2#
削除
コンテナを停止させて cgroup やファイルシステムを削除する。
sh-4.2# exit $ sudo cgdelete -r -g cpu,memory:$UUID $ rm -rf $ROOTFS
まとめ
コンテナの仕組みの勉強のため、以下の記事や参考リンクを見ながらcgroupとNamespaceでコンテナを動かしてみた。 仕組みの理解が進んだのと同時にdockerの便利さや凄さも実感できた。
参考
- コンテナ技術入門 - 仮想化との違いを知り、要素技術を触って学ぼう - エンジニアHub|若手Webエンジニアのキャリアを考える!
- 【連載】世界一わかりみが深いコンテナ & Docker入門 〜 その1:コンテナってなに? 〜 | SIOS Tech. Lab
- 第42回 Linuxカーネルのケーパビリティ[1]:LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術|gihyo.jp … 技術評論社
- 第16回 Linuxカーネルのコンテナ機能 [6] ─ユーザ名前空間:LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術|gihyo.jp … 技術評論社
- 第1章 コントロールグループの概要 (cgroup) Red Hat Enterprise Linux 7 | Red Hat Customer Portal
- 3.2. cpu Red Hat Enterprise Linux 6 | Red Hat Customer Portal
- 2.9. コントロールグループ内のプロセスの開始 Red Hat Enterprise Linux 6 | Red Hat Customer Portal
- 要素技術を触って学ぶ「コンテナ技術入門」を実際にやってみた - フラミナル
- 第3章 Linuxシステムの仕組みと運用、管理
- dockerコマンド無しでコンテナを動かしてみる - Data Eng (なりたい)