[IT-방법] 디플로이먼트 자동화 구축 가이드 – CI/CD와 스크립트로 반복 작업 없애기

디플로이먼트 관련 쿠버네티스 구조를 설명하는 대표 이미지

매번 수동으로 실행하는 kubectl apply, 언제까지 반복할까요?

금요일 저녁 6시, 퇴근을 앞둔 상황에서 급하게 코드를 배포해야 하는 상황을 상상해 보세요. 로컬 PC에서 kubectl apply -f 명령어를 입력했는데, 갑자기 CrashLoopBackOff 에러가 화면을 가득 채웁니다. 원인을 찾으려니 YAML 파일의 오타가 보이고, 환경 변수 설정이 잘못된 것을 뒤늦게 깨닫습니다. 결국 몇 시간 동안 명령어를 반복하며 수동으로 클러스터를 헤매게 되죠.

이런 경험은 쿠버네티스를 처음 접하는 백엔드 개발자라면 누구나 겪는 흔한 고통이에요. 사람이 직접 명령어를 입력하는 과정에는 반드시 실수가 포함될 수밖에 없어요. 배포 환경이 복잡해질수록 설정 파일의 개수는 늘어나고, 어떤 버전의 이미지가 어떤 설정으로 돌아가고 있는지 파악하는 것조차 버거워집니다. 단순한 실수 하나가 전체 서비스의 장애로 이어지는 순간, 수작업 배포의 위험성은 극명하게 드러나요.

우리가 꿈꾸는 개발 환경은 코드를 푸시하기만 하면 자동으로 검증되고, 안전하게 운영 환경까지 전달되는 모습이에요. 디플로이먼트 자동화는 단순히 편리함을 넘어, 운영의 안정성과 개발의 속도를 보장하는 핵심 장치예요. 자동화가 구축되면 배포 과정에서 발생하는 휴먼 에러를 원천 차단하고, 문제가 생기더라도 즉시 이전 상태로 되돌릴 수 있는 회복 탄력성을 얻게 돼요.

이 글에서는 단순한 이론이 아니라, 실제 현장에서 사용하는 자동화 구조를 설계하고 적용하는 과정을 상세히 다룰게요. 다음 내용을 통해 반복 작업의 굴레에서 벗어날 수 있어요.

  • 자동화가 필요한 근본적인 이유와 핵심 개념 이해하기
  • CI/CD 도구 선택을 위한 명확한 기준 세우기
  • 실무에서 바로 쓰는 파이프라인과 스크립트 설계법
  • 배포 실패 시 빠르게 복구하는 롤백 전략

자동화 설계 전 반드시 챙겨야 할 체크리스트

자동화 시스템을 구축하기 전에 무턱대고 도구부터 설치하는 것은 위험해요. 잘못 설계된 파이프라인은 오히려 관리 포인트만 늘리는 독이 될 수 있어요. 먼저 우리 팀의 개발 문화와 현재 인프라 상황을 냉정하게 분석해야 해요. 어떤 도구를 선택하느냐에 따라 앞으로의 운영 난이도가 완전히 달라지기 때문이에요.

가장 먼저 결정해야 할 것은 Push 방식으로 할 것인지, 아니면 Pull 방식(GitOps)으로 할 것인지예요. Push 방식은 CI 도구가 직접 클러스터에 접속해 명령을 내리는 형태라 설정이 간편하지만, 보안상 클러스터 권한을 외부 도구에 넘겨줘야 한다는 부담이 있어요. 반면 GitOps 방식은 클러스터 내부의 에이전트가 Git의 상태를 감시하며 동기화하기 때문에 보안이 뛰어나고 상태 관리가 명확해요.

💡 알아두기
쿠버네티스 자동화를 위해서는 단순히 명령어를 자동화하는 것을 넘어, 애플리케이션의 이미지 빌드, 레지스트리 저장, 매니페스트 업데이트, 클러스터 반영이라는 전체 생애 주기를 설계해야 해요.

또한, 설정 파일을 관리할 때 템플릿 엔진을 도입할지 결정해야 해요. 환경별(Dev, Staging, Prod)로 다른 설정값을 관리하기 위해 Helm이나 Kustomize 같은 도구를 사용할 준비가 되어 있는지 확인하세요. 아래 표를 통해 각 방식의 특징을 비교해 보며 우리 팀에 맞는 방향을 정해 보세요.

