매일 업데이트
2022-09-07 13:12 10 min

AWS ECR 태그가 지정되지 않은 오래된 이미지를 삭제하는 방법은 무엇입니까?

Amazon ECR 컨테이너 이미지 관리 및 최적화

Amazon ECR(Elastic Container Registry)은 Amazon EKS(Elastic Kubernetes Service), Amazon ECS(Elastic Container Service), AWS Lambda와 원활하게 연동되어 개발부터 프로덕션 환경까지 컨테이너 워크플로를 간소화합니다. ECR은 확장성과 고가용성을 갖춘 인프라에서 컨테이너 이미지를 호스팅하므로 애플리케이션을 안정적으로 배포할 수 있도록 지원합니다. 하지만, 최적의 환경을 유지하기 위해 오래되거나 태그가 지정되지 않은 이미지를 주기적으로 정리하는 것이 중요합니다.

현대적인 애플리케이션은 주로 마이크로서비스 형태로 개발됩니다. 마이크로서비스 아키텍처는 애플리케이션의 모든 코드와 종속성을 컨테이너에 패키징하여 모든 컴퓨팅 환경에서 빠르고 안정적으로 실행될 수 있도록 합니다. 컨테이너는 휴대성, 작은 크기, 사용 편의성 덕분에 현대 애플리케이션 배포의 표준 방법으로 자리 잡았습니다.

컨테이너는 이미지라고 하는 읽기 전용 템플릿을 기반으로 합니다. 이러한 이미지는 권한이 있는 시스템에서 접근할 수 있도록 저장소에 보관해야 합니다. 바로 이 지점에서 컨테이너 레지스트리의 필요성이 대두됩니다. 과거에는 Docker Hub를 주로 사용했지만, AWS 클라우드 서비스를 이용하고 있다면 AWS ECR을 이미 사용하고 있을 가능성이 높습니다.

AWS ECR은 AWS에서 제공하는 완전 관리형 컨테이너 레지스트리 서비스로, 고성능 호스팅을 제공하여 퍼블릭 및 프라이빗 레포지토리 형태로 애플리케이션 이미지와 아티팩트를 관리하고 배포할 수 있게 해줍니다. 수많은 AWS 기반 애플리케이션들이 매일 ECR 레포지토리로 수백만 개의 이미지와 아티팩트를 저장하고 가져옵니다.

본 글에서는 사용하지 않거나 오래된 AWS ECR 이미지를 삭제하여 ECR 레포지토리를 효율적으로 유지하는 방법에 대해 알아봅니다.

오래된 이미지 삭제의 필요성

ECR 레포지토리 관리가 필요한 가장 큰 이유는 개발 환경의 위생 관리입니다. 대개 배포된 지 10개 이상의 이미지나 아티팩트는 유지할 이유가 없습니다. 롤백이 자주 발생하긴 하지만, 5개 이상의 아티팩트를 이전 상태로 되돌리는 경우는 드물기 때문입니다.

일반적으로 5년 이상 된 이미지와 아티팩트는 더 이상 쓸모가 없습니다. 물론 조직의 정책에 따라 달라질 수 있지만, 이러한 오래된 이미지를 보관하는 것은 권장하지 않습니다.

업계 표준으로, 태그는 가장 최신의 안정적인 이미지 또는 최근 몇 개의 이미지를 지정하는 데 사용됩니다. 소프트웨어 개발 과정에서 이미지는 빠르게 생성되고 새로운 이미지에 태그가 지정되면서 이전 이미지는 태그가 지정되지 않은 채로 남아 쓸모없게 됩니다.

이러한 이미지/아티팩트들이 차지하는 공간은 스토리지 비용으로 이어집니다. AWS ECR의 스토리지 요금은 "프라이빗 또는 퍼블릭 레포지토리에 저장된 데이터의 경우 GB당 월 $0.10"입니다.

이 금액이 작아 보일 수 있지만, 장기간 동안 많은 이미지를 저장하면 AWS 청구서에 상당한 비용이 추가될 수 있습니다. 따라서 불필요한 오래된 이미지들을 ECR에서 삭제하는 것이 좋습니다. 왜 불필요한 이미지들을 유지하고 비용을 지불해야 할까요?

수동으로 AWS ECR 이미지 삭제하기

방법 1: GUI를 이용한 삭제

1단계: AWS 계정에 로그인한 후 삭제하려는 이미지가 있는 리포지토리로 이동합니다.

2단계: 해당 리포지토리에서 가장 최신 버전의 이미지에 태그가 지정된 것을 확인할 수 있습니다. 그 외 다른 태그들은 태그가 지정되지 않은 이미지일 가능성이 높습니다. 삭제하려는 이미지를 선택하고 삭제 버튼을 클릭합니다.

