Argo CD Degraded — progressDeadlineSeconds 만료
Argo CD 콘솔에서 앱 하나가 HEALTH: Degraded 로 떠 있었습니다. 그런데 서비스는 멀쩡히 돌고
사용자 쪽에서 이상하다는 얘기도 없었습니다.
Argo CD 는 Git 에 선언해 둔 상태를 클러스터에 계속 맞춰 주는 GitOps 배포 도구고, 배포만 하는 게
아니라 배포한 앱이 지금 정상인지도 콘솔에 같이 표시해 줍니다. 앱마다 초록 Healthy 나 빨간
Degraded 같은 배지로 붙습니다.
(ApplicationSets 목록 화면. 출처: Argo CD 공식 문서, Apache-2.0)
그래서 배포가 잘 끝났는지는 대개 이 표시로 봅니다. 파드를 직접 세어 보지 않고 콘솔이 초록이면 됐다고 보게 되는데, 이번엔 그 표시가 빨간색이었습니다.
Degraded 옆에 붙은 메시지는 이랬습니다.
ProgressDeadlineExceeded: ReplicaSet "my-app-xxxx" has timed out progressing.
새 ReplicaSet 이 정해진 시간 안에 진행을 못 끝냈다는 뜻입니다. 이 앱은 Deployment 가 아니라 Argo
Rollouts 의 Rollout 으로 배포합니다. Argo Rollouts 는 새 버전을 한 번에 다 바꾸지 않고
카나리나 blue-green 으로 조금씩 넘기면서 지표를 보고 계속할지 되돌릴지 정해 주는 컨트롤러고,
쿠버네티스에 원래 없는 리소스라 CRD(사용자가 추가하는 리소스 종류)로 등록해서 씁니다. 그래서 이
메시지도 기본 컨트롤러가 아니라 Rollouts 쪽에서 나온 것입니다.
지금 상태부터 확인 — 파드는 정상
메시지가 “has timed out” 이라 배포가 지금도 안 끝나고 매달려 있는 줄 알고, 그것부터 확인했습니다.
kubectl -n <ns> get rs <rs> \
-o custom-columns=NAME:.metadata.name,DESIRED:.spec.replicas,READY:.status.readyReplicas,AVAILABLE:.status.availableReplicas
DESIRED == READY == AVAILABLE. 원하는 개수만큼 떠 있고 전부 준비돼서 서비스에 들어가 있습니다.
파드 쪽에는 손댈 게 없으니 남는 건 저 메시지가 어디서 나오고 왜 안 지워지느냐입니다.
원인 — 안 지워진 과거 타임아웃 기록
메시지를 남기는 쪽은 Argo Rollouts 컨트롤러라, 새 ReplicaSet 이 progressDeadlineSeconds(기본
600초) 안에 진전을 못 하면 컨트롤러가 Rollout 의 status.conditions 에
ProgressDeadlineExceeded 를 기록합니다.
여기까지는 정상 동작이고 문제는 그다음입니다. 원인이 사라지고 파드가 전부 정상으로 돌아와도
그때 남긴 조건이 자동으로 지워지지 않습니다. Argo CD 는 Rollout 의 conditions 를 읽어서
헬스를 판정하니, 오래된 조건 하나 때문에 계속 Degraded 로 표시된 겁니다. 지금 도는 건 멀쩡한데
과거 기록만 남아서 보이던 현상이었습니다.
조건을 직접 열어 보면 그 기록이 그대로 남아 있는 게 보입니다.
kubectl -n <ns> get rollout <ro> \
-o jsonpath='{range .status.conditions[*]}{.type} {.status} {.reason} -> {.message}{"\n"}{end}'
lastTransitionTime 을 같이 보면 그 조건이 언제 붙었는지 나오고, 며칠 전 날짜면 지금 문제가
아니라 남아 있는 기록입니다.
조치 — 파드는 그대로 두고 상태만 재평가
고쳐야 할 게 기록뿐이라 파드나 ReplicaSet 을 다시 만들 이유가 없습니다. Rollout 의
메타데이터에만 의미 없는 어노테이션을 하나 답니다. spec.template 을 안 건드리니 파드는
교체되지 않습니다.
kubectl -n <ns> patch rollout <ro> --type=merge \
-p "{\"metadata\":{\"annotations\":{\"touched-at\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}}}"
컨트롤러가 이 변경을 감지해 조건을 다시 평가하고 오래된 ProgressDeadlineExceeded 가 정리되면서
Healthy 로 돌아오고, 돌고 있는 파드는 하나도 안 건드립니다.
검색하면 이미지 태그를 바꿨다 되돌리는 식으로 spec.template 을 건드려 다시 평가하게 하는
방법도 나옵니다. 그것도 되기는 하지만 파드가 전부 교체됩니다. 상태 표시만 고치면 되는 상황에서
운영 중인 파드를 갈아 끼울 이유는 없습니다.
기동이 느린 앱이면 — progressDeadlineSeconds 상향
위 조치는 한 번 타임아웃이 났다가 회복된 흔적을 지우는 것이라, 앱이 원래 느려서 정상 배포인데도 600초를 넘긴다면 기록이 계속 다시 생기니 그때는 데드라인 자체를 올려 둡니다.
spec:
progressDeadlineSeconds: 1200
기본 600초를 늘려 두면 정상 배포가 데드라인에 안 걸리니, 늦게 뜨는 게 정상인 앱에서는 이쪽이 맞습니다.
콘솔의 헬스는 파드 상태가 아니라 conditions
Argo CD 가 Degraded 를 띄우면 지금 고장 났다는 뜻으로 읽힙니다. 하지만 그 표시는 Rollout 의 conditions 를 읽어서 나오는 값이라, 실제 파드 상태와 따로 놀 수 있습니다.
콘솔은 빨간데 서비스는 멀쩡하면, 먼저 DESIRED == READY == AVAILABLE 로 지금 상태를 확인하고
그다음 conditions 를 열어 그 메시지가 언제 것인지 봅니다. 과거 기록이면 메타데이터만 건드려 다시
평가하게 하면 되고, 지금도 계속 생기는 기록이면 그때 데드라인을 올립니다.
댓글 0