[Kubernetes] Kubernetes architecture

Kubernetes

Kubernetes(K8s)는 컨테이너화된 애플리케이션의 배포, 확장, 관리 등을 자동화해주는 컨테이너 오케스트레이션 도구이다. kubernetes클러스터에는 하나이상의 control plane과 하나 이상의 worker node를 가지고 있다. control plane은 클러스터에 중앙에서 관리하고 API 트래픽을 통해 각 Node와의 통신을 한다. 또한 kubulet deamon과 함계 containerd, CRI-O와 같은 컨테이이너 런타입을 실행한다. 

Control Plane 

클러스터 전체 상태를 관리학 조율하는 역할을 한다. 즉 컨테이너화된 애플리케이션을 실행하는 데 사용되는 물리적인 가상 Node 그룹을 의미한다. 또한 이러한 Control Plane은 한대가 아닌 여러대의 멀티 클러스터 형태로 구축하여 고가용성을 보장 할 수 있다. 하지만 짝수개의 Control plane을 구축하지는 못한다. 

Worker Node 

Pod의 호스팅을 담당한다. Pod 안에 Container가 생성된다. Control Plane은 Worker node 와 클러스터 내 Pod를 관리하고 Worker Node는 애플리케이션의 구성요소인 Pod를 호스트한다. 도한, 네트워크 통신 처리 및 Pod간 트래픽을 관리한다. Control Plane과 마찬가지로 여러대의 Node를 구성하여 고가용성을 보장한다. 

Control Plane과 Worker Node 간 상호작용

  1. 사용자가 kubectl 명령어로 Pod 생성 요청을 Control Plane의 API Server에 전달
  2. Control Plane은 Scheduler를 통해 적절한 Worker Node를 선택
  3. Control Plane의 Controller Manager가 요청에 따라 Pod를 생성 및 관리
  4. Worker Node의 kubelet이 Control Plane의 명령을 실행하여 컨테이너를 시작

Worker Node 컴포넌트

kubelet

Kubernetes의 Node 가용성은 kubelet이라는 컴포넌트에 의해 보장된다. kubelet은 Worker Node에서 실행되며, 클러스터 내에서 Node와 Pod의 상태를 지속적으로 관리하고 모니터링하는 핵심 역할을 수행한다. 

먼저 kubelet은 Control Plane으로부터 할당받은 Pod의 상태를 모니터링하며, 컨테이너가 정상적으로 실행되고 있는지 확인한다. 만약 컨테이너에 문제가 발생하면 이를 자동으로 재시작하거나, 상태를 Control Plane에 보고하여 필요한 조치를 취할 수 있도록 한다.

또한 kubelet은 Node와 Pod의 헬스 체크를 수행한다. Node가 비정상적으로 작동하거나 문제가 생겼을 경우 이를 Control Plane에 즉시 보고하여 해당 Node를 스케줄링 대상에서 제외시킨다. 더불어 Pod에 설정된 Liveness Probe와 Readiness Probe를 실행해 애플리케이션의 상태를 확인하고, 이를 바탕으로 트래픽이 정상적으로 처리될 수 있도록 지원하는 역할까지 수행한다. 

Kube-Proxy

kube-proxy는 클러스터 내 네트워크 통신을 관리하는 역할을 한다. 각 Worker Node에서 실행되며, Pod 간의 통신뿐만 아니라 클러스터 외부에서 들어오는 트래픽을 적절히 라우팅하는 역할을 한다. 

먼저, kube-proxy는 Kubernetes의 Service 개념을 기반으로 네트워크 규칙을 설정 한다. Pod는 동적으로 생성되고 IP가 변경될 수 있기 때문에, 이를 직접 추적하기는 어렵기 때문에 kube-proxy는 이러한 Pod들을 Service라는 논리적 그룹으로 묶고, 트래픽을 해당 Pod들로 분배한다. 예를 들어, 여러 Pod가 동일한 Service에 속해 있다면, kube-proxy는 이들 Pod로 부하를 자동으로 분산시켜 안정적인 트래픽 처리를 지원한다.

또한, kube-proxy는 클러스터 내부와 외부의 트래픽 라우팅을 처리한다. 내부적으로는 클러스터 IP(CIDR) 범위를 사용해 Pod 간 통신을 가능하게 하고, 외부 요청이 들어오는 경우에는 NodePort나 LoadBalancer를 통해 Service로 트래픽을 전달한다. 이 과정에서 IP 테이블 규칙을 설정하거나, IPVS를 활용하여 트래픽 처리를 수행한다. 

kube-proxy의 가장 중요한 기능 중 하나는 네트워크 연결을 유지하는 것이다. 클러스터 내 Pod가 삭제되거나 새로 생성되더라도, kube-proxy는 변경된 네트워크 상태를 즉시 반영하여 트래픽이 올바른 대상에 전달될 수 있도록 한다.

