東日本にきたAKS（Azure Kubernetes Service）とACR（Azure Container Registry）入門

# はじめに

昨日かな？AKS(Azure Kubernetes Service）が東日本で使えるようになりましたね。
早速動かしてみたいと思います。

仕事で使う上ではpublicなイメージではなく、ビルドした独自のイメージをprivateなリポジトリで管理することが多いと思います。
今回はACRにpushしたprivateイメージを使ってKubernetesにデプロイしてみようと思います。
ACRへのデプロイは少し工夫が必要ですので参考にしてみてください。

# ACRへのpush

こちらの記事を参考にACRにpushしてみてください。

[AzureContainerRegistryにprivateイメージをpushしよう](https://qiita.com/uzresk/items/f6fa479186c51dccaba1)

今回はpushされた以下の情報を使います。

* ログインサーバ
    * uzresk0626.azurecr.io
* レジストリ
    * uzresk0626

--- 

# Kubernetesクラスタの構築

Kubernetesサービスを選択し、クラスターの作成を押して、必要事項をポチポチいれていきます

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/7d513a33-0daa-dae1-d3b4-fd229b29ef87.png)

ネットワークも何も考えずにポチポチします

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/a00eb81f-2545-dc5c-3746-8b267b0c9118.png)

モニターは有効にしておきます

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/b8940a22-753b-ac39-4b12-0c00e8f4b69c.png)

タグを適当につけて確認して「作成」

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/4723c2d0-39e2-6905-e48d-aa48e40eb530.png)

少し待つと3ノードのクラスタができているはずです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/169762e1-833f-6b86-7c74-de282690be9a.png)

CloudShellではkubectlコマンドやazコマンドが入っているので、インストールの手間がなくとても便利ですね。
CloudShellを起動します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/b8fe1bfd-83c7-d14e-7ffd-c82ef98f253c.png)

credentialを取得することでkubectlコマンドを使えるようになります。
認証情報は~/.kube/configに書き込まれます。

```
uzresk@Azure:~$ az aks get-credentials --resource-group East-ResourceGroup --name uzresk-aks-cluster
Merged "uzresk-aks-cluster" as current context in /home/uzresk/.kube/config
```

起動したノードの一覧を取得してみましょう。確かに3ノード起動していますね。

```
uzresk@Azure:~$ kubectl get nodes
NAME                       STATUS    ROLES     AGE       VERSION
aks-agentpool-15689703-0   Ready     agent     15m       v1.10.3
aks-agentpool-15689703-1   Ready     agent     15m       v1.10.3
aks-agentpool-15689703-2   Ready     agent     15m       v1.10.3
```

# デプロイの準備（ACRとの連携）

kubernetesからpullするには、ACRから認証を受ける必要があります。
以下のshellを実行することで、ServicePrincipalIDとPasswordを取得することができます。
ACR_NAMEの部分だけ書き換えてください。

```get-service-principal.sh
#!/bin/bash

ACR_NAME=uzresk0626
SERVICE_PRINCIPAL_NAME=acr-service-principal

# Populate the ACR login server and resource id.
ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --query loginServer --output tsv)
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv)

# Create a contributor role assignment with a scope of the ACR resource.
SP_PASSWD=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME --role Reader --scopes $ACR_REGISTRY_ID --query password --output tsv)

# Get the service principle client id.
CLIENT_ID=$(az ad sp show --id http://$SERVICE_PRINCIPAL_NAME --query appId --output tsv)


# Output used when creating Kubernetes secret.
echo "ACR Login Server:" $ACR_LOGIN_SERVER
echo "Service principal ID: $CLIENT_ID"
echo "Service principal password: $SP_PASSWD"
```

実行するとServicePrincipalIDとPasswordが手に入ります。

```
uzresk@Azure:~$ ./get-service-principal.sh
Retrying role assignment creation: 1/36
Service principal ID: XXXXXXXXXXXXXXXXXXXXXXXXX
Service principal password: YYYYYYYYYYYYYYYYYYYYYYYY
```

secretを取得します。`secret "acr-auth" created`が表示されていることを確認してください。

