Azure Docker Kubernetes

ACS Engineを利用してAzure上にkubernetesをdeploy!

はじめに

くどうです。
今回はAzureでのACS Engine について解説していきます。
また、2つのAdvent Calenderにエントリーしてます。

Microsoft Azure Advent Calendar 2017
https://qiita.com/advent-calendar/2017/azure
Kubernetes2 Advent Calendar 2017
https://qiita.com/advent-calendar/2017/kubernetes2
ACS Engineとは何でしょう。Azure Container Service Engineの略です。
AzureにはACS、AKSがありますが、まぁその大元のデプロイツールみたいなもので、テンプレート作成エンジンです。最終的に出来上がるモノは機能的にほぼ変わりませんが、様々なカスタマイズが可能です。
そもそもコードがオープンなので書き換えれば何でもできる(?)かもしれません。

ACS Engine
https://github.com/Azure/acs-engine
オーケストレーションツール
・swarm
・kubernetes
・DC/OS

コンテナー
・Docker

ベースは一緒です。
さてここからが本題です。
ただ、、、いまさらkubernetes(以下k8s)以外の選択する理由がさほど思い浮かばないないのでk8sで解説を進めます。

なぜACS Engine ?

なぜ、ACSやAKSではなく、ACS Engineでデプロイする必要があるのか?
個人的に以下の2つの機能が欲しかったためです。
1、Nodeの配置のカスタマイズ
- 任意のVNETへの配置が行える
- 1200Nodeのクラスタ構築が行える
2、Nodeのオートスケール
- Podの展開数に応じてオートスケールする

以上の理由によりACS Engineである必要がありました。
Service Fabricでも良いのでは?とも考えましたがなんかコンテナ展開するの面倒そうだったの却下(それだけじゃないですけど)

ACS Engineの展開

ではここからは実際に、ACS Engineでk8sを展開していきます。
手始めとして、任意のVNETへ展開していきます。

VNET、Subnetは既に作成されていることが前提です。
展開するリソースは以下です。

・リソースグループ
名前:acsengine
リージョン:eastus

・VNET
名前:acsengine-vnet
CIDR:172.16.0.0/16

・サブネット
名前:acsengine-subnet1
CIDR:172.16.0.0/24

ACSのダウンロード
バイナリで配布されています。
OSに合わせてダウンロードし、Pathを通しましょう。
今回はLinuxでしています。

v0.10.0
https://github.com/Azure/acs-engine/releases/tag/v0.10.0
また、下記のサイトよりソースをダウンロードします。
https://github.com/Azure/acs-engine

jun@kudo3:~/ACS$ git clone https://github.com/Azure/acs-engine.git
Cloning into 'acs-engine'...
remote: Counting objects: 33003, done.
remote: Compressing objects: 100% (63/63), done.
remote: Total 33003 (delta 43), reused 32 (delta 17), pack-reused 32923
Receiving objects: 100% (33003/33003), 45.81 MiB | 3.63 MiB/s, done.
Resolving deltas: 100% (18013/18013), done.
Checking connectivity... done.
Checking out files: 100% (9507/9507), done.

以上で準備完了です。

任意のVNETへ展開する方法

examplesのディレクトリ内にあるサンプルテンプレートを編集します。

jun@kudo3:~/ACS/acs-engine$
jun@kudo3:~/ACS/acs-engine$ vi examples/kubernetes.json

masterProfileに追記します。
・dnsPrefix → dnsPrefixを指定
・vnetSubnetId → 展開するサブネットIDを指定
・FirstConsecutiveStaticIP → マスターノードを展開する最初のIPを指定

agentPoolProfilesに追記します。
・vnetSubnetId → 展開するサブネットIDを指定

{
  "apiVersion": "vlabs",
  "properties": {
    "orchestratorProfile": {
      "orchestratorType": "Kubernetes"
    },
    "masterProfile": {
      "count": 1,
      "dnsPrefix": "acsengin",
      "vmSize": "Standard_D2_v2",
      "vnetSubnetId": "/subscriptions/{サブスクリプションID}/resourceGroups/acsengine/providers/Microsoft.Network/virtualNetworks/acsengine-vnet/subnets/acsengine-subnet1",
      "FirstConsecutiveStaticIP": "172.16.0.100"
    },
    "agentPoolProfiles": [
      {
        "name": "agentpool1",
        "count": 3,
        "vmSize": "Standard_D2_v2",
        "availabilityProfile": "AvailabilitySet",
        "vnetSubnetId": "/subscriptions/{サブスクリプションID}/resourceGroups/acsengine/providers/Microsoft.Network/virtualNetworks/acsengine-vnet/subnets/acsengine-subnet1"
      }
    ],
    "linuxProfile": {
      "adminUsername": "azureuser",
      "ssh": {
        "publicKeys": [
          {
            "keyData": ""
          }
        ]
      }
    },
    "servicePrincipalProfile": {
      "clientId": "",
      "secret": ""
    }
  }
}

以上で展開の準備が完了です。

デプロイする

acs-engineを利用して展開します。

