쿠버네티스의 다양한 리소스들에 대해서 다뤄보면 ETCD라는 중요한 요소에 대해서 알 수 있다. ETCD는 키-값으로 데이터를 저장하는 스토리지로 쿠버네티스에서 모든 상태 정보(메타데이터)를 영구적으로 저장하는 역할을 한다. 마스터 노드에 있는 kube-apiserver는 이 ETCD를 참고하여 클러스터 전체의 최신 상태를 일관성 있게 유지하는 역할을 한다.
간단하게 쿠버네티스의 마스터 노드의 컴포넌트에 대한 그림을 그려보면 위와 같다. 여기서 ETCD에 접근할 수 있는 쿠버네티스의 컴포넌트는 kube-apiserver 뿐으로써 etcd는 쿠버네티스 클러스터에 있어 심장과도 같은 중요한 존재이다.
쿠버네티스는 이런 심장과도 같은 etcd를 어떻게 오케스트레이션하는 것인가? 간단하게 스포일러를 하면 etcd는 위 그림에서 마스터 노드에 내장되어 있지만 밖으로 뺄 수도 있다. 또한 2379 포트를 통해서 etcd에 접근할 수 있는데, etcd를 클러스터링 하게 되면 etcd 간에 2380 포트를 통해서 재미있는 방식으로 고가용성을 유지한다.
이러한 방법이 etcd의 Leader Election(리더 선출)이라고 불리는 과정이다. etcd를 클러스터링하는 경우, 리더를 선출하고 나머지 etcd는 팔로워가 되는데, 이러한 리더 선출의 원리와 활용 방법에 대해서 다뤄보려고 한다.
본론
ETCD?
좀 더 깔끔한 그림을 가져오면 이와 같다. 여기서 왼쪽 아래에 위치한 것이 etcd로, 쿠버네티스에서 핵심적인 역할을 한다. ETCD는 고가용성을 보장하기 위한 솔루션을 제공한다. 먼저, ETCD는 Raft라고 불리는 알고리즘을 통해 각 컴포넌트 간의 리더를 선출하는 기능으로 최적의 성능을 제공하도록 설계되어 있다.
그리고 키-값으로 데이터를 저장하는데, 쿠버네티스의 매니페스트를 살펴보면 apiVersion, kind, metadata, spec으로 이루어져 있는데, 이러한 매니페스트 정보나, 워크로드들의 상태 정보가 구조화된 JSON과 같은 형태로 ETCD에 저장한다. 따라서 kube-apiserver가 특정 워크로드에 대해 확인하는 과정에서 계속 ETCD를 참조할 수 밖에 없는 것이다.
위와 같은 워크로드의 정보 뿐만 아니라 서비스 엔드포인트, 네임스페이스, RBAC(Role-Based Access Control) 정보 그리고 ConfigMap과 Secret까지 모든 설정 파일을 저장하고 있다. ETCD는 클러스터 상태에 대한 단일 진실의 원천(Single Source of Truth) 역할을 한다.
이러한 ETCD를 안전하게 지켜내는 것이 데브옵스의 숙명이며, 쿠버네티스는 이러한 과정을 돕기 위해서 ETCD에 다양한 Raft 알고리즘을 추가하였다.
ETCD 확인 ( minikube를 사용하는 경우 )
ETCD에 대한 간단한 설명이 끝났으니, 이제 직접 워크로드로써 확인을 해보자. ETCD는 kube-system 네임스페이스에서 동작하기 때문에 위의 명령어를 써서 확인할 수 있다.
또한, 해당 etcd-minikube( 쿠버네티스를 사용한다면 etcd-k8s-master일 것이다 )는 deployment 같은 매니페스트를 통해서 실행되는 것이 아니라 Static Pod이라는 설정으로 실행되고 있는 상황이다. Static Pod는 kube-apiserver에서 직접적으로 관리되지 않는 특별한 Pod를 의미하는데, 이 특별한 Pod는 각 노드에 있는 Kubelet이 해당 노드에 있는 특정 디렉토리(/etc/kubernetes/manifests)에 있는 yaml 파일을 읽어 기본적으로 생성하는 것을 의미한다.
ETCD가 데이터를 저장하는 경우는 일반적으로 /var/lib/etcd/ 에서 확인할 수 있다. K8s의 마스터 노드에서 작업하는 경우가 아니라 minikube를 사용하는 사람의 경우 아래의 레퍼런스를 참고하여 직접 컨테이너 안에서 확인해봐야 etcd의 파일들을 확인할 수 있다.
- [hmcardle] Accessing-minikube-etcd-database-in-kubernetes : https://hmcardle.com/accessing-minikube-etcd-database-in-kubernetes
Accessing Minikube ETCD Database in Kubernetes
Look directly into ETCD, the backbone of your Kubernetes cluster
hmcardle.com
나의 경우에는 미니쿠베를 사용하기 때문에 docker exec it을 통해 직접 미니쿠베 컨테이너에 접속하여 확인하였다. 아래와 같이 etcd의 정보를 확인할 수 있었다.
위와 같은 형식으로 etcd는 백업 파일을 저장한다. 이러한 etcd의 직접적인 관리는 etcdctl을 설치하여 관리한다. ETCD는 쿠버네티스 환경에서 모든 상태를 관리하는 원천이기 때문에 잘 보관하는 것도 중요하며, 백업 및 복구도 기본적으로 잘 알아두어야 한다. 그렇다면 이렇게 심장과도 같은 ETCD가 안전하게 고가용성을 유지하는 비밀에 대해서 알아보자.
ETCD Cluster
시나리오에 따라 쿠버네티스 클러스터를 구성하는 방법은 천차 만별이지만, 일반적으로 ETCD는 3개 혹은 5개로 별도의 서버를 구축하는 것이 좋다고 알려져 있다. 이러한 이유는 ETCD의 Leader Election(리더 선출)에서 온다.
먼저, 다른 데이터베이스와 마찬가지로 컴퓨터공학의 기본적인 난제가 있다. 하나의 데이터베이스에 동시에 쓰기 작업이 일어나면 어떻게 할 것인가? 정말 골치 아픈 문제이다. 운영체제, 컴퓨터구조 등 그 어떤 과목을 들어도 항상 나오는 단골 문제이다. 이러한 문제를 해결하기 위해서 인프라의 다양한 컴포넌트들은 읽기와 쓰기를 분리하는 구조를 택한다.
그 중에서 ETCD도 읽기와 쓰기를 분리하는 구조를 지원하고 이를 권고하는데, ETCD가 여러 개 있다면 서로 통신을 통해서 Leader가 되는 ETCD를 정하고 쓰기 작업은 모두 Leader가 담당한다. 그리고 나머지는 Follower가 되어 리더가 전송하는 로그 복제 명령을 수동적으로 따르며 Follower들은 읽기 전용으로 분리된다.
위와 같이 Leader가 된 ETCD는 쓰기를 담당하여 직접 데이터를 받는다. 그 후 Follower들에게 지속적으로 데이터를 나눠주어 읽기 전용 작업들은 Follower에서 가져오는 것으로 ETCD Cluster는 운영된다.
여기서 갑자기 ETCD가 하나 다운된다면, 어떻게 될까? 그것도 쓰기 작업을 담당하는 Leader가? 그 경우에는 남아있는 ETCD가 Leader Election을 통해서 또 다른 Leader를 선출한다.
ETCD Leader Election
이제 본격적으로 ETCD의 Leader Election(이하 리더 선출)에 대해서 알아보자. ETCD가 세 개라고 가정하면 다음과 같은 방식으로 ETCD는 리더를 선출한다. 간단하게 그림으로 알아보자면 아래와 같다.
ETCD가 위와 같이 세 개가 있다. ETCD는 일반적으로 2379 포트를 통해서 연결할 수 있고, ETCD는 서로 2380 포트로 통신한다. 이렇게 ETCD가 통신하는 다른 ETCD는 peer라고 부른다. 위와 같이 연결되어 있는 구성에서 각 ETCD는 연결되어 있는 모든 ETCD에서 통신을 보낸다. 이를 RequestVote RPC Call이라고 하는데, 이렇게 RequestVote에 대한 응답으로 가장 많은 콜백을 받은 ETCD가 리더가 된다.
왼쪽 아래의 ETCD가 먼저 콜백을 두 개 다 받아, 리더가 됐다고 가정하자. 이로 인해 나머지는 리더가 보내주는 데이터를 통해서 팔로워는 최신의 데이터를 유지한다. 여기까지 너무나 좋다. 다음 시나리오로 만약을 가정해서 ETCD가 다운되는 상황을 생각해 보자. 만약에 여기서 리더가 다운되면 어떻게 될까?
그렇다면 똑같이 남아있는 두 ETCD가 서로 RequestVote RPC call을 통해서 리더를 정하게 된다.
이렇게 세 개로 유지되어 있다고 가정하면 읽기를 위한 팔로워와 쓰기를 위한 팔로워가 분리되면서 가용성을 고려할 수 있게 된다. 여기서 다시 다운되었던 기존의 리더가 돌아온다고 하더라도 이미 리더가 있기 때문에 팔로워로서 참여하게 된다.
여기서 간단하게 설명하기 위해서 많은 키워드를 뺐지만, 왜 ETCD cluster는 다섯 개 혹은 세 개가 좋은지에 대해서 설명하기 위해서는 quorum에 대해 설명해야 한다. 이는 한글로 생각하면 정족수라고 볼 수 있겠다. 앞서 많은 RequestVote 콜백을 받아야 리더가 된다고 설명했지만, 사실 quorum을 넘는 만큼의 콜백을 받아야 한다. quorum은 일반적으로 N/2+1 ( 반올림 ) 으로 생각할 수 있다.
quorum은 내결함성(Fault tolerance)과도 연결된다. 특정 노드가 다운되더라도 이로 인하여 클러스터가 중지하지 않고 정상적으로 동작하며 새롭게 ETCD가 돌아올 때까지 잘 동작하는 상황을 말한다. 이러한 특징과 함께 고가용성(High Availiable)을 유지한다. 이러한 내결함성을 판단하는 기준이 바로 정족수이다. 앞서 3인 경우의 정족수는 2로써, 하나가 다운되어 두 개의 ETCD가 남아 있다고 하더라도 둘이 정족수를 맞춰서 리더 선출을 할 수 있다.
반대로 ETCD가 두 개 남아있다면 어떻게 할까? 정족수는 2이기 때문에 하나가 다운되면 제기능을 할 수 없다. 그렇다면 네 개가 남아있다면? 정족수는 3이기 때문에 리더 ETCD가 다운되더라도 남아있는 ETCD 끼리 리더 선출이 가능하지만 또 다른 문제가 발생한다. 그것은 바로 네트워크를 분리했을 때 문제가 생긴다는 것이다. 그것은 결함 비율에 대해서 생각해 보자.
Manager | Majority | Fault Tolerance |
1 | 1 | 0 |
2 | 2 | 0 |
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 2 |
7 | 4 | 3 |
위 표를 생각해 보면 3과 5 그리고 7이 좋다는 것을 설명할 수 있다. 예를 들어 일곱 개와 여섯 개를 비교하면 정족수(여기서는 Majority라고 썼다)는 똑같이 4지만, 내결함성은 1이 차이가 난다. 그림으로 살펴보자.
위와 같이 여섯 개의 ETCD가 있는 경우에는 내결함성이 2이다. 따라서 네트워크가 쪼개지거나 이동하면서 ETCD가 유실되어도 버틸 수 있는 개수가 최대 2개이다.
따라서 위와 같이 네트워크가 이동하여 세 개가 떨어져 나가는 경우에는 클러스터는 가용성을 되찾을 수 없다. 반대로 일곱 개라면?
여섯 개와 다르게, 한 끗차이로 아래의 네트워크에서 정족수를 채울 수 있기 때문에 내결함성이 3인 일곱 개의 경우는 세 개가 떨어져 나가더라도 가용성을 유지할 수 있다. 이러한 이유로 3,5,7과 같은 홀수의 ETCD 클러스터를 유지하는 것을 권장하며 일반적인 경우는 3개 아니면 5개 정도면 충분하다고 한다.
마치며
ETCD 생태계에는 정족수도 있고, 리더 선출도 있고 투표도 있다. 생각보다 민주적인 친구들이다. 어떻게 이렇게 구현할 생각을 했을까?
또한 참고로 달아두었던 카카오 테크의 글이 정말 잘 쓰여있다. 이번 포스팅은 최대한 간추려서 ETCD의 Leader Election에 대해서 다루었지만 보다 깊은 내용이 필요하다고 하면 참고에 있는 kakao tech를 꼭 참고하길 바란다. ( 정말 잘 쓰여있음 )
참고
- [kubernetes] 쿠버네티스 컴포넌트 : https://kubernetes.io/ko/docs/concepts/overview/components/
- [hmcardle] accessing minikube etcd database in kubernetes : https://hmcardle.com/accessing-minikube-etcd-database-in-kubernetes
- [kakao tech] Kubernetes 운영을 위한 etcd 기본 동작 원리의 이해 : https://tech.kakao.com/posts/484
- [kkimoy991] etcd : https://velog.io/@kkimoy991/etcd
감사합니다.
'DevOps > kubernetes' 카테고리의 다른 글
[CKA] 기출 문제 정리 (0) | 2025.01.12 |
---|---|
쿠버네티스의 Kustomize에 대해서 (1) | 2024.12.20 |
Kubernetes의 Ingress와 Service 차이점에 대한 고찰 (0) | 2024.12.17 |
로컬 쿠버네티스 클러스터 환경 세팅 ( feat. minikube, lens ) (1) | 2024.12.16 |
[K8s homeserver 구축 - 3] github actions를 통한 CI (0) | 2023.11.10 |