仕事ではコストを、プライベートでは悪玉コレステロール値を減らしたい、CTO室の岩本 (iwamot) です。
コスト削減を目的に、先日、あるRails 6アプリの基盤をIntel x86ベースのFargateからGraviton2ベースのFargateに替えました。
対応したことを簡単にまとめると、下記のようになります。
- CodeBuildでARM用Dockerイメージをビルドできるようにした
- CodeBuildビルド環境をLINUX_CONTAINERからARM_CONTAINERに替えた
- ExecJSのJavaScriptランタイムをmini_racerからNode.jsに替えた
- NokogiriをネイティブビルドするようBundlerを設定した
- CodeBuildビルド環境のAWS CLIを更新した
- FargateをGraviton2ベースに替えた
- ECSタスク定義を更新した
以下、もう少し詳しく書き残しておきます。
CodeBuildでARM用Dockerイメージをビルドできるようにした
CodeBuildビルド環境をLINUX_CONTAINERからARM_CONTAINERに替えた
DockerイメージのビルドにはCodeBuildを使っているので、そのビルド環境をLINUX_CONTAINERからARM_CONTAINERに替えました。
Terraformテンプレートの差分で示すと、下記のようになります。
resource "aws_codebuild_project" "this" { environment { - image = "aws/codebuild/amazonlinux2-x86_64-standard:4.0" - type = "LINUX_CONTAINER" + image = "aws/codebuild/amazonlinux2-aarch64-standard:2.0" + type = "ARM_CONTAINER"
ExecJSのJavaScriptランタイムをmini_racerからNode.jsに替えた
対応前は、ExecJSのJavaScriptランタイムとして、mini_racerが使われていました。
ただ、mini_racerの依存しているlibv8は、現状ではARMをサポートしていません。
そこで、Dockerイメージからmini_racer gemを削除し、代わりにNode.jsを追加しました。ExecJSがサポートしているJavaScriptランタイムのうち、慣れているものを選んだ形です。
NokogiriをネイティブビルドするようBundlerを設定した
プリコンパイル済みのNokogiriをaarch64-linuxで使うには glibc >= 2.29
が要件となります。
ただし今回は、プラットフォーム側のglibcを更新するのは難しいと考え、Nokogiriをネイティブビルドすることにしました。
具体的には、Dockerfileに下記のような分岐を加えています。
RUN if [[ $(arch) == "aarch64" ]]; then \ bundle config set force_ruby_platform true; \ fi
CodeBuildビルド環境のAWS CLIを更新した
ARM_CONTAINER (aws/codebuild/amazonlinux2-aarch64-standard:2.0) には、バージョン1.20.58と古いAWS CLIがインストールされています。
そのため、ARM_CONTAINERへの移行後に、ビルド処理の一部が失敗するようになりました。
この点については、buildspec.ymlを下記のように変更し、AWS CLIを更新することで解決しています。
pre_build:
on-failure: ABORT
commands:
+ - pip3 install awscli --upgrade --user
FargateをGraviton2ベースに替えた
ECSタスク定義を更新した
ARM用Dockerイメージさえビルドできれば、あとはFargateをGraviton2ベースに替えるだけです。
Terraformテンプレートの差分で示すと、下記のように1行加えるだけでした。
resource "aws_ecs_task_definition" "this" {
runtime_platform {
operating_system_family = "LINUX"
+ cpu_architecture = "ARM64"
}
おわりに
試行錯誤はしましたが、結果的にはそれぞれ数行の変更で済みました。今後はスムーズに対応できそうです。
目的のコスト削減効果は20%でした。これは単純に、Intel x86ベースのFargateより料金が20%安いためです。また、Graviton2はパフォーマンスも優れているため、アプリによっては、割り当てるvCPUやメモリを小さくすることで、さらにコストが抑えられます。
弊社には、Intel x86ベースのFargateで動いているアプリが他にもいくつかあるので、それらもGraviton2に替えていきたいと考えています。