Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

Contents

쿠버네티스에 대해서

쿠버네티스(혹은 K8s)는 컨테이너기반 애플리케이션과 서비스의 운영, 디플로이 자동화, 스케일링을 위한 소프트웨어 도구다. 도커 컨테이너 기반의 운영 툴 중에서는 가장 빠르게 성장하고 있는 소프트웨어라고 할 수 있다. 2014년 구글은 K8s를 오픈소스로 전환했다.

쿠버네티스로 할 수 있는 것들

쿠버네티스는 아래의 목적으로 사용하기 위한 기능들을 제공한다.
  • 컨테이너 플랫폼
  • 마이크로 서비스 플랫폼
  • 가벼운(portable) 클라우드 플랫폼
쿠버네티스는 컨테이너 중심의 관리 환경을 제공한다. 사용자의 워크로드를 실현하기 위해서 필요한 컴퓨팅, 네트워크, 스토리지 인프라를 구성하고 조정한다. 이를 이용해서 IaaS의 유연함과 PaaS의 단순함의 많은 부분들을 제공하고 인프라 공급자간의 이식성도 제공한다.

쿠버네티스는 플랫폼 인가 ?

쿠버네티스에서 제공하는 많은 기능들을 이용해서, 다양한 시나리오에 맞는 새로운 기능들을 빠르게 적용 할 수 있다. 응용 애플리케이션 별로 작으면서 유연한 워크플로우를 만들 수 있는데, 이를 통해서 개발 속도를 높일 수 있다. 또한 응용 프로그램의 손쉬운 배포와 확장, 관리 및 운용 기능들을 제공하고 자동화될 수 있기 때문에 대규모의 시스템 구성에도 능동적으로 대응 할 수 있다. 이러한 쿠버네티스의 특징은 애플리케이션 관리, 스케일링, 배포등을 위한 플랫폼을 제공 함으로써 이 위에 생태계를 구축하는 역할을 수행 할 수 있다.

레이블을 이용해서 사용자는 원하는 대로 리소스를 구성 할 수 있다. 어노테이션(annotations)는 사용자가 자신의 워크플로우를 용이하게 구성할 수 있도록 돕는다.

또한 쿠버네티스의 컨트롤 팬널(control plane)은 개발자와 사용자가 동일하게 사용 할 수 있는 API를 기반으로 한다. API를 이용해서 모든 것을 할 수 있다는 의미로, 사용자는 이들 API를 이용해서 스케줄러를 포함한 자체 컨트롤러를 개발 할 수 있다.

이러한 디자인은 쿠버네티스 위에서 다양한 시스템 설계가 가능하게 한다.

쿠버네티스로 할 수 있는 것과 그렇지 않은 것들

쿠버네티스는 PaaS(Platform as a Service) 시스템이 아니다. 쿠버네티스는 하드웨어가 아닌 컨테이너 수준에서 작동하기 때문에, 배포, 로드밸런싱, 스케일링, 로깅, 모니터링과 같은 PaaS 기능을 제공한다. 이러한 기능과 생태계에서 제공하는 다른 기능들을 조합해서 PaaS 시스템을 구성 할 수는 있겠지만, PaaS 자체는 아니다. 쿠버네티스의 가장 큰 장점은 선택의 자유와 유연성에 있다고 하겠다.

쿠버네티스는
  • 지원 애플리케이션를 특정하거나 제한하지 않는다. 쿠버네티스는 애플리케이션의 특징에 상관 없이, 어떤 종류의 작업이라도 처리 할 수 있도록 지원되는 "환경을 제공"하는 것을 목표로 한다. 컨테이너에서 실행될 수만 있다면, 어떤 애플리케이션이든 상관 없다.
  • 소스코드를 배포하고나 응용 프로그램을 빌드하지 않는다. CI, CD는 기술적요구사항과 조직문화에 따라서 결정된다.
  • 메시지버스와 같은 미들웨어, Spark 등의 데이터처리 프레임워크, 데이터베이스, 캐시, cept 등의 스토리지 시스템과 같은 애플리케이션 레벨의 서비스를 제공하지는 않는다. 쿠버네티스는 이러한 애플리케이션을 실행할 수 있는 환경을 제공한다.
  • 로깅, 모니터링, 알람 솔류션등을 제공하지 않는다.
  • Jsonnet 과 같은 language/system을 제공하거나 필수로 요구하지 않는다.
  • 포괄적인 머신설정, 관리, 유지, 자가치유 시스템등을 제공하지 않는다.
