쿠버네티스를 위한 etcd 클러스터 운영하기
쿠버네티스를 위한 etcd 클러스터 운영하기 (Operating etcd clusters for Kubernetes)
etcd는 쿠버네티스가 모든 클러스터 데이터의 백킹 스토어로 사용하는 일관되고 고가용성인 키-값 저장소예요. 쿠버네티스 클러스터가 etcd를 백킹 스토어로 사용한다면 데이터에 대한 백업 계획이 있는지 확인하세요.
etcd에 대한 심층 정보는 공식 문서에서 찾을 수 있어요.
출처: 문서
본문
시작하기 전에 (Before you begin)
이 페이지의 단계를 따라 etcd를 배포, 관리, 백업하거나 복원하기 전에, etcd 클러스터를 운영하는 데 대한 일반적인 기대치를 이해해야 해요. 더 많은 맥락은 etcd 문서를 참고하세요.
핵심 세부 사항은 다음과 같아요.
- 프로덕션에서 실행하기 위해 권장되는 최소 etcd 버전은
3.4.29+와3.5.11+이에요. - etcd는 리더 기반 분산 시스템이에요. 리더가 주기적으로 모든 팔로워에게 하트비트를 제때 보내 클러스터를 안정적으로 유지하도록 보장하세요.
- etcd를 홀수 개의 멤버로 구성된 클러스터로 실행해야 해요.
- 리소스 부족이 발생하지 않도록 하는 것을 목표로 하세요. 클러스터의 성능과 안정성은 네트워크와 디스크 I/O에 민감해요. 어떤 리소스 부족도 하트비트 타임아웃으로 이어져 클러스터의 불안정을 유발할 수 있어요. 불안정한 etcd는 리더가 선출되지 않았음을 나타내요. 그런 상황에서 클러스터는 현재 상태에 어떤 변경도 할 수 없어서, 새 파드가 스케줄링될 수 없다는 뜻이에요.
etcd를 위한 리소스 요구 사항 (Resource requirements for etcd)
제한된 리소스로 etcd를 운영하는 것은 테스트 목적으로만 적합해요. 프로덕션에 배포하려면 고급 하드웨어 구성이 필요해요. etcd를 프로덕션에 배포하기 전에 리소스 요구 사항 참조를 보세요.
etcd 클러스터를 안정적으로 유지하는 것은 쿠버네티스 클러스터의 안정성에 중요해요. 따라서 보장된 리소스 요구를 위해 전용 머신이나 격리된 환경에서 etcd 클러스터를 실행하세요.
도구 (Tools)
어떤 특정 결과를 위해 작업하느냐에 따라 etcdctl 도구 또는 etcdutl 도구(둘 다 필요할 수도)가 필요할 거예요.
etcdctl과 etcdutl 이해하기 (Understanding etcdctl and etcdutl)
etcdctl과 etcdutl은 etcd 클러스터와 상호작용하는 데 사용되는 명령줄 도구이지만, 다른 목적을 제공해요.
etcdctl: 네트워크를 통해 etcd와 상호작용하기 위한 기본 명령줄 클라이언트예요. 키와 값 관리, 클러스터 관리, 헬스 확인 등의 일상적인 작업에 사용돼요.etcdutl: etcd 데이터 파일에 직접 작동하도록 설계된 관리 유틸리티예요. etcd 버전 간 데이터 마이그레이션, 데이터베이스 조각 모음, 스냅샷 복원, 데이터 일관성 검증을 포함해요. 네트워크 작업에는etcdctl을 사용해야 해요.
etcdutl에 대한 자세한 내용은 etcd 복구 문서를 참고할 수 있어요.
etcd 클러스터 시작하기 (Starting etcd clusters)
이 섹션은 단일 노드와 다중 노드 etcd 클러스터를 시작하는 방법을 다뤄요. 이 가이드는 etcd가 이미 설치되었다고 가정해요.
단일 노드 etcd 클러스터 (Single-node etcd cluster)
단일 노드 etcd 클러스터는 테스트 목적으로만 사용하세요. 다음을 실행해요.
etcd --listen-client-urls=http://$PRIVATE_IP:2379 \
--advertise-client-urls=http://$PRIVATE_IP:2379
--etcd-servers=$PRIVATE_IP:2379 플래그로 쿠버네티스 API 서버를 시작해요. PRIVATE_IP가 etcd 클라이언트 IP로 설정돼 있는지 확인하세요.
다중 노드 etcd 클러스터 (Multi-node etcd cluster)
내구성과 고가용성을 위해 프로덕션에서 etcd를 다중 노드 클러스터로 실행하고 주기적으로 백업하세요. 프로덕션에서는 5개 멤버 클러스터가 권장돼요. 자세한 내용은 FAQ 문서를 참고하세요.
쿠버네티스를 사용하므로 하나 이상의 Pod 안의 컨테이너로 etcd를 실행하는 옵션이 있어요. kubeadm 도구는 기본적으로 etcd 정적 파드를 설정하거나, 별도의 클러스터를 배포하고 kubeadm이 그 etcd 클러스터를 컨트롤 플레인의 백킹 스토어로 사용하도록 지시할 수 있어요.
etcd 클러스터는 정적 멤버 정보 또는 동적 발견(dynamic discovery)으로 구성해요. 클러스터링에 대한 자세한 내용은 etcd 클러스터링 문서를 참고하세요.
예를 들어, 다음 클라이언트 URL로 실행되는 5개 멤버 etcd 클러스터를 고려해 보죠: http://$IP1:2379, http://$IP2:2379, http://$IP3:2379, http://$IP4:2379, http://$IP5:2379. 쿠버네티스 API 서버를 시작하려면:
다음을 실행해요.
etcd --listen-client-urls=http://$IP1:2379,http://$IP2:2379,http://$IP3:2379,http://$IP4:2379,http://$IP5:2379 --advertise-client-urls=http://$IP1:2379,http://$IP2:2379,http://$IP3:2379,http://$IP4:2379,http://$IP5:2379
--etcd-servers=$IP1:2379,$IP2:2379,$IP3:2379,$IP4:2379,$IP5:2379 플래그로 쿠버네티스 API 서버를 시작해요. IP<n> 변수가 클라이언트 IP 주소로 설정돼 있는지 확인하세요.
로드밸런서가 있는 다중 노드 etcd 클러스터 (Multi-node etcd cluster with load balancer)
로드밸런싱 etcd 클러스터를 실행하려면:
- etcd 클러스터를 설정해요.
- etcd 클러스터 앞에 로드밸런서를 구성해요. 예를 들어 로드밸런서의 주소를
$LB로 두세요. --etcd-servers=$LB:2379플래그로 쿠버네티스 API 서버를 시작해요.
etcd 클러스터 보안 설정하기 (Securing etcd clusters)
etcd에 대한 접근은 클러스터에서 root 권한과 같으므로 이상적으로는 API 서버만 접근해야 해요. 데이터의 민감성을 고려해 etcd 클러스터에 접근이 필요한 노드에만 권한을 부여하는 것이 권장돼요.
etcd를 보호하려면 방화벽 규칙을 설정하거나 etcd가 제공하는 보안 기능을 사용해요. etcd 보안 기능은 x509 Public Key Infrastructure(PKI)에 의존해요. 먼저 키와 인증서 쌍을 생성해 보안 통신 채널을 수립하세요. 예를 들어 etcd 멤버 간 통신 보안에는 peer.key와 peer.cert 키 쌍을, etcd와 클라이언트 간 통신 보안에는 client.key와 client.cert를 사용해요. 클라이언트 인증을 위한 키 쌍과 CA 파일을 생성하려면 etcd 프로젝트가 제공하는 예시 스크립트를 참고하세요.
통신 보안 설정하기 (Securing communication)
안전한 피어 통신으로 etcd를 구성하려면 --peer-key-file=peer.key와 --peer-cert-file=peer.cert 플래그를 지정하고 URL 스키마로 HTTPS를 사용해요.
마찬가지로 안전한 클라이언트 통신으로 etcd를 구성하려면 --key=k8sclient.key와 --cert=k8sclient.cert 플래그를 지정하고 URL 스키마로 HTTPS를 사용해요. 안전한 통신을 사용하는 클라이언트 명령 예시:
ETCDCTL_API=3 etcdctl --endpoints 10.2.0.9:2379 \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
member list
etcd 클러스터 접근 제한하기 (Limiting access of etcd clusters)
안전한 통신을 구성한 후 TLS 인증을 사용해 etcd 클러스터의 접근을 쿠버네티스 API 서버로만 제한해요.
예를 들어 CA etcd.ca가 신뢰하는 k8sclient.key와 k8sclient.cert 키 쌍을 고려해 보죠. etcd가 TLS와 함께 --client-cert-auth로 구성되면 시스템 CA 또는 --trusted-ca-file 플래그로 전달된 CA를 사용해 클라이언트의 인증서를 검증해요. --client-cert-auth=true와 --trusted-ca-file=etcd.ca 플래그를 지정하면 접근이 k8sclient.cert 인증서가 있는 클라이언트로 제한돼요.
etcd가 올바르게 구성되면 유효한 인증서가 있는 클라이언트만 접근할 수 있어요. 쿠버네티스 API 서버에 접근을 부여하려면 --etcd-certfile=k8sclient.cert, --etcd-keyfile=k8sclient.key, --etcd-cafile=ca.cert 플래그로 구성하세요.
참고: etcd 인증은 쿠버네티스에서 계획되지 않았어요.
실패한 etcd 멤버 교체하기 (Replacing a failed etcd member)
etcd 클러스터는 경미한 멤버 실패를 허용함으로써 고가용성을 달성해요. 하지만 전체 클러스터의 건강을 개선하려면 실패한 멤버를 즉시 교체하세요. 여러 멤버가 실패하면 하나씩 교체하세요. 실패한 멤버 교체는 두 단계를 포함해요: 실패한 멤버 제거와 새 멤버 추가.
etcd는 내부적으로 고유 멤버 ID를 유지하지만, 사람의 실수를 피하기 위해 각 멤버에 고유 이름을 사용하는 것이 권장돼요. 예를 들어 3개 멤버 etcd 클러스터를 고려해 보죠. URL이 member1=http://10.0.0.1, member2=http://10.0.0.2, member3=http://10.0.0.3라고 해요. member1이 실패하면 member4=http://10.0.0.4로 교체해요.
실패한 member1의 멤버 ID를 가져와요:
etcdctl --endpoints=http://10.0.0.2,http://10.0.0.3 member list
다음 메시지가 표시돼요:
8211f1d0f64f3269, started, member1, http://10.0.0.1:2380, http://10.0.0.1:2379
91bc3c398fb3c146, started, member2, http://10.0.0.2:2380, http://10.0.0.2:2379
fd422379fda50e48, started, member3, http://10.0.0.3:2380, http://10.0.0.3:2379
다음 중 하나를 수행해요:
- 각 쿠버네티스 API 서버가 모든 etcd 멤버와 통신하도록 구성된 경우,
--etcd-servers플래그에서 실패한 멤버를 제거한 다음 각 쿠버네티스 API 서버를 재시작해요. - 각 쿠버네티스 API 서버가 단일 etcd 멤버와 통신하는 경우, 실패한 etcd와 통신하는 쿠버네티스 API 서버를 중지해요.
깨진 노드에서 etcd 서버를 중지해요. 쿠버네티스 API 서버 외에 다른 클라이언트가 etcd에 트래픽을 유발할 가능성이 있고, 데이터 디렉터리에 쓰기를 방지하기 위해 모든 트래픽을 중지하는 것이 바람직해요.
실패한 멤버를 제거해요:
etcdctl member remove 8211f1d0f64f3269
다음 메시지가 표시돼요:
Removed member 8211f1d0f64f3269 from cluster
새 멤버를 추가해요:
etcdctl member add member4 --peer-urls=http://10.0.0.4:2380
다음 메시지가 표시돼요:
Member 2be1eb8f84b7f63e added to cluster ef37ad9dc622a7c4
IP 10.0.0.4의 머신에서 새로 추가된 멤버를 시작해요:
export ETCD_NAME="member4"
export ETCD_INITIAL_CLUSTER="member2=http://10.0.0.2:2380,member3=http://10.0.0.3:2380,member4=http://10.0.0.4:2380"
export ETCD_INITIAL_CLUSTER_STATE=existing
etcd [flags]
다음 중 하나를 수행해요:
- 각 쿠버네티스 API 서버가 모든 etcd 멤버와 통신하도록 구성된 경우,
--etcd-servers플래그에 새로 추가된 멤버를 추가한 다음 각 쿠버네티스 API 서버를 재시작해요. - 각 쿠버네티스 API 서버가 단일 etcd 멤버와 통신하는 경우, 2단계에서 중지한 쿠버네티스 API 서버를 시작해요. 그런 다음 쿠버네티스 API 서버 클라이언트가 중지된 쿠버네티스 API 서버로 요청을 다시 라우팅하도록 구성해요. 이는 보통 로드밸런서를 구성해 수행할 수 있어요.
클러스터 재구성에 대한 자세한 내용은 etcd 재구성 문서를 참고하세요.
etcd 클러스터 백업하기 (Backing up an etcd cluster)
모든 쿠버네티스 객체는 etcd에 저장돼요. etcd 클러스터 데이터를 주기적으로 백업하는 것은 모든 컨트롤 플레인 노드를 잃는 것 같은 재해 시나리오에서 쿠버네티스 클러스터를 복구하는 데 중요해요. 스냅샷 파일은 모든 쿠버네티스 상태와 중요한 정보를 포함해요. 민감한 쿠버네티스 데이터를 안전하게 유지하려면 스냅샷 파일을 암호화하세요.
etcd 클러스터는 두 가지 방식으로 백업할 수 있어요: etcd 내장 스냅샷과 볼륨 스냅샷.
내장 스냅샷 (Built-in snapshot)
etcd는 내장 스냅샷을 지원해요. 스냅샷은 etcdctl snapshot save 명령으로 활성 멤버로부터 생성하거나, 현재 etcd 프로세스가 사용하지 않는 etcd 데이터 디렉터리에서 member/snap/db 파일을 복사해 생성할 수 있어요. 스냅샷 생성은 멤버의 성능에 영향을 주지 않아요.
다음은 $ENDPOINT가 서빙하는 키스페이스의 스냅샷을 snapshot.db 파일로 생성하는 예시예요.
ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save snapshot.db
스냅샷을 검증해요. 아래 예시는 스냅샷 검증을 위한 etcdutl 도구 사용을 보여줘요.
etcdutl --write-out=table snapshot status snapshot.db
다음과 비슷한 출력을 생성해야 해요.
+----------+----------+------------+------------+
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| fe01cf57 | 10 | 7 | 2.1 MB |
+----------+----------+------------+------------+
참고:
etcdctl snapshot status사용은 etcd v3.5.x부터 폐기됐고 etcd v3.6에서 제거될 예정이에요.etcdutl을 대신 사용하는 것이 권장돼요.
아래 예시는 스냅샷 검증을 위한 etcdctl 도구 사용을 보여줘요.
export ETCDCTL_API=3
etcdctl --write-out=table snapshot status snapshot.db
다음과 비슷한 출력을 생성해야 해요.
Deprecated: Use `etcdutl snapshot status` instead.
+----------+----------+------------+------------+
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| fe01cf57 | 10 | 7 | 2.1 MB |
+----------+----------+------------+------------+
볼륨 스냅샷 (Volume snapshot)
etcd가 Amazon Elastic Block Store 같은 백업을 지원하는 스토리지 볼륨에서 실행 중이라면, 스토리지 볼륨의 스냅샷을 만들어 etcd 데이터를 백업해요.
etcdctl 옵션으로 스냅샷 (Snapshot using etcdctl options)
etcdctl이 제공하는 다양한 옵션으로도 스냅샷을 만들 수 있어요. 예를 들어:
ETCDCTL_API=3 etcdctl -h
위는 etcdctl에서 사용 가능한 다양한 옵션을 나열해요. 예를 들어 엔드포인트, 인증서, 키를 지정해 스냅샷을 만들 수 있어요.
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=<trusted-ca-file> --cert=<cert-file> --key=<key-file> \
snapshot save <backup-file-location>
여기서 trusted-ca-file, cert-file, key-file은 etcd Pod의 설명에서 얻을 수 있어요.
etcd 클러스터 확장하기 (Scaling out etcd clusters)
etcd 클러스터를 확장하면 성능을 희생해 가용성을 높여요. 확장은 클러스터 성능이나 능력을 높이지 않아요. 일반적인 규칙은 etcd 클러스터를 확장하거나 축소하지 않는 것이에요. etcd 클러스터에 어떤 자동 확장 그룹도 구성하지 마세요. 프로덕션 쿠버네티스 클러스터에서는 공식적으로 지원되는 모든 규모에서 항상 정적 5개 멤버 etcd 클러스터를 실행하는 것이 강력히 권장돼요.
합리적인 확장은 더 많은 안정성이 필요할 때 3개 멤버 클러스터를 5개 멤버 클러스터로 업그레이드하는 것이에요. 기존 클러스터에 멤버를 추가하는 방법은 etcd 재구성 문서를 참고하세요.
etcd 클러스터 복원하기 (Restoring an etcd cluster)
주의: 클러스터에 API 서버가 실행 중이라면 etcd 인스턴스를 복원하려 시도하면 안 돼요. 대신 다음 단계를 따라 etcd를 복원하세요.
- 모든 API 서버 인스턴스 중지
- 모든 etcd 인스턴스의 상태 복원
- 모든 API 서버 인스턴스 재시작
쿠버네티스 프로젝트는 또한 쿠버네티스 컴포넌트(kube-scheduler, kube-controller-manager, kubelet)를 재시작해 그들이 오래된 데이터에 의존하지 않도록 하는 것을 권장해요. 실무에서 복원에는 시간이 좀 걸려요. 복원 중 중요한 컴포넌트는 리더 잠금을 잃고 스스로 재시작해요.
etcd는 메이저.마이너 버전의 etcd 프로세스에서 가져온 스냅샷에서의 복원을 지원해요. 다른 패치 버전의 etcd에서 버전을 복원하는 것도 지원돼요. 복원 작업은 실패한 클러스터의 데이터를 복구하는 데 사용돼요.
복원 작업을 시작하기 전에 스냅샷 파일이 있어야 해요. 이전 백업 작업의 스냅샷 파일이거나 남아있는 데이터 디렉터리의 것일 수 있어요.
etcdutl로 클러스터를 복원할 때 --data-dir 옵션을 사용해 클러스터가 복원될 폴더를 지정해요.
etcdutl --data-dir <data-dir-location> snapshot restore snapshot.db
여기서 <data-dir-location>은 복원 과정에서 생성될 디렉터리예요.
참고: 복원을 위한
etcdctl사용은 etcd v3.5.x부터 폐기됐고 etcd v3.6에서 제거될 예정이에요.etcdutl을 대신 사용하는 것이 권장돼요.
아래 예시는 복원 작업을 위한 etcdctl 도구 사용을 보여줘요.
export ETCDCTL_API=3
etcdctl --data-dir <data-dir-location> snapshot restore snapshot.db
<data-dir-location>이 이전과 같은 폴더라면, 클러스터 복원 전에 삭제하고 etcd 프로세스를 중지해요. 그렇지 않으면 복원 후 etcd 구성을 변경하고 etcd 프로세스를 재시작해 새 데이터 디렉터리를 사용하게 해요. 먼저 /etc/kubernetes/manifests/etcd.yaml의 volumes.hostPath.path를 name: etcd-data에 대해 <data-dir-location>으로 변경하고, kubectl -n kube-system delete pod <name-of-etcd-pod> 또는 systemctl restart kubelet.service를 실행해요(또는 둘 다).
스냅샷 파일에서 클러스터를 복원하는 더 많은 정보와 예시는 etcd 재해 복구 문서를 참고하세요.
복원된 클러스터의 접근 URL이 이전 클러스터와 변경된 경우, 쿠버네티스 API 서버를 그에 맞춰 재구성해야 해요. 이 경우 --etcd-servers=$OLD_ETCD_CLUSTER 플래그 대신 --etcd-servers=$NEW_ETCD_CLUSTER 플래그로 쿠버네티스 API 서버를 재시작해요. $NEW_ETCD_CLUSTER와 $OLD_ETCD_CLUSTER를 각각의 IP 주소로 교체하세요. etcd 클러스터 앞에 로드밸런서가 사용된다면 로드밸런서를 대신 업데이트해야 할 수도 있어요.
etcd 멤버의 대부분이 영구적으로 실패하면 etcd 클러스터는 실패한 것으로 간주돼요. 이런 시나리오에서 쿠버네티스는 현재 상태에 어떤 변경도 할 수 없어요. 스케줄링된 파드는 계속 실행될 수 있지만 새 파드는 스케줄링될 수 없어요. 그런 경우 etcd 클러스터를 복구하고 문제를 해결하기 위해 쿠버네티스 API 서버를 잠재적으로 재구성해요.
etcd 클러스터 업그레이드하기 (Upgrading etcd clusters)
주의: 업그레이드를 시작하기 전에 먼저 etcd 클러스터를 백업하세요.
etcd 업그레이드에 대한 자세한 내용은 etcd 업그레이드 문서를 참고하세요.
etcd에서 스트리밍 읽기 (Streaming reads from etcd)
기능 상태: Kubernetes v1.37부터 Beta; 기본적으로 활성화.
EtcdRangeStream 기능 게이트가 활성화되고 etcd v3.7 이상이면, API 서버는 large collection을 etcd에서 페이지 단위 대신 스트림으로 읽어 양쪽의 최대 메모리 사용을 낮춰요. 백엔드가 RangeStream RPC를 구현하지 않으면 API 서버가 gRPC Unimplemented 응답을 감지하고 페이지 단위 읽기로 폴백해요. etcd 호환 백엔드나 프록시가 깨끗하게 폴백하지 않는다면 --feature-gates=EtcdRangeStream=false로 게이트를 비활성화하세요.
참고: 스트리밍 읽기는
etcd_request_duration_seconds메트릭에operation="listStream"으로 기록돼요.operation="list"와 일치하는 대시보드나 알림을 업데이트하세요.
etcd 클러스터 유지 관리하기 (Maintaining etcd clusters)
etcd 유지 관리에 대한 자세한 내용은 etcd 유지 관리 문서를 참고하세요.
클러스터 조각 모음 (Cluster defragmentation)
참고: 이 항목은 쿠버네티스 자체가 아닌 서드파티 프로젝트나 제품을 링크해요. 자세한 내용 보기.
조각 모음(defragmentation)은 비용이 큰 작업이므로 가능한 한 드물게 실행해야 해요. 반면 어떤 etcd 멤버도 스토리지 쿼터를 초과하지 않도록 하는 것도 필요해요. 쿠버네티스 프로젝트는 조각 모음을 수행할 때 etcd-defrag 같은 도구를 사용할 것을 권장해요.
조각 모음 도구를 쿠버네티스 CronJob으로 실행해 조각 모음이 정기적으로 일어나도록 할 수도 있어요. 자세한 내용은 etcd-defrag-cronjob.yaml을 참고하세요.