はじめに
2021年5月に発表された「AWS App Runner」がどんなものか確認してみました。
概要
AWS App Runnerとは
https://aws.amazon.com/jp/apprunner/ ※以下引用
AWS App Runner は、コンテナ化されたウェブアプリケーションや API を開発者が簡単かつ迅速にデプロイできるフルマネージド型サービスです。大規模に、しかも事前のインフラ経験を必要とせずにデプロイすることができます。ソースコードからでも、コンテナイメージからでも始められます。App Runner がウェブアプリケーションを自動的にビルドおよびデプロイし、暗号化しつつトラフィックのロードバランスを実行します。また App Runner は、トラフィックのニーズに応じて自動的にスケールアップまたはスケールダウンします。App Runner を使用すれば、サーバーやスケーリングについて煩わされることもなく、アプリケーションに集中できる時間が増えます。
と書かれています。
従来の方法だと、例えばFargateでコンテナ環境を稼働させるためにはVPC、ALB、ECS、Fargateといった各サービスの設定を個別に行う必要がありました。
また自動デプロイを実現する為にはCodebuildやソースリポジトリ、コンテナレジストリと繋ぐパイプラインも必要です。従来必要だったそれら各種サービスの個別設定部分をApp Runner内でラップして抽象化させた事により「AWS上で最も簡単で且つ最速にコンテナ環境のWebアプリのビルド、デプロイを実行する」事を可能にしたのがApp Runnerとなります。
大きな特徴としては以下かと思います。
1.コンテナ環境のデプロイが容易
コンテナイメージ、ソースコードから簡単にコンテナ環境のデプロイが可能。
2.抽象度が高く素早くデプロイが可能
アプリをデプロイする為にVPCのような足回りやECS,Fargateといったコンテナを稼働させるコントロールプレーン、データプレーン、パイプラインで使用するビルド環境や、LB等の準備が不要。とにかく簡単で素早くコンテナ環境のデプロイが行える。という事がこのサービスの売りとなります。
どれだけ簡単なのか?という点が一番気になる所かと思います。
初回のみApp Runnerのサービス作成をチョロッとだけ行えばマネージドのコンテナやロードバランサ等が起動され、アクセスが可能になりますが、デプロイ方法は「コンテナイメージをECRにPushする。」もしくは「ソースコードをGitHubにPushする。」のいずれかになります。
「チョロッと」がどれくらいなのか、手順を確認し記載しようと考えていましたが、既に以下のサイトでクラスメソッドさんがImage版とソースコード版いずれもしっかりした手順を記載してくれています。
https://dev.classmethod.jp/articles/webinar-containersfromthecouch-hello-aws-app-runner/
また以下のAWSさんの動画がとてもわかりやすく説明してくれていましたので、
上記デモと同じ内容をCLI版に置き換え、どれだけ簡単なのかをお伝え出来ればと思います。
これから行う流れ
以下の流れで確認してみます。
1.ECRパブリック上のコンテナイメージからデプロイ
2.サービスの設定値を確認
3.自アカウント上のECRにあるコンテナイメージからデプロイ
4.その他、サービスの設定内容確認
5.オートスケーリングの確認
6.GitHub上のソースコードからデプロイ
7.自動デプロイを確認
それでは早速やってみましょう
1.ECRパブリック上のコンテナイメージをデプロイ
今回コンテナイメージからのデプロイと、Github上のソースコードを使用したデプロイを行いますが、以下のAWSさんのリポジトリにあるお試し用のソースコードを利用していきます。
まずはお試しという事でECRパブリックのイメージを使用したデプロイです。上記リポジトリへアクセスし、README.mdの「Deploy to App Runner」部分に記載されている以下を実行してみて下さい。
SERVICE_NAME=hello-app-runner
cat > hello-app-runner.json <<EOF
{
"ImageRepository": {
"ImageIdentifier": "public.ecr.aws/aws-containers/hello-app-runner:latest",
"ImageConfiguration": {
"Port": "8000"
},
"ImageRepositoryType": "ECR_PUBLIC"
},
"AutoDeploymentsEnabled": false
}
EOF
aws apprunner create-service --service-name ${SERVICE_NAME} \
--source-configuration file://hello-app-runner.json
「aws apprunner create-service」コマンドを打ったら一撃(正確には3回のコマンド)で ECR Public上にあるイメージのデプロイが行われ、以上終了という内容です。
ちなみにAWSCLIのバージョンは2021/10現在の最新「aws-cli/2.2.44」で実行しています。apprunnerコマンドが存在しない場合にはCLIのバージョンアップを行ってください。
成功すると以下のように作成されたサービスの情報がレスポンスとして帰ってきます。InstanceConfiguration等のオプション項目は指定していなければデフォルト値で作られます。
「aws apprunner create-service」コマンド レスポンス内容(抜粋)
{
"Service": {
"Status": "OPERATION_IN_PROGRESS",
"SourceConfiguration": {
"ImageRepository": {
"ImageConfiguration": {
"Port": "8000"
},
"ImageRepositoryType": "ECR_PUBLIC",
"ImageIdentifier": "public.ecr.aws/aws-containers/hello-app-runner:latest"
},
"AutoDeploymentsEnabled": false
},
"InstanceConfiguration": {
"Cpu": "1024",
"Memory": "2048"
},
マネージメントコンソールからApp Runner⇒サービス画面を確認するとサービスが作成されていますので、ステータスが「Running」になるまでしばらく待ちます。
ステータスが「Running」状態になったら「デフォルトドメイン」に記載されているURLをクリックします。 以下の画面が表示されたらデプロイ完了。簡単、早すぎですね。
※参考までに以下のCLIコマンドでも状態やURL、設定値の確認は確認可能です。
2.サービス作成時の設定値を確認
今行った内容を振り返ってみると AppRunnerの以下設定ファイル「hello-app-runner.json」を作成し、サービス作成「create-service」コマンドの引数に指定しただけです。
hello-app-runner.json
{
"ImageRepository": {
"ImageIdentifier" : "public.ecr.aws/aws-containers/hello-app-runner:latest",
"ImageConfiguration": {
"Port":"8000"
},
"ImageRepositoryType": "ECR_PUBLIC"
},
"AutoDeploymentsEnabled": false
}
指定した内容についての説明は以下となります。
- ImageIdentifier:コンテナイメージの指定
- ImageConfiguration.Port:コンテナのListenポート
- ImageRepositoryType:イメージリポジトリのタイプ指定 (ECR | ECR_PUBLIC)
- AutoDeploymentsEnabled:ソースとなるコードやイメージが最新化された時に自動でデプロイを行うかの設定。同一アカウントのソースリポジトリやECRを使用する場合のみ「true」(自動)が設定可能。
3. 自アカウント上のECRにあるコンテナイメージをデプロイ
次に同じイメージをPrivateECRから起動を試す為、手元にPullし、イメージのタグを変更してECRにPushします。
#ECRパブリックからコンテナイメージを手元にpull
docker pull public.ecr.aws/aws-containers/hello-app-runner:latest
#PrivateのECR用にタグ付け
docker tag public.ecr.aws/aws-containers/hello-app-runner xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hello-apprunner-repo
#ECRログイン
aws ecr get-login-password | docker login --username AWS --password-stdin https://xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com
#ECRにプッシュ
docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hello-apprunner-repo:latest
準備完了
プライベートのECRを使用する時の設定ファイルサンプル(hello-app-runner.json)は下記です。※必須項目のみ指定
注意点
xxxxxxxxxxxxと記載されている箇所は個々のアカウントIDに書き換え実行してください。
以下のロールはECRにアクセス出来る権限で事前に作成する必要があります。
cat > hello-app-runner.json <<EOF
{
"ImageRepository": {
"ImageIdentifier": "xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hello-apprunner-repo:latest",
"ImageConfiguration": {
"Port": "8000"
},
"ImageRepositoryType": "ECR"
},
"AutoDeploymentsEnabled": true,
"AuthenticationConfiguration": {
"AccessRoleArn": "arn:aws:iam::xxxxxxxxxxxx:role/service-role/AppRunnerECRAccessRole"
}
}
EOF
ECRパブリック使用時との設定ファイル(hello-app-runner.json)の変更点
- 「ImageIdentifier」→ Pushした自アカウントのECRイメージに変更
- 「 ImageRepositoryType 」→”ECR”に変更 ※PrivateECR
- 「AutoDeploymentsEnabled」→trueに変更 ※自動デプロイ有効化
- 「 AuthenticationConfiguration 」でApp Runnerが使用するロールARNを指定 ※ロールに対してはECRの権限を付与
上記以外の設定値については以下を参照して下さい。
サンプル(https://docs.aws.amazon.com/ja_jp/apprunner/latest/api/API_CreateService.html)
リファレンス(https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apprunner/create-service.html)
それではこの内容でサービス名を変更して実行してみます。
SERVICE_NAME=hello-app-runner2
aws apprunner create-service --service-name ${SERVICE_NAME} \
--source-configuration file://hello-app-runner.json
同じように少し待ち、デプロイ完了後にアクセスするとデプロイが確認出来ます。
4.その他、サービスの設定内容確認
それではマネージメントコンソールから出来上がった環境の設定値を見てみましょう。プライベートリポジトリに変更され、デプロイ方法が「自動デプロイ」に設定されている事を確認
仮想CPUとメモリ、ポート
メトリクス
Cloudwatchメトリクスと統合されおり、リクエスト数やステータスコードカウント、リクエストのレイテンシ、 起動しているインスタンス数(ActiveInstances)等の確認が可能です。
ログ
CloudwatchLogsと統合され、イベントログ、デプロイログ、アプリケーションログを確認可能特にエージェントの設定は不要。
インスタンスロール
コンテナインスタンスが利用するロールアプリがS3等のリソースにアクセスする時に指定デフォルトはロールを設定は無し。
AWS KMSキー
Apprunner上で保持している内容の暗号化に使用。Apprunner上の設定値(AutoScale設定や名前、環境変数)はメタデータとしてApprunner上で保持している。
ヘルスチェック
チェックするポートはコンテナのListenポート、Pathはルートのみで変更不可。
AutoScaling設定
同時実行数
スケーリングの条件です。応答できずに滞留したリクエスト数いくつ溜まっているかがオートスケールのトリガとなる。AppRunnerのオートスケーリング設定は同時実行数だけでCPU使用率等を閾値として設定は出来ない。
最小サイズ
最小で維持するインスタンス数
最大サイズ
スケールする上限のインスタンス数。1-25となっているが、最大サイズは上限緩和可能
5.オートスケーリングの確認
スケールアウトする事を確認したかったのですがF5連打やスクリプトを使用して連続アクセスを行っても同時実行数が上がらず、スケールアウトされる事が確認出来なかった為「Distibuted Load Testing」を使用してAppRunnerのオートスケーリングのテストを実施。応答が滞った際にActiveInstancesの値が上がりスケールアウトされている事を確認。※「Distibuted Load Testing」の使い方は以下を参考にして下さい。
https://dev.classmethod.jp/articles/distributed-load-testing-on-aws/
きちんとオートスケーリングがトリガされ、Activeinstancesが上がっている事を確認。
6.GitHub上のソースコードからデプロイ
次はGitHub上のソースコードでからデプロイしてみましょう。
※注意点
現時点の対応言語はPythonとNodeJsのみです。それ以外の言語はコンテナイメージを使う必要があります。また、ソースリポジトリとして利用できるのはGitHubのみ。なぜかCodeCommitは使用出来ません。
下準備①以下リポジトリのソースを自身のGithubアカウントにFork
以下のリポジトリを自身のGitHubリポジトリにForkして下さい。
https://github.com/aws-containers/hello-app-runner
下準備②GitHub接続の作成
AWS App RunnerがGitHub上のソースを使用してデプロイするためにGithubと接続をする為のコネクションリソースを作成します。マネージメントコンソール⇒App Runer⇒「GitHub接続」からGithubコネクションリソースを作成して下さい。
※詳細は以下サイトの「GitHub接続の作成」を参照
https://dev.classmethod.jp/articles/apprunner-sourcecode/
GitHub接続作成後、以下の情報をメモしておいてください
・自身のGitHubリポジトリのURL
・GitHub接続のARN
■apprunner.yaml
Forkしたリポジトリには「apprunner.yaml」というファイルがあります。「apprunner.yaml」 上でランタイムの指定やパッケージインストール等を行う為のビルドコマンド、開始コマンド等の設定を定義してソースコードと一緒に管理が可能です。 「apprunner.yaml」 はアプリケーションフォルダの直下に配置しする事で利用できます。
#apprunner.yamlの中身
version: 1.0
runtime: python3
build:
commands:
build:
- yum install -y pycairo
- pip install -r requirements.txt
run:
command: python app.py
network:
port: 8000
GUI上では下記の「設定ファイルを使用」にチェックを入れると、このファイル「 apprunner.yaml 」が利用されます。逆に言えば「ここで全ての設定を構成する」にチェックを入れている状態で設定する以下GUIの項目を「apprunner.yaml 」 で定義する事になります。
CLIでapprunner.yamlを使用する場合のサンプルは以下となります。
■apprunner.yamlの使用有無指定
※CodeConfiguration の "ConfigurationSource" に指定している値(REPOSITORY|API)によって「apprunner.yaml」を使用するのか、create-serviceコマンドの CodeConfigurationValues で直接指定するのかを設定しています。
REPOSITORY - App Runner は、ソース コード リポジトリ内の apprunner.yaml ファイルから構成値を読み取り、CodeConfigurationValues を無視します。
API - App Runner は、CodeConfigurationValues で提供される構成値を使用し、ソースコー ドリポジトリ内の apprunner.yaml ファイルを無視します。
GitHubのソースコードからデプロイする際にはRepositoryUrlにGitHubのリポジトリURLを指定し、ブランチを指定する点やConnectionArnにGitHubConnectionのARNを指定する等、ECRの時とは設定が少し異なります。
cat > hello-app-runner.json <<EOF
{
"CodeRepository": {
"RepositoryUrl": "https://github.com/{githubユーザ名}/hello-app-runner",
"SourceCodeVersion": {
"Type": "BRANCH",
"Value": "{ブランチ名}"
},
"CodeConfiguration": {
"ConfigurationSource": "REPOSITORY"
}
},
"AutoDeploymentsEnabled": true,
"AuthenticationConfiguration": {
"ConnectionArn": "{GitHub接続のARN}"
}
}
EOF
変更した設定ファイルを指定して実行後、アプリケーションが起動する事を確認してください。
SERVICE_NAME=hello-app-runner3
aws apprunner create-service --service-name ${SERVICE_NAME} --source-configuration file://hello-app-runner.json
7.自動デプロイを確認
続いて、Github上のソースを更新する事で自動デプロイが行われる事を確認します。
先程Forkした自身のGithubリポジトリの/templates/index.htmlの191行目を「Congratulations」から「Thankyou!!」に変更し、リポジトリにプッシュしてみましょう。
サービスのステータスがプッシュが完了するとサービスのステータスが「Operation in progress」に変わりました。
イベントログを見ると、デプロイがスタートされ、ソースコードのPullが行われ、ビルドが走りデプロイが成功している事が確認出来ます。
URLを確認し変更した内容「Thankyou!!」が更新されていれば成功です。
おまけ
create-serviceコマンドの CodeConfigurationValues で直接指定するケース
ちなみにapprunner.yamlを使用しなかった場合(CodeConfigurationValuesで直接指定)のサンプルは以下になります
https://docs.aws.amazon.com/ja_jp/apprunner/latest/api/API_CreateService.html
※Examples
Create a source code repository serviceを参照
aws apprunner create-service --cli-input-json
{
"ServiceName": "python-app",
"SourceConfiguration": {
"AuthenticationConfiguration": {
"ConnectionArn": "arn:aws:apprunner:us-east-1:123456789012:connection/my-github-connection/ef67242d"
},
"AutoDeploymentsEnabled": true,
"CodeRepository": {
"RepositoryUrl": "https://github.com/my-account/python-hello",
"SourceCodeVersion": {
"Type": "BRANCH",
"Value": "main"
},
"CodeConfiguration": {
"ConfigurationSource": "API",
"CodeConfigurationValues": {
"Runtime": "PYTHON_3",
"BuildCommand": "pip install -r requirements.txt",
"StartCommand": "python server.py",
"Port": "8080",
"RuntimeEnvironmentVariables": [
{
"NAME": "Jane"
}
]
}
}
}
},
"InstanceConfiguration": {
"CPU": "1 vCPU",
"Memory": "3 GB"
}
}
まとめ
触ってみた印象としては、うたい文句通りですがとにかくコンテナを素早く簡単にデプロイしたいといった用途向けのサービスです。
但しApp Runnerの機能内に様々なサービスが隠れて動いており、抽象度が高くシンプルな分出来る事には制限がある点を理解の上で利用する必要があります。
現時点においてはVPC内リソースに対するPrivateアクセスが出来ない点や、セキュリティグループが使用できない等の制限もあるのでユースケースは絞られますが、マイクロサービス化が進み、多くのAPIを細かい単位で素早く開発、素早くリリースできる仕組みを用意するような状況や、構築を含めて開発者で完結させるようなケースでは利用が増えていきそうなサービスだと感じました。
また、この機会で 初めて触った「Distibuted Load Testing」も良い収穫になりました。