Gitea PVC 迁移方案(RWO → RWX / StorageClass 迁移)顺带解决Gitea SSH的clusterIP改为NodePort
场景说明
当前 Gitea 使用的 PVC:
- AccessMode:
ReadWriteOnce - StorageClass:
nfs-csi
现在需要迁移为:
- AccessMode:
ReadWriteMany - StorageClass:
nfs-client
由于 Kubernetes 的 PVC 以下字段创建后不可修改:
spec.accessModesspec.storageClassName
因此不能直接 helm upgrade 修改,只能通过:
创建新 PVC → 数据迁移 → 切换 Gitea 使用的新 PVC
来完成。
一、迁移目标
| 项目 | 旧 PVC | 新 PVC |
|---|---|---|
| PVC 名称 | gitea-shared-storage | gitea-shared-storage-nfs |
| AccessMode | RWO | RWX |
| StorageClass | nfs-csi | nfs-client |
二、迁移流程概览
停止 Gitea
↓
创建新 PVC
↓
创建迁移 Pod
↓
rsync 同步数据
↓
修改 Helm values 使用新 PVC
↓
删除冲突 Service
↓
Helm Upgrade
↓
验证数据
↓
清理旧 PVC
三、停止 Gitea
防止迁移过程中产生文件写入。
kubectl -n gitea scale deployment gitea --replicas=0
确认 Pod 已停止:
kubectl -n gitea get pod
四、创建新的 RWX PVC
1. 创建 PVC YAML
文件名:
gitea-new-pvc.yaml
内容:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gitea-shared-storage-nfs
namespace: gitea
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-csi
resources:
requests:
storage: 5Gi
2. 创建 PVC
kubectl apply -f gitea-new-pvc.yaml
3. 验证 PVC
kubectl -n gitea get pvc
应看到:
gitea-shared-storage-nfs Bound
五、创建数据迁移 Pod
1. 创建迁移 Pod YAML
文件名:
pvc-migrate.yaml
内容:
apiVersion: v1
kind: Pod
metadata:
name: pvc-migrate
namespace: gitea
spec:
restartPolicy: Never
containers:
- name: migrate
image: alpine:3.20
command:
- sh
- -c
- |
apk add --no-cache rsync
sleep 36000
volumeMounts:
- name: old
mountPath: /old
- name: new
mountPath: /new
volumes:
- name: old
persistentVolumeClaim:
claimName: gitea-shared-storage
- name: new
persistentVolumeClaim:
claimName: gitea-shared-storage-nfs
2. 创建迁移 Pod
kubectl apply -f pvc-migrate.yaml
3. 进入迁移 Pod
kubectl -n gitea exec -it pvc-migrate -- sh
六、迁移数据
推荐 rsync 命令
rsync -aH --numeric-ids --info=progress2 /old/ /new/
参数说明
| 参数 | 作用 |
|---|---|
| -a | 保留权限、时间、软链接 |
| -H | 保留硬链接 |
| --numeric-ids | 保留 UID/GID |
| --info=progress2 | 显示进度 |
查看数据大小
du -sh /old
du -sh /new
七、修改 Helm values
persistence:
enabled: true
existingClaim: gitea-shared-storage-nfs
八、处理 Helm ownership 问题
kubectl -n gitea label pvc gitea-shared-storage-nfs \
app.kubernetes.io/managed-by=Helm --overwrite
kubectl -n gitea annotate pvc gitea-shared-storage-nfs \
meta.helm.sh/release-name=gitea \
meta.helm.sh/release-namespace=gitea \
--overwrite
九、删除旧 SSH Service
kubectl -n gitea delete svc gitea-ssh
十、执行 Helm Upgrade
helm upgrade --install gitea gitea-charts/gitea \
-n gitea \
-f values.yaml
十一、启动 Gitea
kubectl -n gitea scale deployment gitea --replicas=1
十二、验证服务
查看日志
kubectl -n gitea logs -f deploy/gitea
生成SSH-KEY,并在Gitea后台添加ssh key的内容
ssh-keygen -t ed25519 -C "[email protected]"
chmod 0644 /root/.ssh/id_ed25519.pub
cat /root/.ssh/id_ed25519.pub # 手动添加到web后台的ssh页面
配置SSH别名
Host mygitea
HostName 192.168.31.30
Port 30022
User git
IdentityFile ~/.ssh/id_ed25519
测试 SSH
ssh -T mygitea
十三、清理迁移资源
kubectl -n gitea delete pod pvc-migrate
确认新 PVC 正常后:
kubectl -n gitea delete pvc gitea-shared-storage
十四、常见问题
PVC immutable
spec is immutable after creation
原因:
K8s 不允许修改:
- accessModes
- storageClassName
Helm ownership
exists and cannot be imported into the current release
解决:
补 Helm labels + annotations。
NodePort Service 冲突
clusterIP None may not be set to 'None'
解决:
删除旧 Service 后重新创建。