adtech studio

[Kubnernetes] kubelet の runtime を docker から cri-o に置き換える

By makocchi

Container Docker Kubernetes Linux 検証

みなさんこんにちは。

アドテク本部の makocchi です。

 

kubernetes で使われている container の runtime にはみなさん何をお使いでしょうか?

ほぼ全ての人が docker と答えると思います。実際 Google Kubernetes Engine(GKE) も runtime には docker が使われています。(2018年01月現在)

しかし kubernetes はこの container の runtime を自由に選択することができます。

kubernetes と container runtime の間は CRI(Container Runtime Interface) を通して行われます。

つまり CRI に対応している runtime であれば何でも良いということになります。

CRI に対応している代表的な runtime には dockercri-orktcri-containerd があります。今後は様々な runtime が増えてくるかもしれないですね。

 

cri-o について

cri-o は Kubernetes Incubator Project として開発されています。

CRI に対応しているのはもちろんですが、もう一つの標準規格である OCI(Open Container Initiative) にも準拠しています。

docker の image は既に OCI に準拠していますので、docker build した image を cri-o も使用することができます。

※ http://cri-o.io/ より抜粋

 

それではさっそく kubernetes の runtime として cri-o を使用してみましょう。

kubernetes 1.8 から cri-o が stable になりましたので、1.8 以上の cluster を用意します。

今回は 1.9 の kubernetes Cluster(Ubuntu) を用意しました。(kubernetes の環境の構築の手順はここでは省略します)

 

現状の runtime を確認しておきます。

 

kubelet と dockerd は落としておきます。

 

runc, crio の install

 

runc の install

現時点(2018年1月)での最新である v1.0.0-rc4 を使います。

 

crio の install

cri-o は binary の filename が crio となるようです(ややこしい)

crio の binary は用意されていないので自分で作る必要があります。

tutorial によると go 1.8.5 が指定されていますので、なるべく 1.8.5 で作るのがいいでしょう。

go の環境が整ったらまずは crictl を build します。

その次に crio を build します。

続いて install します。

続いて config を配置します。

crio の config は /etc/crio/crio.conf のようですね。

default ではこのような内容です。

[crio.image] の registries のところは default では空になっています。

多くの場合は docker hub から image を取ってくると思うので、registries に docker.io を書いておくのがいいでしょう。

もしくは crio の起動時に –registry で渡してあげてもいいと思います(書かなくても image は取ってこれます)

 

crio の起動 (systemd)

 

今回は crio を systemd 経由で起動させます。

crio の引数は自由に設定してください。ここでは loglevel を debug にしています。

 

crio の動作確認

 

動作を確認してみましょう

version の確認

 

下記のようにエラーが出る場合は crio が正常に起動していないと思われます。

journalctl -u crio 等で log を確認しましょう。

image の操作

crictl で image を pull してみます。

その前に /etc/containers/policy.json という file が無いと怒られるので sample を github から持ってきます。

 

crictl pull で image を local に持ってくることが可能です。

crictl images で現在 local にある image 一覧を表示できます。

 

先程落としてきた policy.json ですが、policy の中に

という部分があります。

これは hello-world の image pull は拒否するということで、実際に pull しようとするとちゃんと reject されます。

細かく policy を設定することも出来るようですね。

 

cri-o の storage_driver 変更(devicemapper から overlay2 へ)

image は crio.conf 内に定義されている root のディレクトリ配下に置かれます。

 

/var/lib/containers/storage のディレクトリ構成を見てみます。

先程 pull してきた nginx:alpine(bb00c21b4edf4) の image 定義は ${root}/devicemapper-images 配下に置かれています。

どうやら storage_driver には devicemapper 使われているようですね。

 

それではさっそく overlay2 に変えてみましょう。

crio.conf を編集して storage_driver に overlay2 を設定し、crio を再起動させます。

 

今度は redis の image を pull してみます。

今度は ${root}/overlay2 が作成されていると思います。

 

 

cri-o で pod を起動させ、container を動かす

cri-o ではまず pod を起動させ、その中で container を動かすという手順になるようです。

pod を起動させる為に pod の設定が書かれた json or yaml を渡してあげる必要があります。

 

まずは sandbox の pod を起動させてみましょう。

cri-o の github repo 内の test/testdata 内に sample が置かれているので、そこから pod を起動させます。

pod の起動には crictl runp を使用します。crictl pods で表示させることができます。

podsandbox1 の pod が起動しました。

inspectp をすることでより詳細な情報を見ることができます。

この pod には 10.112.76.6 の ip が振られました。

 

次に podsandbox1 の pod 内で redis の container を起動させてみます。

container を起動する時にも定義ファイルを渡してあげる必要があります。

今回は用意されている testdata 内の container_redis.json を使います。

crictl create が無事に終わったら crictl start させます。

STATE が CONTAINER_CREATED から CONTAINER_RUNNING になりました。

 

それではこの redis に接続してみましょう。

先程 inspectp した際に出てきた podsandbox1 の ip(10.112.76.6) に対して接続してみます。

無事に動作の確認ができました!

 

動作確認が終わったので、pod と container は消しておきます。

container を消す際には rm を、pod を消す際には rmp を使用します。

 

kubelet の設定を変更して runtime に cri-o を指定する

 

kubelet の設定

それではいよいよ kubelet の設定を docker から cri-o に変更してみます。

kubelet に下記の option を設定して起動させます。

–runtime-request-timeout は必要に応じて設定してください。

そして先程と同じように get node で表示させてみます。

無事に変更されました!

 

 

実際に pod を kubernetes 経由で起動させる

次に実際に pod を kubectl で作成してみます。

cri-o で動いている node に label を付け、nodeSelector で指定して作成します。

manifest はこんな感じです。

kubernetes 上から問題なく pod が作成されました。

cri-o 上では f48039701e4c6 で動いていることがわかりましたので、node 側で確認してみます。

無事に起動していますね。

 

まとめ

このように docker から cri-o への runtime 変更することができるのですが、現状の docker で特に苦労していなければ無理に置き換える必要は無いと思っています。

それでも敢えて docker を置き換える理由として考えられるのは個人的には以下のようなものがあるのではと思っています。

  • docker よりも軽量でスリムな crio を使用することで node 側の負担を少しでも軽減させる (手元の環境では dockerd よりも crio のほうが cpu/memory 使用量が小さかった)
  • dockerd よりも安定しそう  これは根拠が無いので憶測に過ぎないのですが、いろいろな機能が実装されている太った dockerd よりもスリムな crio の方が安定性があるのではないかと思っています

今はまだ導入するのに若干手順が多いですが、その内 rpm や deb の package が作られれば導入は楽になるでしょう。

crictl の option は docker の option に非常によく似ている為、docker に慣れていれば問題なく使うことができそうです。

 

それではよい Kubernetes life を!