AWS ECR 조건삭제 스크립트 작성하기

이언철·2022년 9월 15일
0

AWS

목록 보기
2/14

ECR에 계속 쌓여가는 이미지 효율적으로 관리하기

단 10분의 투자로 효율적인 이미지 레포지토리 관리를 할 수 있습니다.

  1. 특정 ECR의 잦은 push로 인해 레포지토리에 적재된 이미지의 개수가 1000건이 넘어가는 일이 발생했다.
  2. ECR에 적재되는 이미지의 크기만큼 스토리지 비용이 발생 할 것이고, 이미지를 관리함에 있어서 불편함이 발생한다.
  3. 또한 AWS API의 조회 건당 최대 1000건으로 추가적인 조회 요청이 불가피하게 발생하게 된다.

이를 개선하기 위해 실제 운영환경에 사용되는 이미지의 네이밍을 점검하고, 운영환경에 사용되지 않는 이미지들의 최대 유지기간을 강제하여 효율적인 ECR관리를 할 수 있도록 한다.


우선, AWS의 ECR은 "수명 주기 정책 규칙" 을 생성할 수 있다.

"수명 주기 정책 규칙" 에서 선택 할 수 있는 규칙은 다음과 같다.
1. 태그가 지정된 이미지
2. 태그가 지정되지 않은 이미지
3. 전체

하지만 운영환경에서 사용되는 네이밍을 제외한 특정 태그를 가지지 않은 항목만 지우고 싶을 경우 "수명 주기 정책 규칙" 을 사용 할 수 없다.

imageTag1: ecr_v1.0.0_rc
imageTag2: ecr_v1.0.1_rc
imageTag3: ecr_v1.0.1

위의 예시에서 _rc를 포함하지 않는 이미지를 지우기 위해 AWS lambda를 활용하고자 한다.

  1. ecr-images-lifecycle라는 람다 함수를 생성한다.
  • 본인의 language 영역에 맞게 런타임 환경을 설정한다. (Node.js로 작성)
  1. 관리하고자 하는 ECR목록과 이미지의 최대 유지기간을 환경변수로 설정한다.

  2. 람다 코드를 작성한다. (아래의 코드처럼 간단하게 작성 할 수 있다.)

const AWS = require('aws-sdk')
const ECR = new AWS.ECR();
const images = process.env.IMAGES
const condition = process.env.CONDITION

exports.handler = (event, context, callback) => {
    images.split(',').forEach(image => {
        let params = {
            repositoryName: image,
            maxResults: 1000
        }
        ECR.describeImages(params, (err, res) => {
            if (err) {
                console.log(image + ' get images failed')
                throw err
            } else {
                const rcFilteringDetails = res.imageDetails.filter(i => !i.imageTags[0].includes('_rc') && !i.imageTags[0].includes('NONE') && !i.imageTags[0].includes('latest'))
                const andLatest14DayFiance = rcFilteringDetails.filter(i => new Date(i.imagePushedAt).setDate(new Date(i.imagePushedAt).getDate() + Number(condition)) < new Date())
                andLatest14DayFiance.division(100).forEach(deletedList => {
                    const imageIds = []
                    deletedList.forEach(i => imageIds.push({imageTag: i.imageTags[0]}))
                    if (imageIds.length > 0) {
                        ECR.batchDeleteImage({repositoryName: image, imageIds}, (err, res) => {
                            if (err) {
                                console.log(image + ' old images delete failed')
                                throw err
                            } else {
                                console.log(image + ' old images deleted')
                            }
                        })
                    }
                })
            }
        })
    })
    return callback(undefined, 200)
};

Array.prototype.division = function (n) {
    var arr = this
    var len = arr.length
    var cnt = Math.floor(len / n)
    var tmp = []

    for (var i = 0; i <= cnt; i++) {
        tmp.push(arr.splice(0, n))
    }

    return tmp
}
  • 이미지 삭제 스케줄링에 에러가 발생하는게 큰 의미는 없으므로 간단하게 로그만 찍도록 설정하였다.
  1. 작성한 코드가 정상적으로 작동하는지 테스트한다.
Test Event Name
ecr-images

Response
200

Function Logs
START RequestId: XXX Version: $LATEST
YYYY-MM-ddTHH:mm:ss	XXX	INFO	ecr1 old images deleted
END RequestId: XXX
REPORT RequestId: XXXDuration: 133.60 ms	Billed Duration: 134 ms	Memory Size: 128 MB	Max Memory Used: 81 MB	Init Duration: 21.21 ms

Request ID
XXX
  1. 테스트가 정상적으로 완료되었고, 이미지가 삭제된 것을 확인했다면 마지막으로 트리거를 설정한다.

설정 완료 후 모니터링을 통해 지정된 시간에 람다식이 정상적으로 동작하는지 확인한다.

profile
Soomgo, DevOps

0개의 댓글