Actions가 초록불인데 배포가 반영되지 않았다면, “CI 성공 ≠ 배포 성공”이다
워크플로가 성공으로 끝났다는 건 스텝이 0으로 종료했다는 뜻일 뿐, 새 버전이 실제로 떠서 트래픽을 받는다는 뜻이 아니다. 초록불과 실제 상태가 어긋나는 지점은 대개 셋 중 하나다.
1) 배포 스텝이 apply만 하고 결과를 기다리지 않는다
kubectl apply는 “요청을 접수했다”에서 0으로 끝난다. 새 ReplicaSet이 기동에 실패해도 워크플로는 성공이다. 배포 스텝은 반드시 rollout이 끝날 때까지 대기하는 게이트를 둬야 한다.
kubectl apply -f k8s/
kubectl rollout status deploy/<name> -n <ns> --timeout=120s # 실패하면 여기서 비-0 종료
2) 이미지 태그가 새 빌드를 가리키지 않는다
CI가 커밋 SHA로 이미지를 빌드·푸시했는데 매니페스트는 여전히 :latest나 이전 태그를 참조하면, 클러스터 입장에선 바뀐 게 없다. 게다가 같은 태그를 재사용하고 imagePullPolicy: IfNotPresent면 노드가 캐시된 옛 이미지를 그대로 쓴다. 태그는 불변(커밋 SHA 또는 digest)으로 두는 게 안전하다.
kubectl get deploy <name> -n <ns> -o jsonpath='{.spec.template.spec.containers[0].image}'
3) context/namespace가 의도와 다르다
러너의 kubeconfig context가 스테이징을 가리키는데 프로덕션을 의도했다면, 배포는 “성공”하지만 엉뚱한 클러스터에 반영된다. 배포 스텝 앞에 kubectl config current-context와 대상 namespace를 명시적으로 출력·고정한다.
어긋남을 사후에 확인하는 법
kubectl rollout history deploy/<name> -n <ns>
kubectl describe deploy <name> -n <ns> | sed -n '/Conditions/,/Events/p'
Conditions의 Progressing / Available과 이미지 값만 봐도 “CI는 왜 성공했는데 반영이 안 됐는지”가 대부분 드러난다. 근본 해결은 불변 태그 + rollout status 게이트 + context 고정 세 가지다.
빠른 진단 체크리스트
- CI 성공은 스텝 종료일 뿐, 배포 성공이 아님을 전제한다
- 배포 스텝에
kubectl rollout status --timeout게이트를 둔다 - 매니페스트 이미지 태그가 새 빌드를 가리키는지 확인한다
- 가변 태그 재사용 + IfNotPresent로 옛 이미지가 캐시되는지 본다
- 이미지는 커밋 SHA·digest로 불변 고정한다
- kubeconfig context·namespace가 의도와 같은지 출력·고정한다
rollout history·describe의 Conditions로 사후 확인한다- progressDeadline 초과로 멈췄는지·자동 롤백됐는지 본다