AKS で asp.net core アプリケーション : Application Gateway と Application Gateway Ingress Controller

[前回](https://qiita.com/kenakamu/items/f4c0fabea8044a6b28cb) は Application Gateway 経由で AKS 上のアプリを外部公開しました。今回はより密に Application Gateway と AKS を連携させる方法として Application Gateway Ingress Controller (AGIC) を使います。

[GitHub: Application Gateway Kubernetes Ingress](https://github.com/Azure/application-gateway-kubernetes-ingress)

# AGIC 概要

AGIC は Kubernetes のイングレスリソースとして AKS にデプロイされます。AGIC は常時クラスタの状態を監視し、必要に応じて Application Gateway の設定を動的更新します。

以下の図は AGIC が Kubernetes API を通じて状態を監視し、その結果 ARMテンプレート経由で Application Gateway を変更する様子を示しています。

![](https://github.com/Azure/application-gateway-kubernetes-ingress/raw/master/docs/images/architecture.png)

AGIC は以下の機能を提供します。

- URL ルーティング
- クッキーベースでのアフィニティ
- SSL 終端
- エンドツーエンドでの SSL 通信
- パブリック、インターナルおよびハイブリッドの Web サイトサポート
- アプリケーションファイヤーウォールとの統合

尚、これらの機能は Application Gateway が実際には提供します。AGIC は AKS 側のリソース作成や変更に対して自動的に Application Gateway がこれらの機能を使えるように構成します。

# 事前準備

## テイントのないノードの追加

現在すべてのノードはそれぞれ type=sql か type=app でテイントされているため、これから追加するポッドを配置するためのノードを、ノードプール 1 に追加します。

1\. nodepool scale コマンドを実行

```shell
az aks nodepool scale -n nodepool1 --node-count 3 -g netcoresample --cluster-name myaks
```

2\. ノードを確認。

```shell
>kubectl get nodes
NAME                                STATUS   ROLES   AGE     VERSION
aks-nodepool1-23705949-vmss000000   Ready    agent   23h     v1.13.11
aks-nodepool1-23705949-vmss000001   Ready    agent   23h     v1.13.11
aks-nodepool1-23705949-vmss000002   Ready    agent   5m42s   v1.13.11
aks-nodepool2-23705949-vmss000000   Ready    agent   23h     v1.13.11
```
これでテイントがないノードが作成されました。

## Helm のインストールとレポジトリの追加

AGIC は Helm を使ってインストールする手順が紹介されているため、ここでは Helm をインストールします。Helm についてはまた別のシリーズで紹介します。

1\. [GitHub: Helm](https://github.com/helm/helm/releases) より利用している OS の最新版の helm を取得。任意の場所に解凍してパスを通す。ここでは [v2.15.2](https://github.com/helm/helm/releases/tag/v2.15.2) をインストール。

2\. AKS で Tiller 用のサービスアカウントを tiller-sa 作成。

```shell
kubectl create serviceaccount --namespace kube-system tiller-sa
```

3\. 作成したアカウントにクラスタ管理者の権限を付与。

```shell
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller-sa
```
4\. Helm を初期化。

```shell
helm init --tiller-namespace kube-system --service-account tiller-sa
```

5\. AGIC 用のレポジトリを追加。

```
helm repo add application-gateway-kubernetes-ingress https://appgwingress.blob.core.windows.net/ingress-azure-helm-package/
helm repo update
```

6\. Tiller が配置されたか確認。

```shell
>kubectl -n kube-system get pods
...
tiller-deploy-7fb69fc45-mlft8           1/1     Running   0          26m
...
>helm version
Client: &version.Version{SemVer:"v2.15.2", GitCommit:"8dce272473e5f2a7bf58ce79bb5c3691db54c96b", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.15.2", GitCommit:"8dce272473e5f2a7bf58ce79bb5c3691db54c96b", GitTreeState:"clean"}
```

## AAD Pod Identity のセットアップ

AAD Pod Identity は AKS で動作するコントローラーで、Azure Active Directory Identities をポッドにバインドできます。このシナリオでは AGIC ポッドが ARM テンプレートを操作する権限が必要となるため、こちらの機能を利用します。

1\. AAD Pod Identity のデプロイを実行。

```shell
kubectl apply -f https://raw.githubusercontent.com/Azure/aad-pod-identity/master/deploy/infra/deployment-rbac.yaml
```

2\. AAD Identity の作成。作成先のリソースグループは、クラスタノードが存在するリソースグループを指定。表示された結果から PrincipalId をメモ。

```shell
az identity create -g MC_netcoresample_myaks_japaneast -n agic_identity
```

3\. Application Gateway のリソース ID を取得。

```shell
az network application-gateway list --query "[].id"
```

4\. 作成した Identity に Application Gateway の　Contributor ロールを付与。

```shell
az role assignment create \
    --role Contributor \
    --assignee <principalId> \
    --scope <App-Gateway-ID>
```

5\. Application Gateway が配置されたリソースグループの ID を取得。

```shell
az group list --query "[].id"
```

6\. Identity にリソースグループの　Reader を付与。

```shell
az role assignment create \
    --role Reader \
    --assignee <principalId> \
    --scope <App-Gateway-Resource-Group-ID>
```

# AGIC のインストール

事前準備が完了したため、 AGIC をインストールします。

1\. Helm 構成ファイルを [https://raw.githubusercontent.com/Azure/application-gateway-kubernetes-ingress/master/docs/examples/sample-helm-config.yaml](https://raw.githubusercontent.com/Azure/application-gateway-kubernetes-ingress/master/docs/examples/sample-helm-config.yaml) よりダウンロードして helm-config.yaml として保存。

2\. ファイルを開いて appgw、armAuth および rbac を適切な値に書き換え。armAuth の値は Identity 作成時のアウトプットから取得。消した場合は ```az identity show -g MC_netcoresample_myaks_japaneast -n agic_identity``` で取得可能。

```yaml
appgw:
    subscriptionId: 93b67b2c-9ac0-4bd8-a565-4603f7073a97
    resourceGroup: netcoresample
    name: netcoresampleag
...
armAuth:
    type: aadPodIdentity
    identityResourceID: <Identity id>
    identityClientID:  <Identity clientId>
...
rbac:
    enabled: true
```

3\. インストール実行。

```shell
helm install -f helm-config.yaml application-gateway-kubernetes-ingress/ingress-azure
```
4\. ポッドの確認。

```shell
>kubectl get pods
NAME                                          READY   STATUS    RESTARTS   AGE
core3webapp-67b678b946-cthmp                  1/1     Running   6          23h
core3webapp-67b678b946-rd6nc                  1/1     Running   6          23h
invited-kiwi-ingress-azure-66d6855bf7-f6lgh   1/1     Running   1          70s
mic-65cbc47665-2wgfb                          1/1     Running   0          64m
mic-65cbc47665-xqfgq                          1/1     Running   0          64m
mssql-deployment-6597f9f5b6-z8g9j             1/1     Running   1          23h
nmi-nkkkn                                     1/1     Running   1          35m
```
5\. Application Gateway が自動で更新され、バックエンドプールの設定が削除されたことを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/f20d891d-9147-c1e1-57b2-f88ab2638439.png)

# アプリの公開

最後にアプリを公開します。アプリの公開はイングレスリソースの作成で行います。

1\. myapp.yaml の最後に以下のコードを追加。

- クッキーによるアフィニティを有効化
- ポート 80 でバックエンドプールに追加

```yaml:myapp.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: core3webapp
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
　　appgw.ingress.kubernetes.io/cookie-based-affinity: "true"
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: core3webapp
          servicePort: 80
```
2\. デプロイを実行。

```
kubectl apply -f myapp.yaml
```

3\. Application Gateway のバックエンドプールを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/0d8cf612-bcb2-33dd-c35a-bc9682d92c5a.png)

4\. 新規に作成されたバックエンドプールの詳細を確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/9b88864c-60a8-47cd-cc26-0a69689eeb8f.png)

5\. ポッドの IP と一致しているか確認。

```shell
>kubectl get pods -o wide
NAME                                          READY   STATUS    RESTARTS   AGE   IP           NODE                                NOMINATED NODE   READINESS GATES
core3webapp-67b678b946-cthmp                  1/1     Running   6          23h   10.0.0.16    aks-nodepool1-23705949-vmss000000   <none>           <none>
core3webapp-67b678b946-rd6nc                  1/1     Running   6          23h   10.0.0.55    aks-nodepool1-23705949-vmss000001   <none>           <none>
invited-kiwi-ingress-azure-66d6855bf7-f6lgh   1/1     Running   1          11m   10.0.0.106   aks-nodepool1-23705949-vmss000002   <none>           <none>
mic-65cbc47665-2wgfb                          1/1     Running   0          74m   10.0.0.127   aks-nodepool1-23705949-vmss000002   <none>           <none>
mic-65cbc47665-xqfgq                          1/1     Running   0          75m   10.0.0.108   aks-nodepool1-23705949-vmss000002   <none>           <none>
mssql-deployment-6597f9f5b6-z8g9j             1/1     Running   1          23h   10.0.0.75    aks-nodepool2-23705949-vmss000000   <none>           <none>
nmi-nkkkn                                     1/1     Running   1          46m   10.0.0.98    aks-nodepool1-23705949-vmss000002   <none>           <none>
```

6\. HTTP 設定から Cookie ベースのアフィニティ設定を確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/839ad3a6-136f-5f99-d30d-d799efb2a2b0.png)

7\. ブラウザからの接続を確認。ログインまで行えるか検証。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/496e0b2a-8f8c-c74c-7dee-cc172aee1bda.png)

# まとめ

今回は AGIC を使った Application Gateway の構成を試しました。AGIC を使うと、AKS 側の設定が自動的に Application Gateway に反映されるため管理を 1 箇所でできるメリットがある一方、AKS 側で追加のポッドをデプロイすることになるので、事前の計画が必要そうです。

現在はテイントでポッドの配置を制御しようとしていますが、まだ問題があることと、アプリに関係ないポッドが増えてきたため、次回はこの辺りを整理していきます。

[次の記事へ](https://qiita.com/kenakamu/items/7003b6013779f1a5bdb6)
[目次へ戻る](https://qiita.com/kenakamu/items/e155740aa60c85a3d867)

# 参照

[GitHub: Application Gateway Kubernetes Ingress](https://github.com/Azure/application-gateway-kubernetes-ingress)
[GitHub: AAD Pod Identity](https://github.com/Azure/aad-pod-identity)
[Azure Kubernetes Service (AKS) での Helm を使用したアプリケーションのインストール](https://docs.microsoft.com/ja-jp/azure/aks/kubernetes-helm)
[GitHub: Helm](https://github.com/helm/helm/releases)