컨트롤 플레인의 구성 요소는 클러스터 상태를 저장하고 관리하지만 애플리케이션 컨테이너를 직접 실행하는 것은 아니다.
etcd 분산 저장 스토리지
API 서버
스케줄러
컨트롤러 매니저
워커 노드에서 실행하는 구성 요소
컨테이너를 실행하는 작업은 각 워커 노드에서 실행되는 구성 요소가 담당
Kubelet
쿠버네티스 서비스 프록시 (kube-proxy)
컨테이너 런타임(docker)
애드온 구성요소
컨트롤 플레인과 노드에서 실행되는 구성 요소 외에도 추가 기능을 제공하는 추가 구성 요소
쿠버네티스 DNS 서버
대시보드
인그레스 컨트롤러
힙스터
컨테이너 네트워크 인터페이스 플러그인
쿠버네티스 구성 요소의 분산 특성
컨트롤 플레인 구성 요소의 상태 확인
API 서버는 각 컨트롤 플레인 구성 요소의 상태를 표시하는 ComponentStatus 라는 API 리소스를 제공, kubectl 명령어로 구성 요소와 각각의 상태를 조회할 수 있다.
kmg48801@cloudshell:~/chapter9 (kubers-368504)$ kubectl get componentstatuses
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true"}
etcd-1 Healthy {"health":"true"}
쿠버네티스 시스템 구성 요소는 오직 API 서버하고만 통신한다.
API 서버는 etcd와 통신하는 유일한 구성 요소다.
다른 구성 요소는 etcd와 직접 통신하지 않고, API 서버로 클러스터 상태를 변경한다.
하지만 API 서버가 kubelet에 접속하는 경우가 있다.
kubectl을 이용해 로그를 가져올때
kubectl attach 명령으로 실행 중인 컨테이너에 연결할 때
워커 노드의 구성 요소는 모두 동일한 노드에서 실행돼야 하지만, 컨트롤 플레인의 구성 요소는 여러 서버에 걸쳐 실행될 수 있다,.
각 컨트롤 플레인 구성 요소 인스턴스를 둘 이상 실행해 가용성을 높일 때
etcd와 API 서버는 여러 인스턴스를 동시에 활성화해 작업을 병렬로 수행 가능(후반에서 자세한 설명)
스케줄러와 컨트롤러 매니저는 하나의 인스턴스만 활성화되고 나머지는 대기 상태 (후반에서 자세한 설명)
구성 요소 실행 방법
kubelet은 항상 일반 시스템 구성 요소로 실행되는 유일한 구성 요소, kubelet이 다른 구성 요소를 파드로 실행하며, kubelet은 무조건 시스템 구성 요소(데몬셋)으로만 실행되어야 한다.
모든 오브젝트(파드, RC, RS, 서비스 등..)는 API 서버가 다시 시작되거나 실패하더라도 유지하기 위해 매니페스트가 영구적으로 저장될 필요가 있다.
쿠버네티스는 빠르고, 분산해서 저장되며, 일관된 키-값 저장소를 제공하는 etcd를 제공한다.
분산돼 있기 때문에 둘 이상의 etcd 인스턴스를 실행해 고가용성과 우수한 성능을 제공한다.
쿠버네티스 API 서버만이 etcd와 직접적으로 통신하는 유일한 구성 요소이다.
쿠버네티스가 클러스터 상태와 메타데이터를 저장하는 유일한 저장소가 etcd 이다.
낙관적 동시성 제어 : 낙관적 동시성 제어는 데이터 조각에 잠금을 설정해 그동안 데이터를 읽거나 업데이트하지 못하도록 하는 대신, 데이터에 버전 번호를 포함하는 방법이다. 데이터가 업데이트될 때마다 버전 번호는 증가하고, 데이터를 업데이트할 때, 클라이언트가 데이터를 읽은 시간과 업데이트를 제출하는 시간 사이에 버전 번호가 증가하였는지 여부를 체크한다. 버전 번호가 증가했다면 수정된 내용은 거부되고 클라이언트는 다시 새 데이터를 읽고, 다시 업데이트를 시도한다. 결과적으로 두 클라이언트가 동일한 데이터 항목을 업데이트를 시도하면, 첫 번째 시도만 성공한다.
쿠버네티스와 비슷하게 오메가는 중앙 저장소를 사용해 클러스터의 상태를 저장하지만 대조적으로 컨트롤 플레인의 구성 요소가 저장소에 직접 접근한다.
API 서버 한곳에서 낙관적 잠금 메너티즘을 구현해서 클러스터의 상태를 업데이트하기 때문에 오류가 발생할 가능성을 줄이고 항상 일관성을 가질 수 있다.
클러스터링된 etcd의 일관성 보장
고가용성을 보장하기 위해 두 개 이상의 etcd 인스턴스를 실행하는 것이 일반적이다.
etcd는 RAFT 합의 알고리즘을 사용해 어느 순간이든 각 노드 상태가 대다수의 노드가 동의하는 현재 상태이거나, 이전에 동의된 상태 중에 하나임을 보장한다.
RAFT 합의 알고리즘은 클러스터가 다음 상태로 진행하기 위해 과반수가 필요하다.
etcd 인스턴스는 홀수로 배포해야한다. 한개의 인스턴스가 장애가 나더라도, 과반을 얻기 위해서 홀수로 배포하고 보통 5~7대의 인스턴스 정도로 구성하는 것이 좋다. (7개는 오히려 성능에 안좋다는 설명이 후반에 나온다)
API 서버의 기능
쿠버네티스 API 서버는 다른 모든 구성 요소와 kubectl 같은 클라이언트에서 사용하는 중심 구성 요소이다.
클러스터 상태를 조회하고 변경하기 위해 RESTful API로 CRUD 인터페이스를 제공한다. 모든 상태는 etcd안에 저장한다.
API 서버의 클라이언트 중 대표적인 것은 kubectl 명령줄 도구인데, JSON, yaml 파일을 활용해 리소스를 생성할 때 kubectl은 파일의 내용을 API 서버에 HTTP POST 요청을 보내고, 해당 정보를 etcd에 저장한다.
위 그림을 자세히 살펴본다면..
먼저 API 서버는 요청을 보낸 클라이언트를 인증
인증 방법에 따라 사용자를 클라이언트 인증서 혹은 HTTP 헤더에서 가져온다.
플러그인은 클라이언트의 사용자 이름, 사용자 ID, 속해 있는 그룹 정보를 추출해서 다음 단계인 인가 단계에서 사용한다.
인가 플러그인을 통한 클라이언트 인가
API 서버는 인증 플러그인 외에도 하나 이상의 인가 플러그인을 사용하도록 설정
인증된 사용자가 요청한 작업이 요청한 리소스를 대상으로 수행할 수 있는지를 판별
파드를 생성할 때 API 서버는 모든 인가 플러그인을 차례로 호출해 사용자가 요청한 네임스페이스 안에 파드를 생성할 수 있는지 결정
어드미션 컨트롤 플러그인으로 요청된 리소스 확인과 수정
리소스를 생성, 수정, 삭제하려는 요청인 경우 해당 요청은 어드미션 컨트롤러로 보내진다.
하지만 데이터를 읽는 요청인 경우에는 어드미션 컨트롤러를 거치지 않는다.
어드미션 컨트롤 플러그인 예시
AlwaysPullImages : 파드의 imagePullPolicy를 Always로 변경해 파드가 배포될 때마다 이미지를 항상 강제로 가져오도록 재정의
ServiceAccount : 명시적으로 지정하지 않을 경우 default 서비스 어카운트 적용
NamespaceLifecycle : 삭제되는 과정에 있는 네임스페이스와 존재하지 않는 네임스페이스 안에 파드가 생성되는 것을 방지
ResourceQuota : 특정 네임스페이스 안에 있는 파드가 해당 네임스페이스에 할당된 CPU와 메모리만을 사용하도록 강제
API 서버는 위와 같은 과정을 거쳐 오브젝트의 유효성을 검증하고, etcd에 저장한다.
API 서버가 리소스 변경을 클라이언트에 통보하는 방법 이해
API 서버는 레플리카셋 리소스를 만들 때 파드를 만들지 않고, 서비스의 엔드포인트를 관리하지 않는다. 해당 작업은 컨트롤러 매니저의 컨트롤러의 역할이다.
컨트롤러들은 다른 구성 요소가 배포된 리소스의 변경 사항을 관찰하고, 컨트롤 플레인 구성 요소는 리소스가 생성, 수정, 삭제될 때 통보를 받을 수 있도록 요청할 수 있고, 구성 요소가 클러스터 메타데이터의 변경에 대응해 필요한 모든 작업을 수행한다.
클라이언트는 API 서버에 HTTP 연결을 맺고 변경 사항을 감지한다.
오브젝트가 갱신될 때마다, 서버는 오브젝트를 감시하고 있는 연결된 모든 클라이언트에게 오브젝트의 새로운 버전을 보낸다.
정리하자면.. API 서버는 리소스를 etcd에 저장 후 클라이언트에 응답을 반환함과 동시에 관련된 클라이언트(ex. 컨트롤러 매니저의 컨트롤러)들에 통보해줍니다. 그리하여 오브젝트가 갱신될 때마다 API 서버는 오브젝트를 감시하고 있는 연결된 모든 클라이언트에게 오브젝트의 새로운 버전을 보내줍니다.
pod 감시하기 kubectl get po kubia-0 --watch, kubectl get po --watch
Ckmg48801@cloudshell:~ (kubers-368504)$ kubectl get po --watch
NAME READY STATUS RESTARTS AGE
kubia-0 1/1 Running 0 5d5h
kubia-1 1/1 Running 0 5d5h
kubia-2 1/1 Running 0 5d5h
스케줄러 이해
파드를 실행할 때 클러스터 노드를 지정하지 않는다, 이 작업은 스케줄러의 작업이다.
API 서버의 감시 메커니즘을 통해 새로 생성될 파드를 기다리고 있다가, 할당된 노드가 없는 새로운 파드를 노드에 할당하는 작업
스케줄러는 선택된 노드에 파드를 실행하도록 지시하지는 않는다. 단지 스케줄러는 API 서버로 파드 정의를 갱신한다.
API 서버는 kubelet에 파드가 스케줄링된 것을 통보한다.
대상 노드의 kubelet은 파드가 해당 노드에 스케줄링된 것을 확인하자마자 파드의 컨테이너를 생성하고 실행한다.
기본 스케줄링 알고리즘
모든 노드 중에서 파드를 스케줄링할 수 있는 노드 목록을 필터링
수용 가능한 노드의 우선순위를 정하고 점수가 높은 노드를 선택(만약 여러 노드가 같은 점수를 가지고 있다면, 파드가 모든 노드에 고르게 배포되도록 라운드로빈 사용)
수용 가능한 노드 찾기
노드가 하드웨어 리소스에 대한 파드 요청을 충족하는가?
노드에 리소스가 부족한가?
파드를 특정 노드로 스케줄하도록 요청한 경우, 해당 노드인가?
노드가 파드 정의에 있는 노드 셀렉터와 일치하는 라벨을 갖고 있는가?
파드가 특정 포트를 쓰려는 경우 해당 포트가 노드에서 이미 사용중인가? ...등등
동일한 서비스 또는 RS에 속한 파드는 기본적으로 여러 노드에 분산되도록 스케줄링된다.
컨트롤러 매니저에서 실행되는 컨트롤러 소개
API 서버는 리소스를 etcd에 저장하고, 변경 사항을 클라이언트에 통보하는 것 외에는 다른 일을 하지 않는다.
스케줄러는 파드에 노드만 할당한다.
컨트롤러 매니저 종류
레플리케이션 매니저
레플리카셋, 데몬셋, 잡 컨트롤러
디플로이먼트 컨트롤러
스테이트풀셋 컨트롤러
노드 컨트롤러
서비스 컨트롤러
엔드포인트 컨트롤러
네임스페이스 컨트롤러
퍼시스턴트볼륨 컨트롤러
그 외
리소스는 클러스터에 어떤 것을 실행해야 하는지 기술하는 반면, 컨틀골러는 리소스를 배포함에 따라 실제 작업을 수행하는 활성화된 쿠버네티스 구성 요소
컨트롤러 역할과 동작 방식 이해
컨트롤러는 다양한 작업을 수행하지만, 모두 API 서버에서 리소스(디플로이먼트, 서비스 등)가 변경되는 것을 감시하고 각 변경 작업을 수행한다.
컨트롤러는 조정 루프를 실행해, 실제 상태를 원하는 상태(리소스의 spec 섹션)로 조정하고 새로운 상태를 리소스의 status 섹션에 기록한다.
컨트롤러는 감시 메커니즘을 이용해 변경 사항을 API 서버로부터 통보받고, 모든 이벤트를 놓치지 않고 받는다는 것을 보장하지 않기 때문에, 정기적으로 목록을 가져오는 작업을 수행해 누락된 이벤트가 없는지 확인한다.
각 컨트롤러는 API 서버에 연결하고 감시 메커니즘을 통해 다른 컨트롤러에서 ㅂ라생한 이벤트를 수힌한다.
레플리케이션 매니저
레플리케이션컨트롤러 리소스를 활성화하는 컨트롤러를 레플리케이션 매니저라고 한다.
파드를 생성하고, 레플리카수를 맞추는 작업은 실제로 레플리케이션컨트롤러가 아닌 레플리케이션 매니저가 수행한다.
컨트롤러는 파드 셀렉터와 일치하는 파드의 수를 찾고 이를 원하는 레플리카 수와 비교한다.
컨트롤러가 매 반복마다 파드 정보를 가져오지 않고 대신 감시 메커니즘을 통해 레플리카 수와 매칭된 실제 파드 수에 영향을 주는 변화를 수신한다.
즉 레플리케이션 매니저는 API 오브젝트의 변경을 API 서버의 레플리케이션컨트롤러 리소스와 파드 리소스로부터 감시한다.
실행 중인 파드 인스턴스가 spec에 정의된 것보다 적으면, 레플리케이션컨트롤러는 새로운 파드 매니페스트를 생성해 API 서버에 게시하고, 스케줄러와 kubelet이 파드 스케줄링과 실행 작업을 수행한다. 레플리케이션 매니저는 API 서버로 파드 API 오브젝트를 조작해 작ㅇ버을 수행
레플리카셋, 데몬셋, 잡 컨트롤러
리소스에 정의된 파드 템플릿에서 파드 리소스를 생성
레플리케이션 매니저와 마찬가지로 이 컨트롤러들은 파드를 실행하지 않고, 파드 정의를 API 서버에 게시해 kubelet이 컨테이너를 생성하고 실행하도록 한다.
디플로이먼트 컨트롤러
디플로이먼트 컨트롤러는 실제 배포된 상태와 디플로이먼트 API 오브젝트에 기록된 원하는 상태가 동기화되도록 관리
디플로이먼트 컨트롤러는 디플로이먼트 오브젝트가 수정될 때마다 새로운 버전을 롤아웃
스테이트풀셋 컨트롤러
스테이트풀셋 컨트롤러는 레플리카셋 컨트롤러와 기타 관련 컨트롤러와 비슷하게 스테이트풀셋 리소스 정의에 따라 파드를 생성, 관리, 삭제한다.
다른 컨트롤러가 파드만을 관리하는 반면, 스테이트풀 컨트롤러는 각 파드 인스턴스를 위한 퍼시스턴트볼륨클레임도 인스턴스화하고 관리한다.
노드 컨트롤러
클러스터에서 실행 중인 실제 머신 목록과 노드 오븢게트 목록을 동기화하는 데 중점을 둔다.
각 노드의 상태를 모니터링하고 연결이 끊어진 노드에서 파드를 제거한다.
노드 오브젝트는 kubelet에 의해 변경되거나 REST API 호출을 통해 사용자가 변경할 수도 있다.
서비스 컨트롤러
서비스 컨트롤러는 LoadBalancer 유형의 서비스가 생성되거나 삭제될 때 인프라스트럭처에 로드 밸런서를 요청하고 해제하는 역할을 수행한다.
엔드포인트 컨트롤러
서비스는 파드에 직접 연결돼 있지 않고, 서비스에 정의된 파드 셀렉터에 따라 수동 혹은 자동으로 생성되고 갱신되는 엔드포인트 목록을 포함한다.
엔드포인트 컨트롤러는 레이블 셀렉터와 일치하는 파드의 IP와 포트로 엔드포인트 리소스를 계속 갱신하는 활성 구성 요소이다.
컨트롤러는 서비스와 파드 모두를 감시하고, 서비스가 추가 또는 갱신되거나 파드가 추가, 갱신, 삭제될 경우 서비스의 파드 셀렉터와 일치하는 파드를 선택해 IP와 포트를 엔드포인트 리소스에 추가한다.
컨트롤 플레인 구성 요소
쿠버네티스 클러스터를 이루는 구성 요소
컨트롤 플레인은 클러스터 기능을 제어하고 전체 클러스터가 동작하게 만드는 역할
워커 노드에서 실행하는 구성 요소
애드온 구성요소
쿠버네티스 구성 요소의 분산 특성
ComponentStatus
라는 API 리소스를 제공, kubectl 명령어로 구성 요소와 각각의 상태를 조회할 수 있다.쿠버네티스 시스템 구성 요소는 오직
API 서버
하고만 통신한다.API 서버
는etcd
와 통신하는 유일한 구성 요소다.다른 구성 요소는
etcd
와 직접 통신하지 않고, API 서버로 클러스터 상태를 변경한다.하지만 API 서버가 kubelet에 접속하는 경우가 있다.
로그
를 가져올때kubectl attach
명령으로 실행 중인 컨테이너에 연결할 때워커 노드의 구성 요소는 모두 동일한 노드에서 실행돼야 하지만, 컨트롤 플레인의 구성 요소는 여러 서버에 걸쳐 실행될 수 있다,.
etcd
와API 서버
는 여러 인스턴스를 동시에 활성화해 작업을 병렬로 수행 가능(후반에서 자세한 설명)스케줄러
와컨트롤러 매니저
는 하나의 인스턴스만 활성화되고 나머지는 대기 상태 (후반에서 자세한 설명)구성 요소 실행 방법
kubelet
은 항상 일반 시스템 구성 요소로 실행되는 유일한 구성 요소,kubelet
이 다른 구성 요소를 파드로 실행하며,kubelet
은 무조건 시스템 구성 요소(데몬셋)으로만 실행되어야 한다.쿠버네티스가 etcd를 사용하는 방법
etcd
를 제공한다.etcd
인스턴스를 실행해 고가용성과 우수한 성능을 제공한다.API 서버
만이etcd
와 직접적으로 통신하는 유일한 구성 요소이다.etcd
이다.리소스를 etcd에 저장하는 방법
etcd v3는 디렉터리를 지원하지 않지만, 키 형식은 동일하게 유지됨
키들이 디렉터리 구조로 그룹을 이루고있다고 생각할 수 있다.
쿠버네티스는 모든 데이터를
/registry
아래에 저장한다.etcdctl이 GCP에서는 안먹혀서 minikube로 진행함
API 서버
는 리소스의 완전한 JSON 표현을etcd
에 저장한다.etcd
의 계층적 키 공간 때문에, 저장된 모든 리소스를 단순하게 파일시스템에 있는JSON 파일
로 생각할 수 있다.저장된 오브젝트의 일관성과 유효성 보장
클러스터링된 etcd의 일관성 보장
etcd
인스턴스를 실행하는 것이 일반적이다.etcd
는RAFT 합의 알고리즘
을 사용해 어느 순간이든 각 노드 상태가 대다수의 노드가 동의하는 현재 상태이거나, 이전에 동의된 상태 중에 하나임을 보장한다.RAFT 합의 알고리즘
은 클러스터가 다음 상태로 진행하기 위해 과반수가 필요하다.etcd
인스턴스는 홀수로 배포해야한다. 한개의 인스턴스가 장애가 나더라도, 과반을 얻기 위해서 홀수로 배포하고 보통 5~7대의 인스턴스 정도로 구성하는 것이 좋다. (7개는 오히려 성능에 안좋다는 설명이 후반에 나온다)API 서버의 기능
API 서버
는 다른 모든 구성 요소와kubectl
같은 클라이언트에서 사용하는 중심 구성 요소이다.RESTful API
로 CRUD 인터페이스를 제공한다. 모든 상태는etcd
안에 저장한다.kubectl
명령줄 도구인데, JSON, yaml 파일을 활용해 리소스를 생성할 때kubectl
은 파일의 내용을 API 서버에 HTTP POST 요청을 보내고, 해당 정보를etcd
에 저장한다.위 그림을 자세히 살펴본다면..
Always
로 변경해 파드가 배포될 때마다 이미지를 항상 강제로 가져오도록 재정의API 서버는 위와 같은 과정을 거쳐 오브젝트의 유효성을 검증하고,
etcd
에 저장한다.API 서버가 리소스 변경을 클라이언트에 통보하는 방법 이해
kubectl get po kubia-0 --watch
,kubectl get po --watch
스케줄러 이해
kubelet
에 파드가 스케줄링된 것을 통보한다.kubelet
은 파드가 해당 노드에 스케줄링된 것을 확인하자마자 파드의 컨테이너를 생성하고 실행한다.기본 스케줄링 알고리즘
수용 가능한 노드 찾기
노드가 하드웨어 리소스에 대한 파드 요청을 충족하는가?
노드에 리소스가 부족한가?
파드를 특정 노드로 스케줄하도록 요청한 경우, 해당 노드인가?
노드가 파드 정의에 있는 노드 셀렉터와 일치하는 라벨을 갖고 있는가?
파드가 특정 포트를 쓰려는 경우 해당 포트가 노드에서 이미 사용중인가? ...등등
동일한 서비스 또는 RS에 속한 파드는 기본적으로 여러 노드에 분산되도록 스케줄링된다.
컨트롤러 매니저에서 실행되는 컨트롤러 소개
API 서버는 리소스를 etcd에 저장하고, 변경 사항을 클라이언트에 통보하는 것 외에는 다른 일을 하지 않는다.
스케줄러는 파드에 노드만 할당한다.
컨트롤러 매니저 종류
리소스는 클러스터에 어떤 것을 실행해야 하는지 기술하는 반면, 컨틀골러는 리소스를 배포함에 따라 실제 작업을 수행하는 활성화된 쿠버네티스 구성 요소
컨트롤러 역할과 동작 방식 이해
레플리케이션 매니저
레플리카셋, 데몬셋, 잡 컨트롤러
kubelet
이 컨테이너를 생성하고 실행하도록 한다.디플로이먼트 컨트롤러
스테이트풀셋 컨트롤러
노드 컨트롤러
kubelet
에 의해 변경되거나REST API
호출을 통해 사용자가 변경할 수도 있다.서비스 컨트롤러
LoadBalancer
유형의 서비스가 생성되거나 삭제될 때 인프라스트럭처에 로드 밸런서를 요청하고 해제하는 역할을 수행한다.엔드포인트 컨트롤러
네임스페이스 컨트롤러
퍼시스턴트볼륨 컨트롤러
컨트롤러 정리
Kubelet
과 직접 통신하거나 어떤 명령도 내리지 않는다.kubelet
과 쿠버네티스 서비스 프록시는 컨트롤러의 존재를 알지 못한 채 파드의 컨테이너에 네트워크 저장소를 붙여 기동하거나 서비스의 경우 파드 사이에 실제 로드밸런싱을 설정하는 것과 같이 맡은 일을 수행한다.