모든 것이 완벽해 보였던 배포 직후, 갑자기 슬랙(Slack) 알람이 쏟아지기 시작해요. 서비스는 응답이 없고, 파드(Pod)들은 끊임없이 CrashLoopBackOff 상태로 변하며 재시작을 반복하죠. 주니어 개발자라면 누구나 한 번쯤 겪어봤을, 혹은 가장 두려워하는 순간이에요.
분명 로컬 환경에서는 잘 돌아갔고, 테스트 클러스터에서도 문제가 없었어요. 하지만 운영 환경에 배포하는 순간, 예상치 못한 리소스 부족이나 네트워크 설정 오류가 터져 나오며 서비스 전체를 마비시키곤 해요. 이런 사고는 단순히 기술적인 실수를 넘어, 팀 전체의 신뢰도와 서비스 가용성에 치명적인 영향을 미쳐요.
우리가 배포 전에 디플로이먼트 체크리스트를 꼼꼼하게 작성하고 확인해야 하는 이유가 바로 여기에 있어요. 단순히 설정을 입력하는 것을 넘어, 시스템이 어떤 상황에서도 견딜 수 있는지 검증하는 과정이 반드시 필요해요.
이 글을 끝까지 읽고 나면, 배포 버튼을 누르기 전 스스로를 점검할 수 있는 단단한 기준을 갖게 될 거예요. 실무에서 바로 꺼내 쓸 수 있는 점검 항목들을 단계별로 정리해 두었으니, 하나씩 따라와 주세요.
이 글에서 함께 살펴볼 내용들
설계 단계에서 반드시 정의해야 하는 리소스와 보안 기준
배포 안정성을 결정짓는 프로브(Probe)와 배포 전략 설정법
배포 직후 사고를 막기 위한 실시간 검증 절차
자주 발생하는 실수 패턴과 해결 방법
배포 버튼을 누르기 전, 이것부터 준비하세요
무작정 YAML 파일을 작성하고 kubectl apply 명령어를 입력하는 것은 매우 위험해요. 안정적인 디플로이먼트를 위해서는 환경에 대한 이해와 명확한 기준이 먼저 세워져야 해요. 준비 과정이 부실하면 배포 과정 내내 불안감에 떨게 될 수밖에 없어요.
가장 먼저 고려해야 할 것은 현재 클러스터의 상태와 배포하려는 애플리케이션의 성격이에요. 트래픽이 몰리는 시간대인지, 혹은 리소스가 부족한 노드에 배포하게 되는 것은 아닌지 미리 파악해야 해요. 또한, 사용하는 이미지의 태그가 latest로 되어 있지는 않은지도 꼭 확인해야 해요. 최신 버전을 보장하지 못하는 태그는 운영 환경에서 재앙을 불러올 수 있어요.
배포 전략 선택을 위한 비교 가이드
애플리케이션의 특성에 따라 어떤 배포 방식을 사용할지 결정해야 해요. 무조건 무중단 배포가 정답은 아니에요. 상황에 맞는 전략을 선택하는 것이 중요해요.
전략 유형
특징
장점
단점
RollingUpdate
파드를 하나씩 순차적으로 교체
서비스 중단 없음
배포 중 리소스 일시 증가
Recreate
기존 파드를 모두 삭제 후 새 파드 생성
설정 충돌 방지 용이
서비스 일시 중단 발생
Blue/Green
새 버전을 완전히 띄운 후 트래픽 전환
빠른 롤백 가능
두 배의 리소스 필요
💡 알아두기 대부분의 웹 서비스는 RollingUpdate를 기본으로 사용해요. 하지만 데이터베이스 스키마 변경처럼 하위 호환성이 깨지는 경우에는 Recreate 방식을 신중히 고려해야 해요.
사전 체크를 위한 판단 기준
전략을 정했다면 다음 세 가지 질문에 답할 수 있어야 해요. 첫째, 우리 서비스가 잠시라도 끊기면 안 되는가? 둘째, 배포 중에 리소스를 추가로 확보할 여유가 있는가? 셋째, 문제가 생겼을 때 즉시 이전 버전으로 되돌릴 수 있는가? 이 질문들에 대한 답이 명확해야 배포 사고를 예방할 수 있어요.
실패 없는 배포를 위한 5단계 핵심 실행 프로세스
이제 본격적인 실무 단계로 들어갈게요. 각 단계는 독립적인 것이 아니라 서로 유기적으로 연결되어 있어요. 하나라도 소홀히 하면 다음 단계에서 반드시 문제가 발생해요.
STEP 1. 리소스 정의와 한도(Limits) 설정하기
가장 흔한 배포 실패 원인은 바로 리소스 부족이에요. 애플리케이션이 사용하는 CPU와 메모리의 양을 정확히 예측하고 이를 YAML 파일에 명시해야 해요. 이때 Requests와 Limits의 차이를 명확히 이해하는 것이 핵심이에요.
Requests는 쿠버네티스 스케줄러가 파드를 배치할 때 참고하는 최소 보장량이에요. 반면 Limits는 파드가 사용할 수 있는 최대 한도죠. 만약 Limit을 너무 낮게 잡으면 애플리케이션이 실행 중에 메모리 부족으로 OOMKilled(Out Of Memory Killed) 상태가 되어 강제 종료될 수 있어요. 반대로 Limit을 설정하지 않으면, 하나의 파드가 노드의 모든 리소스를 점유하여 옆에 있는 다른 파드들까지 함께 죽게 만드는 이른바 ‘노드 잠식’ 현상이 발생해요.
실무에서는 애플리케이션의 부하 테스트를 먼저 수행한 뒤, 평균 사용량과 피크 타임 사용량을 기준으로 이 수치들을 결정해야 해요. 단순히 감으로 정하는 것은 매우 위험한 행동이에요.
STEP 2. 안정성을 결정하는 프로브(Probe) 구성하기
쿠버네티스가 파드의 건강 상태를 어떻게 판단할지 알려주는 것이 바로 프로브 설정이에요. 이 설정이 잘못되면, 실제로는 서비스가 준비되지 않았는데 트래픽이 유입되거나, 정상적인 서비스임에도 불구하고 쿠버네티스가 파드를 계속 재시작하는 비극이 발생해요.
Liveness Probe: 애플리케이션이 살아있는지 확인해요. 응답이 없으면 쿠버네티스는 파드를 재시작해요.
Readiness Probe: 애플리케이션이 요청을 받을 준비가 되었는지 확인해요. 준비가 안 되었다면 트래픽을 보내지 않아요.
Startup Probe: 앱이 초기 구동되는 동안 긴 시간을 벌어주는 용도예요.
특히 Readiness Probe를 설정하지 않으면, 앱이 완전히 로딩되기도 전에 트래픽이 들어와 사용자들에게 502 Bad Gateway 에러를 보여주게 돼요. 반대로 Liveness Probe를 너무 공격적으로 설정하면, 일시적인 네트워크 지연만으로도 멀쩡한 파드가 재시작되는 무한 루프에 빠질 수 있어요. 각 프로브의 initialDelaySeconds와 failureThreshold 값을 애플리케이션의 부팅 속도에 맞춰 정밀하게 조정해야 해요.
STEP 3. 무중단 배포를 위한 전략 파라미터 최적화
RollingUpdate를 사용하더라도 세부 설정을 어떻게 하느냐에 따라 서비스 안정성이 완전히 달라져요. 핵심은 maxSurge와 ⚠️ 주의 클러스터의 전체 리소스가 부족한 상황에서 maxSurge 값을 너무 높게 잡으면, 새로운 파드를 띄울 노드 공간이 없어 배포 자체가 멈춰버리는 상황이 발생할 수 있어요. 반드시 현재 가용 리소스를 먼저 확인하세요.
STEP 4. 보안 및 권한(RBAC) 점검하기
운영 환경에서는 보안이 생명이에요. 디플로이먼트가 사용하는 ServiceAccount가 너무 많은 권한을 가지고 있지는 않은지 확인해야 해요. 애플리케이션이 클러스터의 다른 자원을 수정하거나 삭제할 수 있는 권한이 있다면, 보안 사고 발생 시 피해 범위가 걷잡을 수 없이 커져요.
또한, SecurityContext 설정을 통해 컨테이너가 루트(root) 권한으로 실행되지 않도록 제한해야 해요. 파일을 읽고 쓰는 권한이나 네트워크 접근 권한을 최소한으로 제한하는 ‘최소 권한 원칙’을 지키는 것이 배포 전 필수 점검 사항이에요.
STEP 5. 모니터링 및 로그 수집 준비 완료
배포가 끝났다고 해서 안심하기엔 일러요. 배포 직후에 발생하는 미세한 오류들을 잡아내기 위한 장치가 마련되어 있어야 해요. 애플리케이션 로그가 중앙 집중형 로그 시스템(예: ELK Stack, Loki)으로 잘 전송되고 있는지, 메트릭(Prometheus 등)이 정상적으로 수집되고 있는지 확인해야 해요.
배포 직후에는 kubectl get pods 명령어를 통해 모든 파드가 Running 상태인지, 그리고 Readiness Probe를 통과하여 1/1 Ready 상태가 되었는지 눈으로 직접 확인하는 습관을 가져야 해요.
배포 시나리오 예시: 안정적인 롤링 업데이트
만약 사용자가 10명이고, 리소스가 넉넉하지 않은 환경이라면 다음과 같은 설정을 권장해요.
Strategy: RollingUpdate
maxSurge: 1 (하나씩 천천히 추가)
maxUnavailable: 0 (기존 파드는 새 파드가 완벽히 준비된 후 제거)
Readiness Probe: HTTP GET /health 경로를 통해 2초 간격으로 확인
이렇게 설정하면 배포 과정에서 서비스 가용성을 최우선으로 지키면서도 리소스 사용량을 급격하게 늘리지 않고 안정적으로 전환할 수 있어요.
자주 하는 실수와 해결법 및 자주 묻는 질문
실무에서는 이론대로만 흘러가지 않아요. 예상치 못한 변수들이 늘 발생하죠. 가장 빈번하게 발생하는 실수 패턴을 익혀두면 사고를 미연에 방지할 수 있어요.
자주 하는 실수와 해결법
❌ 이미지 태그를 latest로 설정함 왜 발생하는가: 편리함을 위해 항상 최신 버전을 가져오도록 설정하지만, 이는 배포 시점에 어떤 코드가 실행될지 예측할 수 없게 만들어요. ✅ 해결법: 반드시 Git 커밋 해시나 시맨틱 버저닝(예: v1.2.3)을 사용하여 고유한 태그를 명시하세요.
❌ Liveness Probe만 설정하고 Readiness Probe를 누락함 왜 발생하는가: 앱이 살아있는지만 체크하면 되니까 편하다고 생각하기 때문이에요. 하지만 앱이 로딩 중일 때 트래픽을 받으면 에러가 발생해요. ✅ 해결법: 반드시 Readiness Probe를 함께 설정하여 준비된 파드에만 트래픽이 가도록 하세요.
❌ 리소스 Limit을 설정하지 않음 왜 발생하는가: 개발 환경에서는 리소스 제약이 크지 않아 문제점을 느끼지 못하기 때문이에요. ✅ 해결법: 운영 환경에서는 반드시 CPU와 메모리 Limit을 설정하여 옆 파드를 보호하세요.
❌ ConfigMap/Secret 변경 후 파드 재시작을 잊음 왜 발생하는가: 설정 파일만 바꾸면 바로 반영될 것이라고 착각하기 때문이에요. ✅ 해결법: 설정 변경 후에는 디플로이먼트를 재시작(kubectl rollout restart)하여 새 설정을 반영해야 해요.
❌ Deployment의 Replicas 수를 너무 낮게 설정함 왜 발생하는가: 리소스 절약을 위해 최소한의 개수만 유지하려 하기 때문이에요. ✅ 해결법: 고가용성을 위해 최소 2~3개 이상의 파드가 서로 다른 노드에 분산되도록 설정하세요.
자주 묻는 질문
Q. 배포 도중 심각한 문제가 생기면 어떻게 되돌리나요?
가장 빠르게 이전 버전으로 되돌리는 방법은 kubectl rollout undo deployment/[디플로이먼트명] 명령어를 사용하는 거예요. 이 명령어를 사용하면 이전에 성공했던 리비전(Revision)으로 즉시 롤백이 가능해요.
Q. Pod가 계속해서 CrashLoopBackOff 상태예요. 무엇부터 봐야 하나요?
가장 먼저 kubectl logs [파드명] 명령어로 애플리케이션 자체의 에러 로그를 확인하세요. 그다음 kubectl describe pod [파드명]을 통해 이벤트 로그를 확인하여 메모리 부족(OOM)인지, 이미지 문제인지, 혹은 프로브 실패 때문인지 파악해야 해요.
Q. Deployment와 ReplicaSet의 차이점은 무엇인가요?
ReplicaSet은 지정된 개수의 파드를 유지하는 것에 집중하는 하위 개념이에요. Deployment는 이 ReplicaSet을 관리하며, 배포 전략(RollingUpdate 등)을 실행하고 버전 관리(History)를 수행하는 상위 컨트롤러 역할을 해요. 우리는 보통 Deployment를 직접 조작하게 돼요.
Q. Readiness Probe가 계속 실패하는데 원인이 뭘까요?
애플리케이션이 지정된 경로(예: /health)로 HTTP 요청을 받았을 때 200 OK를 반환하는지 확인하세요. DB 연결이나 외부 API 의존성이 해결되지 않아 응답을 못 주는 경우도 매우 흔해요.
안정적인 운영을 위한 마지막 한 걸음
쿠버네티스 환경에서의 배포는 단순히 코드를 밀어넣는 과정이 아니라, 시스템의 안정성을 검증하는 과정이에요. 오늘 다룬 내용들이 처음에는 복잡하게 느껴질 수 있지만, 반복하다 보면 자연스럽게 습관이 될 거예요.
✅ 핵심 요약
리소스 설정: Requests와 Limits를 명확히 구분하여 정의하세요.
프로브 구성: Liveness와 Readiness Probe를 애플리케이션 특성에 맞춰 설정하세요.
배포 전략: 무중단 배포를 위해 maxSurge와 maxUnavailable을 최적화하세요.
보안 준수: 최소 권한 원칙에 따라 ServiceAccount와 SecurityContext를 관리하세요.
버전 관리: ‘latest’ 태그 대신 고유한 버전 태그를 사용하세요.
이 글을 읽은 여러분이 바로 실행해야 할 액션 플랜을 제안할게요.
오늘 할 일: 현재 운영 중인 디플로이먼트의 YAML 파일을 열어 리소스 Limit과 프로브 설정이 되어 있는지 확인해 보세요.
이번 주 할 일: 배포 전략(RollingUpdate)의 파라미터를 우리 서비스 규모에 맞게 조정해 보세요.
실행 직전 할 일: 배포 전, 반드시 이전 버전으로 돌아갈 수 있는 롤백 명령어(kubectl rollout undo)를 머릿속에 그려보세요.
실습 환경에서 직접 적용해 보시고, 설정 과정에서 막히는 부분이 있다면 언제든 댓글로 질문을 남겨 주세요. 함께 고민하며 성장해 나가요!
함께 읽으면 좋은 글: – 쿠버네티스 디플로이먼트 기본 개념 정리 – 안정적인 쿠버네티스 클러스터 구축 입문 가이드