DockerをAWS上で簡単に動かすことができるサービス、ECS(Elastic Container Service)にチャレンジしてみます。
ECSは、構築方法が何通りもあり、ローカルPCからDockerコマンドで直接構築したり、Copilotというツールを用いて簡単に行う方法が用意されています。
ただ、AWSマネジメントコンソールを使用したほうが自分が何を操作しているか理解しやすいので、今回はブラウザ画面をポチポチしながら構築したいと思います。
ECSの主な要素
まず実際の構築に入る前に、ECSで重要なリソースの説明を行います。
こちらのBlackBeltに図解入りでわかりやすく解説されてますが、自分なりの解釈は以下のとおりです。
タスク定義
使用するDockerイメージや、CPU、メモリをどの程度使用するか、ログをどこに出力するかなど、コンテナを動かす上での基盤となる設定を行います。
オブジェクト指向のクラス、インスタンスを説明するときに、それぞれを「車の設計図」と「実際に走る車」に例えられたりしますが、その車の設計図(クラス)と同じ概念です。
なおタスク定義には複数コンテナ指定することができます。
どのコンテナとどのコンテナを、同一のタスク定義にまとめるかの粒度は、こちらのドキュメントに目安が記載されています。
以下のような要件がある場合には、1 つのタスク定義にコンテナを配置することをお勧めします。
- 各コンテナが同じライフサイクルを共有している (つまり、起動と終了が同時に行われる)。
- 実行基盤となるホストが同じになるようにコンテナを実行する (つまり、あるコンテナが、localhost ポート上の別のコンテナを参照する) 必要がある。
- コンテナはリソースを共有します。
- コンテナでデータボリュームを共有している。
上記の要件がない場合は、複数のタスク定義でコンテナを個別にデプロイすることをお勧めします。これにより、スケーリング、プロビジョニング、プロビジョニング解除を個別に行えるようになります。
AWS公式ドキュメント コンテナイメージ
コンテナのライフサイクルが一緒のケースや、コンテナ同士がマウントしてリソースを共有する必要がある、などの条件がある場合は、複数コンテナを1つのタスクにまとめます。
例えば、CakePHPやLaravelが稼働するサーバを構築する場合、以下の2つのコンテナを準備することがあります。
- nginxプロセスが稼働しているコンテナ
- phpfpmプロセスが稼働しているコンテナ
phpfpm側のimg、js、css(CakePHPならwebroot、Laravelならpublic配下の公開ディレクトリ)をnginxをドキュメントルートに配置したい場合は、nginxコンテナからphpfpmコンテナをマウントする必要があるため、同一タスクに定義します。
タスク
タスク定義をもとに作成された、実際に動くコンテナです。
オブジェクト指向の「車の設計図」と「実際に走る車」の例えでは、実際に走る車(インスタンス)になります。
タスクには、スタンドアロン型とサービス型があり、バッチなど一時的に稼働するのものはスタンドアロン型、APIなど常時稼働するものはサービス型と使い分けます。
サービス型は、タスクの最小数を指定することで、AWS側のハードウェアに障害があって実行コンテナが落ちた場合でも、その最小数を保とうと自動的に復旧する便利な仕組みになっています。
サービス
APIなど常時稼働するコンテナをサービス型のタスクとして設定します。
同時にいくつのタスクを起動するかや、ELBと紐付けてのオートスケーリング設定、デプロイ方式などを設定します。
サービスは、設計図から作られた実際の車(タスク)が、まとめて走れるように道路を整備するイメージです。
クラスター
スタンドアロンタスクやサービスをまとめる任意のグループです。
こちらのドキュメントのように、あるユーザー、グループのみ特定のクラスターにアクセスできるようにするなどのIAM権限の境界として利用するようです。
ちなみに僕の携わっているプロジェクトはインフラメンバが少ないこともあり、IAM権限でがっちり分けるようなことはしてません。
とはいえ1つのクラスターで運用しているわけではなく、API、公開Web、内部管理サーバなど、それぞれの機能ごとに分けています。
こうするとAWSコンソールのECS TOP画面にアクセスした際、どの機能で何台起動してるかを、パッとすぐに把握できて便利かと思います。
2種類のIAMロール
ECSにはタスク定義時にタスクロールとタスク実行ロールという、2つのロールを割り当てることができます。似たような名称なので混同しないように気をつけてください。
タスクロール
実際に稼働するコンテナが使用するロールになります。
例えば作成したDokcerアプリケーションがSDKを使ってS3バケットへのアクセスするのであれば、当該バケットへのアクセス権限を付与したロールを割り当てます。
タスク実行ロール
タスクロールがコンテナの中から必要な権限を割り当てるものだとしたら、タスク実行ロールはその外側のインフラ周り(ECS コンテナと Fargate エージェント)で必要な権限を割り当てるものになります。
例えばタスク起動時にコンテナイメージをECRから取得する場合は、そのECRへのアクセス権限、SecretManagerを使用して機密情報を環境変数に設定する場合は、当該シークレットへのアクセス権限などが必要になります。
なおこのロールは、AWSコンソール画面でのタスク定義作成時に、タスク実行ロールの項で [ 新しいロールの作成 ] を選択するとecsTaskExecutionRoleという名前でIAMロールが自動的に作成されます。
デフォルトでは、ECRとCloudWatchLogsへのアクセス権限が付与されます。
ECS Fargateの構築手順
AWSコンソールにログイン後、 画面上部検索窓 [ ECS ] で検索 → 当該サービスをクリックします。
タスク定義の作成
ECS画面の左ペイン [ タスク定義 ] → [ 新しいタスク定義の作成 ] を押下し、次画面で以下のとおりに設定します。
タスク定義の設定
タスク定義ファミリーに任意の名前を入力します。
インフラストラクチャの要件
以下のとおりに設定します。メモリ、CPUは検証目的なので最小値になります。
項目名 | 値 |
---|---|
起動タイプ | AWS Fargate |
オペレーティングシステム/アーキテクチャ | Linux/X86_64 |
ネットワークモード | awsvpc |
CPU | .25 vCPU |
メモリ | .5 GB |
タスクロール | なし |
タスク実行ロール | 新しいロールの作成 |
タスク実行ロールは、ecsTaskExecutionRole という名前でIAMロールが自動生成されます。
そのAWSアカウントで、既にAWSコンソールからECSを構築した場合は、当該ロールが作成されているはずです。プルダウンの選択肢に ecsTaskExecutionRole が表示されるので、それを選択してください。
コンテナ – 1
以下のとおりに設定します。明記してないものはデフォルトのままでOKです。設定後、画面右下の [ 作成 ] をクリックします。
コンテナの詳細
項目名 | 値 |
---|---|
コンテナ名 | 任意の名前を入力 |
イメージURI | httpd |
必須コンテナ | はい |
イメージURIを単に “httpd” とイメージ名のみ入力した場合は、DockerHubの公式リポジトリから取得されます。
AWSのコンテナイメージリポジトリECRに、イメージがある場合は、AWSアカウントID.dkr.ecr.リージョン.amazonaws.com/リポジトリ名[:タグ or ダイジェスト] のように入力します。
- タグなし(= latest)
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/zoo200-httpd - タグあり
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/zoo200-httpd:latest
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/zoo200-httpd:1.2.3 - ダイジェスト
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/zoo200-httpd@sha256:12345abcef
ポートマッピング
項目名 | 値 |
---|---|
コンテナポート | 80 |
プロトコル | TCP |
アプリケーションプロトコル | HTTP |
クラスターの作成
ECSトップ画面の左ペイン [ クラスター ] → [ クラスターの作成 ] をクリックし、以下のとおり設定します。設定後、画面右下の [ 作成 ] をクリックします。
項目名 | 値 |
---|---|
クラスター名 | 任意の名前を入力 |
AWS Fargate (サーバーレス) | チェックを入れる |
サービスの作成
ECS画面の左ペイン [ クラスター ] → 作成したクラスター名 → サービス タブの [ 作成 ] を押下し、以下のとおりに設定します。明記してないものはデフォルトのままでOKです。
設定後、画面右下の [ 作成 ] をクリックします。
環境
項目名 | 値 |
---|---|
コンピューティングオプション | 起動タイプ |
起動タイプ | FARGATE |
プラットフォームのバージョン | LATEST |
デプロイ設定
以下のとおりに設定します。明記してないものはデフォルトのままでOKです。
項目名 | 値 |
---|---|
アプリケーションタイプ | サービス |
ファミリー | 作成したタスク名 |
リビジョン | 1(最新) |
サービス名 | 任意の名前を入力 |
サービスタイプ | レプリカ |
必要なタスク | 1 |
ネットワーキング
項目名 | 値 |
---|---|
VPC | デフォルトのVPC を選択 |
サブネット | いずれかのパブリックなサブネットを選択 |
セキュリティグループ | 新しいセキュリティグループの作成 |
セキュリティグループ名 | 任意の名前を入力 |
セキュリティグループの説明 | 任意の説明を入力 |
セキュリティグループのインバウンドルール | タイプ:HTTP ソース:Anywhere or Customで自身のアクセス元IPを指定 |
パブリック IP | オン |
疎通テスト
httpdコンテナにhttpでアクセスしてみます。
アクセスするIPアドレスは、タスクの詳細画面に記載されています。
画面遷移が少し複雑ですが、ECS画面の左ペイン [ クラスター ] → [ 作成したクラスター名 ] → サービス タブの [ 作成したサービス名 ] → タスク タブの [ タスクID(30bb1…..のようなID) ] → 詳細 タブ の ネットワーク に表示されている [ パブリック IP ] がそれになります。
$ curl 10.0.0.1
<html><body><h1>It works!</h1></body></html>
$
ブラウザなどでアクセスすると、デフォルトの “It works!” という文字が表示されると思います。
Tips
ECS Execでコンテナ内に入ってデバッグする
ECS Execを使用して、ローカルPCからコンテナの中に入ることができます。以下の記事をご参照ください。
EC2起動タイプのユースケース
ECSのコンテナ実⾏環境は、サーバレスであるFargate起動タイプの他にもう一つ、EC2起動タイプがあります。
EC2起動タイプでは、自分たちでホストとなるEC2インスタンスの管理(パッチ当てやスケーリング管理など)をする必要があります。
EC2起動タイプでクラスターを作成すると、EC2インスタンスが自動的に作成されます。このインスタンスはAWSコンソールのEC2画面から確認できます。
EC2上では、以下のようにDockerプロセスが起動しており、そこにコンテナエージェントとサービス(以下の例では、zoo200-container-httpd というコンテナ)が稼働する形になっています。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b855xxxx httpd "httpd-foreground" 6 minutes ago Up 6 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp ecs-zoo200-task-ec2-1-zoo200-container-httpd-fcd8xxxx
d91bxxxx amazon/amazon-ecs-agent:latest "/agent" 12 minutes ago Up 12 minutes (healthy) ecs-agent
$
このEC2起動タイプのユースケースは、FargateのBlackBeltで以下のとおり示されています。
・docker exec のようなインタラクティブなデバッグ
AWS Black Belt Online Seminar AWS Fargate p.38
・GPUサポート
・Windows コンテナ
・Spot や RI ベースの価格モデルの適用
また、こちらの公式ブログではEC2クラスターの使用率を最大化できた場合、EC2タイプのほうが安くなると言及しているので、うまく使えばEC2タイプのほうがコストを抑えられるケースもあるようです。
ただ、Fargateも進化しており、前述のECS Execでインタラクティブなデバッグが可能になったり、Windowsコンテナもサポートするようになりました。
また効率良くEC2クラスターを運用するにも、かなり手間がかかるイメージです。
そのため、基本的にはFargateを利用して(NEWコンソールでもデフォルトがFargateになっています)、機械学習環境などを構築する場合に、EC2 GPUインスタンスでクラスタを組んで利用するみたいになるのかなと考えています。
今回は以上です〜ノシ
参考
アリガト━━━ヾ(´∀`)ノ━━━━♪
BlackBelt ECS
BlackBelt Fargate
Amazon ECS Fargate/EC2 起動タイプでの理論的なコスト最適化手法
詳細: Fargate データプレーン