こんにちは。しげぞうです。
クラウドサービスを活用することで、プロダクトのサービスレベル向上や運用保守作業の負荷軽減など、様々なGoodを提供してくれますが、利用料金という面で私たちを苦しめてきます。最近は円安の影響もあってクラウド運用コストが高騰し、苦労している方も多いのではないでしょうか。
先日、私の所属しているチームでもクラウド運用の見直しを行いまして、
その時に実施した比較的に簡単に行えるAmazonECR(Dockerイメージを保存するレジストリサービス)のコスト最適化について紹介します。
ECRの課金の仕組み
ECRの課金はストレージ使用量とデータ転送量に対して発生しますが、基本的にストレージ使用量に関する課金がほとんどになると思います。
(別リージョンのECRにアクセスするといった運用がある場合、データ転送量に対する課金も発生します)
ストレージ使用量は、その月にリポジトリに保存されていたDockerイメージのサイズ合計(GB/月)で課金されます。
※パブリックリポジトリは月間50GBの無料枠あり。
例えば、ある実行環境を構成する5GBのDockerイメージを5環境分、東京リージョン(ap-northeast-1)のECRに保存している場合、
毎月2.5USD(1ドル=140円とすると、約350円)の課金が発生します。
計算式
5GB × 5環境 × 1ヶ月 × 0.10 USD/GB/月 = 2.5USD
上記例の場合だとそこまで大きな課金ではありませんが、ECRにおけるイメージ管理の特徴として、
新しいイメージがリポジトリにPushされても、過去の古いイメージは削除されずに残り続ける(別バージョンとして管理される) というものがあり、定期的にDockerイメージをリビルドしてECRにPushするような運用をしていると、ビルドの度にECRのストレージ使用量が増加するため、その都度ECRの課金額が増加してしまいます。
私たちも下記のような運用をしていて過去の使っていないイメージファイルが残りつづけ、塵積で課金額が上昇していました。。
コスト最適化の方法
ECRのコスト最適化は、下記の作業を順番に進めていくといいと思います。
①ECRに保存されている不要なイメージを手動で削除する
②不要なイメージを定期的に自動削除するよう、ECRのライフサイクルポリシーを設定する
③Dockerイメージ自体のイメージサイズ削減を検討する
①②はコスト改善作業で重要視されるタイムパフォーマンスが高いため、今すぐにでも実践いただく価値ありです!
①ECRに保存されている不要なイメージを手動で削除する
いわゆる暫定対応になります。
ターゲットとなるAWSアカウントのマネジメントコンソールにログインし、ECRの管理コンソールに移動します。
左メニューの「Repository」を選択し、不要なイメージを削除したいリポジトリを一覧から選択します。
下記の例だと、リポジトリに6つのイメージ(バージョン)が保存されています。
不要なイメージ(バージョン)を削除する場合は、削除したいバージョンにチェックを入れて、画面右上の「削除」にて消すことができます。
②不要なイメージを定期的に自動削除するよう、ECRのライフサイクルポリシーを設定する
作業①に対して、こちらは恒久対応になります。
ライフサイクルポリシーは対象のリポジトリを選択後、左メニューの「Lifecycle Policy」から設定できます。
ライフサイクルポリシーでは、以下の2点を設定します。
- ポリシー設定(削除イメージを決定するための判定基準)
- ポリシーの優先順位(複数のポリシーが設定された場合に、ポリシーが適応される順番を指定)
たとえば、「latestタグがついていないイメージを2つ残して、それ以外はすべて削除する」ようなポリシーを設定する場合は、次のように設定します。
③Dockerイメージ自体のイメージサイズ削減を検討する
そもそものイメージファイルのサイズを減らすことも立派なコスト改善の一歩です。
イメージファイルの雛形にあたるDockerfileの書き方をちょこっと変えることで実現できます。
レイヤー数の削減
FROM openjdk:11
ENV LANG C.UTF-8
# △
# 1行単位でレイヤー(イメージ作成の手順)が構成されるため、イメージサイズが肥大する
#RUN apt-get update -y
#RUN apt-get upgrade -y
#RUN apt-get install -y wget bsdtar
# ◎
# &&でコマンドを連結することで、レイヤー数を減らせる
RUN apt-get update -y \
&& apt-get upgrade -y \
&& apt-get install -y wget bsdtar
RUN mkdir /workdir && cd /workdir
WORKDIR /workdir
RUN wget -qO- https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/3.3.1/gatling-charts-highcharts-bundle-3.3.1-bundle.zip \
| bsdtar -xvf-
ENV GATLING_HOME=/workdir/gatling-charts-highcharts-bundle-3.3.1
RUN ln -s /workdir/gatling-charts-highcharts-bun
マルチステージビルド
上記のイメージは、負荷試験テストツール「gatling」の実行環境イメージですが、gatlingアプリケーションをインストールするためだけに、apt-getでwgetとbsdtarをインストールしてます。より軽量なイメージを目指す場合、マルチステージビルド(ビルドの手順を分離し、最低限のリソースのみをイメージに含めるようにビルドする仕組み)も非常に有用になります。
# 一時的にビルドするコンテナイメージ(A)
FROM openjdk:11 AS tmp
RUN apt-get update -y \
&& apt-get upgrade -y \
&& apt-get install -y wget bsdtar
RUN wget -qO- https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/3.3.1/gatling-charts-highcharts-bundle-3.3.1-bundle.zip \
| bsdtar -xvf-
# 最終的にビルドされるコンテナイメージ(B)
FROM openjdk:11
ENV LANG C.UTF-8
RUN mkdir /workdir && cd /workdir
WORKDIR /workdir
# Aでビルドしたコンテナを参照し、必要なリソースをコピーする
# Bのビルド完了時にAは破棄される
# → 各モジュールのインストールやレイヤー数が減り、イメージが軽量になる
COPY --from=tmp /gatling-charts-highcharts-bundle-3.3.1 /workdir/gatling-charts-highcharts-bundle-3.3.1
ENV GATLING_HOME=/workdir/gatling-charts-highcharts-bundle-3.3.1
RUN ln -s /workdir/gatling-charts-highcharts-bun
最後に
今すぐにでも実施できるECRのコスト最適化方法を紹介しました。
マネージドサービスは開発者や運用者の作業負荷が減るメリットがありますが、サービス/リソースの利用状況を把握しづらいというデメリットもあります。
サーバーの稼働状況だったり、毎月の請求書情報などは、定期的に収集し見直ししていく必要があると痛感しました。。
今回の投稿が誰かにとってNice!な記事になってくれれば、幸いです。






