쿠버네티스 컨테이너 오케스트레이션 개요


이번 글은 글또 8기에서 진행하는 DevOps 스터디에서 발표한 내용을 정리한 글입니다.
글에서는 컨테이너 오케스트레이션과 쿠버네티스에 대한 개요를 간단히 소개하였으며, Kompose를 사용하여 Docker Compose 파일을 쿠버네티스 매니페스트로 변환하는 방법과 Minikube를 활용하여 로컬 환경에서 쿠버네티스 클러스터를 실행하고 매니페스트를 배포하는 방법을 정리하였습니다. 이후의 포스팅에서는 실제로 로컬 환경에서 쿠버네티스 클러스터를 구성하고, 가능하다면 대시보드를 추가하는 방법에 대해서도 다룰 예정입니다. 앞으로의 글에서는 더욱 실질적인 쿠버네티스 활용과 관련된 내용을 다루도록 하겠습니다.


컨테이너 오케스트레이션에 대한 개요

  1. 컨테이너 오케스트레이션(Container Orchestration)은 도커 컨테이너를 다수의 머신에서 실행하게 해줍니다. 이것은 내결함성(Fault Tolerance; FT)과 고가용성(High Availability; HA)을 달성하기 위한 필수 요소입니다.

    • 내결함성(FT): 여러 컨테이너가 죽어도 다른 컨테이너에는 영향을 안미치는 것.

    • 고가용성(HA): 장애가 발생해도 끊임없이 서비스를 이용할 수 있도록 제공하는 것.

    • 오케스트레이션이란?

      펼쳐보기

      ▫︎ 개념

      오케스트레이션은 다양한 컴퓨터 시스템, 애플리케이션, 서비스들의 조정과 관리를 의미합니다. 다수의 작업을 연결해 큰 워크플로우나 프로세스를 실행하는 방식으로 사용합니다.
      이 프로세스는 여러개의 자동화된 작업으로 구성되고 관련 시스템도 여러개일 수 있습니다.

      ▫︎ 목표

      빈번하게 발생하며 반복 가능한 프로세스를 간소화하고 최적화하는 것 입니다. 이를 통해 사용자가 복잡한 작업과 워크플로우를 쉽게 관리할 수 있게 됩니다.

      ▫︎ 이점

      시간 절약, 효율성 향상, 중복성 제거와 같은 이점을 제공합니다. 만약 프로세스가 반복 가능하고 작업이 자동화가 가능하다고 하면, 오케스트레이션은 이 과정을 훨씬 간편하게 만들어줍니다.

      ▫︎ 오케스트레이션 적용 예시

      오케스트레이션은 다양한 분야에서 활용됩니다.
      데이터 및 머신러닝(ML) 분야: 작업 오케스트레이션을 통해 복잡한 데이터 파이프라인과 모델 학습 및 배포 과정을 간소화하고, 일관성을 유지하는데 사용됩니다.

  1. 클라우드 컴퓨팅은 Scale Up 대신 Scale Out을 권장합니다. 이는 컴퓨터 리소스를 더 많은 인스턴스 또는 노드에 확산시키는 것을 의미합니다. 도커 오케스트레이션 플랫폼은 이러한 리소스를 컨테이너에 세분화하여 할당할 수 있게 해주며, 이로 인해 리소스를 더 효과적으로 활용하고 비용을 절감할 수 있습니다.

  2. 컨테이너와 서버리스 컴퓨팅 인스턴스는 일시적이고 일회용으로 여겨집니다. 따라서 컨테이너의 수명이 짧기 때문에 대규모로 조정하고 운영하는 것은 어렵습니다. 이런 이유로 컨테이너 오케스트레이션 플랫폼이 필요하며 현재 가장 많이 사용되고 있는 컨테이너 오케이스트레이션 플랫폼은 쿠버네티스(Kubernetes)입니다.

    • 다른 컨테이너 오케스트레이션
      • Docker Swarm
      • Apache Mesos/Marathon
      • Amazon ECS(Elastic Container Service)
  3. 쿠버네티스는 컨테이너화된 애플리케이션의 배포, 확장, 관리를 도와주며, 도커와 같은 컨테이너 플랫폼과 함께 사용할 수 있습니다. 또한 패키지 매니저인 헬름(Helm)을 사용해 패키지를 통해 모니터링과 대시보드 툴을 설치하고 커스터마이징할 수 있습니다.

