개발 도구 & 환경

[K8S]클러스터 아키텍처

나맘임 2026. 6. 21. 15:28

쿠버네티스 백엔드 구조와 설계에 대한 공부 내용을 정리했습니다.


컨트롤 플레인과 워커 노드

쿠버네티스 클러스터는 컨트롤 플레인과 워커 노드로 구성되어 있다.

워커 노드들은 우리가 원하는 애플리케이션의 이미지 기반의 컨테이너화된 애플리케이션을 실행한다.

모든 클러스터는 파드를 실행하기 위해 최소한 하나의 워커 노드가 필요하다.

워커 노드는 애플리케이션 워크로드의 구성 요소인 파드를 호스팅한다.

컨트롤 플레인은 클러스터 내의 워커 노드와 파드를 관리한다. 

프로덕션 환경에서, 컨트롤 플레인은 보통 여러 대의 컴퓨터에서 실행되며, 클러스터는 일반적으로 여러 개의 노드를 실행하며 장애를 컨트롤하고 고가용성을 제공한다.

 

노드와 파드
노드는 서버(컴퓨터), 파드는 그 위에서 돌아가는 앱 실행 단위다.
보통 노드는 마스터 노드(컨트롤 플레인이 설치된), 워커 노드(실제 애플리케이션인 파드가 돌아가는 데이터 플레인)으로 분리된다.

 

컨트롤 플레인 컴포넌트

컨트롤 플레인 컴포넌트는 클러스터에 대한 스케줄링, 이벤트 감지&대응과 같은 전역적인 작업을 한다.

동시에 클러스터 안의 어떤 머신에서도 실행될 수 있다.

그러나 (컨트롤 플레인 컴포넌트가 실행하는) 설정 스크립트를 일반적으로 동일한 머신에서 실행하기 때문에, 이 머신에서는 사용자 컨테이너를 실행하지 않는다.

즉, 일반적으론 여러 머신에 걸쳐 컨트롤 플레인을 실행하지 않는다.

물론 여러 머신 환경에서 구축할 수도 있다.

kube-api-server

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

모든 통신은 여기를 걸쳐 간다고 보면 된다.

api-server 또한 한 인스턴스가 아닌 더 많은 인스턴스를 배포해서 확장할 수 있다.

etcd

모든 클러스터 데이터를 담는 쿠버네티스 백엔드 저장소이다.

키-값(Key-Value) 형태의 저장소로 일관성, 고가용성 확보에 필수적이다.

프로덕션 환경에선 이 데이터를 백업하는 건 필수이다.

kube-scheduler

노드가 배정되지 않은 새로 생성된 파드를 감지하고, 실행할 노드를 선택하는 컨트롤 플레인 컴포넌트이다.

이름대로 작업들의 스케줄링을 하는데, 리소스에 대한 요구사항, 하드웨어, 정책, 어피니티(Affinity) 명세 등을 고려한다고 알려져있다.

 

어피니티(Affinity)
쿠버네티스에서 파드를 어느 노드에 스케줄링할지 선호도 규칙을 통해 제어하는 기능
파드 쪽에서 노드를 선택하는 방식으로, Taint/Toleration가 노드 쪽에서 파드를 밀어내는 방식과 대조된다.

 

kube-controller-manager

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

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

컨트롤러에는 여러 가지 유형이 있다. 몇 가지 예시는 다음과 같다.

  • 노드 컨트롤러(Node Controller): 노드가 다운될 때 이를 감지하고 대응한다.
  • 잡 컨트롤러(Job Controller): 일회성 작업을 나타내는 잡(Job) 오브젝트를 감시하고, 해당 작업을 수행하기 위한 파드를 생성한다.
  • 엔드포인트슬라이스 컨트롤러(EndpointSlice controller): 엔드포인트슬라이스 오브젝트를 채워서 파드와 서비스 사이의 연결을 제공한다.
  • 서비스어카운트 컨트롤러(ServiceAccount controller): 신규 네임스페이스에 기본 서비스어카운트를 생성한다.

노드 컴포넌트

kubelet

클러스터의 각 노드에서 실행되는 에이전트. 

Kubelet은 파드에서 컨테이너가 확실하게 동작하도록 관리.

Kubelet은 다양한 메커니즘을 통해 제공된 파드 스펙(PodSpec)의 집합을 받아서 컨테이너가 해당 파드 스펙에 따라 건강하게 동작하는 것을 확실히 한다.

이때, Kubelet은 쿠버네티스를 통해 생성되지 않는 컨테이너는 관리하지 않는다.

kube-proxy

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

노드의 네트워크 규칙을 유지 관리한다.

이 네트워크 규칙이 내부 네트워크 세션이나 클러스터 바깥에서 파드로 네트워크 통신을 할 수 있도록 해줌.

