Kubernetes

From 탱이의 잡동사니
Jump to: navigation, search

Overview

Kubernetes 내용 정리.

Tutorial

쿠버네티스 클러스터

쿠버네티스는 서로 연결되어서 단일 유닛처럼 동작하는 고가용성의 컴퓨터 클러스터를 상호조정한다. 쿠버네티스의 추상화된 개념을 통해 개별 머신에 얽매이지 않고 컨테이너화된 애플리케이션을 클러스터에 배포할 수 있다. 이렇게 새로운 배포 모델을 활용하려면, 애플리케이션을 개별 호스트에 결합되지 않는 방식으로 패키지할 필요가 있다. 즉, 컨테이너화 해야 한다. 컨테이너화 된 애플리케이션은 호스트에 매우 깊에 통합된 패키지로써, 특정 머신에 직접 설치되는 예전의 배포 모델보다 유연하고 가용성이 높다. 쿠버네티스는 애플리케이션 컨테이너를 클러스터에 분산시키고 스케줄링하는 일을 보다 효율적으로 자동화한다. 쿠버네티스는 오픈소스 플랫폼이고 운영 수준의 안정성을 가졌다.

쿠버네티스 클러스터는 두 가지 형태의 자원으로 구성된다.

  • 마스터는 클러스터를 상호조정한다.
  • 노드는 애플리케이션을 구동하는 작업자이다.

클러스터 다이어그램

마스터는 클러스터 관리를 담당한다. 마스터는 애플리케이션을 스케쥴링하거나, 애플리케이션의 항상성을 유지하거나, 애플리케이션을 스케일링하고, 새로운 변경사항을 순서대로 반영하는 일과 같은 클러스터 내 모든 활동을 조율한다.

노드는 쿠버네티스 클러스터 내 워커 머신으로써 동작하는 VM 또는 물리적인 컴퓨터이다. 각 노드는 노드를 관리하고 쿠버네티스 마스터와 통신하는 Kubelet 이라는 에이전트를 갖는다. 노드는 컨테이너 운영을 담당하는 Docker 또는 rkt 과 같은 툴도 갖는다. 운영 트래픽을 처리하는 쿠버네티스 클러스터는 최소 세 대의 노드를 가져야 한다.

마스터는 클러스터를 관리하고 노드는 구동되는 애플리케이션을 수용하는 데 사용된다.

애플리케이션을 쿠버네티스에 배포한다는 것은, 마스터에 애플리케이션 컨테이너를 구동하라고 지시하는 것이다. 마스터는 컨테이너를 클러스터의 어느 노드에 구동시킬지를 스케쥴한다. 노드는 마스터가 제공하는 쿠버네티스 API를 통해서 마스터와 통신한다. 최종 사용자도 쿠버네티스 API 를 직접 사용해서 클러스터와 상호작용할 수 있다.

쿠버네티스 클러스터는 물리 및 가상 머신 모두에 설치될 수 있다. 쿠버네티스 개발을 시작하려면 Minikube 를 사용할 수 있다. Minikube 는 로컬 머신에 VM 을 만들고 하나의 노드로 구성된 간단한 클러스터를 배포하는 가벼운 쿠버네티스 구현체이다. Minikube 는 리눅스, 맥, 그리고 윈도우 시스템에서 구동이 가능하다. Minikube CLI는 클러스터에 대해서 시작, 중지, 상태 조회 및 삭제 등의 기본적인 부트스트래핑 기능을 제공한다.

쿠버네티스 디플로이먼트

일단 쿠버네티스 클러스터를 구동시키면, 그 위에 컨테이너화된 애플리케이션을 배포할 수 있다. 그러기 위해서, 쿠버네티스 디플로이먼트 설정을 만들어야 한다. 디플로이먼트는 쿠버네티스가 애플리케이션의 인스턴스를 어떻게 생성하고 업데이트해야 하는지를 지시한다. 디플로이먼트가 만들어지면, 쿠버네티스 마스터가 해당 어플리케이션 인스턴스를 클러스터의 개별 노드에 스케쥴한다.

