コンテナランタイムKata Containersの実行検証

## はじめに
2018/5/23にリリースされたばかりの新しいコンテナランタイムである
[Kata Containers](https://katacontainers.io/)を触ってみました。

## コンテナランタイムとは
一般的にいうところのコンテナの事を指しています。
現在のコンテナとしての標準はDocker(containerd)と言われています。

まあ、コンテナ自体はnamespacesとcgroupsの2つを組み合わせただけのものなので
自分で調べてそれぞれのコマンドを打てばそれだけでもコンテナは作れてしまうのでランタイムは不要です。

でもコンテナのリソースだとかネットワーク周りを制御したりといったコンテナ間連携とか
イメージ共有とかそういった事を自前でやるのはちょー面倒なのでコンテナランタイムを使うと便利で簡単なのです。


コンテナオーケストレーションとして事実上の標準となったK8Sはコンテナランタイムを固定化しない仕組みになっているので、Dockerに限らず好きなランタイムを選ぶ事ができるようになっています。

こんな感じでコンテナランタイムを柔軟に選択できる基盤ができてきたので
用途や特徴を持たせたコンテナランタイムの差別化/多様化という流れが出来てきたのかもしれません。

High-LevelのコンテナランタイムとLow-Levelのコンテナランタイムがあります。
その辺は別の記事に書きます。

## Kata Containersとは
OpenStack Foundationにより開発されたLow-Levelのコンテナランタイム。
(High-Levelも対応しているのかも。。。場合によっては修正)

最も大きな特徴としては<span style="color: #ef0606">VMのような隔離性を保ちつつコンテナの軽量さも併せ持つ</span>という点ですね。
VMとコンテナの良いとこどりですね。

コンテナ間でホスト側のカーネルを共有しないので更に隔離性を高め、セキュリティも向上しているとの事です。
セキュリティ向上がこのコンテナの主目的だそうです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146026/2fe6dc36-682f-c862-9555-d7c91fb3f83d.png)

最近はこのようにコンテナのようにVMを動かす(あるいはVMのようにコンテナを動かす)ランタイムが増えてきているようです。
技術的にどのように実現しているのかは気になります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146026/1eb8aba9-4b3e-0225-b0e7-7c07407f2b7c.png)