구분 CI/CD Push 방식 GitOps Pull 방식
대표 도구 Jenkins, GitHub Actions ArgoCD, Flux
보안성 낮음 (외부 도구에 권한 필요) 높음 (내부 에이전트가 동작)
상태 동기화 어려움 (명령 실행 시점에만 반영) 매우 우수 (Git 상태와 항시 일치)
학습 곡선 낮음 (직관적인 스크립트) 높음 (GitOps 개념 이해 필요)

준비가 되었다면 이제 구체적인 단계별 실행 계획을 세워야 해요. 도구를 정했다면 그 도구가 요구하는 권한(RBAC)과 네트워크 통로를 확보하는 작업이 선행되어야 한다는 점을 잊지 마세요.

실전! 디플로이먼트 자동화 파이프라인 구축 5단계

이제 본격적으로 자동화의 심장부로 들어가 볼게요. 전체 흐름은 소스 코드의 변경이 감지되어 컨테이너 이미지가 생성되고, 이 이미지를 기반으로 쿠버네티스 리소스가 업데이트되는 일련의 과정을 포함해요. 단계별로 어떤 작업을 수행해야 하는지 아주 상세하게 살펴볼게요.

STEP 1. 컨테이너 빌드 및 이미지 푸시 자동화

모든 자동화의 시작은 코드의 변화를 감지하는 데서 시작해요. 개발자가 Git 저장소에 코드를 푸시하면, CI 도구(예: GitHub Actions)가 즉시 동작을 시작해야 해요.

먼저, 코드를 가져와서 테스트를 수행해요. 유닛 테스트를 통과하지 못한 코드가 이미지로 만들어지는 것은 시간 낭비일 뿐만 아니라 위험해요. 테스트가 성공하면 Docker 빌드를 진행해요. 이때 주의할 점은 이미지 태그를 ‘latest’로 사용하지 않는 것이에요. ‘latest’ 태그는 어떤 버전이 배포되었는지 추적하기 어렵게 만들고, 롤백을 불가능하게 만들어요. 대신 Git의 커밋 해시(Commit Hash)나 시맨틱 버저닝(Semantic Versioning)을 사용하여 고유한 태그를 붙여주세요.

빌드가 완료된 이미지는 사내 컨테이너 레지스트리(ECR, Docker Hub 등)에 푸시해요. 이 과정이 완료되어야 다음 단계인 배포 단계로 넘어갈 수 있는 준비가 끝난 거예요.

STEP 2. 매니페스트 관리와 템플릿 적용

쿠버네티스에 배포할 YAML 파일들을 어떻게 관리하느냐가 자동화의 품질을 결정해요. 단순히 정적인 YAML 파일을 사용하는 것은 확장성이 떨어져요. 개발용, 테스트용, 운영용 환경마다 설정값이 조금씩 다르기 때문이죠.

이때 Helm(헬름)을 사용하면 매우 효율적이에요. Helm 차트를 사용하면 공통적인 구조는 유지하면서, values.yaml 파일만 교체하여 환경별로 다른 리소스 제한(CPU/Memory), 복제본 개수(Replicas), 환경 변수를 손쉽게 주입할 수 있어요. 예를 들어, 개발 환경에서는 리소스를 적게 쓰고, 운영 환경에서는 고가용성을 위해 복제본을 5개 이상으로 설정하는 식이죠.

💡 알아두기
Helm은 패키지 매니저로서 복잡한 배포 과정을 하나의 명령어로 추상화해 줘요. 하지만 설정이 너무 복잡해지면 가독성이 떨어질 수 있으니, 꼭 필요한 변수만 템플릿화하는 절제미가 필요해요.

STEP 3. GitOps 기반의 CD 파이프라인 설계

이제 빌드된 이미지를 실제 클러스터에 반영할 차례예요. 요즘 가장 권장되는 방식은 ArgoCD를 활용한 GitOps 방식이에요. 이 방식의 핵심은 Git 저장소가 곧 클러스터의 진실(Source of Truth)이 된다는 점이에요.

배포 프로세스는 다음과 같아요. CI 도구가 이미지 빌드를 마치면, 이미지 태그 정보를 담은 매니페스트 저장소(Git)의 YAML 파일 내용을 자동으로 수정(Update)해요. 그러면 클러스터 내부에 설치된 ArgoCD가 Git 저장소의 변경 사항을 감지하고, 현재 클러스터의 상태와 다르다는 것을 알아차려요. ArgoCD는 즉시 클러스터에 새로운 설정을 적용하여 Git에 명시된 상태와 클러스터 상태를 일치시켜요.

