しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Azure Container Service Engine を使って Windows と Linux が共存する Kubernetes クラスタを作る

Azure Container Service で Managed Disk を使いたいと思って調べていた時に、Azure Container Service Engine のサンプルに引っかかったので、いろいろと調べてました。

ちょっと前にオープンソース化された ACS Engine ですが、いい感じに ARM Template を作ってくれるだけのコンポーネントで、ECS Agent とは全く異なるものでした。

サンプルの中に Kubernetes のエージェントとして Windows と Linux を同時に扱うものがあったので、面白そうだったので実際にデプロイしてみました。

ACS Engine の準備

まず ACS Engine のリポジトリをクローンしてきます。ドキュメントに書いてあるように Docker を使った方が楽なのでおすすめです。

acs-engine/acsengine.md at master · Azure/acs-engine · GitHub

Docker の環境が出来ていれば devenv.sh を実行して、初回のみ make build を行います。

./script/devenv.sh
make build

これでボリュームがマウントされた ACS Engine の Docker 環境にログインされるので、後は ARM Template を生成すれば終わりです。今回使うのは kubernetes-hybrid.json というファイルです。

acs-engine/kubernetes-hybrid.json at master · Azure/acs-engine · GitHub

dnsPrefix やサービスプリンシパルなどの情報が抜けてるので、acs-engine の実行前に埋めておきます。デフォルトでは Windows と Linux で 2 つずつインスタンスが作られるので注意。

JSON の修正が終われば、そのファイルを acs-engine に食わせるだけです。

./acs-engine ./example/windows/kubernetes-hybrid.json

実行すると Kubernetes のデプロイに必要な証明書など、いろいろと作成してくれます。

f:id:shiba-yan:20170504231858p:plain

Azure へのデプロイに必要な azuredeploy.json と azuredeploy.parameters.json も作成されているので、次はこのファイルと Azure CLI を使ってデプロイを行います。

Azure にデプロイ

デプロイには Azure CLI 2.0 を使いました。手順としては Resource Group を作成して、その Group に対して ARM Template を指定してデプロイを行う形です。

Resource Group や Location は適宜読み替えてほしいですが、大体 2 行で処理は終わります。

az group create --name "Container-RG" --location "Japan West"

az group deployment create --name "kubernetes" --resource-group "Container-RG" \
    --template-file "./azuredeploy.json" --parameters "@./azuredeploy.parameters.json"

parameters に指定するパスの前に付いている @ は必要なので忘れないように。地味にはまりました。

デプロイを実行すると、大量のリソースが作成されます。ACS 自体はリソースとして作成されないです。

f:id:shiba-yan:20170504232226p:plain

これまでと同じように kubectl を使って Kubernetes ダッシュボードからノードを確認しておきます。

f:id:shiba-yan:20170504231512p:plain

名前の付け方やラベルに多少の違いはありますが、1 つの Kubernetes 内で Windows と Linux のノードが動作しています。実は ACS で作ったものより、Kubernetes のバージョンが新しいです。

クラスタが完成したので、実際にアプリケーションをデプロイして確認してみます。

アプリケーションをデプロイ

Windows ノードにデプロイするのは IIS なので、Azure の Kubernetes ドキュメントから拾ってきた YAML をほぼそのまま利用します。変更点としてはイメージを microsoft/iis に変えただけです。

apiVersion: v1
kind: Service
metadata:
  name: win-webserver
  labels:
    app: win-webserver
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: win-webserver
  type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: win-webserver
  name: win-webserver
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: win-webserver
      name: win-webserver
    spec:
      containers:
      - name: windowswebserver
        image: microsoft/iis
      nodeSelector:
        beta.kubernetes.io/os: windows

これとほぼ同じ内容でイメージを nginx に、nodeSelector を linux に変更したものを Linux ノードにデプロイするために用意しました。

YAML をアップロードしてデプロイを行うと、あっさりと Windows と Linux のデプロイが作成されます。

f:id:shiba-yan:20170504234125p:plain

ちょっと不思議な光景ですが、上手く扱えば開発の自由度向上と運用の手間を削減できそうです。

それぞれのポッドが作成完了になった後に、外部エンドポイントにアクセスするとデフォルトのページが表示されます。イメージのサイズが違うので仕方ないのですが、IIS の方が数倍時間がかかりました。*1

f:id:shiba-yan:20170504234612p:plain

同じネットワーク内にいるので、コンテナ間での通信も問題ないです。サービス名だけで繋がります。

f:id:shiba-yan:20170505000315p:plain

kubectl exec を使うことで、Windows と Linux のポッドに接続できるので、それを使って試しました。

最後に何となく、それぞれのポッドのレプリカを増やして試してみました。

f:id:shiba-yan:20170504234519p:plain

普通の感覚だと 2 ノードでレプリカを 2 つに増やすと、それぞれのノードにデプロイされるはずですが、nodeSelector で OS を指定しているので、ちゃんと同一ノード上にデプロイされました。

実行環境は全て 1 つの Kubernetes にまとめてしまって、ネームスペースで Production / Staging など区別し、アプリケーションは OS 問わず同じクラスタに乗せてしまうというのもありかもしれません。

*1:しかも Windows は Premium Storage を使っているというのに