또한 쿠버네티스는 단순한 오케스트레이션 시스템이 아니다. 실제 오케스트레이션이 필요없다. 오케스트레이션이라는 것은 A다음에 B, B 다음에 C를 실행하라는 명령을 저장하는 일종의 정의된 워크 플로의 실행이다. 반대로 쿠버네티스는 제어 프로세스의 세트로 구성된다. A에서 어떻게 C로 가든지 상관 없다. 중앙집중식 제어가 필요 없다. 이로 인해, 사용하기 쉽고 강력하고 견고하며 뛰어난 확장성을 가진 시스템이 만들어졌다.

왜 컨테이너를 사용하는가 ?

왜 컨테이너를 기반으로 하고 있을까 ? 아래 그림을 보자.

 예전방식과 컨테이너 방식

에전에는 운영체제의 패키지 관리자를 이용해서 호스트위에 애플리케이션을 설치해서 실행을 했다. 이 방식은 애플리케이션의 실행파일, 설정파일, 라이브러리와 라이프사이클이 호스트 운영체제에 얽히게 한다는 단점을 가지고 있다. 변경불가능한 가상 시스템이미지를 만들 수도 있었지만 VM은 무겁고 non-portable 하다.

새로운 방식은 하드웨어 가상화가 아닌 운영체제 레벨의 가상화 시스템인 컨테이너를 이용해서 배포를 한다. 이 컨테이너들은 호스트에 있는 다른 컨테이너들과 격리된다. 컨테이너는 자신들의 파일 시스템과 프로세스, 설정파일 라이브러리를 가진다. 이들은 VM보다 쉽게 만들 수 있다. 또한 호스트 시스템에서 분리되므로 클라우드와 OS를 막론하고 간단하게 배포할 수 있다.

컨테이너라는 용어 때문에 헷갈리는 경우가 있는데, 컨테이너는 단위 프로그램이며 프로세스형태로 실행된다. 다만 이 프로세스가 완전히 격리가 되기 때문에 컨테이너라고 부르는 것일 뿐이다. VM처럼 운영체제가 실행되는게 아니고 프로세스가 실행되는 만큼 작고, 빠르다. 하나의 애플리케이션이 하나의 이미지가 되는 구성인데, 이러한 구성은 많은 잇점을 제공한다. 빌드/릴리즈 시간에 변경 할 수 없는 컨테이너 이미지를 만들 수 있으며, 개발에서 프러덕트까지 일관된 컨테이너 이미지를 만들 수 있다. 게다가 VM과 달리 운영체제에서 직절 실행되기 때문에, 훨씬 투명한 모니터링과 관리가 가능하다. 기본적으로 컨테이너 이미지는 패키징된 애플리케이션과 차이가 없다.

컨테이너의 이점은 아래와 같이 정리 할 수 있다.
  • 민첩한 애플리케이션 생성과 배포
  • 연속적인 개발, 통합, 배포 환경 구성
  • 개발과 운영의 분리
  • 높은 관리성
  • 개발, 테스트, 프러덕트 전반에 걸친 환경의 일관성
  • 클라우드와 운영체제에 간단히 배포 할 수 있다.
  • 애플리케이션 중심의 관리
  • 느슨한 결합, 분산, 탄성, 마이크로 서비스화
  • 자원의 격리
  • 효율적인 자원의 사용