Container Runtime 

Kubernetes는 기본적으로 OCI 호환 컨테이너 런타임을 지원하며, 다음과 같은 containerd, CRI-O등의 런타임을 사용할 수 있다. kubelet은 CRI API를 사용하여 container runtime과 상호작용하여 컨테이너의 수명주기를 관리하고 모든 컨테이너 정보를 Control Plane에 제공한다.

* CRI(Container Runtime Interface)는 Kubernetes에서 컨테이너 런타임과 상호작용하기 위한 표준화된 API 인터페이스이다. 

Control Plane 컴포넌트 

kube-apiserver 

kube-apiserver는 Kubernetes API를 노출하는 핵심 컴포넌트이다. 모든 클러스터 내의 통신은 kube-apiserver를 통해 이루어지고  Kubernetes 리소스의 CRUD 작업을 수행한다. 예를 들어, 사용자가 kubectl 명령어로 Pod를 생성하거나 상태를 조회하면, 그 요청은 HTTP REST API를 통해 kube-apiserver에 전달되어 처리된다. Control Plane 컴포넌트들과는 gRPC 통신을 한다. 
TLS를 관리하여, 어떤 사용자가 어떤 리소스를 조작할 수 있는지 확인한다. 

kube-controller-manager

kube-controller-manager는 Kubernetes 클러스터에서 자동화된 작업을 담당하는 컨트롤러들을 관리하는 컴포넌트이다. 무한 제어 루프를 실행하느 프로그램으로 지속적으로 실행되며 객체의 현재 상태와 원하는 상태를 감시하는 역할을 한다. 

주요 controller 

  • 노드 컨트롤러: 노드가 다운되었을 때 이를 감지하고 알림을 보낸다. 예를 들어, 노드가 장애를 일으키면, 해당 노드를 클러스터에서 제외하고 리소스를 다른 노드로 재배치한다. 
  • 레플리케이션 컨트롤러: 지정된 수의 Pod가 항상 실행되도록 보장합니다. 예를 들어, ReplicaSet을 관리하여 Pod의 복제본을 생성하고, 실패한 Pod가 있으면 새로운 Pod를 만들어 재배치한다. 
  • 엔드포인트 컨트롤러: 서비스와 연결된 Pod의 IP 주소를 관리하고, 서비스와 파드 간의 네트워크 엔드포인트를 갱신한다. 
  • 서비스 어카운트 및 토큰 컨트롤러: 새로운 네임스페이스가 생성될 때 기본 서비스 계정과 토큰을 자동으로 생성하여 API 접근을 위한 인증을 제공한다. 

etcd

etcd는 Kubernetes 클러스터에서 모든 데이터를 저장하는 분산형 키-값 저장소이다. 클러스터의 상태, 리소스 설정, 파드 정보 등 모든 중요한 정보를 저장하고 있으며, 클러스터의 백본 역할을 한다. Raft 알고리즘을 지니고 있으며 gRPC 사용하여 API 서버와 통신한다.
Ngins Pod가 생성 되었다고 하면 /regiestry/pods/default/nginx 에서 검색할 수 있다. 

  • Kubernetes의 클러스터 상태와 리소스들의 설정 정보를 모두 저장한다. 예를 들어, Pod의 상태, 서비스의 정보, ConfigMap, Secret 등이 모두 etcd에 저장된다고 보면 된다. 
  • 분산 시스템으로 설계되어, 여러 노드에 걸쳐 데이터를 복제하여 장애가 발생해도 데이터 손실 없이 시스템이 안정적으로 운영하여 고가용성을 보장한다. 
  • etcd의 데이터는 클러스터의 중요한 정보이기 때문에, 정기적으로 백업을 받는것이 권장하는 솔루션이다. (snapshot 기능)

kube-scheduler

kube-scheduler는 새로 생성된 Pod를 클러스터 내에서 실행할 노드를 선택하는 역할을 한다. Kubernetes 클러스터에서 Pod는 실행할 노드가 정해지지 않은 상태로 생성되며, kube-scheduler는 이를 처리한다. Pod가 생성되면, kube-scheduler는 사용 가능한 노드 중에서 Pod를 실행할 노드를 선택한다. 이 과정에서 여러 조건(예: 노드의 리소스 상태, 우선순위, 정책)을 고려하여 최적의 노드를 결정한다. 예를 들어, Pod의 리소스 요구사항(CPU, 메모리 등), Affinity/Anti-affinity 규칙, Taints/Tolerations 등을 바탕으로 노드에 배치한다. 

Kube-scheduler 동작 

1. kubectl 등을 통해 Pod 생성 요청을 kube-apiserver에게 전달

2. kube-apiserver는 요청 정보를 etcd에 기록 (pod state) 

3. Client에게 요청 승인 알림

4. Scheduler는 할당을 위해 Node의 정보를 kube-apiserver에게 요청, etcd에 기록 (pod state)