애플리케이션 인스턴스가 생성되면, 쿠버네티스 디플로이먼트 컨트롤러는 지속적으로 이들 인스턴스를 모니터링한다. 인스턴트를 구동 중인 노드가 다운되거나 삭제되면, 디플로이먼트 컨트롤러가 인스턴스를 교체시켜준다. 이렇게 머신의 장애나 정비에 대응할 수 있는 자동 복구(self-healing)매커니즘을 제공한다.

오케스트레이션 기능이 없던 환경에서는, 설치 스크립트가 애플리케이션을 시작하는데 종종 사용되곤 했지만, 머신의 장애가 발생한 경우 복구를 해주지는 않았다. 쿠버네티스 디플로이먼트는 애플리케이션 인스턴스를 생성해주고 여러 노드에 걸쳐서 지속적으로 인스턴스가 구동되도록 하는 두 가지를 모두 하기 대문에 애플리케이션 관리를 위한 접근법에서 근본적인 차이를 가져다준다.

디플로이먼트는 애플리케이션 인스턴스를 생성하고 업데이트하는 역할을 담당한다.

Kubernetes pod

POD 는 하나 또는 그 이상의 애플리케이션 컨테이너(도커 또는 rkt)들의 그룹을 나타내는 쿠버네티스의 추상적 개념으로 일부는 컨테이너에 대한 자원을 공유한다. 그 자원은 다음을 포함한다.

  • 볼륨과 같은 공유 스토리지.
  • 클러스터 IP 주소와 같은 네트워킹.
  • 컨테이너 이미지 버전 또는 사용할 특정 포트와 같이, 각 컨테이너가 동작하는 방식에 대한 정보.

POD 는 특유한 '로컬 호스트' 애플리케이션 모형을 만들어, 상대적으로 밀접하게 결합되어진 상이한 애플리케이션 컨테이너들을 수용할 수 있다. 가령, POD 는 node.js 앱과 더불어 node.js 웹 서버에 의해 발행되는 데이터를 공급하는 상이한 컨테이너를 함께 수용할 수 있다. POD 내 컨테이너는 IP 주소, 그리고 포트 스페이스를 공유하고 항상 함께 위치하고 함께 스케쥴링되고 동일 노드 상의 컨텍스트를 공유하면서 동작한다.

POD 는 쿠버네티스 플랫폼 상에서 최소 단위가 된다. 우리가 쿠버네티스에서 배포를 생성할 때, 그 배포는 컨테이너 내부에서 컨테이너와 함께 POD를 생성한다. 각 POD는 스케쥴되어진 노드에게 묶여지게 된다. 그리고 (재구동 정책에 따라) 소멸되거나 삭제되기 전까지 그 노드에 유지된다. 노드에 실패가 발생할 경우, 클러스터 내에 가용한 다른 노드들을 대상으로 스케쥴되어진다.

POD 하나 또는 그 이상의 애플리케이션 컨테이너(도커 또는 rkt 와 같은)들의 그룹이고, 공유 스토리지(볼륨), IP 주소 그리고 그것을 동작시키는 방식데 대한 정보를 포함하고 있다.

Node

POD 는 언제나 노드 상에서 동작한다. 노드는 쿠버네티스에서 워커 머신을 말하며 클러스터에 따라 가상 또는 물리 머신일 수 있다. 각 노드는 마스터에 의해 관리된다. 하나의 노드는 여러 개의 POD 를 가질 수 있고, 쿠버네티스 마스터는 클러스터 내 노드를 통해서 POD 에 대한 스케쥴링을 자동으로 처리한다.

모든 쿠버네티스 노드는 최소한 다음과 같이 동작한다.

  • kubelet 은 쿠버네티스 마스터와 노드 간 통신을 책임지는 프로세스이며, 하나의 머신 상에서 동작하는 POD 와 컨테이너를 관리한다.
  • (Docker, rkt)와 같은 컨테이너 런타임은 레지스트리에서 컨테이너 이미지를 가져와 묶여 있는 것을 풀고 애플리케이션을 동작시키는 책임을 맡는다.
만약 컨테이너들이 밀접하게 결합되어 있고, 디스크와 같은 자원을 공유해야 한다면 오직 하나의 단일 POD에 함께 스케쥴되어져야 한다.

