쿠버네티스의 대략적인 구조
이전 포스팅에서는 도커의 대략적인 구조에 대해서 알아보았다. 컨테이너 툴인 도커의 구조에 대해서 알아봤으니 컨테이너들을 관리하는 오케스트레이션 툴인 쿠버네티스에 대해서 간략히 알아보도록 하겠다.
쿠버네티스는 오케스트레이션 툴 중에 가장 유명하고 많이 사용되는 툴이다. 구글의 서비스 운영 철학이 녹아있고 많은 사용사례가 있는 강력한 툴이다. 이러한 쿠버네티스는 5가지의 핵심 사상 아래 설계되었다.
쿠버네티스의 핵심 설계 사상 5가지
선언적 구조 기반의 배포환경
동작을 지시하는 형태보다 원하는 상태를 선언하는 방식을 사용한다.
기능 단위의 분산
각각의 기능들이 개별적인 구성 요소로서 독립적으로 분산되어있다.
클러스터 단위 중앙 제어
클러스터 내의 Master node를 통해서 해당 클러스터 전체를 관리한다.
동적 그룹화
쿠버네티스의 구성요소들에 쿼리 가능한 레이블과 메타데이터용 어노테이션에 임의로 키 값을 삽입 할 수있다. 삽입된 값을 바탕으로 해당 요소의 특정한 내역을 추적할 수 있다. AWS의 태그같은 기능이라고 생각하면 편하다.
API 기반 상호작용
쿠버네티스의 구성 요소들은 오직 Kubernetes API server(kube-apiserver)를 통해서만 상호 접근이 가능한 구조를 가진다. 마스터 노드에서 kubectl을 거쳐 실행되는 모든 명령은 이 API 서버를 거쳐 수행되며, 컨트롤 플레인(Control Plane)에 포함된 클러스터 제어 요소나 워커 노드(Worker Node)에 포함된 kubelet, 프록시 역시 API 서버를 항상 바라보게 되어 있다
쿠버네티스의 구조
다음은 쿠버네티스 공식 홈페이지에 있는 구조도이다.
다음 보이는 그림이 하나의 클러스터다. 쿠버네티스는 이러한 클러스터를 최소 단위로 배포하게 된다. 그림에는 나와있지 않지만 사용자들은 이 클러스터를 Master Node와 Worker Node로 나눠서 많이들 설명하곤 했다. 이러한 Master Node가 뭔지 Worker Node가 뭔지 하나 하나 차근차근 알아가보도록 하겠다.
Control Plane Component
Control Plane의 Component의 집합체를 Master Node라고도 부른다. 이러한 Master Node는 단일로 구성할 수도 있고 다수로 구성할 수도 있는데 다수로 구성할 경우 항상 홀 수개로 구성되어야한다. 상태 값에 대한 합의가 필요할 경우 짝수개일때 합의가 이뤄지지 않을 수 있기 때문이다. (자세한건 RAFT 합의 알고리즘 참고) Control Plane의 Component들은 클러스터에 대한 전반적인 결정을 할 뿐만 아니라 클러스터 이벤트를 감지하고 응답하는 역할도 한다. (예를 들어, 복제세트를 구성했는데 pod의 개수가 부족해 새로운 pod를 실행하는 것이라던지)
Control Plane Component들은 클러스터안의 어느 머신에서도 구동이 가능하다. 하지만 일반적으로는 Worker Node와 동일한 물리서버에서 구동하지 않는다.
kube-apiserver
API 서버는 Kubernetes Control Plane Component로 Kubernetes 클러스터 API를 사용할 수 있도록 해준다. 클러스터로 온 요청이 유효한지 검증하며 이러한 API 서버를 통해 다른 컴포넌트가 서로 필요한 정보를 주고받게 된다. 특히 이후에 언급할 etcd에는 API 서버만 접근이 가능하다. 이러한 API 서버는 수평으로 확장이 가능하며 확장을 통해 적절한 트래픽 분산을 할 수 있다.
etcd
클러스터에서 필요한 모든 데이터의 Kubernetes 저장소로 사용되는 일관성 있고 고가용성의 key-value 저장소이다. 여기서 말하는 모든 데이터라는건 클러스터에 노드가 몇 개인지, 각각의 파드들이 어떤 컨테이너를 들고 어느 노드에서 동작하고 있는지 등의 데이터를 말한다. 이러한 etcd가 소실되면 클러스터에 속한 모든 구성요소를 잃어버리게 된다. 반대로 말하면 etcd만 무사하면 서비스를 재 구동하는데는 아무런 문제가 없기 때문에 가용성 유지가 매우 중요하다. 쿠버네티스 공식 문서에서는 두 가지 방식을 소개하는데, 둘 다 공통으로 최소 3개 이상의 컨트롤 플레인을 갖춘 마스터 노드 구성을 취하라고 말한다.
출처 : https://kubernetes.io/images/kubeadm/kubeadm-ha-topology-stacked-etcd.svg
- 중첩된 etcd 토폴로지
kubeadm에서 기본으로 제공하는 형태로 각각의 클러스터마다 etcd를 갖고 있는 것이다. 이 경우 복제관리도 간단하고 각 클러스터의 etcd는 각 클러스터의 kube-apiserver와 통신하면 된다. 하지만 하나의 컨트롤 플레인 노드가 셧다운 될 경우 같은 클러스터에 있는 etcd까지 영향을 받으므로 데이터 중첩성에 문제가 생길 수 있다.
출처 : https://kubernetes.io/images/kubeadm/kubeadm-ha-topology-external-etcd.svg
- 외부 etcd 토폴로지
kube-apiserver와 control-manager와 schduler는 동일하나 etcd만 별도의 클러스터로 분리하는 것이다. 이럴 경우 컨트롤 플레인 노드가 셧다운 되어도 etcd까지 영향이 미치지는 않는다. 하지만 etcd가 내 장애성을 가지기 위해서는 etcd 노드를 3개를 만들어야하므로 중첩된 etcd 토폴로지에서는 3개면 족한 노드가 여기서는 6개나 필요하게 된다. (컨트롤 플레인 노드 3개 + etcd 노드 3개)
kube-scheduler
새로 생성된 노드가 할당되지 않은 Pod를 감시하고 실행할 노드를 선택하는 Control Plane Component이다. 스케줄링 결정에 고려되는 요소에는 개별 및 집합적인 리소스 요구 사항, 하드웨어/소프트웨어/정책 제약 사항, 친밀도 및 반 친밀도 사양, 데이터 지역성, 작업 간 간섭 및 마감 기한이 포함된다.
kube-controller-manager
Control Plane Component로 논리적으로는 각 제어 장치별 프로세스이지만 복잡성을 줄이기 위해 모두 단일 바이너리로 컴파일되어 단일 프로세스에서 실행된다. 이러한 컨트롤러에는 다양한 유형이 있는데 그 중에 몇 가지 유형은 아래와 같다.
- 노드 컨트롤러 : 노드가 다운될때 이를 인지하고 대응
- 작업 컨트롤러 : 일회성 작업을 나타내는 job 객체를 확인한 이후 pod를 생성하여 작업 완료 담당
- 엔드포인트 슬라이스 컨트롤러 : 엔드포인트 슬라이스 객체를 채운다
- 서비스 계정 컨트롤러 : 새 네임스페이스에 대한 기본 서비스 계정을 만든다.
이외에도 추가적인 유형들이 있다.
cloud-controller-manager
클라우드 특정 제어 논리를 내장한 Kubernetes Control Plane Component이다. 클라우드 컨트롤러 매니저를 사용하면 클러스터를 클라우드 제공업체의 API에 연결할 수 있다. 만약 Kubernetes를 자체 운영 환경이나 개인 PC 내의 학습 환경에서 실행하는 경우, 클러스터에는 클라우드 컨트롤러 매니저가 없다.
kube-controller-manager와 마찬가지로, 클라우드 컨트롤러 매니저는 여러 논리적으로 독립된 제어 루프를 단일 바이너리 파일로 결합하여 단일 프로세스로 실행되며, 성능을 개선하거나 장애를 허용하기 위해 수평으로 확장할 수 있다.
다음 컨트롤러는 클라우드 플랫폼에 대해 종속성을 가질 수 있다:
- 노드 컨트롤러: 노드가 응답을 중단한 후 클라우드에서 삭제되었는지 확인하기 위해 클라우드 제공업체를 확인한다.
- 라우트 컨트롤러: 기본 클라우드 인프라에 경로를 설정하는 데 사용한다.
- 서비스 컨트롤러: 클라우드 제공업체 로드 밸런서를 생성, 업데이트 및 삭제하는 데 사용한다.
Node Component
Node Component의 집합체를 워커 노드라고도 부른다. 워커노드 개수의 제한은 없지만 네트워크 플러그인의 설정에 따라 수백에서 수 천개까지 제한된다. 노드 구성 요소는 모든 노드에서 실행되며, 실행 중인 파드를 유지하고 Kubernetes 실행 환경을 제공한다.
kubelet
클러스터 안 모든 노드에서 실행되는 에이전트로 podspec 설정을 받아서 pod 컨테이너의 실행을 직접적으로 관리하고 해당 컨테이너가 정상적으로 실행되는지 상태 확인을 한다. 하지만 Node안에 있는 컨테이너라도 쿠버네티스를 통해 만들어지지 않은 컨테이너는 관리하지 않는다.
kube-proxy
클러스터 안에 별도의 가상의 네트워크를 생성하고 관리하게 되는데, 이러한 가상 네트워크의 동작을 관리하는 요소이다.
Container runtime
실제로 컨테이너를 실행시키는 요소로 docker의 컨테이너 런타임이기도한 containerd를 많이 사용한다.
Addons
애드온은 클러스터 기능을 구현하기 위해 Kubernetes 리소스 (DaemonSet, Deployment 등)를 사용한다. 이는 클러스터 수준의 기능을 제공하기 때문에, 애드온을 위한 네임스페이스 리소스는 kube-system 네임스페이스 내에 있어야 한다.
DNS
다른 애드온은 꼭 필요한 것은 아니지만 많은 사례에서 이를 사용하므로 모든 Kubernetes 클러스터에는 클러스터 DNS 가 있어야 한다. 클러스터 DNS는 사용자 환경의 다른 DNS 서버 외에 Kubernetes 서비스에 대한 DNS 레코드를 제공하는 DNS 서버입니다. Kubernetes에 의해 시작된 컨테이너는 DNS 검색에 이 DNS 서버를 자동으로 포함합니다.
Web UI(Dashboard)
대시보드는 Kubernetes 클러스터용 범용 웹 기반 UI로, 사용자는 클러스터 내에서 실행되는 애플리케이션 및 클러스터 자체를 관리하고 문제 해결할 수 있다.
Container Resource Monitoring
컨테이너 자원 모니터링은 중앙 데이터베이스에 대한 일반적인 시계열 메트릭을 컨테이너에 대해 기록하고, 해당 데이터를 탐색할 수 있는 UI를 제공한다.
Cluster-level Logging
클러스터 수준의 로깅 메커니즘은 컨테이너 로그를 중앙 로그 저장소에 저장하고 검색/탐색 인터페이스를 제공하는 역할을 담당합니다.
Network Plugins
네트워크 플러그인은 컨테이너 네트워크 인터페이스 (CNI) 사양을 구현하는 소프트웨어 구성 요소이며 이들은 pod에 IP 주소를 할당하고 클러스터 내에서 서로 통신할 수 있도록 하는 역할을 담당한다.
다음 포스팅부터는 예시에 따라서 어떻게 이러한 컴포넌트들이 서버 운영에 쓰이는지 또한 이 컴포넌트들의 세부 구조는 어떻게 되는지에 대해서 포스팅할 예정이다