..

记录:给 ECK 更换 PV

1. 背景

当时部署 ECK 的时候,不知道哪根筋不对,选择了 AWS 上非常慢的 st1 磁盘。导致后续使用的时候,ECK 服务经常 Timeout。实在忍不了,于是想着更换更快的 gp2

另外,原先设想会横向对比好几天的日志的需求,于是分配的磁盘空间是 256G。现在感觉,实际最多显示 3 天(集群每天产生大约 12 G 的日志)即可,所以趁着这次顺便把磁盘空间调小。

2. 操作过程

整体操作过程是:

  1. 备份原有磁盘。在 AWS 上找到原来 PV 对应的 EBS Volumen,打一个快照即可。
  2. 新建一个 gp2 磁盘。保持跟原来的磁盘在同一个 Availability Zone。
  3. 同步数据。如果磁盘空间不变,在步骤 2 的时候就选择可以以步骤 1 的快照作为新磁盘的数据源。但是我们这次是缩容磁盘,所以选择

2.1 备份原有磁盘

这个操作比较简单,就在 AWS 上找到原来 PV 对应的 EBS Volumen,打一个快照即可。

2.2 新建 gp2 磁盘

新建一个 gp2 磁盘。保持跟原来的磁盘在同一个 Availability Zone。如果磁盘空间不变,在步骤 2 的时候就选择可以以步骤 1 的快照作为新磁盘的数据源。但是,本次更换还伴随有磁盘缩容,所以不能这么做。

新建完之后,在 infra repo 里新建对应的 PV 与 PVC,并且 apply 到集群上:

---  
kind: PersistentVolume  
apiVersion: v1  
metadata:  
  name: eck-stack-es-pv-2  
spec:  
  storageClassName: gp2  
  persistentVolumeReclaimPolicy: Retain  
  accessModes:  
    - ReadWriteOnce  
  capacity:  
    storage: 126Gi  
  awsElasticBlockStore:  
    fsType: ext4  
    volumeID: vol-xxxxxxxxx  
---  
kind: PersistentVolumeClaim  
apiVersion: v1  
metadata:  
  name: eck-stack-es-pvc-2  
  namespace: logging  
spec:  
  accessModes:  
    - ReadWriteOnce  
  storageClassName: gp2  
  resources:  
    requests:  
      storage: 126Gi  
  volumeName: eck-stack-es-pv-2

2.3 同步数据

由于日志都有一份 s3 备份,为了让数据同步快一点,我删除了今天以外的所有日志。

修改 deployment,把新磁盘也挂载到服务上。

...
containers:  
...
    volumeMounts:  
      - mountPath: /usr/share/elasticsearch/data  
        name: es-data  
        subPath: ./es-data  
      - mountPath: /mnt/es-data-backup  
        name: es-data-2  
        subPath: ./es-data  
...
volumes:  
  - name: es-data  
    persistentVolumeClaim:  
      claimName: {{ .Values.persistent.existPVC }}  
  - name: es-data-2  
    persistentVolumeClaim:  
      claimName: "eck-stack-es-pvc-2"

然后通过 kubectl exec 命令,登录到 pod 上直接通过 cp 命令进行数据同步。

2.4 替换旧磁盘

数据同步后。再次修改 deployment,把新磁盘直接替换成旧磁盘即可。检查一下服务是否恢复!

2.5 清理

依次移除旧的 PVC 与 PV:

$ kubectl -n logging delete pvc/eck-stack-es-pvc
persistentvolumeclaim "eck-stack-es-pvc" deleted
$ kubectl delete pv/eck-stack-es-pv
persistentvolume "eck-stack-es-pv" deleted

原有的 PV & PVC 的 YAML文件,加个 backup 后缀,并且在文件头写明移除原因、快照 ID。

最后,在 AWS 上把对应的 ELB Volume 删除。

3. 遇到的事故

3.1 原因

由于当时的 PVC 声明的 Access Modes 是 ReadWriteOnce,并且我是粗暴的改了原来的 deployment.yaml 文件,然后通过 helm upgrade 进行更新的。这就导致新 Pod 一直分配不到旧的磁盘(因为旧 Pod 依然占用着),而无法启动。

3.2 解决

这个小插曲最后造成的麻烦是,deployment 卡了一大堆 ReplicaSet,新 Pod 也一直无法部署上去。不知道为什么,通过 kubectl describe 命令查看了 deployment 跟 pod,都没有看到什么有用的信息。

于是我选择同步粗暴的 helm unisntall 然后再重装。虽然最后服务回来了,但是感觉这算是一次运维事故。

3.3 总结

合理一点的做法是,应该停掉原有的服务。比如 scale replica 到 0。然后再通过 helm upgrade。因为日志都有备份,这个 ECK 服务只是用来查看,所以停掉一会完全没事。

服务先停掉,这样在同步数据的时候也不容易把数据同步坏掉。虽然本次没有出现数据同步问题。