이 방식의 장점은 배포 과정이 투명하다는 거예요. 누가, 언제, 어떤 이미지를 배포했는지 Git 로그만 보면 알 수 있고, 누군가 실수로 클러스터 설정을 직접 변경하더라도 ArgoCD가 다시 Git의 상태로 되돌려 놓기 때문에 설정 드리프트(Configuration Drift) 현상을 막을 수 있어요.

STEP 4. 배포 자동화 스크립트 작성 실전

CI 파이프라인 내부에서 매니페스트 저장소의 태그를 업데이트하기 위해 쉘 스크립트나 간단한 도구를 사용할 수 있어요. 아래는 GitHub Actions에서 사용할 수 있는 가상의 스크립트 예시예요. 이 스크립트는 Git 저장소의 특정 파일 내 이미지 태그를 변경하는 역할을 해요.

# 예시: 매니페스트의 이미지 태그 업데이트 스크립트
IMAGE_TAG=${{ github.sha }}
sed -i "s/image: my-app:.*/image: my-app:${IMAGE_TAG}/" ./charts/my-app/values.yaml
git config user.name "github-actions"
git config user.email "github-actions@github.com"
git add .
git commit -m "Deploy image tag: ${IMAGE_TAG}"
git push origin main

위와 같이 스크립트를 통해 사람이 직접 파일을 수정할 필요 없이, 시스템이 알아서 Git을 업데이트하도록 만드는 것이 핵심이에요. 이렇게 하면 배포 기록이 남는 동시에 자동화된 흐름이 완성돼요.

STEP 5. 배포 검증 및 안정성 확보

배포가 완료되었다고 해서 끝이 아니에요. 실제로 서비스가 정상적으로 작동하는지 확인하는 단계가 반드시 필요해요. 쿠버네티스의 Liveness ProbeReadiness Probe를 제대로 설정했는지 확인하세요. Readiness Probe가 제대로 작동하지 않으면, 애플리케이션이 준비되기도 전에 트래픽이 몰려 에러가 발생할 수 있어요.

또한, 배포 직후에는 로그를 모니터링하고 에러율이 급증하지 않는지 체크하는 자동화된 검증 단계(Post-deployment test)를 파이프라인에 포함하는 것이 좋아요. 만약 에러가 감지된다면 즉시 알람을 보내거나 자동으로 롤백을 수행하도록 설계해야 진정한 의미의 자동화가 완성된다고 할 수 있어요.

자주 하는 실수와 해결법

자동화를 구축하다 보면 예상치 못한 벽에 부딪히곤 해요. 현장에서 가장 많이 발생하는 실수들을 정리했으니, 비슷한 상황이라면 아래 해결법을 참고해 보세요.

이미지 태그를 ‘latest’로 설정하여 배포함
왜 발생하는가: 관리가 편하다는 생각에 가장 흔히 하는 실수예요. 하지만 어떤 코드가 배포되었는지 알 수 없게 되어 문제 추적이 불가능해져요.
해결법: Git의 커밋 해시나 빌드 번호를 이미지 태그로 사용하여 고유성을 확보하세요.

CI 도구에 클러스터 관리자(cluster-admin) 권한을 부여함
왜 발생하는가: 파이프라인을 빠르게 통과시키기 위해 가장 편한 권한을 주는 경우예요. 하지만 CI 도구가 해킹당하면 클러스터 전체가 위험해져요.
해결법: 필요한 네임스페이스에 대해서만 특정 리소스(Deployment, Service 등)를 조작할 수 있는 최소 권한(RBAC)만 부여하세요.

매니페스트 파일과 소스 코드를 하나의 저장소에서 관리함
왜 발생하는가: 관리가 단순하다는 이유 때문이에요. 하지만 코드 변경이 잦을 때마다 배포 설정까지 같이 변경되어야 하므로 파이프라인이 복잡해져요.
해결법: 소스 코드 저장소와 인프라 설정(매니페스트) 저장소를 분리하여 GitOps 구조를 만드세요.

