如何修改GKE上Strimzi Kafka集群的PV存储类并保留数据
我是Strimzi新手,想寻求相关建议。我们在GKE上通过Strimzi部署了Kafka集群,覆盖了包括生产环境在内的所有环境。当前Kafka的PVC配置如下:
kafka: template: pod: ..... storage: type: jbod volumes: - id: 0 type: persistent-claim size: {{ .Values.kafka.storageSize | quote }} deleteClaim: true
ZooKeeper的存储配置如下:
zookeeper: ... storage: type: persistent-claim size: {{ .Values.zookeeper.storageSize | quote }} deleteClaim: true
当前配置生成的PV使用默认存储类,其ReclaimPolicy为Delete,我需要将其改为ReclaimPolicy为Retain的自定义存储类,同时保留所有主题数据。我的问题是:应该执行哪些操作以及操作顺序是怎样的?因为直接通过.spec.storage.class修改存储类会导致PVC被释放、PV被删除。
由于直接修改Strimzi配置中的存储类会触发PVC重建(进而导致PV被删除、数据丢失),必须通过先保护现有数据、再迁移到新存储类的安全流程操作,具体步骤如下:
一、提前创建自定义存储类
先在GKE上创建ReclaimPolicy为Retain的自定义存储类,示例配置如下:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: retain-sc provisioner: kubernetes.io/gce-pd parameters: type: pd-standard reclaimPolicy: Retain volumeBindingMode: Immediate
执行创建并确认状态:
kubectl apply -f retain-sc.yaml kubectl get storageclasses
二、临时保护现有PV
把当前默认存储类生成的所有Kafka、ZooKeeper相关PV的ReclaimPolicy改为Retain,防止后续操作中意外删除数据:
- 列出集群内所有相关PVC:
kubectl get pvc -n <你的命名空间>
- 对每个PVC对应的PV,执行补丁修改:
# 替换<pv-name>为实际PV名称 kubectl patch pv <pv-name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
三、备份集群数据(生产环境必做)
1. ZooKeeper元数据备份
进入ZooKeeper pod执行备份:
# 停止单个ZooKeeper节点 kubectl exec -it <zookeeper-pod-name> -n <你的命名空间> -- zkServer.sh stop # 打包数据 kubectl exec -it <zookeeper-pod-name> -n <你的命名空间> -- tar -czf /tmp/zk-backup.tar.gz /var/lib/zookeeper/data # 复制到本地 kubectl cp <zookeeper-pod-name>:/tmp/zk-backup.tar.gz ./zk-backup.tar.gz -n <你的命名空间> # 重启节点 kubectl exec -it <zookeeper-pod-name> -n <你的命名空间> -- zkServer.sh start
2. Kafka主题数据备份(可选但推荐)
使用kafka-dump-log.sh工具备份关键主题,或通过Strimzi MirrorMaker创建临时镜像集群做数据冗余。
四、创建新PVC(绑定自定义存储类)
为每个Kafka broker和ZooKeeper节点创建新PVC,指定自定义存储类retain-sc:
Kafka JBOD PVC示例(每个broker对应一个):
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: kafka-0-retain-sc namespace: <你的命名空间> spec: accessModes: - ReadWriteOnce storageClassName: retain-sc resources: requests: storage: <原存储大小>
ZooKeeper PVC示例(每个节点对应一个):
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: zookeeper-0-retain-sc namespace: <你的命名空间> spec: accessModes: - ReadWriteOnce storageClassName: retain-sc resources: requests: storage: <原存储大小>
创建后确认PVC绑定成功:
kubectl get pvc -n <你的命名空间>
五、迁移数据到新PVC
逐个处理Kafka broker和ZooKeeper节点,确保数据完整迁移:
- 停止目标节点的pod:
# 以Kafka broker 0为例,缩容到0副本 kubectl patch statefulset <kafka-statefulset-name> -p '{"spec":{"replicas":0}}' -n <你的命名空间>
- 创建临时pod同时挂载原PVC和新PVC,复制数据:
# 创建临时休眠pod kubectl run data-copy-pod --image=busybox -n <你的命名空间> --command -- sleep 3600 # 挂载新旧PVC到临时pod kubectl patch pod data-copy-pod -n <你的命名空间> -p '{"spec":{"volumes":[{"name":"old-pvc","persistentVolumeClaim":{"claimName":"<原PVC名称>"}},{"name":"new-pvc","persistentVolumeClaim":{"claimName":"<新PVC名称>"}}],"containers":[{"name":"busybox","volumeMounts":[{"name":"old-pvc","mountPath":"/old"},{"name":"new-pvc","mountPath":"/new"}]}]}}' # 复制数据并校验完整性 kubectl exec -it data-copy-pod -n <你的命名空间> -- cp -r /old/. /new/ kubectl exec -it data-copy-pod -n <你的命名空间> -- diff -r /old /new # 删除临时pod kubectl delete pod data-copy-pod -n <你的命名空间>
- 启动该节点pod,确认运行正常后,再处理下一个节点。
六、更新Strimzi集群配置
修改Kafka和ZooKeeper的存储配置,指定自定义存储类,并恢复Operator的自动同步(如果之前暂停过):
Kafka配置更新:
kafka: template: pod: ..... storage: type: jbod volumes: - id: 0 type: persistent-claim size: {{ .Values.kafka.storageSize | quote }} deleteClaim: true class: retain-sc # 添加自定义存储类
ZooKeeper配置更新:
zookeeper: ... storage: type: persistent-claim size: {{ .Values.zookeeper.storageSize | quote }} deleteClaim: true class: retain-sc # 添加自定义存储类
应用配置变更:
kubectl apply -f <你的Kafka集群配置文件>
七、清理旧资源(可选)
确认集群完全稳定运行、数据无异常后,再删除旧的PVC和PV:
# 删除旧PVC kubectl delete pvc <旧PVC名称> -n <你的命名空间> # 删除旧PV(因已设为Retain,需手动删除) kubectl delete pv <旧PV名称>
内容的提问来源于stack exchange,提问作者Никита Петров