쿠버네티스 개념의 간략한 개요

  1. 노드: 쿠버네티스 클러스터를 구성하는 가상머신 또는 물리적인 서버입니다.

  2. 파드(Pod): 쿠버네티스에서 가장 작은 배포 단위로, 하나 이상의 컨테이너로 구성됩니다. 파드 내의 모든 컨테이너는 동일한 네트워크와 자원을 공유합니다.

  3. Sidecat Container: 애플리케이션의 주 컨테이너와 함께 실행되는 컨테이너로 로깅, 모니터링과 같은 보조 기능을 수행합니다.

  4. Init Container: 특정 작업(ex, DB 마이그레이션 )이 완료될 때 까지 파드의 시작을 지연시키는 컨테이너입니다.
    ⭐️ 기존은 컨테이너마다 바로 옆에 사이드카 컨테이너든 초기화 컨테이너든 존재했는데 최근에는 비용 절감을 위해 노드당 하나씩 생성된다고 합니다. 이를 DemonSet이라고 합니다.

    DaemonSet
    • DaemonSet이란?

      • DaemonSet은 쿠버네티스(Kubernetes)의 API 오브젝트 중 하나로, 클러스터의 모든 (또는 일부) 노드에서 한 개의 파드를 실행하게끔 보장합니다. 즉, 클러스터에 노드가 추가될 때마다 쿠버네티스가 자동으로 파드를 해당 노드에 추가하며, 노드가 제거될 때 이러한 파드도 제거합니다.
    • DaemonSet의 사용 예시

      • 특정 노드에서 로그나 모니터링을 처리하는 애플리케이션을 실행하려는 경우, 이를 DaemonSet으로 배포할 수 있습니다. 이렇게 하면 쿠버네티스 클러스터에 새로운 노드가 추가되면 자동적으로 DaemonSet의 파드가 해당 노드에 배포되어 작업을 시작합니다. 마찬가지로 노드가 클러스터에서 제거되면, 그 노드에서 실행중이던 DaemonSet 파드도 함께 제거됩니다. 이는 로그 수집, 시스템 모니터링, 네트워크 설정과 같은 작업을 효과적으로 처리하는데 사용할 수 있습니다.
    • DaemonSet의 동작 방식

      • DaemonSet이 배포되면, 쿠버네티스 스케줄러는 각 노드에서 하나의 파드 복사본이 실행되도록 스케줄링합니다. 노드가 클러스터에 추가되면, DaemonSet에 의해 파드가 추가됩니다. 반대로, 노드가 클러스터에서 제거되면, 해당 노드의 파드도 쿠버네티스에 의해 제거됩니다.
    • DaemonSet의 장점

      • 일관성: 클러스터의 모든 노드에서 특정 작업을 실행하도록 보장합니다. 이는 시스템의 일관성과 예측 가능성을 향상시킵니다.

      • 자동화: 노드 추가/제거에 따라 파드를 자동으로 추가/제거합니다. 이는 수동 인터벤션이 필요 없음을 의미하며, 이러한 프로세스를 쉽게 관리할 수 있게 해줍니다.

      • 시스템 수준의 작업 용이성: 시스템 수준의 작업 (예: 로깅, 모니터링)을 클러스터 전반에 쉽게 배포할 수 있습니다.

      • 기억할 점은, DaemonSet이 적합하지 않은 작업들도 있다는 것입니다. 예를 들어, 각 노드에서 한 번 이상 실행되어야 하는 작업, 또는 노드 간에 데이터를 공유해야 하는 작업 등이 이에 해당합니다. 이런 경우에는 다른 쿠버네티스 API 오브젝트를 고려해 보아야 합니다.

  5. 디플로이먼트(Deployment): 파드의 개수를 관리하고 업데이트를 자동화 하는 쿠버네티스 객체.

    자세한 내용
    • 쿠버네티스 Deployment란?

      • 애플리케이션의 상태를 안정적이고 예측 가능하게 관리하면서 업데이트와 스케일링을 할 수 있게 해주는 API 오브젝트입니다. Deployment는 ReplicaSet을 생성하여 복제된 애플리케이션 인스턴스를 관리하고, 애플리케이션의 상태를 정의한 상태를 유지합니다.
    • Deployment의 사용 사례

      • Deployment는 쿠버네티스 애플리케이션의 실행에 이상적입니다. 이는 애플리케이션에 대한 선언적 업데이트롤백, 그리고 수평 스케일링을 쉽게 관리할 수 있게 해줍니다.
    • Deployment의 동작 방식

      • Deployment는 쿠버네티스에서 애플리케이션의 원하는 상태를 선언적으로 기술할 수 있게 합니다. 즉, 애플리케이션의 새 버전을 배포할 때마다 쿠버네티스는 Deployment에 정의된 상태를 참조하여 이를 달성하기 위해 필요한 작업을 수행합니다.
      • Deployment를 업데이트하면, 쿠버네티스는 신규 ReplicaSet을 생성하고, 이를 통해 원하는 상태를 달성하는 데 필요한 파드를 생성합니다. 동시에, 이전 ReplicaSet의 파드는 새로 생성된 파드가 준비될 때까지 유지됩니다.
      • 이러한 방식을 통해, Deployment는 애플리케이션의 예상치 못한 중단 없이도 안정적인 업데이트를 보장합니다. 이는 특히 프로덕션 환경에서 중요합니다.
    • Deployment의 장점

      • 선언적(declarative) 업데이트: 애플리케이션의 원하는 상태를 선언적으로 기술할 수 있습니다. 쿠버네티스는 이 상태를 달성하는 데 필요한 모든 작업을 자동으로 수행합니다.
      • 롤백(rollback) 기능: Deployment는 이전 상태로 롤백하는 기능을 제공합니다. 이는 애플리케이션의 예상치 못한 문제를 빠르게 해결하는 데 도움이 됩니다.
      • 스케일링(scaling): Deployment는 수평으로 쉽게 스케일링될 수 있습니다. 이는 레플리카의 수를 증가 또는 감소시킴으로써 이루어집니다.