Services

쿠버네티스 POD 들은 언젠가는 죽게된다. 실제 POD 들은 생명주기를 갖는다. 워커 노드가 죽으면, 노드 상에서 동작하는 POD 들 또한 종료된다. 레플리케이션 컨트롤러는 여러분의 애플리케이션이 지속적으로 동작할 수 있도록 새로운 POD 들의 생성을 통해 동적으로 클러스터를 미리 지정해 둔 상태로 되돌려줄 수도 있다. 또 다른 예시로서, 3 개의 복제본을 갖는 이미 처리용 백엔드를 고려해보자. 그 복제본들은 대체 가능한 상태이다. 그래서 프론트엔드 시스템은 하나의 POD 가 소멸되어 재생성 되더라도, 백엔드 복제본들에 의한 영향을 받아서는 안된다. 즉, 동일 노드 상의 POD 들이라 할지라도, 쿠버네티스 클러스터 내 각 POD 는 유일한 IP 주소를 가지며, 사용자의 애플리케이션들이 지속적으로 가능할 수 있도록 POD 들 속에서 발생하는 변화에 대해 자동으로 조정해 줄 방법이 있어야 한다.

쿠버네티스에서 서비스는 하나의 논리적인 POD 셋과 그 POD 들에 접근할 수 있는 정책을 정의하는 추상적 개념이다. 서비스는 종속적인 POD 사이를 느슨하게 결합되도록 해준다. 서비스는 모든 쿠버네티스 오브젝트들과 같이 YAML 또는 JSON 을 이용하여 정의된다. 서비스가 대상으로 하는 POD 셋은 보통 LabelSelector 에 의해 결정된다.

비록 각 POD들이 고유의 IP 를 갖고 있기는 하지만, 그 IP 들은 서비스의 도움없이 클러스터 외부로 노출되어질 수 없다. 서비스들은 사용자의 애플리케이션들에게 트래픽이 실릴 수 있도록 허용해준다. 서비스들은 ServiceSpec 에서 type 을 지정함으로써 다양한 방식들로 노출시킬 수 있다.

  • ClusterIP(기본값): 클러스터 내에서 내부 IP 에 대해 서비스를 노출해준다. 이 방식은 오직 클러스터 내에서만 서비스가 접근될 수 있도록 해준다.
  • NodePort: NAT가 이용되는 클러스터 내에서 각각 선택된 노드들의 동일한 포트에 서비스를 노출시켜준다. <NodeIP>:<NodePort> 를 이용하여 클러스터 외부로부터 서비스가 접근할 수 있도록 해준다. ClusterIP 의 상위 집합이다.
  • LoadBalancer: (지원가능한 경우)기존 클라우드에서 외부용 로드벨런서를 생성하고 서비스에 고정된 공인 IP 를 할당해준다. NodePort 의 상위 집합이다.
  • ExternalName: 이름으로 CNAME 레코드를 반환함으로써 임의의 이름(스펙에서 externalName 으로 명시)을 이용하여 서비스를 노출시켜준다. 프로시는 사용되지 않는다. 이 방식은 kube-dns 버전 1.7 이상에서 지원 가능하다.

부가적으로, spec 에 selector 를 정의하지 않고 말아넣은 서비스들의 몇 가지 유즈케이스들이 있음을 주의하자. selector 없이 생성된 서비스는 상응하는 엔드포인트 오브젝트들 또한 생성하지 않는다. 이로써 사용자들로 하여금 하나의 서비스를 특정한 엔드포인트에 매핑시킬 수 있도록 해준다. selector 를 생략하게 되는 또 다른 가능성은 사용자가 type: ExternalName 을 이용하겠다고 확고하게 의도하는 경우이다.

쿠버네티스 서비스는 논리적 POS SET 을 정의하고, 외부 트래픽 노출, 로드밸런싱 그리고 그 POD 들에 대한 서비스 디스커버리를 가능하게 해주는 추상 계층이다.