Kubernetes와 K8s는 무엇인가

쿠버네티스는 조타장치 혹은 조종사를 의미하는 그리스어다. K8s는 "ubernete" 8개의 문자를 8로 대체해서 만든 단어다(발음하기가 좀 까다로워서).

쿠버네티스의 구성요소(components)

 k8s 구성요소

Master Components

Master Components는 클러스터를 컨트롤하기 위한 기능들을 제공한다. 마스터 컴포넌트는 클러스터 전역에 걸친 의사 결정(스케쥴링 같은)과 클러스터 이벤트 감지 및 응답을 한다.

마스터 컴포넌트는 클러스터에 있는 어떤 노드에서도 실행 될 수 있다. 일반적으로는 유저 컨테이너가 실행중인 머신을 제외한 머신에서 모든 마스터 컴포넌트를 실행한다.
etcd
etcd는 분산 환경에서 설정관리, 서비스 디스커버리, 작업 조율등을 위한 데이터를 저장하는 분산 key-value 저장소다.

Kubernets는 분산 환경에서 작동한다. etcd는 Kubernetes 클러스터를 안정적으로 운영하기 위한 데이터 저장소를 제공한다. 여기에는 클러스터의 상태(클러스터에 참여한 노드, Pod, 실행 중인 작업 관리, 등등등...) 정보들이 저장된다.

클러스터의 모든 정보가 etcd에 저장이 되므로 항상 백업 계획을 세워야 한다. etcdctl snapshot save 명령으로 etcd 데이터를 백업 할 수 있다. AWS에서 사용 할 경우 EBS 볼륨 스냅샷으로 etcd를 백업할 수 있다. 혹은 etcd 스냅샷을 S3로 저장할 수도 있다.

etcd에 대한 자세한 내용은 etcd 문서를 참고하자.

Kube-apiserver
관리자는 kubectl CLI(Command-line interface)를 이용해서 Kubernets를 관리하는데, 실제로는 Kube-apiserver(이하 API 서버)에서 제공하는 API를 이용하게 된다.

API 서버는 전체 클러스터를 관리하기 위한 접점이다. 즉 REST API를 이용해서 etcd 정보를 조회하고 업데이트하고 명령을 실행한다. API 서버는 간단한 API만을 제공하며, 다른 많은 비지니스 로직은 별도의 구성요소나 플러그인으로 구현한다.

API 서버는 오로지 etcd에만 연결을 한다. 다른 모든 구성요소들은 작업을 위해서 API 서버를 거쳐야만 한다. 또한 API 서버는 인증과 권한을 담당한다. API를 이용하기 위해서는 반드시 인증을 거쳐야 한다.

API 서버는 클라이언트에게 변경사항을 알려주기 위한 watch 매커니즘(etcd와 비슷하다)도 가지고 있다. 이를 통해서 스케줄러와 컨트롤러와 같은 구성요소들이 API를 중심으로 느슨하게 연결할 수 있다. 이 패턴은 Kubernets 전체에 광범위하게 사용하고 있다. 예를 들어 kubectl을 이용해서 pod를 만들 경우 아래와 같은 과정을 거친다.

 Create Pod Flow

  1. Kubectl로 create Pod API를 호출한다.
  2. API Server는 요청이 유효한지를 검사하고 etcd에 저장한다.
  3. etcd가 결과를 리턴한다.
  4. API Server는 스케쥴러를 호출한다.
  5. 스케쥴러는 Pod를 실행할 위치를 결정하고 리턴한다.
  6. API Server는 Pod 실행 결과를 etcd에 기록한다.
  7. etcd가 결과를 리턴한다.
  8. API Server는 해당 노드에있는 Kubelet를 호출한다.
  9. Kubelet는 Docker API를 이용해서 컨테이너를 만든다.
  10. Kubelet는 API를 호출해서 Pod 상태를 업데이트한다.
  11. API 서버는 etcd의 상태를 유지한다.
