Moby/LinuxKit on さくらのクラウド

# Linuxkit/Mobyプロジェクトについて

[Linuxkit/Mobyプロジェクト](https://mobyproject.org/)は2017年4月のDockerConで発表されました。

内容については、既に様々な記事が出ていますね。

- [【参考訳】Mobyプロジェクトのご紹介(dockercon17での発表)](http://qiita.com/zembutsu/items/c8f33b5fbc3211f5be52)
- [Moby で LinuxKit を起動してみる](http://qiita.com/pottava/items/3e64cf0476d4cfa93169)

LinuxKit/Mobyプロジェクトについてはこれらの記事を読むのが良さそうです。

早速調べつつ触ってみました。

## mobyコマンド
  
mobyコマンドが具体的にどう動いているかは以下に詳しく書かれていました。
https://github.com/linuxkit/linuxkit/blob/master/docs/architecture.md

moby = イメージをビルドするためのツール

ですね。

## linuxkit?

linuxkitというプロジェクトには以下が含まれます。

- mobyコマンドでのビルドで利用する、各種コンテナの実装など
- linuxkitコマンド

ライブラリとしてのlinuxkitと、コマンドとしてのlinuxkitですね。
今回はlinuxkitコマンドは使わず、mobyコマンドのみを対象に触ってみました。

## 今回試すこと

mobyコマンドでISOイメージ(iso-bios)を出力し、それをさくらのクラウド上で起動させてみます。

>Note:
>今回は手動でさくらのクラウドへのアップロードなどを行いますが、
>そのうちlinuxkit(コマンド)で実施できるようにしたいです。
>(今の所linuxkitの実装がもう少し固まるまで様子見中)

# CD-ROMから起動するImmutableなサーバを作る

作業環境はmacOS(Sierra)でした。  
以外の環境の方は適宜読み替えてください。

## Mobyのインストール

まずは`moby`コマンドのインストールを行います。

#### go開発環境がある場合

```bash:go開発環境がある場合
go get -u github.com/docker/moby/src/cmd/moby
```

#### 自分でmakeする場合

GitHubからクローンしてmakeします。
makeするには以下が必要とのことです。

- GNU make
- GNU or BSD tar (not busybox tar)
- Docker

```bash:makeする場合
git clone https://github.com/linuxkit/linuxkit.git
cd linuxkit
make
```

binディレクトリ配下に`linuxkit`コマンドと`moby`コマンドが作成されているはずです。

## mobyコマンドでイメージを作成

mobyコマンドはyamlでの定義ファイルを読み込んで、ブータブルなイメージを出力してくれます。
examplesディレクトリにサンプルがありますのでまずはそこからビルドしてみます。

### サンプル: minimal

最小構成でイメージをビルドするためのサンプルが用意されています。

```yaml:examples/minimal.yml
kernel:
  image: "linuxkit/kernel:4.9.x"
  cmdline: "console=ttyS0 console=tty0 page_poison=1"
init:
  - linuxkit/init:f71c3b30ac1ba4ef16c160c89610fa4976f9752f
  - linuxkit/runc:b0fb122e10dbb7e4e45115177a61a3f8d68c19a9
  - linuxkit/containerd:60e2486a74c665ba4df57e561729aec20758daed
onboot:
  - name: dhcpcd
    image: "linuxkit/dhcpcd:48e249ebef6a521eed886b3bce032db69fbb4afa"
    binds:
     - /var:/var
     - /tmp/etc:/etc
    capabilities:
     - CAP_NET_ADMIN
     - CAP_NET_BIND_SERVICE
     - CAP_NET_RAW
    net: host
    command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
trust:
  image:
    - linuxkit/kernel
outputs:
  - format: kernel+initrd
```

yamlにどのようなものが記載できるのかは以下のドキュメントを参照すれば良さそうです。
https://github.com/linuxkit/linuxkit/blob/master/docs/yaml.md

この内容ではDHCPクライアントしか動いていない最小構成のOSイメージが作成されます。

今回はさくらのクラウドを利用しますので、一番下の`outputs`を以下のようにしてISOイメージを出力するようにしましょう。

```bash:example/minimal.yml修正
cp example/minimal.yml sakura.yml
vi sakura.yml
# 一番下のoutputs部分を以下のように修正
#outputs:
#  - format: iso-bios
```

### イメージのビルド

以下のコマンドでビルドします。`sakura.iso`というファイルが出力されるはずです。

```bash:mobyでビルド
moby build sakura.yml
```

## ビルドしたイメージをさくらのクラウド上で起動

isoイメージができましたので、アップロードしてサーバ作成、ISOイメージを挿入しサーバを起動します。

コントロールパネルから実施しても良いのですが、今回はさくらのクラウドの新しい非公式CLIクライアントである`usacloud`コマンドで実施します。

[usacloudコマンド](https://github.com/sacloud/usacloud)

### usacloudコマンドのインストール

GitHubのリリースページからバイナリをダウンロードするだけでOKです。
また、yum/apt/homebrewでのインストールにも対応しています。

今回はmacOSで作業していますので、homebrewでインストールします。

```bash:usacloudインストール
brew tap sacloud/homebrew-usacloud; brew install usacloud
```

インストールしたら動作確認しておきます。(bash_completionを有効にするため再ログインしておいてください)

```bash:usacloud確認
$ usacloud -v
usacloud version 0.0.8, build 4934960
```

### APIキーの設定

以下のコマンドでAPIキーを入力します。(コンパネでAPIキーを作成しておいてください)

```bash:apiキー設定
usacloud config

Setting SakuraCloud API Token => 
	Enter token:                  # APIトークンを入力

Setting SakuraCloud API Secret => 
	Enter secret:                 # APIシークレットを入力

Setting SakuraCloud Zone => 

	Enter zone[is1a/is1b/tk1a/tk1v](default:tk1a):    # ゾーン選択(空でOK)

Written your settings to ~/.usacloud_config
```

以上で準備完了です。

### サーバ作成〜ISOアップロード〜ISOイメージ挿入〜起動

ではいよいよ作成したISOイメージからサーバ起動してみます。

```bash:サーバ起動
# mobyで作成したISOイメージをアップロードする
usacloud iso-image create -y --name moby_example --iso-file sakura.iso

# ディスクレスなサーバを作成(ISOイメージを挿入し、作成後起動する)
usacloud server build -y \
            --name moby_example \
            --disk-mode diskless \
            --iso-image-id `usacloud iso-image read -q moby_example | head -n1`

# 起動したサーバのコンソールに接続(さくらのクラウドのVNCプロキシを経由して接続)
usacloud server vnc -y moby_example
```

`usacloud server vnc`で、デフォルトのVNCクライアントが起動します。
macOSの場合は`画面共有.app`が開くはずです。

![moby_example.png](https://qiita-image-store.s3.amazonaws.com/0/20668/ea7aca28-cb27-4b97-9c11-f05ffeedd239.png)

DHCPクライアントが起動しているので、さくらのクラウドが割り当てたグローバルIPがeth0に付けられているのが確認できるはずです。

これでコンテナが動く最小構成のサーバが作成できました。

確認したら後始末として以下コマンドでサーバとISOイメージを削除しておきましょう。

```bash:削除
usacloud server rm -f -y moby_example
usacloud iso-image rm -y moby_example
```

## ディスクをマウントしてみる

ディスクをマウントすることもできるようです。
今回は空のディスクを作ってフォーマット/マウントする処理をonbootに書いてみます。

### イメージのビルド

yamlファイルを以下のように作成します。

```sakura.yml
kernel:
  image: "linuxkit/kernel:4.9.x"
  cmdline: "console=ttyS0 console=tty0 page_poison=1"
init:
  - linuxkit/init:63eed9ca7a09d2ce4c0c5e7238ac005fa44f564b
  - linuxkit/runc:b0fb122e10dbb7e4e45115177a61a3f8d68c19a9
  - linuxkit/containerd:18eaf72f3f4f9a9f29ca1951f66df701f873060b
onboot:
  - name: format
    image: "linuxkit/format:53748000acf515549d398e6ae68545c26c0f3a2e"
    binds:
     - /dev:/dev
    capabilities:
     - CAP_SYS_ADMIN
     - CAP_MKNOD
  - name: mount
    image: "linuxkit/mount:d2669e7c8ddda99fa0618a414d44261eba6e299a"
    binds:
     - /dev:/dev
     - /var:/var:rshared,rbind
    capabilities:
     - CAP_SYS_ADMIN
    rootfsPropagation: shared
    command: ["/mount.sh", "/var/external"]
services:
  - name: dhcpcd
    image: "linuxkit/dhcpcd:57a8ef29d3a910645b2b24c124f9ce9ef53ce703"
    binds:
     - /var:/var
     - /tmp/etc:/etc
    capabilities:
     - CAP_NET_ADMIN
     - CAP_NET_BIND_SERVICE
     - CAP_NET_RAW
    net: host
    oomScoreAdj: -800
trust:
  image:
    - linuxkit/kernel
outputs:
  - format: iso-bios
```

続いてmobyでビルドします。

```bash:mobyでビルド
moby build sakura.yml
```

### さくらのクラウドの操作

続いてさくらのクラウド側へISOをアップロードします。
その後、サーバと空のディスクを作成し接続、起動という流れです。

```bash:さくらのクラウド操作
# mobyで作成したISOイメージをアップロードする
usacloud iso-image create -y --name moby_example --iso-file sakura.iso

# ディスクレスなサーバを作成(まだ起動させない)
usacloud server build -y \
            --name moby_example \
            --disk-mode diskless \
            --disable-boot-after-create

# 空のディスクを作成
usacloud disk create -y --name moby_example

# サーバとディスクを接続
usacloud server disk-connect -y \
            --disk-id `usacloud disk read -q moby_example | head -n1` \
            moby_example

# サーバにISOイメージを挿入
usacloud server iso-insert -y \
           --iso-image-id `usacloud iso-image read -q moby_example | head -n1` \
           moby_example

# 起動
usacloud server boot -y moby_example

# 起動したサーバのコンソールに接続(さくらのクラウドのVNCプロキシを経由して接続)
usacloud server vnc -y moby_example

```

まずはきちんと接続したディスクがマウントできているか確認します。
![moby_example2.png](https://qiita-image-store.s3.amazonaws.com/0/20668/af21a424-bd52-2e7e-9005-267238053b7d.png)

大丈夫ですね。マウントできました。もちろん書き込みもOKです。

ISOイメージからブートしてデータだけディスクに置く、Immutableなサーバの完成です！！

確認したら後片付けを忘れずに。

```bash:お片付け
usacloud server rm -f -y moby_example
usacloud iso-image rm -y moby_example
```

## 実用的なイメージを作ってみる

ここまでくれば、Dockerイメージ化しているものであればすぐにでもmobyでイメージ化できそうですね！

今回は実用的な例として、さくらのクラウドとMackerelを連携するためのツール「sackerel」を起動するイメージを作成してみます。

sackerelについては以下を参照してください。

[サービス監視をお手軽に！さくらのクラウド + Mackerel = 「Sackerel(サカレル)」](http://knowledge.sakura.ad.jp/tech/6405/)

servicesの中でsackerelを起動するように設定しています。

```sakura.yml
kernel:
  image: "linuxkit/kernel:4.9.x"
  cmdline: "console=ttyS0 console=tty0 page_poison=1"
init:
  - linuxkit/init:63eed9ca7a09d2ce4c0c5e7238ac005fa44f564b
  - linuxkit/runc:b0fb122e10dbb7e4e45115177a61a3f8d68c19a9
  - linuxkit/containerd:18eaf72f3f4f9a9f29ca1951f66df701f873060b
  - linuxkit/ca-certificates:e091a05fbf7c5e16f18b23602febd45dd690ba2f
onboot:
  - name: sysctl
    image: "linuxkit/sysctl:2cf2f9d5b4d314ba1bfc22b2fe931924af666d8c"
    net: host
    pid: host
    ipc: host
    capabilities:
     - CAP_SYS_ADMIN
services:
  - name: rngd
    image: "linuxkit/rngd:c42fd499690b2cb6e4e6cb99e41dfafca1cf5b14"
    capabilities:
     - CAP_SYS_ADMIN
    oomScoreAdj: -800
  - name: dhcpcd
    image: "linuxkit/dhcpcd:48e249ebef6a521eed886b3bce032db69fbb4afa"
    binds:
     - /var:/var
     - /tmp:/etc
    capabilities:
     - CAP_NET_ADMIN
     - CAP_NET_BIND_SERVICE
     - CAP_NET_RAW
    net: host
    oomScoreAdj: -800
  - name: sackerel
    image: "sacloud/sackerel:latest"
    capabilities:
     - all
    net: host
    pid: host
    env:
     - "SAKURACLOUD_ACCESS_TOKEN=さくらのクラウドAPIトークンを入力"
     - "SAKURACLOUD_ACCESS_TOKEN_SECRET=さくらのクラウドAPIシークレットを入力"
     - "MACKEREL_APIKEY=MackerelのAPIキーを入力"
trust:
  image:
    - linuxkit/kernel
    - linuxkit/rngd
outputs:
  - format: iso-bios
```

`env`には適切にAPIキーを入力してください。
本来は`capabilities`をきちんと設定する必要がありますが、今回はとにかく動かすことが目的のために`all`にしてしまいました。

**良い子は絶対に真似しないでね！！**

## 起動してみる

あとはこれまでと同じくアップロードしてサーバ作成、起動してみましょう。

```bash:サーバ起動
# mobyで作成したISOイメージをアップロードする
usacloud iso-image create -y --name moby_example --iso-file sakura.iso

# ディスクレスなサーバを作成(ISOイメージを挿入し、作成後起動する)
usacloud server build -y \
            --name moby_example \
            --disk-mode diskless \
            --iso-image-id `usacloud iso-image read -q moby_example | head -n1`

# 起動したサーバのコンソールに接続(さくらのクラウドのVNCプロキシを経由して接続)
usacloud server vnc -y moby_example
```

起動したら`runc list`で起動しているコンテナを確認してみましょう。

![moby_example3.png](https://qiita-image-store.s3.amazonaws.com/0/20668/53975da0-a900-d91a-613c-05827b9cea88.png)

ログは`/var/log/sackerel.log`に出力されています。

![moby_example4.png](https://qiita-image-store.s3.amazonaws.com/0/20668/36d0f91c-fa38-b29a-0301-5c445f8e35cb.png)

今回はディスクレスなサーバにしましたので、ログが必要であれば別途fluentdを立てるなどしておけば良いでしょう。

## 終わりに

mobyでブータブルなイメージを作成してみました。
今回は扱いませんでしたが、dockerを動かすイメージも作成できます。
その場合、coreosやrancherOSと近いイメージになりますね。

また、linuxkitリポジトリ上ではAMIやk8s用イメージの作成なども実装が進められているようです。

https://github.com/linuxkit/linuxkit/tree/master/projects/kubernetes

こちらも楽しみです。

他にも、linuxkit(コマンド)と組み合わせたり、InfraKitで動的な足回り(インフラ)を構築する、Terraformと連携するなど色々と出来そうです。

linuxkit(コマンド)もmobyも活発に開発が進んでますので、今後も楽しみですね！

以上です。