# Kubernetes Cluster Architecture

2021. 5. 2. 16:04 개발 이야기/아키텍처

 

 

안녕하세요. 해커의 개발일기 입니다.

 

오늘은 지난번에 소개했던, 컨테이너 오케스트레이션인

Kubernetes의 기본적인 아키텍처를 소개하려고 합니다.

Kubernetes의 목적자동화된 방식으로 Container 기반의 Application을 호스팅하는 것 인데요.

이런 목적을 달성하기 위해서 Kubernetes 아키텍처를 이루는

컴포넌트들이 어떤 것들이 있고 어떤 기능을 통해 Kubernetes의 목적을 달성하고 있는지

알아보도록 하겠습니다.

 

 

쿠버네티스 클러스터물리적 또는 가상의 노드 집합으로 구성되어 있습니다. 이 노드 집합의 클러스터에서 논리적으로 Master 노드와 Woker 노드로 구분됩니다. 실제로 컨테이너를 띄우고 제어하는 것은 Worker 노드가 하게 되며, Master 노드는 컨테이너 오케스트레이션에 필요한 명령을 내리고 상태를 저장하는 컴포넌트들로 구성되어 있습니다. 

위 그림을 보면 Master 노드에는 Scheduler, Controllers, etcd, API server로 구성되어 있고 Worker 노드에는 Kubelet과 KubeProxy가 각 노드 별로 존재하는 것을 볼 수 있습니다. Kubelet과 KubeProxy는 모든 노드에 뜨는 컴포넌트이지만 설명 상의 이유로 위와같이 표현했습니다. 이제, 하나씩 컴포넌트 별로 어떤 기능을 하는지 알아보고 종합적으로 어떻게 오케스트레이션이 되는지 알아보겠습니다.

 

먼저, Master 노드에 있는 ETCD는 쿠버네티스 클러스터의 상태값을 저장하는 DB입니다. 기존의 우리가 사용하는 종류의 RDB, NoSQL은 아니고 KEY-VALUE 형태로 저장하는 DB입니다. 여기에는 다양한 정보들을 저장하고 있는데요. Node, POD, Config 등 쿠버네티스 오브젝트들의 모든 상태 값을 저장하고 있습니다. REDIS를 써보신분들은 REDIS와 유사한 DB라고 생각하시면 좋을거같습니다.

ETCD에서 저장된 모든 KEY 값을 가져오는 명령어를 실행해보면그림과 같이 KEY 값으로 사용된 값들이 보입니다. object 명인 pods, services, serviceaccounts 등과 네임스페이스, 그리고 오브젝트 명을 조합해서 key값으로 사용하고 있는 것을 확인할 수 있습니다.

 

 

다음은 VALUE를 조회해봤는데요 단순한 정보가 아닌 많은 정보가 담겨있는 것을 볼 수 있습니다. 이렇게 ETCD DB를 이용해서 쿠버네티스 클러스터의 모든 상태 정보를 저장하고 있는 것을 알 수 있습니다. 

 

 

 

다음은 Kube API Server 입니다. API 서버는 쿠버네티스의 모든 interface를 담당하고 있고 기본적으로 ETCD에 있는 상태값을 UPDATE 해주고, 상태값을 지킬 수 있게 관련 컴포넌트에게 명령을 전달해주는 역할을 하고 있습니다.

kubectl을 통해 get nodes 명령을 전달하면 HTTP 형태로 API server에게 명령이 전달되며, HTTP request 헤더에 있는 Authorization 정보를 통해 인증하고 ETCD에서 정보를 가져와 값을 리턴해줍니다.

다음은 kubectl 명령을 통해서 Application을 배포하는 명령어를 전달하면 발생하는 트랜젝션입니다. 인증을 하고 ETCD의 값을 가져와 다른 경우 상태값을 UPDATE하고, 이를 Scheduler에게 전달하며, Scheduler는 적절한 노드를 선정해 Container를 띄우게 됩니다. 이처럼 API Server는 단순 정보 전달 및 interface 역할을 해주고 있습니다. 

