ECS-github action를 이용한 Fargate FastAPI 배포
FastAPI에 대한 내용은 거의 없습니다
ECS-github action에 대한 내용이 주입니다.
배포 아키텍처
깃헙 액션은 레포지토리에 푸시된 이미지의 번호를 모른다
깃허브에서 만든 유니크한 아이디가 있다. 해당 아이디를 이용해서 image에 태그를 걸어보겠다.
위와 같이 진행
1.
IAM user를 이용해서 로그인
a.
하지만 깃헙에서 해당 방법을 deprecated
2.
유저를 사용하지 않고 Role을 사용해서 AWS CLI 접근
b.
User를 사용하지 않고 Access token(JWT 토큰 형식)을 발급받아서 사용
c.
Identity providers(자격 증명 공급자)를 사용해서 github push event가 왔을 때, access token을 사용할 수 있도록 관리
d.
위의 과정을 통해 만든 공급자에 새 역활을 할당해준다
한국어로는 웹 자격 증명, github repository, github branch는 optional (필요 없다면…)
•
그 다음으로는 ECR 관련 권한을 가진 정책을 부여 후, 생성될 역활에 이름을 지정해주면 된다
◦
IAM, ECR, ECS, Secret Manager가 있다
◦
위 oicd role이 ecs에 role을 전달할 충분한 권한이 부여되어 있어야 한다
IAM role assumed by your ECS task does not have sufficient permissions
to pass another role to the ECS service
Python
복사
◦
해당 설명은 아래에서 더 자세하게 다룬다
•
github action에서 OICD 사용하기
◦
위에 permission을 선언한 후, 아래 role-to-assume에 위에서 만든 역활의 ARN을 할당해준다
▪
개인적으로는
${{ secrets.AWS_ROLE_TO_ASSUME }}
위와 같은 형식으로 arn을 숨기기를 권장드립니다.
permissions:
id-token: write # This is required for requesting the JWT
contents: read
SQL
복사
태스크 정의
아래는 task_definition.json 중 발췌된 부분입니다
"containerDefinitions": [
{
"name": "fast_api_server",
"image": ".dkr.ecr.us-east-2.amazonaws.com/fast_api_server",
"cpu": 1024,
"memory": 3072,
"memoryReservation": 2048,
"portMappings": [
{
SQL
복사
이미지 부분을 지웁니다
github action이 푸시하면서 채울 수 있도록 함
아래 부분의 image: ${{ steps.build-image.outputs.image }} 이 build-image 단계에서 빌드된 이미지를 사용해 ECR에 푸시하는 단계입니다
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
# Build a docker container and
# push it to ECR so that it can
# be deployed to ECS.
cd server
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@c804dfbdd57f713b6c079302a4c01db7017a36fc
with:
task-definition: ${{ env.ECS_TASK_DEFINITION }}
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ steps.build-image.outputs.image }}
Python
복사
또한 기존 task definition에 들어가는 정보들도 필요 없어진다 (처음 배포할 때만 필요한 정보들, 업데이트할 때는 사용이 안됩니다)
1.
taskDefinitionArn: 이것은 작업 정의의 Amazon 리소스 이름 (ARN)입니다. 작업 정의가 등록될 때 ECS에 의해 자동으로 할당되며 정의 파일에는 필요하지 않습니다.
2.
compatibilities: 이 필드는 런치 유형의 호환성인 EC2 또는 FARGATE를 나타냅니다. ECS에서 작업 정의가 실행될 수 있는 위치를 표시하는 데 사용되지만 정의 파일 자체에는 필요하지 않습니다.
3.
requiresAttributes: 이러한 속성은 작업 실행에 필요합니다. ECS에서 작업을 적합한 인스턴스와 매칭하는 데 사용되지만 작업 정의 파일에서는 필요하지 않습니다.
4.
revision: 이것은 ECS에서 작업 정의의 개정 번호입니다. 새 버전이 등록될 때마다 자동으로 증가됩니다. 작업 정의 파일에서는 필요하지 않습니다.
5.
status: ECS에서 작업 정의의 등록 상태를 나타냅니다. ECS에서 관리되므로 정의 파일에서는 필요하지 않습니다.
6.
registeredBy: 이 필드는 작업 정의를 등록한 사람을 나타냅니다. 정보 제공용으로 사용되며 정의 파일에서는 필요하지 않습니다.
ECS 배포를 위한 IAM 권한
•
ECS에 들어가는 Role에는 크게
◦
ECS를 위한 ECS, ECR 권한
◦
Cloudwatch
◦
Secret manager이 필요하다
•
IAM 역활이 필요
amazon-ecs-deploy-task-definition
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"RegisterTaskDefinition",
"Effect":"Allow",
"Action":[
"ecs:RegisterTaskDefinition"
],
"Resource":"*"
},
{
"Sid":"PassRolesInTaskDefinition",
"Effect":"Allow",
"Action":[
"iam:PassRole"
],
"Resource":[
"arn:aws:iam::<aws_account_id>:role/<task_definition_task_role_name>",
"arn:aws:iam::<aws_account_id>:role/<task_definition_task_execution_role_name>"
]
},
{
"Sid":"DeployService",
"Effect":"Allow",
"Action":[
"ecs:UpdateService",
"ecs:DescribeServices"
],
"Resource":[
"arn:aws:ecs:<region>:<aws_account_id>:service/<cluster_name>/<service_name>"
]
}
]
}
Python
복사
ECR 배포 사이클
•
ready → 신규 배포 → Primary → 기존 컨테이너 혹은 실패한 컨테이너 Draining
•
ECS와 연결된 로드밸런서에 등록된 타겟 그룹의 상태를 확인하게 된다
◦
새로운 타겟그룹의 healthy 여부 확인 후, draining 시킴
◦
구 버젼이 다운된 이후, 5분 정도 지나고 나서 배포가 완료가 됨
•
배포가 3분 정도 걸린다면, 위 draining 작업에서 5분 이상 걸림
•
그래서 총 배포가 최소 10분정도 걸리기 때문에 너무 오래걸리게 된다
◦
대상 그룹 설정에 들어가서 설정을 편집
◦
따라서 위의 Target deregistration management에서 draining 시간을 낮춰줄 수 있다.
◦
필자는 해당 속성을 60초로 변경했다