본문 바로가기
Container/Kubernetes

1. Kubernetes Overview

by wrynn 2021. 11. 27.

 쿠버네티스는 컨테이너화된 애플리케이션을 관리하는 도구입니다. 쿠버네티스는 노드의 집합인 클러스터 위에서 동작하며, 각 노드는 역할에 따라 워커 노드와 마스터 노드로 구분됩니다. 워커 노드는 실제로 컨테이너가 실행되는 노드를 말하며, 마스터 노드는 컨테이너를 적절한 워커 노드에 배치하고 클러스터와 노드의 상태를 모니터링하며 클러스터에 관한 정보를 저장합니다. 마스터 노드는 이러한 작업을 컨트롤 플레인이라 부르는 컴포넌트 집합을 활용하여 수행합니다.

 본문에서는 마스터 노드에서 실행되는 네가지 종류의 컨트롤 플레인 컴포넌트와 워커 노드에서 실행되는 두가지 쿠버네티스 컴포넌트에 대해 알아보겠습니다.


마스터 노드 - 컨트롤 플레인 컴포넌트

1. ETCD

 쿠버네티스는 클러스터 및 노드, 컨테이너에 관한 정보를 저장하기 위해 Key-Value 저장소인 ETCD를 사용합니다. 일반적으로 클러스터의 정보를 조회할 때 사용하는 kubectl get 명령의 출력 결과는 ETCD로부터 가져온 데이터입니다. 노드를 추가하거나 Pod 혹은 ReplicaSet을 새로 배포하는 등 클러스터에 대한 모든 변경 사항은 ETCD에 기록하고 나서 적용됩니다. ETCD 프로세스는 기본적으로 2379 포트를 사용합니다.

$ kubectl get no
NAME                                               STATUS   ROLES                  AGE     VERSION
ip-172-20-46-83.ap-northeast-2.compute.internal    Ready    node                   6h52m   v1.21.7
ip-172-20-61-237.ap-northeast-2.compute.internal   Ready    control-plane,master   6h53m   v1.21.7

2. API Server

 앞서 kubectl get 명령어를 사용하면 ETCD에 있는 데이터를 가져와 보여준다고 했습니다. 하지만 외부 사용자가 중간 과정을 거치지 않고 직접적으로 클러스터 내부의 ETCD에 접근할 수는 없습니다. 쿠버네티스 클러스터로 들어오거나 나가는 모든 요청은 API-Server를 통해서 이루어집니다. 사용자가 kubectl get 명령을 실행하면, 요청은 먼저 API-Server에 전달됩니다. API-Server는 요청에 대해 1) 사용자 인증 2) 유효성 검사 3) ETCD에서 데이터 조회 및 반환 순으로 kubectl get 명령을 처리합니다. API-Server 프로세스는 일반적으로 443 포트를 사용합니다. 

3. Kube Controller Manager 

 쿠버네티스에서 컨트롤러란 클러스터 내의 다양한 컴포넌트들의 상태를 끊임없이 모니터링하는 프로세스를 말합니다. 각 컨트롤러마다 담당하는 컴포넌트가 있습니다. 예를 들어 노드 컨트롤러는 노드의 상태를 확인하고 5초마다 노드의 상태(Heartbeat)를 전달받습니다. 만약 Heartbeat 수신이 한 번 중단되면 노드 컨트롤러는 40초 동안의 유예기간을 가진 다음, 현상이 지속되면 해당 노드를 Not Ready 상태로 바꿉니다. 그리고나서 5분 동안 노드가 정상 상태로 돌아오기를 기다립니다. 만약 돌아오지 않으면, 해당 노드에서 실행 중인 애플리케이션을 제거하고 정상 상태인 다른 노드에서 다시 실행시킵니다. 이 외에도 다양한 컴포넌트의 상태를 모니터링하는 컨트롤러를 모아 쿠버네티스에서는 kube-controller-manager 라는 단일 바이너리 형태로 컨트롤러 프로세스를 실행합니다.

