ES /docs

QMAws::startTask | ECS failures - job_id: 90459, task_definition: cupix-skat-master-production-arm,

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

Error Log#

Datadog Logs

text
QMAws::startTask | ECS failures - job_id: 90459, task_definition: cupix-skat-master-production-arm, cluster: cupix-tesla-ece-eu, container_instance: arn:aws:ecs:eu-central-1:002596530511:container-instance/cupix-tesla-ece-eu/c6a22b33f1b64addbe150be3df88cefb, failures: [{"arn":"arn:aws:ecs:eu-central-1:002596530511:container-instance/c6a22b33f1b64addbe150be3df88cefb","reason":"DRAINING"}]

Impact#

  • Service: cupixworks-any-compute-agent
  • Team: groupamana
  • 발생 횟수: 1 (이 클러스터), 19건 (최근 7일 동일 패턴)
  • 최초 발생: 2026-04-18T06:17:30.078Z
  • 최근 발생: 2026-04-18T06:17:30.078Z

Root Cause Summary#

ECS container instance c6a22b33f1b64addbe150be3df88cefb가 DRAINING 상태로 전환 중이었으나, listContainerInstances API가 status: 'ACTIVE' 필터로 조회했음에도 해당 인스턴스를 반환했다. 이는 ECS API의 상태 전환 지연(race condition) 때문이다. 이후 startTask 호출 시 ECS가 DRAINING 사유로 task 배치를 거부했다. 현재 코드는 startTask 실패 시 return으로 즉시 종료하여 다른 정상 인스턴스를 시도하지 않는다. SQS 메시지 재처리(약 10초 간격)를 통해 5번째 시도에서 다른 인스턴스(9c6a809a...)로 성공했지만, 총 약 55초의 불필요한 지연이 발생했다. 이 패턴은 최근 7일간 8개 job에서 19회 반복되고 있다.

Technical Analysis#

Code Path#

  • Entry point: qmAws.ts:117 - runTask() 메서드가 SQS 메시지 처리 시 호출됨
  • qmAws.ts:121 - listContainerInstances()로 ACTIVE 상태 인스턴스 목록 조회
  • qmAws.ts:135 - describeContainerInstances()로 상세 정보(메모리, CPU, 상태) 확인
  • qmAws.ts:149-151 - status == 'ACTIVE', runningTasksCount == 0, pendingTasksCount == 0 조건 확인
  • qmAws.ts:154 - startTask() 호출하여 ECS task 배치 시도
  • Failure point: qmAws.ts:156-157 - startTask 실패 시 catch 블록에서 return으로 즉시 종료 (다른 인스턴스 시도 불가)

listContainerInstances 필터 (qmAws.ts:238-245):

typescript
// applications/agents/packages/cupix-tesla-compute-agent/src/model/qmAws.ts:238-245
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
    };

status: 'ACTIVE' 필터를 사용하지만, ECS API는 DRAINING 전환 중인 인스턴스도 잠시 ACTIVE로 반환할 수 있다.

인스턴스 선택 및 startTask 호출 (qmAws.ts:149-159):

typescript
// applications/agents/packages/cupix-tesla-compute-agent/src/model/qmAws.ts:149-159
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;  // 즉시 종료 - 다른 인스턴스를 시도하지 않음
    }
}

return (line 157)이 핵심 문제점이다. continue가 아닌 return을 사용하여, 하나의 인스턴스에서 실패하면 나머지 정상 인스턴스를 시도하지 않고 전체 runTask가 종료된다.

startTask 에러 처리 (qmAws.ts:191-213):

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);
    } else {
        if (data.failures && data.failures.length > 0) {
            logger.error('QMAws::startTask | ECS failures - job_id: %d, ...', ...);
        }
        const tasks = data.tasks;
        if (tasks == undefined) {
            resolve([]);
        } else {
            resolve(tasks);  // DRAINING failure 시 tasks는 빈 배열
        }
    }
});

DRAINING failure는 err가 아닌 data.failures로 반환된다. 에러를 로깅하지만 resolve(tasks)로 빈 배열을 반환하므로, runTasktasks.length > 0 검사에서 break하지 않고 다음 인스턴스로 넘어간다. 단, AWS API 레벨 에러(reject)가 발생하면 catch에서 return으로 즉시 종료된다.

기존 수정 시도 (TSLA-12392, commit 41576ec8d): agentConnected 필터 추가 + returncontinue 변경이 feature 브랜치에 존재하나, develop/master에 미반영 상태.

Log Evidence#

Datadog 쿼리 1: 에러 로그

text
service:cupixworks-any-compute-agent status:error "QMAws::startTask"

에러 로그 (1건):

text
2026-04-18T06:17:30.078Z | ERROR | QMAws::startTask | ECS failures - job_id: 90459, task_definition: cupix-skat-master-production-arm, cluster: cupix-tesla-ece-eu, container_instance: arn:aws:ecs:eu-central-1:002596530511:container-instance/cupix-tesla-ece-eu/c6a22b33f1b64addbe150be3df88cefb, failures: [{"arn":"arn:aws:ecs:eu-central-1:002596530511:container-instance/c6a22b33f1b64addbe150be3df88cefb","reason":"DRAINING"}]

