こんにちは.前回のポストからだいぶ時間が空きましたが,相変わらず緊急事態宣言中で自宅待機なので時間を持て余しています.
ONE PIECEを読み返していたんですが,無料で読める分を読み終わってしまったので暇です.
今回はdockerに使用されているコンテナランタイムであるrunc
を使ってみました.
では,いきます.
# runcを使ってみる
# runcとは
runc
とは,dockerなどのバックエンドで使用されるコンテナランタイムの一つで,dockerのデフォルトのランタイムです.
コンテナプロセスの作成やリソースの制限を実行します.
実装はgolangです.
# 使ってみる
早速使ってみましょう.実験環境にはVagrantで作成したubuntuを使用します. dockerが動く環境であればruncは入っているはずなのでインストールなどは省略します.
# 概要
runc - Open Container Initiative runtime runc is a command line client for running applications packaged according to the Open Container Initiative (OCI) format and is a compliant implementation of the Open Container Initiative specification.
runc integrates well with existing process supervisors to provide a production container runtime environment for applications. It can be used with your existing process monitoring tools and the container will be spawned as a direct child of the process supervisor.
Containers are configured using bundles. A bundle for a container is a directory that includes a specification file named "config.json" and a root filesystem. The root filesystem contains the contents of the container.
To start a new instance of a container: # runc run [ -b bundle ]
Where "
" is your name for the instance of the container that you are starting. The name you provide for the container instance must be unique on your host. Providing the bundle directory using "-b" is optional. The default value for "bundle" is the current directory.
使用しそうなコマンドは以下の通り
- create
- delete
- exec
- kill
- ps
- run
- spec
- start
では早速使ってみましょう.
# rootfsの準備
runcでは,dockerと違い作成するコンテナのファイルなどを用意してくれません.そこをいい感じにやってくれているのがdockerということですね. というわけで自分で用意します.
$ mkdir runc-test
$ cd runc-test
2
rootfs
ディレクトリを作成します.
$ mkdir rootfs
今回は作成するコンテナのファイルたちをdockerを経由してエクスポートしてきます. そのために,一旦dockerでコンテナを起動します.今回はcentosイメージを使用しました.(なんでもいいです)
$ sudo docker run -it centos /bin/sh
別ターミナルで
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bc36fee690d6 centos "/bin/sh" 6 seconds ago Up 5 seconds suspicious_keller
2
3
NAMES
を記録して,以下コマンドを実行してcentosのファイルシステムをtarファイルにexportします.
$ sudo docker export suspicious_keller > runc-test-centos.tar
すると,runc-test-centos.tar
なるファイルが作成されるので展開しましょう.
$ tar -xvf runc-test-centos.tar
$ rm runc-test-centos.tar
2
とするとcentosのファイルシステムがカントディレクトリ(/runc-test/rootfs)に展開されます.
$ ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
2
これでrootfsの準備が完了しました.
# config.jsonの準備
コンテナはconfig.json
から設定を読み込んで起動されます.ですので,config.json
を準備しましょう.
config.json
はrunc spec
コマンドで生成されます.
$ cd ..
$ sudo runc spec
2
生成されたconfig.json
をみてみましょう.
{
"ociVersion": "1.0.1-dev",
"process": {
"terminal": true,
"user": {
"uid": 0,
"gid": 0
},
"args": [
"sh"
],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm"
],
"cwd": "/",
"capabilities": {
"bounding": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"effective": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"inheritable": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"permitted": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"ambient": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
]
},
"rlimits": [
{
"type": "RLIMIT_NOFILE",
"hard": 1024,
"soft": 1024
}
],
"noNewPrivileges": true
},
"root": {
"path": "rootfs",
"readonly": true
},
"hostname": "runc",
"mounts": [
{
"destination": "/proc",
"type": "proc",
"source": "proc"
},
{
"destination": "/dev",
"type": "tmpfs",
"source": "tmpfs",
"options": [
"nosuid",
"strictatime",
"mode=755",
"size=65536k"
]
},
{
"destination": "/dev/pts",
"type": "devpts",
"source": "devpts",
"options": [
"nosuid",
"noexec",
"newinstance",
"ptmxmode=0666",
"mode=0620",
"gid=5"
]
},
{
"destination": "/dev/shm",
"type": "tmpfs",
"source": "shm",
"options": [
"nosuid",
"noexec",
"nodev",
"mode=1777",
"size=65536k"
]
},
{
"destination": "/dev/mqueue",
"type": "mqueue",
"source": "mqueue",
"options": [
"nosuid",
"noexec",
"nodev"
]
},
{
"destination": "/sys",
"type": "sysfs",
"source": "sysfs",
"options": [
"nosuid",
"noexec",
"nodev",
"ro"
]
},
{
"destination": "/sys/fs/cgroup",
"type": "cgroup",
"source": "cgroup",
"options": [
"nosuid",
"noexec",
"nodev",
"relatime",
"ro"
]
}
],
"linux": {
"resources": {
"devices": [
{
"allow": false,
"access": "rwm"
}
]
},
"namespaces": [
{
"type": "pid"
},
{
"type": "network"
},
{
"type": "ipc"
},
{
"type": "uts"
},
{
"type": "mount"
}
],
"maskedPaths": [
"/proc/kcore",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/sys/firmware",
"/proc/scsi"
],
"readonlyPaths": [
"/proc/asound",
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
capabilities
やnamespaces
などいろいろ設定されています.
process -> args
に起動コマンドとしてsh
が登録されているのでコンテナプロセスがsh
を実行して起動するようです.
# コンテナの起動
それではコンテナプロセスを起動してみます.
コンテナを起動するにはrunc run [container-id]
です.
$ sudo runc run runc-test-centos
sh-4.4#
2
シェルが立ち上がり,無事起動できているようです. これでruncでコンテナを起動することができました.
# その他のコマンドを使ってみる
この調子で他のコマンドを使用してみます.
# create
create
はコンテナを作成サブコマンドです.
$ sudo runc create runc-test-centos2
cannot allocate tty if runc will detach without setting console socket
2
単純に実行するとエラーになりました.
デタッチするときにconsole-socket
を設定してないとtty
を割り当てることができないと言われているので,とりあえずconfig.json
のprocess>terminal
をfalse
に更新して再度実行すると作成できました.
# list
list
で作成されたコンテナを確認することができます.
$ sudo runc list
ID PID STATUS BUNDLE CREATED OWNER
runc-test-centos2 3609 created /home/vagrant/runc-test 2020-04-29T09:35:09.882689575Z root
2
3
無事作成できているようです.
# ps
ps
で指定したコンテナの状態をみることができます.
先ほど作成したrunc-test-centos2
の状態をみてみましょう.
UID PID PPID C STIME TTY TIME CMD
root 3609 1 0 09:35 ? 00:00:00 runc init
2
このコンテナはまだスタートしていないのでCMD
の項目がrunc init
となっていますね.
# start
では,先ほど作成したコンテナを起動してみましょう.
start
でコンテナを起動します.
$ sudo runc start runc-test-centos2
sh: cannot set terminal process group (-1): Inappropriate ioctl for device
sh: no job control in this shell
sh-4.4# vagrant@ubuntu-xenial:~/runc-test$
2
3
4
起動しているようですが,シェルのエラーが出ています.
これはおそらくcreate
するときにterminal: false
にしたからですね.別の方法がありそうです.
とりあえず起動はできたのでよしとします.(怠慢)
# delete
delete
で作成したコンテナを削除します.
$ sudo runc delete runc-test-centos2
何も出てこなければ正常に削除できています.
# まとめ
今回はコンテナランタイムのデファクトスタンダードであるrunc
について一通り使用してみました.dockerでも使用されているのでdockerでコンテナを使用する際に内部でどんなことをしているのかが少し理解できました.