ASK を使いこなす: SQL Server 2017 を AKS で使う - SQL のインストールと障害復旧の検証

[前回](https://qiita.com/kenakamu/items/8d584e6da3e93929b1d9)に引き続き [Azure Kubernetes Services (AKS) を使用して Kubernetes に SQL Server コンテナーを配置する](https://docs.microsoft.com/ja-jp/sql/linux/tutorial-sql-server-containers-kubernetes?view=sql-server-2017) を深堀します。

今回はシークレットの作成や SQL Server 2017 の配置を行います。

# 前提

今回は SQL Server への接続に Azure Data Studio を使います。
インストールしていない場合は、[こちら](https://docs.microsoft.com/ja-jp/sql/azure-data-studio/download?view=sql-server-2017)よりインストールしてください。

# SA パスワードを作成する

1\. 以下コマンドでシークレットを作成。

- シークレットの名前が mssql でキーは SA_PASSWORD

```shell
kubectl create secret generic mssql --from-literal=SA_PASSWORD="MyC0m9l&xP@ssw0rd"
```

2\. 作成したシークレットは以下のように取得可能。

- SA_PASSWORD として base64 エンコード済の値が表示される

```shell
> kubectl get secret mssql -o yaml
apiVersion: v1
data:
  SA_PASSWORD: TXlDMG05bCZ4UEBzc3cwcmQ=
kind: Secret
metadata:
  creationTimestamp: "2019-09-27T03:55:25Z"
  name: mssql
  namespace: default
  resourceVersion: "303952"
  selfLink: /api/v1/namespaces/default/secrets/mssql
  uid: a34d20f1-e0da-11e9-869b-d2cecd57d4bb
type: Opaque
```
3\. PowerShell の場合、以下手順でデコード可能。

```shell
> [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('TXlDMG05bCZ4UEBzc3cwcmQ='))
MyC0m9l&xP@ssw0rd
```

# SQL Server 2017 のインストール

SQL Server 2017 は [mcr.microsoft.com/mssql/server:2017-latest](https://hub.docker.com/_/microsoft-mssql-server) として Docker Hub に公開済のため、こちらを取得する展開を作って適用します。

1\. sqldeployment.yaml として以下の yaml を作成。

- containers.env: コンテナに渡す各種引数を指定
- 作成したシークレットは valueFrom.secretKeyRef で取得
- containers.volumeMounts: ボリュームを /var/opt/mssql にマウント
- spec.volumes: 前回作成した永続ボリューム要求を指定

```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
---
apiVersion: v1
kind: Service
metadata:
  name: mssql-deployment
spec:
  selector:
    app: mssql
  ports:
    - protocol: TCP
      port: 1433
      targetPort: 1433
  type: LoadBalancer
```
2\. yaml を適用。

```shell
kubectl apply -f .\sqldeployment.yaml
```

3\. サービスの確認。40.115.187.66:1433 で公開済。

```shell
> kubectl get services                                             NAME               TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)          AGE
kubernetes         ClusterIP      10.0.0.1      <none>          443/TCP          3d2h
mssql-deployment   LoadBalancer   10.0.192.95   40.115.187.66   1433:30890/TCP   6m7s
```

4\. ポッドの作成は少し時間がかかるため、watch で状況確認。STATUS が Running に変わるまで待機。

```shell
> kubectl get pods -w
NAME                                READY   STATUS              RESTARTS   AGE
mssql-deployment-5b74bdb6f7-tqz8q   0/1     ContainerCreating   0          65s
mssql-deployment-5b74bdb6f7-tqz8q   1/1     Running             0          2m12s
```

5\. Azure Data Studio から接続確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/dd0457e4-c690-5521-2718-ab740c207037.png)


6\. データベース、テーブルとデータを作成。結果を取得できることを確認。

```sql
CREATE DATABASE AKSDemo
GO
USE AKSDemo;
CREATE TABLE T1(
    ID INT PRIMARY KEY,
    Data NVARCHAR(10)
);
INSERT INTO T1 VALUES (1, 'Data1');
INSERT INTO T1 VALUES (2, 'Data2');
INSERT INTO T1 VALUES (3, 'Data3');
INSERT INTO T1 VALUES (4, 'Data4');

SELECT * FROM T1;
```

7\. ポッドが配置されているノードに対してディスクがアタッチされていることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/5e83c541-80d1-81c2-21b4-bd4f47e32ee4.png)

# 障害と復旧を検証する

ここではポッドの再起動とノードの停止をそれぞれ検証します。

## 同一ノード内のポッド再配置

まずは現在稼働中のポッドを単純に停止して、レプリカセットによって同じノードにポッドが再配置された場合の動作を見ます。

1\. ポッドの一覧を確認。

```shell
> kubectl get pods                                                 
NAME                                READY   STATUS    RESTARTS   AGE
mssql-deployment-5b74bdb6f7-tqz8q   1/1     Running   0          9m55s
```
2\. 既存のポッドを削除。

```shell
kubectl delete pod mssql-deployment-5b74bdb6f7-tqz8q 
```

3\. 再度現在のポッド一覧を確認。別名の新しいポッドが起動したことを確認。

```shell
> kubectl get pods                                                 
NAME                                READY   STATUS    RESTARTS   AGE
mssql-deployment-5b74bdb6f7-2cfmm   1/1     Running   0          17s
```

4\. Azure Data Studio より T1 テーブルをクエリ。サービスのおかげで同じ IP アドレスで接続したまま継続したクエリが可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/6c7d47d6-ed14-4c93-4c16-3565627276a8.png)

