DockerをAWS上で簡単に動かすことができるサービス、ECS(Elastic Container Service)にチャレンジしてみます。
ECSは、構築方法が何通りもあり、ローカルPCからDockerコマンドで直接構築したり、Copilotというツールを用いて簡単に行う方法が用意されています。
ただ、AWSマネジメントコンソールを使用したほうが自分が何を操作しているか理解しやすいので、今回はブラウザ画面をポチポチしながら構築したいと思います。
ECSの主な要素
まず実際の構築に入る前に、ECSで重要なリソースの説明を行います。
こちらのBlackBeltに図解入りでわかりやすく解説されてますが、自分なりの解釈は以下のとおりです。
タスク定義
使用するDockerイメージや、CPU、メモリをどの程度使用するか、ログをどこに出力するかなど、コンテナを動かす上での基盤となる設定を行います。
オブジェクト指向のクラス、インスタンスを説明するときに、それぞれを「車の設計図」と「実際に走る車」に例えられたりしますが、その車の設計図(クラス)と同じ概念です。
なおタスク定義には複数コンテナ指定することができます。
どのコンテナとどのコンテナを、同一のタスク定義にまとめるかの粒度は、こちらのドキュメントに目安が記載されています。
コンテナのライフサイクルが一緒のケースや、コンテナ同士がマウントしてリソースを共有する必要がある、などの条件がある場合は、複数コンテナを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の構築手順
ECSでは2020年末に公開されたNEWコンソールへ鋭意移行中のようですが、僕は記事執筆時点ではまだOLDコンソールを使用しています。
タスクスケジューラがなかったり、タスク定義の新リビジョン作成時にCloudFormationのスタックが作成されてしまう点に、まだ戸惑いがある感じです。
そのため本記事では、OLDコンソール(ECS画面の左上にある [ 新しい ECS エクスペリエンス ] のトグルボタンが左にある状態)での手順を記載します。
タスク定義の作成
AWSコンソールにログイン後、 画面上部検索窓 [ ECS ] で検索 → 当該サービスをクリックします。
ECS画面の左ペイン [ タスク定義 ] → [ 新しいタスク定義の作成 ] を押下し、次画面の 起動タイプの互換性の選択 で [ FARGATE ] を選択し [ 次のステップ ] をボタン押下します。
タスクとコンテナの定義の設定
以下のとおりに設定します。明記してないものはデフォルトのままでOKです。メモリ、CPUは検証目的なので最小値になります。
項目名 | 値 |
---|---|
タスク定義名 | 任意の名前を入力 |
タスクロール | なし を選択 |
オペレーティングシステムファミリー | Linux を選択 |
タスク実行ロール | 新しいロールの作成 を選択 |
タスクメモリ (GB) | 0.5GB |
タスク CPU (vCPU) | 0.25vCPU |
タスク実行ロールは、ecsTaskExecutionRole という名前でIAMロールが自動生成されます。
そのAWSアカウントで、既にAWSコンソールからECSを構築した場合は、当該ロールが作成されているはずです。プルダウンの選択肢に ecsTaskExecutionRole が表示されるので、それを選択してください。
コンテナの定義
[ コンテナの追加 ] を押下し、 以下のとおりに設定します。
項目名 | 値 |
---|---|
コンテナ名 | 任意の名前を入力 |
イメージ | httpd |
ポートマッピング | 80 (tcp) |
[ 追加 ] を押下し、画面が戻ったら [ 作成 ] → [ タスク定義の表示 ] を押下します。
なおコンテナイメージを、単純に “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
クラスターの作成
ECSトップ画面の左ペイン [ クラスター ] → [ クラスターの作成 ] → [ ネットワーキングのみ ] を選択し、[ 次のステップへ ] を押下します。
クラスターの設定 画面では、[ クラスター名 ] を入力し、 [ 作成 ] → [ クラスターの表示 ] を押下します。
VPCはデフォルトのものを利用するため、ここでは作成しません。
サービスの作成
ECS画面の左ペイン [ クラスター ] → [ 作成したクラスター名 ] → サービス タブの [ 作成 ] を押下します。
サービスの設定
以下のとおりに設定し、[ 次のステップ ] を押下します。明記してないものはデフォルトのままでOKです。
項目名 | 値 |
---|---|
起動タイプ | FARGATE |
オペレーティングシステムファミリー | Linux |
タスク定義 | 作成したタスク定義を選択 |
クラスター | 作成したクラスターを選択 |
サービス名 | 任意の名前を入力 |
タスクの数 | 1 |
ネットワーク構成
以下のとおりに設定し、[ 次のステップ ] を押下します。明記してないものはデフォルトのままでOKです。
項目名 | 値 |
---|---|
クラスターVPC | デフォルトのVPC を選択 |
サブネット | いずれかのサブネットを選択 |
セキュリティグループの設定 | 新しいセキュリティグループの作成 タイプ:HTTP ソース:あらゆる場所 or カスタムで自身のアクセス元IPを指定 |
パブリック IP の自動割り当て | ENABLED |
ロードバランサーの種類 | なし |
Auto Scaling (オプション)
ここはデフォルトのまま、[ 次のステップ ] を押下します。
項目名 | 値 |
---|---|
Service Auto Scaling | サービスの必要数を直接調整しない |
次の確認画面で [ サービスの作成 ] → [ サービス表示 ] を押下し、構築完了となります。
疎通テスト
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 データプレーン