记录:给 ECK 更换 PV
1. 背景
当时部署 ECK 的时候,不知道哪根筋不对,选择了 AWS 上非常慢的 st1 磁盘。导致后续使用的时候,ECK 服务经常 Timeout。实在忍不了,于是想着更换更快的 gp2。
另外,原先设想会横向对比好几天的日志的需求,于是分配的磁盘空间是 256G。现在感觉,实际最多显示 3 天(集群每天产生大约 12 G 的日志)即可,所以趁着这次顺便把磁盘空间调小。
2. 操作过程
整体操作过程是:
- 备份原有磁盘。在 AWS 上找到原来 PV 对应的 EBS Volumen,打一个快照即可。
- 新建一个 gp2 磁盘。保持跟原来的磁盘在同一个 Availability Zone。
- 同步数据。如果磁盘空间不变,在步骤 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 服务只是用来查看,所以停掉一会完全没事。
服务先停掉,这样在同步数据的时候也不容易把数据同步坏掉。虽然本次没有出现数据同步问题。