[AWS] ECS OIDC Connect와 Managed Instance 테스트
Github OIDC 연동으로 AWS ECS에 자동 배포하는 방법을 소개합니다. Managed Instance로 인스턴스 관리를 자동화하고, 카나리 배포로 안전하게 배포하며, 문제 발생 시 롤백 가능합니다.
개요
Github Action으로 AWS ECS Deploy 하는 방법과 Managed Instance 테스트한 내용을 정리했습니다.
Github OIDC 연동하기
Github Action → AWS 연동
[IAM] > [ID 제공업체] > [공급자 추가]

이후 연동할 역할을 추가합니다
- Github Organization은 ID를 입력합니다
- 개인 계정일 경우 Github ID 등록
- ID 제공업체 →
token.actions.githubusercontent.com - Audience →
sts.amazonaws.com


AmazonEC2ContainerRegistryPowerUser권장합니다(ECR).- Push/Pull 모두 가능

ECS Cluster 생성
Managed Instance Cluster 생성
ECS Managed Instance의 경우 인프라 역할을 사용합니다.
- Launch Template, Fleet 기반 인스턴스 실행(Spot)을 자동으로 관리해줍니다.
- ASG, Launch Template을 생성할 필요 없습니다.

- ecsInfrastructureRoleForManagedInstances 관리형 정책
- 배포 및 인스턴스 관리를 위해 필요한 정책입니다.
- AmazonECSInfrastructureRolePolicyForLoadBalancers
- AmazonECSInfrastructureRolePolicyForManagedInstances
- 배포 및 인스턴스 관리를 위해 필요한 정책입니다.

인스턴스 타입도 유연하게 설정 가능합니다.


클러스터 기본 용량 공급자 구성
Managed Instance의 경우 한 가지 이상의 용량 공급자를 사용할 수 없습니다. 즉, 온디맨드 구성과 Spot 구성은 별개로 구성되야합니다(Managed Instance 한정)

Task Definition
GPU 테스트를 위해 아래와 같이 구성했습니다.
{
"compatibilities": [
"EC2",
"MANAGED_INSTANCES"
],
"containerDefinitions": [
{
"cpu": 0,
"environment": [],
"essential": true,
"image": "<AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com/ecs-gpu-test:latest",
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/ecs-gpu-test",
"awslogs-create-group": "true",
"awslogs-region": "ap-northeast-2",
"awslogs-stream-prefix": "ecs"
}
},
"mountPoints": [],
"name": "gpu-test",
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080,
"protocol": "tcp"
}
],
"resourceRequirements": [
{
"type": "GPU",
"value": "1"
}
],
"systemControls": [],
"volumesFrom": []
}
],
"cpu": "1024",
"executionRoleArn": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/ecsTaskExecutionRole",
"family": "ecs-gpu-test",
"memory": "2048",
"networkMode": "awsvpc",
"placementConstraints": [],
"registeredAt": "2026-01-05T05:17:20.549Z",
"registeredBy": "arn:aws:sts::<AWS_ACCOUNT_ID>:assumed-role/<USER>",
"requiresAttributes": [
{
"name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
},
{
"name": "ecs.capability.execution-role-awslogs"
},
{
"name": "com.amazonaws.ecs.capability.ecr-auth"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
},
{
"name": "ecs.capability.execution-role-ecr-pull"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
},
{
"name": "ecs.capability.task-eni"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.29"
}
],
"requiresCompatibilities": [
"EC2"
],
"revision": 2,
"status": "ACTIVE",
"taskDefinitionArn": "arn:aws:ecs:ap-northeast-2:<AWS_ACCOUNT_ID>:task-definition/ecs-gpu-test:2",
"volumes": [],
"tags": []
}
Github Action workflow
이제 생성된 ARN으로 Github Action Workflow를 구축합니다.
또한 Github Action로 AWS 서비스와 통합하고 있으므로 공식 Repo를 참고하면 좋습니다.
name: Build, Push and Deploy to ECS
on:
push:
branches:
- main
tags:
- 'v*'
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: false # 충돌 방지
env:
AWS_REGION: ap-northeast-2
ECR_REPOSITORY: ecs-gpu-test
ECS_CLUSTER: bjchoi-ecs-cluster
ECS_SERVICE: ecs-gpu-service
CONTAINER_NAME: gpu-test
permissions:
id-token: write
contents: read
jobs:
build-and-push:
runs-on: ubuntu-latest
outputs:
image_uri: ${{ steps.image.outputs.uri }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::{AWS_ACCOUNT_ID}:role/{ROLE_NAME}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}
tags: |
type=sha,prefix=,format=short
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Build and push
id: build
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: false
- name: Output image URI
id: image
run: |
SHORT_SHA=${GITHUB_SHA::7}
echo "uri=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:$SHORT_SHA" >> $GITHUB_OUTPUT
deploy:
runs-on: ubuntu-latest
needs: build-and-push
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::{AWS_ACCOUNT_ID}:role/{ROLE_NAME}
aws-region: ${{ env.AWS_REGION }}
- name: Render Amazon ECS task definition
id: render-task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ needs.build-and-push.outputs.image_uri }}
- name: Deploy to Amazon ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ steps.render-task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
- https://github.com/aws-actions/amazon-ecs-deploy-task-definition
- https://docs.aws.amazon.com/codepipeline/latest/userguide/ecs-cd-pipeline.html
ECS Service 배포 진행 사항
ECS 서비스 > 상태 및 지표에서 배포를 확인 가능합니다.
- 트래픽을 받고 있는 컨테이너 확인 가능
- 트래픽 가중치 확인 가능
- 대상 그룹으로 확인 가능


ECS는 카나리 배포와 선형 배포 2가지 방식이 존재합니다.
- 카나리 배포
- Deployment bake time 기간 동안 가중치 기반 트래픽 분배

- 선형 배포
- Deployment bake time 기간 내 백분율로 트래픽을 높혀갑니다.


기존의 카나리 배포가 ECS에서 선형 배포라고 보시면 됩니다.
Deployment bake time가 완료될 때 까지 언제든지 롤백 가능합니다.



Approve 설정
[Settings] → [Environments] → [production]
deploy:
runs-on: ubuntu-latest
needs: build-and-push
environment: production
...
아래 옵션 활성화가 필요합니다.

배포 설정을 완료하게 되면 아래와 같이 Review Pending deployments가 추가 됩니다.
- 트래픽 전환 자체를 승인하는 과정이 아닌 workflow 흐름만 제어하는 방식입니다.


배포 중 문제 발생시 서킷 브레이커와 롤백 수행으로 언제든지 이전 정상 서비스 구성으로 전환 가능합니다.

정리
ECS Managed Instance는 EKS 수준의 노드 관리 서비스를 제공합니다.
장점은 다음과 같습니다.
- AWS가 EC2 프로비저닝/패칭/스케일링 자동 관리
- Fargate의 편리함 + EC2의 유연성 (GPU, EC2 타입 등)
단점 또한 매우 크게 느껴지는 편입니다.
- EC2 비용과 별도로 추가 청구(Managed Instance 당 추가 비용)
- 단일 Capacity Provider → 유연한 확장 불가능
- 영어로 설정 시 확인 가능
