MMeshOps
쿠버네티스의 현실: 무작정 도입하기 전 알아야 할 컨테이너 오케스트레이션
6예상 10중급

디플로이먼트: 서버가 죽어도 되살려내는 마법

원하는 파드의 개수를 유지하고 뻗어버린 서버를 자동으로 복구하는 디플로이먼트의 자가 치유 능력을 알아봅니다.

지난 시간에 우리는 쿠버네티스 배포의 최소 단위인 '파드(Pod)'에 대해 알아보았습니다. 하지만 파드를 직접 하나하나 손으로 만드는 것은 매우 위험합니다. 왜냐하면 파드는 언제든 죽을 수 있는 일회성 자원이기 때문입니다. 파드가 갑자기 죽어버리면 누가 다시 살려줄까요? 바로 이 문제를 해결하기 위해 등장한 구원자가 디플로이먼트(Deployment)입니다. 관리자의 개입 없이도 서비스를 안정적으로 유지해주는 디플로이먼트의 마법을 살펴봅니다.

왜 파드(Pod)를 직접 만들면 안 될까?

쿠버네티스에서 파드를 직접 생성(Bare Pod)하는 것은 마치 일용직 아르바이트생을 고용하고 아무런 관리자도 두지 않는 것과 같습니다.

아르바이트생(파드)이 갑자기 아파서 결근을 하거나, 일하던 가게(노드)에 불이 나더라도 아무도 그 빈자리를 채워주지 않습니다. 서비스는 그대로 멈춰버리고, 사용자는 에러 페이지를 보게 됩니다. 개발자가 새벽에 알람을 듣고 일어나서 수동으로 파드를 다시 띄워줄 때까지 장애는 계속됩니다.

이런 끔찍한 상황을 막으려면 파드의 상태를 24시간 감시하고, 문제가 생기면 즉각 조치해 주는 '현장 소장' 역할을 할 무언가가 필요합니다.

컨트롤러(Controller)의 등장

쿠버네티스에는 사용자가 원하는 상태(Desired State)와 현재 상태(Current State)를 지속적으로 비교하고, 이를 일치시키기 위해 노력하는 다양한 컨트롤러(Controller)들이 존재합니다.

이 컨트롤러들은 "웹 서버 파드가 항상 3개 유지되어야 해"라는 명령을 받으면, 1초도 쉬지 않고 파드의 개수를 셉니다. 만약 서버 하나가 다운되어 파드가 2개가 되면, 컨트롤러는 즉시 새로운 파드 1개를 더 만들어 다시 3개로 맞춥니다. 디플로이먼트는 이러한 컨트롤러 중에서도 무상태(Stateless) 애플리케이션을 관리하는 가장 강력하고 대중적인 도구입니다.

디플로이먼트의 계층 구조

Deployment

생성 및 관리

ReplicaSet

ReplicaSet

개수 유지 보장

Pod

Pod

실제 애플리케이션 실행

Container

디플로이먼트의 핵심 무기: 레플리카셋과 자가 치유

디플로이먼트의 작동 방식을 제대로 이해하려면, 그 내부에 숨어 있는 레플리카셋(ReplicaSet)이라는 개념을 알아야 합니다.

디플로이먼트를 생성하면 내부적으로 레플리카셋이 함께 만들어집니다. 디플로이먼트가 전체 배포의 큰 그림(어떤 버전의 이미지를 쓸지, 무중단 배포는 어떻게 할지)을 그린다면, 레플리카셋은 오직 "지정된 파드의 개수(Replica)를 무조건 유지한다"는 단일 목표에만 집착하는 행동대장입니다.

자가 치유(Self-Healing)의 기적

레플리카셋 덕분에 쿠버네티스의 가장 강력한 특징인 자가 치유(Self-Healing)가 가능해집니다.

예를 들어, 5대의 파드를 운영 중인데 특정 노드의 하드웨어가 완전히 고장 났다고 가정해 봅시다. 그 노드 위에서 돌고 있던 파드 2개가 한순간에 증발합니다. 쿠버네티스 마스터 서버는 즉각 파드 개수가 5개에서 3개로 줄어든 것을 감지합니다. 디플로이먼트(레플리카셋)는 경고를 울리며 "목표치 5개, 현재치 3개! 즉시 파드 2개 추가 생성!"이라는 결정을 내립니다. 그리고 고장 나지 않은 다른 건강한 노드들을 찾아 새로운 파드 2개를 눈 깜짝할 새에 띄웁니다.

이 모든 과정에 사람의 개입은 1%도 필요하지 않습니다. 새벽 3시라도 끄떡없죠. 이것이 우리가 쿠버네티스를 도입하는 핵심 이유 중 하나입니다.

디플로이먼트 매니페스트 예시 (YAML)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-web-deployment
spec:
  replicas: 3 # 여기서 원하는 파드의 개수를 지정합니다
  selector:
    matchLabels:
      app: web
  template: # 파드를 어떻게 만들지 정의하는 붕어빵 틀
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.14
        ports:
        - containerPort: 80

새로운 버전으로 안전하게 갈아타기: 무중단 배포의 기초

디플로이먼트는 단순히 파드 개수만 유지해 주는 것이 아닙니다. 개발자가 애플리케이션 소스 코드를 수정하고 새로운 도커 이미지를 빌드했을 때, 이를 사용자 접속 끊김 없이 안전하게 교체해 주는 역할도 담당합니다.

디플로이먼트 정의서(YAML)에서 컨테이너의 `image` 버전을 변경하고 적용하면, 디플로이먼트는 즉시 새로운 버전의 레플리카셋을 하나 더 만듭니다. 그리고 구버전 파드를 하나씩 죽이면서 동시에 신버전 파드를 하나씩 살려내는 마법을 부립니다. 이렇게 톱니바퀴 맞물리듯 순차적으로 버전을 교체하는 방식을 롤링 업데이트(Rolling Update)라고 부르며, 이 덕분에 서비스 다운타임 없이 배포가 가능해집니다. (이 롤링 업데이트에 대해서는 Part 3에서 더 깊이 다룰 예정입니다.)

디플로이먼트 운영 철칙

  1. 1절대로 개별 파드(Pod)를 직접 생성(Bare Pod)하지 마라. 항상 디플로이먼트를 통해 파드를 배포하라.
  2. 2배포된 애플리케이션의 버전 기록을 남기기 위해 의미 있는 태그(Tag)를 도커 이미지에 사용하라 (예: latest 사용 지양).
  3. 3스케일 아웃(Scale-Out)이 가능하도록 애플리케이션은 무상태(Stateless)로 설계되어야 한다.

개념 퀴즈

퀴즈 답을 맞춰야 학습 완료가 됩니다.

다음 중 디플로이먼트(Deployment)의 역할이나 특징으로 올바르지 않은 것은 무엇인가요?

3줄 요약

  1. 1파드는 언제든 죽을 수 있기 때문에 직접 생성하지 말고, 이를 안전하게 관리해 주는 디플로이먼트(Deployment)를 사용해야 합니다.
  2. 2디플로이먼트는 레플리카셋(ReplicaSet)을 통해 파드 개수를 항상 원하는 상태로 유지하는 자가 치유(Self-Healing) 능력을 제공합니다.
  3. 3새로운 컨테이너 이미지 버전이 나왔을 때 무중단으로 안전하게 교체할 수 있는 롤링 업데이트를 지원합니다.