MSA - Kubernetes - Architecture
edX에서 쿠버네티스를 공부하면서 알게 된 내용을 정리하고 공유합니다.
쿠버네티스는 control plane master node worker node, etcd(클러스터 상태 관리), 네트워크 상태 설정
- Discuss the Kubernetes architecture.
- Explain the different components for master and worker nodes.
- Discuss about cluster state management with etcd.
- Review the Kubernetes network setup requirements.
마스터 노드
마스터 노드는 클러스터 상태 관리를 책임지는 컨트롤 플레인의 실행 환경을 제공한다. 컨트롤 플레인 컴포넌트들은 각자 구분된 역할을 가지고 있다.
컨트롤 플레인을 항상 가동중이도록 하는 것은 매우 중요하다. 컨트롤 플레인이 죽으면 다운타임이 발생한다. 이를 방지하기 위해 HA(High Availability) 모드에서 마스터 노드 레플리카가 추가되기도 한다. 하나의 마스터 노드만 사용이 되지만 각 컨트롤 플레인 컴포넌트들은 계속 동기화 된다.
쿠버네티스 클러스터 상태를 계속 지속하기 위해 전체 클러스터 설정은 etcd에 저장된다. etcd는 클러스터 상태 정보만 저장하는 분산화된 키-밸류 저장소 이다. etcd는 마스터 노드에 설정될 수도 있고 데이터 손실의 가능성을 줄이기 위해 외부 별도 서버에 설정이 될수도 있다. 외부에 설정이 되는 경우 HA 구성을 별도로 해주어야 한다.
마스터 노드는 컨트롤 플레인의 아래 요소들을 돌리고
-
-
- API Server
- Scheduler
- Controller Managers
- Data Store.
-
또 추가로 아래 요소를 돌린다.
- Container Runtime
- Node Agent
-
Proxy.
- API Server
- 모든 관리와 관련된 일은 마스터 노드에서 동작하는 컨트롤 플레인의 중심 컨포넌트인 kube-apiserver를 통해 조율된다. API Server는 사용자나 다른 Agent로부터 오는 요청을 가로채서 검증하고 처리하는 역할을 수행한다. 이 처리를 하는 동안 etcd 로부터 클러스터 상태를 읽고 처리를 끝내고 상태를 다시 etcd로 쓴다. API Server는 etcd와 데이터를 읽고 쓰면서 소통하는 유일한 마스터노드 컴포넌트이다. API Server는 클러스터 상태를 요청하는 다른 컨트롤 플레인 에이전트들의 미들 인터페이스 역할을 한다.
- API Server는 매우 자유도 높게 커스터미징이 가능하다. 수평적으로 확장도 가능하고 보조 API 서버들을 둘수도 있다. 보조 API 서버들을 둘 경우 API 서버가 보조 서버들의 대리자(proxy) 역할을 수행하며, 사용자가 정의한 규칙에 따라 각 서버들에 요청을 분배한다.
- Scheduler
- kube-scheduler는 새로운 워크로드 객체들을 노드에 할당한다. 스케쥴링 과정에서 클러스터 현재 상태와 새로운 객체의 요구사항에 따라 의사결정이 이루어진다. API Server를 통해 etcd 데이터를 가져오고 클러스터 내 워크 노드들의 자원 사용량을 가져오고, API 서버로부터 설정 정보 중 하나인 새로운 객체 요구사항을 가져온다. 이 요구사항에는 disk가 ssd여야 한다는 등의 설정이 들어가 있을 수 있다. 스케쥴러는 서비스의 품질 요구사항, 데이터 지역성, 선호도, 오염, 허용 오차, 클러스터 위상등을 고려합니다. 모드 클러스터 자원이 가용하면, 스케쥴러는 새로운 워크로드의 요구사항에 가장 부합하는 노드 후보들을 필터합니다. 이 결정의 결과를 API Server에게 전달하여 워크로드 배포를 다른 컨트롤 플레인 Agent에게 위임합니다.
- 스케쥴러는 설정 자유도가 높고 스케쥴링 정책, 플러그인, 프로파일을 통해 커스터마이징이 가능합니다. 추가적인 커스텀 스케쥴러가 사용되면 객체 설정에는 어떤 스케쥴러가 스케쥴링 결정을 할것으로 예상되는지에 대한 이름이 명시되어야 합니다. 명시되지 않은 경우 기본 스케쥴러가 사용됩니다.
- 스케쥴러는 멀티노드 클러스터에서 매우 중요하고 복잡합니다. 단일 노드의 경우 스케쥴러 작업은 단순합니다.
-
Control Manager
- 컨트롤 매니저는 컨트롤러를 구동하는 마스터노드에서 구동되는 컨트롤 플레인 컴포넌트로서 클러스터 상태를 정규화 하는데 사용된다. 컨트롤러는 계속해서 클러스터의 희망 상태(객체 설정 데이터가 제공 )와 etcd에서 획득되는 클러스터 상태를 비교하고 불일치하는 경우에 맞추는 작업을 진행하는 watch loops이다.
- Kube-controller-manger는 노드가 죽었을 때 기대되는 구동되는 컨트롤러를 실행하여 pods의 수가 예상대로인지 확인하고, API 접근 토큰 , endpoints, 서비스 계정을 생성합니다.
- cloud-controller-manager는 노드를 사용할 수 없을 때 클라우드 공급자의 기본 인프라와 상호 작용하고, 클라우드 서비스에서 제공하는 경우 스토리지 볼륨을 관리하고,로드 밸런싱 및 라우팅을 관리하는 컨트롤러를 실행합니다.
- etcd
- etcd는 쿠버네티스 클러스터 상태를 저장하기 위해 사용되는 강력한 지속, 분산 키-밸류 형태의 저장소이다. 새로운 데이터는 기존의 데이터에 덧붙여지는 형태로만 추가된다. 기존 데이터는 대체되지 않으며 주기적으로 압축된다.
- 모든 컨트롤 플레인 컴포넌트 중에서 API Server만이 etcd랑 소통한다.
- Etcdclt(etcd cli management tool)은 단일 etcd 인스턴스에 대해 강력한 백업, 스냅샷 등의 기능을 제공합니다. 단일 etcd는 개발 및 학습 환경에는 적합하지만 프로덕션 환경에서는 HA 모드에서 레플리카 구성이 되어야 합니다.
- kubeadm 같은 쿠버네티스 컴퓨팅 툴은 기본적으로 staced etcd 마스터 노드들을 제공합니다. 이 etcd들은 같은 마스터 노드 안에 있는 컨트롤 플레인들에서 구동이 되며 서로 데이터를 공유합니다.
- 컨트롤 플레인으로부터 데이터 저장소를 격리하기 위해 부트스트랩 프로세스는 격리된 특정 서버에 외부 etcd 형태로 설정될 수 있습니다.
- Stacked 나 external이나 모두 HA 모드로 구성이 될 수 있으며 Raft Consensus Algorythm을 사용해 마스터 노드를 선출한다. 하나의 노드가 마스터 노드가 되며 다른 노드들은 follower가 되며 etcd는 마스터 노드를 포함한 어떤 노드가 죽더라도 마스터 노드 선출을 매우 잘 조절한다.
- 쿠버네티스에서 쿠버네티스 상태뿐아니라 서브넷, configmaps, 비밀 사항 같은 설정 세부 정보가 저장된다.
워커 노드
- 워커 노드는 클라이언트 어플리케이션에 실행 환경을 제공한다. 컨테이너화된 마이크로서비스를 통해 이 어플리케이션들은 마스터 노드의 컨트롤 플레인을 통해 관리되는 Pods 안에 캡슐화 된다. 팟들은 워커 노드 위에서 조정되며 워커노드 위에서 필요한 컴퓨팅 자원 및 네트워킹 자원을 찾습니다. Pods은 쿠버네티스에서 스케쥴링에 사용되는 가장 작은 단위이다. Pods는 함께 동작하는 하나 또는 하나 이상의 컨테이너 묶음이다. Pods에 묵인 컨테이너들은 하나의 작업으로 시작, 중지, 리스케쥴이 될 수 있다.
- 또한 클러스터 환경에서 클라이언트 사용자와 Pods에 배포되어 있는 컨테이너 어플리케이션간의 네트워크 트래픽은 마스터 노드가 아닌 워커 노드에 의해 관리된다.
워커 노드 구성요소
- Container Runtime
- Node Agent - kubelet
- Proxy - kube-proxy
- Addons for DNS, Dashboard user interface, cluster-level monitoring and logging.
Container Runtime.
쿠버네티스가 컨테이너 오케스트레이션 엔진으로 묘사되지만 컨테이너를 직접 다룰 수 있는 기능은 없다. 컨테이너의 라이프사이클을 다루기 위해서 노드에 있는 컨테이너 런타임이 필요하다. 쿠버네티스는 Docker, CRI-O, containerd 등의 많은 컨테이너 런타임을 지원한다.
kubelet
kublet은 각 노드에서 컨트롤 프레인과 소통하는 대리자이다. API 서버로부터 Pod 정의를 받고 Pod과 관련이 있는 컨테이너를 실행하기 위해 컨테이너 런타임과 상호작용한다. 또한 컨테이너들을 실행중인 Pods의 건강과 자원을 모니터링 한다.
kublet은 Container Runtime Interface에 기초한 플러그인을 통해 컨테이너 런타임과 연결된다. CRI는 프로토콜 버퍼, gRPC API 등으로 구성되어 있다. 교체 가능한 컨테이너 런타임과 연결되기 위해 kublet은 kubelet과 container runtime 간의 추상화 계층을 제공하는 shim application 을 사용한다.
kublet은 grpc 클라이언트, CRI shim은 grpc server 로서 동작한다. CRI 는 이미지 서비스와 런타임 서비스를 구현한다. 이미지 서비스는 이미지 관련된 동작과, 런타임은 Pod과 컨테이너 관련된 동작을 책임진다.
컨테이너 런타임은 예전에는 kubelet에 하드코딩 되었지만 CRI가 나온 후로는 다시 컴파일할 필요가 없어졌다. CRI를 구현한 어떤 컨테이너 런타임도 쿠버네티스에 의해 Pod, Container, Container 이미지를 관리하기 위해 사용될 수 있다.
kube-proxy
Kube-proxy은 각 노드에서 동적으로 네트워크 규칙들을 업데이트하고 관리하는 책임을 가진 네트워크 대리자입니다. Pods 의 네트워킹 세부사항들을 추상화하고 커넥션 요청을 팟에게 전달합니다.
kube-proxy는 TCP, UDP 그리고 SCTP 스트림을 전달하거나 pods 백엔드 모음들 사이에서 round-robin 방식으로 요청을 전달하는 역할을 맡고 있습니다. 그리고 API Objects를 통해 정의된 사용자 정의 전달 규칙들을 구현합니다.
Addons
addons는 쿠버네티스가 제공하지 않는 클러스터 피쳐들입니다. DNS, Dashboard, Monitoring, Logging 등이 있습니다.
Networking Challenges
디커플된 마이크로서비스들은 하나의 Monolith어플리케이션처럼 동작하기 위해서 네트워크에 강하게 의존한다. 그리고 일반적으로 네트워크는 이해하거나 구현하기가 쉽지 않다. 쿠버네티스도 마찬가지이며 몇가지 네트워크 문제들을 해결할 필요가 있다.
- Pods 안에서 컨테이너들끼리 소통
- 같은 노드 또는 여러 노드에 걸친 Pod 끼리의 소통
- 같은 네임스페이스, 또는 클러스터 내 다른 네임스페이스에서의 Pod과 서비스 소통
- 클러스터 내부 어플리케이션을 클라이언트가 접근하기 위한 외부 - 서비스 통신
Pods 안에서 컨테이너들끼리 소통
컨테이너 런타임은 각 컨테이너를 실행할 때 독립된 네트워크 스페이스를 만든다. 리눅스에서는 독립되 네트워크 스페이스를 네트워크는 네트워크 네임스페이스를 통해 참조된다. 네트워크 네임스페이스는 컨테이너들끼리 또는 호스트 운영 시스템에 의해 공유될 수 있다.
Pause Container가 Pod이 생성될 때 생성되며 해당 팟 컨테이너를 통해 localhost로 서로를 호출한다.
각각 네트워크 공간을 가지고 컨테이너가 만들어지는데, 같은 네임스페이스로 구동이 되기 위해 Pause 컨테이너를 사용한다.
– 추가 공부 필요한 것 : 리눅스 네트워크 네임스페이스
같은 노드 또는 여러 노드에 걸친 Pod 끼리의 소통
클러스터 내에서 Pods은 예측 불가능한 방법으로 예약된다. 어떤 호스트노드에 있던지 상관 없이 Pods은 NAT을 구현하기 안고 같은 클러스터 내에 있는 다른 Pods와 소통 가능할 것으로 기대된다.
쿠버네티스 네트워크는 복잡성을 줄이는 것을 목표로 하고 Pods를 각 네트워크 인터페이스를 가지고 있는 네트워크 상의 VM으로 취급한다. 그리고 각 Pods에 IP 주소를 할당한다. 그리고 VM들이 동일 네트워크에서 각 소통하는 것과 같은 방식으로 소통한다.
그리고 컨테이너들은 Pod의 네트워크 네임스페이스를 공유하는데 Pod 안에서 localhost로 소통하며 포트 할당을 잘 조정해야 한다. 그러나 컨테이너들은 CNI 플러그인을 통해 지원되는 CNI를 사용해 쿠버네티스 네트워킹 모델과 통합된다. CNI는 컨테이너들을 위한 네트워킹 설정할 수 있도록 하는 스펙과 라이브러리들의 합니다. 대부분의 CNI는 써드파티 쿠버네티스 네트워킹 모델을 구현한 SDN(Software Defined Networking) 솔루션이다.
컨테이너 런타임은 IP 할당을 CNI에 넘긴다. CNI는 기본적으로 설정된 플러그인과 연결되고 IP 주소를 가져온다. 각 플러그인에 의해 IP 주소가 주어지면 CNI는 컨테이너 런타임에 해당 IP 주소를 전달한다.
– 추가 공부 필요한 것 : Loopbak vs Bridge vs Macvlan vs IPvlan Plugin
클러스터 내부 어플리케이션을 클라이언트가 접근하기 위한 외부 - 서비스 통신
쿠버네티스 안의 팟에서 실행되고 있는 어플리케이션들은 외부 사용자로부터 접근될 필요가 있다. Kubernetes는 서비스, 클러스터 노드의 iptables에 저장되고 kube-proxy 에이전트에 의해 구현 된 네트워크 라우팅 규칙 정의의 복잡한 캡슐화를 통해 외부 접근성을 지원합니다. kube-proxy를 사용하여 서비스를 외부 세계에 노출함으로써 가상 IP 주소를 통해 클러스터 외부에서 애플리케이션에 액세스 할 수 있습니다.kube-proxy의 도움으로 서비스들을 외부에 노출함으로써 어플리케이셔은 가상 IP 주소 기반으로 외부에서 접근가능해진다.