3. Kompose를 사용해 docker-compose.yaml에서 쿠버네티스 매니페스트 만들기

Kompose는 Docker Compose 파일(docker-compose.yml)을 쿠버네티스 배포 매니페스트로 변환하는데 사용되는 도구입니다.

3-1. Kompose 설치

Linux

1
2
3
4
# Linux
curl -L https://github.com/kubernetes/kompose/releases/download/v1.22.0/kompose-linux-amd64 -o kompose
chmod +x kompose
sudo mv ./kompose /usr/local/bin/kompose

MacOS

1
brew install kompose

3-2. Docker Compose (yaml 파일)

docker-compose.yaml파일을 쿠버네티스 manifest 파일로 변환하기 위해서 Kompose 툴을 사용하는 것 입니다.

매니페스트(Manifest)란?

  • 매니페스트는 JSON 또는 YAML 형식으로 작성된 파일로, 어떤 소프트웨어나 애플리케이션, 혹은 시스템의 설정, 속성, 의존성 등을 명시적으로 정의하는 것을 말합니다.
  • 어떤 종류의 리소스를 생성할지(예를 들어, 파드, 서비스, 디플로이먼트 등), 그 리소스의 이름이 무엇인지, 그리고 해당 리소스에 대한 세부 설정을 기술합니다.

