이 글에서는 기본 개념과 핵심 컴포넌트를 Pod 생성 흐름과 함께 알아보겠습니다.
Kubernetes Objects
Resource와 Object
쿠버네티스는 클러스터를 구성하기 위한 정보를 Object로 정의합니다. (공식 문서)
Object는 YAML 또는 JSON 형태의 menifest 파일을 통해 선언하고, etcd 라는 저장소를 통해 쿠버네티스 시스템에 영구적으로 저장합니다.
객체지향언어에 대입해볼 때 Resource는 Object를 생성하기 위해 정해둔 타입(Class)라고 볼 수 있고 Object는 사용자가 manifest 문서를 통해 정의한 설계도이며 쿠버네티스 시스템은 Object 정보를 통해 이를 실체화(인스턴스화) 하는 것이라고 이해할 수 있습니다.
대표적인 Object의 종류, 즉 Resource에는 다음과 같은 것들이 있습니다.
- 워크로드 리소스: Pod, ReplicaSet, StatefulSet, DaemeonSet, Deployment
- 네트워크 관련 리소스: Service, Ingress, NetworkPolicy
- 저장소 관련 리소스: PersistentVolume, PersistentVolumeClaim
- 구성 관련 리소스: ConfigMap, Secret
spec과 status를 활용한 상태관리
Object는 사용자의 요구사항(manifest에 정의한 spec)과 쿠버네티스 클러스터 상에서의 실제 상태(status)로 구분됩니다.
쿠버네티스 시스템은 Object의 spec을 저장해두고 status를 감시하여 spec과의 불일치가 일어나지 않도록 감시하고, 관리합니다.
쉬운 예시로 ReplicaSet에서 지정한 container의 replicas 갯수가 3개(spec)인데, 어떤 장애로 인해 container가 중단되어 2개가 되었다면 ReplicaSet Controller 가 이를 감지하고 하나를 더 실행하여 3개가 유지되도록 합니다.
Controller는 아래의 쿠버네티스 시스템 컴포넌트 설명에서 더 자세히 설명하도록 하겠습니다.
Kubernetes Components
쿠버네티스 시스템을 구축하고 운영하는데 필요한 핵심적인 기능을 수행하는 요소들을 Components라고 부릅니다.
Components에 대한 개요는 공식 문서에도 확인할 수 있습니다.
etcd
etcd는 자주 변경되지 않는 분산 시스템의 메타데이터와 같은 값을 저장하기 위해 설계되었습니다.
etcd는 분산 환경에서 일관된 데이터를 저장하고 조회할 수 있도록 지원합니다. 또한 복잡한 쿼리보다는 메타데이터 정보에 대한 간단한 정보를 조회하는데 최적이고, key에 대한 변경사항을 Watch라는 기능을 통해 실시간으로 감시할 수 있습니다.
etcd는 고가용성을 위해 클러스터로 구성될 수 있으며 리더-팔로워 구조를 가집니다.
CAP관점에서 etcd는 CP (강한 일관성과 파티션 내성)을 보장합니다. etcd에 데이터를 쓰면 리더가 새로운 데이터를 기록하고 과반수 이상의 쿼럼에 데이터 저장된 것이 확인했을 때 트랜잭션을 커밋합니다. 리더는 항상 최신의 데이터를 유지하고 팔로워읽기를 수행하기 전에 리더에게 자신의 정보가 최신이 맞는지 확인한 뒤 응답합니다.
etcd 클러스터가 CP를 보장하는 방법은 이 글에 잘 정리되어 있습니다.
CAP 이론과 CP, AP 시스템
CAP에서는 세가지 요소 중 두가지만 동시에 보장할 수 있다고 합니다. 하지만 현대 분산 시스템에서 네트워크 파티션은 필연적으로 일어나기 때문에 P(Partition Torlarance)는 사실상 반드시 보장해야 합니다.
그렇기 때문에 현실적인 시스템은 CP와 AP 중 하나를 선택하는데 CA와 AP의 특징은 다음과 같습니다.
CP: 금융,결제 등 데이터의 일관성이 엄격하게 보장되어야 하는 환경
AP: 단순 조회를 위한 읽기 작업 등에서 데이터의 일관성보다는 가용성을 중시하는 환경
쿠버네티스는 메타데이터를 저장하고 조회하는 단순한 쿼리를 요구하며, 클러스터의 안정성을 위해 일관적이고 고가용성이 지원되어야합니다. 또한 클러스터 정보와 Objects의 정보를 감시하면서, 변화가 발생했을 때 감지하고 이에 대한 핸들을 해야하기 때문에 etcd가 지향점이 일치한다고 볼 수 있습니다.
쿠버네티스는 계층적으로 키 값을 저장하여 B+Tree를 효과적으로 사용하도록 설계하였습니다.
# etctl 로 조회한 key 목록의 일부
/registry/namespaces/harbor
/registry/pods/harbor/harbor-core-6f9fcdb7ff-dgdbx
...
etcd에 저장된 키 목록 조회 결과 /registry/{Resource}/{namespace}/{name} 형태로 키 값이 구성된 것을 확인할 수 있습니다.
이러한 형태로 key값을 저장하여 특정 리소스를 조회하거나 특정 네임스페이스의 리소스를 조회하는 등 B+Tree를 효과적으로 활용하여 메타데이터를 관리합니다.
kube-apiserver
쿠버네티스는 클러스터 관리를 위한 모든 API를 Rest API로 제공합니다.
API Server는 크게 두가지 역할을 합니다.
- 사용자가 오브젝트등의 CRUD를 위해 요청하는 엔드포인트 제공하여 CRUD 기능을 제공하고, 요청 정보를 etcd에 저장
- etcd의 Watch 기능을 통해 변경을 구독하고 변경 사항 발생 시 이를 처리할 수 있는 컴포넌트에 전달하여 작업 위임
모든 Control Plane의 API Server는 동일한 etcd 클러스터를 바라보고 있기 때문에 수평 확장에도 유리하게 설계되었습니다.
kube-controller-manager
Controller Manager는 모든 형태의 컨트롤러를 종합 관리합니다.
이를 위해 컨트롤러 패턴을 먼저 이해하면 좋습니다. 쿠버네티스는 컨트롤러 패턴을 적용해서 리소스를 관리합니다.
컨트롤러는 하나 이상의 리소스를 추적하고 리소스의 status가 spec과 일치하는지 지속적으로 확인합니다.
예를 들면 ReplicaSet은 Pod라는 리소스를 관리하는 컨트롤러 리소스 입니다.
ReplicaSet은 ReplicaSet Controller라는 Controrller 하위 컴포넌트로 동작합니다.
Controller Manager에는 이런 형태로 다양한 내장 컨트롤러로 구성되어 내부적으로 실행됩니다. 사용자 정의 타입 컨트롤러를 개발해서 추가하는 것 또한 지원합니다.
컨트롤러는 크게 두 가지 방식으로 제어됩니다.
- API Server를 통해 제어
- 자체적으로 제어
클러스터 내부의 리소스를 관리는 API Server를 통해 제어됩니다.
이 유형에서는 API 서버를 통해 현재 상태를 조회하고 spec과 status를 비교하여 의도한 상태와 현재 상태가 다르다면 api-server를 통해 조정을 요청합니다.
쿠버네티스 API가 자체적으로 제공하는 Controller Resource는 이 방식으로 제어된다고 이해할 수 있습니다.
(Job, CronJob, ReplicaSet, Deployment ... )
클러스터 외부 리소스를 제어하는 Controller도 있습니다.
이 유형은 외부 서비스와 직접 통신하여 의도한 상태 혹은 기대 상태를 파악하고 상태 변경이 필요하면 변경을 수행한뒤 api-server에게 변경을 보고합니다.
예시로 Cloud에서 제공하는 Node autoscaler같은 경우 Cloud의 API와 직접 상호작용하고 클러스터 부하 증가로 새로운 Node가 필요하다면 생성한 뒤 변경 사항을 api-server에 알리는 형태로 동작합니다.
Scheduler
Scheduler는 Pod 생성시 어떤 노드에 배치할 지 계산합니다. 새로 생성되거나 스케쥴링 되지 않은 (어떤 노드에 배치되지 않은) 파드를 실행할 최적의 위치를 찾습니다.
스케쥴러는 파드를 배치하기 위해 필터링, 스코어링 단계를 거칩니다.
필터링 단계에서는 CPU, Memory, Affinity, Taints & Tolerations, Priorty 등을 고려하여 파드가 배치될 수 있는 적절한 노드를 필터링합니다.
스코어링 단계에서도 필터링 조건과 비슷한 조건들을 검사하여 노드 간 리소스 사용량 밸런스와 affinity에 설정에 의해 선호 배치 조건등을 점수로 계산하여 가장 적합한 노드에 배치하는 과정입니다.
kubelet
kublet은 모든 노드 컴포넌트에서 실행됩니다.
kubelet의 주요 작업은 노드와 Pod의 상태를 관리하고 주기적으로 API Server에 보고하는 것 입니다.
kubelet이 수행하는 작업은 다음과 같은 것들이 있습니다.
- API서버로부터 노드에 할당되는 Pod 정보를 감지하고 컨테이너 생성을 요청합니다. kubelet은 CRI (표준화된 Container Runtime Interface)를 통해 컨테이너 런타임과 통신합니다.
- CNI 플러그인을 호출해 Pod 네트워킹을 설정합니다.
- CSI 플러그인을 호출해 Pod의 볼륨을 설정합니다.
- Pod에 정의된 Probe를 실행합니다.
- 그 외에도 컨테이너의 표준 출력을 로그로 수집하여 로깅 시스템에 전달하고 오래된 로그를 정리하여 리소스를 최적화 하는 등의 작업을 합니다.
컨트롤러 리소스를 통한 Pod 생성
위에서 설명한 컴포넌트들이 협력하여 Pod를 생성하는 과정을 정리해보겠습니다.

