kubernetes
container
cri-o

kubernetes用コンテナランタイムcri-oを試す

http://cri-o.io/

https://github.com/kubernetes-incubator/cri-o

cri-oとは、kubernetes専用のコンテナランタイムとして主にRed Hatが開発を進めているツールです。
kubernetes(kubelet)cri-oを操作し、cri-oがコンテナランタイムを操作するという、kubeletとコンテナランタイムの橋渡し的な位置付けになっています。

開発の背景

kubernetesは、コンテナを操作するインターフェースとしてCRIと呼ばれる仕様を策定しており、kubeletはこのインターフェースを使ってコンテナを操作することになっています。
CRIに準拠したツールであれば、どんなコンテナランタイムでもkubernetesと結合して使えるというわけです。

現在、kubernetesを使っている人は大抵コンテナランタイムとしてdockerを利用されているかと思いますが、これもkubelet組み込みのCRI-dockerアダプタで操作されています。
kubernetesはdockerだけでなくrktも利用できますが、こちらは https://github.com/kubernetes/kubernetes/tree/release-1.8/pkg/kubelet/rktshim というアダプタがありました。

ただ、dockerやrktなど、ランタイムごとにアダプタを用意するとなるとめんどくさいので、OCIという標準に準拠したランタイムであれば何でも使える汎用的なアダプタが欲しいということで開発されているのが、この cri-oです。
また、開発の背景には、dockerの開発速度が早い中、それに依存するkubernetesが不安定になっており、より小さく単純な、専用のランタイムを用意することでkubernetesの安定化に繋げたいという意図があったようです。

READMEによると、cri-oのスコープは以下となっています。

  • 既存のDockerイメージを含む、複数のイメージフォーマットをサポート
  • イメージの検証を含む複数のイメージダウンロード方法をサポート
  • コンテナイメージの管理(イメージレイヤー、オーバーレイファイルシステムその他)
  • コンテナプロセスのライフサイクルを管理
  • CRIに準拠するために必要なモニタリングとロギング
  • CRIに準拠するために必要なリソースの隔離

そして、以下はスコープ外とされているリストです。

  • イメージをビルドしたり署名したり、さまざまなレジストリにpushしたりする機能
  • cri-oと直接やり取りするcliツール群。このプロジェクトでビルドされるツール群はcri-oをテストするために作られているもので、後方互換性は保証されていない。

さて、先日、そのcri-oがstableリリースされました。

https://medium.com/cri-o/cri-o-1-0-is-here-d06b97b92a98

今回は、そのcri-oに簡単に触れてみたいと思います。

cri-oでコンテナを動かしてみる

cri-oのチュートリアルがあるので、これを参考にcri-oだけでredisのコンテナを動かしてみます。

https://github.com/kubernetes-incubator/cri-o/blob/master/tutorial.md

また、プロジェクトを見てみるとDockerfileが用意されています。
試すだけであれば、このDockerfileを使用してdockerで実行してみるのが簡単そうです。

dockerイメージのビルド

cri-oプロジェクトをcloneし、以下でイメージをビルドします。
なお、以下はすべてMac上のDocker for Macで動かしています。

git clone https://github.com/kubernetes-incubator/cri-o.git
cd cri-o
docker build -t crio_dev:master

または、イメージをビルドするためのターゲットがMakefileに定義されているので、makeを使ってもビルドできます。

make crioimage

dockerイメージの実行

以下でコンテナを実行し、中に入ります。

docker run -it --rm --privileged crio_dev:master /bin/bash

cri-oのビルド

cri-oは、makeでビルド、インストールできます。

make install.tools
make
make install

また、cri-oは/etc/crio/crio.confに設定ファイルを配置します。以下コマンドで、設定ファイルをインストールできます。

make install.config

設定ファイルの修正

インストールしたままの crio.confだとDocker環境でうまく動かないので、以下のように修正します(vimが入ってないので、私はapt-getで入れてしまいました)。

15 # storage_driver = ""
16 storage_driver = "vfs"

...

46 # runtime = "/usr/local/bin/runc"
47 runtime = "/usr/bin/runc"

CNIの設定

チュートリアルにあるとおり、以下でCNIの設定を行います。

mkdir -p /etc/cni/net.d

sh -c 'cat >/etc/cni/net.d/10-mynet.conf <<-EOF
{
    "cniVersion": "0.2.0",
    "name": "mynet",
    "type": "bridge",
    "bridge": "cni0",
    "isGateway": true,
    "ipMasq": true,
    "ipam": {
        "type": "host-local",
        "subnet": "10.88.0.0/16",
        "routes": [
            { "dst": "0.0.0.0/0"  }
        ]
    }
}
EOF'

sh -c 'cat >/etc/cni/net.d/99-loopback.conf <<-EOF
{
    "cniVersion": "0.2.0",
    "type": "loopback"
}
EOF'

cri-oデーモンの実行

バックグラウンドでcri-oを起動します。

crio --log-level debug &

crioctl コマンドで、cri-oが起動していることを確認できます。

crioctl runtimeversion
# VersionResponse: Version: 0.1.0, RuntimeName: cri-o, RuntimeVersion: 1.8.0-dev, RuntimeApiVersion: v1alpha1

Pod sandboxの作成

Pod sandboxを作成します。
Podの概念はkubernetesに触れている方は馴染み深いと思います。Pod sandboxは複数のコンテナをまとめて格納できる隔離環境を示すCRIの用語です。(「Pod and container lifecycle management
」参照 http://blog.kubernetes.io/2016/12/container-runtime-interface-cri-in-kubernetes.html)

POD_ID=$(crioctl pod run --config test/testdata/sandbox_config.json)

以下で作成したsandboxの状態を確認できます。

crioctl pod status --id $POD_ID

Pod内でコンテナを起動する

上記で作成したPod sandbox内にコンテナを作成します。

# コンテナイメージのダウンロード
crioctl image pull redis:alpine

# イメージからコンテナをpod内に作成する
CONTAINER_ID=$(crioctl ctr create --pod $POD_ID --config test/testdata/container_redis.json)

作成できたら、以下コマンドでコンテナを立ち上げましょう。

crioctl ctr start --id $CONTAINER_ID

# コンテナの状態を確認
crioctl ctr status --id $CONTAINER_ID

これで、作成したPod内でRedisコンテナが起動しました。

コンテナの動作確認

telnetで起動したコンテナのredisにつないでみます。

crioctl pod status --id $POD_IDで確認できたPodのIPを指定して以下コマンドを実行します。

# telnetのインストール
apt-get install telnet

# podのipを指定して、redisコンテナに接続
telnet 10.88.0.2 6379

redisに繋いだら、redisのINFOやMONITORコマンドを実行してみましょう。

Trying 10.88.0.2...
Connected to 10.88.0.2.
Escape character is '^]'.

INFO
# Server
redis_version:4.0.2
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:7f502971648182f2
....


MONITOR
+OK

このように、pod内に起動したredisコンテナが動作していることを確認できました。

まとめ

この記事では、簡単にcri-oを紹介した上で、cri-oを使用してコンテナを起動するまでの動作を見てみました。

cri-oのようなシンプルなCRI実装でこのように動作を確認してみると、kubernetesがどのようにPodやコンテナを扱っているか内側をのぞいてみることができて大変面白いですね。