Claude Code Kubernetes 배포 가이드: Deployment부터 롤백까지
Claude Code로 Kubernetes Deployment, Service, Ingress, probe, 리소스, 롤백 흐름을 안전하게 만드는 방법.
Kubernetes YAML을 리뷰 가능한 산출물로 만들기
Kubernetes는 컨테이너 앱을 클러스터에서 운영하기 위한 강력한 플랫폼입니다. 하지만 초보자가 처음 만나는 어려움은 클러스터 자체보다 Deployment, Service, Ingress, ConfigMap, Secret, readinessProbe, livenessProbe, resource request, rollout, rollback 같은 개념을 한 번에 이해해야 한다는 점입니다. Claude Code에 단순히 “Kubernetes YAML 만들어 줘”라고 말하면 그럴듯한 YAML은 나오지만, latest 태그를 쓰거나, probe가 없거나, Secret 예시를 Git에 넣는 위험한 결과가 생길 수 있습니다.
이 글의 목표는 Claude Code를 자동 배포 버튼처럼 쓰는 것이 아닙니다. 안전한 초보자용 배포 뼈대를 만들고, 그 차이를 사람이 리뷰할 수 있게 만드는 것입니다. 예시는 nginx:1.27-alpine과 ConfigMap으로 제공하는 작은 HTML 페이지를 사용합니다. private registry가 없어도 kind, minikube, Docker Desktop Kubernetes, 테스트 클러스터에서 바로 실행할 수 있습니다.
실제 프로젝트에 맞게 바꿀 때는 공식 문서를 기준으로 삼으세요. Deployments, Services, Ingress, probes, resource management, ConfigMap, Secret, kubectl rollout을 함께 확인하면 좋습니다. 관련 글로는 Docker integration, CI/CD setup, code review, permissions guide를 이어서 볼 수 있습니다.
실제 사용 사례
처음부터 큰 운영 플랫폼을 만들 필요는 없습니다. 작은 앱을 배포하고, 확인하고, 일부러 망가뜨리고, 다시 되돌리는 흐름을 익히는 것이 더 실용적입니다.
| 사용 사례 | 목표 | Claude Code에 맡길 일 |
|---|---|---|
| 내부 도구 첫 배포 | Web 앱 하나를 안정적인 Service 뒤에 둔다 | Deployment, ClusterIP Service, probe, requests와 limits 초안 |
| 교육용 클러스터 | 모든 수강자가 같은 명령으로 실습한다 | namespace 포함 manifest, 확인 명령, 실패 실습 |
| 운영 전 YAML 리뷰 | 위험한 설정을 배포 전에 잡는다 | selector, Secret, probe, Ingress 리뷰 |
| Pull Request 게이트 | 인프라 변경 실수를 조기에 막는다 | dry-run CI, 리뷰 프롬프트, rollback 체크리스트 |
이 주제는 수익화에도 맞습니다. 독자는 단순 정의보다 “운영 사고를 피하는 방법”을 찾고 있기 때문입니다. ClaudeCodeLab은 이런 글을 무료 자료, 템플릿, Claude Code 교육과 상담으로 연결해 팀이 실제 저장소에 적용하도록 돕습니다.
Claude Code에 줄 프롬프트
Kubernetes에서는 “무엇을 만들지”만큼 “무엇을 만들지 않을지”가 중요합니다. LoadBalancer를 만들지 말 것, Secret 실값을 만들지 말 것, cluster-wide RBAC를 만들지 말 것처럼 경계를 적어야 합니다.
로컬에서 검증 가능한 Kubernetes 초보자용 배포 예제를 만들어 주세요.
요구사항:
- namespace는 claude-k8s-demo
- private registry 대신 nginx:1.27-alpine 사용
- ConfigMap으로 HTML 페이지 하나를 제공
- Deployment는 replicas 2, RollingUpdate, readinessProbe, livenessProbe, resources 포함
- Service는 ClusterIP
- Ingress는 선택 사항이며 host는 claude-k8s.local
- Secret 정책은 설명하되 실제 Secret 값은 생성하지 않음
- apply, rollout status, port-forward, 실패, rollback 명령 포함
제약:
- NodePort나 LoadBalancer 사용 금지
- 실제 Secret 값을 YAML에 쓰지 않기
- ClusterRole, ClusterRoleBinding, 파괴적 정리 명령 생성 금지
이 프롬프트는 리뷰 범위를 분명히 합니다. selector와 label이 맞는지, probe가 실제 포트를 가리키는지, resources가 있는지, Secret이 Git에 들어가지 않는지 확인할 수 있습니다. 반복해서 쓴다면 CLAUDE.md에 옮기고, CLAUDE.md best practices를 기준으로 팀 규칙을 만드세요.
복사해서 실행하는 manifest
다음을 k8s/claude-k8s-demo.yaml로 저장합니다. Ingress Controller가 없어도 Service는 port-forward로 확인할 수 있습니다.
apiVersion: v1
kind: Namespace
metadata:
name: claude-k8s-demo
---
apiVersion: v1
kind: ConfigMap
metadata:
name: demo-page
namespace: claude-k8s-demo
data:
APP_ENV: "demo"
index.html: |
<!doctype html>
<html lang="ko">
<head><meta charset="utf-8" /><title>Claude Code Kubernetes Demo</title></head>
<body><h1>Claude Code Kubernetes Demo</h1><p>Deployment, Service, ConfigMap, probes are running.</p></body>
</html>
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-web
namespace: claude-k8s-demo
labels:
app: demo-web
spec:
replicas: 2
revisionHistoryLimit: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: demo-web
template:
metadata:
labels:
app: demo-web
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
resources:
requests:
cpu: "50m"
memory: "64Mi"
limits:
cpu: "250m"
memory: "128Mi"
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 3
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 10
periodSeconds: 10
volumeMounts:
- name: demo-page
mountPath: /usr/share/nginx/html/index.html
subPath: index.html
readOnly: true
volumes:
- name: demo-page
configMap:
name: demo-page
---
apiVersion: v1
kind: Service
metadata:
name: demo-web
namespace: claude-k8s-demo
spec:
type: ClusterIP
selector:
app: demo-web
ports:
- name: http
port: 80
targetPort: http
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-web
namespace: claude-k8s-demo
spec:
ingressClassName: nginx
rules:
- host: claude-k8s.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: demo-web
port:
name: http
초보자가 가장 자주 놓치는 부분은 selector.matchLabels, Pod template labels, Service selector의 일치입니다. 하나라도 어긋나면 Service endpoint가 비거나 Deployment가 의도한 Pod를 관리하지 못합니다.
검증 명령
먼저 kubectl cluster-info로 대상 클러스터를 확인한 뒤 실행합니다.
kubectl apply -f k8s/claude-k8s-demo.yaml
kubectl -n claude-k8s-demo rollout status deployment/demo-web
kubectl -n claude-k8s-demo get pods -l app=demo-web
kubectl -n claude-k8s-demo get service demo-web
kubectl -n claude-k8s-demo port-forward service/demo-web 8080:80
다른 터미널에서 확인합니다.
curl http://localhost:8080/
Ingress는 마지막에 봅니다. Pod와 Service가 정상인지 확인하기 전에 Ingress부터 디버깅하면 원인을 놓치기 쉽습니다.
kubectl -n claude-k8s-demo get ingress demo-web
kubectl -n claude-k8s-demo describe ingress demo-web
ConfigMap, Secret, 롤백
ConfigMap은 민감하지 않은 설정용입니다. 데이터베이스 비밀번호, API 토큰, 세션 키는 넣으면 안 됩니다. Secret은 민감값을 위한 리소스지만 base64는 암호화가 아닙니다. 운영에서는 cloud Secret Manager, External Secrets, Sealed Secrets, SOPS, 내부 vault 절차 중 하나를 팀 표준으로 정해야 합니다.
로컬 실습용 Secret은 이렇게 만들고 secret.local.yaml을 .gitignore에 넣습니다.
kubectl -n claude-k8s-demo create secret generic demo-api-secret \
--from-literal=API_TOKEN='replace-me-locally' \
--dry-run=client \
-o yaml > secret.local.yaml
kubectl apply -f secret.local.yaml
롤아웃과 실패 롤백도 직접 해 봅니다.
kubectl -n claude-k8s-demo set image deployment/demo-web nginx=nginx:1.27-alpine
kubectl -n claude-k8s-demo rollout status deployment/demo-web
kubectl -n claude-k8s-demo rollout history deployment/demo-web
kubectl -n claude-k8s-demo set image deployment/demo-web nginx=nginx:not-a-real-tag
kubectl -n claude-k8s-demo rollout status deployment/demo-web --timeout=30s
kubectl -n claude-k8s-demo rollout undo deployment/demo-web
rollback은 모든 것을 되돌리지 않습니다. ConfigMap, Secret, DB migration, DNS, feature flag가 같이 바뀌었다면 별도 절차가 필요합니다. Claude Code에는 runbook에 이 차이를 쓰게 하세요.
CI 리뷰와 실패 사례
Pull Request에서 최소한 dry-run을 실행합니다.
name: Kubernetes manifest review
on:
pull_request:
paths:
- "k8s/**"
jobs:
dry-run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: azure/setup-kubectl@v4
with:
version: "v1.30.0"
- run: kubectl apply --dry-run=client -f k8s/
흔한 실패는 운영에서 latest 사용, readiness와 liveness 혼동, resources 누락, base64를 보안으로 착각, Service 확인 전 Ingress 디버깅, Claude Code 결과를 그대로 배포하는 것입니다. 해결책은 공식 문서, CI, 작은 실습, 사람의 리뷰를 함께 두는 것입니다.
상담 경로와 확인 결과
이 예제는 학습용 최소 구성입니다. 운영에서는 이미지 빌드, 태그 정책, TLS, Secret 주입, 모니터링, RBAC, CI/CD, 장애 대응이 필요합니다. 개인은 무료 cheatsheet로 시작할 수 있고, 팀은 Claude Code 교육과 상담에서 실제 저장소 기준으로 프롬프트, CLAUDE.md, 리뷰 체크리스트, rollback 훈련을 정리하는 편이 안전합니다.
이 글의 흐름은 apply, rollout status, Pod 확인, port-forward, curl, 잘못된 이미지로 실패 만들기, rollout undo 순서로 검증하도록 설계했습니다. 실제로 초보자가 많이 틀리는 부분은 고급 네트워킹이 아니라 selector 불일치, probe path 오류, resources 누락, Secret 예시 처리였습니다. 이 제약을 첫 Claude Code 요청에 넣는 것이 나중에 YAML을 고치는 것보다 빠릅니다.
무료 PDF: Claude Code 치트시트
이메일을 입력하면 명령, 리뷰 습관, 안전한 워크플로를 정리한 PDF를 받을 수 있습니다.
개인정보를 안전하게 관리하며 스팸을 보내지 않습니다.
작성자 소개
Masa
Claude Code 실무 워크플로와 팀 도입을 검증하는 엔지니어입니다.
관련 글
Obsidian 메모를 CLAUDE.md로 바꾸는 Claude Code 워크플로
Obsidian 작업 메모를 CLAUDE.md 운영 노트로 정리해 Claude Code 세션의 문맥 반복을 줄입니다.
Claude Code Revenue CTA Routing: 글에서 PDF, Gumroad, 상담으로 보내기
독자 의도에 따라 무료 PDF, Gumroad 상품, 상담으로 나누는 Claude Code CTA 설계입니다.
Claude Code 팀 인계 규칙: 리뷰 증거, 권한, 롤백, 수익 경로까지 넘기는 법
Claude Code 작업을 팀에 넘길 때 필요한 증거, 권한 규칙, 롤백, 무료 PDF, Gumroad, 상담 경로 체크리스트.