1. ๊ฐ์
Kubernetes ํด๋ฌ์คํฐ์์ etcd๋ ๋ชจ๋ ํด๋ฌ์คํฐ ์ํ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ํต์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ค. etcd ๋ฐ์ดํฐ๊ฐ ๋ ์๊ฐ๋ฉด ํด๋ฌ์คํฐ ์ ์ฒด๋ฅผ ์ฌ๊ตฌ์ฑํด์ผ ํ๋ ์น๋ช ์ ์ธ ์ํฉ์ด ์จ๋ค.
์์ ์ ํด๋ฌ์คํฐ๋ฅผ ๊ตฌ์ฑํ๋ฉด์ etcd๋ฅผ ๋ฐฑ์ ํ์ง ์์ ์ฑ ๋ ธ๋ join์ ํ๋ค๊ฐ etcd ํด๋ฌ์คํฐ ์ฅ์ ๋ฅผ ๋ธ ์ ์ด ์๋ค. ๊ฒฐ๊ตญ ํด๋ฌ์คํฐ ์ ์ฒด๋ฅผ ๋ค์ ์ธ์์ผ ํ๋๋ฐ, ์ด์ ์๋ฒ๊ฐ ์๋์์ผ๋ ๋ง์ ์ด์ง ์ ๋ง ๋๋๋ ๊ฒฝํ์ด์๋ค. ๊ทธ ๋ค๋ก ๋ฐฑ์ ์ ์ต๊ด์ด ๋๋ค.
IMPORTANT
etcd ๋ฐฑ์ ์ ํด๋ฌ์คํฐ ์ด์์์ ํ์๋ค. ์ ๊ธฐ ๋ฐฑ์ ์์ด๋ ์ฅ์ ์ ๋ณต๊ตฌ๊ฐ ๋ถ๊ฐ๋ฅํ๋ค.
2. ๋ฐฑ์ ์ ๋ต
์ด๋ฒ ์ค์ ์์ ์ด ๋ฐฑ์ ์ ๋ต์ ๋ค์๊ณผ ๊ฐ๋ค.
- ๋ฐฑ์ ์ฃผ๊ธฐ: ๋งค์ผ ์คํ 5์ (Asia/Seoul ๊ธฐ์ค)
- ๋ณด๊ด ์ ์ฑ : ๋ก์ปฌ๊ณผ ์๊ตฌ ์ ์ฅ์์ ๊ฐ๊ฐ 5์ผ๊ฐ ๋ณด๊ด
- ์ด์คํ: ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ PVC๋ฅผ ํ์ฉํ ์ด์ค ๋ฐฑ์
- ์๋ ์ ๋ฆฌ: ์ค๋๋ ๋ฐฑ์ ํ์ผ ์๋ ์ญ์
3. CronJob ๊ตฌ์ฑ
3-1. ๊ธฐ๋ณธ ์ค์
CronJob์ ๋งค์ผ ์ ํด์ง ์๊ฐ์ etcd ์ค๋ ์ท์ ์์ฑํ๊ณ ๋ฐฑ์ ํ์ผ์ ๊ด๋ฆฌํ๋ค.
apiVersion: batch/v1
kind: CronJob
metadata:
name: etcd-backup-cron-job
namespace: kube-system
spec:
schedule: "0 17 * * *" # ๋งค์ผ ์คํ 5์
timeZone: "Asia/Seoul"
concurrencyPolicy: Allow
failedJobsHistoryLimit: 1
successfulJobsHistoryLimit: 33-2. Pod ์ค์ผ์ค๋ง
๋ฐฑ์ ์์ ์ ๋ฐ๋์ control-plane ๋ ธ๋์์ ์คํ๋์ด์ผ ํ๋ค. etcd ์๋ฒ์ ์ง์ ์ ๊ทผํ ์ ์๋ ๋ ธ๋์์๋ง ๋ฐฑ์ ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ค.
spec:
template:
spec:
nodeSelector:
node-role.kubernetes.io/control-plane: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Exists
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- kdev-master-a-04 # ํน์ ๋ง์คํฐ ๋
ธ๋ ์ ํธ
weight: 1003-3. etcd ๋ฐฑ์ ์ํ
InitContainer์์ ์ค์ etcd ์ค๋
์ท ์์ฑ ์์
์ ์ํํ๋ค. etcdctl snapshot ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ํ์ฌ etcd ์ํ๋ฅผ ๋ฐฑ์
ํ์ผ๋ก ์ ์ฅํ๋ค.
initContainers:
- name: etcd-backup
image: bitnami/etcd:latest
command:
- /bin/sh
- -c
- |
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
BACKUP_DIR="/backup/host"
SNAPSHOT_FILE="etcd-snapshot-${DATE}.db"
etcdctl \
--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 \
snapshot save "${BACKUP_DIR}/${SNAPSHOT_FILE}"NOTE
etcd ๋ฐฑ์ ์์๋ etcd ์๋ฒ์ TLS ์ธ์ฆ์๊ฐ ํ์ํ๋ค. Kubernetes์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก
/etc/kubernetes/pki/etcd/๊ฒฝ๋ก์ ํ์ํ ์ธ์ฆ์๋ค์ด ์์นํ๋ค.
3-4. ๋ฐฑ์ ํ์ผ ๊ด๋ฆฌ
๋ฉ์ธ ์ปจํ ์ด๋์์๋ ๋ฐฑ์ ํ์ผ์ ์๊ตฌ ์ ์ฅ์๋ก ๋ณต์ฌํ๊ณ , ์ค๋๋ ๋ฐฑ์ ํ์ผ๋ค์ ์ ๋ฆฌํ๋ค.
containers:
- name: backup-purge
image: busybox:latest
command:
- /bin/sh
- -c
- |
# ๋ก์ปฌ ๋ฐฑ์
์ ์๊ตฌ ์ ์ฅ์๋ก ๋ณต์ฌ
cp -u /backup/host/*.db /backup/persist/
# 5์ผ ์ด์ ๋ ๋ฐฑ์
ํ์ผ ์ญ์
find /backup/host -type f -mtime +5 -name '*.db' -exec rm -- '{}' \;
find /backup/persist -type f -mtime +5 -name '*.db' -exec rm -- '{}' \;4. ๋ณผ๋ฅจ ๊ตฌ์ฑ
๋ฐฑ์ ํ์ผ์ ์ ์ฅํ๊ธฐ ์ํด ๋ ๊ฐ์ง ๋ณผ๋ฅจ์ ์ฌ์ฉํ๋ค:
etcd-backup: ๋ ธ๋์ ๋ก์ปฌ ์คํ ๋ฆฌ์ง (/data/etcd-backup)second-backup: PVC๋ฅผ ํตํ ์๊ตฌ ์ ์ฅ์etcd-certs: etcd TLS ์ธ์ฆ์ ๋๋ ํ ๋ฆฌ
volumes:
- name: etcd-backup
hostPath:
path: /data/etcd-backup
- name: etcd-certs
hostPath:
path: /etc/kubernetes/pki/etcd
type: Directory
- name: second-backup
persistentVolumeClaim:
claimName: etcd-backup-pvc5. ์ ์ฒด ์ค์
์์ ํ CronJob YAML ์ค์
apiVersion: v1
items:
- apiVersion: batch/v1
kind: CronJob
metadata:
name: etcd-backup-cron-job
namespace: kube-system
spec:
concurrencyPolicy: Allow
failedJobsHistoryLimit: 1
jobTemplate:
metadata:
creationTimestamp: null
spec:
template:
metadata:
creationTimestamp: null
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- kdev-master-a-04
weight: 100
containers:
- command:
- /bin/sh
- -c
- |
cp -u /backup/host/*.db /backup/persist/
find /backup/host -type f -mtime +5 -name '*.db' -exec rm -- '{}' \;
find /backup/persist -type f -mtime +5 -name '*.db' -exec rm -- '{}' \;
image: busybox:latest
imagePullPolicy: IfNotPresent
name: backup-purge
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /backup/host
name: etcd-backup
- mountPath: /backup/persist
name: second-backup
dnsPolicy: ClusterFirst
hostNetwork: true
initContainers:
- command:
- /bin/sh
- -c
- |
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
BACKUP_DIR="/backup/host"
SNAPSHOT_FILE="etcd-snapshot-${DATE}.db"
ARCHIVE_FILE="${SNAPSHOT_FILE}.gz"
etcdctl \
--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 \
snapshot save "${BACKUP_DIR}/${SNAPSHOT_FILE}"
image: bitnami/etcd:latest
imagePullPolicy: IfNotPresent
name: etcd-backup
resources: {}
securityContext:
allowPrivilegeEscalation: false
runAsGroup: 0
runAsUser: 0
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /backup/host
name: etcd-backup
- mountPath: /etc/kubernetes/pki/etcd
name: etcd-certs
readOnly: true
nodeSelector:
node-role.kubernetes.io/control-plane: ""
restartPolicy: OnFailure
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Exists
volumes:
- hostPath:
path: /data/etcd-backup
type: ""
name: etcd-backup
- hostPath:
path: /etc/kubernetes/pki/etcd
type: Directory
name: etcd-certs
- name: second-backup
persistentVolumeClaim:
claimName: etcd-backup-pvc
schedule: 0 17 * * *
successfulJobsHistoryLimit: 3
suspend: false
timeZone: Asia/Seoul6. ๋ฐฑ์ ํ์ธ ๋ฐ ๋ณต๊ตฌ
๋ฐฑ์ ์ด ์ ์์ ์ผ๋ก ์ํ๋๋์ง ์ ๊ธฐ์ ์ผ๋ก ํ์ธํด์ผ ํ๋ค:
# ๋ฐฑ์
ํ์ผ ํ์ธ
ls -la /data/etcd-backup/
# ๋ฐฑ์
ํ์ผ ๋ฌด๊ฒฐ์ฑ ๊ฒ์ฆ
etcdctl snapshot status /data/etcd-backup/etcd-snapshot-<timestamp>.db
# ๋ณต๊ตฌ ํ
์คํธ (ํ
์คํธ ํ๊ฒฝ์์๋ง)
etcdctl snapshot restore /data/etcd-backup/etcd-snapshot-<timestamp>.db \
--data-dir=/var/lib/etcd-restoreINFO
๋ฐฑ์ ์ ์์ฑํ๋ ๊ฒ๋ ์ค์ํ์ง๋ง, ์ค์ ๋ก ๋ณต๊ตฌ๊ฐ ๊ฐ๋ฅํ์ง ์ฃผ๊ธฐ์ ์ผ๋ก ํ ์คํธํ๋ ๊ฒ์ด ๋์ฑ ์ค์ํ๋ค. ํ ์คํธ ํ๊ฒฝ์์ ์ ๊ธฐ์ ์ผ๋ก ๋ณต๊ตฌ ํ ์คํธ๋ฅผ ์ํํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค.