Azure Kubernetes Service (AKS) で PersistentVolumeClaimResize による Persistent Volume (Azure Disk) の拡張

# やりたいこと
Kubernetes では [PersistentVolumeClaimResize を用いることで PersistentVolumeClaim (PVC) の拡張が可能](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#persistentvolumeclaimresize)ですが、[Azure 公式ドキュメント](https://docs.microsoft.com/en-us/azure/aks/azure-disks-dynamic-pv)に現段階で手順の記載がないため検証を行います。

# 注意点
英語ですが、当機能について [GitHub で Issue](https://github.com/kubernetes/kubernetes/issues/68427) が作成されています。Azure Disk ではマウントされている状態でディスクの拡張は出来ません。そのため、2019 年 1 月時点では Pod の削除を行ってから PVC の拡張を行い、再作成する、という手順になります。

また、Azure Disk は 2019 年 1 月時点で拡張はできるものの縮小はできません。

# 手順
1. yaml ファイルの準備
2. PersistentVolumeClaimResize を有効にした Storage Class を作成する
3. PVC を作成する
4. PVC を使用した Pod を作成する
5. Pod にマウントされている PV のサイズを確認する
6. Pod を削除する
7. PVC を編集する
8. Pod を再作成する
9. Pod にマウントされている PV のサイズを確認する

# コマンド
##1. yamlファイルの準備
以下の 3 ファイルを使用します。

```yaml:sample-storageclass-resize-azure.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: sample-storageclass-resize-azure
parameters:
  kind: Managed
  storageaccounttype: Premium_LRS
provisioner: kubernetes.io/azure-disk
reclaimPolicy: Delete
allowVolumeExpansion: true
```

```yaml:sample-pvc-resize-azure.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: sample-pvc-resize-azure
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 8G
  storageClassName: sample-storageclass-resize-azure
```

```yaml:sample-pvc-resize-pod-azure.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-pvc-resize-pod-azure
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12
      ports:
        - containerPort: 80
          name: "http"
      volumeMounts:
      - mountPath: "/usr/share/nginx/html"
        name: nginx-pvc
  volumes:
    - name: nginx-pvc
      persistentVolumeClaim:
       claimName: sample-pvc-resize-azure
```

## 2. PersistentVolumeClaimResize を有効にした Storage Class を作成する

Azure Kubernetes Service では以下のように記載することで Azure Managed Disk (管理ディスク) の Premium Storage を使用できます。 その他の指定の仕方は[Storage Class の公式リファレンス](https://kubernetes.io/docs/concepts/storage/storage-classes/#new-azure-disk-storage-class-starting-from-v1-7-2) をご参照ください。

```yaml:sample-storageclass-resize-azure.yamlの抜粋
parameters:
  kind: Managed
  storageaccounttype: Premium_LRS
provisioner: kubernetes.io/azure-disk
```

最終行を以下のようにして頂くことで Volume Expansion (ボリュームの拡張) が可能になります。拡張させたくない場合は false にします。

```yaml:sample-storageclass-resize-azure.yamlの抜粋
allowVolumeExpansion: true
```

Storage Class の作成を前述の yaml ファイルから行います。

``` bash
kubectl apply -f sample-storageclass-resize-azure.yaml
```

## 3. PVC を作成する

PVC の yaml では storageClassName パラメータで用いる Storage Class を指定します。先ほど作成した Storage Class を指定しましょう。

```yaml:sample-pvc-resize-azure.yamlから抜粋
  storageClassName: sample-storageclass-resize-azure
```

PVC の作成を前述の yaml ファイルから行います。


```bash
kubectl apply -f ./sample-pvc-resize-azure.yaml
```

## 4. PVC を使用した Pod を作成する

Pod の yaml では ClaimName で使用する PVC を指定します。先ほど作成した PVC を指定しましょう。

```yaml:sample-pvc-resize-pod-azure.yamlから抜粋
      persistentVolumeClaim:
       claimName: sample-pvc-resize-azure
```

Pod の作成を前述の yaml ファイルから行います。

```bash
kubectl apply -f ./sample-pvc-resize-pod-azure.yaml
```

##5. Pod にマウントされている PV のサイズを確認する
きちんと PVC で指定したサイズで作成されていることが確認できます。

```shell-session
# kubectl exec -it sample-pvc-resize-pod-azure -- df -h |grep nginx
/dev/sdc        7.8G   18M  7.8G   1% /usr/share/nginx/html
```

##6. Pod を削除する
Azure での PVC の拡張には PVC をどこからもマウントされていない状態にしなくてはなりません。

```shell-session
# kubectl describe pvc sample-pvc-resize-azure |grep Mount
Mounted By:  sample-pvc-resize-pod-azure
```

そのため、一度 Pod を削除します。 PVC がどこからもマウントされていないことが確認できるかと思います。

```shell-session
# kubectl delete -f ./sample-pvc-resize-pod-azure.yaml
pod "sample-pvc-resize-pod-azure" deleted
# kubectl describe pvc sample-pvc-resize-azure |grep Mount
Mounted By:  <none>
```

##7. PVC を編集する
以下のように PVC のサイズを変更します。

```shell-session
# kubectl patch pvc sample-pvc-resize-azure --patch '{"spec": {"resources": {"requests": {"storage": "16G"}}}}'
persistentvolumeclaim/sample-pvc-resize-azure patched
```

検証環境では PVC への反映には若干時間がかかったのですが、実体として PV のサイズはすぐに拡張が確認できました。CAPACITY が15 Gi になっているのがわかります。16G ではないのは 1G=1000M で 1Gi=1024Mi による差異だと思います。

```shell-session
# kubectl get pvc sample-pvc-resize-azure
NAME                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                       AGE
sample-pvc-resize-azure   Bound    pvc-292e15a1-220f-11e9-8174-ee11fdbb22d1   8Gi        RWO            sample-storageclass-resize-azure   6m
# kubectl get pv pvc-292e15a1-220f-11e9-8174-ee11fdbb22d1
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                             STORAGECLASS                       REASON   AGE
pvc-292e15a1-220f-11e9-8174-ee11fdbb22d1   15Gi       RWO            Delete           Bound    default/sample-pvc-resize-azure   sample-storageclass-resize-azure            6m
```

##8. Pod を再作成する
Pod を再作成します。PVC を使用しているのがわかります。

```shell-session
# kubectl apply -f sample-pvc-resize-pod-azure.yaml
pod/sample-pvc-resize-pod-azure created
# kubectl describe pvc sample-pvc-resize-azure | grep Mount
Mounted By:  sample-pvc-resize-pod-azure
```


##9. Pod にマウントされている PV のサイズを確認する
きちんと拡張できているのがわかります。PVC を見ても拡張されています。

```shell-session
# kubectl exec -it sample-pvc-resize-pod-azure -- df -h |grep nginx
/dev/sdc         15G   20M   15G   1% /usr/share/nginx/html
# kubectl get pvc sample-pvc-resize-azure
NAME                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                       AGE
sample-pvc-resize-azure   Bound    pvc-292e15a1-220f-11e9-8174-ee11fdbb22d1   15Gi       RWO            sample-storageclass-resize-azure   15m
```


# エラー時のメッセージ
Pod を削除しないで PVC のサイズを変更しようとすると、以下のように PVC でエラーメッセージが確認できます。

```shell-session
# kubectl describe pvc sample-pvc-resize-azure
###############################################
###中略
###############################################
Events:
  Type       Reason                 Age                From                         Message
  ----       ------                 ----               ----                         -------
  Normal     ProvisioningSucceeded  5m32s              persistentvolume-controller  Successfully provisioned volume pvc-b02dceae-2205-11e9-8174-ee11fdbb22d1 using kubernetes.io/azure-disk
  Warning    VolumeResizeFailed     36s (x2 over 90s)  volume_expand                Error expanding volume "default/sample-pvc-resize" of plugin kubernetes.io/azure-disk : compute.DisksClient#CreateOrUpdate: Failure sending request: StatusCode=409 -- Original Error: failed request: autorest/azure: Service returned an error. Status=<nil> Code="OperationNotAllowed" Message="Cannot resize disk kubernetes-dynamic-pvc-b02dceae-2205-11e9-8174-ee11fdbb22d1 while it is attached to running VM /subscriptions/xxxxxxxxxxx/resourceGroups/MC_aks-rg_testaks_japaneast/providers/Microsoft.Compute/virtualMachines/aks-agentpool-18627786-1."
```

# 参考
※ 使用しているyamlファイルのほとんどは 「[Kubernetes 完全ガイド (青山 真也)](http://amzn.asia/d/g5P72V5)」で使用されている [GitHub リポジトリ](https://github.com/MasayaAoyama/kubernetes-perfect-guide) を参考にさせて頂いております。