- 사용자가 ReplicaSet manifest파일을 정의하고 api-server에 생성을 요청합니다.
- api-server는 Object 정보를 etcd에 저장합니다.
- api-server는 etcd의 데이터 변화를 감지하고 이를 적절한 컴포넌트에게 push 합니다. 위 상황에서는 ReplicaSet Controller에게 전달합니다.
- ReplicaSet Controller는 Controller Loop를 돌며 spec과 status를 비교하고 다르다면 api-server에게 생성을 요청합니다. 이 상황에는 Pod가 생성되지 않았으므로 Pod 생성을 요청합니다.
- api-server는 Pod 생성 정보를 etcd에 저장합니다.
- api-server는 etcd로부터 Pod 생성을 감지하고 scheduler에게 이를 전달합니다.
- scheduler는 필터링, 스코어링 과정을 거쳐 적절한 노드를 선택하고 api-server를 거쳐 etcd에 kublet에게 Pod 생성을 지시합니다.
- Pod를 배치하게되는 Node의 kubelet이 CRI를 통해 컨테이너를 생성하고 CNI, CSI등을 통해 Pod에 네트워크 정책과 볼륨 정책을 연결합니다.
참고자료
- https://kubernetes.io/ko/docs/home/
- https://etcd.io/docs/v3.3/learning/data_model/
- https://etloveguitar.tistory.com/159
- https://gngsn.tistory.com/284
- https://tech.kakao.com/posts/484
'Server' 카테고리의 다른 글
| VM과 Container 기술의 배경과 개념 (+ Docker, Kubernetes) (0) | 2025.04.20 |
|---|