Резервное копирование и восстановление GitLab с использованием Velero
В этом руководстве показано, как реализовать операции резервного копирования и восстановления GitLab с помощью Velero, инструмента с открытым исходным кодом для аварийного восстановления в облачных нативных средах.
Область применения
Данное решение применимо к экземплярам GitLab версии 17.8 и выше.
Данные GitLab состоят из трёх основных компонентов: база данных PostgreSQL, Git-репозитории и загруженные артефакты (включая аватары пользователей, вложения к комментариям и т.д.). Это решение поддерживает резервное копирование только Git-репозиториев и загруженных артефактов. Резервное копирование базы данных PostgreSQL требует отдельной процедуры в соответствии со стратегией резервного копирования вашего поставщика базы данных.
DANGER
Данное решение не поддерживает экземпляры GitLab, развернутые с использованием хранилища HostPath.
Терминология
Предварительные требования
- Развернуть MinIO Object Storage: Текущее решение резервного копирования и восстановления использует объектное хранилище для сохранения данных резервных копий, требуется предварительно развернутый экземпляр MinIO. ACP предоставляет
MinIO Object Storage для быстрого создания экземпляра MinIO.
- Развернуть Velero: Velero — инструмент для резервного копирования и восстановления. ACP предоставляет
Alauda Container Platform Data Backup for Velero, который можно развернуть во вкладке Administrator на странице Marketplace -> Cluster Plugins, найдите Velero и разверните.
- Установить утилиту командной строки mc: mc — это командная утилита MinIO для управления экземплярами MinIO. Инструкции по установке см. в официальной документации MinIO.
- Установить утилиту командной строки kubectl: kubectl — это командная утилита Kubernetes для управления кластерами Kubernetes. Инструкции по установке см. в официальной документации Kubernetes.
Для удобства последующих операций сначала задайте переменные окружения:
export MINIO_HOST=<адрес доступа к экземпляру MinIO> # Пример: http://192.168.1.100:32008
export MINIO_ACCESS_KEY=<ключ доступа к экземпляру MinIO> # Пример: minioadmin
export MINIO_SECRET_KEY=<секретный ключ экземпляра MinIO> # Пример: minioadminpassword
export MINIO_ALIAS_NAME=<псевдоним экземпляра MinIO> # Пример: myminio
export VELERO_BACKUP_BUCKET=<имя бакета для резервных копий Velero> # Пример: backup
export VELERO_BACKUP_REPO_NAME=<имя репозитория резервных копий Velero> # Пример: gitlab-backup-repo
export GITLAB_NAMESPACE=<пространство имён экземпляра GitLab для резервного копирования>
export GITLAB_NAME=<имя экземпляра GitLab для резервного копирования>
Выполните следующие команды для настройки утилиты mc и проверки подключения:
mc alias set ${MINIO_ALIAS_NAME} ${MINIO_HOST} ${MINIO_ACCESS_KEY} ${MINIO_SECRET_KEY}
mc ping ${MINIO_ALIAS_NAME}
# Вывод:
# 1: http://192.168.131.56:32571:32571 min=98.86ms max=98.86ms average=98.86ms errors=0 roundtrip=98.86ms
# 2: http://192.168.131.56:32571:32571 min=29.57ms max=98.86ms average=64.21ms errors=0 roundtrip=29.57ms
# 3: http://192.168.131.56:32571:32571 min=29.57ms max=98.86ms average=52.77ms errors=0 roundtrip=29.88ms
Если ping до экземпляра MinIO прошёл успешно, значит mc настроен корректно.
Резервное копирование
Подготовка
Подготовка к резервному копированию включает два шага:
- Создание бакета
- Настройка репозитория резервных копий Velero
Создание бакета
Выполните следующие команды для создания бакета для хранения данных резервных копий:
mc mb ${MINIO_ALIAS_NAME}/${VELERO_BACKUP_BUCKET}
# Вывод:
# Bucket created successfully `myminio/backup`.
Настройка репозитория резервных копий Velero
Выполните следующие команды для создания репозитория резервных копий Velero, который будет использоваться для хранения данных резервных копий:
gitlab_backup_repo_credentials_secret_name="gitlab-backup-repo-credentials"
minio_gitlab_backup_bucket="${VELERO_BACKUP_BUCKET:-backup}"
minio_gitlab_backup_bucket_directory="gitlab"
kubectl apply -f - <<EOF
apiVersion: v1
stringData:
cloud: |
[default]
aws_access_key_id = ${MINIO_ACCESS_KEY}
aws_secret_access_key = ${MINIO_SECRET_KEY}
kind: Secret
metadata:
labels:
component: velero
cpaas.io/backup-storage-location-repo: ${VELERO_BACKUP_REPO_NAME}
name: ${gitlab_backup_repo_credentials_secret_name}
namespace: cpaas-system
type: Opaque
---
apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
name: ${VELERO_BACKUP_REPO_NAME}
namespace: cpaas-system
spec:
config:
checksumAlgorithm: ""
insecureSkipTLSVerify: "true"
region: minio
s3ForcePathStyle: "true"
s3Url: ${MINIO_HOST}
credential:
key: cloud
name: ${gitlab_backup_repo_credentials_secret_name}
objectStorage:
bucket: ${minio_gitlab_backup_bucket}
prefix: ${minio_gitlab_backup_bucket_directory}
provider: aws
EOF
# Вывод
# secret/gitlab-backup-repo-credentials created
# backupstoragelocationrepo.ait.velero.io/gitlab-backup-repo created
Выполнение резервного копирования
Ручное резервное копирование состоит из шести шагов:
- Пометить ресурсы для резервного копирования
- Остановить сервисы GitLab
- Создать pod для резервного копирования
- Создать расписание резервного копирования
- Выполнить резервное копирование
- Восстановить сервисы GitLab
Пометить ресурсы для резервного копирования
Выполните следующий скрипт:
if [ -z "${GITLAB_NAMESPACE}" ] || [ -z "${GITLAB_NAME}" ]; then
cat <<EOF
Пожалуйста, задайте правильные namespace и имя экземпляра:
export GITLAB_NAME=<оригинальное имя экземпляра GitLab>
export GITLAB_NAMESPACE=<оригинальное имя namespace>
EOF
return
fi
kubectl label gitlabofficial -n ${GITLAB_NAMESPACE} ${GITLAB_NAME} release=${GITLAB_NAME} --overwrite
secrets_to_label=()
root_password_secret_name=$(kubectl get gitlabofficial -n ${GITLAB_NAMESPACE} ${GITLAB_NAME} -o jsonpath='{.spec.helmValues.global.initialRootPassword.secret}')
secrets_to_label+=(${root_password_secret_name})
rails_secret_name=$(kubectl get gitlabofficial -n ${GITLAB_NAMESPACE} ${GITLAB_NAME} -o jsonpath='{.spec.helmValues.global.railsSecrets.secret}')
if [ -n "${rails_secret_name}" ]; then
echo "Найден rails secret: ${rails_secret_name}"
secrets_to_label+=(${rails_secret_name})
fi
pg_connect_secret_name=$(kubectl get gitlabofficial -n ${GITLAB_NAMESPACE} ${GITLAB_NAME} -o jsonpath='{.spec.helmValues.global.psql.password.secret}')
secrets_to_label+=(${pg_connect_secret_name})
ingress_secret_name=$(kubectl get gitlabofficial -n ${GITLAB_NAMESPACE} ${GITLAB_NAME} -o jsonpath='{.spec.helmValues.global.ingress.tls.secretName}')
if [ -n "${ingress_secret_name}" ]; then
echo "Найден ingress secret: ${ingress_secret_name}"
secrets_to_label+=(${ingress_secret_name})
fi
redis_connect_secret_name=$(kubectl get gitlabofficial -n ${GITLAB_NAMESPACE} ${GITLAB_NAME} -o jsonpath='{.spec.helmValues.global.redis.auth.secret}')
if [ -n "${redis_connect_secret_name}" ]; then
echo "Найден redis auth secret: ${redis_connect_secret_name}"
secrets_to_label+=(${redis_connect_secret_name})
fi
redis_sentinel_connect_secret_name=$(kubectl get gitlabofficial -n ${GITLAB_NAMESPACE} ${GITLAB_NAME} -o jsonpath='{.spec.helmValues.global.redis.sentinelAuth.secret}')
if [ -n "${redis_sentinel_connect_secret_name}" ]; then
echo "Найден redis sentinel connect secret: ${redis_sentinel_connect_secret_name}"
secrets_to_label+=(${redis_sentinel_connect_secret_name})
fi
object_store_secret_name=$(kubectl get gitlabofficial -n ${GITLAB_NAMESPACE} ${GITLAB_NAME} -o jsonpath='{.spec.helmValues.global.appConfig.object_store.connection.secret}')
if [ -n "${object_store_secret_name}" ]; then
echo "Найден secret подключения к объектному хранилищу: ${object_store_secret_name}"
kubectl label secret ${object_store_secret_name} -n ${GITLAB_NAMESPACE} release=${GITLAB_NAME}
fi
for secret_name in "${secrets_to_label[@]}"; do
echo "Добавление метки к secret: ${secret_name}"
kubectl label secret ${secret_name} -n ${GITLAB_NAMESPACE} release=${GITLAB_NAME} --overwrite
done
kubectl get pvc -n ${GITLAB_NAMESPACE} --no-headers | grep ${GITLAB_NAME} | awk '{print $1}' | xargs -I {} kubectl label pvc {} release=${GITLAB_NAME} -n ${GITLAB_NAMESPACE}
kubectl get secret -n ${GITLAB_NAMESPACE} --no-headers | grep ${GITLAB_NAME} | awk '{print $1}' | xargs -I {} kubectl label secret {} release=${GITLAB_NAME} -n ${GITLAB_NAMESPACE}
# Вывод:
# secret/sh.helm.release.v1.xxx-gitlab.v9 не помечен
Если необходимо резервировать дополнительные ресурсы, см. раздел Пометка дополнительных ресурсов для резервного копирования.
Остановить сервисы GitLab
Во время резервного копирования все компоненты GitLab должны быть остановлены:
kubectl annotate statefulset -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME} skip-sync="true"
kubectl scale statefulset -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME} --replicas=0
kubectl annotate deployment -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME} skip-sync="true"
kubectl scale deployment -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME} --replicas=0
kubectl delete pod -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME} --ignore-not-found
# Вывод:
# statefulset.apps/xxxx-gitlab-gitaly annotated
# deployment.apps/xxxx-gitlab-webservice-default annotated
# deployment.apps/xxxx-gitlab-toolbox scaled
# deployment.apps/xxxx-gitlab-webservice-default scaled
Создать pod для резервного копирования
На этом шаге создаётся pod, который монтирует PVC GitLab, чтобы Velero мог выполнить резервное копирование данных PVC.
image=''
if [ -z "${IMAGE}" ]; then
image=$(kubectl get deployment -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME},app=gitlab-shell -o jsonpath='{range .items[0].spec.template.spec.containers[]}{.image}{"\n"}{end}' | head -n1)
fi
PVC_NAMES=($(kubectl get pvc -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME} -o jsonpath='{range .items[*]}{.metadata.name}{" "}{end}'))
VOLUME_MOUNTS=""
VOLUMES=""
INDEX=0
for pvc in ${PVC_NAMES[@]}; do
VOLUME_MOUNTS="${VOLUME_MOUNTS}
- name: data-${INDEX}
mountPath: /mnt/data-${INDEX}"
VOLUMES="${VOLUMES}
- name: data-${INDEX}
persistentVolumeClaim:
claimName: ${pvc}"
INDEX=$((INDEX+1))
done
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: ${GITLAB_NAME}-backup-pod
namespace: ${GITLAB_NAMESPACE}
labels:
release: ${GITLAB_NAME}
spec:
containers:
- name: backup
image: ${image}
command: ["/bin/sh", "-c", "sleep 86400"]
resources:
limits:
cpu: 1
memory: 1Gi
volumeMounts:${VOLUME_MOUNTS}
volumes:${VOLUMES}
restartPolicy: Never
EOF
kubectl wait --for=condition=ready pod -n ${GITLAB_NAMESPACE} ${GITLAB_NAME}-backup-pod
# Вывод
# pod/xxxx-gitlab-backup-pod created
# pod/xxxx-gitlab-backup-pod condition met
Создать политику резервного копирования томов
Политика томов используется для указания метода резервного копирования PVC. По умолчанию используется метод fs-backup.
export BACKUP_POLICY_NAME=${BACKUP_POLICY_NAME:-gitlab-backup}
export VELERO_BACKUP_REPO_NAME=${VELERO_BACKUP_REPO_NAME:-backup}
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: ${BACKUP_POLICY_NAME}-volume-policy
namespace: cpaas-system
data:
resourcepolicies: |
version: v1
volumePolicies:
- conditions:
csi: {}
action:
type: fs-backup
- conditions:
csi: {}
action:
type: fs-backup
EOF
# Вывод
# configmap/gitlab-backup-volume-policy created
Если PVC поддерживает snapshot, можно использовать snapshot для резервного копирования PVC, чтобы ускорить процесс. Для этого необходимо изменить ConfigMap политики томов, указав, что класс хранилища использует snapshot для резервного копирования. Например, если класс хранилища ceph поддерживает snapshot, добавьте следующую конфигурацию (добавленное условие должно быть размещено в начале для более высокого приоритета):
Как определить, поддерживает ли PVC snapshot?
WARNING
Если вы используете резервное копирование PVC через snapshot, при восстановлении нельзя менять класс хранилища. Пожалуйста, корректируйте класс хранилища в соответствии с фактической ситуацией.
apiVersion: v1
kind: ConfigMap
metadata:
name: ${BACKUP_POLICY_NAME}-volume-policy
namespace: cpaas-system
data:
resourcepolicies: |
version: v1
volumePolicies:
+ - conditions:
+ storageClass:
+ - ceph
+ action:
+ type: snapshot
- conditions:
csi: {}
action:
type: fs-backup
- conditions:
csi: {}
action:
type: fs-backup
WARNING
Если Velero не включён с поддержкой CSI snapshot, при резервном копировании вы получите ошибку:
Skip action velero.io/csi-pvc-backupper for resource persistentvolumeclaims:xxx, because the CSI feature is not enabled.
Для исправления необходимо добавить параметр --features=EnableCSI в развертывание Velero.
apiVersion: apps/v1
kind: Deployment
metadata:
name: velero
spec:
template:
spec:
containers:
- args:
- server
- --uploader-type=restic
+ - --features=EnableCSI
- --namespace=cpaas-system
command:
- /velero
name: velero
Выполнить резервное копирование
Выполните следующую команду для создания расписания резервного копирования и запуска задания резервного копирования:
export BACKUP_POLICY_NAME=${BACKUP_POLICY_NAME:-gitlab-backup}
export VELERO_BACKUP_REPO_NAME=${VELERO_BACKUP_REPO_NAME:-backup}
kubectl apply -f - <<EOF
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: ${BACKUP_POLICY_NAME}
namespace: cpaas-system
spec:
schedule: '@every 876000h'
template:
defaultVolumesToFsBackup: true
hooks: {}
includedNamespaces:
- ${GITLAB_NAMESPACE}
includedResources:
- '*'
resourcePolicy:
kind: configmap
name: ${BACKUP_POLICY_NAME}-volume-policy
orLabelSelectors:
- matchLabels:
release: ${GITLAB_NAME}
storageLocation: ${VELERO_BACKUP_REPO_NAME}
ttl: 720h0m0s
EOF
kubectl create -f - <<EOF
apiVersion: velero.io/v1
kind: Backup
metadata:
labels:
velero.io/schedule-name: ${BACKUP_POLICY_NAME}
velero.io/storage-location: ${VELERO_BACKUP_REPO_NAME}
generateName: ${BACKUP_POLICY_NAME}-
namespace: cpaas-system
spec:
csiSnapshotTimeout: 10m0s
defaultVolumesToFsBackup: true
includedNamespaces:
- ${GITLAB_NAMESPACE}
includedResources:
- "*"
itemOperationTimeout: 4h0m0s
resourcePolicy:
kind: configmap
name: ${BACKUP_POLICY_NAME}-volume-policy
orLabelSelectors:
- matchLabels:
release: ${GITLAB_NAME}
snapshotMoveData: false
storageLocation: ${VELERO_BACKUP_REPO_NAME}
ttl: 720h0m0s
EOF
# Вывод
# schedule.velero.io/gitlab-backup created
# backup.velero.io/gitlab-backup-r6hht created
Просмотр логов резервного копирования:
kubectl logs -f -n cpaas-system -l app.kubernetes.io/instance=velero | grep gitlab-backup
# Вывод
# time="2025-07-01T07:29:54Z" level=info msg="PodVolumeBackup completed" controller=PodVolumeBackup logSource="pkg/controller/pod_volume_backup_controller.go:244" pvb=gitlab-backup-xxx-q7prc
Проверьте статус задачи. Если статус Completed, резервное копирование прошло успешно.
kubectl get backup -n cpaas-system -o jsonpath="{range .items[*]}{.metadata.name}{'\t'}{.status.phase}{'\t'}{.status.startTimestamp}{'\n'}{end}"
# Вывод
# Completed
Восстановить сервисы GitLab
Удалите pod резервного копирования и восстановите все компоненты GitLab.
kubectl delete pod -n ${GITLAB_NAMESPACE} ${GITLAB_NAME}-backup-pod
kubectl annotate statefulset -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME} skip-sync-
kubectl scale statefulset -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME} --replicas=1
kubectl annotate deployment -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME} skip-sync-
kubectl scale deployment -n ${GITLAB_NAMESPACE} -l release=${GITLAB_NAME} --replicas=1
После восстановления всех компонентов зайдите в экземпляр GitLab и убедитесь, что он работает нормально.
Восстановление
Подготовка
Подготовка к восстановлению включает четыре шага:
- Восстановление базы данных PostgreSQL (опционально)
- Выбор резервной копии для восстановления
- Определение целевого namespace для восстановления
- Удаление Gitlab CE Operator
Восстановление базы данных PostgreSQL (опционально)
Если новый экземпляр будет использовать тот же экземпляр и базу данных PostgreSQL, восстанавливать базу данных PostgreSQL не нужно.
Если новый экземпляр будет использовать другой экземпляр или базу данных PostgreSQL, необходимо сначала восстановить базу данных PostgreSQL. Обратитесь к документации вашего поставщика PostgreSQL по резервному копированию и восстановлению.
Выбор данных резервной копии для восстановления
Выполните следующую команду для просмотра списка успешных записей резервного копирования и выберите нужную по времени начала.
kubectl get backup -n cpaas-system -o jsonpath="{range .items[*]}{.metadata.name}{'\t'}{.status.phase}{'\t'}{.status.startTimestamp}{'\n'}{end}" | grep Completed
# Вывод:
# gitlab-backup-xxx Completed 2025-07-01T07:29:19Z
Задайте переменную окружения BACKUP_NAME:
export BACKUP_NAME=<имя выбранной записи резервного копирования>
Определение целевого namespace
Рекомендуется восстанавливать экземпляр в новое пространство имён. Задайте следующие переменные окружения:
export NEW_GITLAB_NAMESPACE=<имя нового namespace>
kubectl create namespace ${NEW_GITLAB_NAMESPACE}
Удаление Gitlab CE Operator
Выполните следующую команду для удаления оператора GitLab CE:
kubectl get subscription --all-namespaces | grep gitlab-ce-operator | awk '{print "kubectl delete subscription "$2" -n "$1}' | sh
# Вывод:
# subscription.operators.coreos.com "gitlab-ce-operator" deleted
Почему нужно удалять оператор GitLab?
Во время восстановления Velero запускает pod для восстановления данных в PVC, что занимает некоторое время. Если оператор не удалить, могут возникнуть следующие проблемы:
- Оператор может пересоздать ресурсы workloads на основе GitLab CR, из-за чего восстановленные pod перезапустятся или пересоздадутся, что приведёт к прерыванию или сбою восстановления.
- Некоторые восстановленные ресурсы могут конфликтовать, например ingress ресурсы, созданные оператором на основе восстановленного GitLab CR, могут конфликтовать со старыми ingress ресурсами.
Влияние удаления оператора GitLab CE
Если оператор удалён, изменения в ресурсе GitLab CR не будут применяться, например, изменение ресурсов или размера хранилища.
Удаление оператора не приведёт к сбоям в работе существующих экземпляров.
Операции восстановления
Операции восстановления состоят из пяти шагов:
- Создание конфигурационного файла восстановления
- Создание задачи восстановления
- Очистка ресурсов
- Изменение ресурса GitLab CR
- Развёртывание Gitlab CE Operator
Создание конфигурационного файла восстановления
Внимательно прочитайте комментарии в YAML и внесите изменения согласно вашей ситуации (например, изменение класса хранилища), затем создайте изменённый YAML.
# Если необходимо изменить класс хранилища, задайте две переменные окружения
OLD_STORAGECLASS_NAME='' # Оригинальное имя класса хранилища
NEW_STORAGECLASS_NAME='' # Новое имя класса хранилища
if [ -n "${OLD_STORAGECLASS_NAME}" ] && [ -n "${NEW_STORAGECLASS_NAME}" ] && [ ${NEW_STORAGECLASS_NAME} != ${OLD_STORAGECLASS_NAME} ]; then
kubectl apply -f - <<EOF
apiVersion: v1
data:
resourcemodifier: |
version: v1
resourceModifierRules:
- conditions:
groupResource: persistentvolumeclaims
resourceNameRegex: .*
namespaces:
- "*"
patches: &a1
- operation: test
path: /spec/storageClassName
value: ${OLD_STORAGECLASS_NAME}
- operation: replace
path: /spec/storageClassName
value: ${NEW_STORAGECLASS_NAME}
- conditions:
groupResource: persistentvolume
resourceNameRegex: .*
namespaces:
- "*"
patches: *a1
- conditions:
groupResource: persistentvolumeclaims
resourceNameRegex: .*
namespaces:
- "*"
patches:
- operation: test
path: "/metadata/annotations/meta.helm.sh~1release-namespace"
value: ${GITLAB_NAMESPACE}
- operation: replace
path: "/metadata/annotations/meta.helm.sh~1release-namespace"
value: ${NEW_GITLAB_NAMESPACE}
kind: ConfigMap
metadata:
labels:
component: velero
name: gitlab-restore-modifier
namespace: cpaas-system
EOF
else
kubectl apply -f - <<EOF
apiVersion: v1
data:
resourcemodifier: |
version: v1
resourceModifierRules:
- conditions:
groupResource: persistentvolumeclaims
resourceNameRegex: .*
namespaces:
- "*"
patches:
- operation: test
path: "/metadata/annotations/meta.helm.sh~1release-namespace"
value: ${GITLAB_NAMESPACE}
- operation: replace
path: "/metadata/annotations/meta.helm.sh~1release-namespace"
value: ${NEW_GITLAB_NAMESPACE}
kind: ConfigMap
metadata:
labels:
component: velero
name: gitlab-restore-modifier
namespace: cpaas-system
EOF
fi
Создание задачи восстановления
Выполните следующую команду для создания задачи восстановления:
kubectl create -f - <<EOF
apiVersion: velero.io/v1
kind: Restore
metadata:
generateName: ${GITLAB_NAME}-restore-
namespace: cpaas-system
spec:
backupName: ${BACKUP_NAME}
hooks: {}
includedNamespaces:
- ${GITLAB_NAMESPACE}
includedResources:
- persistentvolumeclaims
- persistentvolumes
- secrets
- pods
- gitlabofficials.operator.alaudadevops.io
- volumesnapshots
- volumesnapshotcontents
itemOperationTimeout: 10h0m0s
namespaceMapping:
${GITLAB_NAMESPACE}: ${NEW_GITLAB_NAMESPACE}
resourceModifier:
kind: configmap
name: gitlab-restore-modifier
EOF
Просмотр логов восстановления:
kubectl logs -f -n cpaas-system -l app.kubernetes.io/instance=velero | grep gitlab-restore
# Вывод
# time="2025-07-01T08:01:41Z" level=info msg="Async fs restore data path completed" PVR=xxxx-gitlab-restore-mv6l5-sc4pk controller=PodVolumeRestore logSource="pkg/controller/pod_volume_restore_controller.go:275" pvr=xxxx-gitlab-restore-mv6l5-sc4pk
# time="2025-07-01T08:01:41Z" level=info msg="Restore completed" controller=PodVolumeRestore logSource="pkg/controller/pod_volume_restore_controller.go:327" pvr=xxxx-gitlab-restore-mv6l5-sc4pk
Проверьте статус задачи. Если статус Completed, восстановление прошло успешно.
kubectl get restore -n cpaas-system -o jsonpath="{range .items[*]}{.metadata.name}{'\t'}{.status.phase}{'\t'}{.status.startTimestamp}{'\n'}{end}"
# Вывод
# xxx-gitlab-restore-xxx InProgress 2025-07-01T10:18:17Z
Очистка ресурсов
Убедитесь, что операция восстановления завершена, прежде чем продолжить!
Выполните следующие команды для очистки ресурсов.
kubectl get pod -n ${NEW_GITLAB_NAMESPACE} | grep ${GITLAB_NAME} | awk '{print $1}' | xargs kubectl delete pod -n ${NEW_GITLAB_NAMESPACE}
kubectl get secret -n ${NEW_GITLAB_NAMESPACE} | grep sh.helm.release.v1.${GITLAB_NAME} | awk '{print $1}' | xargs kubectl delete secret -n ${NEW_GITLAB_NAMESPACE}
Изменение ресурса GitLab CR
kubectl edit gitlabofficial ${GITLAB_NAME} -n ${NEW_GITLAB_NAMESPACE}
В новом ресурсе CR экземпляра могут потребоваться следующие изменения. Пожалуйста, внесите корректировки в соответствии с вашей ситуацией.
- Доменное имя:
- Сценарий применения: исходный экземпляр был развернут с использованием доменного имени
- Причина изменения: одинаковые доменные имена в ingress ресурсах, созданных старым и новым экземплярами, вызовут конфликты и приведут к сбою создания ingress ресурсов нового экземпляра
- Рекомендации по изменению:
- (Рекомендуется) Изменить домен исходного экземпляра на временный, оставить домен нового экземпляра без изменений
- Оставить домен исходного экземпляра без изменений, изменить домен нового экземпляра на новый
- Как изменить: см. Настройка сетевого доступа к экземпляру для изменения доменного имени доступа к экземпляру.
- NodePort:
- Сценарий применения: исходный экземпляр был развернут с использованием NodePort
- Причина изменения: одинаковые NodePort в сервисах, созданных старым и новым экземплярами, вызовут конфликты и приведут к сбою создания сервисов нового экземпляра
- Рекомендации по изменению:
- (Рекомендуется) Изменить NodePort исходного экземпляра на временный, оставить NodePort нового экземпляра без изменений
- Оставить NodePort исходного экземпляра без изменений, изменить NodePort нового экземпляра на новый
- Как изменить: см. Настройка сетевого доступа к экземпляру для изменения конфигурации доступа к экземпляру.
- Класс хранилища:
- Сценарий применения: исходный экземпляр был развернут с классом хранилища, и между старым и новым экземплярами изменился класс хранилища (например, старый использовал NFS, новый — Ceph)
- Причина изменения: если не изменить, оператор будет использовать старый класс хранилища для создания PVC, что вызовет конфликт с восстановленными PVC
- Рекомендация по изменению: изменить класс хранилища на корректный
- Как изменить: см. Настройка хранилища экземпляра для изменения конфигурации хранилища экземпляра.
- Информация для подключения к PostgreSQL:
- Сценарий применения: новый экземпляр и старый планируют использовать разные экземпляры или базы данных PostgreSQL
- Причина изменения: если не изменить, новый экземпляр будет подключаться к старому экземпляру или базе данных PostgreSQL
- Рекомендация по изменению: изменить информацию подключения к PostgreSQL на корректные значения
- Как изменить: см. Настройка конфигурации учётных данных доступа к PostgreSQL для изменения конфигурации доступа к PostgreSQL.
Развёртывание Gitlab CE Operator
Перейдите во вкладку Administrator, откройте страницу Marketplace -> OperatorHub и повторно разверните оператор Alauda Build of Gitlab.
После развертывания оператора он создаст новый экземпляр согласно GitLab CR. Вы можете отслеживать прогресс развертывания на странице деталей экземпляра.
После того, как статус экземпляра вернётся в норму, войдите в GitLab и проверьте успешность восстановления данных. Проверяемые элементы включают, но не ограничиваются:
- Группы
- Репозитории
- Пользователи
- Merge Requests
Вопросы и ответы
Пометка дополнительных ресурсов для резервного копирования
Этот шаг необязателен. Если в том же namespace есть другие ресурсы, которые вы хотите резервировать вместе, можно добавить метку release к соответствующим ресурсам. Значение метки должно быть именем исходного экземпляра GitLab, например:
metadata:
labels:
release: gitlab-g6zd4
Как определить, поддерживает ли PVC snapshot?
Чтобы определить, поддерживает ли PVC snapshot, необходимо проверить, поддерживает ли его базовый StorageClass функцию snapshot. PVC поддерживает snapshot, если в кластере существует VolumeSnapshotClass, у которого поле driver совпадает с provisioner StorageClass. Если такой VolumeSnapshotClass есть, значит StorageClass (и, следовательно, PVC) поддерживает snapshot.
Пример конфигурации:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ceph
provisioner: rook-ceph.cephfs.csi.ceph.com
parameters:
clusterID: rook-ceph
csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner
csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
fsName: cephfs
pool: cephfs-data0
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true
---
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: csi-cephfs-snapshotclass
deletionPolicy: Delete
driver: rook-ceph.cephfs.csi.ceph.com
parameters:
clusterID: rook-ceph
csi.storage.k8s.io/snapshotter-secret-name: rook-csi-cephfs-provisioner
csi.storage.k8s.io/snapshotter-secret-namespace: rook-ceph
Ключевые моменты:
provisioner StorageClass должен точно совпадать с driver VolumeSnapshotClass
- Оба ресурса должны существовать в кластере
- CSI драйвер должен поддерживать операции snapshot