Backup & Restore — Kubernetes On-Premise
Server Backup chính: MinIO server cài trên 1 Ubuntu server riêng. Tất cả dự liệu toàn bộ hệ thống sẽ được backup về đây có IP 10.128.48.222 có domain tương ứng là http://backup-center.giangit.com.Trong trường hợp không có dns server nội bội thì có thể sử dụng trực tiếp IP thay vì domain
Server Backup phụ : Bổ sung thêm 1 MinIO server cài trên 1 Ubuntu server làm replication cho server backup chính . Dữ liệu backup chính sẽ được replication 1 chiều sang backup phụ có IP 10.128.48.223
Lưu ý: MinIO sẽ cài trực tiếp, không cài đặt bằng docker để tăng hiệu năng. Velero cài vào trong cụm k8s dưới dạng pod
Kiến trúc & phạm vi backup
Điểm quan trọng nhất cần nắm trước khi đọc runbook này: không phải mọi thành phần đều chạy trong cluster Kubernetes. Một số dịch vụ được cài trực tiếp trên các server Ubuntu riêng biệt (không phải pod K8s), nên Velero không backup được chúng — phải backup bằng cron + đẩy thẳng lên MinIO qua mc (MinIO Client) trên từng server đó.
Chạy trong cluster Kubernetes (backup qua Velero + Longhorn)
- Control-plane (3 node) + etcd
- Worker (3 node)
- ArgoCD (namespace
argocd) - cert-manager (namespace
cert-manager) - Grafana / Prometheus / Loki (namespace
monitoring) — cài trực tiếp vào cụm - Toàn bộ ứng dụng do ArgoCD deploy, dữ liệu trên Longhorn/NFS
Chạy ngoài cluster — mỗi thành phần 1 server Ubuntu riêng (backup bằng cron + mc cp thẳng lên MinIO, không qua Velero)
- LB API (HAProxy cho control-plane) — 1 server
- LB External (HAProxy cho worker + ingress) — 1 server
- Harbor — 1 server
- GitLab Runner (Kubernetes executor) — 1 server (runner agent chạy ở đây, job build thực thi bằng pod bên trong cluster)
- MinIO backup server (chính) — 1 server riêng (
10.128.48.222) - MinIO backup server (phụ) — 1 server riêng (
10.128.48.223), nhận replication 1 chiều từ MinIO chính qua Bucket Replication (mục 1.5)
Máy quản trị (Admin CLI) — 10.128.48.207
admin có 1 máy Ubuntu riêng dùng để quản trị cụm bằng CLI, kết nối tới control-plane qua LB API (không SSH trực tiếp vào từng control-plane để chạy kubectl). Vì máy này chỉ nói chuyện với cluster qua kubeconfig → LB API, không phải mọi lệnh trong runbook đều chạy tập trung được từ đây — chỉ những lệnh thuần kubectl/velero/mc (không cần chứng chỉ hay file cục bộ chỉ có trên 1 server cụ thể) mới centralize được. Từ mục 2 trở đi, mỗi phần đều có ghi rõ dòng "Chạy ở đâu" để admin biết lệnh nào gõ được ngay trên 10.128.48.207, và lệnh nào bắt buộc phải chạy (hoặc SSH vào) đúng server đích.
Tóm tắt nhanh:
| Nhóm lệnh | Có centralize từ máy quản trị được không? |
|---|---|
kubectl (mọi loại: get/apply/describe...) |
✅ Có — chỉ cần kubeconfig trỏ VIP của LB API |
velero (install/schedule/backup/restore) |
✅ Có — Velero CLI dùng chung kubeconfig với kubectl |
mc (thao tác với MinIO) |
✅ Có — chỉ cần cài mc + network tới 10.128.48.222:9000, không phụ thuộc node nào |
etcdctl snapshot save/restore |
❌ Không — cần chứng chỉ etcd cục bộ, chỉ có sẵn trên từng control-plane node |
gitlab-backup, docker exec (Harbor) |
❌ Không — chỉ chạy được trên đúng server cài GitLab/Harbor đó |
Backup config HAProxy/GitLab Runner (tar czf /etc/...) |
❌ Không — phải chạy trên đúng server đó vì đọc file cục bộ |
Lưu ý: LB API và LB External vẫn chỉ có 1 instance duy nhất nên thêm keepalived + 1 server dự phòng cho mỗi loại LB nếu ngân sách cho phép, chúng quan trọng ngang etcd. Riêng MinIO đã bớt là SPOF tuyệt đối nhờ quyết định triển khai Replication sang MinIO phụ ở mục 1.5 — miễn là quá trình replication luôn chạy đúng và được kiểm tra định kỳ (mục 12).
ArgoCD hiện chỉ cài UI, không cài ArgoCD CLI — các bước backup/restore ArgoCD dưới đây dùng kubectl thuần thay vì argocd admin export/import.
StorageClass trong cluster chỉ gồm Longhorn và NFS.
0. Nguyên tắc trước khi bắt đầu
- Chiến lược backup tập trung on-premise: toàn bộ backup gom về 1 điểm — MinIO server
10.128.48.222— và không đẩy bản sao ra cloud/off-site. Đây là lựa chọn có đánh đổi thật: nguyên tắc 3-2-1 kinh điển (3 bản sao, 2 loại lưu trữ, 1 bản off-site) khuyến nghị luôn có ít nhất 1 bản ở địa điểm khác để chống rủi ro mất cả cluster lẫn backup cùng lúc (cháy phòng máy, ngập nước, mất điện diện rộng...).Runbook này tập trung vào việc làm cho bản backup on-premise duy nhất đó đáng tin cậy nhất có thể — đã có RAID 6 ở tầng đĩa (mục 1.1), và có thêm các bước nâng cấp dự phòng ở tầng server/site tại mục 1.5 nếu muốn giảm rủi ro hơn nữa mà vẫn không cần dùng cloud. - Backup ứng dụng-nhất-quán (application-consistent) khác với snapshot volume thô. Snapshot lúc GitLab/Harbor đang ghi dữ liệu có thể tạo ra bản backup restore lên bị lỗi database. GitLab và Harbor có quy trình backup riêng ở mục 5, 6.
- Test restore định kỳ. Một backup chưa từng được restore thử là một backup chưa được xác minh.
- Tách quyền truy cập MinIO theo từng loại backup — dùng access key/secret key riêng cho từng nhóm (Velero, etcd, GitLab, Harbor, infra-config) thay vì dùng chung 1 root credential cho mọi thứ.
1. Chuẩn bị MinIO server làm kho backup
1.1. Cài đặt MinIO trực tiếp trên Ubuntu server (10.128.48.222)
Đã có RAID 6 cho phần đĩa chứa dữ liệu MinIO. RAID 6 dùng 2 khối chẵn-lẻ (double parity) nên chịu được 2 ổ đĩa hỏng đồng thời mà không mất dữ liệu — đây là lớp bảo vệ ở tầng đĩa vật lý, độc lập với MinIO. Toàn bộ hướng dẫn dưới đây coi /mnt/minio-data là điểm mount của RAID 6 đó (mount point cụ thể tuỳ chỉnh theo cấu hình RAID ra thiết bị nào, ví dụ /dev/md0 với mdadm hoặc virtual disk của RAID controller phần cứng).
# Tạo user và thư mục dữ liệu riêng cho MinIO
useradd -r minio-user -s /sbin/nologin
mkdir -p /mnt/minio-data
chown minio-user:minio-user /mnt/minio-data
# Tải binary MinIO server chính thức
wget https://dl.min.io/server/minio/release/linux-amd64/minio -O /usr/local/bin/minio
chmod +x /usr/local/bin/minio
chown minio-user:minio-user /usr/local/bin/minio
# File biến môi trường
cat <<ENV_EOF > /etc/default/minio
MINIO_VOLUMES="/mnt/minio-data"
MINIO_OPTS="--address :9000 --console-address :9001"
MINIO_ROOT_USER=backup-admin
MINIO_ROOT_PASSWORD=<mật-khẩu-mạnh>
ENV_EOF
chmod 600 /etc/default/minio
# Systemd service
cat <<SERVICE_EOF > /etc/systemd/system/minio.service
[Unit]
Description=MinIO Object Storage
After=network-online.target
Wants=network-online.target
[Service]
User=minio-user
Group=minio-user
EnvironmentFile=/etc/default/minio
ExecStart=/usr/local/bin/minio server \$MINIO_VOLUMES \$MINIO_OPTS
Restart=always
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
SERVICE_EOF
systemctl daemon-reload
systemctl enable --now minio
systemctl status minio
Console quản trị truy cập qua: http://backup-center.giangit.com:9001
1.2. Cài mc (MinIO Client) trên tất cả server cần đẩy backup lên
Chạy trên: control-plane (etcd), server GitLab, server Harbor, server LB API, server LB External, server GitLab Runner, bao gồm bất kỳ máy nào dùng để chạy lệnh restore và máy quản trị
wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /usr/local/bin/mc
chmod +x /usr/local/bin/mc
# Đăng ký alias trỏ tới MinIO server backup
mc alias set backupminio http://10.128.48.222:9000 backup-admin '<mật-khẩu-mạnh>'
mc admin info backupminio # kiểm tra kết nối thành công
1.3. Tạo các bucket riêng theo từng loại backup
Chạy các lệnh dưới 1 lần duy nhất trên máy quản trị 10.128.48.207 để tạo các bucket lưu trữ backup cho từng loại.
mc mb backupminio/etcd-backup
mc mb backupminio/longhorn-backup
mc mb backupminio/velero
mc mb backupminio/gitlab-backup
mc mb backupminio/harbor-backup
mc mb backupminio/infra-config-backup
mc ls backupminio
1.4. (Khuyến nghị) Tạo access key riêng theo từng mục đích thay vì dùng chung root
Cũng là thao tác làm 1 lần duy nhất, trên máy quản trị 10.128.48.207. Sau khi tạo xong, các access key này mới được đưa vào file cấu hình/credentials trên từng server tương ứng (control-plane dùng cho etcd, server GitLab/Harbor/LB/Runner dùng cho phần của mình) ở các mục 2-9 phía sau.
mc admin user add backupminio velero-svc '<mật-khẩu-riêng>'
mc admin policy attach backupminio readwrite --user velero-svc
# Lặp lại tương tự cho etcd-svc, gitlab-svc, harbor-svc, infra-svc nếu muốn tách quyền chi tiết hơn
1.5. Tăng độ dự phòng cho MinIO — triển khai Replication MinIO server)
Thông tin hạ tầng đã xác nhận: MinIO phụ đặt tại 10.128.48.223, cũng dùng RAID 6 giống MinIO chính (mục 1.1). Cả 2 server đều có 2 PSU cắm vào 2 UPS online riêng biệt, và UPS có ắc-quy ngoài đủ thời gian chờ máy phát điện của toà nhà khởi động khi mất điện lưới — đây là mức bảo vệ nguồn điện khá tốt, giảm đáng kể khả năng mất điện đột ngột làm hỏng dữ liệu đang ghi hoặc gây corrupt filesystem giữa lúc ghi RAID.
Bước 1 — Cài MinIO trên server phụ (10.128.48.223), làm giống hoàn toàn mục 1.1 (binary + systemd), chỉ khác IP/hostname — ổ đĩa cũng đã có RAID 6 sẵn nên không cần cấu hình thêm gì ở tầng đĩa. Có thể dùng MINIO_ROOT_USER/MINIO_ROOT_PASSWORD khác với MinIO chính nếu muốn, chỉ cần nhất quán với alias mc sẽ đăng ký ở Bước 2.
Bước 2 — Đăng ký alias và bật replication (chạy trên MinIO chính, hoặc từ máy quản trị 10.128.48.207 nếu đã cài mc + có alias backupminio trỏ tới MinIO chính):
# Đăng ký alias tới MinIO phụ
mc alias set backupminio2 http://10.128.48.223:9000 backup-admin '<mật-khẩu-minio-phụ>'
mc admin info backupminio2 # xác nhận kết nối được tới MinIO phụ trước khi tiếp tục
# Bật versioning (bắt buộc phải có trước khi bật replication) cho từng bucket cần nhân bản
mc version enable backupminio/etcd-backup
mc version enable backupminio2/etcd-backup
# Tạo replication rule 1 chiều: mọi thay đổi trên bucket chính tự động đồng bộ sang bucket phụ
mc replicate add backupminio/etcd-backup \
--remote-bucket http://backup-admin:'<mật-khẩu-minio-phụ>'@10.128.48.223:9000/etcd-backup
Lặp lại Bước 2 (bật versioning + tạo replication rule) cho từng bucket còn lại: longhorn-backup, velero, gitlab-backup, harbor-backup, infra-config-backup.
Bước 3 — Kiểm chứng replication đang hoạt động:
# Xem trạng thái/thống kê replication của 1 bucket
mc replicate status backupminio/etcd-backup
# Kiểm chứng thực tế: tạo 1 file test trên bucket chính, đợi vài giây, kiểm tra đã có ở MinIO phụ chưa
echo "test-replication" > /tmp/test-replication.txt
mc cp /tmp/test-replication.txt backupminio/etcd-backup/
sleep 5
mc ls backupminio2/etcd-backup/ # phải thấy file test-replication.txt xuất hiện ở đây
mc rm backupminio/etcd-backup/test-replication.txt backupminio2/etcd-backup/test-replication.txt # dọn file test
Với Replication server đã triển khai: dù server MinIO chính bị phá huỷ hoàn toàn, dữ liệu vẫn còn nguyên trên MinIO phụ — cập nhật lại quy trình restore (mục 2-9) để trỏ mc alias/kubeconfig sang MinIO phụ (backupminio2) trong trường hợp MinIO chính không còn khả dụng.
2. Backup & Restore etcd (quan trọng nhất)
Chạy ở đâu: chạy trực tiếp trên (hoặc SSH vào) từng control-plane node.
2.0. Kiểm tra & cài đặt etcdctl (etcd-client) trước khi backup
Gói etcd-client chưa chắc được cài sẵn theo mặc định trên mọi control-plane node (tuỳ cách dựng cluster bằng kubeadm) — kiểm tra trước khi chạy bước 2.1, tránh script cron fail âm thầm vì thiếu binary.
# Chạy trên TỪNG control-plane node
which etcdctl
# Nếu không thấy thông tin output thì tiến hành cài đặt thủ công
apt update && apt install -y etcd-client
# Xác nhận version, và xác nhận etcdctl gọi được vào etcd cục bộ
etcdctl version
ETCDCTL_API=3 etcdctl endpoint health \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
2.1. Script backup (chạy trên từng control-plane node + cron)
#!/bin/bash
# /usr/local/bin/backup-etcd.sh
set -e
DATE=$(date +%F-%H%M)
SNAPSHOT_DIR=/opt/etcd-backup
mkdir -p $SNAPSHOT_DIR
ETCDCTL_API=3 etcdctl snapshot save $SNAPSHOT_DIR/etcd-snapshot-$DATE.db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
# Đẩy thẳng lên MinIO qua mc (không cần mount gì cả)
mc cp $SNAPSHOT_DIR/etcd-snapshot-$DATE.db backupminio/etcd-backup/$(hostname)/
# Giữ 7 bản gần nhất tại local, retention dài hạn xử lý bằng lifecycle rule trên bucket (mục 2.3)
ls -1t $SNAPSHOT_DIR/etcd-snapshot-*.db | tail -n +8 | xargs -r rm --
Cron mỗi 6 giờ:
crontab -e
0 */6 * * * /usr/local/bin/backup-etcd.sh >> /var/log/backup-etcd.log 2>&1
2.2. Restore etcd
Chỉ thực hiện khi thật sự cần thiết — restore etcd đưa cluster về đúng thời điểm chụp snapshot.
# Tải snapshot cần restore về từ MinIO
mc cp backupminio/etcd-backup/<node>/etcd-snapshot-<ngày>.db /opt/etcd-backup/restore.db
mv /etc/kubernetes/manifests/etcd.yaml /tmp/
mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/
ETCDCTL_API=3 etcdctl snapshot restore /opt/etcd-backup/restore.db \
--name <tên-node> \
--initial-cluster <node1>=https://<ip1>:2380,<node2>=https://<ip2>:2380,<node3>=https://<ip3>:2380 \
--initial-cluster-token etcd-cluster-restore \
--initial-advertise-peer-urls https://<ip-node-hiện-tại>:2380 \
--data-dir /var/lib/etcd-restore
mv /tmp/etcd.yaml /etc/kubernetes/manifests/
mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/
kubectl get nodes
kubectl get pods -A
Lưu ý: phải restore đồng thời trên cả 3 control-plane node với cùng 1 snapshot, đổi tên data-dir để tránh nhầm dữ liệu cũ.
2.3. Lifecycle rule tự dọn snapshot cũ trên MinIO (thay cho việc tự xoá thủ công)
mc ilm rule add backupminio/etcd-backup --expire-days 30
3. Velero — backup resource Kubernetes + dữ liệu Volume
Chạy ở đâu: Trên máy quản trị.
Velero backup (a) manifest/resource (ArgoCD Application, cert-manager Certificate, ConfigMap, Secret...) và (b) dữ liệu PV qua node-agent (Kopia/Restic) — hoạt động đồng nhất cho cả Longhorn và NFS.
3.0. Cài đặt Velero CLI trên máy quản trị
# Chạy trên máy quản trị 10.128.48.207 (link download: https://github.com/velero-io/velero/releases/tag/v1.18.2)
wget https://github.com/velero-io/velero/releases/download/v1.18.2/velero-v1.18.2-linux-amd64.tar.gz
tar -xzf velero-v1.18.2-linux-amd64.tar.gz
sudo cp velero-v1.18.2-linux-amd64/velero /usr/local/bin/
sudo chmod +x /usr/local/bin/velero
# Xác nhận cài đặt thành công (client-only vì chưa install Velero vào cluster ở bước 3.1)
velero version --client-only
3.1. Cài đặt Velero vào cluster
Tạo file credential cho Velero trước khi chạy lệnh install, vì velero install cần đọc file này ngay khi chạy (credentials-velero):
# File: credentials-velero
[default]
aws_access_key_id = velero-svc
aws_secret_access_key = <mật-khẩu-riêng-của-velero-svc>
Sau khi đã có file credentials-velero cùng thư mục, chạy:
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.9.0 \
--bucket velero \
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://10.128.48.222:9000 \
--secret-file ./credentials-velero \
--use-node-agent \
--default-volumes-to-fs-backup
3.2. Lịch backup định kỳ
# Backup toàn cluster mỗi ngày, giữ 14 ngày
velero schedule create daily-full \
--schedule="0 1 * * *" \
--ttl 336h0m0s
# Backup riêng các namespace quan trọng trong cluster (GitLab/Harbor KHÔNG có ở đây vì chạy ngoài cluster)
velero schedule create hourly-critical-ns \
--schedule="0 * * * *" \
--include-namespaces argocd,cert-manager,monitoring \
--ttl 72h0m0s
Kiểm chứng ngay bằng 1 bản backup thử (không cần chờ tới giờ chạy theo schedule):
# Tạo backup thủ công ngay lập tức, --wait để đứng chờ tới khi xong luôn
velero backup create test-backup --include-namespaces argocd --wait
# Kiểm tra kết quả — Phase phải là "Completed"
velero backup describe test-backup --details
# Nếu Phase là "PartiallyFailed" hoặc "Failed", xem log chi tiết để biết lỗi ở đâu
velero backup logs test-backup
# Sau khi xác nhận ổn, có thể xoá bản test này (không xoá dữ liệu gốc trong cluster, chỉ xoá bản backup)
velero backup delete test-backup --confirm
3.3. Restore
velero backup get
velero restore create --from-backup daily-full-20250101010000
velero restore create --from-backup daily-full-20250101010000 --include-namespaces monitoring
velero restore describe <tên-restore>
velero restore logs <tên-restore>
4. Longhorn — backup native qua S3 (MinIO)
Chạy ở đâu: Trên máy quản trị. Riêng việc thao tác qua giao diện Longhorn UI là qua trình duyệt.
4.1. Tạo Secret chứa thông tin kết nối MinIO cho Longhorn
kubectl create secret generic minio-secret \
--from-literal=AWS_ACCESS_KEY_ID=backup-admin \
--from-literal=AWS_SECRET_ACCESS_KEY='<mật-khẩu-mạnh>' \
--from-literal=AWS_ENDPOINTS=http://10.128.48.222:9000 \
-n longhorn-system
4.2. Cấu hình Backup Target
Cách 1 — qua Longhorn UI (đơn giản nhất, khuyến nghị cho hầu hết trường hợp):
Longhorn UI → Backup and Restore → Backup Targets → Create Backup Target:
s3://longhorn-backup@us-east-1/
(region us-east-1 chỉ là placeholder bắt buộc phải điền, MinIO không thật sự dùng khái niệm region — không cần tạo region gì thêm)
Ở mục Backup Target Credential Secret, chọn secret minio-secret vừa tạo.
Cách 2 — qua YAML (nếu quản lý hạ tầng theo GitOps, tương đương Cách 1):
kubectl apply -f - <<EOF
apiVersion: longhorn.io/v1beta2
kind: BackupTarget
metadata:
name: default
namespace: longhorn-system
spec:
backupTargetURL: s3://longhorn-backup@us-east-1/
credentialSecret: minio-secret
pollInterval: 5m0s
EOF
4.3. Recurring Backup Job — hướng dẫn tạo chi tiết
Có 3 cách tương đương để tạo, chọn cách phù hợp với quy trình vận hành theo thực tế:
Cách 1 — kubectl apply file YAML (khuyến nghị, dễ đưa vào Git để version control):
# Lưu nội dung dưới đây vào file recurring-job-daily-backup.yaml, rồi:
kubectl apply -f recurring-job-daily-backup.yaml
apiVersion: longhorn.io/v1beta2
kind: RecurringJob
metadata:
name: daily-backup
namespace: longhorn-system
spec:
cron: "30 1 * * *"
task: "backup"
groups:
- default
retain: 14
concurrency: 2
Sau khi apply, xác nhận job đã được tạo:
kubectl get recurringjobs.longhorn.io -n longhorn-system
Cách 2 — qua Longhorn UI:
Vào Longhorn UI → Recurring Job → Create Recurring Job, điền các trường tương ứng 1:1 với YAML ở trên (Name: daily-backup, Task: backup, Cron: 30 1 * * *, Groups: default, Retain: 14, Concurrency: 2) → OK. Longhorn tự tạo object RecurringJob giống hệt Cách 1 phía sau, chỉ khác cách nhập.
Bước cuối — gắn volume cần backup vào group default (làm bằng UI dù chọn cách nào ở trên, vì đây là thao tác theo từng volume): Longhorn UI → Volume → bấm chọn vào tên volume → Tìm mục Recurring Job Schedule → Add → Existing → Recurring Job Name → Chọn Recurring Jobs.
4.4. Restore volume Longhorn
Longhorn UI → Backup tab → chọn bản backup → Restore Latest Backup → gắn PVC mới, hoặc:
kubectl apply -f - <<EOF
apiVersion: longhorn.io/v1beta2
kind: Volume
metadata:
name: restored-vol
namespace: longhorn-system
spec:
fromBackup: "s3://longhorn-backup@us-east-1/?backup=<backup-id>"
size: "20Gi"
numberOfReplicas: 3
EOF
Khuyến nghị dùng Longhorn UI thay vì CLI khi đang xử lý sự cố — ít rủi ro gõ sai tham số.
5. GitLab — server Ubuntu riêng (KHÔNG chạy trong K8s)
Chạy ở đâu: Chạy trên (SSH vào) GitLab server.
5.1. Backup
# Chạy trực tiếp trên server Ubuntu cài GitLab
gitlab-backup create
# Backup kèm gitlab-secrets.json và gitlab.rb — KHÔNG nằm trong gitlab-backup create,
# nhưng bắt buộc phải có để restore đúng (chứa khoá mã hoá CI variables, 2FA...)
mkdir -p /root/gitlab-config-backup
cp /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab.rb /root/gitlab-config-backup/
# Đẩy thẳng lên MinIO (đã cài mc + alias backupminio ở mục 1.2)
mc cp /var/opt/gitlab/backups/*.tar backupminio/gitlab-backup/
mc cp --recursive /root/gitlab-config-backup/ backupminio/gitlab-backup/config/
Cron trên server GitLab:
crontab -e
0 2 * * * /usr/bin/gitlab-backup create CRON=1 && mc cp /var/opt/gitlab/backups/*.tar backupminio/gitlab-backup/ >> /var/log/gitlab-backup.log 2>&1
5.2. Restore
# Tải file backup cần restore về từ MinIO
mc cp backupminio/gitlab-backup/<file>_gitlab_backup.tar /var/opt/gitlab/backups/
chown git:git /var/opt/gitlab/backups/<file>_gitlab_backup.tar
gitlab-ctl stop puma
gitlab-ctl stop sidekiq
gitlab-backup restore BACKUP=<timestamp>
# Nếu restore lên server mới hoàn toàn, phục hồi thêm 2 file cấu hình đã backup:
mc cp backupminio/gitlab-backup/config/gitlab-secrets.json /etc/gitlab/
mc cp backupminio/gitlab-backup/config/gitlab.rb /etc/gitlab/
gitlab-ctl reconfigure
gitlab-ctl restart
gitlab-rake gitlab:check SANITIZE=true
Quan trọng: phiên bản GitLab lúc restore phải khớp đúng với phiên bản lúc backup.
6. Harbor — server Ubuntu riêng (KHÔNG chạy trong K8s)
Chạy ở đâu: Trên (hoặc SSH vào) server Harbor.
Harbor cài bằng docker-compose (theo installer chính thức) trên 1 server Ubuntu riêng.
6.1. Backup
cd /opt/harbor # thay bằng đường dẫn cài đặt Harbor thực tế
# Dừng tạm để backup nhất quán data volume
docker compose stop
DATE=$(date +%F)
tar czf /tmp/harbor-data-$DATE.tar.gz /data # /data = data_volume khai báo trong harbor.yml
docker compose start
# Backup DB riêng — có thể chạy khi Harbor vẫn đang hoạt động (ít downtime hơn tar toàn bộ /data)
docker exec harbor-db pg_dumpall -U postgres > /tmp/harbor-db-$DATE.sql
# (kiểm tra đúng tên container bằng: docker ps | grep harbor)
mc cp /tmp/harbor-data-$DATE.tar.gz backupminio/harbor-backup/
mc cp /tmp/harbor-db-$DATE.sql backupminio/harbor-backup/
Cron trên server Harbor:
crontab -e
0 3 * * * /usr/local/bin/backup-harbor.sh >> /var/log/harbor-backup.log 2>&1
6.2. Restore
cd /opt/harbor
docker compose stop
mc cp backupminio/harbor-backup/harbor-data-<ngày>.tar.gz /tmp/
tar xzf /tmp/harbor-data-<ngày>.tar.gz -C /
docker compose up -d harbor-db
mc cp backupminio/harbor-backup/harbor-db-<ngày>.sql /tmp/
cat /tmp/harbor-db-<ngày>.sql | docker exec -i harbor-db psql -U postgres
docker compose start
7. ArgoCD — chỉ có UI, backup bằng kubectl thuần
Chạy ở đâu: Từ máy quản trị 10.128.48.207 — toàn bộ mục 7 chỉ dùng kubectl, không cần SSH vào node hay server nào.
Vì dùng GitOps — cài lại ArgoCD trỏ đúng repo cũ là Application tự đồng bộ lại. Nhưng nên backup thêm để không phải cấu hình lại repo credentials/RBAC/SSO từ đầu.
7.1. Backup (không cần ArgoCD CLI)
NS=argocd
DATE=$(date +%F)
OUTDIR=/tmp/argocd-backup-$DATE
mkdir -p $OUTDIR
for res in applications applicationsets appprojects; do
kubectl get $res -n $NS -o yaml > $OUTDIR/$res.yaml
done
kubectl get configmap argocd-cm argocd-rbac-cm argocd-cmd-params-cm -n $NS -o yaml > $OUTDIR/configmaps.yaml
# Secret chứa repo credentials, SSO config — dữ liệu nhạy cảm, giữ quyền truy cập chặt trên MinIO
kubectl get secret -n $NS -o yaml > $OUTDIR/secrets.yaml
tar czf argocd-backup-$DATE.tar.gz -C /tmp argocd-backup-$DATE
mc cp argocd-backup-$DATE.tar.gz backupminio/infra-config-backup/argocd/
Namespace argocd cũng nằm trong lịch Velero hourly-critical-ns (mục 3.2) như lớp dự phòng thứ hai — tự động, không cần chạy tay.
7.2. Restore
mc cp backupminio/infra-config-backup/argocd/argocd-backup-<ngày>.tar.gz .
tar xzf argocd-backup-<ngày>.tar.gz
kubectl apply -f argocd-backup-<ngày>/configmaps.yaml
kubectl apply -f argocd-backup-<ngày>/secrets.yaml
kubectl apply -f argocd-backup-<ngày>/appprojects.yaml
kubectl apply -f argocd-backup-<ngày>/applications.yaml
kubectl apply -f argocd-backup-<ngày>/applicationsets.yaml
8. Grafana / Prometheus / Loki (cài trực tiếp trong cluster)
| Thành phần | Có cần backup nghiêm ngặt? | Cách xử lý |
|---|---|---|
| Grafana dashboards/datasources | Có — nếu không quản lý bằng code | Nên chuyển sang provisioning qua ConfigMap/GitOps. Nếu chưa, backup DB Grafana qua Velero namespace monitoring. |
| Prometheus TSDB | Thường KHÔNG cần — dữ liệu vận hành | Có thể bỏ qua, hoặc backup nếu compliance yêu cầu giữ lâu dài. |
| Loki logs | Tuỳ yêu cầu compliance/audit | Loki vốn đã hỗ trợ dùng S3-compatible object storage làm backend — có thể trỏ thẳng Loki vào chính MinIO server này (bucket riêng, ví dụ loki-chunks) thay vì cần job backup riêng. |
Vì cả 3 nằm trong namespace monitoring bên trong cluster, lịch Velero hourly-critical-ns (mục 3.2) đã tự động bao phủ phần config/dashboard.
9. Backup hạ tầng ngoài cluster: LB API, LB External, GitLab Runner
Chạy ở đâu: Chạy trên đúng server đó.
Đây là 3 server Ubuntu còn lại chưa có cách backup riêng ở trên. Vì LB API và LB External không có redundancy (mỗi loại chỉ 1 server), backup/restore nhanh 2 server này gần như quan trọng ngang etcd.
#!/bin/bash
# /usr/local/bin/backup-infra.sh — chạy trên LB-API, LB-External, và GitLab Runner (mỗi server 1 bản)
DATE=$(date +%F)
HOST=$(hostname)
mkdir -p /tmp/infra-backup
case "$HOST" in
*lb-api*)
tar czf /tmp/infra-backup/haproxy-api-$HOST-$DATE.tar.gz /etc/haproxy
;;
*lb-external*)
tar czf /tmp/infra-backup/haproxy-external-$HOST-$DATE.tar.gz /etc/haproxy
;;
*runner*)
tar czf /tmp/infra-backup/gitlab-runner-$HOST-$DATE.tar.gz /etc/gitlab-runner
;;
esac
mc cp --recursive /tmp/infra-backup/ backupminio/infra-config-backup/$HOST/
Cron (mỗi server, giờ khác nhau chút để tránh dồn tải lên MinIO cùng lúc):
0 4 * * * /usr/local/bin/backup-infra.sh >> /var/log/infra-backup.log 2>&1
Restore:
- HAProxy (API hoặc External): cài lại Ubuntu + HAProxy package → mc cp file backup từ bucket infra-config-backup về → giải nén vào /etc/haproxy → systemctl restart haproxy.
- GitLab Runner: cài lại gitlab-runner package → mc cp + giải nén vào /etc/gitlab-runner → gitlab-runner restart. Nếu GitLab server cũng bị cài lại hoàn toàn (token cũ không còn hợp lệ), phải đăng ký lại runner bằng token mới.
Khuyến nghị mạnh hơn: đưa file cấu hình HAProxy/Runner vào 1 Git repo riêng ("infra-config") làm nguồn chân lý, MinIO chỉ là bản sao thứ cấp.
10. Lịch backup & retention tổng hợp
| Thành phần | Nơi chạy | Tần suất | Retention | Công cụ |
|---|---|---|---|---|
| etcd | Control-plane (K8s) | 6 giờ/lần | 7 bản local + 30 ngày trên MinIO (lifecycle rule) | etcdctl snapshot + mc cp |
| Velero (toàn cluster) | K8s | Hằng ngày | 14 ngày | Velero schedule |
| Velero (argocd/cert-manager/monitoring) | K8s | Hằng giờ | 3 ngày | Velero schedule |
| Longhorn volumes | K8s → MinIO (S3) | Hằng ngày | 14 bản | Longhorn RecurringJob |
| GitLab | Server Ubuntu riêng → MinIO | Hằng ngày | 14 ngày | gitlab-backup create + cron + mc cp |
| Harbor (data + DB) | Server Ubuntu riêng → MinIO | Hằng ngày | 14 ngày | tar + pg_dumpall + cron + mc cp |
| ArgoCD (kubectl export) | K8s → MinIO | Hằng ngày | 14 ngày | kubectl get -o yaml + cron + mc cp |
| HAProxy API/External config | 2 server Ubuntu riêng → MinIO | Khi thay đổi + hằng tuần | Vô hạn (dung lượng nhỏ) | mc cp + Git |
| GitLab Runner config | Server Ubuntu riêng → MinIO | Khi thay đổi + hằng tuần | Vô hạn (dung lượng nhỏ) | mc cp + Git |
11. Thứ tự khôi phục khi mất toàn bộ hệ thống (Full DR)
- Khôi phục hạ tầng vật lý/OS trên control-plane, worker, và cả 6 server Ubuntu độc lập (LB API, LB External, GitLab, Harbor, GitLab Runner, MinIO backup server) nếu cần cài lại từ đầu.
- Khôi phục MinIO backup server trước tiên nếu có thể — nếu MinIO chính (
10.128.48.222) bị phá huỷ cùng sự cố, chuyển sang dùng MinIO phụ (10.128.48.223, mục 1.5) làm nguồn restore tạm thời: đổi aliasmc alias set backupminio http://10.128.48.223:9000 ...và trỏ lạis3Urltrong cấu hình Velero/Longhorn sang MinIO phụ. Sau khi hệ thống ổn định, dựng lại MinIO chính mới và đảo hướng replication (MinIO phụ trở thành nguồn, MinIO chính mới thành đích) để không mất khả năng dự phòng về sau. RAID 6 (mục 1.1) và Bucket Replication (mục 1.5) đã giảm đáng kể khả năng cả 2 MinIO cùng bị phá huỷ trong 1 sự cố — nhưng nếu vẫn xảy ra (ví dụ chưa kịp đặt MinIO phụ ở phòng/rack khác), xem mục 13 để biết rủi ro còn lại. - Khôi phục LB API và LB External (mục 9) — 2 server này không có redundancy, phải sống lại sớm để có đường vào cluster và ứng dụng.
- Khôi phục etcd (mục 2.2) trên control-plane, join lại 3 node theo kubeadm.
- Cài lại CNI (Calico), CSI (Longhorn, NFS driver).
- Cài lại Velero, trỏ về MinIO server (
10.128.48.222) —velero backup getđể xác nhận thấy lại lịch sử backup cũ. - Restore Longhorn volumes trước (mục 4.4) nếu StatefulSet phụ thuộc dữ liệu đã tồn tại.
velero restore createtheo thứ tự:cert-manager→argocd→monitoring→ workload khác.- Cài lại GitLab (Omnibus) trên server Ubuntu riêng, restore bằng
gitlab-backup restore+gitlab-secrets.json/gitlab.rb(mục 5.2). - Cài lại Harbor (docker-compose) trên server Ubuntu riêng, restore tar data volume + DB dump (mục 6.2).
- Cài lại GitLab Runner trên server Ubuntu riêng, restore
config.toml, đăng ký lại runner nếu token cũ không còn hợp lệ. - ArgoCD: sau khi restore namespace
argocd(qua Velero) hoặc áp lại file kubectl export thủ công (mục 7.2), kiểm trakubectl get applications -n argocdxem tất cả tự Sync lại từ Git. - Kiểm tra cert-manager cấp lại chứng chỉ Let's Encrypt (tự renew/issue lại nếu Secret cũ không phục hồi được — không nghiêm trọng, chỉ cần theo dõi).
- Smoke test toàn diện: đăng nhập GitLab, push thử code, pipeline CI chạy qua Runner (pod spawn trong cluster), build image push Harbor, ArgoCD tự deploy, kiểm tra Grafana thấy metric mới.
12. DR Drill — kiểm tra định kỳ (đừng bỏ qua)
| Việc cần test | Tần suất khuyến nghị |
|---|---|
| Restore 1 backup Velero vào namespace tạm | Hằng tháng |
| Restore thử etcd snapshot lên cluster test riêng | Mỗi quý |
Restore thử gitlab-backup restore lên GitLab test |
Mỗi quý |
| Restore thử Harbor (data + DB) lên server test | Mỗi quý |
| Dựng lại HAProxy API/External từ backup config trên server mới | Mỗi quý (vì đây là 2 SPOF không có failover) |
| Kiểm tra tình trạng RAID 6 (còn đủ dự phòng chưa, có ổ nào đang degraded chưa thay) trên server MinIO | Hằng tháng |
| Kiểm chứng Bucket Replication (Tier 2) đang chạy đúng — tạo file test, xác nhận xuất hiện ở MinIO phụ (lệnh ở mục 1.5) | Hằng tháng |
| Diễn tập Full DR toàn bộ (mục 11) trên hạ tầng test | Ít nhất 1-2 lần/năm |
Một backup chưa test restore = một backup mà hy vọng là hoạt động, không phải một backup biết chắc là hoạt động.
13. Rủi ro còn tồn tại cần lưu ý
- LB API và LB External không có redundancy — Nên xem xét thêm keepalived + 1 server dự phòng cho mỗi loại LB nếu ngân sách cho phép.
- alert khi job backup fail — bổ sung giám sát job để biết tình trạng backup.
- GitLab Runner cần đăng ký lại token sau DR nếu GitLab server cũng bị dựng lại từ đầu — nên ghi rõ bước này vào checklist DR để không quên.