Argo CD Degraded — progressDeadlineSeconds 만료

Kubernetes3분조회

Argo CD 는 Git 에 선언한 상태를 쿠버네티스에 계속 맞춰 주는 GitOps 배포 도구이고, 배포한 앱의 헬스 상태를 콘솔에 보여줍니다. 그 콘솔에서 앱이 HEALTH: Degraded 로 떴는데, 정작 파드는 전부 정상이었습니다.

ProgressDeadlineExceeded: ReplicaSet "my-app-xxxx" has timed out progressing.

Argo Rollouts(Rollout CRD)로 배포되는 앱이었습니다.

원인 — 안 지워진 과거 타임아웃 기록

먼저 지금이 정말 정상인지 확인했습니다.

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.conditionsProgressDeadlineExceeded 를 기록합니다.

문제는 이후 원인이 사라지고 파드가 다 정상이 되어도 그때의 기록이 자동으로 지워지지 않는다는 겁니다. Argo CD 는 이 오래된 조건을 그대로 읽어서 Degraded 로 표시합니다. 런타임은 정상인데 과거 흔적이 남아 보이는 현상입니다.

조건을 직접 확인하면 타임아웃 기록이 보입니다.

kubectl -n <ns> get rollout <ro> \
  -o jsonpath='{range .status.conditions[*]}{.type} {.status} {.reason} -> {.message}{"\n"}{end}'

해결 — 파드 안 건드리고 상태만 재평가

기록만 갱신되면 되는 상황이라, 파드나 ReplicaSet 을 재생성할 이유가 없습니다. Rollout 의 메타데이터에만 no-op 어노테이션을 답니다. 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 로 돌아옵니다. 운영 영향이 0입니다.

spec.template 을 건드리는 방식(이미지 태그를 바꿨다 되돌리는 등)으로도 재평가가 되지만, 그건 파드를 교체합니다. 상태 표시만 고치면 되는 상황에서 파드까지 갈아치울 이유가 없습니다.

재발 방지 — 데드라인 상향

기동이 느린 앱이면 정상인데도 600초 안에 진전을 못 해서 이 기록이 처음부터 남습니다. 그런 앱은 progressDeadlineSeconds 를 올려둡니다.

spec:
  progressDeadlineSeconds: 1200

이건 근본 원인이 “앱이 원래 느리다” 일 때의 대응입니다. 한 번 타임아웃이 났다가 회복된 흔적이 남은 경우라면 위의 재평가로 충분합니다.

참고

  1. 불러오는 중