목적
- 워커 노드 → 쿠버네티스를 loading 할 수 있는 배
- 마스터 노드 → 적재, 적재를 계획, 선박 식별, 정보를 저장하고 위치는 감시 등등…컨테이너 관리, 모니터링
마스터 노드
ETCD : 클러스터의 핵심 데이터 저장소
- key, value 로 클러스터의 상태 정보를 저장하는 데이터베이스.
- 노드 정보, 파드 상태, 네임스페이스, 서비스, 엔드포인트 … 등등
kube-scheduler : 파드를 클러스터 내의 적절한 노드에 할당해주는 kubernetes 의 기본 스케쥴러
- pending 상태인 파드를 보고 어떤 노드가 이 파드를 실행할 수 있을지 결정하는 머리 역할
Node controller , Replication Controller : 상태 불일치를 감지하고 자동 조정하는 “컨트롤 루프” 방식으로 동작
- Node controller : 노드 관리, 새 노드를 클러스터에 온보딩하고 노드가 사용 불가능한 상황 처리
- replication controller : 원하는 컨테이너 수가 레플리케이션 그룹에서 항상 실행되도록 보장
Controller Manager : 여러 컨트롤러를 하나의 프로세스로 실행함. (Node controller , Replication Controller)
Kube ApiServer : 클러스터 내에서 모든 작업들을 관리 (오케스트레이팅)
Docker : 컨테이너를 실행할 SW (runtime engine)
kubelet (선장) : 컨테이너의 모든 활동 관리. 선박에 합류할 의사가 있다, 컨테이너의 정보를 받고 적재하고 컨테이너의 상태를 보고..
- 클러스터의 각 노드에서 실행되는 에이전트
- kube api 의 지시를 듣고 노드에서 컨테이너 배포, 파괴
- kube api 가 큐블렛의 주기적으로 상태 보고서를 가져옴
kube proxy : (노드와 컨테이너끼리의 통신) 워커노드의 실행 규칙
도커와 container d
이전엔 도커, 이젠 컨테이너디
도커 스토리
쿠버네티스는 처음에 도커 컨테이너를 오케스트레이션 하기 위해 존재했다. 그러나 이젠 다른 컨테이너 런타임이 필요했다.
CRI (Container Runtime Interface) 를 만들어 쿠버네티스를 컨테이너 런타임으로 작업하게 해줌(OCI 를 지키며 → OCI-Open Container Initative)
이미지펙 → 이미지를 어케 만들어야하는가? : 이미지 빌드 방식에 대한 기준
- 누구나 이 기준을 지키며 이미지를 빌드하고 쿠버네티스를 사용할 수 있도록
그러나 도커는 CRI 표준을 지키기 위해 만들어진 것이 아님.
dockershim : 쿠버네티스가 도커를 지원하기 위해 만들어진 인터페이스
- 도커는 CRI 를 지키지 않기 때문에…
도커가 활용하는 컨테이너d 는 CRI 호환이 가능하고 다른 런타임처럼 쿠버네티스와 직접 작업 가능
지금은 쿠버는 도커심을 지원하지 않고 컨테이너d 를 사용함. → 지금은 도커는 지원 런타임에서 제거됨.
컨테이너디
Docker 를 설치하지 않아도 컨테이너디로 컨테이너만 설치할 수 있다.
- 컨테이너디를 설치하면 ctr 이라는 명령줄 도구를 사용할 수 있다.
- 컨테이너를 디버깅하기 위해 만들어졌음.
- 제한된 기능만 지원해서 사용자 친화적이지 않음.
- 컨테이너와 상호작용하려면 api 를 직접 호출하는 수밖에..
- 그래서 사용자 친화적인 nerdctl 을 사용함 → Docker 와 유사, 도커가 지원하는 거의 모든 옵션을 지원함.
- 컨테이너디에 구현된 최신 기능에 엑세스 가능! : 암호화된 컨테이너 이미지 사용하거나 lazy 이미지 로딩도 됨
- crictl(CRI) 사용 : 명령줄 유틸리티, CRI 호환 가능한 컨테이너 런타임과 상호작용 (쿠버와 상호작용)
- 디버깅 툴임 → 이걸로 컨테이너를 만들거나 하는 건 아님.
- 이걸 통해서 컨테이너를 만들면 큐블렛이 그걸 삭제할거임 → 왜 ? 내가 모르는 컨테이너와 포트가 보이면 다 삭제..
- pull image, images, ps -a, exec -it , logs, pods 명령 등을 사용 (도커와 유사하죠?)
요약
ctr 인터페이스는 컨테이너디와 함께 제공되고 작동됨 → 디버깅 목적으로 매우 제한된 기능 이상적으로는 전혀 사용하지 않음
nerdctl → 걍 도커임 컨테이너를 만들고 도커CLI 와 비슷하게 작동 굿굿 ㅋㅋ
crictl → 쿠버네티스 커뮤니티에서 만듬. CRI 호환 가능한 런타임과 상호작용할때 사용 (통틀어 작동)
그냥 스토리
→ 쿠버는 오픈 소스, 도커는 영리 기업
오픈 소스인 쿠버네티스가 영리 기업인 도커 뒷바라지(?) 하는 게 맞냐? → 자체 오픈소스인 컨테이너디를 사용하자.
- 컨테이너 엔진이 별개의 스펙을 쓰는 게 아니라 도커가 빌드한 이미지도 띄울 수 있음.
- 컨테이너디가 도커 이미지를 띄운다.
- 컨테이너랑 이미지는 다르고 컨테이너디는 도커의 스펙을 충실하게 따라서 뭐로 빌드하던 차이가 없다.
- 컨테이너디를 직접 로컬에 띄울 필요는 없다.
- 도커 이미지를 땡겨와서 그걸 컨테이너디로 작업하고 쿠버네티스를 사용하는 것이어서 도커는 계속 쓰는 것이라고 생각하면 됨.
그런 고로 도커 공부를 게을리할 이유가 없다…
ETCD
쿠버네티스의 모든 상태 정보를 저장하는 분산 키-값 저장소
쿠버네티스에서 ETCD 의 역할은?
- 클러스터에 대한 정보를 저장한다.
- 노드, 포트, 설정, accounts, roles …
- 클러스터에 노드가 추가되거나 할 때 포드 배포할 때마다 서버에 업데이트 됨. ETCD 에 업데이트 되어야 진정으로 상태가 변경됐다고 볼 수 있음 (최종)
사용자가 따로 운영하는 방식은 아니다.
[사용자 kubectl 명령]
↓
[Kube API Server]
↓
[etcd]
↑
[Scheduler, Controller Manager]
그냥 Control plane (쿠버의 두뇌)와 연결되어 있고 일부라고 보면 됨.
- 파드를 띄우고 애플리케이션이 도는 곳과는 별개로, 쿠버의 정보를 저장하고 관리하는 곳
예시
- nginx 에 파드 3개를 띄우는 명령을 쿠버네티스에게 한다.
- API Server 가 이 요청을 etcd 에 저장한다.
- Scheduler 가 이 정보를 기반으로 적절한 노드에 파드 스케쥴링 한다.
- 컨트롤러가 파드 개수를 계속 모니터링하다가 3개가 안 되면 다시 띄운다.
- 파드 상태도 ETCD 에 업데이트 된다.
→ ETCD 가 없으면 쿠버네티스는 기억을 못해서 동작을 못 함.
kube api server
쿠버네티스 클러스터의 모든 명령이 들어가는 입구.
- kubectl 명령을 실행하면 kube api server 에 요청이 도달하고, 요청을 인증하고 유효성을 확인한 후 ETCD 에서 정보를 얻어 그 정보로 응답한다.
- kubectl 명령 말고 직접 api 를 호출할 수도 있음!
- 모든 요청을 받고 상태를 ETCD 에 기록한다.
모든 요청은 kube api server 로 도달한다.
pod 생성 요청
# kubectl
kubectl apply -f pod.yaml
# REST Api
POST /api/v1/namespaces/default/pods
→ kubectl 로 포드를 만들든, 직접 api 를 호출하든 결국 api server 를 통해서만 클러스터와 소통할 수 있다.
- 인증(Authentication) : 이 사용자가 누구인지 확인
- 권한 확인(Authorization) : 이 사용자가 파드를 만들 권한이 있는지 확인
- 유효성 검사(Admission) : 보안 정책, 리소스 할당 같은 규칙 적용
ETCD 에 기록
요청이 유효하면 API Server 는 ETCD 에 “파드가 생성되어야 한다”는 정보 저장.
- 파드를 아직 띄우지 않았지만 기록만 일단 저장.
kube-scheduler
큐브스케쥴러가 api 서버를 계속 watch 하고 있다가 아직 어느 노드에도 배치되지 않은 파드를 발견하면..
- 적절한 노드를 선택(예:메모리 많은 노드)
- api 서버에 이 파드는 노드1에 띄워야한다고 알려줌.
→ 이 때도 ETCD 에 상태 업데이트가 들어감
kublet 이 실행
노드1에 있는 큐블렛이 노드를 띄우라는 명령을 받았으니 api server 를 통해 정보를 가져온다.
- 컨테이너디에게 지시함.
- 컨테이너디는 실제 실행을 함.
상태 보고 & 반복
- 파드가 성공적으로 실행되면 큐블렛은 현재 상태를 api server 에 보고
- api server 는 그 상태를 ETCD 에 기록
- kubectl get pods 로 확인할 수 있는 상태가 이거임!
항상 → API Server → etcd → scheduler/controller → kubelet → 상태 보고 패턴 반복
kube controller manager
컨트롤러 : 리소스의 현재 상태를 원하는 상태로 맞춰주자 → (모니터링) 상태를 감시하고 문제가 생기면 조치를 취하자
큐브 컨트롤러 매니저 : 여러 컨트롤러를 관리하는 중앙 관리자 프로세스
- 노드 컨트롤러
- 노드의 상태를 감시하고 애플리케이션이 계속 실행되도록 필요한 조치를 취함. → kube api server 를 통하여
- 복제 컨트롤러 (replication controller)
- 레플리카셋의 상태를 모니터링 원하는 수의 포드가 셋 내에서 항상 사용 가능하도록 함
- 파드가 죽으면 다른 파드 실행
- 레플리카셋의 상태를 모니터링 원하는 수의 포드가 셋 내에서 항상 사용 가능하도록 함
→ 실제로는 개별 프로세스가 아니라 하나의 바이너리 프로세스 안에 다 모여 있음. api server 를 watch 하면서 변화가 생기면 자동으로 대응함.
동작 원리
- api server 에서 리소스 watch(감시)
- 현재 상태를 읽어옴
- 원하는 상태와 비교
- 차이가 있으면 조정 (ex: 파드 생성, 삭제 등)
노드 컨트롤러
클러스터 내 노드의 생존 여부(상태) 를 감시하고, 노드가 다운됐을 때 파드를 다른 노드로 옮기거나 삭제 함.
- kublet 이 주기적으로 하트비트 보냄
- 노드 컨트롤러는 이 하트비트를 api 서버를 통해 감시
- 일정 시간 이상 하트비트가 없으면 → 노드를 Not Ready 상태로 변경
- 그 노드에 있던 파드를 다른 노드로 스케쥴링.
레플리케이션 컨트롤러
설정한 갯수 만큼 파드 수를 유지시켜주는 컨트롤러, 지금은 ReplicaSet 으로 대체 됨.(기능은 유사)
아키텍처
[사용자] ---> [API Server] <--- [kubectl apply, etc.]
↑
↓ watch
+------------------------+
| kube-controller-manager|
| |
| ├── Node Controller |--- 감시: 노드 상태
| ├── Replication Ctrlr |--- 감시: 포드 개수
| └── 기타 컨트롤러들 |
+------------------------+
↓
[etcd 저장소]
↑
↓
[kubelet on Node]
예시 : nginx 레플리카 3개를 유지하고 싶은데 파드 1개가 죽었을 때
- 사용자가 nginx deployment 생성 (replicas: 3)
- kube-api server 가 요청을 받아 ETCD 에 저장.
- Replication controller (혹은 ReplicaSet Controller)가 상태 확인
- 현재 nginx 파드 중 1개 죽어 있음.
- 파드 수가 부족 → 새 파드 생성 요청
- scheduler 가 노드에 파드 할당.
- kublet 이 해당 파드 실행.
- 상태가 변경 되면 ETCD → api server → 유저 확인 가능.
kube-scheduler
어떤 파드가 어떤 노드에 들어갈지 결정 함.
왜 필요?
kubectl 로 파드를 만들면, 그 파드는 아직 어느 노드에 띄울지 모르는 채로 생성.
- 전체 노드의 상태를 확인하고
- 자원이나 조건을 고려해서
- 가장 적절한 노드를 선택(스케줄링)해준다.
결정법
어떤 파드를 가지고 그 파드에 맞는 가장 적합한 노드에 파드를 놓는다.
CPU 가 10 필요한 노드가 있을 경우
- 리소스로 필터링
- CPU 가 10 필요한 파드가 있다면, CPU 자원이 4인 노드에는 둘 수 없다.
- CPU 리소스가 10 과 같거나 10 보다 큰 노드에 파드가 들어가도록 결정한다.
- 가장 적합한 노드 고르기
- 노드에 점수를 매겨서 제일 적합한 노드 찾음.
- 파드를 놨을 때 리소스가 많이 남는다 → 12 파드보단 16 바드가 더 많이 남는다.
아키텍처
+-----------------+
| kubectl apply |
+--------+--------+
|
v
+----------+-----------+
| Kube API Server |
+----------+-----------+
|
(파드: nodeName 없음)
|
v
+-------------------------------+
| kube-scheduler |
+---------------+---------------+
|
(1) 후보 노드 필터링
(2) 점수 계산 및 정렬
(3) nodeName 결정
|
v
[API Server에 업데이트]
(파드에 nodeName 할당)
|
v
+------------------------------+
| kubelet on nodeX |
+------------------------------+
|
(컨테이너 런타임으로 실행)
kublet
배의 선장, 선내의 모든 활동을 지휘한다!
쿠버네티스에서 파드를 실행하고 관리하는 에이전트. ”명령을 받으면 직접 실행! 상태 보고! 문제가 나면 스스로 복구!”
내부 동작
- api 서버 감시
- 이 노드에 배치된 파드가 있는가?
- 실행 대상 발견
- 내가 실행해야 할 파드는?
- containerd 등에 실행 요청
- containerd, docker 등에게 “이 이미지로 컨테이너 띄워줘” 요청
- 상태 감시 + 보고
- 컨테이너 상태가 running , crashLoopBackOff 인지 확인하고
- API Server 에 주기적으로 보고
- 프로브 수행
- 파드에 설정된 헬스 체크 실행
- 상태 이상이면 재시작하거나 서비스에서 제외
왜 중요?
- kublet 이 없으면 파드 실행되지 않음.
- kublet 은 할 일 목록을 직접 실행하는 사람임.
kube-proxy
쿠버네티스 노드에서 서비스를 외부 또는 내부 트래픽과 연결해주는 네트워크 라우터
왜 필요?
파드는 동적으로 계속 생겼다가 사라지고 IP 도 계속 바뀜.. 그럼 어디로 요청을 보내야 되?
- 서비스 IP 로 요청을 보내면 kube-proxy 가 알아서 뒤에 있는 파드로 연결시켜줌.
역할
- 서비스 라우팅 : 서비스 IP → 실제 파드 IP 로 연결해줌
- NAT 처리 : 외부 IP 에서 들어온 트래픽을 내부 파드로 전달
- 클러스터 DNS 와 연결 : 클러스터 IP 로 트래픽 보낼 수 있도록 처리
- iptables / IPVS 설정 : 실제 라우팅 처리는 커널 레벨에서 함.
→ kublet 이 파드를 실행시키면, kube-proxy 가 그 파드로 요청이 잘 전달되도록 경로를 만들어줘
'개발공부 개발새발 > Kubernetes' 카테고리의 다른 글
kubernetes ) ReplicaSet Service Deployment (2) | 2025.06.06 |
---|---|
Kubernetes ) Environment (0) | 2024.04.24 |
Kubernetes ) Volume (0) | 2024.04.24 |
Kubernetes ) 선언적 접근 방식으로 쿠버네티스 사용해보기 (0) | 2024.04.22 |
Kubernetes ) 명령적 접근 방식으로 쿠버네티스 사용해보기 (0) | 2024.04.22 |