1. 배경
쿠버네티스는 클러스터에 대한 대부분의 정보를 저장하기 위해 키-값 저장소인 ETCD를 사용합니다. ETCD에 문제가 발생하면 클러스터 전체에 장애가 발생할 수 있고, 데이터 유실에 따라 리소스가 변경될 수 있습니다. 그렇기 때문에 클러스터를 안전하게 운영하기 위해서 ETCD의 백업은 필수입니다. 이전에도 대규모 클러스터를 운영하면서, 원인이 파악되지 않는 클러스터 이상이 발생하였을 때도, ETCD백업이 구성되어 있어, 빠른 시간에 복구를 함으로써 이에 대한 중요함을 느낀 적이 있습니다. 이를 위하여 백업과 복구하는 방법에 대해 정리합니다.
테스트를 진행하는 환경은 Ubuntu 서버에 클러스터가 구성되어있는 멀티 마스터 구조입니다. 또한 ETCD는 파드로 설치되어 데몬으로 설치되어있는 환경과는 파일의 경로와, 설정이 다를 수 있습니다만, 작업의 과정은 동일합니다.
2. ETCDCTL 설치 및 초기 설정
ETCD가 데몬으로 설치 되어 있을 경우 기본적으로 ETCDCTL은 같이 설치됩니다. 하지만 저는 파드로 클러스터를 구성했기 때문에 따로 설치를 진행해야 합니다. ETCDCTL만 따로 설치할 수 없기 때문에 etcd를 서버에 설치합니다.
Github의 Release를 참조합니다.
ETCD_VER=v3.5.9
# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
/tmp/etcd-download-test/etcdutl version
설치가 완료되면 다음과 같이 etcdctl을 복사한 후 설치를 확인합니다.
하지만 설치한 후 etcdctl member list 로 조회 시 정상적으로 조회가 되지 않습니다. ETCD가 secured 모드로 설치되어있기 때문에 인증을 위한 키를 입력해야 합니다. 저는 이를 alias로 설정하여 사용하도록 변경하였습니다. 추가로 주어야 되는 파라미터는 —cacert, —cert, —key,--endpoints
옵션 입니다. 다음과 같이 alias를 설정한 후 통신을 시도합니다.
alias etcdctl='etcdctl --endpoints=172.31.30.247:2379,172.31.21.9:2379,172.31.27.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key'
etcd는 기본적으로 2379,2380,2381 3개의 포트를 사용합니다. 2379는 client에서 통신하기 위한 포트, 2380은 클러스터 간의 통신을 위한 포트, 2381은 메트릭을 조회하기 위한 포트로 사용합니다. 각 포트를 적절하게 사용해야 통신이 이루어집니다.
3. Snapshot 생성하기
etcd 클러스터로 구성 할 경우 각 노드의 데이터가 유지되고 동기화되기 때문에 각 노드에서 모두 스냅샷을 생성할 필요는 없습니다. 클러스터 중 하나의 노드에서만 스냅샷을 생성해도 되지만, 해당 노드가 문제가 발생하였을 경우 스냅샷이 생성되지 않을 수 있기 때문에 이를 고려하여 스냅샷을 생성할 노드의 개수를 정해야됩니다. 저는 테스트를 위해 한 곳에서만 스냅샷을 생성하도록 하였습니다. 또한 스냅샷 생성 후 동일한 파일을 각 클러스터에서 백업할 때 사용해야 하기 때문에 파일이 공유되는 곳에 저장해야 됩니다.
백업 및 복구가 제대로 되는지 확인하기 위해 파드를 생성합니다.
snapshot의 경우 etcdctl로 간단하게 생성할 수 있습니다. etcdctl snapshot save \[파일명\]
커맨드를 이용해 생성합니다.
다만, 이전에 alias를 통해 endpoint를 지정하였는데, snpashot 생성 시 단일 endpoint를 지정해야 되기 때문에 alias를 해제하고 수동으로 커맨드를 실행합니다. 만약 해제를 안 할 경우 다음과 같은 에러가 발생할 수 있습니다
Snapshot이 정상적으로 생성되었다면 다음 커맨드를 통해 확인 확인 할 수 있습니다.
3. ETCD Restore
이제 생성된 스냅샷으로 복구하기 위하여 생성되어 있는 nginx 파드를 모드 지웁니다. 복구 이후 파드가 생성되어 있으면, 복구가 정상적으로 이루어진 것으로 판단할 수 있습니다.
Restore의 경우 다음과 같은 과정으로 모든 마스터 노드에서 이루어집니다.
- Kubernetes Static Pod 및 ETCD 중지
- ETCD Restore
- Kubernetes Static Pod 및 ETCD 재시작 이를 위해 Static 파드 및 ETCD를 중지합니다. 저는 단순히
Static Pod 매니페스트 파일의 위치를 옮겨서 중지시켰습니다. 또한 ETCD가 파드로 생성되어 있기 때문에 따로 중지할 필요 없습니다. 데몬으로 설치했을 경우 systemctl stop etcd 커맨드로 중지해야 합니다. 아래와 같이 kube-apiserver, etcd
등의 컨테이너가 중지된 것을 확인할 수 있습니다.
이후 각 마스터 노드에서 restore를 진행합니다.
etcdctl snapshot restore /data/backup/20231114-snapshot.db \\
--name master1 --initial-cluster master1=https://172.31.30.247:2380,master2=https://172.31.21.9:2380,master3=https://172.31.27.1:2380 \\
--initial-advertise-peer-urls=https://172.31.30.247:2380 \\
--data-dir=/var/lib/etcd-new \\
--initial-cluster-token etcd-cluster-1
etcdctl snapshot restore /data/backup/20231114-snapshot.db \\
--name master2 --initial-cluster master1=https://172.31.30.247:2380,master2=https://172.31.21.9:2380,master3=https://172.31.27.1:2380 \\
--initial-advertise-peer-urls=https://172.31.21.9:2380 \\
--data-dir=/var/lib/etcd-new \\
--initial-cluster-token etcd-cluster-1
etcdctl snapshot restore /data/backup/20231114-snapshot.db \\
--name master3 --initial-cluster master1=https://172.31.30.247:2380,master2=https://172.31.21.9:2380,master3=https://172.31.27.1:2380 \\
--initial-advertise-peer-urls=https://172.31.27.1:2380 \\
--data-dir=/var/lib/etcd-new \\
--initial-cluster-token etcd-cluster-1
각 옵션은 다음과 같은 의미를 같습니다.
- initial-advertise-peer-urls: 복원을 진행하는 노드의 경로를 입력하여 클러스터에 자신의 정보를 공유할 때 사용합니다.
- --initial-cluster : 초기 클러스터를 구성할 때의 내용과 동일한 구성으로 이루어지며, 클러스터에 대한 정보를 나타냅니다.
- —data-dir: ETCD 복구 후 저장되는 데이터의 경로를 나타냅니다. 설정하지 않을 경우 Overwrite 되며, 기본 값은 /var/lib/etcd입니다.
- —initial-cluster-token : ETCD 클러스터를 식별하는 토큰입니다. 멀티 클러스터에서 구분을 위해 사용되며, 각 노드에서 동일한 값이 입력되어야 합니다.
저는 —data-dir 옵션으로 백업 전 데이터를 보관하기 위해 새로운 경로로 데이터를 따로 지정하였기 때문에 etcd가 재시작될 때 해당 경로로 데이터를 바라보도록 수정해야 합니다.
#etcd.yml
spec:
containers:
- command:
- etcd
- --advertise-client-urls=https://172.31.30.247:2379
- --cert-file=/etc/kubernetes/pki/etcd/server.crt
- --client-cert-auth=true
- --data-dir=/var/lib/etcd-new
...
volumeMounts:
- mountPath: /var/lib/etcd-new
name: etcd-data
...
- hostPath:
path: /var/lib/etcd-new
type: DirectoryOrCreate
name: etcd-data
이후 정상적으로 복구가 완료되면 지웠던 nginx 파드가 생성된 것을 확인할 수 있습니다.
4. ETCD CronJob 생성
위의 과정을 바탕으로 CronJob을 생성하여 12시마다 백업을 생성하도록 설정합니다. cronJob 생성을 위한 과정은 다음 링크를 참조하였습니다. 저는 해당 링크의 Dockerfile을 바탕으로 ETCDCTl이 설치된 이미지를 만든 후 프라이빗 레포에 업로드 후 사용하였습니다.
apiVersion: batch/v1
kind: CronJob
metadata:
name: etcd-backup
spec:
schedule: "0 12 * * *"
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
concurrencyPolicy: Allow
timeZone: Asia/Seoul
jobTemplate:
spec:
template:
spec:
containers:
- name: etcd-backup
image: seokbin9023/etcd-backup
imagePullPolicy: Always
env:
- name: ETCDCTL_API
value: "3"
- name: ETCDCTL_ENDPOINTS
value: "<https://172.31.30.247:2379>"
- name: ETCDCTL_CACERT
value: "/etc/kubernetes/pki/etcd/ca.crt"
- name: ETCDCTL_CERT
value: "/etc/kubernetes/pki/etcd/server.crt"
- name: ETCDCTL_KEY
value: "/etc/kubernetes/pki/etcd/server.key"
command: ["/bin/bash","-c"]
args: ["etcdctl snapshot save /data/etcd-backup/etcd-snapshot-$(date +%Y-%m-%dT%H:%M).db"]
volumeMounts:
- mountPath: /etc/kubernetes/pki/etcd
name: etcd-certs
readOnly: true
- mountPath: /data/etcd-backup
name: etcd-backup
restartPolicy: OnFailure
hostNetwork: true
nodeSelector:
kubernetes.io/hostname: master01
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
operator: Exists
volumes:
- name: etcd-certs
hostPath:
path: /etc/kubernetes/pki/etcd
type: Directory
- name: etcd-backup
hostPath:
path: /data/etcd-backup
type: DirectoryOrCreate
위의 내용을 살펴보면, nodeSelector와 Toleration을 이용해 master1번에서 잡이 실행되도록 하고, /data/etcd-backup 경로에 스냅샷이 생성되도록 하였습니다.
'Kubernetes' 카테고리의 다른 글
Kubernetes CSI Driver 란? (1) | 2024.01.21 |
---|---|
Github Action/ Argo CD를 이용한 CI/CD 구성 (0) | 2024.01.14 |
Velero를 이용한 쿠버네티스 Backup (0) | 2023.10.12 |
EFK Stack을 이용한 쿠버네티스 로깅 스택 구축#2 (0) | 2023.10.12 |
EFK Stack을 이용한 쿠버네티스 로깅 스택 구축#1 (0) | 2023.10.12 |