증상
ECS 클러스터에서 운영 중인 서비스의 Task가 기동 직후 크래시하며 crash loop에 진입했습니다. CloudWatch 로그에는 Spring Boot 기동 실패(Application run failed)가 기록되었고, ECS 이벤트에서 Task 시작 → 등록 → drain → deregister가 반복되었습니다.
RedisWrongPasswordException: WRONGPASS invalid username-password pair
or user is disabled.
Redis(Valkey) 인증 실패로 인해 Bean 생성 체인이 연쇄적으로 실패했습니다.
redissonClient → redissonConnectionFactory → stringRedisTemplate
→ JwtBlacklistService → jwtValidationCache → jwtAuthenticationFilter
→ Tomcat 기동 불가
JWT 블랙리스트를 Valkey에 저장하는 구조였기 때문에, Valkey 연결 실패가 곧 서비스 전체 기동 실패로 이어졌습니다.
조사 과정
CloudTrail + Athena 감사 로그 분석
누군가 비밀번호를 변경했거나, 인프라 설정이 바뀌었을 가능성을 먼저 확인했습니다.
| 조사 항목 | 결과 |
|---|---|
Secrets Manager 변경 이력 (PutSecretValue, UpdateSecret) | 없음 — GetSecretValue만 존재 |
| ElastiCache API 변경 이력 | 없음 |
ECS 새 배포 (RegisterTaskDefinition, UpdateService) | 없음 |
ECR 이미지 push (PutImage) | 없음 |
CloudTrail 분석 결과, 최근 어떤 변경도 발생하지 않았습니다. 비밀번호가 바뀐 것도, 새 배포가 된 것도, 이미지가 푸시된 것도 아니었습니다.
인프라 상태 확인
| 항목 | 상태 |
|---|---|
| Valkey Replication Group | available, 정상 |
AuthTokenEnabled | true (AUTH TOKEN 방식) |
AuthTokenLastModifiedDate | 약 한 달 전 |
| ElastiCache 이벤트 | 스냅샷 성공만 존재, 페일오버/유지보수 없음 |
| Task Definition | 변경 없음 |
| Secrets Manager 저장값 | 정상 존재 |
모든 것이 정상이었지만, 한 가지 단서가 있었습니다 — AUTH TOKEN의 마지막 수정일이 약 한 달 전이었습니다.
원인 특정
Secrets Manager에 저장된 비밀번호로 AUTH TOKEN을 재설정(SET) 시도했을 때 결정적인 에러가 발생했습니다.
InvalidParameterValue: The AUTH token provided does not match the AUTH token
provided for rotation. To SET, please use an AUTH token that is the same as
the AUTH token provided for rotation.
이 에러는 AUTH TOKEN 로테이션이 중간 상태에서 멈춰 있다는 것을 의미합니다.
근본 원인
Secrets Manager ↔ ElastiCache 관계
┌─────────────────────┐ ┌──────────────────────┐ ┌─────────────────────┐
│ Secrets Manager │ │ ECS Task │ │ ElastiCache Valkey │
│ │ │ │ │ │
│ [secret-path] │──①──│ REDIS_PASSWORD │──②──│ AUTH TOKEN │
│ │ │ (환경변수로 주입) │ │ (인증에 사용) │
│ │ │ │ │ │
│ {"password":"xxx"} │ │ 값: "xxx" │ │ 허용 토큰: "yyy" │
└─────────────────────┘ └──────────────────────┘ └─────────────────────┘
↑ ↑
│ 자동 동기화 없음 — 수동 관리 필요 │
└──────────────────────────────────────────────────────────┘
문제: "xxx" ≠ "yyy" → WRONGPASS
Secrets Manager와 ElastiCache AUTH TOKEN 사이에는 자동 동기화가 없습니다. ElastiCache "간편한 생성"으로 Valkey를 만들 때 자동 생성된 AUTH TOKEN과, Secrets Manager에 수동으로 저장한 비밀번호가 처음부터 달랐습니다.
"간편한 생성" 시 AUTH TOKEN이 자동 생성되지만 그 값을 다시 확인할 방법이 없으므로, 생성 직후 반드시 AUTH TOKEN을 원하는 값으로 변경하고 Secrets Manager와 동기화해야 합니다.
ElastiCache AUTH TOKEN 변경 프로세스
ElastiCache의 AUTH TOKEN 변경은 2단계로 이루어집니다.
정상 절차:
ROTATE (새 비밀번호 추가) → SET (기존 비밀번호 제거, 새 비밀번호 확정)
ROTATE 단계에서는 기존 비밀번호와 새 비밀번호가 동시에 유효합니다. 이후 SET을 실행해야 기존 비밀번호가 제거되고 새 비밀번호만 남습니다.
실제 발생한 상황
ROTATE 실행 (새 비밀번호 추가) → SET 미실행 (로테이션 중간 상태 방치)
약 한 달 전 AUTH TOKEN 변경 작업 시 ROTATE만 실행하고 SET을 실행하지 않은 채 방치되었습니다.
왜 한 달간 문제가 없었는가
기존 Task들은 이미 Valkey에 연결된 상태였기 때문에 재인증이 필요하지 않았습니다. 기존 커넥션은 유지되므로 로테이션 중간 상태여도 정상 동작했습니다.
장애 트리거
[약 한 달 전] ElastiCache "간편한 생성"으로 Valkey 생성
→ AUTH TOKEN 자동 생성 (값 확인 불가)
→ Secrets Manager에 별도 비밀번호 수동 저장
→ 두 값이 다른 상태로 운영 시작
[약 한 달간] task 재시작 없이 장기 운영
→ persistent connection 유지 → 문제 미발견
[장애 당일 새벽] Valkey 스냅샷 윈도우 실행
[장애 당일 오전] Task 재시작 (ECS 내부 스케줄링 또는 인프라 이벤트)
→ 새 Task가 Secrets Manager 비밀번호로 AUTH 시도
→ AUTH TOKEN 불일치 → WRONGPASS
→ Spring Boot 기동 실패
→ ECS crash loop 진입
핵심은 로테이션 중간 상태가 한 달간 방치되었고, Task 재시작이 트리거가 되어 장애가 발생한 것입니다.
복구 과정
Step 1: ROTATE로 Secrets Manager 비밀번호를 다시 유효하게 추가
aws elasticache modify-replication-group \
--replication-group-id [replication-group-id] \
--auth-token "[password]" \
--auth-token-update-strategy ROTATE \
--apply-immediatelyStep 2: available 상태 확인 후 SET으로 확정
# 상태 확인 (available 될 때까지 대기)
aws elasticache describe-replication-groups \
--replication-group-id [replication-group-id] \
--query "ReplicationGroups[0].Status" --output text
# SET 실행 — 로테이션 완료
aws elasticache modify-replication-group \
--replication-group-id [replication-group-id] \
--auth-token "[password]" \
--auth-token-update-strategy SET \
--apply-immediatelyStep 3: ECS 서비스 강제 재배포
aws ecs update-service \
--cluster [cluster-name] \
--service [service-name] \
--force-new-deploymentROTATE → SET → ECS 재배포 순서로 진행하여 서비스가 정상 복구되었습니다.
재발 방지
AUTH TOKEN 변경 시 필수 절차
| 단계 | 작업 | 확인 사항 |
|---|---|---|
| 1 | ROTATE 실행 | 새 비밀번호 추가 (기존 + 새 비밀번호 둘 다 유효) |
| 2 | 애플리케이션 연결 확인 | 새 비밀번호로 정상 연결되는지 검증 |
| 3 | SET 실행 | 기존 비밀번호 제거, 새 비밀번호만 유효 |
| 4 | Secrets Manager 업데이트 | 저장된 비밀번호를 새 값으로 변경 |
| 5 | ECS force new deployment | Task 재시작하여 새 비밀번호로 연결 확인 |
신규 생성 직후 동기화 절차
ElastiCache "간편한 생성" 후 AUTH TOKEN이 자동 생성되지만 확인할 방법이 없으므로, 원하는 비밀번호로 덮어써야 합니다:
# (1) 원하는 비밀번호를 ROTATE로 추가
aws elasticache modify-replication-group \
--replication-group-id [replication-group-id] \
--auth-token "[password]" \
--auth-token-update-strategy ROTATE \
--apply-immediately
# (2) available 대기 후 SET으로 확정 (기존 자동 생성 토큰 제거)
aws elasticache modify-replication-group \
--replication-group-id [replication-group-id] \
--auth-token "[password]" \
--auth-token-update-strategy SET \
--apply-immediately
# (3) Secrets Manager에 같은 비밀번호 저장
aws secretsmanager put-secret-value \
--secret-id "[secret-name]" \
--secret-string '{"password":"[password]"}'
# (4) ECS 서비스 재배포
aws ecs update-service \
--cluster [cluster-name] \
--service [service-name] \
--force-new-deployment동기화 상태 확인 방법
Bastion에서 Secrets Manager 비밀번호로 직접 연결 테스트:
redis-cli -h [valkey-endpoint] -p 6379 --tls -a '[password]'
# PONG → 동기화 정상
# WRONGPASS → 불일치 → 위 동기화 절차 수행 필요핵심 교훈
ROTATE후 반드시SET으로 완료할 것 — 중간 상태 방치는 시한폭탄- AUTH TOKEN 변경과 Secrets Manager 업데이트는 반드시 한 세트로 처리
- 기존 커넥션이 유지되는 동안은 문제가 드러나지 않으므로, 변경 직후 Task를 재시작하여 새 비밀번호로 연결을 검증해야 함
- CloudTrail + Athena 감사 로그는 "변경이 없었다"는 사실을 확인하는 데에도 유용함 — 소거법의 핵심 도구
정리
- ElastiCache AUTH TOKEN 로테이션 미완료(ROTATE만 실행, SET 미실행)가 근본 원인
- 기존 커넥션이 유지되는 동안 약 한 달간 문제가 잠복
- Task 재시작 시 새 커넥션에서 인증 실패 → 서비스 crash loop
- CloudTrail 감사 로그로 최근 변경 없음을 확인하여 원인 범위를 좁힘
- ROTATE → SET → Secrets Manager 업데이트 → ECS 재배포로 복구