운영 체제에 가용한 패킷 필터링 계층이 있는 경우, 이를 사용함.

그렇지 않으면 kube-proxy는 트래픽 자체를 포워드 함.

서비스에 대한 패킷 포워딩을 자체적으로 구현하고, kube-proxy와 동등한 동작을 제공하는 네트워크 플러그인(Flannel 등)을 사용하면 kube-proxy를 사용할 필요 없다.

컨테이너 런타임

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

docker를 과거에 많이 사용했다면 이제는 containered 위주이다.

컨트롤 플레인-노드 간 통신

노드에서 컨트롤 플레인으로의 통신

쿠버네티스는 hub-and-spoke API 패턴을 기반으로 노드의 모든 API 사용은 API 서버에서 종료되도록 되어있다.

다른 컨트롤 플레인 컴포넌트 중 어느 것도 원격 서비스를 노출하도록 설계되지 않았다.

API 서버는 하나 이상의 클라이언트 인증 형식이 활성화된 보안 HTTPS 포트에서 원격 연결을 수신하도록 구성됨.

따라서 노드가 유효한 자격 증명과 함께 API 서버에 안전하게 연결할 수 있도록 클러스터에 대한 공개 루트 인증서를 미리 셋팅(프로비전)해야 한다.

kubelet 클라이언트 인증서를 넣어주면 되는데 kubeadm의 init / join을 쓰면 자동으로 처리하지만 TLS 부트스트랩을 만들거나 수동으로 인증서를 셋팅할 수도 있다.

네트워크 환경 여건 상 자동으로 처리되지 않는 경우들도 많으므로 수동 셋팅하는 방법을 알아두면 좋다.

 

결과적으로, 노드 및 노드에서 실행되는 파드에서 컨트롤 플레인으로 연결하기 위한 기본 작동 모드는 기본적으로 보호되며 신뢰할 수 없는 네트워크 및/또는 공용 네트워크에서 실행될 수 있다.

컨트롤 플레인에서 노드로의 통신

컨트롤 플레인(API 서버)에서 노드로는 두 가지 기본 통신 경로가 있다. 

첫 번째는 API 서버에서 클러스터의 각 노드에서 실행되는 kubelet 프로세스이다. 

두 번째는 API 서버의 프록시 기능을 통해 API 서버에서 모든 노드, 파드 또는 서비스에 이르는 것이다.

 

API 서버에서 kubelet으로의 통신

API 서버에서 kubelet으로의 연결은 다음의 용도로 사용된다.

  • 파드에 대한 로그를 가져온다.
  • 실행 중인 파드에 (보통의 경우 kubectl을 통해) 연결한다.
  • kubelet의 포트-포워딩 기능을 제공한다.

위와 같은 연결은 kubelet의 HTTPS 엔드포인트에서 종료된다.

기본적으로, API 서버는 kubelet의 제공 인증서를 확인하지 않는다.

이는 연결이 중간자 공격(man-in-the-middle)에 시달리게 하며, 신뢰할 수 없는 네트워크 및/또는 공용 네트워크에서 실행하기에 안전하지 않다.

이것이 가능하지 않은 경우, 신뢰할 수 없는 네트워크 또는 공용 네트워크를 통한 연결을 피하기 위해 필요한 경우, API 서버와 kubelet 간 SSH 터널링을 사용한다.

마지막으로, kubelet API를 보호하려면 Kubelet 인증 및/또는 인가를 활성화해야 한다.

 

API 서버에서 노드, 파드 및 서비스로의 통신

 

API 서버에서 노드, 파드 또는 서비스로의 연결은 기본적으로 일반 HTTP 연결로 연결되므로 인증되거나 암호화되지 않는다.

이 연결에서 URL을 노드, 파드 또는 서비스 이름에 접두어 https: 을 붙여 보안 HTTPS 연결이 되도록 실행할 수 있지만, HTTPS 엔드포인트가 제공한 인증서의 유효성을 검증하지 않으며 클라이언트 자격 증명도 제공하지 않는다.

그래서 연결이 암호화되는 동안 그 어떤 무결성도 보장되지 않는다. 이러한 연결은 신뢰할 수 없는 네트워크 및/또는 공용 네트워크에서 실행하기에 현재는 안전하지 않다 .

SSH 터널

쿠버네티스는 SSH 터널을 지원하여 컨트롤 플레인에서 노드로의 통신 경로를 보호한다.

이 구성에서, API 서버는 클러스터의 각 노드에 SSH 터널을 시작하고 (포트 22에서 수신 대기하는 ssh 서버에 연결) 터널을 통해 kubelet, 노드, 파드 또는 서비스로 향하는 모든 트래픽을 전달한다.

이 터널은 노드가 실행 중인 네트워크의 외부로 트래픽이 노출되지 않도록 한다.