Skip to content

K8s Architecture

쿠버네티스는 중앙(Master)에 API 서버와 상태 저장소를 두고 각 서버(Node)의 에이전트(kubelet)와 통신하는구조로 동작한다. 하지만 이 개념을 여러 모듈로 쪼개어 구현하고 다양한 오픈소스를 사용하기 떄문에 설치가 까다롭고 구성이 복잡해보일 수 있다.

마스터-노드 구조

쿠버네티스는 전체 클러스터를 관리하는 마스터와 컨테이너가 배포되는 노드로 구성되어있다. 모든 명령은 마스터의 API 서버를 호출하고 노드는 마스터와 통신하면서 필요한 작업을 수행한다. 특정 노드의 컨테이너에 명령하거나 로그를 조회할 때도 노드에 직접 명령하는게 아니라 마스터에 명령을 내리고 마스터가 노드에 접속하여 대신 결과를 응답한다.

Master

마스터 서버는 다양한 모듈이 확장성을 고려하여 기능별로 쪼개져 있는 것이 특징이다. 관리자만 접속할 수 있도록 보안 설정을 해야하고 마스터 서버가 죽으면 클러스터를 관리할 수 없기 때문에 보통 3대를 구성하여 안정성을 높인다. AWS EKS 같은 경우 마스터를 AWS에서 자체 관리하여 안정성을 높였고(마스터에 접속 불가) 개발 환경이나 소규모 환경에선 마스터와 노드를 분리하지 않고 같은 서버에 구성하기도 한다.

Node

노드 서버는 마스터 서버와 통신하면서 필요한 Pod를 생성하고 네트워크와 볼륨을 설저한다. 실제 컨테이너들이 생성되는 곳으로, 수백대로 확장 가능하다. 각각의 서버에 라벨을 붙여 사용목적을 정의할 수 있다.

Kubectl

API 서버는 json 또는 protobuf 형식을 이용한 http 통신을 지원한다. 이 방식을 그대로 쓰면 불편하므로 보통 kubectl이라는 명령행 도구를 사용한다. 공식적으론 큐브컨트롤(cube control)이라고 읽는다.

Master 구성 요소

API 서버 (Kube-apiserver)

API 서버는 모든 요청을 처리하는 마스터의 핵심 모듈이다. Kubectl의 요청뿐 아니라 내부 모듈의 요청도 처리하며 권한을 체크하여 요청을 거부할 수 있다. 실제로 하는 일은 원하는 상태를 Key-value 저장소에 저장하고 저장된 상태를 조회하는 매우 단순한 작업이다. Pod을 노드에 할당하고 상태를 체크하는 일은 다른 모듈로 분리되어있다. 노드에서 실행중인 컨테이너의 로그를 보여주고 명령을 보내는 등 디버거 역할도 수행한다.

API 서버는 요청을 받으면 etcd 저장소와 통신할 뿐, 실제로 상태를 바꾸는 건 스케줄러와 컨트롤러이다. 현재 상태를 모니터링하다가 원하는 상태와 다르면 각자 맡은 작업을 수행하고 상태를 갱신한다.

스케줄러

스케줄러는 할당되지 않은 Pod을 여러 가지 조건(필요한 자원, 라벨)에 따라 적절한 노드 서버에 할당해주는 모듈이다.

컨트롤러

  • 큐브 컨트롤러 (kube-controller-manager)

    큐브 컨트롤러는 다양한 역할을 하는 아주 바쁜 모듈이다. 쿠버네티스에 있는 거의 모든 오브젝트의 상태를 관리한다. 오브젝트별로 철저하게 분업화되어 Deployment는 ReplicaSet을 생성하고 ReplicaSet은 Pod을 생성하고 Pod은 스케줄러가 관리하는 식이다.

  • 클라우드 컨트롤러 (cloud-controller-manager)

    클라우드 컨트롤러는 AWS, GCE, Azure 등 클라우드에 특화된 모듈이다. 노드를 추가/삭제하고 로드 밸런서를 연결하거나 볼륨을 붙일 수 있다. 각 클라우드 업체에서 인터페이스에 맞춰 구현하면 되기 때문에 확장성이 좋고 많은 곳에서 자체 모듈을 만들어 제공하고 있다.

분산 데이터 저장소 (etcd)

RAFT 알고리즘을 이용한 Key-value 저장소이다. 여러개로 분산하여 복제할 수 있기 때문에 안정성이 높고 속도도 빠른 편이다. 단순히 값을 저장하고 읽는 기능뿐 아니라 Watch 기능이 있어 어떤 상태가 변경되면 바로 체크하여 로직을 실행할 수 있다.

클러스터의 모든 설정, 상태 데이터는 여기 저장되고 나머지 모듈은 statless하게 동작하기 때문에 etcd만 잘 백업해두면 언제든지 클러스터를 복구할 수 있다. etcd는 오직 API 서버와만 통신하고, 다른 모듈은 API 서버를 거쳐 etcd 데이터에 접근한다. k3s 같은 초경량 쿠버네티스 배포판에서는 ectd 대신 sqlite를 사용하기도 한다.

Node 구성 요소

큐블릿 (Kublet)

노드에 할당된 Pod의 생명주기를 관리한다. Pod를 생성하고 Pod 안의 컨테이너에 이상이 없는지 확인하면서 주기적으로 마스터에 상태를 전달한다. API 서버의 요청을 받아 컨테이너의 로그를 전달하거나 특정 명령을 대신 수행하기도 한다.

큐블릿 서비스는 kube API 서버를 통해 클러스터의 변화를 감지하고, CNI 플러그인을 호출하여 노드 네트워크를 구성한다.

프록시 (Kube-proxy)

큐블릿이 Pod를 관리한다면 프록시는 Pod로 연결되는 네트워크를 관리한다. TCP, UDP, SCTP 스트림을 포워딩하고 여러개의 Pod를 라운드로빈 형태로 묶어 서비스를 제공할 수 있다.

초기에는 Kube-proxy 자체가 프록시 서버로 동작하면서 실제 요청을 프록시 서버가 받고 각 Pod에 전달해 주었는데 시간이 지나면서 iptables를 설정하는 방식으로 변경되었다. iptables에 등록된 규칙이 많아지면 느려지는 문제가 발생하여 최근에는 IPVS를 지원하기 시작했다.

Container runtime

컨테이너 런타임은 컨테이너 실행을 담당하는 소프트웨어이다.

Kubernetes는 containerd, CRI-O 및 기타 Kubernetes CRI(Container Runtime Interface) 구현과 같은 컨테이너 런타임을 지원한다.


참고