jun@kudo3:~/ACS/acs-engine$ acs-engine deploy --subscription-id {サブスクリプションID} --resource-group acsengine --location eastus --auto-suffix --api-model examples/kubernetes.json
WARN[0007] apimodel: ServicePrincipalProfile was missing or empty, creating application...
WARN[0009] created application with applicationID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx) and servicePrincipalObjectID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx).
WARN[0009] apimodel: ServicePrincipalProfile was empty, assigning role to application...
didn't find EtcdDiskSizeGB
INFO[0039] Starting ARM Deployment (acsengine-1414093469). This will take some time...
INFO[0472] Finished ARM Deployment (acsengine-1414093469).

アカウント情報がない場合はログインをログインを求められます。
自動的に、サービスプリンシパルとNodeにログインするためのKeyが作成されます。
テンプレートやKeyは_output内にdnsPrefix名で作成されます。

jun@kudo3:~/ACS/acs-engine$ ls -l _output/acsengine/
合計 212
-rw------- 1 jun jun  26352 12月  9 23:59 apimodel.json
-rw------- 1 jun jun   4304 12月  9 23:59 apiserver.crt
-rw------- 1 jun jun   3243 12月  9 23:59 apiserver.key
-rw------- 1 jun jun 109974 12月  9 23:59 azuredeploy.json
-rw------- 1 jun jun  36321 12月  9 23:59 azuredeploy.parameters.json
-rw------- 1 jun jun   3243 12月  9 23:58 azureuser_rsa
-rw------- 1 jun jun   1720 12月  9 23:59 ca.crt
-rw------- 1 jun jun   3247 12月  9 23:59 ca.key
-rw------- 1 jun jun   1781 12月  9 23:59 client.crt
-rw------- 1 jun jun   3243 12月  9 23:59 client.key
drwx------ 0 jun jun    512 12月  9 23:59 kubeconfig
-rw------- 1 jun jun   1781 12月  9 23:59 kubectlClient.crt
-rw------- 1 jun jun   3243 12月  9 23:59 kubectlClient.key

デプロイ後色々と展開されます。
まぁそこは確認してください。

サブネットに適用しているルートテーブルの変更します。
これを行わない場合、正しくNodeへの通信が行えません。