```
uzresk@Azure:~$ kubectl create secret docker-registry acr-auth --docker-server uzresk0626.azurecr.io --docker-username XXXXXXXXXXXXXXXXXXXXXXXXX --docker-password YYYYYYYYYYYYYYYYYYYYYYYY --docker-email test@xxxx.com
secret "acr-auth" created
```

取得していることを確認します。acr-authが表示されていることを確認してください。

```
uzresk@Azure:~$ kubectl get secrets -o wide
NAME                  TYPE                                  DATA      AGE
acr-auth              kubernetes.io/dockerconfigjson        1         6m
default-token-gwtdh   kubernetes.io/service-account-token   3         25m
```

# デプロイ

ymlファイルを準備しましょう。

```uzresk0626.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: uzresk0626
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: uzresk0626
    spec:
      containers:
      - name: uzresk0626
        image: uzresk0626.azurecr.io/uzresk0626:3.4.4
        ports:
        - containerPort: 80
        env:
        - name: MAX_MEMORY_MB
          value: "4096"
      imagePullSecrets:
      - name: acr-auth
---
apiVersion: v1
kind: Service
metadata:
  name: uzresk0626
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: uzresk0626
```

ポイントはpullするときに認証を受ける設定です。

```uzresk0626.yml
      imagePullSecrets:
      - name: acr-auth
```

やっとデプロイです。applyコマンドを使います。

```
uzresk@Azure:~$ kubectl apply -f uzresk0626.yml
deployment "uzresk0626" created
service "uzresk0626" created
uzresk@Azure:~$
```

コンテナがpullできているか確認してみます。
「Successfully pulled images」となっていることを確認してください。

```
uzresk@Azure:~$ kubectl describe pod uzresk0626-6bfdbd495d-mnkqt
Name:           uzresk0626-6bfdbd495d-mnkqt
・・・・
Events:
  Type    Reason                 Age   From                               Message
  ----    ------                 ----  ----                               -------
  Normal  Scheduled              22m   default-scheduler                  Successfully assigned uzresk0626-6bfdbd495d-mnkqt to aks-agentpool-15689703-1
  Normal  SuccessfulMountVolume  22m   kubelet, aks-agentpool-15689703-1  MountVolume.SetUp succeeded for volume "default-token-gwtdh"
  Normal  Pulling                22m   kubelet, aks-agentpool-15689703-1  pulling image "uzresk0626.azurecr.io/uzresk0626:3.4.4"
  Normal  Pulled                 17m   kubelet, aks-agentpool-15689703-1  Successfully pulled image "uzresk0626.azurecr.io/uzresk0626:3.4.4"
  Normal  Created                17m   kubelet, aks-agentpool-15689703-1  Created container
  Normal  Started                17m   kubelet, aks-agentpool-15689703-1  Started container
```

進行状況をみてみましょう。

```
uzresk@Azure:~$ kubectl get service uzresk0626 --watch
NAME         TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)        AGE
uzresk0626   LoadBalancer   10.0.36.236   13.78.29.237   80:31845/TCP   1m
```

すこし待つとEXTERNAL-IPが取れますので、Ctrl+Cで抜けて該当のIPにアクセスすると画面が表示されるはずです。

# クラスタの削除

サービスの削除（いきなりクラスタを削除しても構いません）

```
uzresk@Azure:~$ kubectl delete service uzresk0626
service "uzresk0626" deleted
```

クラスタを削除する

```
uzresk@Azure:~$ az aks delete --resource-group East-ResourceGroup --name uzresk-aks-cluster --no-wait
Are you sure you want to perform this operation? (y/n): y
uzresk@Azure:~$
```

すこし待つとVirtualMachineも削除されるはずです。

# 最後に

AzureでもKubernetesがこんなに簡単に扱えるのは嬉しいですね。
ACRの部分は独特ですが、他の手順はGCPとほぼ一緒なので途中でGCPを触っているような錯覚に襲われました。
これがKubernetesを使う意義なんでしょうね。

# 参考

* [Azure Kubernetes Service から Azure Container Registry の認証を受ける](https://docs.microsoft.com/ja-jp/azure/container-registry/container-registry-auth-aks)