3단계: 삭제를 확인합니다.

방법 2: CLI를 이용한 삭제

CLI를 사용하여 이미지를 삭제하려면, 먼저 해당 AWS 계정에 접근할 수 있는 IAM 액세스 키와 리포지토리 접근 권한을 설정해야 합니다. 이미 구성되어 있다면, AWS 구성 기본 안내서를 참고하여 진행할 수 있습니다.

AWS CLI가 구성되어 있는지 확실하지 않다면, 다음 명령어를 사용하여 확인할 수 있습니다.

aws sts get-caller-identity

AWS CLI가 정상적으로 작동하는 것을 확인했다면, 다음 명령어를 사용하여 태그가 지정되지 않은 ECR 이미지를 삭제할 수 있습니다.

aws ecr batch-delete-image --repository-name test-ecr-policy --image-ids imageTag=custom-image-6

이 명령은 GUI에서와 마찬가지로 test-ecr-policy 리포지토리에서 custom-image-6 태그가 지정된 이미지를 삭제합니다.

방법 3: 스크립트를 이용한 삭제

스크립트를 이용하여 삭제하는 경우, 시스템에 AWS 액세스 키가 구성되어 있어야 합니다.

다음은 태그가 지정되지 않은 이미지를 삭제하는 스크립트입니다.

import boto3

client = boto3.client('ecr')

response = client.list_images(repositoryName="test-ecr-policy")

untaggedImageList = [image for image in response['imageIds'] if image['imageTag'] == 'custom-build-4']

response2 = client.batch_delete_image(repositoryName="aws-test-ecrpolicy", imageIds=untaggedImageList)

print(response2)

스크립트의 결과는 삭제된 이미지 ID 목록과 오류가 발생한 경우 해당 오류 메시지를 출력합니다.

ECR 이미지 삭제 예약하기

DevOps 엔지니어이거나 AWS ECR을 자주 관리하는 사용자라면 이러한 이미지들을 수동으로 삭제하는 것이 얼마나 번거로운 일인지 잘 알고 있을 것입니다. 스크립트나 명령어를 사용하면 작업이 훨씬 수월해지지만, 이미지 삭제를 자동으로 처리하는 기능이 있다면 훨씬 편리할 것입니다.

다행히 AWS ECR에서는 이미지 수명 주기 정책을 제공하여 이러한 이미지를 자동으로 삭제할 수 있도록 지원합니다. 이제 수명 주기 정책을 설정하는 방법을 알아보겠습니다.

방법 1: GUI를 이용한 수명 주기 정책 설정

1단계: 수명 주기 정책을 설정하려는 리포지토리로 이동합니다. 왼쪽 패널에서 "수명 주기 정책" 메뉴를 찾을 수 있습니다. 클릭하여 정책 설정을 시작합니다.

2단계: "수명 주기 정책" 메뉴를 클릭한 후 첫 번째 규칙을 생성합니다.

3단계: ECR에서는 두 가지 조건으로 이미지를 삭제할 수 있습니다. 하나는 이미지가 특정 날짜보다 오래된 경우, 또 다른 하나는 태그 유무와 상관없이 특정 기간 동안만 유지하는 경우입니다.

예를 들어, 태그가 없는 이미지가 하루 이상 경과했거나 태그가 없는 이미지 수가 1개를 초과하는 경우 삭제하도록 설정할 수 있습니다. 본인의 사용 사례에 맞게 설정하면 됩니다. 이 숫자는 원하는 대로 늘릴 수 있으며, 저장하면 수명 주기 규칙이 적용됩니다.

방법 2: CLI를 이용한 수명 주기 정책 설정

수명 주기 정책을 설정하는 AWS ECR CLI 명령어는 "put-lifecycle-policy"입니다. 사용하려면 정책 조건을 명시하는 JSON 파일을 먼저 만들어야 합니다. 파일 이름은 policy.json 또는 원하는 이름으로 지정할 수 있습니다.

정책 요소를 살펴보겠습니다.

rulePriority (Type: integer, Required: yes):

낮은 우선순위에서 높은 우선순위 순으로 규칙을 설정합니다. 규칙 우선순위가 1인 수명 주기 정책 규칙이 먼저 적용되고 2, 3 순으로 적용됩니다. 각 규칙은 고유한 우선순위 값을 가져야 합니다. 연속적인 값이 필요하지 않지만, 태그가 있는 규칙이 가장 높은 우선순위를 가져야 하며 마지막에 검토되어야 합니다.

description (Type: string, Required: no):

수명 주기 정책의 규칙에 대한 설명을 입력합니다.

tagStatus (Type: string, Required: yes):

