마루옵스서버 · 네트워크 · AI 기술 노트

소개문의

[쿠버네티스 학습 05] Deployment 배포와 롤링 업데이트

Virginia Tech 데이터센터의 장비 통로

참고 사진 · Virginia Tech 데이터센터의 장비 통로 · 사진: Christopher Bowns / 원본 / CC BY-SA 2.0 · 목록용 크기 조정

전체 연재 안내 · 실습 파일 ZIP

Windows 11 · VMware · Rocky Linux Kubernetes 연재 05/10

웹 서버 두 개를 배포한 뒤 Pod 하나를 지워 보겠습니다. 새 Pod가 만들어지는 과정을 보면 선언한 복제본 수를 유지하는 동작이 드러나요. 명령은 cp01에서 실행하고 일반 Pod는 워커에 배치합니다.

1. 네임스페이스와 Deployment

mkdir -p ~/k8s-lab/app
cd ~/k8s-lab/app
kubectl create namespace lab

파일 이름은 web-deployment.yaml입니다. 비특권 사용자로 8080 포트를 여는 nginx-unprivileged를 사용합니다. 예제는 확인 당시 stable-alpine의 digest를 함께 지정했어요. 같은 태그의 내용은 바뀔 수 있고 digest 고정은 보안 업데이트를 자동 적용하지 않으므로 새 이미지의 교체 시점도 따로 관리합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: lab
spec:
  replicas: 2
  revisionHistoryLimit: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 101
        runAsGroup: 101
        seccompProfile:
          type: RuntimeDefault
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: web
      containers:
        - name: nginx
          image: nginxinc/nginx-unprivileged:stable-alpine@sha256:782bb89768cc87b7f95c18b95baa1af250e5d451f26794f59363540161147c01
          ports:
            - name: http
              containerPort: 8080
          resources:
            requests:
              cpu: 100m
              memory: 64Mi
            limits:
              cpu: 500m
              memory: 256Mi
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop: [ALL]
          readinessProbe:
            httpGet:
              path: /
              port: http
            initialDelaySeconds: 3
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /
              port: http
            initialDelaySeconds: 15
            periodSeconds: 10
kubectl apply --dry-run=server -f web-deployment.yaml
kubectl apply -f web-deployment.yaml
kubectl -n lab rollout status deployment/web --timeout=180s
kubectl -n lab get deployment,replicaset,pods -o wide

2. requests·limits와 스케줄링

CPU 100m은 한 코어의 0.1입니다. 스케줄러는 requests와 노드의 할당 가능 자원 등을 비교합니다. 실제 사용량을 requests에 고정하는 설정은 아닙니다. CPU limit 초과는 제한될 수 있고 메모리 limit 초과는 OOM 종료로 이어질 수 있습니다. 현재 CPU가 한가해도 requests 합계 때문에 Pending이 될 수 있어요.

스케줄러의 Filter는 자원과 taint, 선택 조건 등으로 후보를 거릅니다. 남은 노드는 플러그인의 Score를 반영해 배치 위치를 고릅니다. 예제의 topology spread는 앱의 분산을 유도합니다. ScheduleAnyway는 분산이 어려워도 배치를 허용하므로 워커가 하나라면 같은 노드에 두 복제본이 실행될 수 있습니다.

3. readiness·liveness

readiness는 요청을 받아도 되는지, liveness는 다시 시작해야 할 만큼 멈췄는지를 봅니다. readiness 실패 Pod는 일반적인 Service 전달 대상에서 제외됩니다. 실제 앱에서는 의존 서비스의 준비와 프로세스 생존을 나눠 설계하세요. DB가 잠깐 느린데 웹 서버를 모두 재시작하면 부하가 더 커질 수 있습니다. 기동이 긴 앱에는 startupProbe도 검토합니다.

kubectl -n lab describe deployment web
kubectl -n lab get pods -l app=web

4. Pod 삭제와 재생성

POD=$(kubectl -n lab get pods -l app=web -o jsonpath='{.items[0].metadata.name}')
kubectl -n lab delete pod "$POD"
kubectl -n lab get pods -l app=web -w

새 이름의 Pod가 Ready가 되는지 본 뒤 Ctrl+C로 감시를 끝냅니다. Pod 재생성을 직접 담당하는 것은 ReplicaSet 컨트롤러이고, Deployment는 ReplicaSet 교체와 복제본 수를 관리합니다. 이름과 IP가 바뀔 수 있으므로 앱의 연결 대상에 Pod IP를 고정하지 않습니다.

5. 롤링 업데이트·롤백

# 기능은 바꾸지 않고 Pod 템플릿 annotation을 바꿔 롤아웃을 관찰
kubectl -n lab patch deployment web --type=merge -p \
  '{"spec":{"template":{"metadata":{"annotations":{"lab.maruops.com/release":"exercise-2"}}}}}'
kubectl -n lab rollout status deployment/web --timeout=180s
kubectl -n lab rollout history deployment/web
kubectl -n lab rollout undo deployment/web
kubectl -n lab rollout status deployment/web --timeout=180s

maxUnavailable: 0은 사용 가능한 복제본을 의도적으로 줄이지 않는 설정입니다. maxSurge: 1을 위해 잠시 세 번째 Pod가 실행될 공간도 필요합니다. 자원이 모자라거나 새 Pod가 readiness를 통과하지 못하면 롤아웃이 기다립니다. 이번 예제는 다운로드 영향을 빼고 템플릿 변경만 관찰하지만 이미지 변경도 같은 경로를 따릅니다.

롤백은 Deployment의 Pod 템플릿을 되돌립니다. DB 스키마나 외부 데이터까지 복구하지는 않습니다. Git의 최종 상태와 실제 리소스도 비교합니다. 끝나면 kubectl apply -f web-deployment.yaml로 예제 기준에 다시 맞춥니다.

참고 자료

공식 문서와 배포 파일 확인 기준: 2026년 10월 18일. 출력은 완료 여부를 판단하기 위한 예시이며 환경별로 달라질 수 있습니다.


← 04편 · 06편 →

전체 10편 목차 펼치기

전체 연재 안내와 실습 기준

댓글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

닉네임·이메일·댓글 내용·IP 주소·브라우저 정보는 댓글 게시 및 관리에 사용됩니다. 이메일과 접속 정보는 공개 댓글에 표시하지 않습니다. 개인정보 요청은 운영자 이메일로 보내 주세요. 개인정보처리방침