Kubernetes Cluster 컴포넌트

seokhyun·2025년 9월 3일

Kubernetes

목록 보기
3/7

이 포스팅에서는 Kubernetes Cluster의 자세한 구성요소에 대해서 알아보자.

Cluster Component

전 포스팅에서 설명한 것 처럼 Cluster Component는 크게 Control Plane과 여러 Node로 구성된다.

Control Plane Component

컨트롤 플레인 컴포넌트는 클러스터에 관한 전반적인 결정(예를 들어, 스케줄링)을 수행하고 클러스터 이벤트(예를 들어, 디플로이먼트의 replicas 필드에 대한 요구 조건이 충족되지 않을 경우 새로운 파드를 구동시키는 것)를 감지하고 반응한다.

컨트롤 플레인 컴포넌트는 클러스터 내 어떠한 머신에서든지 동작할 수 있다. 그러나 간결성을 위하여, 구성 스크립트는 보통 동일 머신 상에 모든 컨트롤 플레인 컴포넌트를 구동시키고, 사용자 컨테이너는 해당 머신 상에 동작시키지 않는다.

NKS(Naver Cloud Platform의 Naver Kubernetes Service)에서는 자체적으로 Control Plane을 마스터 노드에서 관리하며(단일, 다중 가능) 사용자는 관리할 수 없다.

kube-api-server

API 서버는 쿠버네티스 API를 노출하는 쿠버네티스 컨트롤 플레인 컴포넌트이다. API 서버는 쿠버네티스 컨트롤 플레인의 프론트 엔드이다.

쿠버네티스 API 서버의 주요 구현은 kube-apiserver 이다. kube-apiserver는 수평으로 확장되도록 디자인되었다. 즉, 더 많은 인스턴스를 배포해서 확장할 수 있다. 여러 kube-apiserver 인스턴스를 실행하고, 인스턴스간의 트래픽을 균형있게 조절할 수 있다.

즉 kube-apiserver 을 여러 마스터 노드에 각각 배치하여 트래픽을 분산한다는 의미이다.

etcd

모든 클러스터 데이터를 담는 쿠버네티스 뒷단의 저장소로 사용되는 일관성·고가용성 키-값 저장소.

쿠버네티스 클러스터에서 etcd를 뒷단의 저장소로 사용한다면, 이 데이터를 백업하는 계획은 필수이다. 그래서 etcd도 다중으로 두는 편이다.

보통 홀수개를 두며, 장애가 일어나도 과반수 이상이 정상작동하면 Raft 합의 알고리즘에 의해 동기화 된다.

[쓰기 과정]
1. 클라이언트 → Leader에게 쓰기 요청
2. Leader → 모든 Follower에게 로그 엔트리 전송
3. 과반수(2/3)가 "OK" 응답하면 → 커밋
4. Leader → 클라이언트에게 "성공" 응답
5. Leader → Follower들에게 커밋 알림

NKS에서는 Secrets 값을 etcd에 저장하며 kube-api-server로 명령이 온 것은 다 etcd에 기록해둔다.

kube-scheduler

노드가 배정되지 않은 새로 생성된 파드 를 감지하고, 실행할 노드를 선택하는 컨트롤 플레인 컴포넌트. 즉, kubectl에 새로운 파드 생성 요청오면 워커노드 중 어떤 노드 안에 만들지 결정하는 일을 한다. 근데, 사용자가 pod 생성시 직접 정하거나 특정 라벨이 있는 파드(ex, gpu)에 배치하는 걸 결정할 수 도 있음.(ex, nodeSelector, nodeName, Node Affinity 등 조정해서)

스케줄링 결정을 위해서 고려되는 요소는 리소스에 대한 개별 및 총체적 요구 사항, 하드웨어/소프트웨어/정책적 제약, 어피니티(affinity) 및 안티-어피니티(anti-affinity) 명세, 데이터 지역성, 워크로드-간 간섭, 데드라인을 포함한다.

어피니티: 특정 노드를 선호하거나 특정 파드에 가까이 배치해주세요
안티-어피니티: 어피니티와 반대로 비선호, 멀리 배치해주세요

kube-controller-manager

컨트롤러 프로세스를 실행하는 컨트롤 플레인 컴포넌트.

논리적으로, 각 컨트롤러는 분리된 프로세스이지만, 복잡성을 낮추기 위해 모두 단일 바이너리로 컴파일되고 단일 프로세스 내에서 실행된다. > 여러 컨트롤러를 묶어 총괄 관리함

이들 컨트롤러는 다음을 포함한다.

노드 컨트롤러: 노드가 다운되었을 때 통지와 대응에 관한 책임을 가진다.
잡 컨트롤러: 일회성 작업을 나타내는 잡 오브젝트를 감시한 다음, 해당 작업을 완료할 때까지 동작하는 파드를 생성한다.
엔드포인트슬라이스 컨트롤러: (서비스와 파드 사이의 연결고리를 제공하기 위해) 엔드포인트슬라이스(EndpointSlice) 오브젝트를 채운다
서비스어카운트 컨트롤러: 새로운 네임스페이스에 대한 기본 서비스어카운트(ServiceAccount)를 생성한다.

cloud-controller-manager

클라우드별 컨트롤 로직을 포함하는 쿠버네티스 컨트롤 플레인 컴포넌트이다. 클라우드 컨트롤러 매니저를 통해 클러스터를 Cloud Provider API에 연결하고, 해당 클라우드 플랫폼과 상호 작용하는 컴포넌트와 클러스터와만 상호 작용하는 컴포넌트를 구분할 수 있게 해 준다.
cloud-controller-manager는 클라우드 제공자 전용 컨트롤러만 실행한다. 자신의 사내 또는 PC 내부의 학습 환경에서 쿠버네티스를 실행 중인 경우 클러스터에는 클라우드 컨트롤러 매니저가 없다.

