これはなに?
AWSのECSを使う前提で、ECRを利用しています。
こちらはDockerイメージのリポジトリで、CIやパイプラインで定期的にビルドしたイメージをpush & 登録する設定を試しています。
ここでは、ECSについてはまだ触れません。
(ECSを起動すると思いがけず課金が発生するので、個人枠では慎重に進めています....)
やりたいこと
さて、ECRもAWSの1年間の無償枠の中の1つとして利用ができます。
ただし、サイズ制限があり、リポジトリの利用サイズが0.5GBを越えてしまうと、課金対象になってしまいます。
今実験しているDockerのイメージは、サイズが450MB程度...。
CIでの定期的なpushは実施できそうなので、更新した単位でイメージの登録はできますが、2世代分は保持はできません。
ということで、やりたいのはこちら。
- 最新の1つを残して、うまく削除できるようにしたい
注意点
スクリーンショットや設定方法は変更される可能性があります。
また、実際にちゃんと消えているか、課金状況はどうかというのは、こまめに確認することをお勧めします...。
方法: ライフサイクルの設定
設定にあたっては、こちらの記事を参考にさせていただきました。
-
Amazon ECR ライフサイクルポリシー / ライフサイクルポリシーの作成
(AWS公式) - ECRのライフサイクルポリシー設定によるリポジトリ容量の節約 (Classmethod DevelopersIO)
設定画面
「最新の1つを残して」を条件にしたので、「次の数値を超えるイメージ数」に1を設定。さらに、タグ付けの有無は問わずに指定しています。
適用の結果
リポジトリに複数イメージが溜まった状態で、テストのポリシーを実行すると、該当するイメージがあれば以下のように表示されます。
実際には、新しいイメージがプッシュされた直後に削除が発生するのではなく、削除フラグ的なものが設定された上で、2〜3時間くらい経ってから削除になっています。
Terraformで設定する
コンソールでの設定がうまく行ったので、設定をTerraform側に落とし込んでみます。
ECR作成やライフサイクルポリシーの設定も、リソースとして定義ができるので、terraform importをしてから、以下のような形で書き出しています。
- ECRのリポジトリ名は akiko/redmine_banner
- メンテナ&イメージ名的に / が使えるので、あえてこうしてみる
- ECRのリポジトリ作成後に、
aws_ecr_lifecycle_policy
で、ポリシーを設定 - 対象は
repository =
で設定します
resource "aws_ecr_repository" "akiko_redmine_banner" {
name = "akiko/redmine_banner"
}
resource "aws_ecr_lifecycle_policy" "akiko_redmine_banner_policy" {
policy = jsonencode(
{
rules = [
{
action = {
type = "expire"
}
description = "最新の1つを残してイメージを削除する"
rulePriority = 1
selection = {
countNumber = 1
countType = "imageCountMoreThan"
tagStatus = "any"
}
},
]
}
)
repository = "${aws_ecr_repository.akiko_redmine_banner.name}"
}
補足:AWSからのアラート
課金のアラームを設定しているので、ECRに関しても警告メッセージが届きました。抜粋ですがこんな感じ。
補足:CircleCIからのイメージのビルドと登録
以下は抜粋ですが、CircleCIからaws-cliを使ってイメージのビルドとECRへの登録を行う部分です。
- CircleCIのAWS ECR用のOrbsを使ってみています
- 基本的にはjobsのところで細かいスクリプト処理を記載したりするのですが、Orbsを使っている場合は、環境変数と呼び出したい処理の名前を記載するぐらいでOK
- 以下の例だとbuildではソースのチェックアウトしかしてません
個人的には、CodePipelone & CodeBuildで同じ処理をするよりは、手元でcliを操作する感覚に近いので、こちらのほうが好きかも...です。
orbs:
aws-ecr: circleci/aws-ecr@6.2.0
version: 2.1
jobs:
build:
docker:
# specify the version you desire here (ruby 2.4.x)
- image: circleci/ruby:2.5-browsers-legacy
steps:
- checkout
workflows:
build_test_push:
jobs:
- build:
filters:
branches:
ignore:
- /ignore-build-.*/
- master
- aws-ecr/build-and-push-image:
account-url: AWS_ECR_ACCOUNT_URL
aws-access-key-id: AWS_ACCESS_KEY_ID
aws-secret-access-key: AWS_SECRET_ACCESS_KEY
create-repo: true
dockerfile: Dockerfile
path: .
region: AWS_REGION
repo: akiko/redmine_banner
extra-build-args: '--build-arg COMMIT=$CIRCLE_SHA1 --build-arg=BRANCH=$CIRCLE_BRANCH'
requires:
- build
filters:
branches:
only:
- ecs-trial