ES /docs

QMAws::startTask | ECS failures - job_id: 89685, task_definition: cupix-pano-postprocessor-productio

RCA: QMAws::startTask | ECS failures - DRAINING container instances

Error Log#

Datadog Logs

text
QMAws::startTask | ECS failures - job_id: 89685, task_definition: cupix-pano-postprocessor-production, cluster: cupix-tesla-ece-eu, container_instance: arn:aws:ecs:eu-central-1:002596530511:container-instance/cupix-tesla-ece-eu/1e16c03a1eef416c85d83d42f62e9d39, failures: [{"arn":"arn:aws:ecs:eu-central-1:002596530511:container-instance/1e16c03a1eef416c85d83d42f62e9d39","reason":"DRAINING"}]

Impact#

  • Service: cupixworks-any-compute-agent
  • 발생 횟수: 2
  • 최초 발생: 2026-04-14T15:17:29.959Z
  • 최근 발생: 2026-04-14T15:17:30.149Z

Root Cause Summary#

listContainerInstances API가 status: 'ACTIVE' 필터로 container instance 목록을 조회한 시점과, 실제 startTask API를 호출하는 시점 사이에 해당 instance가 DRAINING 상태로 전환되는 race condition이 발생했습니다. describeContainerInstances에서도 status == 'ACTIVE'로 확인했지만, 이 검증 이후 ECS가 ASG scale-in 또는 infrastructure 이벤트로 인해 instance를 DRAINING으로 전환했습니다. 이 에러 자체는 SQS 재전송을 통한 retry로 ~5분 후 성공적으로 복구되었으나, 동일한 패턴이 지난 7일간 34건 발생하여 processing 지연을 유발하고 있습니다.

Technical Analysis#

Code Path#

  • Entry point: qmAws.ts:117runTask 메서드에서 ECS task 실행 시작
  • qmAws.ts:121listContainerInstances 호출로 ACTIVE 상태의 container instance 목록 조회
