AKS で asp.net core アプリケーション : ラベル、セレクターと名前空間

[前回の記事](https://qiita.com/kenakamu/items/6997c894e6cce58f2ea2)までで、以下の図のようにある程度の構成ができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/ef3047e8-f326-1039-fce0-4f0ef9f06011.png)

この記事ではノードセレクターと名前空間を使っていくつかの問題を解決します。

# ポッドの配置問題

これまでの手順でポッドを配置していると、なんとなく意図したノードにポッドが配置されているように見えますが、必ずしも意図通りにならない問題があります。

## Taints と Tolerations

現在 SQL と Web アプリをそれぞれ別のノードプールに配置するため、[こちらの記事](https://qiita.com/kenakamu/items/aee6748b6d15b8aab34f#taints-%E3%81%A8-tolerations) で紹介したとおりテイントと容認を使っています。しかし前回 AGIC を入れるため、テイントがないノードを追加しており、現在は以下のような構成となっています。

|ノード|付与したテイント|
|---|---|
|aks-nodepool1-23705949-vmss000000| kind=app:NoSchedule　|
|aks-nodepool1-23705949-vmss000001| kind=app:NoSchedule　|
|aks-nodepool1-23705949-vmss000002| なし　|
|aks-nodepool2-23705949-vmss000000| kind=sql:NoSchedule　|

|デプロイ|付与した容認|
|---|---|
|core3webapp| kind=app:NoSchedule　|
|mssql-deployment| kind=sql:NoSchedule　|

この場合の問題は、SQL も Web アプリもノード aks-nodepool1-23705949-vmss000002 には配置される可能性があるという事です。

1\. 現在の core3webapp ポッドの 1 つの配置先を確認。

```shell
>kubectl get pods -o wide
NAME                                          READY   STATUS    RESTARTS   AGE   IP           NODE                                NOMINATED NODE   READINESS GATES
core3webapp-67b678b946-h2t9p                  1/1     Running   0          8h    10.0.0.16    aks-nodepool1-23705949-vmss000000   <none>           <none>
```

2\. core3webapp ポッドを 1 つ削除。

```shell
kubectl delete pod core3webapp-67b678b946-h2t9p
```

3\. ポッドを再度表示しテイントが内ノードに配置されていることを確認。
※一度で再現しない可能性はあるが、何度かやると再現する。

```shell
>kubectl get pods -o wide
NAME                                          READY   STATUS              RESTARTS   AGE   IP           NODE                                NOMINATED NODE   READINESS GATES
core3webapp-67b678b946-vlp2h                  0/1     ContainerCreating   0          10s   <none>       aks-nodepool1-23705949-vmss000002   <none>           <none>
```

この問題を解決するにはポッドでノードセレクターを利用します。

## ラベルとノードセレクター

ノードをはじめ各種リソースにはラベルが指定できますが、このラベルを使ってリソースを指定することが可能です。早速 SQL ポッドがノードプール 2 のノードに配置できるようにしてみます。

1\. 任意のラベルをノードに追加。

```shell
kubectl label nodes aks-nodepool2-23705949-vmss000000 kind=sql
```

2\. 追加したラベルを確認。

```shell
>kubectl describe node aks-nodepool2-23705949-vmss000000
Name:               aks-nodepool2-23705949-vmss000000
Roles:              agent
Labels:             agentpool=nodepool2
                    beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/instance-type=Standard_DS1_v2
                    beta.kubernetes.io/os=linux
                    failure-domain.beta.kubernetes.io/region=japaneast
                    failure-domain.beta.kubernetes.io/zone=0
                    kind=sql
                    kubernetes.azure.com/cluster=MC_netcoresample_myaks_japaneast
<省略>
```

3\. Deployment で mssql-deployment にノードセレクターを追加。

```yaml:myapp.yaml
<省略>
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: mssql-deployment
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mssql
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: mssql
        image: mcr.microsoft.com/mssql/server:2017-latest
        ports:
        - containerPort: 1433
        env:
        - name: MSSQL_PID
          value: "Developer"
        - name: ACCEPT_EULA
          value: "Y"
        - name: MSSQL_SA_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mssql
              key: SA_PASSWORD 
        volumeMounts:
        - name: mssqldb
          mountPath: /var/opt/mssql
      volumes:
      - name: mssqldb
        persistentVolumeClaim:
          claimName: mssql-data
      tolerations:
      - key: "kind"
        operator: "Equal"
        value: "sql"
        effect: "NoSchedule"
      nodeSelector:
        kind: sql
<省略>
```
3\. 同様に Web アプリも対応。

```shell
kubectl label nodes aks-nodepool1-23705949-vmss000000 kind=app
kubectl label nodes aks-nodepool1-23705949-vmss000001 kind=app
```
4\. core3webapp に nodeSelector を追加。またレプリカを 4 に増加。

```yaml:myapp.yaml
<省略>
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: core3webapp
  namespace: default
  labels:
    app: core3webapp
spec:
  replicas: 4
  selector:
    matchLabels:
        app: core3webapp
  template:
    metadata:
      name: core3webapp
      labels:
        app: core3webapp
    spec:
      containers:
      - name: core3webapp
        image: kenakamuacr.azurecr.io/core3webapp:20191029043926
        resources: 
          requests:
            cpu: "250m"
            memory: "512Mi"
          limits:
            cpu: "500m"
            memory: "1Gi"
        imagePullPolicy: Always
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      tolerations:
        key: "kind"
        operator: "Equal"
        value: "app"
        effect: "NoSchedule"
      nodeSelector:
        kind: app
<省略>
```
5\. kubectl apply を実行。

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

6\. ポッドの詳細を取得して、意図通りになっていることを確認。

```shell
>kubectl get pods -o wide
NAME                                          READY   STATUS    RESTARTS   AGE   IP           NODE                                NOMINATED NODE   READINESS GATES
core3webapp-b599bd5d-4rjl6                    1/1     Running   0          3s    10.0.0.50    aks-nodepool1-23705949-vmss000001   <none>           <none>
core3webapp-b599bd5d-9wp7c                    1/1     Running   0          51s   10.0.0.22    aks-nodepool1-23705949-vmss000000   <none>           <none>
core3webapp-b599bd5d-cjdqm                    1/1     Running   0          57s   10.0.0.10    aks-nodepool1-23705949-vmss000000   <none>           <none>
core3webapp-b599bd5d-szmgv                    1/1     Running   0          3s    10.0.0.55    aks-nodepool1-23705949-vmss000001   <none>           <none>
invited-kiwi-ingress-azure-66d6855bf7-f6lgh   1/1     Running   2          22h   10.0.0.106   aks-nodepool1-23705949-vmss000002   <none>           <none>
mic-65cbc47665-2wgfb                          1/1     Running   2          24h   10.0.0.102   aks-nodepool1-23705949-vmss000002   <none>           <none>
mic-65cbc47665-xqfgq                          1/1     Running   2          24h   10.0.0.125   aks-nodepool1-23705949-vmss000002   <none>           <none>
mssql-deployment-749f664d67-zc86p             1/1     Running   0          57s   10.0.0.83    aks-nodepool2-23705949-vmss000000   <none>           <none>
nmi-nkkkn                                     1/1     Running   3          23h   10.0.0.98    aks-nodepool1-23705949-vmss000002   <none>           <none>
```

# ポッドやサービスの分離問題

同じクラスタにテスト環境や本番環境をデプロイする場合、それぞれのリソースが扱いやすいようにグループ化する必要があります。k8s では名前空間が利用できます。

## 名前空間

k8s には名前空間の概念があり、必要に応じてポッドを任意の名前空間に配置することができます。名前空間を使うと、表示を絞れる他、リソースの制約など各種設定を名前空間に対して設定することもできるため、操作性や管理性が上がります。

## 既定の名前空間

既定で以下の名前空間を持ちます。

- default
- kube-public
- kube-system

ユーザーが作成したリソースの大半は default へ自動配置されます。名前空間は kubectl create でも yaml 経由でも作成できますが今回は kubectl で作成しました。

1\. production 名前空間リソースを作成。

```shell
kubectl create namespace production
```

2\. 現在のデプロイを一度削除。※ Persistent Volume も消えるため SQL のデータが削除される。 PV は名前空間に関係ないため、PV 以外を手動で削除してもよい。

```shell
kubectl delete -f myapp.yaml
```

3\. 名前空間の指定つきでデプロイ。

```shell
kubectl apply -f myapp.yaml --namespace=production
```

4\. 既定の名前空間でポッド一覧を取得。

```shell
>kubectl get pods
NAME                                          READY   STATUS    RESTARTS   AGE
invited-kiwi-ingress-azure-66d6855bf7-f6lgh   1/1     Running   2          23h
mic-65cbc47665-2wgfb                          1/1     Running   2          24h
mic-65cbc47665-xqfgq                          1/1     Running   2          24h
nmi-nkkkn                                     1/1     Running   3          24h
```

5\. 名前空間を指定して取得。

```shell
>kubectl get pods --namespace production
NAME                                READY   STATUS    RESTARTS   AGE
core3webapp-b599bd5d-47wjx          1/1     Running   3          3m11s
core3webapp-b599bd5d-9l8hx          1/1     Running   2          3m11s
core3webapp-b599bd5d-mp7h9          1/1     Running   2          3m11s
core3webapp-b599bd5d-n76cj          1/1     Running   3          3m11s
mssql-deployment-749f664d67-w8pd7   1/1     Running   0          3m11s
```

6\. アプリの動作はこれまで通りか確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/d6dadf2a-12d7-df48-913e-9575c7e4f926.png)

## 既定の名前空間の切り替え

既定が default の場合、常に --namespace パラメーターをつける必要があるため面倒です。ここでは既定の名前空間を production に変更します。

1\. 現在の構成情報を確認。

```shell
kubectl config view
```

2\. 現在のコンテキストを確認。

```shell
>kubectl config current-context
myaks
```

3\. myaks コンテキストの情報を使いつつ、名前空間を指定してコンテキストを作成。

```shell
kubectl config set-context prod --namespace=production --cluster=myaks --user=clusterUser_netcoresample_myaks
```

4\. コンテキストを切り替え。

```shell
kubectl config use-context prod
```

5\. ポッドを取得。

```shell
>kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
core3webapp-b599bd5d-47wjx          1/1     Running   3          12m
core3webapp-b599bd5d-9l8hx          1/1     Running   2          12m
core3webapp-b599bd5d-mp7h9          1/1     Running   2          12m
core3webapp-b599bd5d-n76cj          1/1     Running   3          12m
mssql-deployment-749f664d67-w8pd7   1/1     Running   0          12m
```

# まとめ

配置の問題はテイント/容認にノードセレクターを組み合わせることで解決し、グループ化の問題は名前空間を使いました。次回は自動のスケールについて詳細を見ていきます。

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

# 参考

[ノードのセレクター](https://docs.microsoft.com/ja-jp/azure/aks/concepts-clusters-workloads#node-selectors)
[Namespace](https://kubernetes.io/docs/tasks/administer-cluster/namespaces-walkthrough/)