쿠버네티스는 구역을 나누는 Namespace라는 단위로 이루어진다.
우리가 직접 생성했던 nginx
와 chk-hn
와 같은 부분은 default 네임스페이스 공간에 있고,
나머지 기본적인 쿠버네티스의 구성들은 kube-system의 네임스페이스 공간에 있다.
실제로 get pods
명령어를 이용해서 확인해보면 다음과 같이 kube-system
네임스페이스 내 다양한 기능을 수행하는 파드들이 존재하는 것을 확인할 수 있다.
그럼 AKS / EKS / GKS에 있는 쿠버네티스의 구성요소는 다를까?
확인해보도록 하자.
- EKS
네이티브 쿠버네티스 구성 요소
동일하게 kube-system 네임스페이스 밑에 배포된 pods들이 있는 것을 확인할 수 있다.
- AKS
MS 사의 Azure에서 제공하는 네이티브 쿠버네티스의 구성요소 또한 확인해보자.
Azure의 네이티브 쿠버테스 또한 동일한 kube-system 네임스페이스에 파드들이 존재한다.
- GKS
마지막으로 GCP의 GKS까지 확인해보자.
동일하게kube-system
네임스페이스에 위치한 파드들이 나온다.
그럼 이러한 kube-system
의 네임스페이스에 있는 기본 파드들(쿠버네티스 구성 요소들)은 어떤 일을할까?
먼저 파드가 배포되는 과정을 통해서 해당 기본 구성들이 하는 일에 대해서 알아보도록 하자.
추구하는 상태와 현재 상태를 계속해서 맞추려고 하는것
쿠버네티스 클러스터의 원하는 상태를 선언(명시)하고, 쿠버네티스 시스템이 실제 상태와 원하는 상태를 계속 맞추려고 하는 방식으로 작동한다. 그 중간에는 🫀API 서버가 다른 쿠버네티스 구성요소와 상호 작용하여 동작하게 된다.
API서버는 2가지 상태에 대한 정보를 처리한다.즉, 현재 상태가, 추구하는 상태로 되도록 다른 구성요소들에게 정보를 제공하는 역할을 한다.
이 상태 정보는 etcd와 같은 키-값 저장소에 저장 된다
API서버는 중심에서 굳건하게 이러한 상태값만 가지고 있고, 컨트롤러 매니저
, 스케쥴러
등 나머지 구성요소가 계속해서 해당 상태가 변경될 때 마다 이를 추구하는 상태로 만들기 위해서 동작한다.
선언적인 구조이며, 쿠버네티스에 있는 각 파드들은 자기 할 일만 한다.
API 서버는 클러스터의 원하는 상태(Desired State)
와 현재 상태(Current State)
에 대한 정보를 처리하고, 이를 기반으로 클러스터를 관리한다.
하지만, API 서버 자체가 이 두 상태를 '가지고 있는' 것은 아니며, 대신 이러한 상태 정보는 etcd와 같은 키-값 저장소에 저장된다.
API 서버는 이들 컴포넌트가 클러스터의 원하는 상태를 유지하도록 정보를 제공한다.
예를 들어, 스케줄러나 컨트롤러 같은 컴포넌트들은 API 서버로부터 정보를 받아 각자의 역할을 수행한다.
이렇게 계속 서로 맞춰가려고 하는 것이 바로 쿠버네티스의 핵심 원리이다.
사용자 또는 kubectl 명령어를 통한 API 서버 요청
Kubernetes에서 사용자는 직접 또는 kubectl 명령어를 통해 API 서버에 요청을 보내 파드 생성, 업데이트, 삭제 등을 수행합니다.
API 서버와 etcd 동기화
API 서버는 이러한 요청을 받고, 클러스터의 상태를 저장하고 있는 etcd 데이터베이스에 변경 사항을 업데이트합니다. etcd는 클러스터의 상태 정보를 저장하는 핵심 컴포넌트입니다.
컨트롤러 매니저의 역할
컨트롤러 매니저는 API 서버로부터 상태 변화를 감지하고, 클러스터의 현재 상태를 원하는 상태로 만들기 위해 작업을 수행합니다. 예를 들어, 파드의 복제 수를 관리하는 것이 이에 해당합니다.
스케줄러의 역할
스케줄러는 생성해야 할 파드를 적절한 워커 노드에 할당하는 역할을 합니다. 이 과정에서 리소스 사용량, 제약 조건 등을 고려하여 최적의 노드를 선택합니다.
kubelet을 통한 파드 생성
할당된 워커 노드의 kubelet은 API 서버로부터 파드 생성 명령을 받고, 해당 노드의 컨테이너 런타임을 통해 파드를 생성합니다.
컨테이너 런타임의 역할
컨테이너 런타임은 실제로 컨테이너를 시작, 정지하는 역할을 합니다. 이를 통해 파드 내의 컨테이너가 실행됩니다.
파드 생성 완료
위의 단계를 거쳐 파드가 성공적으로 생성되고 실행됩니다.
kubeproxy를 통한 사용자와의 통신
kubeproxy는 클러스터 내부의 네트워크 트래픽을 관리하고, 파드 간 통신 및 외부 트래픽을 파드로 라우팅하는 역할을 합니다.
사용자와의 통신 과정
사용자는 kubeproxy를 통해 파드와 통신할 수 있으며, 이를 통해 클라이언트 요청이 파드로 전달됩니다.
♐ 컨테이너 네트워크 인터페이스(CNI)
이러한 과정은 컨테이너 네트워크 인터페이스(CNI)와 관련이 있다. (파드 배포 시 IP 할당, 파드간 통신, 서비스 노출 등)
쿠버네티스는 기본적으로 네트워킹 기능을 직접 제공하지 않고, 대신 CNI 플러그인을 사용하여 네트워킹을 처리하게 된다.
이러한 네트워크 인터페이스는 쿠버네티스가 자체적으로 제공하는 것이 아닌, CALICO와 같은 컨테이너 네트워크 인터페이스를 사용자가 직접 선택해서 사용한다.
🎩
: 워커 노드👑
: 마스터 노드(컨트롤 플레인)클러스터의 프론트엔드의 역할
클러스터 외부 및 내부의 모든 프로세스 요청은 API 서버를 통해서 처리된다.
K8S 클러스터를 구성하는 모든 데이터를
key:value
형태로 저장하는 저장소
클러스터의 구성 데이터 전체를 저장하고, 클러스터의 상태를 저장한다.
🧠뇌와 같은 역할을 하며 API 서버
와 1:1로 동기화된다. 따라서, 만약 문제 발생 시 백업된 etcd 데이터를 사용하여 클러스터를 복구할 수 있다.
파드를 "어떤 노드에 배치할 것인가"를 결정하는 구성요소.
노드 및 파드의 요구사항/제약조건/정책 등을 고려하여 어떤 노드에 배치할 것인지를 결정한다.
클러스터 내에서 DNS 서비스를 제공하는 것으로, 파드 이름(서비스 이름) 및 외부 도메인을 IP 주소로 변환해 주는 작업을 한다.
이를 통해 클러스터 내의 파드가 다른 파드의 IP 주소로 통신할 수 있다.
또한, 클러스터 내의 파드가 외부의 도메인에 접속할 때 도메인 이름을 IP로 변경하여 외부 사이트로 접속할 수 있도록 해준다.
1. 노드에 할당된 파드를 괸리하는 역할.
컨테이너의 시작/중지/상태 모니터링을 수행한다.
kubelet은 개별 노드 수준에서 작동하며, API 서버로 부터 명령을 받아, 노드에 할당된 파드(직접적인 컨테이너 관리)를 관리한다.
2. 노드 시작 시, 쿠버네티스 클러스터에 노드를 등록하는 역할.
이 과정에서 노드의 정보를 마스터 노드에 보고하며, 쿠버네티스 클러스터에서 노드가 올바르게 작동하는지 확인한다.
클러스터의 전체 상태를 감시하고, 필요에 따라서 시스템의 상태를 조정한다.
쿠버네티스와 함께 제공되는 다양한 컨트롤러(노드 컨트롤러, RS 컨트롤러 등)를 포함한다.
예를 들어, 파드가 비 정상적으로 종료되면 RS 컨트롤러가 복사본 수를 유지하기 위해 새로운 파드를 생성한다.
(+)
: 클라우드 공급자에 따라서, 있을 수도 있고 없을 수도 있다.
클라우드 공급자와 관련된 기능을 관리.
Type:LoadBalancer
를 요청하면, cloud-controller-manager는 AWS에서 ELB
를 생성하고, 이를 쿠버네티스 서비스와 연동시킨다.Service와 파드간의 네트워크 통신을 관리하고, 파드들 사이에 트래픽을 분산시키는 역할
각 노드에서 실행되며, Service가 외부 요청을 받을 때, 적절한 파드로 중계하는 역할을 한다.
kube-proxy
로 받은 명령어를 통해 실제로 파드 내 컨테이너를 관리하는 구성요소.
⚠️주의 1!
kube-proxy
는 단지 중계의 역할이다.
직접적으로 파드 내 컨테이너를 실행하는 것은 컨테이너 런타임이 수행하는 것임을 주의하자.
⚠️주의 2!
컨테이너를 시작 또는 중지 하도록 명령을 내리고, 감시/관리하는 것은kubelet
이 수행한다.
컨테이너 런타임은 이러한 명령을 받아, 실제 컨테이너가 시작되거나 중지되도록 명령을 수행하는 것이다.
클러스터 내에서 파드의 네트워크를 설정하고 관리하는 구성요소
파드 간의 네트워크 통신을 구성하고 관리하기 위해 사용된다.
이를 통해서 파드 내 컨테이너(애플리케이션)가 외부의 네트워크와 통신할 수 있다.
대표적으로 calico, flannel 등이 있다.
kubelet
과 container runtime
이 실행 되어야만 워커노드의 CNI(파드의 네트워크 통신관리) 및 kube-proxy(서비스 ↔ 파드 간의 통신 관리)가 제대로 동작할 수 있다.
이는 당연하게도 기본적인 파드 및 컨테이너에 대한 실행(kubelet
, container runtime
)이 충족 되어야지만, 이후 이러한 파드에 대한 네트워크 구성을 할 수 있는 것이다.
이러한 쿠버네티스의 구성요소는 어디에 위치할까?
구성요소는 Static Pod로 /etc/kuberenetes/mainfest 위치에 YAML
파일의 형태로 존재한다.
이 위치에 YAML
파일을 위치시키면 해당 파드가 노드에 자동으로 배포되고, 또 없다면 자동으로 삭제되게 된다.
이러한 Static Pod의 생성 및 삭제는 노드 단위에서 파드 생명주기를 관리하는 Kubelet에 의해서 관리된다.
kubelet이 /etc/kuberenetes/mainfest 위치를 주기적으로 검사하며 YAML 파일의 존재 여부에 따라 파드를 생성하기도, 삭제하기도 한다.
이 과정에서는 중요한 점은 보편적인 방법인 API 서버를 거쳐 생성되는 것이 아닌, kubelet이 독립적으로 파드를 생성하고, 관리한다는 것이다.
생각해보면 당연한 것이 현재 API 서버
, 컨트롤러 매니저
, 스케쥴러
모두 kubelet이 생성해 주는 것이기 때문..!