kube-controller-manager
Kubernets Controller Manager는 core control loops(controllers라고 부르는)에 임베디드된 데몬이다. 기본적으로 컨트롤러는 API Server의 watch 기능을 이용해서 클러스터의 상태를 감시하고, 알림을 받고, 현재 상태를 원하는 상태로 바꾸기 위한 작업을 수행한다. 컨트롤러의 몇 가지 다른 예로 복제 컨트롤러(Replication Controller), 엔드포인트 컨트롤러(Endpoints Controller), 네임스페이스 컨트롤러(Namespace Controller)등이 있다.

또한 컨트롤러는 네임스페이스의 생성과 라이프사이클 관리, 이벤트 가비지 콜랙션, Pod의 삭제, 노드 가비지 컬렉션등의 기능을 수행한다.

kube-scheduler
스케쥴러는 Pod 생성을 위해서 요청한 리소스, 서비스 품질 요구 사항, 우선순휘 기타 제약조건에 따라서 노드에 바인드하는 일을 한다. Pod를 노드에 할당하고 나면 Kubelet가 실행되서, 실제 Pod와 컨테이너가 만들어진다.

Node Components

이제 Kubernets Node를 구성하는 Node Components를 살펴보자. Kubernets Node는 Kubelet와 Service Proxy가 주요한 역할을 수행한다. 이들은 컨테이너를 실행하고 네트워크를 설정하는 등 실제 유저가 사용하는 서비스를 관리하는 일을 한다.

Service-proxy
(Kube proxy라고 부르기도 한다.)서비스 프록시는 각 노드에서 실행되며, 서비스와 Pod의 변경사항을 읽어서 Pod간 통신, 다른 노드간의 통신이 가능하도록 한다. 컨테이너는 서비스 프록시를 이용해서 다른 서비스와 통신 할 수 있다. 또한 iptables를 조작해서 서비스 IP에 대한 접근 제어를 수행하고, 패킷을 올바른 컨테이너로 리다이렉션 한다.
  1. 각 노드에서 실행된다.
  2. UDP와 TCP를 프락시 할 수 있다.
  3. HTTP를 이해하지 못한다. 즉 L7에서 작동하는 프락시는 아니다. L7 프락시는 개발자가 직접 구성을 해야 한다.
  4. 로드밸런싱 기능을 제공한다.
kubelet
kubelet는 kubernetes에서 가장 중요한 요소 중 하나다. 이 애플리케이션은 각 노드에서 실행되는 일종의 에이전트이며 노드에 바인딩된 pod가 실행 중인지 관리 한다. 도커 API를 이용해서 도커 데몬과 통신을 해서 컨테이너를 실행하고, 이를 통해서 pod 상태가 변하면 API Server에 보고한다. Kubelet이 하는 일은 아래와 같다.
  • Pod 컨테이너를 실행한다.
  • 각 노드와 pod의 상태를 리포팅 한다.
  • container probe를 실행한다.
  • cAdvisor로 컨테이너를 모니터링 한다.
또한 kubelet는 10255 포트로 HTTP 서버를 시작하고 /metrics, /metrics/cadvisor, /pods, /spec 와 같은 디버깅, 통계용 API를 제공한다.

cAdvisor
Kubelet는 CPU, 메모리, 파일, 네트워크 사용량과 같은 메트릭을 수집하고 처리하는 cAdvisor를 기본으로 제공한다. cAdvisor는 4194 포트로 접근 할 수 있는 내장 웹서버를 가지고 있다. 브라우저에서 http://<node-ip>:4194 를 호출하는 것으로 컨테이너 정보를 모니터링 할 수 있다.

주요 메트릭 엔드포인트는 GET http://<node-ip>:4194/metrics 로 확인 할 수 있다.

심심해서 내 PC에 cAdvisor를 설치해서 직접 테스트해보기로 했다.
# docker run --publish=8080:8080 --detach=true --name=cadvisor google/cadvisor

참고