Datadog 쿼리 2: job 90459 전체 타임라인

text
service:cupixworks-any-compute-agent "90459"

타임라인 (SQS 재처리 기반 6회 시도):

시간 (UTC) 이벤트
06:17:29.656 runTask begin - job id: 90459, instance_type: m8g.8xlarge
06:17:29.881 container instance c6a22b33...: status ACTIVE, 126943 MiB free, 0 running, 0 pending
06:17:29.881 container instance ba0df0cd...: status ACTIVE, 991 MiB free, 1 pending task (스킵됨)
06:17:30.078 startTask FAILED - DRAINING failure
06:17:40 ~ 06:18:13 재시도 2~4회 - 동일 실패 (task size: 0)
06:18:24.132 재시도 5회 - 새 인스턴스 9c6a809a... 선택 (126943 MiB, 0 running, 0 pending)
06:18:24.324 startTask SUCCESS - task size: 1
06:18:24.674 updateTaskIdToJob 완료 - task ARN: 339598c8fb1f45edbbdf2628793f20a2

총 복구 시간: 약 55초.

Datadog 쿼리 3: 최근 7일 DRAINING 에러 패턴

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

최근 7일간 19건의 DRAINING 에러가 8개 job에서 발생:

날짜 Job ID Task Definition Cluster DRAINING 인스턴스 수
2026-04-18 06:17 90459 cupix-skat-master-production-arm cupix-tesla-ece-eu 1
2026-04-18 01:33 1022147 cupix-skat-master-production-arm cupix-tesla-ece 1
2026-04-16 19:23 1018906 cupix-capture-3d-reconstruction-production cupix-tesla-ece 3
2026-04-16 08:33 1018106 cupix-skat-master-production-arm cupix-tesla-ece 5
2026-04-16 08:03 1018051 cupix-skat-master-production-arm cupix-tesla-ece 3
2026-04-14 15:17 89685 cupix-pano-postprocessor-production cupix-tesla-ece-eu 2
2026-04-14 00:53 1012847 cupix-capture-3d-reconstruction-production cupix-tesla-ece 1
2026-04-13 15:33 1011694 cupix-capture-3d-reconstruction-production cupix-tesla-ece 3

US (cupix-tesla-ece)와 EU (cupix-tesla-ece-eu) 클러스터 모두에서 발생하며, 3개 task definition에 걸쳐 반복됨.

Fix Recommendation#

즉시 조치 (Critical)#

TSLA-12392 (commit 41576ec8d)를 develop/master에 머지해야 한다. 해당 수정은 두 가지 핵심 변경을 포함:

  1. qmAws.ts:149 - agentConnected == true 필터 추가: ECS agent가 연결 해제된 인스턴스(DRAINING 전환 중 발생)를 사전에 제외
  2. qmAws.ts:157 - returncontinue 변경: 한 인스턴스 실패 시 다른 정상 인스턴스로 즉시 fallback

이 수정이 적용되면 SQS 재처리 대기(~10초 x N회) 없이 같은 runTask 호출 내에서 다른 인스턴스를 바로 시도할 수 있다.

단기 개선 (1주 이내)#

  • startTask에서 data.failures에 DRAINING이 포함된 경우, 해당 인스턴스를 로컬 캐시에 기록하여 같은 polling 주기 내에서 재선택하지 않도록 개선. 현재는 resolve([])로 반환하므로 continue와 조합하면 다음 인스턴스를 시도하지만, 명시적 DRAINING 감지 로직을 추가하면 불필요한 startTask API 호출을 줄일 수 있다.
  • listContainerInstances 호출 시 agentConnected 필터를 ECS API 레벨에서 적용 가능한지 검토 (filter 파라미터에 agentConnected == true 추가).

장기 개선 (재발 방지)#

  • ECS Capacity Provider 전략 도입을 검토. startTask (특정 인스턴스 지정) 대신 runTask (ECS가 인스턴스 선택)를 사용하면 ECS 스케줄러가 DRAINING 인스턴스를 자동으로 제외한다.
  • Auto Scaling Group의 instance refresh/replacement 이벤트와 compute agent의 인스턴스 조회 사이에 발생하는 race condition을 근본적으로 해결하기 위해, ECS 서비스 기반 스케줄링으로의 마이그레이션을 고려.

Monitoring#

  • DRAINING 에러 빈도 추적:
text
service:cupixworks-any-compute-agent status:error "DRAINING" | count by @job_id
  • task 배치 지연 시간 모니터링 (runTask begin ~ startTask success 사이 시간):
text
service:cupixworks-any-compute-agent "QMAws::runTask | end" | measure @duration
  • TSLA-12392 배포 후 DRAINING 에러 발생 건수가 0으로 감소하는지 확인

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: trivial (기존 수정 TSLA-12392 머지만 필요)

현재 SQS 재처리 메커니즘이 자동 복구 역할을 하고 있어, 서비스 중단은 없다. 다만 55초의 불필요한 지연이 사용자 경험에 영향을 줄 수 있으며, 다수의 인스턴스가 동시에 DRAINING 상태인 경우(job 1018106: 5개 인스턴스) 지연이 수 분까지 늘어날 수 있다.