Cluster Architecture
아키텍처 구조 개요
Kubernetes 클러스터는 크게 두 종류의 노드로 구성된다.
- Master Node (Control Plane)
- Worker Node
Master Node
1. etcd
- etcd와 통신하는 유일한 Kubernetes 컴포넌트는 kube-apiserver이다.
- 고가용성 Key-Value 저장소
- 클러스터의 모든 상태 정보 저장
- 노드 정보
- Pod 정보
- 설정 데이터
- 메타데이터 등
2. kube-apiserver
- 모든 요청의 진입점
- 외부 사용자, 컨트롤러, kubelet 모두 이 API 서버를 통해 통신
- 클러스터 전체를 오케스트레이션하는 중앙 관리 서버
Controller-Manager / kube-scheduler / kubelet
↓
kube-apiserver
↓
etcd
3. kube-scheduler
- Pod를 어떤 Worker Node에 배치할지 결정
- 스케줄러는 “어디에 배치할지 결정”만 하고, 실제 생성은 하지 않는다.
4. Controller Manager
- Node Controller
- 노드 상태 감시
- 노드 장애 처리
- 신규 노드 등록 관리
- Replication Controller
- 원하는 개수의 Pod가 항상 유지되도록 보장
Woker Node
1. Container Runtime
컨테이너를 실행하기 위한 엔진.
- Docker
- containerd
- CRI-O 등
2. kubelet
- 각 노드에서 실행되는 에이전트
- kube-apiserver로부터 명령 수신
- Pod 생성/삭제 수행
- 노드 및 Pod 상태를 API 서버에 보고
3. kube-proxy
- 노드 간 네트워크 통신 지원
- 클러스터 내부 통신을 가능하게 함
Docker vs ContainerD
개요
- 초기 Kubernetes는 Docker 전용이었다.
- 다양한 런타임을 지원하기 위해 CRI(Container Runtime Interface) 도입.
- Docker는 CRI를 직접 지원하지 않아 Dockershim을 사용.
- Kubernetes 1.24에서 Dockershim 제거 → Docker 런타임 지원 종료. (단, 이미지는 사용 가능 ! OCI 표준 준수하므로)
- 현재 표준 런타임은 containerd.
Docker vs containerD
Docker는 여러 구성요소로 이루어져 있다:
- Docker CLI
- Docker API
- Image Build Tools
- Volume 관리
- Security
- containerd
- runc
여기서 containerd는 실제 컨테이너 실행을 담당하는 런타임이다.
현재 containerd는:
- 독립 프로젝트
- Docker 없이 단독 설치 가능
CLI 도구
1. ctr - containerd CLI
containerd 기본 디버깅 CLI
기능 제한적 / Docker와 문법 다름 / 실사용 비권장
| 이미지 pull | ctr images pull docker.io/library/nginx:latest |
| 이미지 목록 | ctr images ls |
| 컨테이너 실행 | ctr run IMAGE NAME |
| 태스크 목록 | ctr tasks ls |
| 컨테이너 삭제 | ctr containers rm NAME |
2. nerdctl - containerd CLI
Docker 대체 CLI (containerd용)
일반 사용 가능 / Docker와 거의 동일
| docker run | nerdctl run |
| docker ps | nerdctl ps |
| docker logs | nerdctl logs |
| docker exec | nerdctl exec |
| docker build | nerdctl build |
| docker pull | nerdctl pull |
| docker images | nerdctl images |
| docker network | nerdctl network |
| docker volume | nerdctl volume |
추가 기능 (Docker보다 앞선 기능)
- Lazy Pull
- 이미지 암호화
- P2P 이미지 배포
- image signing
- containerd namespace 지원
목적: Docker 대체 실사용 CLI
3. crictl - Kubernetes 커뮤니티에서 제공.
Kubernetes 관점 디버깅 도구
CRI 인터페이스 기반
kubelet이 사용하는 런타임을 직접 조회containerd 전용이 아니라:
- CRI-O
- 기타 CRI 런타임
모두 지원.
| 이미지 목록 | crictl images |
| 컨테이너 목록 | crictl ps |
| Pod 목록 | crictl pods |
| 로그 확인 | crictl logs CONTAINER_ID |
| exec | crictl exec -it CONTAINER_ID sh |
| inspect | crictl inspect CONTAINER_ID |
| pull | crictl pull IMAGE |
컨테이너 생성은 가능하지만 권장하지 않음 : kubelet은 자신이 모르는 컨테이너를 삭제하기 때문
- ctr → containerd 내부 디버깅용
- nerdctl → Docker 대체 CLI
- crictl → Kubernetes 노드 디버깅용
Docker는 deprecated된 것이 아니라 Kubernetes에서 런타임으로서의 Docker 지원이 제거된 것이다.
-> containerd가 Kubernetes의 기본 런타임 역할을 한다.
Docker 런타임 지원 중단?
Kubernetes가 Docker Engine을 컨테이너 런타임으로 직접 사용하지 않는다는 뜻이다.
- kubelet이 Docker daemon과 더 이상 통신하지 않는다.
- Dockershim이 제거되었다. (v1.24)
과거 구조: kubelet → Dockershim → Docker Engine → containerd → runc
현재 구조: kubelet → CRI → containerd → runc
변경된 점:
- Dockershim 제거
- Docker Engine 경로 제거
- kubelet이 Docker API를 더 이상 호출하지 않음
ETCD
etcd는 Kubernetes 클러스터 상태를 저장하는 분산형과 강한 일관성을 가진 Key-Value 데이터 저장소이다.
다음과 같은 특징을 가지고 있다.
특징 & 기본 개념
Distributed
- 여러 서버(노드)에 데이터 복제
- 하나의 인스턴스가 죽어도 동작 가능
- 클러스터 형태로 구성 가능
Strongly Consistent
- 한 번 write 가 성공하면 그 이후의 모든 read 는 항상 최신 값을 본다
- Raft 기반이기 때문에 가능함
<-> Eventually Consistency: 시간이 지나면 결국 동일해지지만, 그 전까지는 다른 값을 볼 수도 있다.
<-> stale raed: 이미 업데이트된 데이터가 있는데, 이전 값을 읽는 것
Raft 기반
분산 노드들이 항상 동일한 상태를 유지하기 위해 만든 과반수 합의 알고리즘
Raft 클러스터는 보통 3개 또는 5개 노드로 구성된다.
Client
│
▼
Leader (etcd)
/ \
/ \
Follower A Follower B
| Leader | 모든 write 요청 처리 |
| Follower | Leader 데이터를 복제 |
| Client | kube-apiserver |
Write는 항상 Leader만 처리한다
예를 들어, Kubernetes가 Pod 생성을 한다고 가정해보자
Client (kube-apiserver)
│
▼
Leader
Leader
/ \
/ \
Follower A Follower B
log log
3개 노드라면 2개 이상 성공해야 commit된다.
즉, Leader, FollowerA 가 성공하면 commit 가능하다.
write 는 데이터를 변경하는 요청이고,
commit 은 write가 과반수 노드에 복제되어 클러스터 공식 상태로 확정되는 것
Leader가 Client에게 성공 응답을 보내고, 이 시점부터 모든 read는 최신 데이터임
Q 1. 커밋을 못한 Follower B 로 인해 이전 데이터를 반환해서 정합성이 깨지는 일은 없을까?
-> Strong consistency 환경에서는 follower가 commit되지 않은 상태로 read를 직접 처리하지 않는다.
commit 이후 내부 동작
Leader가 commit을 선언하면 다음이 일어난다.
Leader → followers "commit index 업데이트"
Follower B는 이미 로그가 있으므로 바로 commit되지만, Follower C는 아직 로그가 없다.
하지만 Raft 규칙상, follower C는 이후 leader로부터 로그를 다시 받아 catch-up replication을 수행한다.
즉 시간이 지나면 모든 노드가 동일 상태로 수렴한다.
그런데 read가 follower C로 가면?
Raft에서는 읽기 전략이 여러 가지가 있다.
1. Leader Read (기본 / 강한 일관성)
모든 read 요청을 Leader가 처리한다.
이 경우 stale read가 절대 발생하지 않는다.
2. Linearizable Read
Follower가 read 요청을 받으면
즉 follower가 바로 응답하지 않는다.
그래서 stale read가 방지된다.
3. Stale Read (허용 모드)
성능을 위해 일부 시스템은
하지만 이 경우 eventual consistency가 된다.
-> 하지만, etcd의 기본 read는 linearizable이다.
etcd에서는 어떻게 처리되나?
client read 요청
↓
leader 확인
↓
commit index 확인
↓
응답
즉 뒤처진 follower가 바로 응답하지 않는다.
요약하자면
- A: committed
- B: committed
- C: 아직 replication 안됨
이런 상황에서 read 요청이 C로 가면,
C → leader 확인해 leader가 최신 commit index를 알려준다.
C가 최신 로그가 없다면, replication → catch-up 후에 read 응답.
etcd의 기본 read는 linearizable이므로, leader 에게 확인하는 과정이 있어
C가 옛 데이터를 반환하는 일이 없다.
Q 2. 커밋을 못한 follwer B 가 리더가 되면 ?
- leader가 죽으면 follower에서 랜덤 election timeout이 발생하고 가장 먼저 timeout된 노드가 candidate가 된다.
- 가장 먼저 candidate가 된 노드는 자기 자신에게 투표를 하고, RequestVote RPC로 다른 노드에게 투표를 요청한다.
이때, 투표할 때 follower는 다음을 확인한다.
candidate log ≥ follower log
즉 candidate가 더 오래된 로그면 vote를 거부함
- 과반수 투표를 받으면 leader가 된다.
- 이때 로그가 뒤처진 노드는 투표를 받지 못하기 때문에 commit 상태보다 오래된 노드는 leader가 될 수 없다.
Q 3. etcd가 왜 절대 split brain 이 발생하지 않을까?
split brain은 두 리더가 동시에 존재해서 ,
- A : replicas = 5
- B : replicas = 3
클러스터 상태가 갈라진다.
Raft는 두 가지 규칙으로 split brain을 막는다.
- Leader는 quorum 투표로만 선출
- Write도 quorum 필요
Network Partition 상황
- 5개의 노드: A B C D E
- 과반수 -> 3
partition
- Group1 : A,B
- Group2 : C,D,E
Group1
- nodes = 2 quorum = 3
- -> leader 불가.
Group2
- nodes = 3 quorum = 3
- -> leader 가능.
- C,D,E → leader
- A,B → follower
항상 한쪽만 leader 가능.
-> 수학적으로 두 개의 leader 는 절대로 불가능하다!
그래서 etcd는 split brain을 방지한다
Raft 규칙:
- leader election → quorum 필요
- commit → quorum 필요
- quorum 집합은 항상 교집합 존재
- 로그 최신성 검증
Raft는 split brain 대신 availability를 포기한다.
- cluster = 3 nodes
- partition = 1 + 1 + 1
-> quorum 없음.
하지만, 데이터 불일치는 발생하지 않는다.
CAP 이론과 연결된다
분산 시스템은 세 가지 중 두 개만 선택 가능하다.
| C | Consistency |
| A | Availability |
| P | Partition tolerance |
etcd 는 CP 시스템
Consistency + Partition tolerance
대신에 Availability 일부 포기
Cluster State Store
etcd는 Kubernetes 클러스터의 모든 상태를 저장하는 저장소이다.
저장 대상:
- Nodes
- Pods
- Deployments
- ConfigMaps
- Secrets
- RBAC
- Services
- etc.
kubectl get으로 보는 모든 정보는 etcd에 저장되어 있다.
Q. Kubernetes는 모든 상태를 etcd에 저장할까?
Kubernetes는 클러스터 상태 기반(control loop) 시스템으로 설계되어 있다.
즉, 모든 컴포넌트가 동일한 상태를 기준으로 동작해야 한다.
그래서 하나의 신뢰 가능한 상태 저장소가 필요하고, 그것이 etcd이다.
etcd 배포 방식
클러스터를 어떻게 구성하느냐에 따라 etcd의 배포 방식도 달라진다.
1. From scratch 방식
직접 Kubernetes를 설치하는 방식이다.
직접 해야 하는 작업:
- etcd 바이너리 다운로드
- etcd 설치
- systemd service 작성
- etcd 실행 옵션 설정
etcd \
--advertise-client-urls=http://10.0.0.5:2379 \
--listen-client-urls=http://0.0.0.0:2379 \
--initial-cluster=...
즉 이런 옵션들을 직접 설정해야 한다.
대표적으로 설정하는 것
| --advertise-client-urls | API server가 접근할 주소 |
| --listen-client-urls | etcd가 실제 listen 하는 주소 |
| --initial-cluster | HA etcd 클러스터 구성 |
| TLS options | 인증서 |
2. kubeadm 방식
kubeadm은 control plane 구성 자동화 도구다.
kubeadm이 하는 일:
- etcd 설치
- etcd 설정
- TLS 인증서 생성
- etcd cluster 구성
- etcd 실행
사용자가 직접 설정 X, kubeadm이 자동 생성
3. etcd 실행 방식 차이
From scratch
보통 systemd service로 실행
/etc/systemd/system/etcd.service
kubeadm
etcd는 static pod로 실행된다.
kubelet이 이 파일을 보고 자동으로 pod를 실행한다.
kubectl get pods -n kube-system
-------------------------------
etcd-master
kube-apiserver
kube-controller-manager
kube-scheduler
4. kubeadm에서도 옵션은 존재한다
# /etc/kubernetes/manifests/etcd.yaml
----------------------------------------
containers:
- command:
- etcd
- --advertise-client-urls=https://10.0.0.5:2379
- --listen-client-urls=https://127.0.0.1:2379
- --initial-cluster=...
즉 옵션은 동일하지만 사용자가 직접 작성하지는 않는다.
5. etcd 데이터 구조
Kubernetes 리소스는 etcd에서 다음 구조로 저장된다.
root
/registry
예
/registry/nodes
/registry/pods
/registry/deployments
/registry/services
/registry/secrets
6. HA etcd 클러스터
HA 환경에서는 여러 etcd 노드가 있다.
이때 etcd는 서로를 알아야 함
--initial-cluster \
etcd1=http://10.0.0.5:2380,\
etcd2=http://10.0.0.6:2380,\
etcd3=http://10.0.0.7:2380
| 항목 | From Scratch | Kubeadm |
| etcd 설치 | 직접 | 자동 |
| etcd 옵션 설정 | 직접 | kubeadm 자동 |
| 실행 방식 | systemd | static pod |
| 인증서 | 직접 생성 | kubeadm 자동 생성 |
| 클러스터 구성 | 직접 | kubeadm 자동 |
kube-api-server
Kubernetes의 중앙 관제 서버
모든 요청이 여기로 들어오고, 모든 컴포넌트가 여기와 통신한다.
왜 중요한가?
Kubernetes에는 여러 컴포넌트가 있다.
- kubectl
- scheduler
- controller-manager
- kubelet
- etcd
이 컴포넌트들이 서로 직접 통신하는 게 아니라,
대부분 kube-apiserver를 중심으로 연결된다.
kube-apiserver가 하는 일
1. 요청 받기
kubectl get pods
kubectl apply -f pod.yaml
이 명령은 실제로 kube-apiserver로 간다.
2. 인증 / 권한 확인 / 유효성 검사
- 이 사용자가 누구인지
- 이 작업을 할 권한이 있는지
- YAML이 올바른 형식인지
3. etcd와 통신
kube-apiserver는 etcd에 직접 접근하는 유일한 컴포넌트다.
- 데이터 읽기
- 데이터 저장
- 상태 업데이트
를 kube-apiserver가 담당한다.
4. 다른 컴포넌트와 연결
예를 들어 Pod 생성 시:
- 사용자가 Pod 생성 요청
- kube-apiserver가 Pod 객체를 etcd에 저장
- scheduler가 이 Pod를 보고 노드 선택
- kube-apiserver가 그 결과를 etcd에 업데이트
- kubelet이 자기 노드에 할당된 Pod를 보고 실행
- kubelet이 상태를 kube-apiserver에 보고
- kube-apiserver가 etcd에 상태 저장
즉, 모든 상태 변화의 중간 허브다.
Pod 생성 흐름을 아주 쉽게 보면
사용자 → kube-apiserver → etcd 저장
↓
scheduler가 노드 선택
↓
kube-apiserver 업데이트
↓
kubelet이 실행
↓
kube-apiserver에 상태 보고
↓
etcd 업데이트
Pod 생성 과정 상세
1. 요청이 들어오면 먼저 인증과 검증이 수행된다.
2. kube-api-server는 Pod 객체를 생성한다.
3. 이때 아직 어떤 노드에도 할당되지 않은 상태이다.
4. 해당 정보를 etcd 서버에 저장한다.
5. 사용자에게 Pod가 생성되었다는 응답을 반환한다.
6. Scheduler는 계속해서 API Server를 모니터링하고 있다.
7. Scheduler는 다음 상태: 노드가 할당되지 않은 새로운 Pod 를 발견한다.
10. etcd 클러스터에 노드 할당 정보를 업데이트한다.
11. 해당 워커 노드의 kubelet에게 정보를 전달한다.
kubelet은 다음 작업을 수행한다.
13. 해당 노드에 Pod를 생성한다.
14. 컨테이너 런타임 엔진(container runtime)을 사용해 애플리케이션 이미지를 실행한다.
16. 작업이 완료되면 kubelet은 Pod 상태 정보를 API Server에 전달한다.
17. 그리고 API Server는 etcd에 상태 정보를 다시 업데이트한다.
설치 방식에 따른 차이
1. kubeadm으로 설치한 경우
- kube-apiserver를 kubeadm이 자동으로 구성
- 보통 kube-system 네임스페이스의 Pod로 실행
kubectl get pods -n kube-system
2. from scratch로 설치한 경우
- kube-apiserver 바이너리를 직접 설치
Master 노드에서 서비스로 실행하도록 설정해야 함
또는 서비스 파일 확인.
인증서 옵션
Kubernetes의 각 컴포넌트에는 인증서가 존재한다
많은 옵션들이 TLS 인증서(certificates) 와 관련되어 있다.
이 인증서는 Kubernetes 컴포넌트 간 통신을 보안적으로 보호한다.
기존 클러스터에서 kube-api-server 옵션 확인 방법
kubeadm으로 설치한 경우
kubeadm은 kube-api-server를 Pod 형태로 배포한다.
위치 : kube-system namespace
Pod 정의 파일 위치: /etc/kubernetes/manifests/
kubeadm이 아닌 경우 (from scratch)
이 경우 kube-api-server는 systemd 서비스로 실행된다.
서비스 파일 위치: /etc/systemd/system/kube-apiserver.service
이 명령어로 실제 실행 중인 옵션들을 확인할 수 있다.
kube-controller-manager
- 시스템의 다양한 컴포넌트 상태를 지속적으로 모니터링
- 시스템을 원하는 상태(desired state) 로 유지하도록 동작
Node Controller
역할
- 노드 상태 모니터링
- 애플리케이션이 정상적으로 실행되도록 유지
Node Controller는 kube-api-server를 통해 노드 상태를 확인한다.
동작 방식
Node Controller는 5초마다 노드 상태를 확인한다.
이 과정을 통해 노드의 건강 상태를 모니터링한다.
장애 처리
Node Controller가 어떤 노드에서 heartbeat를 받지 못하면
즉시 장애 처리하지 않는다. 먼저 40초 동안 기다린다.
그래도 heartbeat가 오지 않으면 해당 노드를 Unreachable 상태로 표시한다.
노드 복구 대기
노드가 Unreachable 상태가 되면 5분 동안 노드가 복구되기를 기다린다.
만약 복구되지 않으면
- 해당 노드에 있던 Pod들을 제거
- 다른 정상 노드에 Pod를 다시 생성
Replication Controller 예시
또 다른 컨트롤러는 Replication Controller이다.
이 컨트롤러의 역할:
- ReplicaSet 상태 모니터링
- 항상 원하는 Pod 개수 유지
-> 만약 Pod 하나가 죽으면 새 Pod를 생성하여 개수를 맞춘다.
지금까지는 두 개만 설명했지만 Kubernetes에는 훨씬 많은 컨트롤러가 존재한다.
- Deployment controller
- Service controller
- Namespace controller
- Persistent Volume controller
Kubernetes의 많은 기능과 자동화 로직은 이 컨트롤러들로 구현되어 있다.
Controller = Kubernetes 자동화 로직의 핵심
Controller Manager
이 많은 컨트롤러들은 Kube Controller Manager 라는 하나의 프로세스 안에 포함되어 있다.
Controller Manager = 여러 Controller들의 집합
Controller Manager 설치
Controller Manager를 설치하면
- 여러 컨트롤러들이 함께 설치된다.
설치 방법:
- Kubernetes 릴리스 페이지에서 kube-controller-manager 다운로드
- 압축 해제
- 서비스(service)로 실행
Controller Manager 실행 옵션
Controller Manager는 실행 시 다양한 옵션을 사용할 수 있다.
예를 들어 앞에서 설명한
- node monitor period
- grace period
- eviction timeout
같은 설정을 옵션으로 지정할 수 있다.
특정 Controller만 활성화
다음 옵션을 사용하면
활성화할 컨트롤러를 선택할 수 있다.
기본적으로는 모든 컨트롤러가 활성화되어 있다.
하지만 특정 컨트롤러만 활성화하도록 설정할 수도 있다.
만약 어떤 컨트롤러가 동작하지 않는다면
을 확인
Controller Manager 설정 확인 방법
클러스터 설정 방식에 따라 확인 방법이 다르다.
kubeadm으로 설치한 경우
kubeadm은 Controller Manager를 Pod로 실행한다.
위치 : kube-system namespace
Pod 설정 파일 위치: /etc/kubernetes/manifests/
kubeadm이 아닌 경우
Controller Manager는 서비스(service) 로 실행된다.
서비스 파일 위치 : /etc/systemd/system/
또는 실행 중인 프로세스를 확인할 수도 있다.
예: ps -ef | grep kube-controller-manager
kube scheduler
Kubernetes Scheduler는 Pod를 어떤 Node에 배치할지 결정하는 역할을 한다.
Scheduler는 Pod를 실제로 Node에 배치하지 않는다.
Pod를 실제로 생성하는 것은 kubelet의 역할이다.
비유하자면,
- Scheduler → 어떤 배(ship)에 어떤 컨테이너를 실을지 결정하는 사람
- kubelet → 실제로 컨테이너를 배에 실어주는 선장(captain)
kubelet = Pod 실제 생성
Scheduler가 필요한 이유
클러스터에는 여러 개의 Node와 여러 개의 Pod가 있다.
Scheduler는 다음을 고려해야 한다.
- Pod의 CPU / Memory 요구사항
- Node의 리소스 용량
- 특정 Node에 배치해야 하는 애플리케이션
- 특정 Node를 피해야 하는 경우
즉 올바른 Pod가 올바른 Node에 배치되도록 결정한다.
Scheduler 동작 방식
Scheduler는 Pod를 Node에 배치할 때 두 단계를 거친다.
1. Filtering 단계
먼저 Pod의 요구사항을 만족하지 못하는 Node들을 제거한다.
예를 들어 Pod가 다음과 같은 리소스를 요구한다고 하자.
- CPU: 4
- Memory: 8GB
Scheduler는 Node들을 검사하면서
- 리소스가 부족한 Node
- 조건에 맞지 않는 Node
들을 제거한다.
즉 적합하지 않은 Node 제거이다.
2. Ranking 단계
Filtering을 통과한 Node들 중에서 가장 적합한 Node를 선택한다.
Scheduler는 Priority Function을 사용하여 Node에 점수를 매긴다.
점수 범위: 0 ~ 10
예를 들어 Pod를 배치했을 때 남는 리소스가 많은 Node가 더 높은 점수를 받을 수 있다.
예: Node남는 CPU
| Node A | 2 |
| Node B | 6 |
Node B가 더 높은 점수를 받게 된다.
그래서 Scheduler는 Node B를 선택한다.
Scheduler 커스터마이징
Scheduler 동작은 사용자가 커스터마이징할 수도 있다.
예를 들어:
- Custom Scheduler 작성
- 스케줄링 정책 변경
Kubernetes에는 스케줄링과 관련된 많은 기능이 있다.
예:
- Resource requests / limits
- Taints and tolerations
- Node selectors
- Node affinity
Scheduler 설치
Scheduler를 직접 설치하려면 다음과 같은 과정을 거친다.
1. Kubernetes release 페이지에서 kube-scheduler 바이너리 다운로드
2. 압축 해제
3. 서비스(service)로 실행
Scheduler 실행 시에는 scheduler configuration 파일을 지정한다.
Scheduler 설정 확인 방법
클러스터 구성 방식에 따라 확인 방법이 다르다.
kubeadm으로 설치한 경우
kubeadm은 Scheduler를 Pod 형태로 배포한다.
위치: kube-system namespace
설정 파일 위치: /etc/kubernetes/manifests/
실행 중인 프로세스 확인
Master 노드에서 다음 명령으로 확인할 수도 있다.
이 명령으로 실행 옵션과 설정값을 확인할 수 있다.
kubelet
kubelet은 배(ship)의 선장(captain) 과 같다.
선장은 배에서 일어나는 모든 활동을 관리한다.
예를 들어:
- 클러스터에 참여하기 위해 필요한 모든 절차를 수행한다.
- 마스터와 통신하는 유일한 연락 창구 역할을 한다.
- 마스터의 스케줄러가 지시하면 컨테이너를 배에 싣거나 내린다.
- 배와 컨테이너 상태를 정기적으로 보고한다.
Kubernetes에서 kubelet 역할
Kubernetes에서 worker node에 있는 kubelet은 다음 역할을 한다.
1.노드를 Kubernetes 클러스터에 등록한다.
2. Pod나 컨테이너를 실행하라는 명령을 받으면
컨테이너 런타임 엔진(예: Docker)을 통해
- 필요한 이미지를 pull 하고
- 컨테이너를 실행한다.
3. 실행된 Pod와 컨테이너 상태를 지속적으로 모니터링한다.
4. 상태 정보를 kube-apiserver에 주기적으로 보고한다.
kubelet 설치
kubelet 설치 방법을 보자.
만약 kubeadm을 사용해 클러스터를 배포했다면
kubeadm은 kubelet을 자동으로 배포하지 않는다.
이것이 다른 컴포넌트와 다른 점이다.
kubelet은 항상 worker node에 직접 설치해야 한다.
설치 과정은 다음과 같다.
1. kubelet 설치 파일 다운로드
2. 압축 해제
3. 서비스(service)로 실행
kubelet 실행 상태 확인
worker node에서 다음 명령어로 실행 중인 kubelet을 확인할 수 있다.
이 명령어를 사용하면
- 실행 중인 kubelet 프로세스
- 실행 옵션
을 확인할 수 있다.
kube proxy
Kubernetes에서는 모든 Pod가 다른 모든 Pod와 통신할 수 있다.
이것은 Pod 네트워크를 통해 가능하다.
Pod 네트워크는 클러스터의 모든 노드에 걸쳐 있는 내부 가상 네트워크이다.
모든 Pod는 이 네트워크에 연결되어 있고, 이 네트워크를 통해 서로 통신할 수 있다.
Service를 사용하는 이유
예를 들어 다음과 같은 상황을 생각해 보자.
- 첫 번째 노드에는 웹 애플리케이션 Pod
- 두 번째 노드에는 데이터베이스 Pod
웹 애플리케이션은 데이터베이스 Pod의 IP 주소를 사용해서 접근할 수 있다.
하지만 문제가 있다.
Pod의 IP 주소는 항상 동일하게 유지되지 않는다.
Pod가 재시작되거나 재생성되면 IP가 바뀔 수 있다.
그래서 Kubernetes에서는 Service를 사용한다.
Service를 생성하면 데이터베이스 애플리케이션을 클러스터 전체에서 접근 가능하게 노출할 수 있다.
예를 들어 Service 이름: DB라고 하자.
웹 애플리케이션은 이제 DB라는 서비스 이름으로 데이터베이스에 접근할 수 있다.
Service에는 IP 주소도 하나 할당된다.
Pod가 Service의 이름이나 IP로 요청을 보내면
Service는 해당 요청을 백엔드 Pod(데이터베이스 Pod) 로 전달한다.
단, Service는 실제 컨테이너가 아니다.
- Pod처럼 실제로 실행되는 것이 아니다.
- 네트워크 인터페이스도 없다.
- 실제 프로세스도 없다.
Service는 Kubernetes 내부 메모리에 존재하는 가상 객체이다.
Service는 실제 실행되는 객체가 아니라,
백엔드 Pod 집합에 대해 고정된 이름/IP와 접근 경로를 제공하는 가상 리소스다.
실제 트래픽 전달은 kube-proxy 등의 네트워크 규칙이 수행한다.
Service 에 접근하는 방법
Service는 실제 프로세스가 아니지만 클러스터의 어떤 노드에서도 접근 가능해야 한다.
이 기능을 제공하는 것이 바로 kube-proxy 이다.
역할
- 새로운 Service가 생성되는지 감시한다.
- Service가 생성되면 각 노드에 트래픽 전달 규칙을 만든다.
- Service로 들어온 요청을 실제 Pod로 전달한다.
동작 방식
kube-proxy는 주로 iptables 규칙을 사용한다.
- Service IP : 10.96.0.1
- 실제 Pod IP: 10.32.0.15
실제 Pod IP로 전달
Service → Backend Pod 으로 트래픽을 전달하도록 설정한다.
kube-proxy 설치
kube-proxy 설치 방법은 다음과 같다.
- Kubernetes release 페이지에서 kube-proxy 바이너리 다운로드
- 압축 해제
- 서비스(service)로 실행
kubeadm을 사용할 경우
kubeadm을 사용하면 kube-proxy는 Pod 형태로 자동 배포된다.
그리고 kube-proxy는 DaemonSet으로 배포된다.
DaemonSet이란 클러스터의 모든 노드에 하나씩 Pod가 실행되도록 보장하는 Kubernetes 객체이다.
각 노드마다 kube-proxy Pod 1개가 항상 실행된다.
pods
Pods를 이해하기 전에 몇 가지 전제가 있다.
우리는 이미 다음이 준비되어 있다고 가정한다.
- 애플리케이션이 개발되어 있다.
- 애플리케이션이 Docker 이미지로 빌드되어 있다.
- Docker Hub 같은 Docker 레지스트리에 업로드되어 있다.
- Kubernetes가 이미 이미지를 pull 할 수 있다.
- Kubernetes 클러스터가 이미 구축되어 있다.
클러스터는 다음과 같을 수 있다.
- 단일 노드 클러스터
- 멀티 노드 클러스터
어떤 형태든 상관없다.
또한 Kubernetes의 모든 서비스가 정상적으로 실행 중이라고 가정한다.
목표 : Kubernetes 클러스터의 Worker Node에 컨테이너 형태로 애플리케이션을 배포하는 것
하지만 Kubernetes는 컨테이너를 직접 노드에 배포하지 않는다.
대신 컨테이너는 pod 객체 안에서 실행된다.
Pod 란?
Pod는 다음과 같다.
Kubernetes에서 생성할 수 있는 가장 작은 단위의 객체
애플리케이션의 단일 인스턴스
예를 들어 가장 간단한 구조는 다음과 같다.
Kubernetes Node
└ Pod
└ Container (App)
- Pod 안에 컨테이너가 있고
- 컨테이너 안에서 애플리케이션이 실행된다.
애플리케이션 스케일링
웹 애플리케이션 트래픽이 증가하면 애플리케이션 인스턴스를 늘려야 한다.
이때 선택지는 두 가지가 있다.
- 기존 Pod 안에 컨테이너 추가
- 새로운 Pod 생성
정답은 새로운 Pod 생성 이다.
├ Pod1 → App container
└ Pod2 → App container
즉 Pod를 복제하여 스케일링한다.
노드 리소스 부족
만약 현재 노드에 리소스가 부족하면 어떻게 할까?
새로운 노드를 클러스터에 추가할 수 있다.
Node1
├ Pod1
└ Pod2
Node2
└ Pod3
- Pod는 여러 노드에 분산 배치될 수 있다.
Pod와 Container 관계
대부분의 경우 다음 관계가 성립한다.
- 하나의 Pod
- 하나의 애플리케이션 컨테이너
스케일링 방법
스케일링은 다음과 같이 한다.
스케일 업
스케일 다운
주의할 점:
기존 Pod에 컨테이너를 추가해서 스케일하지 않는다.
Pod에 여러 컨테이너가 가능할까?
가능하다.
Pod에는 여러 컨테이너가 들어갈 수 있다.
하지만 일반적으로 같은 종류의 컨테이너를 여러 개 넣지는 않는다.
대신 다음과 같은 경우가 있다.
Helper Container (Sidecar)
예를 들어
- 웹 애플리케이션 컨테이너
- 파일 처리 컨테이너
- 로그 처리 컨테이너
같이 보조 역할(helper) 을 하는 컨테이너가 있을 수 있다.
이 경우 같은 Pod에 넣는다.
Pod
├ App Container
└ Helper Container
같은 Pod의 컨테이너 특징
같은 Pod 안의 컨테이너는 다음을 공유한다.
- 네트워크: localhost로 서로 통신 가능
- 스토리지: 같은 볼륨 공유 가능
- 생명주기: 같이 생성, 같이 종료=
Kubernetes가 해결해주는 문제
만약 Kubernetes 없이 Docker만 사용한다면 다음을 직접 관리해야 한다.
- 컨테이너 연결 관계
- 네트워크 연결
- 볼륨 공유
- 컨테이너 상태 모니터링
- 컨테이너 종료 시 정리 작업
하지만 Kubernetes에서는 Pod 정의만 하면 자동으로 관리된다.
Multi Container Pod
여러 컨테이너가 있는 Pod는 가능하지만 실제 사용 사례는 많지 않다.
그래서 이 강의에서는 대부분 Pod = Container 1개 구조를 사용한다.
Pod 생성
Pod를 생성하려면 다음 명령어를 사용한다.
kubectl run nginx --image=nginx
이 명령은 내부적으로 다음을 수행한다.
- Pod 생성
- nginx 컨테이너 실행
이미지 다운로드
이미지는 DockerHub 위치에서 가져온다.
Docker Hub는 Docker 이미지 저장소이다.
- 사설 레지스트리
- 조직 내부 레지스트리
도 사용할 수 있다.
Pod 목록을 확인하려면 다음 명령어를 사용한다.
kubectl get pods
--------------------------------------
NAME READY STATUS
nginx 0/1 ContainerCreating
곧 상태가 Running으로 바뀐다.
지금 상태에서는 nginx 웹 서버가 외부에서 접근 가능하지 않다.
노드 내부에서는 접근할 수 있지만
외부 사용자에게 공개하려면 Service 가 필요하다.
'Infra > K8S' 카테고리의 다른 글
| [CKA 준비] Pod & Deployment 명령어 정리 (0) | 2026.04.18 |
|---|---|
| [CKA 준비] Scheduling (0) | 2026.04.11 |
| [CKA 준비] Core Concepts - 3 (0) | 2026.03.15 |
| [CKA 준비] - Core Concepts - 2 (0) | 2026.03.15 |
| KEDA 필요성, HPA 와의 차이점 (0) | 2026.01.18 |