서비스는 pod set 에 걸쳐서 트래픽을 라우트한다. 사용자의 어플리케이션에 영향을 주지 않으면서 쿠버네티스에서 pod 들이 죽게도 하고, 복제가 되게도 해주는 추상적 개념이다. 종속적인 pod 들 사이에서의 디스커버리와 라우팅은(하나의 어플리케이션에서 프론트엔드와 백엔드 컴포넌트와 같은)쿠버네티스 서비스들에 의해 처리된다.

서비스는 쿠버네티스의 객체들에 대해 논리연산을 허용해주는 기본 그룹핑 단위인, 레이블과 셀렉터를 이용하여 pod set 과 매치시킨다. 레이블은 오브젝트들에 붙여진 key/value 쌍으로 다양한 방식으로 이용가능하다.

레이블은 오브젝트의 생성 시점 또는 이후 시점에 붙여질 수 있다. 언제든지 수정이 가능하다.

kubectl 명령에 --expose 옵션을 사용하면 디플로이먼트 생성과 동일 시점에 서비스를 생성할 수 있다.

Scaling

트래픽이 증가하면, 사용자의 요청에 맞추어 어플리케이션의 규모를 조정할 필요가 있다. Deployment 의 복제 수를 변경하면 scaling 이 수행된다.

kubectl run 명령에 --replicas 파라미터를 사용해서 처음부터 복수의 인스턴스로 구동되는 deployment 를 만들 수도 있다.

Deployment 를 scale-out 하면, 신규 pod 가 생성되어서 가용한 자원이 있는 노드에 스케쥴된다. 스케일링 기능은 새로 의도한 상태(desired state) 까지 pod 의 수를 늘린다. 쿠버네티스는 pod의 auto-scaling 도 지원하며 0까지 스케일링하는 것도 가능하다. 이 경우 해당 deployment의 모든 pod 가 종료된다.

어플리케이션의 인스턴스를 복수로 구동하게 되면 트래픽을 해당 인스턴스 모두에 분산시킬 방법이 필요해진다. 서비스는 노출된 deployment의 모든 pod 에 네트워크 트래픽을 분산시켜줄 통합된 로드밸런서를 갖는다. 서비스는 endpoint 를 이용해서 구동중인 pod 를 지속적으로 모니터링함으로써 사용한 pod 에만 트래픽이 전달되도록 해준다.

deployment의 복제 수를 변경하면 sacling이 수행된다.

일단 복수의 어플리케이션의 인스턴스가 구동 중이면, 다운타임 없이 롤링 업데이트를 할 수 있다.

Rolling-update

사용자들은 어플리케이션이 항상 가용한 상태일 것이라 여기고 개발자들은 하루에 여러번씩 새로운 버전을 배포하도록 요구 받고있다. 쿠버네티스에서는 이것을 롤링 업데이트를 통해 이루고 있다. 롤링 업데이트는 pod 인스턴스를 점진적으로 새로운 것으로 업데이트하여 디플로이먼트 업데이트가 서비스 중단 없이 이루어질 수 있도록 해준다. 새로운 pod 는 가용한 자원을 보유한 노드로 스케쥴될 것이다.

롤링 업데이트는 pod 인스턴스를 점진적으로 새로운 것으로 업데이트하여 디플로이먼트 업데이트가 서비스 중단 없이 이루어질 수 있도록 해준다.

어플리케이션 스케일링과 유사하게, 디플로이먼트가 외부로 노출되면, 서비스는 업데이트가 이루어지는 동안 오직 가용한 pod에게만 트래픽을 로드밸런스할 것이다. 가용한 pod란 어플리케이션의 사용자들에게 가용한 상태의 인스턴스를 말한다.

롤링 업데이트는 다음 동작들을 허용해준다.

  • 하나의 환경에서 또 다른 환경으로의 어플리케이션 프로모션(컨테이너 이미지 업데이트를 통해).
  • 이전 버전으로의 롤백
  • 서비스 중단 없는 어플리케이션의 지속적인 통합과 지속적인 전달.
디플로이먼트가 외부로 노출되면, 서비스는 업데이트가 이루어지는 동안 오직 가용한 pod 에게만 트래픽을 로드밸런스 할 것이다.

See also