containerd v1.1.2を動かして色々操作してみた

containerdを動かしてコンテナを作ったりイメージをプルしたり色々やってみようっていう内容です。containerdに対する操作はCLIツールのctrを使用します。

containerdのインストールと実行

GitHubのリリースページよりtarballをダウンロードしてきます。今回はバージョンv1.1.2をダウンロードします。

containerd-1.1.2.linux-amd64.tar.gzはビルド済みのバイナリファイルが入ってるので、解凍すればすぐ使えて便利です。

github.com

ダウンロードして解凍するとbinディレクトリが出てきます。その中にはcontainerdの他にctrなどのツールも入ってます。

ubuntu@v-Ubuntu:~$ wget https://github.com/containerd/containerd/releases/download/v1.1.2/containerd-1.1.2.linux-amd64.tar.gz
ubuntu@v-Ubuntu:~$ tar -xzf containerd-1.1.2.linux-amd64.tar.gz
ubuntu@v-Ubuntu:~$ rm containerd-1.1.2.linux-amd64.tar.gz 
ubuntu@v-Ubuntu:~$ cd bin
ubuntu@v-Ubuntu:~/bin$ ls
containerd  containerd-release  containerd-shim  containerd-stress  ctr
ubuntu@v-Ubuntu:~/bin$ sudo cp * /usr/bin/

さっそくcontianerdを起動してみましょう。