## 異なるノードへのポッド再配置

次に現在ポッドが起動しているノードが障害やメンテナンスで停止した場合、レプリカセットによって別ノードにポッドが配置された場合の挙動を見ます。

1\. ポッドが現在稼働しているノードを確認。

```shell
> kubectl get pods -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP            NODE                       NOMINATED NODE   READINESS GATES
mssql-deployment-5b74bdb6f7-fzvfx   1/1     Running   0          61s   10.244.1.75   aks-nodepool1-34717040-0   <none>           <none>
```

2\. 該当のノードに対して```drain``` を使うことにより、ポッドの配置を一旦停止。

```shell
kubectl drain aks-nodepool1-34717040-0
```

3\. ポッドを削除してレプリカセットによって再配置。

```shell
> kubectl delete pods mssql-deployment-5b74bdb6f7-fzvfx
```

4\. ポッド再配置の様子を ```watch``` で確認。

- aks-nodepool1-34717040-0 のポッドが停止される
- aks-nodepool1-34717040-1 に新しいポッドが作成される

```shell
> kubectl get pods -o wide -w
NAME                                READY   STATUS    RESTARTS   AGE   IP            NODE                       NOMINATED NODE   READINESS GATES
mssql-deployment-5b74bdb6f7-fzvfx   1/1     Running   0          85s   10.244.1.75   aks-nodepool1-34717040-0   <none>           <none>
mssql-deployment-5b74bdb6f7-fzvfx   1/1     Terminating   0          87s   10.244.1.75   aks-nodepool1-34717040-0   <none>           <none>
mssql-deployment-5b74bdb6f7-gvfwn   0/1     Pending       0          0s    <none>        <none>                     <none>           <none>
mssql-deployment-5b74bdb6f7-gvfwn   0/1     Pending       0          0s    <none>        aks-nodepool1-34717040-1   <none>           <none>
mssql-deployment-5b74bdb6f7-gvfwn   0/1     ContainerCreating   0          0s    <none>        aks-nodepool1-34717040-1   <none>           <none>
mssql-deployment-5b74bdb6f7-fzvfx   0/1     Terminating         0          90s   <none>        aks-nodepool1-34717040-0   <none>           <none>
mssql-deployment-5b74bdb6f7-fzvfx   0/1     Terminating         0          90s   <none>        aks-nodepool1-34717040-0   <none>           <none>
mssql-deployment-5b74bdb6f7-fzvfx   0/1     Terminating         0          98s   <none>        aks-nodepool1-34717040-0   <none>           <none>
mssql-deployment-5b74bdb6f7-fzvfx   0/1     Terminating         0          98s   <none>        aks-nodepool1-34717040-0   <none>           <none>
mssql-deployment-5b74bdb6f7-gvfwn   1/1     Running             0          70s   10.244.0.11   aks-nodepool1-34717040-1   <none>           <none>
```
5\. クエリが実行できることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/5c011e04-f14b-c253-7968-8e16e3f3a17f.png)

6\. ディスクが新しいノードにアタッチされていることをポータルから確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/7a36ecad-b96b-20df-496a-5ce05096b336.png)


7\. 最後にノードでポッドが配置できるように ```uncordon``` を実施。

```shell
kubectl uncordon aks-nodepool1-34717040-0
```

# まとめ

今回は SQL Server 2017 コンテナの配置と障害復旧について検証してみました。

[目次へ戻る](https://qiita.com/kenakamu/items/e155740aa60c85a3d867)

# 参照
[Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)
[Nodes: Condition](https://kubernetes.io/docs/concepts/architecture/nodes/?utm_sq=g18hpku31k#condition)