Deployment로 배포하고 스케일링하기
앞 장에서 Pod을 직접 만들면 안 되는 이유를 이야기했습니다. 이 장에서 그 대안인 Deployment를 씁니다. Deployment에 매니페스트를 하나 적용하면, 여러분이 할 일은 사실상 끝입니다. "이 이미지로 3개의 복제본을 유지해줘"라고 선언만 해두면, 그 뒤로 Pod을 몇 개 만들지, 죽은 걸 언제 다시 만들지는 전부 쿠버네티스가 알아서 합니다.
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-api
spec:
replicas: 3
selector:
matchLabels:
app: my-api
template:
metadata:
labels:
app: my-api
spec:
containers:
- name: my-api
image: my-api:1.0.0
ports:
- containerPort: 8080kubectl apply -f deployment.yaml
kubectl get deployments
kubectl get pods -l app=my-api
# my-api-7d9f8c6b5-a1b2c 1/1 Running
# my-api-7d9f8c6b5-d3e4f 1/1 Running
# my-api-7d9f8c6b5-g5h6i 1/1 Running왜 중간에 ReplicaSet이 하나 더 있는가
kubectl get all을 실행해보면 Deployment와 Pod 사이에 ReplicaSet이라는 리소스가 하나 더 보입니다. 처음 보면 쓸데없는 계층처럼 느껴지지만, 이 계층이 바로 무중단 배포를 가능하게 하는 트릭입니다.
flowchart TD D["Deployment: my-api"] --> RS1["ReplicaSet (image: 1.0.0)"] D -.롤아웃 시 새로 생성.-> RS2["ReplicaSet (image: 1.1.0)"] RS1 --> P1["Pod"] RS1 --> P2["Pod"] RS2 --> P3["Pod"] RS2 --> P4["Pod"] RS2 --> P5["Pod"]
이미지를 1.0.0에서 1.1.0으로 바꾸면 Deployment는 기존 ReplicaSet을 수정하는 게 아니라 새 ReplicaSet을 하나 더 만듭니다. 그리고 새 ReplicaSet의 Pod 수를 서서히 늘리면서 옛 ReplicaSet의 Pod 수를 서서히 줄입니다. 이 과정이 끝나면 옛 ReplicaSet은 Pod이 0개인 채로 남아 있는데, 이게 바로 롤백이 순식간에 되는 이유입니다 — 옛 버전을 다시 만드는 게 아니라, 이미 존재하는 옛 ReplicaSet의 Pod 수를 다시 늘리기만 하면 됩니다.
스케일과 업데이트
# 복제본 수만 바꾸고 싶을 때
kubectl scale deployment my-api --replicas=5
# 이미지 버전만 바꾸고 싶을 때 (매니페스트 파일을 안 고쳐도 된다)
kubectl set image deployment/my-api my-api=my-api:1.1.0
# 방금 배포가 어떻게 진행되는지 실시간으로 보기
kubectl rollout status deployment/my-apikubectl set image처럼 명령줄로 즉흥적으로 바꾸는 방법과, YAML 파일을 고치고 kubectl apply를 다시 실행하는 방법 둘 다 결과는 같습니다. 다만 실무에서는 후자를 강하게 권합니다. YAML 파일을 Git으로 관리하지 않고 명령줄로 즉흥 수정을 반복하면, 몇 주 뒤에는 "지금 클러스터에 떠 있는 게 정확히 어떤 설정인지" 아무도 정확히 모르는 상태가 됩니다. 이 방식(선언한 파일을 Git에 두고, 그 파일을 기준으로만 배포하는 것)을 GitOps라고 부르는데, 이 책의 범위를 넘어서는 주제라 여기서는 짚기만 하고 넘어갑니다.
롤백
배포한 버전에 문제가 있으면 되돌리는 것도 명령 한 줄입니다.
kubectl rollout history deployment/my-api
kubectl rollout undo deployment/my-api
# 특정 리비전으로 되돌리고 싶다면
kubectl rollout undo deployment/my-api --to-revision=2여기서 하나 짚고 넘어가야 할 게 있습니다. kubectl rollout undo는 어디까지나 직전 배포로 되돌리는 것이지, 데이터베이스 마이그레이션이나 외부 상태까지 되돌려주지는 않습니다. 애플리케이션 코드는 롤백했는데 이미 실행된 DB 마이그레이션이 새 스키마를 요구한다면, 롤백한 옛 코드가 오히려 그 자리에서 깨질 수 있습니다. 배포 전략을 짤 때 "코드 롤백"과 "데이터 롤백"은 항상 따로 생각해야 합니다.
복제본 수를 왜 3개로 잡았는지, 그리고 노드 장애가 났을 때 이 숫자가 실제로 무엇을 보장해주는지는 10장에서 리소스 요청량과 함께 다시 다룹니다. 다음 장에서는 이렇게 늘어난 여러 개의 Pod을 클라이언트가 어떻게 하나의 주소로 찾아가는지 — Service — 를 봅니다.