지난 글 Kubernetes Cluster에서 Master Node는 클러스터의 Control Plane이라 했으며, 구성 요소들도 대강 함께 알아보았는데 이번에는 각 구성요소들을 더 자세히 알아보겠다.
etcd
: 키-값 형태의 데이터베이스로 클러스터 안의 구성정보들을 저장한다.scheduler(kube-scheduler)
: 애플리케이션 구동에 필요한 각 컨테이너들에대해 클러스터 내 최적의 배포를 수행하는 스케쥴러controller-manager
: Node, Deployment, Service Account 등 클러스터에 구동되는 리소스들을 유지 관리하는 프로세스들의 집합kube-dns
: 클러스터 안에 특정 DNS를 찾는데 사용되는 네임 서버 (구성도에는kube-dns
라 되어 있으나, 쿠버네티스1.12
버전부터는CoreDNS
로 대체됨)api-server
: 클러스터 구성 요소들의 상호 통신에 필요한 쿠버네티스 API를 관리하는 컴포넌트
etcd
etcd는 클러스터의 각 구성요소들의 정보가 키-값 형태로 저장된 데이터베이스다.
즉, 클러스터의 핵심 데이터들이 모두 이 곳에 저장되어 있는 것이다.
쿠버네티스에서는 클러스터에 노드가 몇 개인지, 각각 파드들이 어떤 컨테이너를 들고 어느 노드에 어떻게 동작하고 있는지 등등 모두 etcd에 기록된다. kubectl
명령을 통해서 조회 가능한 모든 정보는 모두 etcd를 겨쳐 온다.
제어 명령을 통해 클러스터에 변화가 적용되었다면 etcd에 업데이트가 된다.
만약 etcd가 유실된다면 클러스터에 대한 모든 구성 요소들을 함께 잃어버리게 된다.
쿠버네티스 클러스터를 구축할 때는 etcd의 고가용성을 어떻게 확보할 것인지를 반드시 고민해야한다.
쿠버네티스의 공식문서에서는 두 가지 방법을 소개하고 있으며 공통적으로 최소 3개 이상의 컨트롤 플레인을 갖춘 마스터 노드 구성을 권고한다.
- 중첩(stacked) etcd 토폴리지: 각 컨트롤 플래인 노드마다 etcd 파드가 함께 생성되어 스택된 형태의 클러스터로 구성하는 방식이다. 구현이 간단하고 인프라 자원 소모도 상대적으로 적지만, 노드가 죽으면 컨트롤 플래인 인스턴스와 etcd를 함께 잃어버리므로 중복성 이슈가 발생한다. 이를 상쇄하고 고가용성을 유지하려면 가급적 많은 수의 컨트롤 플래인 노드를 동시에 운영해야한다.
- 외부(external) etcd 토폴리지: 각 컨트롤 플레인 노드에 대응되는 etcd 파드를 함께 묶어서 별도의 클러스터를 따로 생성하고
kube-apiserver
로 이들을 연동하는 방식이다. 1번 방식에 비해 노드 상태에 따른 중복성 이슈 영향이 덜하지만, 노드 숫자 만큼 etcd 멤버를 별도 클러스터로 구성해야하므로 인프라 자원이 2배의 인프라 자원과 비용을 더 소모하게 된다.
kubeadm
에서는 1번 방식을 기본값으로 하고 있으며, 실제 상용 환경에서는 1번 방식에 L4 스위치를 결합한 형태를 주로 선호하는 것으로 알려져 있다.kubeadm
을 통해 설치된 클러스터에서 1번 방식을 따랐을 경우, etcd 또한kube-system
네임스페이스에 속한etcd-master
이름의 파드 형태로 배포된다.
스케줄러 (kube-scheduler)
파드를 어느 노드에 배치할 지 결정하는 프로세스다.
결정만 한다는 점을 주의해야한다. 실제로 파드를 노드에 배치하는 역할은 kubelet이 수행한다.
스케줄러가 파드를 노드에 배치하는 우선순위는 다음과 같다. 물론 여기에 적용되는 기준은 필요에 따라 우회하거나 변경할 수 있다.
- 파드가 요구하는 컴퓨팅 자원(CPU, Memory ..) 기준으로 필터링
- 파드가 배치된 이후 해당 노드에 남게 될 잔여 컴퓨팅 자원의 양을 기준으로 우선순위 책정
스케줄러는 기본적으로 kube-system
네임스페이스에 kube-controller-scheduler-master
파드로 존재한다. 이 파드로 정의한 파일(yaml) 위치는 클러스터 구축 방법에 따라 다르다.
kubeadm
으로 구축했다면/etc/kubernetes/manifests/kube-scheduler.yaml
에 존재한다.- 그 외의 방법으로 구축했다면
/etc/systemd/system/kube-scheduler.service
에 존재한다.
컨트롤러 매니저 (kube-controller-manager)
클러스터 안에서 구동되는 다양한 리소스들을 모니터링하며 이들이 원활하게 동작하도록 관리하는 프로세스다.
노드(Node), 레플리카셋(ReplicaSet), 디플로이먼트(Deployment), 스테이트풀셋(StatefulSet), 데몬셋(DaemonSet), 서비스 어카운트(Service Account), 크론잡(Cronjob), 네임스페이스(Namespace) 등 각 구성 요소들을 관리하는 컨트롤러들이 하나로 패키징된 형태를 가지며, 이는 기능 단위 분산이라는 쿠버네티스의 설계 사상에 따른 것이다.
컨트롤러 매니저 역시 기본적으로 kube-system
네임스페이스에 kube-controller-manager-master
파드로 존재한다. 이 파드의 정의 파일 yaml 위치는 클러스터 구축 방법에 따라 다르다.
kubeadm
으로 구축했다면/etc/kubernetes/manifests/kube-controller-manager.yaml
에 존재한다.- 그 외의 방법으로 구축했다면
/etc/systemd/system/kube-controller-manager.service
에 존재한다.
API 서버 (kube-apiserver)
클러스터의 각 요소들을 모니터링하며 작업을 수행하도록 해주는 중앙 접근 포인트 역할을 한다.
쿠버네티스는 "모든 통신은 API 중심으로 한다"라는 설계 사상을 바탕에 두고 있다.
그렇기에 쿠버네티스는 모든 객체들은 원칙적으로 API를 바라보며 API를 통해서만 통신하도록 한다.
API 서버는 Stateless 특성을 갖고 세션을 유지하는 대신 etcd를 사용한다.
그때그때 데이터를 체크하고 작업을 처리하는 방식이며 복제를 통해 병렬로 확장이 가능한 특징이 있다.
유저 인증, 요청사항 검증, 데이터 수신, etcd 업데이트, 스케줄링, kubelet 통신과 같은 다양한 역할을 담당한다.
주요기능은 다음과 같다.
API 관리
: 서버에서 API를 노출하고 관리하는 프로세스 역할을 한다. 일반적으로 쿠버네티스 API 접근용 포트로 6443을 오픈한다. 다만 별도로 haproxy라는 오픈소스를통해 16443 포트로 접근시 API 서버로 넘어가도록 하는 방법도 활용한다.요청 처리
: 클라이언트의 개별 API 요청을 처리한다. 대부분 HTTP 형태로 이루어지나, 콘텐츠의 경우에는 일부 JSON으로 처리하기도 한다.내부 제어 루프
: API 작동에 필요한 백그라운드 작업도 담당한다. 다만 이 작업은 대부분 컨트롤러 매니저가 대신 수행하는 편이다.
API 서버 또한 클러스터의 kube-system
네임스페이스 안에 파드 형태로 배포된다.
이 파드에 대한 정의 파일 경로는 다음과 같다.
kubeadm
으로 구축했다면/etc/kubernetes/manifests/kube-apiserver.yaml
에 존재한다.- 그 외의 방법으로 구축했다면
/etc/systemd/system/kube-apiserver.service.yaml
에 존재한다.
클러스터에서 API 서버가 동작하는 방식
kubectl
을 이용해 새로운 파드를 생성한다고 가정해보자, 이 경우 API 서버에는 새로운 파드 객체를 만든 뒤 etcd에 새 파드 정보를 업데이트한다. 그 동안 다른 컴포넌트들은 API 서버를 모니터링하면서 변화된 상황에 맞게 각자의 역할을 수행한다. 이러한 작업의 흐름을 좀 더 자세히 살펴보면 다음과 같다.
- API 서버가 먼저 파드 객체를 생성한다.
- API 서버는 etcd에 새 파드가 생성되었음을 업데이트한다.
- 스케쥴러는 API 서버를 모니터링하여, 새 파드가 생겼음을 인지하고 이를 배포할 노드를 확인한다.
- API 서버는 etcd에 정보를 업데이트한다.
- API 서버가 해당 정보를 적합한 노드에 kubelet에 전달한다.
- kubelet이 해당 노드에 파드를 생성하고, 컨테이너 런타임 엔진에 해당 애플리케이션 이미지를 배포하도록 지시한다.
- kubelet은 API 서버에 상태를 업데이트시키고, API 서버는 이 상태 데이터를 etcd에 저장한다.
쿠버네티스에서 일어나는 많은 작업들이 대체로 이러한 흐름을 따른다. 예를 들어 kubectl get
을 실행한다면, API 서버가 해당 요청(request)을 인증/확인 후 etcd
에서 데이터를 검색해 반환하는 식이다. 클러스터 구성 요소들의 동작과 관리에 있어 API 서버의 중요성을 확인할 수 있는 부분이다.
'Server & Infra.' 카테고리의 다른 글
[K8s] Pod 알아보기 (0) | 2024.03.12 |
---|---|
[K8s] 노드 컴포넌트 알아보자 (0) | 2024.03.12 |
[K8s] 쿠버네티스 클러스터 (0) | 2024.03.12 |
Nginx, 아파치와의 관계 알아보기 (0) | 2023.10.06 |
JPA 벌크 수정, 삭제 연산과 영속성 컨텍스트 ✍️ (1) | 2023.08.23 |