이어서, 실제 Container를 띄울 노드를 선정하는 Scheduler에 대해서 알아보겠습니다.

 Scheduler는 만약 사용자가 메모리가 2GB가 필요한 Container를 배포한 경우 2GB의 메모리가 여유가 있는 노드를 선정해서 이를 전달하는 역할을 해주는데요. 단순하게 생각할 수도 있지만, 여기에는 다양한 CheckList가 존재합니다.

1. 노드가 하드웨어 리소스에 대한 POD requirement를 이행할 수 있는지

2. 노드의 리소스가 부족하지 않은지

3. node selector 라벨이 있는지?

4. 포트가 사용중이지는 않은지?

 

이 외에도 여러 조건들이 있으며, 이런 조건을 모두 만족하는 노드에 Container를 배포하게 됩니다. 기본적으로 사용자는 Requirements, Limits, Taints, Tolerations, Node Selectors, Affinity를 이용해 이런 조건을 컨트롤할 수 있습니다. 

다음은 Kube Controller에 대해서 알아보겠습니다. Controller는 클러스터의 상태 모니터링과 관리를 해주는 컴포넌트인데요.

 

컨트롤러에는 오브젝트 별로 각각 쓰레드를 만들어 각각의 오브젝트만들 모니터링하도록 설계되어 있습니다.  노드의 상태만 모니터링하는 Node-controllerReplication 상태만 모니터링하는 Replication-controller를 통해 어떻게 클러스터에 배포된 Application을 관리하는지 간단하게 알아보겠습니다.

 

 

Node-Controller는 Defaults 설정 기준으로 5초마다 노드의 상태를 확인하고 40초 동안 상태가 비정상인 경우 해당 노드륵 NotReady 상태로  변경하게됩니다. 이런 경우가 발생하면 해당 노드에 떠있던 POD들도 EVICTED 상태가 되게 되는데요.

 

이렇게 되면 Replication만을 모니터링하는 Replication-controller가 이를 감지해 정상적인 노드로 해당 POD를 재배포해 어플리케이션의 호스팅을 계속하게 됩니다. 각각의 컨트롤러 쓰레드들은 맡은 바 역할을 충실히 이행해 쿠버네티스의 상태 모니터링과 관리를 하게 됩니다.

 

 

 

여기까지가 Master 노드에 해당하는 컴포넌트들의 설명이었습니다. 이어서 모든 노드에 해당하는 컴포넌트인 Kubelet과 KubeProxy에 대해서 알아보겠습니다. 

Kubelet은 크게 3가지 Mission을 수행하는데요. Node를 Kubernetes controll plane에 등록해주고, API 명령을 받아 POD를 생성해줍니다. 그리고 Node와 PODs 정보를 지속적으로 모니터링해 상태를 Report해주고 있습니다.

끝으로 Kubernetes의 마지막 컴포넌트인 KubeProxy를 알아보겠습니다. KubeProxy는 클라이언트가 API 서버를 통해 정의한 서비스들을 네트워크 상 연결할 수 있도록 하는 것을 목적으로 하고 있습니다. 클러스터 개념이다 보니 서로 다른 노드에 뜬 POD들이 통신을 해야하는 경우가 있는데요. 이를 위해 Proxy 역할을 해주고 있습니다.

또한, 하나의 Service 오브젝트에 하나 이상의 POD가 연결되어 있다면, 로드밸런싱(Load-Balancing) 역할을 해주기도 합니다. 

이렇게 Kubernetes Cluster에 존재하는 각각의 컴포넌트에 대해서 알아봤는데요. 각각의 컴포넌트들의 역할을 알고 보니, 자연스럽게 Kubernetes가 보장하는 기능들이 어떤 것들인지 생각할 수 있게됩니다. 

모두들 즐거운 Kube되시길 바라겠습니다.