Container Orchestration


Container Orchestration 이란 복잡한 컨테이너 환경을 효과적으로 관리하기 위한 도구로 K8s 가 주로 쓰인다.

  • Cluster = Master Node 가 중앙제어, 다수의 Worker Node 가 클러스터를 이루어 서로 통신하며 작동
  • State = Desired State 선언 시 관리자의 개입 없이 자동으로 상태를 유지
  • Scheduling = Container 를 배치할 적합한 Worker Node 를 찾아 배포
  • Rollout Rollback = 배포 버전관리
  • Service Discovery = 서비스 등록 및 조회
  • Volume = NFS, EBS 등 다양한 스토리지 마운팅

K8s Architecture


K8s 는 Master Node 와 Worker Node 의 집합으로 이루어진다.

Master Node 는 Worker Node 들을 Manage, Plan, Schedule, Monitor 하는 역할을 수행하기 위해 아래와 같은 Component 들을 가진다.

  • kube-apiserver
  • controller manager
  • etcd cluster
  • kube-scheduler

Worker Node 는 Containerized Application 이 실행되는 Node 로, 이를 위해 아래와 같은 Component 들을 가진다.

  • Container Runtime
  • kubelet
  • kube-proxy

Docker vs containerd


  • 2013년 Docker 출현으로 인한 컨테이너 기술 부상 이후 타 경쟁사 역시 각자 Container Runtime 을 개발하기 시작했고 이로 인해 표준화가 필요해졌다. 2016년 Docker 와 CoreOS 가 주축으로 imagespecruntimespec 등을 포함한 Open Container Initiative, OCI 를 출범하여 Container Runtime 의 표준화를 재정했다. 이후 OCI 스펙에 맞춰 각 기업들이 Container Runtime 을 발전시켰고, Docker 의 경우 OCI 표준에 맞춰 개발한 Container Runtime 이 runc 이다.
  • K8s 의 경우 초창기엔 Docker 만을 유일한 Container Runtime 으로 지원했었는데, OCI 등장 이후 다양한 Container Runtime 들이 등장하면서 각 Container Runtime 에 따라 kubelet 이 관리해야 하는 방법을 따로 유지보수해야하는 어려움이 발생하기 시작했다. 이런 kubelet 유지보수 문제를 해결하면서 동시에 다양한 Container Runtime 들을 지원하기 위해 kubelet 에서 Container Runtime 을 관리할 수 있는 인터페이스인 Container Runtime Interface, CRI 가 등장하게된다.
  • 초창기 Docker 는 monolithic 한 구조로 Docker Daemon 하나에서 Docker Client, Docker API, Container Runtime, Image Build 등을 포함하고 있었고, 이는 kubelet 이 Docker 의 Container Runtime 을 사용할 때 CRI 표준에 부합하는 dockershim 이라는 컴포넌트를 추가적으로 사용해야했다.
  • 이후 K8s 의 dockershim 지원이 중지되고, containerd 가 Docker 에서 분리되면서, CRI 스펙에 맞추기 위한 cri plugin 등을 containerd 내부적으로 추가하여 containerdkubelet 에 의해 관리될 수 있게되었다.
  • runc 가 컨테이너를 실행하는 실질적인 주체라면, containerd 는 한 단계 위에서 이미지 저장, 네트워킹, 스냅샷 및 기타 관리 작업 등의 기능들을 포함한 고수준의 Container Runtime 으로, 내부적으로 runc 를 사용하기에 OCI 와 CRI 표준을 모두 준수할 수 있는 Container Runtime 이 된 것이다.
  • We can use the 2 CLIs below instead of Docker to work with K8s
    • nerdctl = for general purpose from the containerd community
    • crictl = for debugging from the K8s community (works with all CRI-compatible container runtimes)

ETCD


  • ETCD is a distributed reliable key-value store that is Simple, Secure & Fast
  • K8s 의 모든 상태와 데이터를 저장
  • Key-Value 형태로 데이터를 저장
  • 분산 시스템으로 구성하여 고가용성 확보
  • TTL, watch 등 부가 기능 제공

Kube-API Server


  • 상태를 바꾸거나 조회
  • etcd 와 유일하게 통신하는 모듈
  • REST API 형태로 제공
  • 요청에 대한 권한 체크
  • 수평적 확장 가능
  • kubeadm 으로 설치할 경우 Pod 의 형태로 실행된다.
  1. Authenticate User
  2. Validate Request
  3. Retrieve data
  4. Update ETCD
  5. Scheduler
  6. Kubelet

Kube Controller Manager


  • 다양한 Controller 가 존재
    • A controller is a process that continuously monitors the state of the components within the system and works towards bringing the whole system to the desired functioning state
    • Replication Controller, Node Controller, Endpoint Controller, …
    • 끊임 없이 상태를 체크하고 원하는 상태를 유지
    • 복잡성을 낮추기 위해 하나의 프로세스로 실행

Installing Kube Controller Manager

wget https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kube-controller-manager
  • kubeadm 으로 설치할 경우 Pod 의 형태로 실행된다.

Kube Scheduler


  • kube-scheduler 는 생성 요청된 Pod 가 어느 Node 에 배포되어야 하는지 확인하는 역할을 수행한다. Node 의 현재 상태와 Pod 의 요구사항을 체크하여 적절한 Node 를 찾는 작업만 수행할 뿐 Pod 를 생성하는 역할은 kubelet 이 수행한다.

How does it work?

  • Pod 에 필요한 리소스를 여분으로 가지고 있는 Node 를 확인하고 Pod 가 배치된 후 남은 리소스량을 기준으로 순위를 매겨 스케쥴링을 수행한다.

Installing Kube Scheduler

wget https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kube-scheduler
  • kubeadm 으로 설치할 경우 Pod 의 형태로 실행된다.

Kubelet


kubelet 은 Master Node 의 kube-apiserver 로 부터 Container 생성 요청을 받아 Worker Node 에 설치된 Container Runtime 을 이용해 Container 를 생성하는 역할을 한다. kubelet 은 자신이 위치한 Node 와 생성한 Pod 들을 모니터링하여 주기적으로 kube-apiserver 와 소통한다.

Installing Kubelet

wget https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kubelet

kubeadm 으로 K8s Cluster 를 구축할 때 kubelet 은 설치되지 않으니 수동으로 Worker Node 에 kubelet 을 설치해주어야 한다. 때문에 kubelet 은 다른 Component 들과 다르게 Pod 이 아닌 Node 의 프로세스로서 실행된다.

Kube Proxy


  • 네트워크 프록시와 부하 분산 역할을 하며 K8s Cluster 에 배포된 모든 Pod 간의 통신을 담당한다.
  • 각 Node 에서 Pod 형태로 실행되기 때문에 kubectl get pods 로 조회 가능하다.
  • Service 와 EndpointSlice 의 변경을 감시한다.
  • 성능상의 이유로 별도의 프록시 프로그램 대신 iptables / IPVS / eBPF 등을 사용하여 트래픽 라우팅 설정만 관리한다.

References