oomichi / try-kubernetes

12 stars 5 forks source link

あるDeploymentで利用していたPV/PVCを、Deployment削除後に別のDeploymentで直ぐに使えるようにしたい #90

Closed oomichi closed 5 years ago

oomichi commented 5 years ago

Reclaim Policy は Retain になっていた。

oomichi commented 5 years ago

手元の環境で再現させる

手元のOpenStack環境では以下のように Delete になっている。

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS        CLAIM                  STORAGECLASS   REASON   AGE
pvc-d65da5c7-8f1e-49c5-b14d-70ee66843f4a   1Gi        RWO            Delete           Terminating   default/cinder-claim   gold                    7m59s
pvc-e242949e-42e7-4758-a147-ed2002c5add8   1Gi        RWO            Delete           Bound         default/cinder-claim   gold                    3m5s

これだと、PVCが削除されたタイミングでPVも削除処理が走ってしまう。 まずは Retain に設定する方法を調べる。

https://kubernetes.io/docs/tasks/administer-cluster/change-pv-reclaim-policy/#why-change-reclaim-policy-of-a-persistentvolume に明記されている。

PV は異なる Reclaim policy を設定できる。Retain, Recycle, そして Delete だ。
Dynamically Provisioned PV においてデフォルトのポリシーは Delete だ。
これが意味するところは、ユーザが対応するPVCを削除したタイミングで自動的にDynamically provisioned PV が削除されることになる。
この自動的な振る舞いは、Volumeに貴重なデータが含まれる場合は不適切なものだろう。
その場合、Retain Policy を使うことが適切だ。Retain Policy ではユーザがPVCを削除してもPVは削除されない。
その代わり、PVはReleased フェーズに移行し、そのデータは主導でリカバーが可能となる。

PVのRetain Policy の変更方法

kubectl patch pv <your-pv-name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

やってみた

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS        CLAIM                  STORAGECLASS   REASON   AGE
pvc-e242949e-42e7-4758-a147-ed2002c5add8   1Gi        RWO            Delete           Bound         default/cinder-claim   gold                    43m
$ kubectl patch pv pvc-e242949e-42e7-4758-a147-ed2002c5add8 -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
persistentvolume/pvc-e242949e-42e7-4758-a147-ed2002c5add8 patched
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS        CLAIM                  STORAGECLASS   REASON   AGE
pvc-e242949e-42e7-4758-a147-ed2002c5add8   1Gi        RWO            Retain           Bound         default/cinder-claim   gold                    44m
$

対応するPVCを削除して、PVの状態を確認する。 → スグに Released になった。Claim が default/cinder-claim のままになっているのが気になる。 In the preceding output, you can see that the volume bound to claim default/claim3 has reclaim policy Retain. It will not be automatically deleted when a user deletes claim default/claim3 とあるので「Claim が default/cinder-claim のまま」なのは仕様。

$ kubectl delete pvc cinder-claim
persistentvolumeclaim "cinder-claim" deleted
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS        CLAIM                  STORAGECLASS   REASON   AGE
pvc-e242949e-42e7-4758-a147-ed2002c5add8   1Gi        RWO            Retain           Released      default/cinder-claim   gold                    45m
oomichi commented 5 years ago

Retain に変更

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS        CLAIM                  STORAGECLASS   REASON   AGE
pvc-ce9cbaae-93d0-483d-8e9f-1978ef538898   1Gi        RWO            Delete           Bound         default/cinder-claim   gold                    2m19s
$ kubectl patch pv pvc-ce9cbaae-93d0-483d-8e9f-1978ef538898 -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS        CLAIM                  STORAGECLASS   REASON   AGE
pvc-ce9cbaae-93d0-483d-8e9f-1978ef538898   1Gi        RWO            Retain           Bound         default/cinder-claim   gold                    3m12s

cinder-claim という名の PVC が存在

$ kubectl get pvc
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
cinder-claim   Bound    pvc-ce9cbaae-93d0-483d-8e9f-1978ef538898   1Gi        RWO            gold           3m52s

このPVCを使うDeploymentを作成

$ cat deployment.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: service
  labels:
    app: service
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: service
    spec:
      containers:
        - name: service
          image: nginx
          volumeMounts:
            - name: content
              mountPath: "/opt/datasets"
      volumes:
        - name: content
          persistentVolumeClaim:
            claimName: cinder-claim
$ kubectl create -f deployment.yaml
deployment.apps/service created
$ kubectl get deployment
NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
service             1/1     1            1           36s

PVCの状態を確認する → PVC視点では誰(Deployment, Podなど)によって使われているかはわからない?

$ kubectl get pvc
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
cinder-claim   Bound    pvc-ce9cbaae-93d0-483d-8e9f-1978ef538898   1Gi        RWO            gold           6m6s
$ kubectl describe pvc cinder-claim
Name:          cinder-claim
Namespace:     default
StorageClass:  gold
Status:        Bound
Volume:        pvc-ce9cbaae-93d0-483d-8e9f-1978ef538898
Labels:        <none>
Annotations:   cinderVolumeId: 3024179b-2c00-4a81-925f-9669e93460ed
               pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
               volume.beta.kubernetes.io/storage-provisioner: openstack.org/standalone-cinder
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      1Gi
Access Modes:  RWO
VolumeMode:    Filesystem
Mounted By:    service-8576dc7759-cpzdz
Events:
  Type    Reason                 Age                 From                                                                                                                 Message
  ----    ------                 ----                ----                                                                                                                 -------
  Normal  Provisioning           7m                  openstack.org/standalone-cinder_standalone-cinder-provisioner-857f85bb84-5fcz9_849181e1-5bd1-4ffc-b6d1-6d69a1419242  External provisioner is provisioning volume for claim "default/cinder-claim"
  Normal  ExternalProvisioning   6m52s (x3 over 7m)  persistentvolume-controller                                                                                          waiting for a volume to be created, either by external provisioner "openstack.org/standalone-cinder" or manually created by system administrator
  Normal  ProvisioningSucceeded  6m52s               openstack.org/standalone-cinder_standalone-cinder-provisioner-857f85bb84-5fcz9_849181e1-5bd1-4ffc-b6d1-6d69a1419242  Successfully provisioned volume pvc-ce9cbaae-93d0-483d-8e9f-1978ef538898
oomichi commented 5 years ago

このDeploymentを削除後に直ぐにDeploymentの再生成をして、問題が発生するか確認

12秒くらいでちゃんとDeploymentの再生成が成功し、問題が再現しなかった。

$ kubectl delete deployment/service
deployment.extensions "service" deleted
$ kubectl create -f deployment.yaml
deployment.apps/service created
$ kubectl get pods
NAME                                             READY   STATUS              RESTARTS   AGE
service-8576dc7759-xhr7c             0/1     ContainerCreating   0          3s
... (12秒くらい)
$ kubectl get pods
NAME                                             READY   STATUS    RESTARTS   AGE
service-8576dc7759-xhr7c             1/1     Running   0          32s
$ kubectl get deployment
NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
service             1/1     1            1           37s
oomichi commented 5 years ago

先週発生していた環境でも再現しなくなっていたため、ひとまずCloseする。