아키텍처 (Architecture)
아키텍처 (Architecture)
출처: Kubernetes 공식 문서 — Cluster Architecture (원문을 한국어로 재구성했습니다)
쿠버네티스 클러스터를 처음 마주하면 '도대체 뭐가 어디서 돌아가는 거지?' 싶을 때가 있어요. 이 글에서는 클러스터를 이루는 구성 요소를 하나씩 짚어가며, 그 역할이 왜 그런 자리에 있는지 옆에서 설명해 드릴게요.
클러스터는 무엇으로 이루어져 있나요
쿠버네티스 클러스터는 크게 두 층으로 나뉘어요. 하나는 컨트롤 플레인(control plane), 다른 하나는 실제 작업을 하는 노드(node) 들이에요.
- 컨트롤 플레인은 클러스터 전체의 '두뇌'예요. 스케줄링 같은 전역적인 결정을 내리고, 클러스터에서 일어나는 이벤트를 감지해서 응답해요. 예를 들어 Deployment의
replicas값이 맞지 않으면 새 파드를 띄우는 식으로요. - 노드(worker node) 는 컨테이너화된 애플리케이션을 실제로 돌리는 머신들이에요. 이 노드들이 파드(Pod)를 호스팅하면서 애플리케이션 워크로드의 구성 요소가 됩니다.
모든 클러스터는 파드를 실행하기 위해 최소한 하나의 워커 노드가 필요해요. 프로덕션 환경에서는 컨트롤 플레인이 보통 여러 대의 컴퓨터에서, 그리고 클러스터도 여러 노드 위에서 운영돼요. 그래야 장애가 나도 서비스가 멈추지 않는 내결함성(fault-tolerance)과 고가용성(high availability) 을 얻을 수 있어요.
한 가지 짚어둘 점: 각 노드에는 kube-proxy라는 네트워크 프록시가 돌아가요. Service API와 그에 딸린 동작이 클러스터 네트워크에서 동작하려면 각 노드에 이런 네트워크 프록시가 필요하거든요. 다만 일부 네트워크 플러그인은 자체적인 프록시 구현을 제공하기도 해요.
컨트롤 플레인 컴포넌트
컨트롤 플레인의 컴포넌트들은 클러스터 전체에 대한 결정을 내리고(예: 스케줄링), 클러스터 이벤트를 감지해 응답해요(예: Deployment의 replicas가 충족되지 않았을 때 새 파드를 시작). 이 컴포넌트들은 클러스터의 어떤 머신에서든 실행될 수 있지만, 간단하게 만들기 위해 보통 설정 스크립트가 전부 같은 머신에서 시작하고, 그 머신에는 사용자 컨테이너를 두지 않아요.
kube-apiserver
API 서버는 쿠버네티스 API를 노출하는 컨트롤 플레인 컴포넌트예요. 컨트롤 플레인의 '정문(front end)' 역할을 하죠. 쿠버네티스 API 서버의 주 구현체가 바로 kube-apiserver예요.
kube-apiserver는 수평 확장을 하도록 설계됐어요. 즉, 인스턴스를 더 많이 배치해서 확장하는 구조죠. 여러 인스턴스를 띄워서 그 사이에 트래픽을 분산시킬 수 있어요.
etcd
etcd는 일관성 있고(consistent) 고가용성인(highly-available) 키-값 저장소로, 쿠버네티스의 모든 클러스터 데이터를 담는 백킹 스토어(backing store) 역할을 해요. 클러스터가 등을 기대는 저장소인 만큼, etcd를 백킹 스토어로 쓴다면 데이터 백업 계획을 반드시 세워 두어야 해요. etcd에 대한 자세한 내용은 공식 문서에서 확인할 수 있어요.
kube-scheduler
kube-scheduler는 아직 노드가 배정되지 않은 새 파드를 감시하다가, 그 파드가 실행될 노드를 선택해 주는 컨트롤 플레인 컴포넌트예요.
노드를 고를 때는 개별·집합적인 리소스 요구량(CPU, 메모리 등), 하드웨어·소프트웨어·정책상의 제약, 어피니티(affinity)와 안티-어피니티(anti-affinity) 명세, 데이터 지역성(data locality), 워크로드 간 간섭, 데드라인 같은 요소를 종합적으로 고려해요.
kube-controller-manager
컨트롤러 프로세스들을 실행하는 컨트롤 플레인 컴포넌트예요. 논리적으로는 각 컨트롤러가 별도의 프로세스지만, 복잡도를 줄이기 위해 모두 단일 바이너리로 컴파일되어 하나의 프로세스로 실행돼요.
컨트롤러에는 여러 종류가 있어요. 예를 들면:
- Node controller: 노드가 다운됐는지 감지하고 응답하는 역할을 해요.
- Job controller: 일회성 작업을 나타내는 Job 오브젝트를 감시하다가, 그 작업을 끝까지 수행할 파드를 만들어요.
- EndpointSlice controller: Service와 Pod 사이를 연결하는 EndpointSlice 오브젝트를 채워 넣어요.
- ServiceAccount controller: 새 네임스페이스에 기본 ServiceAccount를 만들어 줘요.
cloud-controller-manager
클라우드 특유의 제어 로직을 담고 있는 컨트롤 플레인 컴포넌트예요. 이 컴포넌트를 통해 쿠버네티스를 특정 클라우드 제공자(cloud provider)와 연결할 수 있어요.
kube-controller-manager와 마찬가지로, 논리적으로 독립된 여러 제어 루프를 하나의 바이너리로 합쳐 단일 프로세스로 실행해요. 성능을 올리거나 장애를 견디기 위해 수평 확장(복사본을 더 띄움) 도 가능해요.
- Node controller: 노드가 응답을 멈췄을 때 클라우드 제공자에서 해당 노드가 삭제됐는지 확인해요.
- Route controller: 기반 클라우드 인프라에 라우트를 설정해요.
- Service controller: 클라우드 제공자의 로드 밸런서를 생성·업데이트·삭제해요.
노드 컴포넌트
노드 컴포넌트는 모든 노드에서 실행되며, 실행 중인 파드를 유지하고 쿠버네티스 런타임 환경을 제공해요.
kubelet
kubelet은 여러 메커니즘으로 전달된 PodSpec 집합을 받아서, 그 PodSpec이 기술한 컨테이너가 실행 중이고 정상(healthy)인지 보장해요. 여기서 중요한 게 하나 있어요. kubelet은 쿠버네티스가 만든 컨테이너만 관리하고, 쿠버네티스가 만들지 않은 컨테이너는 건드리지 않아요.
kube-proxy (선택)
kube-proxy는 클러스터의 각 노드에서 실행되는 네트워크 프록시로, 쿠버네티스 Service 개념의 일부를 구현해요. 노드에 네트워크 규칙을 유지해서, 클러스터 안팎의 네트워크 세션에서 파드로 통신이 가능하게 해 줘요.
컨테이너 런타임 (Container runtime)
쿠버네티스가 컨테이너를 제대로 실행하도록 돕는 핵심 컴포넌트예요. 쿠버네티스 환경 안에서 컨테이너의 실행과 수명주기(lifecycle)를 관리하는 책임을 져요. 쿠버네티스는 containerd, CRI-O 같은 컨테이너 런타임을 지원해요.
애드온(Addons)
여기까지가 핵심 구성 요소라면, 애드온은 클러스터에 기능을 얹어 주는 보조 요소들이에요.
Web UI (Dashboard)
클러스터를 위한 범용 웹 UI예요. 클러스터 안에서 돌아가는 애플리케이션과 클러스터 자체를 관리하고 문제를 해결(troubleshoot)할 수 있게 해 줘요.
네트워크 플러그인 (Network plugins)
컨테이너 네트워크 인터페이스(CNI, Container Network Interface) 스펙을 구현하는 소프트웨어 컴포넌트예요. 파드에 IP 주소를 할당하고, 파드끼리 클러스터 안에서 서로 통신할 수 있게 해 줘요.
아키텍처의 변형들
쿠버네티스 아키텍처는 이렇게 고정된 게 아니라, 상황에 맞게 배치 방식을 바꿀 수 있어요.
컨트롤 플레인 배포 옵션
- 전통적 배포(Traditional deployment): 컨트롤 플레인 컴포넌트를 전용 머신이나 VM에 직접 실행하고, 흔히 systemd 서비스로 관리해요.
- 정적 파드(Static Pods): 컨트롤 플레인 컴포넌트를 정적 파드로 배포하고, 특정 노드의 kubelet이 관리해요. kubeadm 같은 도구가 쓰는 흔한 방식이에요.
- 셀프 호스팅(Self-hosted): 컨트롤 플레인이 쿠버네티스 클러스터 자체 안에서 파드로, Deployment와 StatefulSet 같은 쿠버네티스 프리미티브로 관리돼요.
- 관리형 쿠버네티스 서비스(Managed Kubernetes services): 클라우드 제공자가 컨트롤 플레인을 추상화해서, 서비스 일부로 관리해 줘요.
클러스터 관리 도구
kubeadm, kops, Kubespray 같은 도구들은 클러스터를 배포·관리하는 서로 다른 접근법을 제공하며, 각자 구성 요소 배치와 관리 방식이 달라요.
커스터마이징과 확장성
- 커스텀 스케줄러를 기본 스케줄러와 함께, 또는 완전히 대체해서 배포할 수 있어요.
- API 서버는 CustomResourceDefinition과 API Aggregation으로 확장할 수 있어요.
- 클라우드 제공자는 cloud-controller-manager를 통해 쿠버네티스와 깊게 통합할 수 있어요.
이런 유연성 덕분에 조직은 운영 복잡성, 성능, 관리 오버헤드 같은 요소를 저울질하면서 클러스터를 자기 필요에 맞게 조정할 수 있어요.
다음으로 볼 것
아키텍처의 큰 그림을 잡았다면, 그다음은 이렇게 이어서 보면 좋아요.
- 노드(Node)와 컨트롤 플레인의 통신
- 쿠버네티스 컨트롤러(controllers)
- 클러스터 오브젝트의 가비지 컬렉션
- 쿠버네티스의 기본 스케줄러인 kube-scheduler
- etcd 공식 문서
- 쿠버네티스의 여러 컨테이너 런타임