Readiness Probe 설정을 생략함
왜 발생하는가: 애플리케이션이 빠르게 뜨기 때문에 필요성을 느끼지 못하는 경우가 많아요.
해결법: 앱이 실제 요청을 처리할 준비가 되었는지 확인하는 경로를 반드시 설정하여, 준비되지 않은 컨테이너에 트래픽이 가는 것을 막으세요.

Secret 정보를 Git 저장소에 평문으로 저장함
왜 발생하는가: 자동화 과정에서 설정을 쉽게 관리하려고 하기 때문이에요.
해결법: Sealed Secrets나 External Secrets Operator를 사용하여 암호화된 상태로 관리하세요.

자주 묻는 질문

Q. 배포 중에 문제가 생겼을 때 가장 빠르게 복구하는 방법은 무엇인가요?

가장 빠른 방법은 kubectl rollout undo deployment/[이름] 명령어를 사용하는 거예요. 하지만 GitOps를 사용 중이라면 Git 저장소에서 이전 커밋으로 되돌리는(Revert) 것이 정석이에요. 그래야 Git과 클러스터의 상태가 다시 일치하게 됩니다.

Q. Jenkins와 GitHub Actions 중 무엇을 추천하시나요?

현재 운영 중인 환경에 따라 달라요. 이미 GitHub를 사용 중이고 관리 부담을 줄이고 싶다면 GitHub Actions가 유리해요. 반면, 매우 복잡한 워크플로우나 자체 인프라 내부에 설치해야 하는 제약이 있다면 Jenkins가 더 강력한 커스터마이징 기능을 제공해요.

Q. GitOps를 도입하면 배포 속도가 느려지지 않나요?

초기 설정과 동기화 과정에서 아주 미세한 차이는 있을 수 있지만, 오히려 배포의 안정성이 높아져 재작업 시간이 줄어들기 때문에 전체적인 배포 주기(Cycle time)는 훨씬 빨라지게 돼요.

Q. Helm과 Kustomize 중 어떤 것이 더 나은가요?

애플리케이션 구조가 복잡하고 여러 환경을 유연하게 관리해야 한다면 강력한 기능을 가진 Helm을 추천해요. 반면, 기존 YAML 파일을 거의 그대로 유지하면서 환경별 차이점만 살짝 수정하고 싶다면 Kustomize가 더 가볍고 직관적이에요.

자동화로 얻는 여유, 지금 바로 시작해 보세요

디플로이먼트 자동화는 단순한 기술적 도입이 아니라, 개발자가 개발 본연의 업무에 집중할 수 있도록 만드는 문화의 변화예요. 수동 작업의 불안함에서 벗어나 시스템을 믿고 코드를 푸시할 수 있는 환경을 구축하는 것이 목표예요.

✅ 핵심 요약

  • 이미지 태그는 반드시 고유한 값(Commit Hash 등)을 사용하세요.
  • 환경별 설정 관리를 위해 Helm이나 Kustomize를 도입하세요.
  • 보안을 위해 GitOps(Pull 방식) 도입을 적극 고려하세요.
  • 최소 권한 원칙에 따라 CI/CD 도구의 권한을 제한하세요.
  • 배포 후 상태 검증(Probe 설정)을 자동화 파이프라인에 포함하세요.

오늘 당장 모든 것을 자동화할 수는 없어요. 하지만 작은 것부터 시작할 수 있어요. 이번 주에는 직접 만든 앱의 이미지를 빌드하고 레지스트리에 푸시하는 과정만이라도 스크립트로 만들어 보는 건 어떨까요?

다음 단계로 나아가기 위해 추천하는 실천 계획이에요.

  • 오늘 할 일: 현재 수동으로 배포 중인 YAML 파일의 환경별 차이점 정리하기
  • 이번 주 할 일: GitHub Actions나 GitLab CI를 이용해 Docker 이미지 빌드 파이프라인 만들기
  • 실행 직전 할 일: ArgoCD를 설치하고 Git 저장소의 변경 사항을 반영하는 테스트 수행하기

실습 환경에서 직접 적용해 보다가 막히는 부분이 있다면 언제든 댓글로 질문을 남겨 주세요. 함께 고민하고 해결해 드릴게요!

관련해서 더 깊이 있는 내용을 알고 싶다면 쿠버네티스 디플로이먼트 기본 개념 글이나 클러스터 구축 입문 글을 함께 읽어보시는 것을 추천해요.

댓글 남기기