*긴글 주의*
AWS ECR을 사용하게된 계기
이때까지 github action에서 docker hub로 docker image를 push/pull해왔습니다.
그러다가 pull에서 더이상 진행되지 않는 현상이 종종있었습니다.
아무래도 무료계정을 이용하다보니 월 200회 pull 제한에 걸려서 그런 것 같습니다.
현재 진행하고 있는 프로젝트는 배포가 빈번히 일어날 것이기 때문에 docker hub를 사용하기에 부적합했습니다.
그리고 public 레포지토리에 이미지를 올려놔서 보안상 문제가 있었습니다.
장점 및 단점
그래서 대안을 찾아보던 중, AWS에서 완전 관리형 컨테이너 레지스트리인 ECR (Elastic Container Registry)을 사용해서 CI/CD를 구축하는 방법을 알게되었습니다.
일단 장점은
1. 컨테이너 이미지 저장소를 직접 관리할 수 있다.
2. 이용 횟수에 제한이 없다.
3. 안정적으로 push/pull할 수 있다.
단점은
1. 적용 방법이 조금 복잡하다.
2. 비용이 든다.
AWS로 HTTPS 도메인을 설정해봤고, github action을 사용해본 경험이 있는 분이라면 충분히 할만 합니다.
비용
데이터 전송 비용은 2024년 8월 기준 다음과 같습니다.
- private 리포지토리에 모든 수신 비용은 무료입니다.
- 스토리지는 모든 종류의 리포지토리에 저장된 데이터의 경우에 GB/월당 0.10 USD입니다.
- 동일한 리전의 Amazon ECR 및 기타 서비스 사이에서 전송된 데이터(예: Amazon EC2, AWS Lambda, AWS App Runner 또는 AWS Fargate)는 무료입니다.
- 프리티어 계정은 1년간 private 리포지토리 저장공간 500MB를 무료로 이용할 수 있습니다.
- 기본적으로 public 리포지토리는 월 50GB의 무료 스토리지를 이용할 수 있습니다.
- AWS 계정이 아니면 매월 public 리포지토리에서 500GB의 데이터를 인터넷으로 무료로 전송할 수 있고, AWS 계정을 이용하면 매월 5TB의 데이터를 public 리포지토리에서 인터넷으로 무료로 전송할 수 있습니다.
- public 리포지토리에서 AWS 컴퓨팅리소스 간에는 무제한 대역폭을 무료로 사용할 수 있습니다.
private 리포지토리에서
모든 이미지들의 총 용량이 400MB이고,
30일 동안 이 모든 이미지를 매일 10번 push, 10번 pull한다면,
400 * 30 * 10(push) -> 120GB -> 12.00 USD가 대략적인 저장 비용입니다.
400 * 30 * 10(pull) -> 120GB ->15.12 USD가 대략적인 데이터 전송 비용입니다.
생각보다 만만찮은 비용인데, 다행히도 레포지토리 설정에서 Lifecycle Policy를 통해 저장 비용을 줄일 수 있습니다.
그리고 동일한 리전의 AWS 서비스(EC2, Lambda 등)로 데이터 전송하는 건 무료이므로, 리전마다 ECR을 만들면 데이터 전송 비용을 줄일 수 있을 것입니다.
적용방법
1. private ECR 리포지토리 만들기
이름만 설정하고 나머지는 기본값 그대로 만들어 줍니다.
2. IAM 사용자 생성하기
간단히 AmazonEC2ContainerRegistryFullAccess 정책을 검색해서 적용합니다.
또는 다음과 같이 입력해 최소 권한(private ecr repository push/pull) 정책을 적용할 수도 있습니다.
이때 Resource는 생성한 private 리포지토리의 ARN입니다. 아래 사진처럼 '요약' 메뉴에서 볼수 있습니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPushPull",
"Effect": "Allow",
"Action": [
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:CompleteLayerUpload",
"ecr:GetDownloadUrlForLayer",
"ecr:InitiateLayerUpload",
"ecr:PutImage",
"ecr:UploadLayerPart"
],
"Resource": "arn:aws:ecr:us-east-1:123456789012:repository/my-ecr-repo"
}
]
}
정책을 설정하고 사용자를 만들었으면,
해당 IAM 사용자의 '보안자격증명' 탭에서 '외부 애플리케이션' 액세스키를 만들어줍니다.
csv 파일 받는 걸 추천합니다.
3. EC2에 AWS CLI 설치하기
ECR을 사용하려면 AWS CLI가 있어야합니다.
아래 AWS 공식문서를 따라하면 됩니다. 저는 ubuntu 환경으로 설치했습니다.
https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html
최신 버전의 AWS CLI설치 또는 업데이트 - AWS Command Line Interface
이전 버전에서 업데이트하는 경우 unzip 명령을 실행하면 기존 파일을 덮어쓸지 묻는 메시지가 표시됩니다. 스크립트 자동화와 같은 경우에 이러한 프롬프트를 건너뛰려면 unzip에 대한 -u 업데이
docs.aws.amazon.com
4. aws configure 설정
EC2에 접속해서 AWS CLI 설정을 해줍니다.
다음 명령어를 치면
aws configure
순서대로 Access key ID, Secret access key, region을 입력하는 커맨드가 뜹니다.
IAM 사용자를 생성하면서 발급한 key들을 입력해주면 됩니다.
region은 ECR 리포지토리를 생성한 region을 입력해줍니다. 서울은 ap-northeast-2입니다.
5. 이미지 수명주기 설정
Lifecycle Policy를 사용해서 비용을 아낄 수 있습니다.
리포지토리를 선택하고 작업에서 수명 주기 정책을 클릭합니다.
규칙 생성을 클릭합니다.
다음과 같이 설정하면 모든 이미지마다 최근 10개만 유지됩니다.
매치 범위로 '이미지가 푸시된 후'를 선택하면 며칠동안 저장할지 설정할 수 있습니다.
이미지 태그를 지정하면 특정 이미지들에만 Lifecycle policy를 적용할 수 있습니다.
6. github action workflow 작성하기
- AWS_REGION 환경변수를 설정하면 ECR public 리포지토리를 사용할 수 없습니다.
- ECR public은 us-east-1에서만 로그인할 수 있습니다. 즉, GetAuthorizationToken 명령이 us-east-1만 지원합니다.
- Access Key와 Secret Key대신 github action 공식 문서에서 추천하는 OIDC를 사용하여 AWS에 로그인하겠습니다.
6-1. 자격 증명 공급자(Identity providers) 생성하기
AWS IAM의 자격 증명 공급자 항목에 들어가서 자격 증명 공급자를 만들어줍니다.
공급자 유형은 OpenID Connect를 선택합니다.
공급자 URL(Provider URL)은 https://token.actions.githubusercontent.com
대상(Audience)은 sts.amazonaws.com
입니다.
6-2. 정책 생성하기
github action에 적용할 IAM 정책을 생성합니다. 정책 편집기에서 JSON을 클릭하고 아래 내용을 붙여넣습니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:CompleteLayerUpload",
"ecr:DescribeImages",
"ecr:GetAuthorizationToken",
"ecr:DescribeRepositories",
"ecr:UploadLayerPart",
"ecr:ListImages",
"ecr:InitiateLayerUpload",
"ecr:BatchCheckLayerAvailability",
"ecr:GetRepositoryPolicy",
"ecr:PutImage"
],
"Resource": "*"
}
]
}
6-3. 역할 생성 및 신뢰 관계 작성하기
github action에서 사용할 IAM 역할을 생성합니다.
웹 자격 증명(web identity)를 선택하고 아까 추가했던 자격 증명 공급자를 선택합니다.
Audience(대상)도 자격 증명 공급자를 만들때 넣은 것과 같은 것을 선택합니다.
organization에는 적용할 organization이 있다면 그 이름을 적거나
개인 레포지토리에서 사용할 거라면 본인 github 닉네임을 적습니다.
이 IAM 역할을 사용할 github repository, branch를 적어서 세세하게 설정할 수 있습니다.
나머지는 그대로 두고 역할을 생성합니다.
다음을 클릭하면 역할 이름을 정하고 신뢰 정책을 작성합니다.
아래처럼 기본적으로 적혀있긴 합니다.
하지만 우리는 아래와 같이 작성해야합니다.
Federated는 그대로 둡니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:ddolboghi/*:*"
},
"ForAllValues:StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:iss": "https://token.actions.githubusercontent.com"
}
}
}
]
}
이제 생성해주면 OIDC를 사용하기 위한 밑작업은 다끝났습니다.
6-4. github action workflow 작성하기
이제 마지막입니다. 여기서는 필수적인 것만 작성하겠습니다.
나머지는 본인의 CI/CD 전략에 맞게 작성하면 됩니다.
아래는 AWS ECR에 OIDC로 로그인하고 ECR repository로 docker image를 push하는 작업입니다.
env:
AWS_REGION: ap-northeast-2
ECR_REPOSITORY: my-ecr-repository
IMAGE_TAG: my-image-tag
jobs:
build-and-push-image:
runs-on: ubuntu-latest
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::1234567890:role/example-role
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and tag image to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
docker buildx build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f ./Dockerfile .
pull 받을때는 다음과 같습니다.
이때도 Configure AWS credentials, Login to Amazon ECR step 순서대로 똑같이 작성해야합니다.
- name: Pull image from Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
sudo docker pull $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
참고
https://github.com/aws-actions/amazon-ecr-login?tab=readme-ov-file#building-and-pushing-an-image
GitHub - aws-actions/amazon-ecr-login: Logs into Amazon ECR with the local Docker client.
Logs into Amazon ECR with the local Docker client. - aws-actions/amazon-ecr-login
github.com
https://docs.aws.amazon.com/ko_kr/AmazonECR/latest/userguide/security_iam_service-with-iam.html
Amazon Elastic Container Registry가 IAM과 작동하는 방식 - Amazon ECR
Amazon ECR 리포지토리 정책에서 정책 요소 Sid는 IAM 정책에서 지원되지 않는 추가 문자 및 공백을 지원합니다.
docs.aws.amazon.com
Amazon ECR 수명 주기 정책을 통한 컨테이너 이미지 자동 삭제 기능 출시 | Amazon Web Services
오늘부터 Amazon EC2 Container Registry(Amazon ECR)의 일부인 수명 주기 정책을 사용하여 오래되거나 사용하지 않는 이미지를 자동으로 제거함으로써 컨테이너 이미지 리포지토리를 깔끔하게 정리할 수
aws.amazon.com
Use OpenID Connect to Authenticate AWS Account in GitHub Actions
In my recent personal project, I decided to use GitHub Actions workflow to push my docker image to AWS Elastic Container Registry as part…
medium.com
# [CI/CD] Github Action - AWS IAM Role 이용해 이미지를 ECR에 올리기
OIDC를 적용한 Role을 만들어 Github Action으로 ECR 이미지 배포하기
velog.io