AwsTask#fetch! — cross-region IAM permission denied
RCA: PullTaskWorker::perform | ecs:DescribeTasks IAM Permission Denied
Error Log#
PullTaskWorker::perform | error on 5561 - User: arn:aws:iam::002596530511:user/system/tesla-api-production-5nod is not authorized to perform: ecs:DescribeTasks on resource: * because no identity-based policy allows the ecs:DescribeTasks action
Impact#
- Service:
cupixworks-worker - 발생 횟수: 54
- 최초 발생: 2026-04-06T09:03:45.691Z
- 최근 발생: 2026-04-07T09:00:10.154Z
Root Cause Summary#
IAM user arn:aws:iam::002596530511:user/system/tesla-api-production-5nod의 identity-based policy에 ecs:DescribeTasks 권한이 누락되어 있습니다. PullTaskWorker가 AwsTask#fetch! 메서드에서 Aws::ECS::Client.describe_tasks를 호출할 때, AWS가 해당 IAM user에 대해 권한 거부 응답을 반환합니다. 이 에러는 특정 노드(tesla-api-production-5nod)에서만 발생하며, 해당 노드의 IAM user에만 ecs:DescribeTasks 정책이 빠져 있는 것으로 판단됩니다. 성공하는 요청은 다른 노드(다른 IAM credential)에서 처리되고 있습니다.
Technical Analysis#
Code Path#
- Entry point:
app/workers/pull_task_worker.rb:5—PullTaskWorker#perform(id)Sidekiq worker - DB lookup:
app/workers/pull_task_worker.rb:7—AwsTask.find_by_id(id)로 DB에서 ECS task 레코드 조회 - pull 호출:
app/workers/pull_task_worker.rb:10—task.pull!호출 - pull! 구현:
app/models/aws_task.rb:46-49—fetch!후save호출 - Failure point:
app/models/aws_task.rb:69-73—ecs_client.describe_tasks호출 시 IAM 권한 거부
# app/workers/pull_task_worker.rb:5-15
def perform(id)
Cupix::Logger.info("PullTaskWorker::perform | begins on #{id}", class: self.class.name, function: __method__)
task = ::AwsTask.find_by_id(id)
return if task.nil?
task.pull!
Cupix::Logger.info("PullTaskWorker::perform | done on #{id}", class: self.class.name, function: __method__, task: { task_id: task.task_id })
rescue StandardError => e
Cupix::Logger.error("PullTaskWorker::perform | error on #{id} - #{e.message}", class: self.class.name, function: __method__, task: { task_id: task.task_id })
end
perform에서 task.pull!이 호출되면 AwsTask#fetch!가 실행됩니다:
# app/models/aws_task.rb:42-44
def ecs_client
Aws::ECS::Client.new region: ENV['CUPIX_REGION'] || 'us-west-2'
end
# app/models/aws_task.rb:63-73
def fetch!(by_force: false)
unless fetchable?
Cupix::Logger.info("Task is not fetchable with task_id: #{task_id}, last status: #{last_status}", class: self.class.name, function: __method__, task: { task_id: task_id })
return
end
resp = self.ecs_client.describe_tasks({
tasks: [task_id],
cluster: $AWS[:ecs][:cluster_name],
include: ['TAGS']
})
Aws::ECS::Client.new는 명시적 credential을 전달받지 않으므로 AWS SDK의 기본 credential chain을 사용합니다. Production 환경에서 이 chain은 환경변수(AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY) 또는 instance profile을 통해 IAM credential을 가져옵니다. tesla-api-production-5nod 노드에서는 이 credential에 ecs:DescribeTasks 권한이 없습니다.
Enqueue 경로 — PullTaskWorker는 두 곳에서 enqueue됩니다:
# app/models/concerns/statable/job.rb:86-89
after_transition any => :stopped do |job, transition|
job.aws_tasks.each do |task|
PullTaskWorker.perform_in(20.second, task.id)
end
end
# app/repositories/job_repository.rb:214-217
def pull
@model.aws_tasks.each do |task|
PullTaskWorker.perform_async(task.id)
end
end
기대 동작: describe_tasks API 호출이 성공하여 ECS task 상태를 DB에 동기화
실제 동작: IAM 권한 거부로 Aws::ECS::Errors::AccessDeniedException 발생, rescue StandardError에서 catch되어 에러 로그만 남기고 종료. Task 상태가 업데이트되지 않음.
Log Evidence#
사용한 Datadog 쿼리:
service:cupixworks-worker status:error "PullTaskWorker"
service:cupixworks-worker (status:warn OR status:info) "PullTaskWorker"
service:cupixworks-worker "on 5561"
에러 로그 (동일 패턴 반복, 대표 샘플):
2026-04-06T09:03:45.691Z error PullTaskWorker::perform | error on 5561 - User: arn:aws:iam::002596530511:user/system/tesla-api-production-5nod is not authorized to perform: ecs:DescribeTasks on resource: * because no identity-based policy allows the ecs:DescribeTasks action
2026-04-07T14:53:20.401Z error PullTaskWorker::perform | error on 5713 - User: arn:aws:iam::002596530511:user/system/tesla-api-production-5nod is not authorized to perform: ecs:DescribeTasks on resource: * because no identity-based policy allows the ecs:DescribeTasks action
2026-04-07T09:12:42.255Z error PullTaskWorker::perform | error on 5686 - Rate exceeded
타임라인:
- 2026-04-06 09:03 — 최초 발생 (task ID 5561)
- 2026-04-06 09:18 ~ 09:33 — task ID 5566-5574 범위에서 집중 발생
- 2026-04-06 16:06 ~ 19:03 — task ID 5587-5616 범위에서 대량 발생 (약 30건)
- 2026-04-07 06:01 ~ 14:53 — task ID 5649-5714 범위에서 지속 발생
- 2026-04-07 09:12 — "Rate exceeded" 에러 1건 발생 (AWS API throttling)
성공 vs 실패 패턴 비교:
# 성공 (높은 ID 범위, 다른 노드에서 처리)
2026-04-07T15:38:00.268Z info PullTaskWorker::perform | begins on 741509
2026-04-07T15:38:00.268Z info PullTaskWorker::perform | done on 741509
# 실패 (낮은 ID 범위, tesla-api-production-5nod 노드)
2026-04-06T09:03:45.691Z info PullTaskWorker::perform | begins on 5561
2026-04-06T09:03:45.691Z error PullTaskWorker::perform | error on 5561 - ...ecs:DescribeTasks...
성공하는 task들은 ID가 80,000+ ~ 741,000+ 범위이며, 실패하는 task들은 5,000~5,700 범위입니다. 이는 실패하는 task들이 특정 환경 또는 ECS cluster에 속한 것임을 시사합니다. 동일한 시간대에 다른 노드에서는 정상 동작하므로, 문제는 tesla-api-production-5nod 노드의 IAM 정책에 국한됩니다.
Fix Recommendation#
즉시 조치 (Critical)#
IAM user arn:aws:iam::002596530511:user/system/tesla-api-production-5nod의 identity-based policy에 ecs:DescribeTasks 권한을 추가해야 합니다. 다른 정상 동작 중인 노드의 IAM policy와 비교하여 누락된 권한을 확인하고 동일하게 맞춰야 합니다.
해당 IAM policy에 최소한 다음 action을 추가:
ecs:DescribeTasks
Resource scope는 해당 ECS cluster ARN으로 제한하는 것을 권장합니다 (arn:aws:ecs:*:002596530511:task/cupix-tesla-ece/*).
단기 개선 (1주 이내)#
app/models/aws_task.rb:69—describe_tasks호출 시Aws::ECS::Errors::AccessDeniedException을 별도로 catch하여, 권한 문제를 명확히 구분하는 에러 로깅을 추가하는 것을 고려합니다. 현재는 모든StandardError가 동일한 형식으로 로깅되어 IAM 문제와 다른 에러를 구분하기 어렵습니다.- 모든 production 노드의 IAM policy를 일괄 감사하여, 노드 간 권한 불일치가 없는지 확인합니다.
장기 개선 (재발 방지)#
- IAM user 대신 IAM role (instance profile 또는 IRSA)을 사용하도록 전환하여, 노드별 credential 관리 부담을 줄이고 정책 일관성을 보장합니다.
- Infrastructure as Code (Terraform/CloudFormation)로 IAM policy를 관리하여, 노드 추가/교체 시 권한 누락을 방지합니다.
ecs_client생성 시 credential을 명시적으로 전달하거나, 공유 client instance를 사용하여 credential 관리를 중앙화합니다.
Monitoring#
- PullTaskWorker IAM 거부 에러를 감지하는 Datadog monitor 추가:
service:cupixworks-worker status:error "PullTaskWorker" "not authorized"
- AWS CloudTrail에서
ecs:DescribeTasksAccessDenied 이벤트 모니터링 - PullTaskWorker 성공/실패 비율 메트릭 추가 (현재는 로그만 남기고 메트릭은 없음)
Risk Assessment#
- Risk level: medium — ECS task 상태 동기화가 실패하여 job 완료 상태가 정확히 반영되지 않을 수 있으며,
retry: 1설정으로 1회 재시도 후 포기합니다. - 예상 복잡도: trivial — IAM policy에 permission 한 줄 추가로 해결 가능합니다. 코드 변경은 불필요합니다.