오버 엔지니어링이라는 말도 많긴 하지만, 난 쿠버네티스 알고 싶은 걸...? 🥺
지적 호기심 충족 겸 복습 겸 스터디 했던 내용 정리해본다.
쿠버네티스 아키텍쳐
우선 가장 큰 구분인 Control Plane와 Data Plane에 대해서 봅시다
Control Plane와 Node
- Control Plane: 쿠버네티스 클러스터 전체를 관리하는 컴포넌트
- 이후에 소개하는 일꾼(워커 노드)들을 제어하는 역할
- 쿠버네티스 사용자의 명령을 받아 일꾼들을 어떻게 지지고 볶을 것인가 고민하고 처리
- 보통 하나의 리드 마스터, 두 개의 마스터를 생성해서 문제가 생길 경우를 대비함
- Node: 컨트롤 플레인의 명령을 받아 일하는 컴포넌트
- 실제 파드(컨테이너 여러 개 묶음)가 띄워져서 일하는 친구들
이 다음에는 각각의 요소에 대해서 봅시다
Control Plane 컴포넌트
- API Server
- 쿠버네티스의 모든 기능들을 REST API로 제공하고 그에 대한 명령을 처리 (상태를 바꾸거나 조회)
- etcd와 유일하게 통신하는 모듈
- 권한을 체크하여 적절한 권한이 없을 경우 요청을 차단
- 관리자 요청뿐만 아니라 다양한 내부 모듈과 통신
- etcd (엣시디 라고 읽더라...)
- 쿠버네티스 클러스터의 데이터베이스 역할이 되는 서버, 설정값이나 클러스터의 상태 저장 (키-밸류)
- 그럼 왜 그때그때 명령을 처리해주면 되지 왜 etcd에 기록을 한 다음에 실행하느냐?
- 마스터 서버 3대가 각기 다른 상태 정보를 가지고 있으면 안 되기 때문에, 중점적으로 참고할 수 있는 데이터베이스를 하나 만든 것
- kube-scheduler
- 새로 생성된 pod을 감지하고 실행할 노드를 선택 & 노드의 현재 상태와 pod의 요구사항 체크
- kube-controller-manager
- 컨트롤러(레플리카 컨트롤러, 서비스 컨트롤러, 볼룸 컨트롤러, 노드 컨트롤러..등)를 생성하고 이를 관리하는 역할
- 컨트롤러는 끊임없이 대상이 되는 것들의 상태를 체크하고 원하는 상태를 유지
- 복잡성을 낮추기 위해 모든 컨트롤러를 단일 바이너리로 컴파일, 하나의 프로세스로 실행
- cloud-controller-manager
- 클라우드별 컨트롤 로직을 포함, 클라우드 프로바이더의 API에 연결, 클라우드와 연결된 컴포넌트를 구분할 수 있게 함
- kube-controller-manager와 마찬가지로 여러 컨트롤 루프를 단일 프로세스로 실행하는 단일 바이너리로 결합
Node 컴포넌트
- kubelet
- 각 노드에서 실행되는 에이전트로 파드에서 컨테이너가 확실하게 동작하도록 관리
- PodSpec의 집합을 받아 컨테이너들이 파드의 스펙에 따라 건강하게 동작하는지 확인
- kube-proxy
- 각 노드에서 실행되는 네트워크 프록시
- 내부 네트워크 세션이나 외부에서 내부로 네트워크 통신을 가능하게 함
- 보통 트래픽을 포워딩해서 사용
- pod
파드(Pod)
파드는 하나 이상의 컨테이너로 이루어진 그룹인데, 고래 때(pod of whales)이라는 단어를 생각해보면 그 개념을 조금 더 직관적으로 받아드릴 수 있을 것 같다. 결국 쿠버네티스는 엄청나게 많은 컨테이너를 파드 단위로 잘, 효율적으로, 자동적으로 관리하기 위한 툴이다.
- 한 개 이상의 container로 구성되어 있음
- 파드 내에서는 스토리지를 공유하고 함께 배치/스케쥴링 됨 (공유 컨텍스트)
- 파드마다 고유 IP가 존재하며, 컨테이너들은 해당 IP를 공유하고 포트 번호로 구별한다
- 파드 내에서 localhost로 통신 가능
- 상호의존성이 높은 컨테이너들을 묶어 하나의 단위 수행을 할 수 있도록 묶는다
파드 CRUD
쿠버네티스는 커맨드라인을 통해 명령형으로 파드를 생성, 관리할 수 있지만 기록도 안 남고 여러모로 불편하므로 yaml 파일을 작성하여 선언형으로 파드(및 다른 모든 기능들을) 사용한다.
# podsample.yaml
apiVersion: v1 # 스크립트 실행을 위한 쿠버 API 버전
kind: Pod # 리소스 종류 정의
metadata: # 리소스의 메타데이터
name: nginx # 파드를 식별할 수 있는 이름
namespace: practice
spec: # 리소스의 스펙 정의
containers: # 여러 개 가능
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 8888
# create
$ kubectl apply -f podsample.yaml
# read
$ kubectl describe pods nginx -n practice
# update, vi 편집기로 실행 중인 파드 수정 가능
$ kubectl edit pods nginx -n practice
# delete
$ kubectl delete -f podsample.yaml
파드의 생성 과정
파드는 대단히 복잡한 과정을 통해서 생성되는데
1. 사용자가 kubectl 명령으로 API Server에 파드 생성 요청
2. API Server가 etcd에 현재 상태 기록 (Pod가 생성되어야 하는 상태이지만, 현재 아직 생성되지 않았다 노드에 할당 되지 않았다)
3. Scheduler는 API Server를 통해 etcd에 적힌 상태 업데이트를 인지하고 어떤 노드에 파드를 할당할지 결정
4. Scheduler는 API Server에 파드를 특정 노드에 바인딩했다는 것을 알림
5. 파드가 노드에 바인딩 되었다는 것을 etcd에 기록
6. 노드의 kublet들은 API Server와 파드 관련 자신의 상태에 대해서 통신하다가 자신의 노드에 파드가 생성 요청 되었으나 아직 생성 되지 않은 상태라는 것을 인지, 컨테이너 런타임을 통해 파드를 띄움 (파드의 상태는 kubelet이 계속적으로 API Server에 알려줌)
7. 파드 상태들을 etcd에 기록한다
파드의 라이프사이클 - 파드의 단계 (Pod phase)
파드의 phase 필드를 통해 파드가 라이프사이클 중 어느 단계에 해당하는지 알 수 있다.
값 | 의미 |
Pending | 파드가 쿠버네티스 클러스터에서 승인되었지만, 하나 이상의 컨테이너가 설정되지 않았고 실행할 준비가 되지 않았다. 여기에는 파드가 스케줄되기 이전까지의 시간 뿐만 아니라 네트워크를 통한 컨테이너 이미지 다운로드 시간도 포함된다. |
Running | 파드가 노드에 바인딩되었고, 모든 컨테이너가 생성되었다. 적어도 하나의 컨테이너가 아직 실행 중이거나, 시작 또는 재시작 중에 있다. |
Succeeded | 파드에 있는 모든 컨테이너들이 성공적으로 종료되었고, 재시작되지 않을 것이다. |
Failed | 파드에 있는 모든 컨테이너가 종료되었고, 적어도 하나 이상의 컨테이너가 실패로 종료되었다. 즉, 해당 컨테이너는 non-zero 상태로 빠져나왔거나(exited) 시스템에 의해서 종료(terminated)되었다. |
Unknown | 어떤 이유에 의해서 파드의 상태를 얻을 수 없다. 이 단계는 일반적으로 파드가 실행되어야 하는 노드와의 통신 오류로 인해 발생한다. |
- Pending에서 시작. 파드가 노드에 바인딩 되기 이전에 단계
- 파드가 노드에 바인딩 되고, 컨테이너 중 적어도 하나 이상이 잘 띄어지기 시작하면 Running 단계가 된다
- 파드의 컨테이너가 모두 잘 띄워졌냐, 1개 이상이 띄워지는데 실패했냐에 따라 Succeeded / Failed
- 참고로 파드 종료 시 Terminating은 파드의 단계(Phase)는 아니다
파드의 라이프사이클 - 컨테이너 상태 (Container states)
쿠버네티스는 파드의 단계뿐만 아니라 파드 내부의 컨테이너 상태도 추적한다. Scheduler가 노드에 파드를 할당하면 kubelet은 컨테이너 런타임을 사용하여 해당 파드에 대한 컨테이너 생성을 실행하고, 이 컨테이너에 대한 상태를 추적한다
상태 | 의미 |
Waiting | Running과 Terminated가 아닌 상태. 컨테이너를 시작하는데 완료하는데 필요한 작업(컨테이너 이미지 레지스트리에서 컨테이너 이미지를 가져오거나, 시크릿 데이터를 적용하는 작업)을 실행 중. kubectl로 Waiting 상태인 파드를 쿼리하면 waiting에 있는 이유를 요약하는 Reason 필드도 표시 됨. |
Running | 컨테이너가 문제없이 실행되고 있음. kubectl을 통해 Running 상태인 파드를 쿼리하면 Running 상태에 진입한 시기에 대한 정보도 볼 수 있음. |
Terminated | 컨테이너가 실행 시작한 이유로 어떤 이유로 실패한 상태. kubectl을 통해 Terminated 상태인 파드를 쿼리하면 이유와 종료 코드, 해당 컨테이너의 실행 기간에 대한 시작과 종료 시간이 표시 됨 |
'DevOps > Kubernetes' 카테고리의 다른 글
Docker Desktop을 이용한 쿠버네티스 설치하기 (0) | 2023.01.31 |
---|