概要
Kubernetesではコンテナを作成するとき、コンテナランタイム(高レベルランタイム、低レベルランタイム)を利用しています。
低レベルランタイムであるyoukiを通じてコンテナに関する理解をちょっと深めます。
Youkiとは?
YoukiはRust言語で記載された低レベルコンテナランタイムです。
最近CNCFのsandboxとして登録されました。
モチベーションとしてruncよりも高速、Cよりもメモリ安全などがあると思います。
コンテナランタイムとは?
コンテナランタイムはコンテナを実行、管理する仕組みのことです。
主にコンテナのライフサイクルを管理する高レベルランタイムと実際のコンテナを作成する低レベルランタイムに別れます。
Kubernetesでは?
KubernetesでPodを作成する場合にはKubeletが実際にコンテナを作成しますが、その中ではコンテナランタイムが利用されています。
- Kubeletが自分のノードで実行するPodの情報を取得
- KubeletはCRIを通じて高レベルコンテナランタイムにコンテナ作成のリクエストを送信する
- 高レベルランタイムは低レベルランタイムを呼び出して、コンテナを作成する
Youkiを動かしてみる
youkiを実際に動かして、低レベルランタイムが何をやっているか体験してみます。(runcでも大体同様に実行できます)
EC2インスタンス(Ubuntu Server 24.04 LTS (HVM))上で実施
(youkiはDev Containerが用意されているので,そちらを利用することもできます)
準備
youkiをビルドする
必要なpackageをインストール
sudo apt-get install \
pkg-config \
libsystemd-dev \
build-essential \
libelf-dev \
libseccomp-dev \
libclang-dev \
libssl-dev
Build
just youki-devでyoukiのバイナリが作成されます。
git clone git@github.com:containers/youki.git
cd youki
just youki-dev
./youki -h
ファイルシステムを取得する
コンテナを動かすためのファイルシステムを用意します。
docker export $(docker create busybox) | tar -C rootfs -xvf -
config.jsonの雛形を作成
低レベルランタイムではconfig.jsonで実際のコンテナの設定を行います。
./youki spec
config.jsonのargsを以下の値に変更
"process": {
"terminal": false,
"user": {
"uid": 0,
"gid": 0
},
"args": [
"sleep", "300"
],
事前確認
コンテナ作成前のnamespaceやcgroupを確認してみます。
lsnsコマンドでnamespace確認
$ lsns -o NS,TYPE,PATH,NPROCS,PID,PPID,COMMAND,UID,USER
NS TYPE PATH NPROCS PID PPID COMMAND UID USER
4026531834 time /proc/1/ns/time 111 1 0 /sbin/init 0 root
4026531835 cgroup /proc/1/ns/cgroup 111 1 0 /sbin/init 0 root
4026531836 pid /proc/1/ns/pid 111 1 0 /sbin/init 0 root
4026531837 user /proc/1/ns/user 111 1 0 /sbin/init 0 root
4026531838 uts /proc/1/ns/uts 105 1 0 /sbin/init 0 root
4026531839 ipc /proc/1/ns/ipc 111 1 0 /sbin/init 0 root
4026531840 net /proc/1/ns/net 111 1 0 /sbin/init 0 root
4026531841 mnt /proc/1/ns/mnt 101 1 0 /sbin/init 0 root
4026532172 mnt /proc/189/ns/mnt 1 189 1 ├─/usr/lib/systemd/systemd-udevd 0 root
4026532173 uts /proc/189/ns/uts 1 189 1 ├─/usr/lib/systemd/systemd-udevd 0 root
4026532193 mnt /proc/332/ns/mnt 1 332 1 ├─/usr/lib/systemd/systemd-resolved 991 systemd-resolve
4026532202 mnt /proc/474/ns/mnt 1 474 1 ├─/usr/lib/systemd/systemd-networkd 998 systemd-network
4026532215 mnt /proc/684/ns/mnt 2 684 1 ├─/usr/sbin/chronyd -F 1 110 _chrony
4026532216 mnt /proc/22353/ns/mnt 1 22353 1 ├─/usr/lib/polkit-1/polkitd --no-debug 989 polkitd
4026532217 uts /proc/586/ns/uts 1 586 1 ├─/usr/lib/systemd/systemd-logind 0 root
4026532218 uts /proc/684/ns/uts 2 684 1 ├─/usr/sbin/chronyd -F 1 110 _chrony
4026532272 mnt /proc/586/ns/mnt 1 586 1 ├─/usr/lib/systemd/systemd-logind 0 root
4026532273 mnt /proc/3964/ns/mnt 1 3964 1 ├─/usr/sbin/irqbalance 0 root
4026532274 uts /proc/742/ns/uts 1 742 1 ├─/usr/sbin/rsyslogd -n -iNONE 102 syslog
4026532280 uts /proc/22353/ns/uts 1 22353 1 ├─/usr/lib/polkit-1/polkitd --no-debug 989 polkitd
4026532288 mnt /proc/22365/ns/mnt 1 22365 1 └─/usr/sbin/ModemManager 0 root
4026531862 mnt /proc/26/ns/mnt 1 26 2 kdevtmpfs 0 root
systemd-cglsコマンドでcgroup確認
systemd-cgls
CGroup /:
-.slice
├─user.slice
│ └─user-0.slice
│ ├─session-c13.scope
│ │ ├─124828 su
│ │ ├─124845 bash
│ │ ├─124856 systemd-cgls
│ │ └─124857 pager
│ └─user@0.service …
│ └─init.scope
│ ├─124831 /usr/lib/systemd/systemd --user
│ └─124833 (sd-pam)
├─init.scope
│ └─1 /sbin/init
└─system.slice
├─irqbalance.service
│ └─3964 /usr/sbin/irqbalance
├─containerd.service …
...
コンテナを作成
- youki createで作成
- -bオプションでバンドルするファイルシステムを指定する
- 名前がtutorial_containerのコンテナを作成する
./youki create -b tutorial tutorial_container
コンテナ作成後namespaceを確認します
PIDが124891のnamespaceが作成されていることがわかります。
lsns -o NS,TYPE,PATH,NPROCS,PID,PPID,COMMAND,UID,USER
NS TYPE PATH NPROCS PID PPID COMMAND UID USER
4026531834 time /proc/1/ns/time 113 1 0 /sbin/init 0 root
4026531835 cgroup /proc/1/ns/cgroup 112 1 0 /sbin/init 0 root
4026531836 pid /proc/1/ns/pid 112 1 0 /sbin/init 0 root
4026531837 user /proc/1/ns/user 113 1 0 /sbin/init 0 root
4026531838 uts /proc/1/ns/uts 106 1 0 /sbin/init 0 root
4026531839 ipc /proc/1/ns/ipc 112 1 0 /sbin/init 0 root
4026531840 net /proc/1/ns/net 112 1 0 /sbin/init 0 root
4026531841 mnt /proc/1/ns/mnt 102 1 0 /sbin/init 0 root
4026532172 mnt /proc/189/ns/mnt 1 189 1 ├─/usr/lib/systemd/systemd-udevd 0 root
4026532173 uts /proc/189/ns/uts 1 189 1 ├─/usr/lib/systemd/systemd-udevd 0 root
4026532193 mnt /proc/332/ns/mnt 1 332 1 ├─/usr/lib/systemd/systemd-resolved 991 systemd-resolve
4026532202 mnt /proc/474/ns/mnt 1 474 1 ├─/usr/lib/systemd/systemd-networkd 998 systemd-network
4026532215 mnt /proc/684/ns/mnt 2 684 1 ├─/usr/sbin/chronyd -F 1 110 _chrony
4026532216 mnt /proc/22353/ns/mnt 1 22353 1 ├─/usr/lib/polkit-1/polkitd --no-debug 989 polkitd
4026532217 uts /proc/586/ns/uts 1 586 1 ├─/usr/lib/systemd/systemd-logind 0 root
4026532218 uts /proc/684/ns/uts 2 684 1 ├─/usr/sbin/chronyd -F 1 110 _chrony
4026532221 pid /proc/124891/ns/pid 1 124891 1 ├─./youki create -b tutorial tutorial_container 0 root
4026532222 uts /proc/124891/ns/uts 1 124891 1 ├─./youki create -b tutorial tutorial_container 0 root
4026532223 ipc /proc/124891/ns/ipc 1 124891 1 ├─./youki create -b tutorial tutorial_container 0 root
4026532224 net /proc/124891/ns/net 1 124891 1 ├─./youki create -b tutorial tutorial_container 0 root
4026532272 mnt /proc/586/ns/mnt 1 586 1 ├─/usr/lib/systemd/systemd-logind 0 root
4026532273 mnt /proc/3964/ns/mnt 1 3964 1 ├─/usr/sbin/irqbalance 0 root
4026532274 uts /proc/742/ns/uts 1 742 1 ├─/usr/sbin/rsyslogd -n -iNONE 102 syslog
4026532280 uts /proc/22353/ns/uts 1 22353 1 ├─/usr/lib/polkit-1/polkitd --no-debug 989 polkitd
4026532287 cgroup /proc/124891/ns/cgroup 1 124891 1 ├─./youki create -b tutorial tutorial_container 0 root
4026532288 mnt /proc/22365/ns/mnt 1 22365 1 ├─/usr/sbin/ModemManager 0 root
4026532289 mnt /proc/124891/ns/mnt 1 124891 1 └─./youki create -b tutorial tutorial_container 0 root
4026531862 mnt /proc/26/ns/mnt 1 26 2 kdevtmpfs 0 root
cgroupも:youki:tutorial_containerが作成されていることが確認できます
CGroup /:
-.slice
├─:youki:tutorial_container
│ └─124891 ./youki create -b tutorial tutorial_container
├─user.slice
│ └─user-0.slice
│ ├─session-c13.scope
│ │ ├─124828 su
│ │ ├─124845 bash
│ │ ├─124894 systemd-cgls
│ │ └─124895 pager
│ └─user@0.service …
│ └─init.scope
│ ├─124831 /usr/lib/systemd/systemd --user
│ └─124833 (sd-pam)
├─init.scope
│ └─1 /sbin/init
└─system.slice
ls /sys/fs/cgroup/:youki:tutorial_container
cgroup.controllers cgroup.threads cpu.weight hugetlb.1GB.events hugetlb.2MB.numa_stat memory.events.local memory.stat pids.events
cgroup.events cgroup.type cpu.weight.nice hugetlb.1GB.events.local hugetlb.2MB.rsvd.current memory.high memory.swap.current pids.max
cgroup.freeze cpu.idle cpuset.cpus hugetlb.1GB.max hugetlb.2MB.rsvd.max memory.low memory.swap.events pids.peak
cgroup.kill cpu.max cpuset.cpus.effective hugetlb.1GB.numa_stat io.max memory.max memory.swap.high
cgroup.max.depth cpu.max.burst cpuset.cpus.exclusive hugetlb.1GB.rsvd.current io.pressure memory.min memory.swap.max
cgroup.max.descendants cpu.pressure cpuset.cpus.exclusive.effective hugetlb.1GB.rsvd.max io.prio.class memory.numa_stat memory.swap.peak
cgroup.pressure cpu.stat cpuset.cpus.partition hugetlb.2MB.current io.stat memory.oom.group memory.zswap.current
cgroup.procs cpu.stat.local cpuset.mems hugetlb.2MB.events io.weight memory.peak memory.zswap.max
cgroup.stat cpu.uclamp.max cpuset.mems.effective hugetlb.2MB.events.local memory.current memory.pressure memory.zswap.writeback
cgroup.subtree_control cpu.uclamp.min hugetlb.1GB.current hugetlb.2MB.max memory.events memory.reclaim pids.current
コンテナを起動します
./youki start tutorial_container
作成されたnamespaceに入ってコマンドを実行する
プロセスが隔離されて実行されていることが確認できます
PID=124921
nsenter --target $PID --uts --mount --ipc --net --pid /bin/sh
/ # ps -ef
PID USER TIME COMMAND
1 root 0:00 sleep 300
2 root 0:00 /bin/sh
3 root 0:00 ps -ef
まとめ
コンテナランタイムについて簡単に紹介し、youkiを実際に動かしてみました。
他にも色々config.jsonの値を変えてみて、試してみると面白いと思います。