- Kubernetes 클러스터가 무엇인지 이해하고, 이를 구성하는 2가지 영역을 안다.
- 클러스터 각 영역이 가지는 역할 및 구성요소(컴포넌트)를 이해한다.
- Api 리소스와 오브젝트 개념에 대해 이해하고, 이를 관리하는 메니페스트 파일(yml 파일)에 대해서도 살펴본다.
- 본 쿠버네티스 실습 시리즈는 아래 학습 자료를 참고한다.
1) 쿠버네티스 클러스터란?
- 쿠버네티스를 배포하면 클러스터를 얻는다. 즉, 쿠버네티스를 실행 중이라는 건 클러스터를 실행하고 있다는 얘기와 같다.
- 쿠버네티스 클러스터는 컨테이너화된 애플리케이션을 실행하는 노드(워커 머신)의 집합이다.
- 모든 클러스터는 최소 한 개 이상의 마스터 노드 및 워커 노드를 가진다.
2) 클러스터의 2가지 영역
- 쿠버네티스 클러스터는 크게 컨트롤 플레인(Control Plane)과 노드(Node)라고 하는 2가지 영역으로 구성되어 있다.
- 컨트롤 플레인: 제어 영역이라고 할 수 있으며, Master Node라고 부르기도 한다.
- 노드: 애플리케이션 컨테이너를 실행하는 역할을 한다고 하여 Worker Node라고 부르기도 한다.
- 워낙 큰 영역을 차지하는 중요한 구성요소인만큼 챕터를 분리하여 하나하나 자세하게 다루고자 한다.
1) 컨트롤 플레인 : 마스터 노드
(1) 설명
- Master Node라 불리는 컨트롤 플레인은 보통 1개~n개(홀수개)가 존재한다.
- 컨트롤 플레인은 클러스터의 상태를 관리하고, 명령어를 처리하는 역할을 한다.
- 각각의 컨트롤 플레인은 etcd, controller-manager, scheduler, kube api server라고 하는 여러 컴포넌트(구성요소)를 가진다.
- 일전에 배운 kubectl 커맨드는 여기의 구성요소인 kube apiserver와 커뮤니케이션하는 용도라고 할 수 있다.
- 마치 전통적인 3 tier 아키텍쳐 관계처럼, 클라이언트 - 백엔드 서버 - 데이터 서버의 역할을 하는 방식으로 마스터 노드가 돌아간다고 볼 수 있다. 클라이언트의 요청을 처리하는 API 서버가 있고, 그 API가 클러스터의 상태 데이터를 저장하는 데 활용하는 db가 있다. (scheduler, controller-manager가 클라이언트, kube api server가 백엔드, etcd가 데이터 서버에 해당된다고 볼 수 있다.)
(2) 컴포넌트 분석
- scheduler:
- Api 서버와 통신하는 컴포넌트로써, 각각의 노드(워커 노드)의 자원(cpu, memory, gpu 등) 사용 상태를 관리한다. 동시에 아직 노드가 배정되지 않은 새로 생성된 pod를 감지하고 새로운 워크로드를 띄우는 역할을 한다. 이 때, 클러스터내 자원할당이 가능한 노드중 알맞은 노드를 선택하여 해당 노드에 워크로드를 배포하는(== pod를 띄우는) 역할을 한다.
- controller-manager:
- 여러 컨트롤러 프로세스를 관리한다. (이전에는 컨트롤러로가 각각 다 나누어져 있었는데, 하나로 통합되면서 매니저라는 이름이 붙은 것)
- 크게 두가지 매니저로 나뉘는데, Kube 컨트롤러 매니저와 Cloud 컨트롤러 매니저이다.
- Cloud 컨트롤러 매니저는 대표적인 클라우드 provider들(aws, gcp, azure 등)과 통신한다. 각각의 클라우드 환경에 맞춘 컨트롤러가 배정되어, provider들의 종속적인 기능들을 클러스터에서 수행하는 역할을 한다.
- kube 컨트롤러 매니저도 여러 컨트롤러로 이루어져있다. Api 서버에는 다양한 api 리소스들(pod, deployment, service, secret 등)이 있고 각각의 리소스들을 관리하는 컨트롤러가 배정된다. 이들은 Api 서버를 주기적으로 찌르면서 현재 클러스터 상태와, etcd에 저장된 리소스의 상태를 비교한다. 만약 etcd 리소스 상태에 변화가 있다면 이를 현재 클러스터 리소스에 반영함으로써 동기화 시켜준다. 이러한 변화를 감지하고 동기화시키는 반복된 과정을 reconcile 이라고 부른다.
- kube api server:
- 쿠버네티스 리소스와 클러스터의 상태 관리 및 동기화를 위한 API를 제공한다.
- etcd를 데이터 저장소로 사용한다.
- etcd:
- 분산 key-value 저장소로 클러스터의 상태를 저장한다.
- 만약 클러스터 상태를 백업하고 복구하고 싶다면 etcd만 건드리면 된다.
- 컨트롤 플레인(마스터 노드) 영역 밖에 따로 떼서 관리하기도 하는데, 일반적으로는 컨트롤 플레인 내부에 각각 할당된다.
2) 노드 : 워커 노드
(1) 설명
- 애초에 클러스터를 구성하는 목적이 애플리케이션의 효율적인 관리라고 할 수 있는데, 애플리케이션이 실질적으로 실행되는(컨테이너가 띄워지는) 공간이 바로 이 노드이다. 노드도 최소 1개~n개로 구성이 되고, 내부에 존재하는 컴포넌트 구성도 모든 노드가 동일하다.
- Container Runtime 위에서 Pod가 실행되는 게 기본 형태이며, 그 외에 System 컴포넌트들이라 할 수 있는 kubelet, kube-proxy, network-addOn과 같은 여러 컴포넌트들도 돌아간다.
(2) 컴포넌트 분석
- kubelet:
- 모든 노드에 기본적으로 설치되는 컴포넌트 이다.
- Api 서버와 통신하며 노드의 리소스 상태를 보고하고 관리한다.
- Container Runtime과도 통신하며, 해당 노드 내에 띄워지는 컨테이너의 라이프사이클을 관리하기도 한다.
- CRI(Container Runtime Interface):
- kubelet이 다양한 컨테이너 런타임과 통신할 수 있도록 쿠버네티스가 자체적으로 준비한 인터페이스이다.
- 컨테이너를 관리해주는 게 docker만 있는 게 아니기 때문이다. 오히려 docker에 대한 의존성을 줄이기 위한 목적이라고도 할 수 있다.
- 즉, 쿠버네티스는 docker 외에도 containerd, cri-o을 포함한 모든 CRI 구현체들을 지원하며, 이러한 컨테이너 런타임들은 CRI를 통해 kublet과 통신할 수 있게 된다.
- kube-proxy
- 이 컴포넌트는 우선 클러스터 상에 오버레이 네트워크를 구성한다.
- 그리고 내부적으로는 네트워크 프록시 및 내부 로드밸런서 역할을 수행한다.
참고 1: minikube 클러스터는 어떻게 구성되어 있을까?
- minikube는 단일 노드로 구성되어 있어서, 해당 단일 노드가 마스터 노드의 역할과 워커 노드의 역할을 모두 수행하게 된다. 그야말로 로컬 실습에 적합한 배포판이라 할 수 있다.
- 정정사항: 실습 중에 minikube로도 멀티 노드 클러스터를 구축할 수 있다는 걸 알게 되었다. 로컬에서도 멀티 노드로 실습이 가능하단 얘기다. 방법이 궁금하면 아래의 링크를 참고하길 바란다.
- https://velog.io/@pinion7/Kubernetes-%EB%A6%AC%EC%86%8C%EC%8A%A4-NodeSelector%EC%97%90-%EB%8C%80%ED%95%B4-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B3%A0-%EC%8B%A4%EC%8A%B5%ED%95%B4%EB%B3%B4%EA%B8%B0
- 실질적으로 쿠버네티스 시리즈 동안 클러스터를 커스텀 구축하는 실습을 할 생각은 없고, 최대한 이미 구축된 클러스터(minikube)를 쉽게 활용하여 그저 사용자 관점에서의 이해도를 높이고자 한다. 즉, 쿠버네티스 리소스엔 무엇이 있고 어떤식으로 관리하며, 애플리케이션을 어떻게 운영할 수 있는지 그런 방법들에 대해서 다룰 예정이다.
참고 2: 워크로드란 무엇일까?
- 워크로드?
- 워크로드라는 말은 클러스터에서 실행하려는 작업 혹은 서비스, 프로세스 등을 가리키는 말로 주로 사용된다.
- Pod가 컨테이너 기반 애플리케이션의 최소 단위이긴 하지만, 쿠버네티스에서는 Pod를 단독으로 생성해서 사용하지 않는다. 그 대신에, Deployment 또는 Job과 같은 API 리소스를 사용하여 생성한다.
- 이렇게 워크로드는 Pod 집합을 관리하여 Pod 집합이 지정된 개수만큼, 올바른 종류의 Pod가 실행될 수 있도록 보장하는 API 리소스 기반의 프로세스를 의미한다.
- Deployment, ReplicaSet, StatefulSet, DaemenSet, Job, CronJob 등 다양한 API 리소스가 그 기반이 될 수 있다.
=> 정리하면 워크로드란, 쿠버네티스에서 실질적인 작업 리소스를 기반으로 구동되는 애플리케이션이라고 생각하면 된다.
1) API 리소스와 오브젝트
(1) API 리소스
- 쿠버네티스가 관리할 수 있는 오브젝트의 종류라고 할 수 있다.
- pod, service, configMap, secret 뿐만아니라, 클러스터가 사용하는 node, serviceAccount, role도 리소스로 사용 및 표현이 된다.
- 이는 설계도이자 템플릿이라고 이해하면 된다. 즉, 객체지향으로 이해하자면 클래스이다.
- 대표적인 API 리소스 관련 커맨드도 있다.
- kubectl api-resources: 현재 쿠버네티스가 지원하는 API 리소스 목록을 출력할 수 있다.
- kubectl explain pod: 특정 API 리소스에 대해 간단한 설명을 확인할 수 있다. API 리소스가 어떤 스펙을 가지고 있는지, 어떤 용도 및 목적으로 사용될 수 있는지 등을 알 수 있다.
- 물론 pod만 해당되는 건 아니다. service, configmap 등 가능한 리소스는 다 입력가능 하다. 이를 통해 우리가 몰랐던 스펙(fields)를 확인할 수 있고 추후 yml 파일 작성에 도움이 될 수 있다.
(2) 오브젝트
- 위의 API 리소스를 인스턴스화 한 것이다.
- 객체 지향으로 이해하면, 설계도를 통해 실제 만들어낸 인스턴스 객체라 할 수 있다.
- 가령 Pod라는 리소스로 ubuntu Pod라는 오브젝트를 만들 수도 있고, nginx Pod라는 오브젝트를 만들 수도 있는 것이다.
(3) API 리소스와 오브젝트 간의 상호작용
- 상호작용의 흐름을 이야기해보자면
- 명령형이나 선언형 커맨드의 오브젝트 명세가 API 서버로 전달된다.
- 각 API 리소스의 컨트롤러들은 오브젝트 명세가 들어오면 API 리소스(설계도)를 참고하여 오브젝트 인스턴스를 새롭게 만들어 API 서버에 업데이트를 요청한다.
- API 서버는 위 요청에 맞게, 실제 클러스터의 오브젝트 상태를 생성 및 업데이트 한다. 업데이트 된 부분이 있으면 그 부분만 새로운 오브젝트(인스턴스)를 덮어씌워 동기화 시키게 되는 것이다.
- 참고로 클러스터 상태는 etcd 컴포넌트에서 관리되므로 etcd를 업데이트한다고 생각하면 된다.
- 참고로 컨트롤러는 수시로 아래와 같은 일을 수행한다.
- API 서버를 통해 새로운 커맨드를(오브젝트 명세가 담긴) 감시한다.
- API 서버를 통해 현재 클러스터의 오브젝트 상태를 감시한다.
- 즉, 이 2가지를 항시 꾸준히 수행하여 새로운 오브젝트 명세와 실제 오브젝트 상태를 비교하고, 즉각 동기화시킬 수 있게 된다.
2) 메니페스트 파일 (.yml)
(1) 설명
- 쿠버네티스는 오브젝트를 yml 기반 메니페스트 파일로 관리한다.
- apiVersion, kind, metadata, spec가 대표적인 4가지 루트키이다.
- 이 중에 apiVersion, kind, metadata는 어떤 오브젝트에도 반드시 존재하는 루트키이며, spec은 API 리소스 종류에 따라 data, rules, subjects라는 다른 속성으로 대체되기도 한다.
- 가령 configmap, secret는 data를, role은 rules를 사용하는 리소스이다.
(2) 루트키 분석 (required)
- apiVersion: 오브젝트가 어떤 API 그룹에 속하고 API 버전이 몇인지를 정의한다.
- kind: 오브젝트가 어떤 API 리소스인지 타입을 정의한다.
- metadata: 오브젝트를 식별하기 위한 정보(이름, 네임스페이스, 레이블, 어노테이션 등)를 담는다.
- spec: 오브젝트가 가지고자 하는 데이터를 정의한다. 다르게 표현하자면, desired state(적용되길 원하는 오브젝트의 상태)를 기재하는 부분이다.
(3) Lables와 Annotations (optional)
- 모든 쿠버네티스 오브젝트는 Labels와 Annotations이라는 메타데이터를 가질 수 있다.
- Labels와 Annotations 모두 문자열 형식의 key-value 데이터를 기록한다.
- Lables:
- 오브젝트를 식별하기 위한 목적으로 사용한다.
- 추후 검색, 분류, 필터링의 효율을 높이기 위한 목적으로 사용한다.
- 가령 여러 쿠버네티스 기능들 중에 Label Selector 기능은 특정 오브젝트를 필터링 하기 위한 목적으로 자주 사용된다.
- Annotations:
- 식별이 아닌 다른 목적으로 사용한다.
- 가령 쿠버네티스의 클러스터를 형성하는 여러 애드온 서비스가 있을 수 있는데, 이러한 애드온이 오브젝트들을 관찰을 하면서 오브젝트의 어노테이션 값들을 자주 확인한다. 어노테이션 값들이 어떤지에 따라 애드온이 해당 오브젝트를 다르게 처리하게 된다.
- 어찌보면 애드온의 설정 용도로 어노테이션이 사용된다고 할 수 있고, 어노테이션은 오브젝트를 어떻게 처리할지 결정하기 위한 용도인 것이다.
참고 1: 모든 pod 목록을 확인하는 커맨드는?
- kubectl get pod라고 생각할 수 있는데 아니다. 사실 굳이 노출하지 않는 pod들도 존재한다. 실제로 커스텀하게 pod를 생성하지 않아도 존재하는 system pod들이 있다.
- 그런 pod까지 전부 불러오는 커맨드는 다음과 같다.
- kubectl get pod --all-namespaces