쿠버네티스에서의 매니페스트

쿠버네티스에서 Manifest는 주로 YAML파일로 작성됩니다. 이는 쿠버네티스의 파드, 서비스, 볼륨, 네임스페이스와 같은 오브젝드를 생성, 업데이트 및 삭제를 선언적으로 정의합니다. 이 파일은 kubectl apply -f 명령어를 통해 쿠버네티스에 적용되며, 그 결과 쿠버네티스의 클러스터는 Manifest에 정의된 상태를 달성하려고 반복적으로 시도하게 됩니다.

특징

  • Infra Structor를 코드로 관리가 가능해집니다.
  • 버전 관리 시스템으로 추적이 가능해집니다. (*ex, git으로 관리 가능 )
  • 리소스를 일관되게 배포하고 유지하는데 사용됩니다.
  • Manifest를 사용하면 수동으로 각 리소스를 생성하거나 변경하는 대신, 원하는 클러스터의 상태를 파일에 기술하고 이 파일을 쿠버네티스 API 서버에 적용함으로써 원하는 상태를 선언적으로 관리가 가능해집니다.

3-2. Docker Compose 파일에서 서비스를 정의

1
2
3
4
5
6
7
# docker-compose.yml
version: '3'
services:
web:
image: 'nginx:latest'
ports:
- '80:80'

3-3. Docker Compose 파일을 쿠버네티스 메니페스트로 변환 (Kompose 사용)

1
kompose convert -f docker-compose.yml

3-4. Deployment 및 Service 매니페스트 파일을 생성

3-3에서 kompose로 Manifest로 변환하면 Docker Compose 파일에 정의된 각 서비스에 대한 Deployment 및 Service Manifest 파일이 생성됩니다.

web-deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert -f docker-compose.yml
kompose.version: 1.22.0 (955b78124)
creationTimestamp: null
labels:
io.kompose.service: web
name: web
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: web
template:
metadata:
annotations:
kompose.cmd: kompose convert -f docker-compose.yml
kompose.version: 1.22.0 (955b78124)
creationTimestamp: null
labels:
io.kompose.service: web
spec:
containers:
- image: nginx:latest
name: web
ports:
- containerPort: 80
resources: {}
restartPolicy: Always
status: {}
web-service.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# web-service.yaml
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert -f docker-compose.yml
kompose.version: 1.22.0 (955b78124)
creationTimestamp: null
labels:
io.kompose.service: web
name: web
spec:
ports:
- name: "80"
port: 80 # 외부에서 들어올때 포트
targetPort: 80 # containerPort와 같아야 함 (연결)
selector:
io.kompose.service: web
status:
loadBalancer: {}

3-5. 쿠버네티스 클러스터에 배포

1
2
kubectl apply -f web-deployment.yaml
kubectl apply -f web-service.yaml

Docker Compose로 정의된 애플리케이션을 쿠버네티스에 배포할 수 있습니다. 이 절차는 Docker Compose파일이 복잡하거나 여러 서비스를 포함하는 경우에도 동일하게 적용됩니다.

4. 미니큐브를 기반으로 로컬 쿠버네티스 클러스터에 쿠버네티스 매니페스트 배포하기

미니큐브(minikube)를 기반으로 쿠버네티스 클러스터에 쿠버네티스 매니페스트를 배포하는 것.

💡 미니큐브(Minikube)는 로컬 환경에서 쿠버네티스를 실행하고 테스트하는 데 사용하는 도구입니다. 개발자가 로컬 환경에서 단일 노드 쿠버네티스 클러스터를 실행하고 관리할 수 있게 해줍니다. 쿠버네티스 매니페스트는 쿠버네티스 API 서버에 전달되는 YAML 또는 JSON 형식의 설정 파일입니다.

4-1. Mikikube 설치

MacOS

1
brew install minikube