추가된 수명 주기 정책 규칙이 이미지 태그를 지정하는지 확인합니다. 값은 태그 지정됨(tagged), 태그 지정되지 않음(untagged), 아무 값(any)이 가능합니다. 아무 값도 지정하지 않으면 모든 이미지가 평가됩니다. 태그를 지정하려면 tagPrefixList 값이 필요합니다. 태그가 지정되지 않은 경우에는 tagPrefixList를 생략해야 합니다.

tagPrefixList (Type: list[string], Required: yes, only if tagStatus is set to tagged):

tagStatus가 'tagged'로 설정된 경우, 수명 주기 정책에서 쉼표로 구분된 이미지 태그 접두사 목록이 필요합니다. 예를 들어, 태그 접두사 prod를 사용하면 prod, prod1, prod2 등으로 표시된 모든 이미지를 선택할 수 있습니다. 여러 개의 태그는 모든 태그가 일치하는 이미지만 선택합니다.

countType (Type: string, Required: yes):

countType이 'imageCountMoreThan'인 경우, 저장소의 이미지 수를 제한하기 위해 countNumber를 지정합니다.

countType이 'sinceImagePushed'인 경우, countUnit 및 countNumber를 지정하여 저장소의 이미지 보관 기간을 제한합니다.

countUnit (Type: string, Required: yes, only if countType is set to sinceImagePushed):

countType이 'sinceImagePushed'인 경우에만 카운트 단위를 지정합니다. 그렇지 않으면 오류가 발생합니다.

countNumber (Type: integer, Required: yes):

양의 정수만 사용 가능(0은 허용되지 않는 값). countType이 'imageCountMoreThan'인 경우, 값은 보관할 최대 사진 수입니다. countType으로 'sinceImagePushed'를 사용하면 최대 이미지 수명이 결정됩니다.

 type (Type: string, Required: yes):

작업 유형을 선택합니다. 사용 가능한 값은 'expire'입니다.

다음은 policy.json 파일 예시입니다.

{

"rules": [

{

"rulePriority": 1,

"description": "10일 이상 된 이미지 삭제",

"selection": {

"tagStatus": "untagged",

"countType": "sinceImagePushed",

"countUnit": "days",

"countNumber": 14

},

"action": {

"type": "expire"

}

}

]

}

이 설정은 조직의 요구 사항에 따라 변경할 수 있습니다. 'sinceImagePushed'는 'imageCountMoreThan'으로 대체될 수 있습니다.

정책을 설정하는 CLI 명령어는 다음과 같습니다.

aws ecr put-lifecycle-policy --repository-name "test-ecr-polict" --lifecycle-policy-text "file://policy.json"

방법 3: 스크립트를 이용한 수명 주기 정책 설정

boto3 명령을 사용하여 정책을 설정할 수 있습니다. 같은 policy.json 파일을 사용하여 설정할 수 있습니다. 아래는 사용된 코드 스니펫입니다.

import boto3

client = boto3.client('ecr')

response = client.put_lifecycle_policy(
registryId='PODES12342',
repositoryName="test-ecr-policy",
lifecyclePolicyText="plicy.json"
)

print(response)

여러 ECR 리포지토리에 단일 정책을 적용하려면 어떻게 해야 할까요?

여러 리포지토리에 동일한 정책을 적용하는 방법에 대한 질문을 자주 받습니다.

수동으로 정책을 설정하는 것은 반복적이고 지루한 작업입니다.

다음은 프로덕션 환경에서 100개 이상의 리포지토리에 정책을 적용하는 데 사용할 수 있는 코드 스니펫입니다.

from boto3 import Session,client

from os import getenv
AWS_ACCESS_KEY_ID = getenv("ACCESSKEY")


AWS_SECRET_ACCESS_KEY = getenv("SECRETKEY")
session = Session(
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY
)

client = client('ecr')

response = client.describe_repositories()

repositories = response['repositories']

globalLifecyclePolicy = 'put your policy here’’

for repo in repositories:

repoName = repo['repositoryName']

client.put_lifecycle_policy( repositoryName = repoName,lifecyclePolicyText = globalLifecyclePolicy)

결론

ECR 수명 주기 정책을 사용하면 지정된 조건에 따라 오래된 이미지를 쉽게 삭제할 수 있습니다. AWS는 수명 주기 정책에 대한 광범위한 문서와 샘플을 제공합니다. 또한 이미지 업로드 날짜와 같은 다른 기준으로 태그가 지정된 이미지에 대한 정책을 설정할 수도 있습니다.

AWS 학습을 발전시키기 위해 추가적으로 AWS 주요 용어를 살펴볼 수 있습니다.

저자
Korea

기술 트렌드와 실용적인 팁을 전하는 लेखक입니다.