kube-controller-manager와 마찬가지로 cloud-controller-manager는 논리적으로 독립적인 여러 컨트롤 루프를 단일 프로세스로 실행하는 단일 바이너리로 결합한다. 수평으로 확장(두 개 이상의 복제 실행)해서 성능을 향상시키거나 장애를 견딜 수 있다.

다음 컨트롤러들은 클라우드 제공 사업자의 의존성을 가질 수 있다.

노드 컨트롤러: 노드가 응답을 멈춘 후 클라우드 상에서 삭제되었는지 판별하기 위해 클라우드 제공 사업자에게 확인하는 것
라우트 컨트롤러: 기본 클라우드 인프라에 경로를 구성하는 것
서비스 컨트롤러: 클라우드 제공 사업자 로드밸런서를 생성, 업데이트 그리고 삭제하는 것

그니까 우리가 어떤 클라우드 플랫폼에서 쿠버네티스를 구축하면 kubectl로 표준 쿠버네티스 명령을 보내게 돼. 이때 kube-apiserver를 통해 etcd에 저장된 쿠버네티스 오브젝트의 변화를 감지해서, 해당 클라우드 플랫폼(AWS, GCP, NCP 등)의 API를 직접 호출하여 실제 클라우드 리소스를 생성하거나 관리하는 역할을 해.
여기서 주의해야할거는 일반적인 쿠버네티스 오브젝트들은 kubelet이 실제로 만드는데 클라우드 의존적인 오브젝트(LoadBalancer Service, PVC 등)는 CLOUD PROVIDER API를 호출해서 생성한다는거야. 그래서 LoadBalnacer가 처음에 pending 이였다가 외부 IP 할당되는 거야.

Node Component

노드 컴포넌트는 동작 중인 파드를 유지시키고 쿠버네티스 런타임 환경을 제공하며, 모든 노드 상에서 동작한다.

kubelet

클러스터의 각 노드에서 실행되는 에이전트. Kubelet은 파드에서 컨테이너가 확실하게 동작하도록 관리한다.

Kubelet은 다양한 메커니즘을 통해 제공된 파드 스펙(PodSpec)의 집합을 받아서 컨테이너가 해당 파드 스펙에 따라 건강하게 동작하는 것을 확실히 한다. Kubelet은 쿠버네티스를 통해 생성되지 않는 컨테이너는 관리하지 않는다.
즉, 파드를 실행하고 관리도 하고, 컨테이너의 라이프사이클을 관리하고, Pod의 상태를 주기적으로 API 서버에 보고함.

[진행과정]

  1. kubectl create deployment nginx --image=nginx
  2. kube-apiserver가 etcd에 Deployment 저장
  3. scheduler가 Node1에 배치 결정
  4. Node1의 kubelet이 감지: "내가 nginx Pod 만들어야 하네!"
  5. kubelet → Docker/containerd → 실제 nginx 컨테이너 실행

kube-proxy

kube-proxy는 클러스터의 각 노드에서 실행되는 네트워크 프록시로, 쿠버네티스의 서비스 개념의 구현부이다.

kube-proxy는 노드의 네트워크 규칙을 유지 관리한다. 이 네트워크 규칙이 내부 네트워크 세션이나 클러스터 바깥에서 파드로 네트워크 통신을 할 수 있도록 해준다.

kube-proxy는 운영 체제에 가용한 패킷 필터링 계층이 있는 경우, 이를 사용한다 > iptables 모드). 그렇지 않으면, kube-proxy는 트래픽 자체를 포워드(forward)한다 > 직접 포워딩 모드.
보통 iptables 모드를 사용하여 빠르게 처리.

CRI(Container Runtime Interface)

CRI(Container Runtime Interface)는 쉽게 말해서 "Kubernetes가 다양한 컨테이너 런타임과 대화하기 위한 공통 언어/규칙"

CRI( 컨테이너 런타임 인터페이스 )는 추가될 사양/요구 사항, 프로토콜 버퍼 API , 그리고 노드에서 kubelet과 통합하기 위한 컨테이너 런타임 라이브러리 로 구성됩니다 . CRI API는 현재 알파 버전이며, 쿠버네티스 1.7 이상 버전부터는 CRI-Docker 통합이 기본적으로 사용됩니다.

만약 CRI 없다면:
각 런타임마다 kubelet 코드 수정 필요
kubelet ←→ Docker (전용 코드)
kubelet ←→ containerd (전용 코드)
kubelet ←→ CRI-O (전용 코드)
→ 유지보수 지옥! 😱

CRI로 해결:
표준 인터페이스 제공:
kubelet ←→ [CRI 표준] ←→ Docker or containerd or CRI-O

앞으로 CRI 검증 테스트 등 더 많은 개발자 도구를 추가할 계획입니다.

Container Runtime

컨테이너 런타임은 컨테이너 실행을 담당하는 소프트웨어이다.

쿠버네티스는 containerd, CRI-O와 같은 컨테이너 런타임 및 모든 Kubernetes CRI (컨테이너 런타임 인터페이스) 구현체를 지원한다.

현재 쿠버네티스는 dockershim 을 없애고 containerd(고수준 런타임) + runC(저수준 런타임) 로 컨테이너를 실행한다.

profile
개발자 하고싶어 응애

0개의 댓글