jun@kudo3:~/ACS/acs-engine$ rt=$(az network route-table list -g acsengine | jq -r '.[].id')
jun@kudo3:~/ACS/acs-engine$ az network vnet subnet update -n acsengine-subnet1 -g acsengine --vnet-name acsengine-vnet --route-table $rt
{
  "addressPrefix": "172.16.0.0/24",
  "etag": "W/\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx\"",
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/acsengine/providers/Microsoft.Network/virtualNetworks/acsengine-vnet/subnets/acsengine-subnet1",
  "ipConfigurations": [
    {
      "etag": null,
・・・

ログインしてみる
マスターノードのIPは各自、Portalなどから確認してください。
デフォルト設定ではユーザー名はazureuserです。
ユーザー名_rsaのkeyファイルです。

jun@kudo3:~/ACS/acs-engine/_output/acsengine$ ssh -i azureuser_rsa azureuser@52.191.194.23
The authenticity of host '52.191.194.23 (52.191.194.23)' can't be established.
ECDSA key fingerprint is SHA256:FJulgboLg+8EMeYGHprh2TuN3rxlD7ABfQO7h1zJTk0.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '52.191.194.23' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.11.0-1013-azure x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

49 packages can be updated.
0 updates are security updates.


*** System restart required ***

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To run a command as administrator (user "root"), use "sudo < command >".
See "man sudo_root" for details.

azureuser@k8s-master-93548069-0:~$

あとは、k8sの利用方法と同じです。

nodeをスケールする場合は以下のコマンドで行えます。
以下では3から5に増やしています。

jun@kudo3:~/ACS/acs-engine$ acs-engine scale --subscription-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx --resource-group acsengine --location eastus --deployment-dir _output/acsengine --new-node
-count 5 --node-pool agentpool1 --master-FQDN acsengine.eastus.cloudapp.azure.com
INFO[0000] validating...
INFO[0006] Name suffix: 93548069
INFO[0006] Starting ARM Deployment (acsengine-1960058367). This will take some time...
INFO[0223] Finished ARM Deployment (acsengine-1960058367).

サンプルとしてnginxを展開しますnginx.yml作成します。

apiVersion: v1
kind: Service
metadata:
    name: nginx-service
    annotations:
        service.beta.kubernetes.io/azure-load-balancer-internal: "true"
spec:
    type: LoadBalancer
    ports:
    - name: http
      port: 80
      targetPort: nginx-http
      protocol: TCP
    selector:
        app: nginx
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - name: nginx-http
          containerPort: 80
        resources:
          requests:
            cpu: 200m

AzureでInternal LoadBalancerを利用するには以下の指定が必要となります。
External LoadBalancerの場合はannotationsの指定は必要ありません。

metadata:
  ・・・
    annotations:
        service.beta.kubernetes.io/azure-load-balancer-internal: "true"
spec:
    type: LoadBalancer
azureuser@k8s-master-93548069-0:~$ kubectl create -f nginx.yml
2017-12-09 15:54:26.841483 I | proto: duplicate proto type registered: google.protobuf.Any
2017-12-09 15:54:26.841531 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-12-09 15:54:26.841543 I | proto: duplicate proto type registered: google.protobuf.Timestamp
service "nginx-service" created
deployment "nginx-deploy" created
azureuser@k8s-master-93548069-0:~$ kubectl get po
2017-12-09 16:00:59.015164 I | proto: duplicate proto type registered: google.protobuf.Any
2017-12-09 16:00:59.015210 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-12-09 16:00:59.015222 I | proto: duplicate proto type registered: google.protobuf.Timestamp
NAME                            READY     STATUS    RESTARTS   AGE
nginx-deploy-2978454550-wp50m   1/1       Running   0          7s
azureuser@k8s-master-93548069-0:~$ kubectl get svc
2017-12-09 16:01:44.758885 I | proto: duplicate proto type registered: google.protobuf.Any
2017-12-09 16:01:44.758929 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-12-09 16:01:44.758946 I | proto: duplicate proto type registered: google.protobuf.Timestamp
NAME            CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes      10.0.0.1      < none >        443/TCP        58m
nginx-service   10.0.243.49   172.16.0.9    80:30817/TCP   7m

Serviceを確認するとプライベートIPが作成EXTERNAL-IPが指定されています。
テスト用のVMを立てて確認してみましょう。

azureuser@test1:~$ curl 172.16.0.9



Welcome to nginx!
< style >
    body {
        width: 35em;
        margin: 0 auto;
・・・

大体これで完了です。
あとはご自由にk8sを操ってください。

オートスケール

Podのオートスケールはkubanetesの機能に組み込まれていますが、Node単位でも可能です。
以下のKubernetes-acs-engine-autoscalerを利用します。
https://github.com/wbuchwalter/Kubernetes-acs-engine-autoscaler
Podがスケールするとnodeに展開できるpod数を超えるとnodeがオートスケールする仕組みです。

おまけ

ダッシュボードはbugのようなものがあります。
http://blog.shibayan.jp/entry/20171114/1510669620
また、起動時すでに利用できるようになっていますがCPUなどの情報が表示されません。
対応策としてdashboardのpodを一旦削除し、Deployされるのを待ちます。

azureuser@k8s-master-93548069-0:~$ kubectl get --namespace kube-system po |grep dashboard
2017-12-09 16:27:13.322334 I | proto: duplicate proto type registered: google.protobuf.Any
2017-12-09 16:27:13.322377 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-12-09 16:27:13.322387 I | proto: duplicate proto type registered: google.protobuf.Timestamp
kubernetes-dashboard-3432808331-mt1wt           1/1       Running   0          1h
azureuser@k8s-master-93548069-0:~$ kubectl delete po --namespace kube-system kubernetes-dashboard-3432808331-mt1wt
2017-12-09 16:28:00.220370 I | proto: duplicate proto type registered: google.protobuf.Any
2017-12-09 16:28:00.220425 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-12-09 16:28:00.220446 I | proto: duplicate proto type registered: google.protobuf.Timestamp
pod "kubernetes-dashboard-3432808331-mt1wt" deleted
azureuser@k8s-master-93548069-0:~$ kubectl get --namespace kube-system po |grep dashboard
2017-12-09 16:28:26.639064 I | proto: duplicate proto type registered: google.protobuf.Any
2017-12-09 16:28:26.639109 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-12-09 16:28:26.639120 I | proto: duplicate proto type registered: google.protobuf.Timestamp
kubernetes-dashboard-3432808331-c1lkz           1/1       Running   0          26s

あとは接続するためにForwardingします。

azureuser@k8s-master-93548069-0:~$ kubectl --namespace kube-system port-forward kubernetes-dashboard-3432808331-c1lkz 8001:9090
2017-12-09 16:30:23.645857 I | proto: duplicate proto type registered: google.protobuf.Any
2017-12-09 16:30:23.645902 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-12-09 16:30:23.645912 I | proto: duplicate proto type registered: google.protobuf.Timestamp
Forwarding from 127.0.0.1:8001 -> 9090
Forwarding from [::1]:8001 -> 9090

クライアント側からアクセスできるようするようSSLでトンネルを掘ります。

ssh -v -N -D 10080  azureuser@52.191.194.23 -i _output/acsengine/azureuser_rsa -f

Proxyの設定をブラウザで指定します。

以下にアクセスします。
http://127.0.0.1/8001

これでGUIでの確認が行えます。

削除する場合は丸っとリソースグループごと消しちゃいましょう。

まとめ

ACS Engineは難しくはないです。また今後も進化を遂げるでしょう、Node単位でのオートスケールにも対応していくようです。
ACS、AKSを利用するよりも現実的な提案が行えるかと思います。簡単ですが以上です。

-Azure, Docker, Kubernetes
-, , ,