ECS 컨테이너 인스턴스의 SSM 에이전트가 ssmmessages VPC 엔드포인트 통해 ECS Exec 작업을 처리할 경우 반환되는 TargetNotConnectedException 오류를 해결하고, SSM 에이전트의 지수 백오프 재시도 동작으로 인해 해결 조치 후에도 오류가 즉시 사라지지 않는 이유를 분석합니다.
이슈
ECS 컨테이너 인스턴스와 동일한 VPC에 ssmmessages VPC 엔드포인트가 위치할 경우, 컨테이너 인스턴스 내에서 실행 중인 SSM 에이전트의 모든 세션 채널 작업은 ssmmessages VPC 엔드포인트를 거쳐 수행됩니다.
컨테이너 인스턴스에서 실행 중인 태스크 컨테이너에 접속하기 위해 ECS Exec 작업을 시도하면 SSM 에이전트가 컨테이너 연결을 정상적으로 처리하지 못해 TargetNotConnectedException 오류가 발생할 수 있으며, 그 원인은 다음과 같습니다.
- ECS 태스크 역할(IAM)에 ssmmessages 필수 권한이 없습니다.
- ssmmessages VPC 엔드포인트의 보안그룹에서 ECS 컨테이너 인스턴스의 443 포트(HTTPS) 트래픽을 허용하는 인바운드 규칙이 없습니다.
$ aws ecs execute-command --interactive --command "/bin/sh" --cluster 클러스터명 --task 태스크ID
The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.
aws: [ERROR]: An error occurred (TargetNotConnectedException) when calling the ExecuteCommand operation: The execute command failed. TargetNotConnected: ecs:태스크명_태스크ID_컨테이너ID is not connected.
해결
ECS 태스크 역할(IAM)에 ssmmessages 필수 권한이 없을 경우, 공식 가이드를 참고하여 IAM 역할에 연결된 정책을 업데이트합니다.
{
"Version":"2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
"Resource": "*"
}
]
}
ssmmessages VPC 엔드포인트의 보안그룹에서 ECS 컨테이너 인스턴스의 443 포트(HTTPS) 트래픽을 허용하는 인바운드 규칙이 없을 경우, 컨테이너 인스턴스에서 실행 중인 SSM 에이전트와 Systems Manager 서비스 간 통신이 불가하기 때문에 세션 채널 생성을 위한 모든 작업이 실패합니다. 이 경우 443 포트(HTTPS)에 대한 인바운드 규칙을 추가하는 것이 해결 방법이지만, 보안그룹을 수정한 직후에도 ECS Exec 작업은 곧바로 성공하지 않고, 상당 시간 동안 동일한 TargetNotConnectedException 오류가 지속됩니다.
ECS 컨테이너 인스턴스의 SSM 에이전트는 웹소켓 연결에 실패하면 곧바로 재시도하지 않고 지수 백오프(Exponential Backoff) 재시도 전략에 따라 재시도 간격을 지수적으로 늘립니다. 즉, ssmmessages VPC 엔드포인트 통신이 계속 실패할 경우, 이전 시도와 다음 시도 사이의 대기 시간이 지수적으로 증가하며, 이 대기 시간은 ControlChannelRetryMaxIntervalMillis 구성값에 따라 최대 40분까지 증가할 수 있습니다.
보안그룹을 수정해 ssmmessages VPC 엔드포인트 통신을 위한 네트워크 요건을 모두 충족시켰다고 해도 컨테이너 인스턴스의 SSM 에이전트가 이미 지수 백오프 대기 상태에 진입한 이후라면 다음 재시도 시점까지 대기해야 하며, SSM 에이전트가 스케쥴을 앞당겨 재시도 작업을 수행하지는 않습니다. 다음 재시도 시점이 도래하기 전까지는 여전히 이전 실패 상태가 유지되며, 이 구간에서 ECS Exec 작업을 요청하면 TargetNotConnectedException 오류가 그대로 반환됩니다.
SSM 에이전트 로그로 살펴보는 지수 백오프 재시도 전략
SSH 또는 Session Manager 등을 통해 ECS 컨테이너 인스턴스에 연결한 후, cat /var/log/amazon/ssm/amazon-ssm-agent.log 명령을 수행하면 웹소켓 연결 시도(Setting up websocket for controlchannel) 시점을 통해 재시도 간격이 약 2배씩 지수적으로 증가하는 것을 확인할 수 있습니다. 최대 대기 시간인 약 40분 (약 2,400초) (+/-600초)에 도달한 다음부터는 더 이상 재시도 간격이 늘어나지 않습니다. 다음은 ssmmessages VPC 엔드포인트 보안 그룹의 443 포트(HTTPS) 인바운드 규칙이 없는 상태에서 SSM 에이전트의 웹소켓 연결 작업을 추적한 타임라인 예시입니다.
| 웹소켓 연결 시도 | 이전 시도와의 간격 | 결과 |
|---|
| 1차(최초 시도) | - | 실패 (타임아웃) |
| 2차(재시도) | +31초 | 실패 (타임아웃) |
| 3차(재시도) | +61초 | 실패 (타임아웃) |
| 4차(재시도) | +127초 | 실패 (타임아웃) |
| 5차(재시도) | +248초 | 실패 (타임아웃) |
| 6차(재시도) | +448초 | 실패 (타임아웃) |
| 7차(재시도) | +882초 | 실패 (타임아웃) |
| 8차(재시도) | +1,787초 | 실패 (타임아웃) |
| 9차(재시도) | +2,388초 | 실패 (타임아웃) |
| 10차(재시도) | +2,395초 | 실패 (타임아웃) |
각 웹소켓 연결 시도 시점의 SSM 에이전트 로그는 아래와 같은 패턴으로 반복됩니다.
$ cat /var/log/amazon/ssm/amazon-ssm-agent.log
INFO [MessageService] [MGSInteractor] Setting up websocket for controlchannel for instance: i-****************, requestId: ********-****-****-****-************
ERROR [MessageService] [MGSInteractor] Failed to get controlchannel token, error: CreateControlChannel failed with error: createControlChannel request failed: failed to make http client call: Post "https://ssmmessages.****.amazonaws.com/v1/control-channel/i-****************,": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
이처럼 ssmmessages VPC 엔드포인트 네트워크 설정을 수정한 시점과 SSM 에이전트의 재시도 시점은 서로 무관하게 진행되므로, 보안그룹 규칙 문제를 해결했다고 해서 ECS Exec 작업이 즉시 성공하지는 않습니다. SSM 에이전트의 재시도 간격은 무한히 늘어나지 않고 약 40분(+/-10분)의 상한이 걸리므로, 충분한 시간을 대기한 후에 ECS Exec 작업을 재시도할 것을 권장합니다.
동일한 컨테이너 인스턴스에서 기존 태스크를 중지하고 신규 태스크를 새로 실행하면, SSM 에이전트가 신규 태스크에 대해서 웹소켓 연결을 새롭게 시도하므로 누적된 지수 백오프 대기 시간 없이 즉시 웹소켓 연결을 수립할 수 있습니다. 즉, 지수 백오프 대기 시간을 무시하기 위해서는 ECS 태스크 교체를 통해 SSM 에이전트의 웹소켓 연결 작업을 초기화해야 합니다.
충분한 시간을 대기하거나 ECS 태스크를 교체한 이후에도 TargetNotConnectedException 오류가 계속 발생하면 GitHub 저장소의 amazon-ecs-exec-checker 스크립트를 실행하여 AWS CLI 환경과 ECS 클러스터/태스크 리소스를 조회하고 ECS Exec 사전 요구 사항의 충족 여부를 점검할 수 있습니다. 예시 명령어는 다음과 같습니다.
bash <( curl -Ls https://raw.githubusercontent.com/aws-containers/amazon-ecs-exec-checker/main/check-ecs-exec.sh ) 클러스터명 태스크ID