ubuntu@v-Ubuntu:~/bin$ sudo containerd
INFO[0000] starting containerd                           revision=468a545b9edcd5932818eb9de8e72413e616e86e version=v1.1.2
INFO[0000] loading plugin "io.containerd.content.v1.content"...  type=io.containerd.content.v1
INFO[0000] loading plugin "io.containerd.snapshotter.v1.btrfs"...  type=io.containerd.snapshotter.v1
WARN[0000] failed to load plugin io.containerd.snapshotter.v1.btrfs  error="path /var/lib/containerd/io.containerd.snapshotter.v1.btrfs must be a btrfs filesystem to be used with the btrfs snapshotter"
INFO[0000] loading plugin "io.containerd.snapshotter.v1.aufs"...  type=io.containerd.snapshotter.v1
INFO[0000] loading plugin "io.containerd.snapshotter.v1.native"...  type=io.containerd.snapshotter.v1
INFO[0000] loading plugin "io.containerd.snapshotter.v1.overlayfs"...  type=io.containerd.snapshotter.v1
INFO[0000] loading plugin "io.containerd.snapshotter.v1.zfs"...  type=io.containerd.snapshotter.v1
WARN[0000] failed to load plugin io.containerd.snapshotter.v1.zfs  error="path /var/lib/containerd/io.containerd.snapshotter.v1.zfs must be a zfs filesystem to be used with the zfs snapshotter"
INFO[0000] loading plugin "io.containerd.metadata.v1.bolt"...  type=io.containerd.metadata.v1
WARN[0000] could not use snapshotter zfs in metadata plugin  error="path /var/lib/containerd/io.containerd.snapshotter.v1.zfs must be a zfs filesystem to be used with the zfs snapshotter"
WARN[0000] could not use snapshotter btrfs in metadata plugin  error="path /var/lib/containerd/io.containerd.snapshotter.v1.btrfs must be a btrfs filesystem to be used with the btrfs snapshotter"
INFO[0000] loading plugin "io.containerd.differ.v1.walking"...  type=io.containerd.differ.v1
INFO[0000] loading plugin "io.containerd.gc.v1.scheduler"...  type=io.containerd.gc.v1
INFO[0000] loading plugin "io.containerd.service.v1.containers-service"...  type=io.containerd.service.v1
INFO[0000] loading plugin "io.containerd.service.v1.content-service"...  type=io.containerd.service.v1
INFO[0000] loading plugin "io.containerd.service.v1.diff-service"...  type=io.containerd.service.v1
INFO[0000] loading plugin "io.containerd.service.v1.images-service"...  type=io.containerd.service.v1
INFO[0000] loading plugin "io.containerd.service.v1.leases-service"...  type=io.containerd.service.v1
INFO[0000] loading plugin "io.containerd.service.v1.namespaces-service"...  type=io.containerd.service.v1
INFO[0000] loading plugin "io.containerd.service.v1.snapshots-service"...  type=io.containerd.service.v1
INFO[0000] loading plugin "io.containerd.monitor.v1.cgroups"...  type=io.containerd.monitor.v1
INFO[0000] loading plugin "io.containerd.runtime.v1.linux"...  type=io.containerd.runtime.v1
INFO[0000] loading plugin "io.containerd.service.v1.tasks-service"...  type=io.containerd.service.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.containers"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.content"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.diff"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.events"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.healthcheck"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.images"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.leases"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.namespaces"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.snapshots"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.tasks"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.version"...  type=io.containerd.grpc.v1
INFO[0000] loading plugin "io.containerd.grpc.v1.cri"...  type=io.containerd.grpc.v1
INFO[0000] Start cri plugin with config {PluginConfig:{ContainerdConfig:{Snapshotter:overlayfs DefaultRuntime:{Type:io.containerd.runtime.v1.linux Engine: Root:} UntrustedWorkloadRuntime:{Type: Engine: Root:}} CniConfig:{NetworkPluginBinDir:/opt/cni/bin NetworkPluginConfDir:/etc/cni/net.d NetworkPluginConfTemplate:} Registry:{Mirrors:map[docker.io:{Endpoints:[https://registry-1.docker.io]}]} StreamServerAddress: StreamServerPort:10010 EnableSelinux:false SandboxImage:k8s.gcr.io/pause:3.1 StatsCollectPeriod:10 SystemdCgroup:false EnableTLSStreaming:false MaxContainerLogLineSize:16384} ContainerdRootDir:/var/lib/containerd ContainerdEndpoint:/run/containerd/containerd.sock RootDir:/var/lib/containerd/io.containerd.grpc.v1.cri StateDir:/run/containerd/io.containerd.grpc.v1.cri} 
INFO[0000] Connect containerd service                   
INFO[0000] Get image filesystem path "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs" 
ERRO[0000] Failed to load cni during init, please check CRI plugin status before setting up network for pods  error="cni config load failed: no network config found in /etc/cni/net.d: cni plugin not initialized: failed to load cni config"
INFO[0000] loading plugin "io.containerd.grpc.v1.introspection"...  type=io.containerd.grpc.v1
INFO[0000] Start subscribing containerd event           
INFO[0000] Start recovering state                       
INFO[0000] serving...                                    address="/run/containerd/containerd.sock"
INFO[0000] containerd successfully booted in 0.032078s  
INFO[0000] Start event monitor                          
INFO[0000] Start snapshots syncer                       
INFO[0000] Start streaming server                       

CNIのエラーが起きていますが、今回はお触りするだけなのでほっといていいです。

containerdの操作

ctrを使うことでCLIからcontainerdを操作することができます。

ubuntu@v-Ubuntu:~$ sudo ctr
NAME:
   ctr - 
        __
  _____/ /______
 / ___/ __/ ___/
/ /__/ /_/ /
\___/\__/_/

containerd CLI


USAGE:
   ctr [global options] command [command options] [arguments...]

VERSION:
   v1.1.2

COMMANDS:
     plugins, plugin           provides information about containerd plugins
     version                   print the client and server versions
     containers, c, container  manage containers
     content                   manage content
     events, event             display containerd events
     images, image, i          manage images
     namespaces, namespace     manage namespaces
     pprof                     provide golang pprof outputs for containerd
     run                       run a container
     snapshots, snapshot       manage snapshots
     tasks, t, task            manage tasks
     shim                      interact with a shim directly
     cri                       interact with cri plugin
     help, h                   Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --debug                      enable debug output in logs
   --address value, -a value    address for containerd's GRPC server (default: "/run/containerd/containerd.sock")
   --timeout value              total timeout for ctr commands (default: 0s)
   --connect-timeout value      timeout for connecting to containerd (default: 0s)
   --namespace value, -n value  namespace to use with commands (default: "default") [$CONTAINERD_NAMESPACE]
   --help, -h                   show help
   --version, -v                print the version
ubuntu@v-Ubuntu:~$

イメージのプル

ctr image pullでプルができます。

ubuntu@v-Ubuntu:~$ sudo ctr image pull --help
NAME:
   ctr images pull - pull an image from a remote

USAGE:
   ctr images pull [command options] [flags] <ref>

DESCRIPTION:
   Fetch and prepare an image for use in containerd.

After pulling an image, it should be ready to use the same reference in a run
command. As part of this process, we do the following:

1. Fetch all resources into containerd.
2. Prepare the snapshot filesystem with the pulled resources.
3. Register metadata for the image.


OPTIONS:
   --skip-verify, -k       skip SSL certificate validation
   --plain-http            allow connections using plain HTTP
   --user value, -u value  user[:password] Registry user and password
   --refresh value         refresh token for authorization server
   --snapshotter value     snapshotter name. Empty value stands for the default value. (default: "overlayfs") [$CONTAINERD_SNAPSHOTTER]
   --label value           labels to attach to the image
   --platform value        Pull content from a specific platform (default: "linux/amd64")
   --all-platforms         pull content from all platforms
   
ubuntu@v-Ubuntu:~$ 

docker pullでは引数にイメージ名を渡すだけでdocker.io/library/<image name>:latestなイメージをプルすることができましたが、ctrでは「ドメインリポジトリ、イメージ名、タグ」を全て指定しないとできないようです。ちょいと面倒臭い。

ubuntu@v-Ubuntu:~$ sudo ctr image pull redis
ctr: failed to resolve reference "redis": object required
ubuntu@v-Ubuntu:~/bin$ sudo ctr image pull redis:latest
ctr: failed to resolve reference "redis:latest": object required
ubuntu@v-Ubuntu:~/bin$ sudo ctr image pull docker.io/redis:latest
docker.io/redis:latest: resolving      |--------------------------------------| 
elapsed: 1.6 s          total:   0.0 B (0.0 B/s)                                         
ctr: failed to resolve reference "docker.io/redis:latest": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
ubuntu@v-Ubuntu:~/bin$ sudo ./ctr image pull docker.io/library/redis:latest
docker.io/library/redis:latest:                                                   resolved       |++++++++++++++++++++++++++++++++++++++| 
index-sha256:096cff9e6024603decb2915ea3e501c63c5bb241e1b56830a52acfd488873843:    done           |++++++++++++++++++++++++++++++++++++++| 
manifest-sha256:f20ec679e1bdf0b6a83b4b4d4097dddf08edf0aa3cc6ff2ef4b9afebb0c8b5ef: done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:ce8aaa9fe90ad0dada1d2b2fed22ee9bb64bcfc1a5a4d5f7d2fe392df35050aa:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:d6f5ea773ca39a0094e300aec4c30478b616d1631382c6eba21fdc2fa20c0385:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:735cc65c0db489710ba88840b2075d6d4195f0d0c5dfc5e59fdfc6243aca0daf:    done           |++++++++++++++++++++++++++++++++++++++| 
config-sha256:f06a5773f01e1f77eb4487acb3333649716f45b3c32aad038765dc0ab0337bd4:   done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:ff89c30e4d8c53c3403ed2c09737963e5e1c2052f285e34c3ae3baf2d49b2017:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:59bf782a86b38d9f3b9e9c20588467b427460403d06146099026cdf1310a7285:    done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:be8881be8156e4068e611fe956aba2b9593ebd953be14fb7feea6d0659aa3abe:    done           |++++++++++++++++++++++++++++++++++++++| 
elapsed: 1.9 s                                                                    total:  9.2 Mi (4.8 MiB/s)                                       
unpacking sha256:096cff9e6024603decb2915ea3e501c63c5bb241e1b56830a52acfd488873843...
done
ubuntu@v-Ubuntu:~$ 

イメージ一覧の取得

ctr image lsで取得可能。

ubuntu@v-Ubuntu:~$ sudo ctr image ls --help
NAME:
   ctr images list - list images known to containerd

USAGE:
   ctr images list [command options] [flags] <ref>

DESCRIPTION:
   list images registered with containerd

OPTIONS:
   --quiet, -q  print only the image refs
   
ubuntu@v-Ubuntu:~$ 

ターミナルの横幅が狭いと一行で収まらないのがなんか嫌ですね(PLATFORMSとかTYPEのカラムはオプションで表示できるようにしたいんですけど...)

ubuntu@v-Ubuntu:~$ sudo ctr image ls
REF                            TYPE                                                      DIGEST                                                                  SIZE     PLATFORMS                                                                                LABELS 
docker.io/library/redis:latest application/vnd.docker.distribution.manifest.list.v2+json sha256:096cff9e6024603decb2915ea3e501c63c5bb241e1b56830a52acfd488873843 30.6 MiB linux/386,linux/amd64,linux/arm/v5,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -      
ubuntu@v-Ubuntu:~/bin$ sudo ./ctr image ls -q
docker.io/library/redis:latest
ubuntu@v-Ubuntu:~$

コンテナの作成・起動

ctr runでできます。

ubuntu@v-Ubuntu:~$ sudo ctr run --help
NAME:
   ctr run - run a container

USAGE:
   ctr run [command options] [flags] Image|RootFS ID [COMMAND] [ARG...]

OPTIONS:
   --rm                      remove the container after running
   --null-io                 send all IO to /dev/null
   --detach, -d              detach from the task after it has started execution
   --fifo-dir value          directory used for storing IO FIFOs
   --snapshotter value       snapshotter name. Empty value stands for the default value. (default: "overlayfs") [$CONTAINERD_SNAPSHOTTER]
   --config value, -c value  path to the runtime-specific spec config file
   --checkpoint value        provide the checkpoint digest to restore the container
   --cwd value               specify the working directory of the process
   --env value               specify additional container environment variables (i.e. FOO=bar)
   --label value             specify additional labels (i.e. foo=bar)
   --mount value             specify additional container mount (ex: type=bind,src=/tmp,dst=/host,options=rbind:ro)
   --net-host                enable host networking for the container
   --privileged              run privileged container
   --read-only               set the containers filesystem as readonly
   --runtime value           runtime name (io.containerd.runtime.v1.linux, io.containerd.runtime.v1.windows, io.containerd.runtime.v1.com.vmware.linux) (default: "io.containerd.runtime.v1.linux")
   --tty, -t                 allocate a TTY for the container
   --with-ns value           specify existing Linux namespaces to join at container runtime (format '<nstype>:<path>')
   --pid-file value          file path to write the task's pid
   
ubuntu@v-Ubuntu:~$ 

ここでちょいと詰まります。redisのコンテナを動かそうとしたらOCI runtime errorなるものが発生。どうやらruncが必要なようです。

ubuntu@v-Ubuntu:~$ sudo ctr run -d docker.io/library/redis:latest redis1
ctr: OCI runtime create failed: unable to retrieve OCI runtime error (open /run/containerd/io.containerd.runtime.v1.linux/default/redis1/log.json: no such file or directory): exec: "runc": executable file not found in $PATH: unknown
ubuntu@v-Ubuntu:~$

というわけでruncをインストールします。GithHubのリリースページより1.0.0のバイナリファイルをダウンロードしました。

github.com

ubuntu@v-Ubuntu:~$ wget https://github.com/opencontainers/runc/releases/download/v1.0.0-rc5/runc.amd64
ubuntu@v-Ubuntu:~$ chmod +x runc.amd64 
ubuntu@v-Ubuntu:~$ sudo cp runc.amd64 /usr/bin/runc

これでどうじゃ!と思ったらまた詰まります。

ubuntu@v-Ubuntu:~$ sudo ctr run -d docker.io/library/redis:latest redis1
ctr: snapshot "redis1": already exists
ubuntu@v-Ubuntu:~$

redis1のスナップショットが存在するということです。スナップショットが何かということについてはあとで説明します。

ctr runが失敗してもスナップショットとコンテナ(ただし停止している)が作成されるようです。これらを削除するためにctr container rm redisを実行します。

ubuntu@v-Ubuntu:~$ sudo ctr container rm redis1

これでどうじゃ!

ubuntu@v-Ubuntu:~$ sudo ctr run -d docker.io/library/redis:latest redis1
1:C 30 Jul 11:18:28.266 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 30 Jul 11:18:28.266 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 30 Jul 11:18:28.266 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
1:M 30 Jul 11:18:28.267 # You requested maxclients of 10000 requiring at least 10032 max file descriptors.
1:M 30 Jul 11:18:28.267 # Server can't set maximum open files to 10032 because of OS error: Operation not permitted.
1:M 30 Jul 11:18:28.267 # Current maximum open files is 1024. maxclients has been reduced to 992 to compensate for low ulimit. If you need higher maxclients increase 'ulimit -n'.
1:M 30 Jul 11:18:28.267 * Running mode=standalone, port=6379.
1:M 30 Jul 11:18:28.267 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 30 Jul 11:18:28.267 # Server initialized
1:M 30 Jul 11:18:28.267 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
1:M 30 Jul 11:18:28.267 * Ready to accept connections
ubuntu@v-Ubuntu:~$

なんかうまくいったようです。

コンテナがRUNNINGになっているかを確認する

containerdでは起動中のコンテナ(プロセス)は「タスク」として扱います。

 ubuntu@v-Ubuntu:~$ sudo ctr task
NAME:
   ctr tasks - manage tasks

USAGE:
   ctr tasks command [command options] [arguments...]

COMMANDS:
     attach      attach to the IO of a running container
     checkpoint  checkpoint a container
     delete      [flags] delete a task
     exec        execute additional processes in an existing container
     list, ls    list tasks
     kill        signal a container (default: SIGTERM)
     pause       pause an existing container
     ps          list processes for container
     resume      resume a paused container
     start       start a container that have been created

OPTIONS:
   --help, -h  show help
   
ubuntu@v-Ubuntu:~$

ctr task lsでタスクの一覧を表示できます。

ubuntu@v-Ubuntu:~$ sudo ctr task ls
TASK      PID      STATUS    
redis1    16722    RUNNING
ubuntu@v-Ubuntu:~$

redis1が動いているのがわかりますね。

ついでにpsコマンドでどんなプロセスが動いているか確認しましょう。

ubuntu@v-Ubuntu:~$ ps axu
...
root     16705  0.0  0.0   7512  4184 pts/0    Sl   20:18   0:00 containerd-shim -namespace default -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/default/redis1 -address /run/containerd/containerd.sock -containerd-binary /home/ubuntu/bin/containerd
999      16722  0.0  0.0  41668  3528 ?        Ssl  20:18   0:00 redis-server *:6379
...
ubuntu@v-Ubuntu:~$

containerd-shimのプロセスがありますね。またredisは999というユーザーによって実行されているようです。

コンテナに入る

ctr task execdocker execライクなコマンドで、コンテナ内で特定のコマンドを実行できます。

ubuntu@v-Ubuntu:~$ sudo ctr task exec --help
NAME:
   ctr tasks exec - execute additional processes in an existing container

USAGE:
   ctr tasks exec [command options] [flags] CONTAINER CMD [ARG...]

OPTIONS:
   --cwd value       working directory of the new process
   --tty, -t         allocate a TTY for the container
   --exec-id value   exec specific id for the process
   --fifo-dir value  directory used for storing IO FIFOs
   
ubuntu@v-Ubuntu:~$ 

コンテナ内でシェルを起動してコンテナの中で操作をしてみましょう。

ubuntu@v-Ubuntu:~$ sudo ctr task exec -t redis1 /bin/bash 
ctr: exec id must not be empty: invalid argument
ubuntu@v-Ubuntu:~$ 

ありゃりゃ。exec idは絶対設定しないといけないようです。じゃあ適当にIDを指定して再度実行してみましょう。

ubuntu@v-Ubuntu:~$ sudo ctr task exec -t --exec-id 5000 redis1 /bin/bash 
root@v-Ubuntu:/data# cat /etc/hostname
debuerreotype
root@v-Ubuntu:/data# exit
exit
ubuntu@v-Ubuntu:~$ 

というわけでちゃんとコンテナの中に入れましたね。ちなみにctr attachでもコンテナの中に入れます(今回の場合はコンテナ内部でシェルが動いてないんでアタッチしたところで何もできませんが)

コンテナのリストやコンテナの情報を表示する

ubuntu@v-Ubuntu:~$ sudo ctr container
NAME:
   ctr containers - manage containers

USAGE:
   ctr containers command [command options] [arguments...]

COMMANDS:
     create           create container
     delete, del, rm  delete one or more existing containers
     info             get info about a container
     list, ls         list containers
     label            set and clear labels for a container

OPTIONS:
   --help, -h  show help
   
ubuntu@v-Ubuntu:~$

ctr container lsでコンテナ一覧を表示。停止しているコンテナも表示されます。今回はコンテナが1個だけ表示されます。

ubuntu@v-Ubuntu:~$ sudo ctr container ls 
CONTAINER    IMAGE                             RUNTIME                           
redis1       docker.io/library/redis:latest    io.containerd.runtime.v1.linux    
ubuntu@v-Ubuntu:~$

ctr container infoでコンテナの情報を見ることができます。

ubuntu@v-Ubuntu:~$ sudo ctr container info redis1
{
    "ID": "redis1",
    "Labels": null,
    "Image": "docker.io/library/redis:latest",
    "Runtime": {
        "Name": "io.containerd.runtime.v1.linux",
        "Options": null
    },
    "Spec": {
        "type_url": "types.containerd.io/opencontainers/runtime-spec/1/Spec",
        "value": "eyJvY2lWZXJzaW9uIjoiMS4wLjEiLCJwcm9jZXNzIjp7InVzZXIiOnsidWlkIjowLCJnaWQiOjB9LCJhcmdzIjpbImRvY2tlci1lbnRyeXBvaW50LnNoIiwicmVkaXMtc2VydmVyIl0sImVudiI6WyJQQVRIPS91c3IvbG9jYWwvc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL3NiaW46L3Vzci9iaW46L3NiaW46L2JpbiIsIlBBVEg9L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluIiwiR09TVV9WRVJTSU9OPTEuMTAiLCJSRURJU19WRVJTSU9OPTQuMC4xMCIsIlJFRElTX0RPV05MT0FEX1VSTD1odHRwOi8vZG93bmxvYWQucmVkaXMuaW8vcmVsZWFzZXMvcmVkaXMtNC4wLjEwLnRhci5neiIsIlJFRElTX0RPV05MT0FEX1NIQT0xZGI2NzQzNWE3MDRmOGQxOGFlYzliOTYzN2IzNzNjMzRhYTIzM2Q2NWI2ZTE3NGJkYWM0YzFiMTYxZjM4Y2E0Il0sImN3ZCI6Ii9kYXRhIiwiY2FwYWJpbGl0aWVzIjp7ImJvdW5kaW5nIjpbIkNBUF9DSE9XTiIsIkNBUF9EQUNfT1ZFUlJJREUiLCJDQVBfRlNFVElEIiwiQ0FQX0ZPV05FUiIsIkNBUF9NS05PRCIsIkNBUF9ORVRfUkFXIiwiQ0FQX1NFVEdJRCIsIkNBUF9TRVRVSUQiLCJDQVBfU0VURkNBUCIsIkNBUF9TRVRQQ0FQIiwiQ0FQX05FVF9CSU5EX1NFUlZJQ0UiLCJDQVBfU1lTX0NIUk9PVCIsIkNBUF9LSUxMIiwiQ0FQX0FVRElUX1dSSVRFIl0sImVmZmVjdGl2ZSI6WyJDQVBfQ0hPV04iLCJDQVBfREFDX09WRVJSSURFIiwiQ0FQX0ZTRVRJRCIsIkNBUF9GT1dORVIiLCJDQVBfTUtOT0QiLCJDQVBfTkVUX1JBVyIsIkNBUF9TRVRHSUQiLCJDQVBfU0VUVUlEIiwiQ0FQX1NFVEZDQVAiLCJDQVBfU0VUUENBUCIsIkNBUF9ORVRfQklORF9TRVJWSUNFIiwiQ0FQX1NZU19DSFJPT1QiLCJDQVBfS0lMTCIsIkNBUF9BVURJVF9XUklURSJdLCJpbmhlcml0YWJsZSI6WyJDQVBfQ0hPV04iLCJDQVBfREFDX09WRVJSSURFIiwiQ0FQX0ZTRVRJRCIsIkNBUF9GT1dORVIiLCJDQVBfTUtOT0QiLCJDQVBfTkVUX1JBVyIsIkNBUF9TRVRHSUQiLCJDQVBfU0VUVUlEIiwiQ0FQX1NFVEZDQVAiLCJDQVBfU0VUUENBUCIsIkNBUF9ORVRfQklORF9TRVJWSUNFIiwiQ0FQX1NZU19DSFJPT1QiLCJDQVBfS0lMTCIsIkNBUF9BVURJVF9XUklURSJdLCJwZXJtaXR0ZWQiOlsiQ0FQX0NIT1dOIiwiQ0FQX0RBQ19PVkVSUklERSIsIkNBUF9GU0VUSUQiLCJDQVBfRk9XTkVSIiwiQ0FQX01LTk9EIiwiQ0FQX05FVF9SQVciLCJDQVBfU0VUR0lEIiwiQ0FQX1NFVFVJRCIsIkNBUF9TRVRGQ0FQIiwiQ0FQX1NFVFBDQVAiLCJDQVBfTkVUX0JJTkRfU0VSVklDRSIsIkNBUF9TWVNfQ0hST09UIiwiQ0FQX0tJTEwiLCJDQVBfQVVESVRfV1JJVEUiXX0sInJsaW1pdHMiOlt7InR5cGUiOiJSTElNSVRfTk9GSUxFIiwiaGFyZCI6MTAyNCwic29mdCI6MTAyNH1dLCJub05ld1ByaXZpbGVnZXMiOnRydWV9LCJyb290Ijp7InBhdGgiOiJyb290ZnMifSwibW91bnRzIjpbeyJkZXN0aW5hdGlvbiI6Ii9wcm9jIiwidHlwZSI6InByb2MiLCJzb3VyY2UiOiJwcm9jIn0seyJkZXN0aW5hdGlvbiI6Ii9kZXYiLCJ0eXBlIjoidG1wZnMiLCJzb3VyY2UiOiJ0bXBmcyIsIm9wdGlvbnMiOlsibm9zdWlkIiwic3RyaWN0YXRpbWUiLCJtb2RlPTc1NSIsInNpemU9NjU1MzZrIl19LHsiZGVzdGluYXRpb24iOiIvZGV2L3B0cyIsInR5cGUiOiJkZXZwdHMiLCJzb3VyY2UiOiJkZXZwdHMiLCJvcHRpb25zIjpbIm5vc3VpZCIsIm5vZXhlYyIsIm5ld2luc3RhbmNlIiwicHRteG1vZGU9MDY2NiIsIm1vZGU9MDYyMCIsImdpZD01Il19LHsiZGVzdGluYXRpb24iOiIvZGV2L3NobSIsInR5cGUiOiJ0bXBmcyIsInNvdXJjZSI6InNobSIsIm9wdGlvbnMiOlsibm9zdWlkIiwibm9leGVjIiwibm9kZXYiLCJtb2RlPTE3NzciLCJzaXplPTY1NTM2ayJdfSx7ImRlc3RpbmF0aW9uIjoiL2Rldi9tcXVldWUiLCJ0eXBlIjoibXF1ZXVlIiwic291cmNlIjoibXF1ZXVlIiwib3B0aW9ucyI6WyJub3N1aWQiLCJub2V4ZWMiLCJub2RldiJdfSx7ImRlc3RpbmF0aW9uIjoiL3N5cyIsInR5cGUiOiJzeXNmcyIsInNvdXJjZSI6InN5c2ZzIiwib3B0aW9ucyI6WyJub3N1aWQiLCJub2V4ZWMiLCJub2RldiIsInJvIl19LHsiZGVzdGluYXRpb24iOiIvcnVuIiwidHlwZSI6InRtcGZzIiwic291cmNlIjoidG1wZnMiLCJvcHRpb25zIjpbIm5vc3VpZCIsInN0cmljdGF0aW1lIiwibW9kZT03NTUiLCJzaXplPTY1NTM2ayJdfV0sImxpbnV4Ijp7InJlc291cmNlcyI6eyJkZXZpY2VzIjpbeyJhbGxvdyI6ZmFsc2UsImFjY2VzcyI6InJ3bSJ9XX0sImNncm91cHNQYXRoIjoiL2RlZmF1bHQvcmVkaXMxIiwibmFtZXNwYWNlcyI6W3sidHlwZSI6InBpZCJ9LHsidHlwZSI6ImlwYyJ9LHsidHlwZSI6InV0cyJ9LHsidHlwZSI6Im1vdW50In0seyJ0eXBlIjoibmV0d29yayJ9XSwibWFza2VkUGF0aHMiOlsiL3Byb2MvYWNwaSIsIi9wcm9jL2tjb3JlIiwiL3Byb2Mva2V5cyIsIi9wcm9jL2xhdGVuY3lfc3RhdHMiLCIvcHJvYy90aW1lcl9saXN0IiwiL3Byb2MvdGltZXJfc3RhdHMiLCIvcHJvYy9zY2hlZF9kZWJ1ZyIsIi9zeXMvZmlybXdhcmUiLCIvcHJvYy9zY3NpIl0sInJlYWRvbmx5UGF0aHMiOlsiL3Byb2MvYXNvdW5kIiwiL3Byb2MvYnVzIiwiL3Byb2MvZnMiLCIvcHJvYy9pcnEiLCIvcHJvYy9zeXMiLCIvcHJvYy9zeXNycS10cmlnZ2VyIl19fQ=="
    },
    "SnapshotKey": "redis1",
    "Snapshotter": "overlayfs",
    "CreatedAt": "2018-07-30T11:18:28.151489308Z",
    "UpdatedAt": "2018-07-30T11:18:28.151489308Z",
    "Extensions": null
}
ubuntu@v-Ubuntu:~$ 

スナップショットを表示する

スナップショットはDockerイメージでいうところのレイヤーです。

ubuntu@v-Ubuntu:~$ sudo ctr snapshot
NAME:
   ctr snapshots - manage snapshots

USAGE:
   ctr snapshots command [command options] [arguments...]

COMMANDS:
     commit            commit an active snapshot into the provided name
     diff              get the diff of two snapshots. the default second snapshot is the first snapshot's parent.
     info              get info about a snapshot
     list, ls          list snapshots
     mounts, m, mount  mount gets mount commands for the snapshots
     prepare           prepare a snapshot from a committed snapshot
     remove, rm        remove snapshots
     label             add labels to content
     tree              display tree view of snapshot branches
     unpack            unpack applies layers from a manifest to a snapshot
     usage             usage snapshots
     view              create a read-only snapshot from a committed snapshot

OPTIONS:
   --snapshotter value  snapshotter name. Empty value stands for the default value. (default: "overlayfs") [$CONTAINERD_SNAPSHOTTER]
   --help, -h           show help
   
ubuntu@v-Ubuntu:~$ 

ctr snapshot lsでスナップショット一覧を表示します。

ubuntu@v-Ubuntu:~$ sudo ctr snapshot ls
KEY                                                                     PARENT                                                                  KIND      
redis1                                                                  sha256:3c7bfc410c0e316ba2b72a18e1ec45263b81921eafbec05d87cfb6dfd2a31f85 Active    
sha256:3c7bfc410c0e316ba2b72a18e1ec45263b81921eafbec05d87cfb6dfd2a31f85 sha256:f69435472d99c717999e1e458828567320e5f5375365c9551c2d13b489f30a22 Committed 
sha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016 sha256:e6b3eda8746c5cc312ebb40e1ca5c064638af429b9b3848280aab8ed882bd10b Committed 
sha256:aee8b479b9a768a64f4c32d69108566fbdbb71c8e541496dd1fa9f7ad19d8632 sha256:cdb3f9544e4c61d45da1ea44f7d92386639a052c620d1550376f22f5b46981af Committed 
sha256:cdb3f9544e4c61d45da1ea44f7d92386639a052c620d1550376f22f5b46981af                                                                         Committed 
sha256:e6b3eda8746c5cc312ebb40e1ca5c064638af429b9b3848280aab8ed882bd10b sha256:aee8b479b9a768a64f4c32d69108566fbdbb71c8e541496dd1fa9f7ad19d8632 Committed 
sha256:f69435472d99c717999e1e458828567320e5f5375365c9551c2d13b489f30a22 sha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016 Committed 
ubuntu@v-Ubuntu:~$ 

どのスナップショットがどのスナップショットの親かが分かるのがいいですね。ちなみにスナップショットredis1はコンテナredis1のwritableなスナップショットです。それ以外はredisのイメージに含まれるRead Onlyなスナップショットですね。

ctr snapshot treeはスナップショットの親子関係をツリーで表示してくれます。

ubuntu@v-Ubuntu:~$ sudo ctr snapshot tree
 sha256:cdb3f9544e4c61d45da1ea44f7d92386639a052c620d1550376f22f5b46981af
  \_ sha256:aee8b479b9a768a64f4c32d69108566fbdbb71c8e541496dd1fa9f7ad19d8632
    \_ sha256:e6b3eda8746c5cc312ebb40e1ca5c064638af429b9b3848280aab8ed882bd10b
      \_ sha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016
        \_ sha256:f69435472d99c717999e1e458828567320e5f5375365c9551c2d13b489f30a22
          \_ sha256:3c7bfc410c0e316ba2b72a18e1ec45263b81921eafbec05d87cfb6dfd2a31f85
            \_ redis1
ubuntu@v-Ubuntu:~$ 

タスクを削除する

ctr task deleteでタスクを終了させることができます。

ubuntu@v-Ubuntu:~$ sudo ctr task ls
TASK      PID      STATUS    
redis1    16722    RUNNING
ubuntu@v-Ubuntu:~$ sudo ctr task delete redis1
ctr: task must be stopped before deletion: running: failed precondition
ubuntu@v-Ubuntu:~$ 

タスクを削除する前にタスクを停止しろって言ってるので、一回停止してから削除をやりましょう。ctr killでコンテナにSIGTERMのシグナルを送って停止させます。

ubuntu@v-Ubuntu:~$ sudo ctr task kill redis1
ubuntu@v-Ubuntu:~$ sudo ctr task ls
TASK      PID      STATUS    
redis1    16722    STOPPED
ubuntu@v-Ubuntu:~$ sudo ctr task delete redis1
ubuntu@v-Ubuntu:~$ sudo ctr task ls
TASK    PID    STATUS    
ubuntu@v-Ubuntu:~$ 

コンテナを削除する

タスクを削除してもコンテナは残り続けます。

ubuntu@v-Ubuntu:~$ sudo ctr container ls
CONTAINER    IMAGE                             RUNTIME                           
redis1       docker.io/library/redis:latest    io.containerd.runtime.v1.linux    
ubuntu@v-Ubuntu:~$ 

ctr container rmでコンテナを削除しましょう。

ubuntu@v-Ubuntu:~$ sudo ctr container rm redis1
ubuntu@v-Ubuntu:~$ sudo ctr container ls
CONTAINER    IMAGE    RUNTIME    
ubuntu@v-Ubuntu:~$

これを実行するとついでにwritableなスナップショットも削除されます。

ubuntu@v-Ubuntu:~$ sudo ctr snapshot ls
KEY                                                                     PARENT                                                                  KIND      
sha256:3c7bfc410c0e316ba2b72a18e1ec45263b81921eafbec05d87cfb6dfd2a31f85 sha256:f69435472d99c717999e1e458828567320e5f5375365c9551c2d13b489f30a22 Committed 
sha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016 sha256:e6b3eda8746c5cc312ebb40e1ca5c064638af429b9b3848280aab8ed882bd10b Committed 
sha256:aee8b479b9a768a64f4c32d69108566fbdbb71c8e541496dd1fa9f7ad19d8632 sha256:cdb3f9544e4c61d45da1ea44f7d92386639a052c620d1550376f22f5b46981af Committed 
sha256:cdb3f9544e4c61d45da1ea44f7d92386639a052c620d1550376f22f5b46981af                                                                         Committed 
sha256:e6b3eda8746c5cc312ebb40e1ca5c064638af429b9b3848280aab8ed882bd10b sha256:aee8b479b9a768a64f4c32d69108566fbdbb71c8e541496dd1fa9f7ad19d8632 Committed 
sha256:f69435472d99c717999e1e458828567320e5f5375365c9551c2d13b489f30a22 sha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016 Committed 
ubuntu@v-Ubuntu:~$ 

ここで注意なんですが、コンテナより先にスナップショットを削除しないようにしましょう。スナップショットを削除してからコンテナを削除しようとすると以下のようなエラーが発生します。

ubuntu@v-Ubuntu:~$ sudo ctr snapshot rm redis1
ubuntu@v-Ubuntu:~$ sudo ctr container ls
CONTAINER    IMAGE                             RUNTIME                           
redis1       docker.io/library/redis:latest    io.containerd.runtime.v1.linux    
ubuntu@v-Ubuntu:~$ sudo ctr container rm redis1
ERRO[0000] failed to delete container "redis1"           error="snapshot redis1 does not exist: not found"
ctr: snapshot redis1 does not exist: not found
ubuntu@v-Ubuntu:~$ 

「redis1のスナップショットがねーよ」って言ってますね。

こういう時の対処法としてはctr snapshot viewで同名のスナップショットを作ってやるって方法があります。

ubuntu@v-Ubuntu:~$ sudo ctr snapshot view --help
NAME:
   ctr snapshots view - create a read-only snapshot from a committed snapshot

USAGE:
   ctr snapshots view [command options] [flags] <key> [<parent>]

OPTIONS:
   --target value, -t value  mount target path, will print mount, if provided
   
ubuntu@v-Ubuntu:~$

parentは適当に指定してスナップショットredis1を作成します。

ubuntu@v-Ubuntu:~$ sudo ctr snapshot view redis1 sha256:3c7bfc410c0e316ba2b72a18e1ec45263b81921eafbec05d87cfb6dfd2a31f85
ubuntu@v-Ubuntu:~$ sudo ctr snapshot ls
KEY                                                                     PARENT                                                                  KIND      
redis1                                                                  sha256:3c7bfc410c0e316ba2b72a18e1ec45263b81921eafbec05d87cfb6dfd2a31f85 View      
sha256:3c7bfc410c0e316ba2b72a18e1ec45263b81921eafbec05d87cfb6dfd2a31f85 sha256:f69435472d99c717999e1e458828567320e5f5375365c9551c2d13b489f30a22 Committed 
sha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016 sha256:e6b3eda8746c5cc312ebb40e1ca5c064638af429b9b3848280aab8ed882bd10b Committed 
sha256:aee8b479b9a768a64f4c32d69108566fbdbb71c8e541496dd1fa9f7ad19d8632 sha256:cdb3f9544e4c61d45da1ea44f7d92386639a052c620d1550376f22f5b46981af Committed 
sha256:cdb3f9544e4c61d45da1ea44f7d92386639a052c620d1550376f22f5b46981af                                                                         Committed 
sha256:e6b3eda8746c5cc312ebb40e1ca5c064638af429b9b3848280aab8ed882bd10b sha256:aee8b479b9a768a64f4c32d69108566fbdbb71c8e541496dd1fa9f7ad19d8632 Committed 
sha256:f69435472d99c717999e1e458828567320e5f5375365c9551c2d13b489f30a22 sha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016 Committed 
ubuntu@v-Ubuntu:~$ sudo ctr container rm redis1
ubuntu@v-Ubuntu:~$ sudo ctr container ls
CONTAINER    IMAGE    RUNTIME    
ubuntu@v-Ubuntu:~$ 

すると見事に削除できるようになりました。

イメージを削除する

ctr image rmでイメージを削除できます。

ubuntu@v-Ubuntu:~$ sudo ctr image rm docker.io/library/redis:latest
docker.io/library/redis:latest
ubuntu@v-Ubuntu:~$ sudo ctr image ls 
REF TYPE DIGEST SIZE PLATFORMS LABELS 
ubuntu@v-Ubuntu:~$ 

スナップショットも綺麗さっぱりなくなります。

ubuntu@v-Ubuntu:~$ sudo ctr snapshot ls
KEY PARENT KIND 
ubuntu@v-Ubuntu:~$ 

まとめ

ctrを使ってcontainerdに対して基本的な操作を行いました。今の世の中コンテナランタイムは色々種類がありますし、色々触って使い心地(笑)を比較してみるのもいいかもしれませんね。

ちなみにちなみに、containerdのバージョン1.1にはcriのプラグインが備わっており、CRI v1alpha2に対応しています。というわけでctr以外にcrictlのようなCLIツールで操作を行うことが可能になっています。

今度はcrictlで操作してみたさがありますね。また、CNIの設定もちゃんとやりたいです。

おまけ

ボツネタにしようと思ったけどやっぱ記事に残しておくことにした内容

スナップショットを削除する

再度redisのイメージをプル

ubuntu@v-Ubuntu:~$ sudo ctr image pull docker.io/library/redis:latest
ubuntu@v-Ubuntu:~$ sudo ctr snapshot tree
 sha256:cdb3f9544e4c61d45da1ea44f7d92386639a052c620d1550376f22f5b46981af
  \_ sha256:aee8b479b9a768a64f4c32d69108566fbdbb71c8e541496dd1fa9f7ad19d8632
    \_ sha256:e6b3eda8746c5cc312ebb40e1ca5c064638af429b9b3848280aab8ed882bd10b
      \_ sha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016
        \_ sha256:f69435472d99c717999e1e458828567320e5f5375365c9551c2d13b489f30a22
          \_ sha256:3c7bfc410c0e316ba2b72a18e1ec45263b81921eafbec05d87cfb6dfd2a31f85
ubuntu@v-Ubuntu:~$

特に深い意味はないんですけどスナップショットsha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016の削除を試みます。スナップショットの削除はctr snapshot rmコマンド。

ubuntu@v-Ubuntu:~$ sudo ctr snapshot rm sha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016
ctr: failed to remove "sha256:7460940a3a5274245b091035dbbb1b724e5bd2d2135326d61f542de962f3a016": cannot remove snapshot with child: failed precondition
ubuntu@v-Ubuntu:~$ 

子のスナップショットがいるときは削除できないようになっているようです。賢い。

じゃあ子がいないスナップショットを削除してみましょうか

ubuntu@v-Ubuntu:~$ sudo ctr snapshot rm sha256:3c7bfc410c0e316ba2b72a18e1ec45263b81921eafbec05d87cfb6dfd2a31f85
ubuntu@v-Ubuntu:~$ sudo ctr snapshot ls
KEY PARENT KIND 
ubuntu@v-Ubuntu:~$ sudo ctr image ls -q
docker.io/library/redis:latest
ubuntu@v-Ubuntu:~$ 

スナップショット全部消えるんですね・・・でもイメージは残ってるのか・・・

これでctr image rmiを実行したら何が起こるか気になりました(なんとなくctr container rmの時のエラーみたいに「スナップショット○○が存在しない」ってメッセージが出ると思いました)

ubuntu@v-Ubuntu:~$ sudo ctr image rm docker.io/library/redis:latest
docker.io/library/redis:latest
ubuntu@v-Ubuntu:~$ sudo ctr image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS 
ubuntu@v-Ubuntu:~$ 

普通に削除できちゃった。

コンテナのポートバインディング

タスクのポートバインディングって言った方がいいのかな?containerdではDockerのdcoker0みたいな仮想のブリッジネットワークは備わってないみたいです。ただホストネットワークは使用できます。そんなわけでコンテナの80番ポートをホストの80番ポートにバインドするなんてことができます。

それでは再度redisのイメージをプルしてコンテナを起動してしましょう。オプション--net-hostをつけてctr runを実行します。

ubuntu@v-Ubuntu:~$ sudo ctr image pull docker.io/library/redis:latest
ubuntu@v-Ubuntu:~$ sudo ctr run -d --net-host docker.io/library/redis:latest redis1
ubuntu@v-Ubuntu:~$ ss -atn | grep 6379
LISTEN     0      128          *:6379                     *:*                  
LISTEN     0      128         :::6379                    :::*                  
ubuntu@v-Ubuntu:~$ 

ホストの6379番ポートが空いています。このポートで何のプロセスが動いているかを調べてみると、redisのプロセスが動いていることがわかりました。

ubuntu@v-Ubuntu:~$ sudo lsof -i:6379
lsof: no pwd entry for UID 999
lsof: no pwd entry for UID 999
COMMAND     PID     USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
lsof: no pwd entry for UID 999
redis-ser 18748      999    6u  IPv6 3558672      0t0  TCP *:6379 (LISTEN)
lsof: no pwd entry for UID 999
redis-ser 18748      999    7u  IPv4 3558673      0t0  TCP *:6379 (LISTEN)
ubuntu@v-Ubuntu:~$ 

というわけでポートバインディングは成功です。