Firecracker + Kata を動かしてみるところまで

KataでFirecrackerをサポートしたようです。
[セキュアなコンテナランタイム「Kata Container」が、AWSのマイクロVM「Firecracker」をサポート](https://www.publickey1.jp/blog/19/kata_containerawsvmfirecracker.html)

たまたまKata ContainerもFirecrackerも触った事があるので
せっかくなんで動かしてみます。

qemuの代わりにFirecrackerでVMを起動するようにKataを設定する、という感じですね。


## やってみる
とりあえず[Kata ContainerのGithub](https://github.com/kata-containers)ページへ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146026/b5d1745a-1004-cf13-7168-38e508090f8f.png)

`More Users Guide`に`HOWTO: Kata Containers with Firecracker`が追加されていますね。

https://github.com/kata-containers/documentation/wiki/Initial-release-of-Kata-Containers-with-Firecracker-support

今回はDockerを使いますがドライバの関係でバージョンが18.06じゃないとダメみたいです。

```bash

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

```

Kataをダウンロードして展開。

```bash

$ wget https://github.com/kata-containers/runtime/releases/download/1.5.0/kata-static-1.5.0-x86_64.tar.xz

$ tar -xvf kata-static-1.5.0-x86_64.tar.xz -C /
```

deamon.jsonを作ってRuntime設定を追加。

```/etc/docker/daemon.json
{
  "runtimes": {
    "kata-fc": {
      "path": "/opt/kata/bin/kata-fc"
    },
   "kata-qemu": {
      "path": "/opt/kata/bin/kata-qemu"
    }
  },
  "storage-driver": "devicemapper"
}
```

リロード。

```bash

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
```

DockerのRuntime設定にkata-fcとkata-qemuが追加されています。
Qemuで動かしたい時はkata-qemuを使えばいいみたいです。

```bash

$ docker info | grep "Runtimes"
Runtimes: kata-fc kata-qemu runc
```

vsockモジュールをロードします。

```
$ modprobe vhost_vsock
```

実行前にkvmを使っているディスクリプタをチェック。
特になし。

```bash

$ sudo lsof | grep kvm
```

docker run時にrutimeでkata-fcを指定します。

```bash

$ sudo docker run --runtime=kata-fc -itd --name=oh-sweet-fc alpine sh
$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
e2723b5c68c0        alpine              "sh"                37 minutes ago      Up 37 minutes                           oh-sweet-fc
```

firecrackerが実行されているみたいです。

```bash

$ ps -ae | grep -E "kata|fire"
27134 ?        00:00:08 firecracker
27147 pts/0    00:00:00 kata-shim
```

ファイルディスクリプタを見てみるとFirecrackerが/dev/kvmへアクセスしていますねー

```bash

$ sudo lsof | grep kvm
firecrack 27134                  root  mem       REG               0,13                 10612 anon_inode:kvm-vcpu (stat: No such file or directory)
firecrack 27134                  root   12u      CHR             10,232        0t0        384 /dev/kvm
firecrack 27134                  root   13u  a_inode               0,13          0      10612 kvm-vm
firecrack 27134                  root   88u  a_inode               0,13          0      10612 kvm-vcpu
fc_vmm    27134 27135            root  mem       REG               0,13                 10612 anon_inode:kvm-vcpu (stat: No such file or directory)
fc_vmm    27134 27135            root   12u      CHR             10,232        0t0        384 /dev/kvm
fc_vmm    27134 27135            root   13u  a_inode               0,13          0      10612 kvm-vm
fc_vmm    27134 27135            root   88u  a_inode               0,13          0      10612 kvm-vcpu
fc_vcpu0  27134 27139            root  mem       REG               0,13                 10612 anon_inode:kvm-vcpu (stat: No such file or directory)
fc_vcpu0  27134 27139            root   12u      CHR             10,232        0t0        384 /dev/kvm
fc_vcpu0  27134 27139            root   13u  a_inode               0,13          0      10612 kvm-vm
fc_vcpu0  27134 27139            root   88u  a_inode               0,13          0      10612 kvm-vcpu
kvm-pit/2 27138                  root  cwd       DIR                8,1       4096          2 /
kvm-pit/2 27138                  root  rtd       DIR                8,1       4096          2 /
kvm-pit/2 27138                  root  txt   unknown                                          /proc/27138/exe
```

プロセスを眺めていたところ、`/opt/kata/bin/firecracker --api-sock ～firecracker.sock`というものを見つけ、なんかFirecrackerのエンドポイントっぽいように見える。

```bash

$ ps auxf
・
・
・
root     26244  0.1  0.9 1115404 76416 ?       Ssl  Feb19   2:34 /usr/bin/dockerd -H fd://
root     26268  0.3  0.4 1023028 35228 ?       Ssl  Feb19   4:19  \_ docker-containerd --config /var/run/docker/containerd/containerd.toml
root     27093  0.0  0.0   7500  4252 ?        Sl   Feb19   0:02      \_ docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/e2723b5c68c0af1c29f1f7f520db7267698daf63f0137fd4
root     27134  0.1  1.2 145956 92028 ?        Sl   Feb19   2:14          \_ /opt/kata/bin/firecracker --api-sock /run/vc/sbs/e2723b5c68c0af1c29f1f7f520db7267698daf63f0137fd44de54d1b3a01389e/firecracker.sock
root     27147  0.0  0.1 615524 14720 pts/0    Ssl+ Feb19   0:00          \_ /opt/kata/libexec/kata-containers/kata-shim -agent vsock://3472509929:1024 -container e2723b5c68c0af1c29f1f7f520db7267698daf63f0137fd44de54d1b3a01389e -exec-id e2
```

```bash
$ cd /run/vc/sbs/e2723b5c68c0af1c29f1f7f520db7267698daf63f0137fd44de54d1b3a01389e/
root@kata-testing:/run/vc/sbs/e2723b5c68c0af1c29f1f7f520db7267698daf63f0137fd44de54d1b3a01389e
$ ll firecracker.sock
srwxr-xr-x 1 root root 0 Feb 19 14:04 firecracker.sock=
```

```bash

$ sudo curl --unix-socket firecracker.sock -i http://localhost/
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 20 Feb 2019 12:39:36 GMT

{"id":"anonymous-instance","state":"Running"}root@kata-testing:/run/vc/sbs/e2723b5c68c0af1c29f1f7f520db7267698daf63f0137fd44de54d1b3a01389e
```

RESTでアクセスすると応答が返ってきました。
Kataからもここを経由して制御しているんでしょうかね。

```bash
sudo curl --unix-socket firecracker.sock -i http://localhost/machine-config
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 20 Feb 2019 12:43:15 GMT

{ "vcpu_count": 1, "mem_size_mib": 128,  "ht_enabled": false,  "cpu_template": "Uninitialized" }root@kata-testing:/run/vc/sbs/e2723b5c68c0af1c29f1f7f520db7267698daf63f0137fd44de54d1b3a01389e
```

ちなみに同じパスにいくつかjsonファイルが置かれていてこれが構成ファイルになっているようでした。

```bash

$ ll
total 20
drwxr-x--- 4 root root  220 Feb 19 14:04 ./
drwxr-x--- 3 root root   60 Feb 19 14:04 ../
-rw-r--r-- 1 root root   46 Feb 19 14:04 agent.json
-rw-r--r-- 1 root root  420 Feb 19 14:04 devices.json
drwxr-x--- 2 root root  120 Feb 19 14:04 e2723b5c68c0af1c29f1f7f520db7267698daf63f0137fd44de54d1b3a01389e/
srwxr-xr-x 1 root root    0 Feb 19 14:04 firecracker.sock=
-rw-r--r-- 1 root root   13 Feb 19 14:04 hypervisor.json
-rw-r--r-- 1 root root    0 Feb 19 14:04 lock
-rw-r--r-- 1 root root 1980 Feb 19 14:04 network.json
-rw-r--r-- 1 root root  104 Feb 19 14:04 state.json
drwxr-x--- 2 root root  200 Feb 19 14:04 tempDir/
```

```bash

$ cat hypervisor.json | jq
{
  "PID": 27134
}
```

```bash
$ cat state.json | jq
{
  "state": "running",
  "BlockDeviceID": "",
  "blockIndex": 1,
  "fstype": "",
  "pid": 27147,
  "guestMemoryBlockSize": 128
}
```

```bash

$ cat agent.json | jq
{
  "ProxyPid": 0,
  "URL": "vsock://3472509929:1024"
}
```

```bash

$ cat devices.json | jq
[
  {
    "Type": "block",
    "Data": {
      "ID": "d852841c08719cf6",
      "DeviceInfo": {
        "HostPath": "/dev/dm-1",
        "DevType": "b",
        "Major": 253,
        "Minor": 1,
        "FileMode": 0,
        "UID": 0,
        "GID": 0,
        "ID": "d852841c08719cf6",
        "DriverOptions": {
          "block-driver": "virtio-mmio"
        }
      },
      "RefCount": 1,
      "AttachCount": 1,
      "BlockDrive": {
        "File": "/dev/dm-1",
        "Format": "raw",
        "ID": "drive-d852841c08719cf6",
        "Index": 0,
        "MmioAddr": "",
        "PCIAddr": "",
        "SCSIAddr": "",
        "NvdimmID": "",
        "VirtPath": "/dev/vdb"
      }
    }
  }
]
```

```bash
$ cat network.json | jq
{
  "NetNsPath": "/var/run/netns/cni-c24982d5-d4fe-5e54-1e8f-318bf2aba489",
  "NetNsCreated": true,
  "Endpoints": [
    {
      "Type": "virtual",
      "Data": {
        "NetPair": {
          "ID": "970f73a7-b1bb-4ccc-8ac4-1c8446e2eb79",
          "Name": "br0_kata",
          "TAPIface": {
            "Name": "tap0_kata",
            "HardAddr": "02:42:ac:11:00:02",
            "Addrs": null
          },
          "VMFds": null,
          "VhostFds": [],
          "VirtIface": {
            "Name": "eth0",
            "HardAddr": "f6:46:86:dd:52:f0",
            "Addrs": null
          },
          "NetInterworkingModel": 4
        },
        "EndpointProperties": {
          "Iface": {
            "Index": 6,
            "MTU": 1500,
            "TxQLen": 0,
            "Name": "eth0",
            "HardwareAddr": "AkKsEQAC",
            "Flags": 19,
            "RawFlags": 69699,
            "ParentIndex": 7,
            "MasterIndex": 0,
            "Namespace": null,
            "Alias": "",
            "Statistics": {
              "RxPackets": 2,
              "TxPackets": 0,
              "RxBytes": 180,
              "TxBytes": 0,
              "RxErrors": 0,
              "TxErrors": 0,
              "RxDropped": 0,
              "TxDropped": 0,
              "Multicast": 0,
              "Collisions": 0,
              "RxLengthErrors": 0,
              "RxOverErrors": 0,
              "RxCrcErrors": 0,
              "RxFrameErrors": 0,
              "RxFifoErrors": 0,
              "RxMissedErrors": 0,
              "TxAbortedErrors": 0,
              "TxCarrierErrors": 0,
              "TxFifoErrors": 0,
              "TxHeartbeatErrors": 0,
              "TxWindowErrors": 0,
              "RxCompressed": 0,
              "TxCompressed": 0
            },
            "Promisc": 0,
            "Xdp": {
              "Fd": 0,
              "Attached": false,
              "Flags": 0,
              "ProgId": 0
            },
            "EncapType": "ether",
            "Protinfo": null,
            "OperState": 6,
            "NetNsID": 0,
            "NumTxQueues": 0,
            "NumRxQueues": 0,
            "Type": "veth"
          },
          "Addrs": [
            {
              "IP": "172.17.0.2",
              "Mask": "//8AAA==",
              "Label": "eth0",
              "Flags": 128,
              "Scope": 0,
              "Peer": {
                "IP": "172.17.0.2",
                "Mask": "//8AAA=="
              },
              "Broadcast": "172.17.255.255",
              "PreferedLft": 4294967295,
              "ValidLft": 4294967295
            }
          ],
          "Routes": [
            {
              "LinkIndex": 6,
              "ILinkIndex": 0,
              "Scope": 0,
              "Dst": null,
              "Src": "",
              "Gw": "172.17.0.1",
              "MultiPath": null,
              "Protocol": 3,
              "Priority": 0,
              "Table": 254,
              "Type": 1,
              "Tos": 0,
              "Flags": 0,
              "MPLSDst": null,
              "NewDst": null,
              "Encap": null,
              "MTU": 0,
              "AdvMSS": 0
            },
            {
              "LinkIndex": 6,
              "ILinkIndex": 0,
              "Scope": 253,
              "Dst": {
                "IP": "172.17.0.0",
                "Mask": "//8AAA=="
              },
              "Src": "172.17.0.2",
              "Gw": "",
              "MultiPath": null,
              "Protocol": 2,
              "Priority": 0,
              "Table": 254,
              "Type": 1,
              "Tos": 0,
              "Flags": 0,
              "MPLSDst": null,
              "NewDst": null,
              "Encap": null,
              "MTU": 0,
              "AdvMSS": 0
            }
          ],
          "DNS": {
            "Servers": null,
            "Domain": "",
            "Searches": null,
            "Options": null
          }
        },
        "Physical": false,
        "EndpointType": "virtual",
        "PCIAddr": ""
      }
    }
  ]
}
```



まあ、検証なり商用なりで使ってみないと違いや良し悪しはわかりませんな。