## インストール
[KataContainersのGitHubリポジトリがあるので参照](https://github.com/kata-containers/documentation/blob/master/install/README.md)

今回はAWSでUbuntuイメージを使います。

| AMI-ID | OS Version |
| --- | --- |
| ami-940cdceb | Ubuntu 16.04.4 LTS |

#### kata インストール

```
$ sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/katacontainers:/release/xUbuntu_$(lsb_release -rs)/ /' > /etc/apt/sources.list.d/kata-containers.list"
$ curl -sL  http://download.opensuse.org/repositories/home:/katacontainers:/release/xUbuntu_$(lsb_release -rs)/Release.key | sudo apt-key add -
$ sudo -E apt-get update
$ sudo -E apt-get -y install kata-runtime kata-proxy kata-shim
```

#### インストール確認

```
$ dpkg -l | grep kata
ii  kata-containers-image            1.1.0-30                                   amd64        Kata containers image
ii  kata-ksm-throttler               1.1.0.git+1fecaff-30                       amd64
ii  kata-linux-container             4.14.51.1-132                              amd64        linux kernel optimised for container-like workloads.
ii  kata-proxy                       1.1.0+git.8a305e5-30                       amd64
ii  kata-runtime                     1.1.0+git.bf1cf68-43                       amd64
```

#### Docker インストール

```
$ sudo -E apt-get -y install apt-transport-https ca-certificates software-properties-common
$ curl -sL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ arch=$(dpkg --print-architecture)
$ sudo -E add-apt-repository "deb [arch=${arch}] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
$ sudo -E apt-get update
$ sudo -E apt-get -y install docker-ce
```

#### インストール確認

```
$ dpkg -l | grep docker
ii  docker-ce                        18.06.0~ce~3-0~ubuntu                      amd64        Docker: the open-source application container engine
```

### kata 起動設定
kataはHigh/Low-Level両方に対応しているっぽいコンテナランタイムなので今回はDocker(containerd)から呼び出す形にします。

Dockerは標準でrunCを実行する設定になっています。

```
# docker info | grep run
Runtimes: runc
Default Runtime: runc
runc version: 69663f0bd4b60df09991c08812a60108003fa340
```


そこをkataに変更します。
次の2パターンのいずれかの手順でkata Containersを使うようになります。

#### 1.systemd
```
$ sudo mkdir -p /etc/systemd/system/docker.service.d/
$ cat <<EOF | sudo tee /etc/systemd/system/docker.service.d/kata-containers.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -D --add-runtime kata-runtime=/usr/bin/kata-runtime --default-runtime=kata-runtime
EOF
```

#### 2.Docker daemon.json
```/etc/docker/daemon.json
{
  "default-runtime": "kata-runtime",
  "runtimes": {
    "kata-runtime": {
      "path": "/usr/bin/kata-runtime"
    }
  }
}
```

#### Docker 再起動
```
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
```

dockerのランタイム設定を見ると、kataコンテナが追加されています。

```
# docker info | grep time
Runtimes: kata-runtime runc
Default Runtime: kata-runtime
WARNING: No swap limit support
```


ステータスを見て正常に起動している事を確認します。

```
$ sudo systemctl status docker
sudo: unable to resolve host ip-10-0-0-129
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2018-08-05 14:55:04 UTC; 36s ago
     Docs: https://docs.docker.com
 Main PID: 4857 (dockerd)
    Tasks: 21
   Memory: 48.5M
      CPU: 348ms
   CGroup: /system.slice/docker.service
           tq4857 /usr/bin/dockerd -H fd://
           mq4866 docker-containerd --config /var/run/docker/containerd/containerd.toml

Aug 05 14:55:04 ip-10-0-0-129 dockerd[4857]: time="2018-08-05T14:55:04.007448919Z" level=info msg="ClientConn switching balancer to \"pick_first\"" module=grpc
Aug 05 14:55:04 ip-10-0-0-129 dockerd[4857]: time="2018-08-05T14:55:04.007476048Z" level=info msg="pickfirstBalancer: HandleSubConnStateChange: 0xc4201c7180, CONNECT
Aug 05 14:55:04 ip-10-0-0-129 dockerd[4857]: time="2018-08-05T14:55:04.007607286Z" level=info msg="pickfirstBalancer: HandleSubConnStateChange: 0xc4201c7180, READY"
Aug 05 14:55:04 ip-10-0-0-129 dockerd[4857]: time="2018-08-05T14:55:04.007622239Z" level=info msg="Loading containers: start."
Aug 05 14:55:04 ip-10-0-0-129 dockerd[4857]: time="2018-08-05T14:55:04.078415794Z" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0
Aug 05 14:55:04 ip-10-0-0-129 dockerd[4857]: time="2018-08-05T14:55:04.102016256Z" level=info msg="Loading containers: done."
Aug 05 14:55:04 ip-10-0-0-129 dockerd[4857]: time="2018-08-05T14:55:04.124815789Z" level=info msg="Docker daemon" commit=0ffa825 graphdriver(s)=overlay2 version=18.0
Aug 05 14:55:04 ip-10-0-0-129 dockerd[4857]: time="2018-08-05T14:55:04.124876494Z" level=info msg="Daemon has completed initialization"
Aug 05 14:55:04 ip-10-0-0-129 dockerd[4857]: time="2018-08-05T14:55:04.135153636Z" level=info msg="API listen on /var/run/docker.sock"
Aug 05 14:55:04 ip-10-0-0-129 systemd[1]: Started Docker Application Container Engine.
```

### 起動エラー
しかしコンテナを起動しようとしてもエラーになってしまいます。

```
docker: Error response from daemon: OCI runtime create failed: Could not access KVM kernel module: No such file or directory
qemu-lite-system-x86_64: failed to initialize KVM: No such file or directory: unknown.
ERRO[0004] error waiting for container: context canceled
```

色々調べたところ、Hardware requirementsを満たしていない気がする。

```
$ kata-runtime kata-check
INFO[0000] CPU property found                            description="Intel Architecture CPU" name=GenuineIntel pid=1888 source=runtime type=attribute
ERRO[0000] CPU property not found                        description="Virtualization support" name=vmx pid=1888 source=runtime type=flag
INFO[0000] CPU property found                            description="64Bit CPU" name=lm pid=1888 source=runtime type=flag
INFO[0000] CPU property found                            description=SSE4.1 name=sse4_1 pid=1888 source=runtime type=flag
INFO[0000] kernel property found                         description="Intel KVM" name=kvm_intel pid=1888 source=runtime type=module
ERRO[0000] open /sys/module/kvm_intel/parameters/nested: no such file or directory  name=kata-runtime pid=1888 source=runtime
open /sys/module/kvm_intel/parameters/nested: no such file or directory
```

CPUの仮想化支援機能が有効になってないっぽいのと
VMなのでKVMのネスト設定とかを有効にしないといけないっぽい、のかな。
よく考えたらKataはKVMを使うらしいからXen on KVMもしくはKVM on KVMになるからちょっと色々イジらないとダメかな。

ベアメタルインスタンスとかで試したらうまく動くかな。
他のやり方も試す予定。

## AWSベアメタルインスタンス(i3.metal)で検証
VMのデフォルトだとうまく動かなかったのでAWSのベアメタルインスタンスで再検証。

| インスタンスタイプ | AMI-ID| OS Version |
| --- | --- | --- |
| i3.metal | ami-759bc50a | Ubuntu 16.04.4 LTS |

導入手順は済ませて、ハードウェア要件をチェック。

```
$ kata-runtime kata-check
INFO[0000] CPU property found                            description="Intel Architecture CPU" name=GenuineIntel pid=4807 source=runtime type=attribute
INFO[0000] CPU property found                            description="64Bit CPU" name=lm pid=4807 source=runtime type=flag
INFO[0000] CPU property found                            description=SSE4.1 name=sse4_1 pid=4807 source=runtime type=flag
INFO[0000] CPU property found                            description="Virtualization support" name=vmx pid=4807 source=runtime type=flag
INFO[0000] kernel property found                         description="Host kernel accelerator for virtio" name=vhost pid=4807 source=runtime type=module
INFO[0000] kernel property found                         description="Host kernel accelerator for virtio network" name=vhost_net pid=4807 source=runtime type=module
INFO[0000] kernel property found                         description="Intel KVM" name=kvm_intel pid=4807 source=runtime type=module
WARN[0000] kernel module parameter has unexpected value  description="Intel KVM" expected=Y name=kvm_intel parameter=nested pid=4807 source=runtime type=module value=N
INFO[0000] Kernel property value correct                 description="Intel KVM" expected=Y name=kvm_intel parameter=unrestricted_guest pid=4807 source=runtime type=module value=Y
INFO[0000] kernel property found                         description="Kernel-based Virtual Machine" name=kvm pid=4807 source=runtime type=module
INFO[0000] System is capable of running Kata Containers  name=kata-runtime pid=4807 source=runtime
```
おお、ERRORがなくなった。
WARNはあるけどなんかうまくいきそう。

テキトーにnginxとかでコンテナ起動。

```
root      7128  0.5  0.0 2455128 91772 ?       Ssl  11:46   0:08 /usr/bin/dockerd -H fd://
root      7142  0.4  0.0 1749336 46900 ?       Ssl  11:46   0:07  \_ docker-containerd --config /var/run/docker/containerd/containerd.toml
root      8175  0.0  0.0   8556  5112 ?        Sl   11:48   0:00  |   \_ docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd
root      8228  0.0  0.0 3196760 229468 ?      Sl   11:48   0:01  |       \_ /usr/bin/qemu-lite-system-x86_64 -name sandbox-0973daf5b7b4a66a7f3529e829b70284a5c7aca31628
root      8241  0.0  0.0 432804  7688 ?        Sl   11:48   0:00  |       \_ /usr//libexec/kata-containers/kata-proxy -listen-socket unix:///run/vc/sbs/0973daf5b7b4a66a
root      8260  0.0  0.0 301092 13680 ?        Sl   11:48   0:00  |       \_ /usr/libexec/kata-containers/kata-shim -agent 
```
プロセスで見てもkataの文字列が見えます。
ちゃんとkata使ってそう。

```
$ sudo kata-runtime list
ID                                                                 PID         STATUS      BUNDLE                                                                                                                               CREATED                          OWNER
0973daf5b7b4a66a7f3529e829b70284a5c7aca31628d132f4590c0e58644257   8260        running     /run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/0973daf5b7b4a66a7f3529e829b70284a5c7aca31628d132f4590c0e58644257   2018-08-06T11:48:23.986799523Z   #0
```
kata-runtimeコマンドでもコンテナを認識しているので問題なく動いていそう。

## GCPで環境を作ってみる

#### imageを作る

```
$ SOURCE_IMAGE_PROJECT=ubuntu-os-cloud
$ SOURCE_IMAGE_FAMILY=ubuntu-1804-lts
$ IMAGE_NAME=${SOURCE_IMAGE_FAMILY}-nested

$ gcloud compute images create \
    --source-image-project $SOURCE_IMAGE_PROJECT \
    --source-image-family $SOURCE_IMAGE_FAMILY \
    --licenses=https://www.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx \
    $IMAGE_NAME
```

ここの設定でNested Virtualizationを有効にしている。
つまり、VM上でVMを実行するオプションを有効にしている。

Kata ConteinerはHypervisorの機能が必須なため、有効にするひつようがある。

#### 用意したイメージをベースにGCEを構築

```
$ gcloud compute instances create \
    --image $IMAGE_NAME \
    --machine-type n1-standard-2 \
    --min-cpu-platform "Intel Broadwell" \
    --zone asia-northeast1-a \
    kata-testing
```

## 参考
https://qiita.com/mamomamo/items/ed5db2ab1555078f8a24