소수의 컨테이너 관리는 어렵지 않아서 수동으로 가능하지만, 개수가 많아지고 다수의 멀티 호스트로 구성된 대용량 분산 환경에서는 수동 작업이 불가능해진다.
이런 환경에서 다수의 컨테이너를 쉽고 자동적으로 제어/관리하기 위해 생겨난 기법이 Container Orchestration이다.
Container Orchestration는 다음과 같은 다양한 역할을 한다.
Kubernetes는 컨테이너 오케스트레이션 도구로, 사실상 컨테이너 오케스트레이션의 표준처럼 자리잡고 있다.
Google에서 개발되었지만, 현재는 영리적으로 사용하지 않겠다는 의지를 밝힌 후 CNCF에 이관되었다.
Kubernetes, Docker Swarm, Apache Mesos/Marathon 등과 같은 도구들이 존재한다.
CNCF
- Cloud Native Computing Foundation
- 오픈소스 소프트웨어 재단
- 구글, 아마존, MS, Rad Hat, Docker 등이 참여
Docker Swarm은 Docker Inc에서 개발되었고 설치와 사용이 Kubernetes에 비해 단순하다는 장점이 있지만,
대용량 분산환경에서 사용하기에는 기능이 부족하다.(모니터링이나 스토리지 옵션 등)
Apache Mesos는 분산된 CPU, memory, storage 등을 추상화하여 하나의 단일 리소스처럼 만들어준다.
Marathon은 컨테이너 관리 도구로, Mesos와 Marathon의 통합으로 대규모 환경의 컨테이너들을 관리할 수 있다.
Kubernetes는 대규모 분산환경에서 상대적으로 소수의 엔지니어만으로 컨테이너를 관리하는 것이 목적으로,
다음과 같은 다양한 특징을 가진다.
Kubernetes의 철학 3가지를 알아보자.
기존에는 서로 다른 시기에 구매한 장비들을 유지 보수하며 상태 관리를 했다.
그러나 클라우드 환경에서는 자원들을 간단하게 구축하거나 파기하는 것이 가능하다.
한번 구축한 인프라는 수정하지 않고 바로 파기하며, 원하는 상태를 만들어서 새로운 환경을 구축할 수 있음을 의미한다.
예를 들어, 자바의 버전을 올려야 한다고 가정해보자.
기존에는 서버에 접속하여 명령어를 이용해 버전 업데이트를 했다면, Immutable Infra 방식은 업데이트 된 이미지를 만든 후에 새로운 서버를 구축하여 컨테이너 배포를 하면 된다. (기존 서버는 파기)
Kubernetes는 선언적으로 상태를 명시할 수 있다.
원하는 상태를 만들기 위해 명령어를 하나씩 치지 않고 단지 원하는 상태를 기술하여 Kubernetes에 적용할 수 있다.
원하는 상태 = 시스템이 되어있어야 할 모습
장애가 발생했을 시 사람의 개입을 최소화하여 자동으로 복구할 수 있어야 한다.
시스템이 되어있어야 하는 상태를 항상 감시하며, 원하는 상태와 다를 경우에 자동으로 복구한다.
Kubernetes는 Master에 API 서버와 상태 저장소를 두고 각 서버의 에이전트와 통신하는 구조이다.
컨테이너가 위치하는 곳이 노드이고, 컨테이너는 pod라는 단위로 노드에 배포된다.
마스터는 kubectl을 통해 클라이언트와 통신을 한다.
마스터는 클러스터 관리하는 역할을 한다.
노드의 상황을 파악하고, 컨테이너를 어떤 노드에서 가동할지 선택한다.
etcd라는 분산 저장소를 사용해 클러스터의 정보를 저장한다.
컴포넌트들이 각각 통신을 하는 것이 아니라, 사진과 같이 API Server를 통해 통신한다.
클라이언트도, 노드들과의 통신도, 마스터 안의 컴포넌트들도 모두 API Server을 통해 통신한다.
API 서버는 모든 요청을 처리하는 마스터의 핵심이다.
모든 컴포넌트들은 API 서버를 통해서 커뮤니케이션 한다.
아무나 들어오면 안되기 때문에 인증 및 민가 기능 또한 보유하고 있다.
스케줄러는 컨테이너를 어떤 노드에서 가동할지 결정하는 컴포넌트이다.
따라서 CPU/메모리 가용 수준 파악이 필요하다.
컨트롤러 매니저는 K8s 클러스터의 상태를 감시한다.
되어 있어야 한 시스템을 상태를 감시하고, 다를 경우 같아지도록 조치한다.
여러개의 컨트롤러 매니저가 존재할 수 있다.
etcd는 분산 key-value 저장소로, 클러스터의 모든 설정과 데이터를 저장한다.
클러스터의 모든 데이터를 가지고 있기 때문에 가용성이 매우 중요하고, 마스터에서 분리하여 독자적으로 구축 가능하다.
노드는 컨테이너가 가동되는 서버로, 다수의 노드로 클러스터를 구성한다.
클라우드의 경우 가상머신이 노드가 된다(AWS EC2등)
하나의 노드는 위 사진처럼 구성된다.
pod가 현재 상태에서는 컨테이너라고 볼 수 있다.
kubelet은 실제로 컨테이너를 생성하는 주체로, 마스터로부터 생성 요청을 받으면 컨테이너를 생성한다.
컨테이너의 상태를 감시하는 역할도 수행하며, 이 상태를 API 서버로 전송한다.
kube proxy는 각 노드에서 실행되는 네트워크 프록시이다.
노드의 네트워크 규칙을 유지 및 관리하고, 내부 네트워크 세션이나 클러스터 바깥에서 컨테이너로 네트워크 통신을 할 수 있도록 해준다.
Kubernetes Objects는 대규모 분산환경에 필요한 공통 요소들을 추상화한 것이다.
컨테이너 자체, 어플리케이션 배포나 추상 방식, 네트워크 등을 쿠버네티스에서 사용할 수 있도록 추상화한다.
이렇게 추상화 한 것들을 Object라고 통칭하며, 다양한 오브젝트들이 존재한다.
pod는 Kubernetes에서 배포할 수 있는 가장 작은 단위로, 한 개 이상의 컨테이너와 스토리지, 네트워크 속성을 가진다.
pod에 속한 컨테이너는 스토리지와 네트워크를 공유하고 서로 localhost로 접근할 수 있으며,
컨테이너를 하나만 사용하는 경우에도 반드시 pod로 관리해야 한다.
ReplicaSet는 동일한 파드를 복제해서 관리하기 위해 사용하는 것이다.
Pod을 생성하고 개수를 유지하려면 ReplicaSet을 사용해야 한다.
Deployment는 Kubernetes에서 실제 배포를 진행하는 기본 단위로 중요한 개념이다!
pod나 ReplicaSet 단위로 배포할 수도 있지만,
Deployment는 실제 배포를 진행하기 위한 여러가지 기능들을 제공하기 때문에 기본 단위로 사용된다.
배포와 관련된 다양한 기능 및 옵션을 제공한다.
DaemonSet은 클러스터 전체에 Pod를 띄울 때 사용하는 Controller으로, 어플리케이션 수행 방식에 관한 것이다.
DaemonSet은 항상 모든 노드에 특정 파드(컨테이너)가 실행되는 것을 보장하며,
새로운 Node가 추가되면 자동으로 pod가 실행되도록 관리한다.
Kubernetes의 대부분의 Object는 Stateless 이다.
StatefulSet은 상태를 유지하는 pod를 위한 오브젝트로, Volume을 사용해서 데이터를 저장하고 Pod 재기동 시에도 유지가 가능하다.
Service는 네트워크와 관련된 오브젝트로 pod간 연결 및 pod와 외부 네트워크를 연결하는 역할을 한다.
ReplicaSet을 사용해 여러개의 파드가 복제돼있을때, 그 내부를 로드밸런싱하는 역할도 제공한다.
위 사진처럼 여러 개의 노드들과 마스터가 존재하고, 노드 안에는 여러 pod(웹 서비스)들이 배포되어있다.
우리같은 엔지니어는 kubectl을 통해 마스터와 통신하고,
사용자들은 service나 ingress와 같은 네트워크를 통해 개발하고 배포한 어플리케이션에 접근한다.
Manifest 파일은 Kubernetes에서 선언적인 상태 변경을 하기 위한 파일이다.
YAML(또는 JSON) 파일로 작성도며 리소스의 종류와 원하는 상태를 입력한다.