Azure Container Service エンジン入門

このエントリは「[Microsoft Azure Advent Calendar 2016](http://qiita.com/advent-calendar/2016/azure)」の12日目です。

# 書いてあること
* Azure Container Service オープンソース化
* どうやって使うの？
* acs-engine がすぐ使えるコンテナを Docker Hub に上げました

# Azure Container Service って？
Azure には、Azure Container Service(以下ACS) というコンテナ環境を簡単に作れるサービスがあります。
AWS でいうところの Amazon EC2 Container Service (ECS) ですね。

ただ、ちょっと違うところとしては、ECS がガッツリとコンテナ管理を含めてサービスを作りこんでいるのに対し、ACS は、オープンソースな製品を組み合わせて Azure 上にコンテナ基盤を作りますよ、管理は各製品に用意された方法でよろしくね、という点で、アプローチの違いがあります。

そして、このACS を使うと、Swarm・DC/OS・Kubernetes といった、Docker でよく聞くオーケストレーション製品がすぐに使えるようになります。

この辺りのサービス紹介は、公式のドキュメントをご参照ください。
Azure Container Service の概要
https://docs.microsoft.com/ja-jp/azure/container-service/container-service-intro

# オープンソース化って？
そして、このACSが最近オープンソース化されました。
以下ニュースソース。

公式 : [Azure Container Service: the cloud’s most open option for containers](https://azure.microsoft.com/en-us/blog/azure-container-service-the-cloud-s-most-open-option-for-containers/)
TechCrunch Japan : [MicrosoftがAzure Container Service Engineをオープンソース化、Kubernetesのネイティブインテグレーションも発表](http://jp.techcrunch.com/2016/11/08/20161107microsoft-open-sources-its-azure-container-service-engine-and-launches-deeper-kubernetes-integration/)
Publickey : [マイクロソフト、クラウドでコンテナサービスを実現する「Azure Container Service Engine」をオープンソースとして公開](http://www.publickey1.jp/blog/16/azure_container_service_engine.html)

サービスがオープンソース化ってどういうこと？というところが真っ先に疑問としてあるかと思いますが、要は、**ACS をAzure へデプロイする時の ARM テンプレートを生成する部分**が、オープンソース化したよ、という意味です。

ちなみに、今でもポータルからは ACS をデプロイすることはできるのですが、既存の仮想ネットワークへ所属させるというオプションが画面上無い為、現状これらのカスタマイズを行う為には、このオープンソース化された ACS エンジンを使う必要があります。

次では、実際に既存の仮想ネットワークに所属する ACS を作ってみます。

# 使ってみよう
ここからが本題。じゃーこのオープンソース化されたエンジンどうやって使うのか、というところを説明していきます。

## 必要なもの
* Golang が使える環境
* Azure のサブスクリプション(コンテナ環境のデプロイ時に使用。エンジンの使用のみでは不要)

## 使用方法
### 1. ACS エンジンを持ってくる
初めて知ったのですが、Golang には、Gitからライブラリを持ってくるという機能があります。
で、この機能を使って、GitHub で公開されている ACS エンジンをインストールします。
※Golang 詳しくないので間違ってたら教えてください。。

```bash:ACSエンジンのインストール
# ライブラリのダウンロードとインストール
go get github.com/Azure/acs-engine
# 依存関係もインストール
go get all
```

これで ACS エンジンが使えるようになりました。
ちなみに、ACS エンジンは、acs-engine というコマンドで使えます。

```
# acs-engine
usage: acs-engine [OPTIONS] ClusterDefinitionFile
       read the ClusterDefinitionFile and output an arm template
options:
  -artifacts string
        directory where artifacts will be written
  -classicMode
        enable classic parameters and outputs
  -noPrettyPrint
        do not pretty print output
  -parametersOnly
        only output the parameters
```

### 2. クラスタ定義ファイルを作成する
acs-engine コマンドは、Cluster Definition File(クラスタ定義ファイル)から、ARM のテンプレートを生成します。
このクラスタ定義ファイルですが、ゼロから作るのはなかなか大変なので、サンプルを使いましょう。

**サンプル**
acs-engine/examples/vnet/swarmvnet.json
https://github.com/Azure/acs-engine/blob/master/examples/vnet/swarmvnet.json

ちなみに、クラスタ定義ファイルの詳細は以下をご参照ください。
ここに、必須のパラメーター等が記載されています。

Microsoft Azure Container Service Engine - Cluster Definition
https://github.com/Azure/acs-engine/blob/master/docs/clusterdefinition.md

このサンプルをベースに、次のような環境を作ってみます。

![ACS](https://qiita-image-store.s3.amazonaws.com/0/132347/02c8665c-cbd1-b94c-401b-7b799619b58f.png "ACS")

この環境は、ほとんど [Azure Container Service の概要](https://docs.microsoft.com/ja-jp/azure/container-service/container-service-intro) に記載されているものと同じですが、仮想ネットワークを既存のものに含める、という点が違います。

以下、上の環境のクラスタ定義ファイルです。
※Swarmモードで作ります。

```JSON:クラスタ定義ファイル(swarmvnet.json)
{
  "apiVersion": "vlabs",
  "properties": {
    "orchestratorProfile": {
      "orchestratorType": "Swarm"
    },
    "masterProfile": {
      "count": 1,
      "dnsPrefix": "tsunomuracs2",
      "vmSize": "Standard_A2",
      "vnetSubnetId": "/subscriptions/<サブスクリプションID>/resourceGroups/acsenginedemo/providers/Microsoft.Network/virtualNetworks/vnet/subnets/mastervnet",
      "firstConsecutiveStaticIP": "172.19.3.21"
    },
    "agentPoolProfiles": [
      {
        "name": "agentpublic",
        "count": 3,
        "vmSize": "Standard_A2",
        "dnsPrefix": "tsunomuracsagent",
        "vnetSubnetId": "/subscriptions/<サブスクリプションID>/resourceGroups/acsenginedemo/providers/Microsoft.Network/virtualNetworks/vnet/subnets/agentvnet",
        "ports": [
          80,
          443,
          8080
        ]
      }
    ],
    "linuxProfile": {
      "adminUsername": "tsunomur",
      "ssh": {
        "publicKeys": [
          {
            "keyData": "ssh-rsa AAAAB--略--npN root@alinsrv02"
          }
        ]
      }
    }
  }
}
```

見ての通りですが、count、dnsPrefix、vmSize、vnetSubnetID、ssh の publicKeys 等々は置き換えます。
この辺りは一度ポータルから ACS の環境を作ってみるとイメージがつくかと思います。

また、上の GitHub のサンプルは、エージェントノードとして、パブリックとプライベートの2つのスケールセットが定義されていますが、パブリックのみにしています。
※逆に、agentPoolProfiles に複数定義することで複数のスケールセットが出来上がります。

### 3. acs-engine コマンドを使って、ARMテンプレートを生成する
それではいよいよ acs-engine コマンドを使ってみましょう。

使い方は簡単、引数にクラスタ定義ファイルを指定してあげるだけです。

```:ARMテンプレートを生成する
# acs-engine swarmvnet.json
wrote _output/Swarm-37618431/apimodel.json
wrote _output/Swarm-37618431/azuredeploy.json
wrote _output/Swarm-37618431/azuredeploy.parameters.json
acsengine took 233.693568ms
```

上のコマンドの結果の通り、`_ouput` ディレクトリに ARM テンプレートが出力されます。
ちょっと出来上がったテンプレートを見てみましょう。

```
# ls -l _output/Swarm-37618431/
total 52
-rw------- 1 root root  1680 Dec  8 12:05 apimodel.json
-rw------- 1 root root 44329 Dec  8 12:05 azuredeploy.json
-rw------- 1 root root  1252 Dec  8 12:05 azuredeploy.parameters.json
# wc -l _output/Swarm-37618431/azuredeploy.json
1086 _output/Swarm-37618431/azuredeploy.json
#
```

という感じで、なかなかの量の JSON ファイルが出来上がりました。

ここまで見て頂いて分かったかと思いますが、ACS エンジンというのはぶっちゃけ、ARM テンプレートを生成する為のツールということですね。

### 4. デプロイする
ここまで来たらあとは `azure` コマンドでデプロイしてあげれば完成です。

acsenginedemo という リソース グループ にデプロイします。

```:デプロイ
# azure group deployment create -g acsenginedemo -n acs-deploy -f azuredeploy.json -e azuredeploy.parameters.json -d All
```


デプロイできたらあとは SSH でつないで docker run が出来ます。

マスターノードには、2357番ポート で Swarm コンテナが動いているのでそこにつないであげます。

```
root@swarm-master-37618431-0:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                                                                                NAMES
a15e09e5a52e        swarm:1.1.0         "/swarm manage --repl"   6 hours ago         Up 6 hours          0.0.0.0:2375->2375/tcp                                                                                                               containers_swarm_1
7835b6f7a6ba        progrium/consul     "/bin/start -server -"   6 hours ago         Up 6 hours          0.0.0.0:8300-8302->8300-8302/tcp, 0.0.0.0:8400->8400/tcp, 53/tcp, 53/udp, 0.0.0.0:8500->8500/tcp, 0.0.0.0:8301-8302->8301-8302/udp   containers_consul_1
root@swarm-master-37618431-0:~# export DOCKER_HOST=:2375
root@swarm-master-37618431-0:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@swarm-master-37618431-0:~# docker run -d -p 80:80 tsunomurdocker01-microsoft.azurecr.io/tsubasaxzzz/nginx
a1de10719317812c97eb4cb6c9e74f0104553838c84e147a356425ef37c74e73
root@swarm-master-37618431-0:~# docker ps
CONTAINER ID        IMAGE                                                     COMMAND                  CREATED             STATUS              PORTS                            NAMES
a1de10719317        tsunomurdocker01-microsoft.azurecr.io/tsubasaxzzz/nginx   "nginx -g 'daemon off"   4 seconds ago       Up 2 seconds        172.19.3.7:80->80/tcp, 443/tcp   swarm-agentpublic-37618431000003/nauseous_bhaskara
root@swarm-master-37618431-0:~#
```

そして、上の通り、残念ながら今のところは、Docker 1.12 で組み込まれた Swarm ではなく、以前のタイプの Swarm なので、少し使い方は独特です。
そのあたりは、[Docker Swarm 入門ハンズオン](http://qiita.com/TsutomuNakamura/items/6124ab7d32a58bc93ac7) が詳しそうです。

# まとめ
ざっと ACS エンジンの概要がお分かり頂けたでしょうか。
基本的に出来ることというのは大きくは変わっていないのですが、acs-engine コマンドを他のツール、例えばCIツールと組み合わせることも出来たりするので、これまで以上に幅は広がったのではないでしょうか。

# tsubasaxzzz/acs-engine を作りました
acs-engine コマンドがすぐに使えるイメージを作って、Docker Hub に登録しました。
宜しければお使いください。

https://hub.docker.com/r/tsubasaxzzz/acs-engine/

参考までに、Dockerfile です。

```Dockerfile
FROM golang
RUN set -x && \
    go get github.com/Azure/acs-engine && \
    go get all && \
    apt-get update && \
    apt-get install -y vim
```

ちなみに、上で書いていた、Golang の環境や Azure CLI の環境、インストールめんどくさいなぁと思ったので Docker コンテナ使いました。コンテナ 最高。

# 参考リンク

Microsoft Azure Container Service Engine - Cluster Definition
https://github.com/Azure/acs-engine/blob/master/docs/clusterdefinition.md

Microsoft Azure Container Service Engine
https://github.com/Azure/acs-engine/blob/master/docs/acsengine.md

# 雑記
オートスケーリングの設定が無いけど、ARM テンプレートがりがり編集なのかな。。
クラスタ定義ファイルにスケーリングの設定も入ることを期待です。

# さて、次回のアドベントカレンダーは…
[Microsoft Azure Advent Calendar 2016](http://qiita.com/advent-calendar/2016/azure)
明日は @papeMK2 さんです！