1. 쿠버네티스(Kubernetes, k8s)란?
쿠버네티스는 컨테이너화된 애플리케이션의 배포, 확장, 관리를 자동화하는 오픈소스 오케스트레이션 플랫폼이다. 2014년 구글에 의해 공개되었으며 현재는 CNCF에 의해 관리되고 있다.
쿠버네티스를 사용하면 컨테이너를 여러 서버에 분산 배포하거나 서버 장애 시 자동 복구, 트래픽에 따른 자동 확장 등이 가능해진다.
*k8s라는 약어는 'K'와 's' 사이에 8개의 글자가 있다는 의미에서 유래되었다.
2. 클러스터(Cluster)
클러스터는 컨테이너화된 애플리케이션을 실행하는 노드(Node)들의 집합을 의미한다.
여러 대의 물리적/가상 서버 자원을 하나의 논리적 자원 풀로 통합하고 특정 노드에 장애가 발생하면 클러스터 내의 다른 노드가 작업을 인계받아 서비스 중단을 방지한다.
클러스터는 크게 결정을 내리는 컨트롤 플레인(Control Plane)과 실제 작업을 수행하는 워커 노드(Worker Node)로 나뉜다.
- Control Plane
클러스터의 '두뇌' 역할을 한다. 클러스터의 Desired State를 정의하고 관리하며 실제 Node가 그 상태대로 동작하도록 지시한다.
Desired State란 쿠버네티스가 목표로 하는 클러스터 상태를 의미하며 Control Plane은 항상 Desired State와 실제 상태(Actual State)를 비교하고 차이가 발생 시 자동으로 수정한다.
[주요 컴포넌트]
- API Server: 클러스터 진입점으로 kubectl 명령과 외부 요청 처리
- Scheduler: 새로 만들어진 Pod를 적절한 Node에 배치
- Controller Manager: 다양한 컨트롤러를 구동하여 클러스터의 현재 상태를 Desired State와 맞추는 제어 루프를 실행
- etcd: 클러스터 상태의 단일 진실 공급원, 모든 상태 정보는 etcd에 기록된 데이터만 신뢰
- Node (Worker Node)
실제로 애플리케이션을 실행하는 서버이다. Control Plane이 지시한 상태대로 Pod와 컨테이너를 실행하고 유지한다.
[주요 컴포넌트]
- Kubelet: Pod 명세를 받아 컨테이너 런타임에 전달하고 상태를 보고
- Kube-proxy: 쿠버네티스 서비스 개념을 구현하기 위해 각 Node에서 네트워크 규칙을 유지 관리
- 컨테이너 런타임: CRI를 준수하는 런타임을 통해 컨테이너 실행
*Pod: 쿠버네티스의 최소 배포 단위
Pod는 쿠버네티스에서 컨테이너를 실행하는 가장 작은 단위이다. 하나의 Pod 안에는 한 개 이상의 컨테이너가 들어갈 수 있다.
하나의 Pod는 단일 IP 주소를 가지며 컨테이너 간 볼륨을 공유할 수 있다. Pod는 영구적이지 않으며 Pod가 삭제되거나 실패하면 새로운 Pod가 Control Plane에 의해 생성될 수 있다.
3. 상태 관리 (Status & Phase)
쿠버네티스는 선언적 모델을 따른다. Control Plane은 클러스터의 실제 상태를 지속적으로 수집하여 사용자가 정의한 Desired State와 일치하도록 자동 조정한다.
- 노드 상태 (Node Status)
노드의 상태는 단순한 연결 여부를 넘어 여러 조건에 의해 결정된다. kubectl get nodes 명령으로 요약된 상태를 확인할 수 있다.
- Ready: 노드가 건강하며 포드를 수용할 준비가 된 상태 (True)
- NotReady: 네트워크 문제나 Kubelet 중단으로 컨트롤 플레인과 연결이 끊긴 상태 (False)
- SchedulingDisabled: 노드가 점검 또는 유지보수를 위해 새로운 포드 배치를 막은 상태 (
kubectl cordon) - Pressure 계열: CPU, 메모리, 디스크 등 자원이 부족하여 노드 상태가 불안정한 경우
- Unknown: Node 상태 확인 불가, 일정 시간 유지되면 Node Controller가 포드를 재스케줄링하도록 유도
- 포드 단계 (Pod Phase)
포드는 생성부터 삭제까지의 생명주기를 가지며 이를 단계(Phase)라고 부른다. kubectl get pods 명령으로 현재 단계를 확인할 수 있다.
- Pending (대기): API 서버에 포드는 등록되었으나 하나 이상의 컨테이너가 생성되지 않은 상태, 노드 배치 전이거나 이미지 다운로드(Pulling) 단계가 포함
- Running (실행 중): 포드가 특정 노드에 할당되고 최소 하나 이상의 컨테이너가 실행 중이거나 시작/재시작 중인 상태
- Succeeded (성공): 포드 내의 모든 컨테이너가 성공적으로 종료되어 더 이상 재시작되지 않는 상태 (주로 일회성 Job에서 발생)
- Failed (실패): 포드 내의 모든 컨테이너가 종료되었으나 적어도 하나 이상의 컨테이너가 0이 아닌 코드로 종료되었거나 시스템에 의해 강제 종료된 상태
- Unknown (상태 불명): 포드의 상태를 파악할 수 없는 상태, 주로 해당 포드가 실행 중인 노드와 컨트롤 플레인 사이의 통신 장애 시 발생
4. 이벤트 흐름
쿠버네티스의 핵심은 선언된 Desired State를 실제 상태(Actual State)로 수렴시키는 과정이다. 포드 하나가 생성될 때 내부 컴포넌트들은 다음과 같이 긴밀하게 통신한다.
[단계별 상세 흐름]
- 사용자 요청 및 검증 (kubectl apply)
사용자가 kubectl apply -f pod.yaml 명령을 내리면 kube-apiserver가 요청을 수신한다.
단순 수신 뿐 아니라 인증과 권한을 검증하고 Admission Controller 단계를 거쳐 요청된 리소스가 클러스터 정책에 적합한지 확인하고 필요한 경우 설정을 보정한다.
- API 서버 수신 및 etcd 기록
검증된 포드 명세는 etcd에 기록된다. 이 시점의 포드는 아직 노드가 배정되지 않은 Pending 상태이며 모든 상태 정보의 변경은 오직 API Server를 통해서만 etcd에 기록된다.
- 스케줄링 (Scheduler)
kube-scheduler는 노드가 배정되지 않은 포드를 감지한다. 리소스 요구량, 노드 친화성, 테인트와 톨러레이션 등 다양한 제약 조건을 계산한 후 최적의 노드를 선택해 해당 정보를 API 서버에 전달하여 etcd 내의 포드 정보를 업데이트한다.
- 노드 작업 실행 (Kubelet)
배정된 노드의 kubelet은 API 서버를 모니터링하다가 자신에게 할당된 포드 정보를 인지한다.
kubelet은 컨테이너 런타임에 지시하여 실제 컨테이너를 생성하고 실행한다. 컨테이너가 준비되면 kubelet은 포드의 상태와 개별 컨테이너의 상태를 주기적으로 API 서버에 보고한다.
- 실제 상태 반영
모든 컨테이너가 정상적으로 구동되면 포드의 상태는 Running으로 업데이트된다. 이때 컨테이너의 Ready 상태 여부는 서비스를 통한 트래픽 라우팅 결정에 중요한 기준이 된다.
- 지속적 관찰 및 조정 (Controller Manager)
클러스터 구동 중 장애가 발생하면 kube-controller-manager가 개입한다.
ReplicaSet이나 Deployment 컨트롤러가 etcd의 의도한 상태와 실제 상태를 비교하고 노드 장애로 포드가 사라지면 Controller Manager와 Scheduler가 협력하여 다른 건강한 노드에 포드를 재배치한다.