跨 StorageClass 迁移 PVC 数据
之前部署服务时 PVC 使用的 StorageClass 为 local-path,现在为了服务高可用需要切换到 longhorn,所以需要对现有使用 local-path 作为 StorageClass 的 PVC 做数据迁移
经过评估下面这种方式最合适,并且有下面优点:
- 操作简便,相比能想到的其他方法,这是最简便的了
- 理论上可以支持所有的 StorageClass,因为迁移数据时只需要将老PVC和新PVC挂载到同一个迁移Pod中即可
- 可以保留旧 PVC 数据,方便回滚
缺点:
- 需要停服,有时甚至需要删除 StatefulSet(删除之前需要提前备份 yaml,如果使用的是 Helm 也应当有所备份)
- 虽然这已经是想到的最简单的方法,但是整体过程还是较为麻烦,不够自动化,当需要迁移的 PVC 较多的情况下,这个过程将会比较耗时,还有可能由于人为因素造成问题,如果只是部署时没有使用正确的 StorageClass,没有产生业务数据的情况下,那倒不如直接删除重新部署来的方便
总而言之,这是一个可供参考的方法,实际操作的话建议综合评估再选择
准备测试 Pod
创建一个 StatefulSet,运行 1 个 MySQL Pod 副本,通过volumeClaimTemplates为 Pod 副本创建 PVC 并挂载,使用的 StorageClass 为local-path
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-pvc-test
namespace: test
spec:
serviceName: mysql-pvc-test
replicas: 1
selector:
matchLabels:
app: mysql
persistentVolumeClaimRetentionPolicy:
whenDeleted: Retain
whenScaled: Retain
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: swr.cn-east-3.myhuaweicloud.com/r4in/bitnami/mysql:8.0.34
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
- name: ALLOW_EMPTY_PASSWORD
value: "no"
ports:
- containerPort: 3306
name: mysql
protocol: TCP
volumeMounts:
- name: data
mountPath: /bitnami/mysql/data
subPath: mysql
volumeClaimTemplates:
- metadata:
name: data
labels:
app: mysql
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 20Gi
查看 Pod,PVC
kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
mysql-pvc-test-0 1/1 Running 0 20s
kubectl get pvc -n test
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
data-mysql-pvc-test-0 Bound pvc-d40a13bd-3f3d-4640-b9de-c874ea8012e6 20Gi RWO local-path <unset> 26s
创造数据,在 MySQL Pod 中创建个数据库aaa
kubectl exec -it -n test mysql-pvc-test-0 -- mysql -uroot -p123456 -e 'create database aaa; show databases;'
创建新的 PVC
新建 PVC,指定StorageClass为longhorn,PVC名称为是在旧 PVC 名前加上了longhorn-前缀,名称为longhorn-data-mysql-pvc-test-0
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
labels:
app: mysql
name: longhorn-data-mysql-pvc-test-0
namespace: test
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: longhorn
查看 PVC
kubectl get pvc -n test
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
data-mysql-pvc-test-0 Bound pvc-a1aca789-6130-4e26-8aac-1f15dac54bc0 20Gi RWO local-path <unset> 94s
longhorn-data-mysql-pvc-test-0 Bound pvc-b6296cf3-2540-4c49-95af-85d93dcf316c 20Gi RWO longhorn <unset> 8s
创建 Rsync Pod 迁移数据
步骤1:MySQL StatefulSet 副本调为0
kubectl scale statefulset mysql-pvc-test -n test --replicas 0
步骤2:创建数据迁移 Pod
apiVersion: v1
kind: Pod
metadata:
name: data-mysql-pvc-test-0-migrate
namespace: test
spec:
restartPolicy: Never
containers:
- name: sync-data
image: swr.cn-east-3.myhuaweicloud.com/r4in/eeacms/rsync:2.9
command:
- sh
- -c
- |
rsync -avh --progress --delete /old-data/ /new-data && \
ls -rlth /new-data && \
du -sh /new-data
volumeMounts:
- name: old-volume
mountPath: /old-data
- name: new-volume
mountPath: /new-data
volumes:
- name: old-volume
persistentVolumeClaim:
claimName: data-mysql-pvc-test-0
- name: new-volume
persistentVolumeClaim:
claimName: longhorn-data-mysql-pvc-test-0
查看迁移 Pod
# 查看 Pod
kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
data-mysql-pvc-test-0-migrate 0/1 Completed 0 38s
# 查看日志
kubectl logs -f -n test data-mysql-pvc-test-0-migrate
sending incremental file list
deleting lost+found/
./
mysql/
mysql/#ib_16384_0.dblwr
196.61K 100% 156.25MB/s 0:00:00 (xfr#1, to-chk=175/178)
(...省略...)
mysql/sys/sys_config.ibd
114.69K 100% 203.64kB/s 0:00:00 (xfr#170, to-chk=0/178)
sent 191.87M bytes received 3.30K bytes 127.92M bytes/sec
total size is 191.81M speedup is 1.00
total 4K
drwxrwxrwx 8 root root 4.0K Nov 8 09:45 mysql
183.2M /new-data
恢复 Pod
数据迁移到新的 PVC 之后就可以修改 StatefulSet 中的 PVC 相关的字段名称然后重新启动 MySQL Pod
由于 StatefulSet 不支持修改volumeClaimTemplates字段,所以不能直接通过kubectl edit等方式来直接修改现有的 StatefulSet 中volumeClaimTemplates,就需要先删除之前的 StatefulSet,然后修改里面的volumeClaimTemplates再重新创建 StatefulSet,由于之前已经将数据同步到了新的 PVC,所以重新创建之后数据还在
如果没有通过
volumeClaimTemplates的方式来创建 PVC,使用 Deployment 运行 Pod 并直接使用已存在的 PVC,则可以直接修改volumes中的使用的 PVC 的名称,步骤会简单一些
步骤1:删除旧 MySQL StatefulSet
kubectl delete sts -n test mysql-pvc-test
步骤2:修改 MySQL StatefulSet yaml 文件并重新创建
- 修改
spec.volumeClaimTemplates.metadata.name为longhorn-data(增加了longhorn-前缀,与之前手动创建的 PVC 名称添加的longhorn-前缀对应) - 修改
spec.template.spec.containers.volumeMounts.name为longhorn-data(与上面的对应) - 修改
spec.volumeClaimTemplates.spec.storageClassName为longhorn
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-pvc-test
namespace: test
spec:
serviceName: mysql-pvc-test
replicas: 1
selector:
matchLabels:
app: mysql
persistentVolumeClaimRetentionPolicy:
whenDeleted: Retain
whenScaled: Retain
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: swr.cn-east-3.myhuaweicloud.com/r4in/bitnami/mysql:8.0.34
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
- name: ALLOW_EMPTY_PASSWORD
value: "no"
ports:
- containerPort: 3306
name: mysql
protocol: TCP
volumeMounts:
- name: longhorn-data
mountPath: /bitnami/mysql/data
subPath: mysql
volumeClaimTemplates:
- metadata:
name: longhorn-data
labels:
app: mysql
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 20Gi
待 MySQL Pod 启动之后检查数据,之前创建的aaa数据库还在
kubectl exec -it -n test mysql-pvc-test-0 -- mysql -uroot -p123456 -e 'show databases;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database |
+--------------------+
| aaa |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+