4. Kube Scheduler

 스케줄러를 이해하려면 먼저 쿠버네티스의 Pod 개념을 짚고 넘어가야 합니다. 쿠버네티스를 사용하는 궁극적인 목적은 컨테이너의 형태로 실행되는 애플리케이션을 쉽게 배포하는 것입니다. 쿠버네티스는 컨테이너를 바로 워커 노드에서 실행시키지 않고 별도의 쿠버네티스 오브젝트인 Pod로 캡슐화하여 실행합니다. Pod는 쿠버네티스에서 실행할 수 있는 가장 작은 배포 단위로 하나의 Pod는 하나의 애플리케이션 인스턴스를 나타냅니다. 애플리케이션에 부하가 늘어 인스턴스를 추가해야 하는 경우 컨테이너가 새로 생성되는 것이 아니라 Pod 단위로 생성되며, 하나의 Pod가 하나의 컨테이너를 포함하는 것이 일반적이지만, 여러개의 컨테이너를 포함할 수도 있습니다. 

 스케줄러는 여러 대의 노드와 수 많은 Pod가 있을 때, 특정 Pod가 어떤 노드에 배치되는 것이 적절한지를 계산해줍니다. 스케줄러는 Pod가 어떤 노드에서 실행될지만을 결정하고, 실제로 Pod를 노드에서 실행하는 일은 kubelet이 담당합니다. 특정 컨테이너가 어떤 노드에 배치되는 것이 최적인지를 결정하는 것은 두 단계를 통해 이루어집니다. 첫번째 단계는 노드 필터링 단계로 컨테이너가 배치될 수 없는 노드를 걸러내는 단계입니다. 예를 들어 Pod의 CPU 및 메모리 요청량보다 가용한 자원이 작은 노드들은 이 단계에서 제외됩니다. 두번째 단계는 스코어링 단계로 가용한 노드들 사이에 점수를 매기는 것입니다. 우선순위를 정하는 함수를 수행하여 노드의 점수를 매긴 다음, 가장 높은 점수를 받은 노드에 Pod를 배치합니다. 점수를 매기는 데에는 컨테이너를 배치한 후 유휴 자원 등을 고려하며, 이는 커스터마이징이 가능하기 때문에 사용자의 선호에 맞게 스케줄러를 새로 구성할 수도 있습니다.


워커 노드

1. Kubelet

 kubelet은 각 워커 노드(이하 노드)를 대표하는 프로세스로, 해당 노드를 쿠버네티스 클러스터에 등록하여 클러스터의 일부로 동작하도록 만들어 줍니다. 그리고 API-Server를 통해 실행해야 할 컨테이너 정보를 주기적으로 확인합니다. 새로 실행할 컨테이너가 나타나면 노드의 컨테이너 런타임에 컨테이너 이미지를 다운로드하고 컨테이너를 실행하도록 지시합니다. 또한 kubelet은 일정 주기로 노드 및 그 노드에서 실행 중인 컨테이너의 상태를 지속적으로 마스터 노드에 전달하는 역할을 수행합니다. 

2. Kube Proxy 

 kube proxy를 이해하기 위해서는 쿠버네티스의 '서비스' 개념에 대해 알아야 합니다. 쿠버네티스에 웹 애플리케이션 Pod 하나와, 이와 연결된 데이터베이스 Pod 하나를 배포하는 상황을 생각해봅시다. 일반적인 3티어 구성에서 웹 애플리케이션은 IP 정보를 사용해 데이터베이스에 접근합니다. 하지만 쿠버네티스에서 데이터베이스 Pod의 IP가 항상 일정하리라는 보장은 없습니다. 쿠버네티스에서 Pod는 언제나 중단될 수 있고 새로 만들어질 수 있는데, Pod는 생성될 때 마다 IP가 바뀌기 때문입니다.

 쿠버네티스에서는 자주 변경되는 Pod의 IP 대신 'Service' 라는 자체적으로 사용되는 오브젝트를 활용하여 다른 Pod에 접근할 수 있게 해 줍니다. Service는 고정된 IP를 가지며, 해당 Service로 들어온 트래픽을 이와 연결된 Pod로 보내주는 역할을 합니다. 데이터베이스 Pod를 데이터베이스 Service에 연결해 두고, 웹 애플리케이션은 Service를 호출함으로써 데이터베이스 Pod를 호출할 수 있게 되는 것입니다. 

 kube proxy는 쿠버네티스 클러스터에서 이러한 서비스가 동작할 수 있도록 해 줍니다. kube-proxy는 쿠버네티스 클러스터에 속하는 각 노드에서 실행되는 하나의 프로세스로, 특정 서비스로 유입되는 트래픽을 적절한 Pod로 전달하는 규칙을 설정합니다. kube proxy의 구현 방법 중 하나는 iptables 규칙을 사용하는 것입니다. 각 노드마다 특정 서비스의 IP로 들어오는 트래픽을 그 서비스와 연결된 Pod의 IP로 전달하는 iptable 규칙을 생성하여 구현할 수 있습니다. 

 

 

 

 

 

댓글