typescript
// applications/agents/packages/cupix-tesla-compute-agent/src/model/qmAws.ts:238-244
private listContainerInstances = (awsClusterName: string, instanceType: string): Promise<Array<string>> => new Promise((resolve, reject) => {
    const params: AWS.ECS.ListContainerInstancesRequest = {
        cluster: awsClusterName,
        status: 'ACTIVE',
        filter: `attribute:ecs.instance-type == ${instanceType} and runningTasksCount == 0`,
        maxResults: 10
    };
  • qmAws.ts:135describeContainerInstances로 상세 정보 조회 후 status == 'ACTIVE' 재검증
typescript
// applications/agents/packages/cupix-tesla-compute-agent/src/model/qmAws.ts:149-158
if (containerInstance.status == 'ACTIVE'
    && containerInstance.runningTasksCount == 0
    && containerInstance.pendingTasksCount == 0
) {
    try {
        tasks = await this.startTask(awsClusterName, containerInstance.containerInstanceArn as string, job);
        if (tasks.length > 0) break;
    } catch (error) {
        return;  // catch 블록에서 즉시 return — 다른 instance 시도하지 않음
    }
}
  • Failure point: qmAws.ts:191-203ecs.startTask API 호출 시 ECS가 DRAINING failure를 반환
typescript
// applications/agents/packages/cupix-tesla-compute-agent/src/model/qmAws.ts:191-213
this.ecs.startTask(params, (err, data) => {
    if (err) {
        logger.error('QMAws::startTask | end - %s', err.message);
        reject(err);  // err 발생 시 reject → runTask의 catch에서 return으로 전체 중단
    } else {
        if (data.failures && data.failures.length > 0) {
            logger.error('QMAws::startTask | ECS failures - ...');
            // failures 로깅 후 계속 진행 — reject하지 않음
        }
        const tasks = data.tasks;
        if (tasks == undefined) {
            resolve([]);  // task가 없으면 빈 배열로 resolve → 다음 instance 시도 가능
        } else {
            resolve(tasks);
        }
    }
});

기대 동작 vs 실제 동작:

  • 기대: listContainerInstances에서 ACTIVE로 반환된 instance는 startTask 시점에도 ACTIVE 상태여야 함
  • 실제: 조회 후 수백ms 사이에 instance가 DRAINING으로 전환되어 startTask가 failure를 반환함. data.failures가 있어도 에러로 reject하지 않고 빈 task 배열로 resolve하므로, 코드는 다음 instance를 시도함 (이 점은 올바른 동작). 그러나 이 클러스터의 모든 instance(2개)가 동시에 DRAINING이어서 결국 task size: 0으로 종료됨

Log Evidence#

사용한 Datadog 쿼리:

text
service:cupixworks-any-compute-agent status:error @environment:production "QMAws::startTask"
text
service:cupixworks-any-compute-agent @environment:production "89685"

Job 89685 타임라인 (EU region, 2026-04-14):

시각 (UTC) 이벤트
15:15:57.766Z SQS 메시지 수신, job 89685 생성 (capture_id: 33467, team: byuk)
15:15:57.913Z runTask begin — g6.2xlarge instance 조회 시작
15:15:58.188Z runTask endtask size: 0 (사용 가능한 instance 없음)
15:17:29.514Z SQS 재전송으로 두 번째 시도
15:17:29.762Z container instance 1e16c03a1eef416c85d83d42f62e9d39 발견 — status: ACTIVE, memory: 30940 MiB, CPU: 8192
15:17:29.959Z startTask DRAINING failure — instance 1e16c03a1eef416c85d83d42f62e9d39
15:17:29.959Z container instance 8130b6080a4d4114b2c188c8f18390e7 발견 — status: ACTIVE, memory: 30940 MiB, CPU: 8192
15:17:30.149Z startTask DRAINING failure — instance 8130b6080a4d4114b2c188c8f18390e7
15:17:30.149Z runTask endtask size: 0 (두 instance 모두 DRAINING)
15:19:01.557Z 세 번째 시도 — instance 없음, task size: 0
15:20:43.490Z 네 번째 시도 — 새 instance 31aec61bbd824e29bccc39aa560b758e 발견
15:20:43.683Z runTask endtask size: 1 (성공)
15:20:44.014Z task ARN 할당 완료

핵심 에러 로그 원문:

json
{
  "timestamp": "2026-04-14T15:17:29.959Z",
  "status": "error",
  "service": "cupixworks-any-compute-agent",
  "message": "QMAws::startTask | ECS failures - job_id: 89685, task_definition: cupix-pano-postprocessor-production, cluster: cupix-tesla-ece-eu, container_instance: arn:aws:ecs:eu-central-1:002596530511:container-instance/cupix-tesla-ece-eu/1e16c03a1eef416c85d83d42f62e9d39, failures: [{\"arn\":\"arn:aws:ecs:eu-central-1:002596530511:container-instance/1e16c03a1eef416c85d83d42f62e9d39\",\"reason\":\"DRAINING\"}]"
}
json
{
  "timestamp": "2026-04-14T15:17:30.149Z",
  "status": "error",
  "service": "cupixworks-any-compute-agent",
  "message": "QMAws::startTask | ECS failures - job_id: 89685, task_definition: cupix-pano-postprocessor-production, cluster: cupix-tesla-ece-eu, container_instance: arn:aws:ecs:eu-central-1:002596530511:container-instance/cupix-tesla-ece-eu/8130b6080a4d4114b2c188c8f18390e7, failures: [{\"arn\":\"arn:aws:ecs:eu-central-1:002596530511:container-instance/8130b6080a4d4114b2c188c8f18390e7\",\"reason\":\"DRAINING\"}]"
}

7일간 서비스 전체 동일 패턴:

text
service:cupixworks-any-compute-agent status:error "ECS failures" "DRAINING"

지난 7일간 DRAINING/AGENT 관련 failure가 34건 발생, 3개 리전(us-west-2, eu-central-1, ap-southeast-2) 모두에서 확인됨. 주요 task definition별 분포: cupix-capture-3d-reconstruction-production, cupix-pano-postprocessor-production, cupix-skat-master-production-arm, cupix-capture-refinement-production-arm.

Fix Recommendation#

즉시 조치 (Critical)#

  • 파일: applications/agents/packages/cupix-tesla-compute-agent/src/model/qmAws.ts:196-203
  • startTask에서 data.failures에 DRAINING reason이 포함된 경우 error 로그 대신 warn 레벨로 변경. 이는 인프라의 일시적 상태 변화로 인한 예상 가능한 실패이며, SQS retry로 자동 복구되므로 error로 분류할 필요 없음
  • 현재 코드는 failure 시 빈 배열로 resolve하여 다음 instance를 시도하는 동작은 올바르지만, 불필요한 error alert를 발생시킴

단기 개선 (1주 이내)#

  • 파일: applications/agents/packages/cupix-tesla-compute-agent/src/model/qmAws.ts:149
  • describeContainerInstances 결과에서 status == 'ACTIVE' 체크 외에, agentConnected == true 조건을 추가하여 AGENT 연결이 끊긴 instance도 사전에 필터링
  • startTask failure 시 DRAINING/AGENT reason을 감지하면, 해당 instance를 제외하고 listContainerInstances를 재호출하여 다른 instance를 즉시 시도하는 retry 로직 추가 (현재는 SQS visibility timeout에 의존하여 ~90초 후 재시도)

장기 개선 (재발 방지)#

  • ECS startTask API 대신 runTask API(Fargate 또는 EC2 launch type)를 사용하면 ECS 스케줄러가 자동으로 적절한 instance를 선택하므로 DRAINING race condition을 근본적으로 회피 가능
  • ASG scale-in 시 container instance draining에 대한 lifecycle hook을 설정하여, draining 시작 전에 해당 instance를 agent 목록에서 먼저 제거하는 방식 검토
  • 클러스터별 최소 active instance 수를 보장하는 ASG 정책 검토 (현재 EU 클러스터에서 2개 instance가 동시에 DRAINING되어 전체 용량 부재 발생)

Monitoring#

  • DRAINING failure를 warn으로 변경 후, 아래 쿼리로 빈도 모니터링:
text
service:cupixworks-any-compute-agent "ECS failures" ("DRAINING" OR "AGENT")
  • 특정 클러스터에서 연속 DRAINING failure가 임계치(예: 5분 내 5건)를 초과하면 alert 발생:
text
service:cupixworks-any-compute-agent status:error "ECS failures" "DRAINING" cluster:cupix-tesla-ece-eu
  • job 처리 지연 시간 메트릭 추가: SQS 메시지 최초 수신 시각과 task 성공 시각 간 차이를 추적

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: standard
  • SQS retry 메커니즘이 자동 복구를 보장하므로 데이터 유실 위험은 없음. 주요 영향은 processing 지연(이 건은 ~5분). 7일간 34건 발생으로 빈도가 높지만, 모두 자동 복구됨.