Linux

1
2
3
4
# Linux
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 \
&& chmod +x minikube
sudo mv minikube /usr/local/bin/

💡 쿠버네티스 클러스터에 주로 사용하는 명령어: kubectl

4-2. 클러스터 실행

1
minikube start

위 과정으로 로컬 쿠버네티스 클러스터가 실행되었습니다.

4-3. Manifest 작성

쿠버네티스 매니페스트를 작성해야 합니다. 예를 들어, 아래와 같이 간단한 Pod 매니페스트(pod.yaml)를 작성 가능 합니다

1
2
3
4
5
6
7
8
9
10
11
12
# pod.yaml
apiversion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']

4-4. Manifest 배포

pod.yaml 매니페스트를 쿠버네티스 클러스터에 배포.

1
kubectl apply -f pod.yaml

4-5. Pod 상태 확인

Pod이 올바르게 배포되었는지 확인.

1
kubectl get pods

Pod란

💡 Pod는 쿠버네티스에서 가장 기본적인 배포 단위입니다. Pod는 하나 이상의 컨테이너 그룹으로 구성되며, 이들 컨테이너는 동일한 네트워크 및 볼륨 공유를 통해 함께 스케줄링되고 실행됩니다.

  1. 여러 컨테이너의 그룹: 하나의 Pod는 여러 컨테이너를 함께 실행할 수 있습니다. 이들 컨테이너는 동일한 생명주기를 공유하며, 또한 서로의 프로세스를 쉽게 통신할 수 있습니다. 하지만 대부분의 경우, 하나의 Pod는 하나의 컨테이너만 실행합니다.
  2. 네트워킹과 통신: Pod 내의 모든 컨테이너는 동일한 네트워크 네임스페이스를 공유합니다. 이는 같은 로컬호스트 내에서 서로 통신할 수 있음을 의미하며, 이들 간에는 IPC 통신도 가능합니다.
  3. 공유 스토리지: Pod는 볼륨(Volumes)을 통해 스토리지를 정의하고 공유할 수 있습니다. 이를 통해 Pod 내의 컨테이너들은 데이터를 공유하고 영속화할 수 있습니다.
    1. PV
  4. Pod 생명주기: Pod는 보통 일회성으로 설계되어 있습니다. Pod가 생성되면 클러스터의 특정 노드에 스케줄링되고, 실행이 종료되거나 삭제될 때까지 그 노드에서 실행됩니다. Pod가 삭제되면 동일한 이름의 새로운 Pod는 생성되지 않습니다. 또한, Pod 내의 컨테이너가 실패하면 그 컨테이너는 자동으로 재시작됩니다. Pod 자체가 실패하면, 그 Pod가 실행되고 있던 노드에 따라 다르게 처리됩니다.
  5. 스케줄링: 쿠버네티스 스케줄러는 Pod를 실행할 노드를 자동으로 선택합니다. 또한 사용자는 NodeSelector, Affinity 및 Anti-Affinity 규칙 등을 사용하여 특정 노드에 Pod를 스케줄링하는 것을 선호하거나 회피하도록 스케줄러에 힌트를 제공할 수 있습니다.

4-6. 정리

미니큐브를 사용하면 로컬 환경에서 쿠버네티스 클러스터를 쉽게 실행하고 관리할 수 있습니다. 이를 위해 먼저 미니큐브를 설치하고 시작합니다. 이후에는 쿠버네티스 매니페스트(일반적으로 YAML 또는 JSON 형식의 설정 파일)를 작성하여 클러스터에 배포하면 됩니다. 이 방법을 사용하면 쿠버네티스 리소스(Pods, Deployments, Services 등)를 쉽게 배포하고 관리할 수 있습니다. ‘kubectl apply -f’ 명령을 사용하면 매니페스트를 클러스터에 배포할 수 있고, ‘kubectl get’ 명령을 사용하면 리소스의 상태를 확인할 수 있습니다