5. Pod 할당을 위해 kube-apiserver는 지정된 Node의 kubelet에게 Pod(container) 생성

6. kubelet은 해당 Node의 container runtime 에게 container 시작 요청

7. kubelete은 생성상태를 kube-apiserver에게 Bind pod to Node 알림

8. kube-apiserver는 etcd에 기록(pod state) 

CNI(Container Network Interface)

CNI는 컨테이너 간의 네트워킹을 제어할 수 있는 Plugin 기반 Network architecture로 다양한 형태의 container runtime과 orchestrator 사이의 네트워크 계층을 구현하는 공통된 인터페이스를 제공한다. k8s는 Pod 간의 통신을 위해서 CNI를 사용한다. 

CNI가 없을 시 각 Node에 존재하는 container network의 IP 대역이 동일하여 Pod들이 같은 IP를 할당 받을 가능성이 높다. 즉 Pod의 IP가 다르게 할당되어도 해당 Pod가 어느 Node에 존재하는지 확인이 불가하다. 이는 자신의 Node에 있는 Pod IP만 식별 가능하기 때문이다. 따라서 중복되지 않는 IP를 부여해줄 CNI Plugin이 필요한것이다. CNI Plugin은 모든 worker node에게 중복되지 않는 subnet(CIDR)부여, worker node에 할당된 Pod는 해당 subnet에 포함된 IP를 제공받는다. 

 

CNI 구성시 CNI가 Bridge Interface를 만들고, 컨테이너 네트워크 대역대를 나누어 routing table 생성을 한다. Pod들은 CNI에 의해 고유의 IP를 제공받는다. 클러스터 내의 모든 Pod들은 내부 네트워크가 자동으로 구성되어 Service 없이도 Pod간 통신이 가능한 것이다. 그 중 대표적으로 kubernetes에서 많이 사용하는 CNI의 종류는 Calico이다. Calico는 vRouter를 구현하고 BGP프로토콜을 이용한다. 라우팅 정보를 공유하여 pod, service 네트워크를 수행하고 외부 pod통신은 overlay또는 Direct로 통신한다. calico에 대한 라우팅 정보는 마찬가지로 etcd에 저장된다. 

Calico는 각 node에게 중복되지 않는 subnet(CIDR)를 부여하고 node에 할당된 Pod는 해당 subnet에 포함된 IP를 제공받는다. 이를 관리하기 위해 IPAM 구성요소를 사용한다. 

즉 그래서 Calico에서의 IPAM을 정의한다면 다음과 같이 말할수있다. 

  • IP 범위 정의: 쿠버네티스 클러스터에서 각 노드의 Pod 네트워크 CIDR이 설정된다. 
  • Pod에 IP 할당: Pod가 생성되면 CNI 플러그인은 IPAM을 호출하여 Pod에 고유한 IP를 할당한다. 
  • IP 주소 회수: Pod가 삭제되면 해당 IP 주소를 다시 IP 풀로 반환한다. 

또한, Calico는 BIRD를 통해 각 Node의 라우팅 정보를 공유한다. Pod를 생성시 Bind된 Node에 caliexxxx 인터페이스가 자동으로 생성되어 연결된다. 

Calico의 작동 예시

  1. BGP(Border Gateway Protocol)를 통한 라우팅 정보 공유
    • Calico는 클러스터 내 각 노드에서 실행되는 BIRD 프로세스를 사용하여 BGP를 통해 라우팅 정보를 교환한다. 
    • 각 노드는 자신의 Pod CIDR(사설 IP 주소 범위)을 다른 노드와 공유한다. 
    • 이를 통해 모든 노드가 클러스터 내의 Pod 네트워크를 완전히 이해하게 되며, Pod 간 통신 시 트래픽을 올바른 노드로 라우팅할 수 있다. 
  2. 라우팅 테이블 설정
    • 각 노드의 라우팅 테이블에는 클러스터 내 모든 Pod에 대한 경로가 설정된다. 
    • Pod가 한 노드에서 다른 노드로 통신할 때, Calico는 로컬 라우팅 테이블을 참조하여 트래픽을 올바른 대상 노드로 전달한다. 
    • 예를 들어, Pod A가 노드 A에 있고, Pod B가 노드 B에 있다면, 노드 A는 라우팅 테이블을 참조해 트래픽을 노드 B로 전달하고, 노드 B는 해당 트래픽을 Pod B로 전달하는 구조이다. 

'kubernetes' 카테고리의 다른 글

[Kubernetes] Label, Select & Annotation  (0) 2024.12.03
[Kubernetes] Namespace  (0) 2024.11.29
[Kubernetes] Kubernetes Objects  (0) 2024.11.28
[kubernetes] Pod  (0) 2024.11.27
[Kubernetes] Kubernetes Cluster 환경 구축  (0) 2024.11.20