こんにちは。インフラエンジニアの永井(shnagai)です。
これまでEC2バックエンドでECSを運用してきたが、Fargateを採用するにあたり、EC2バックエンド時と比べた差分についてまとめてみました。
内容は、ざっくり下記5項目について。
- NW(awsvpc)
- タスク定義
- サービス
- AutoScalling
- メトリクス/ログ
Fargateをやってみたというのは出たての事にやったので、今回は本番運用を考えるにあたり知っておいたほうがよさそうな点についてまとめてます。
NW(awsvpc)
アーキテクチャ的に一番大きく変わるのは、NWの部分だと思う。 EC2上で、タスクを動かすときはデフォルトだと「bridge」が指定されるので、ホスト経由で外部と通信を行っていた。同一タスク(コンテナのリッスンポートが同じもの)を効率的にEC2上で動かすために、動的ポートマッピングを使うのが通例となっていた。
Fargateになると、EC2の存在は隠蔽されるが、当然VPC内にタスクを立てたかったり、セキュリティグループを指定したいのでそれを実現するために、awsvpcネットワークモードを使うことになる。 ちなみに、awsvpcはEC2バックエンドの時でも使えるので、Fargate用の機能ではない。
awsvpcネットワークモード
- タスクネットワーキング機能により、Amazon EC2 インスタンスと同じネットワーキングプロパティが Amazon ECS タスクに提供される。
- awsvpcの指定は、タスク定義で行う
- タスクが、独自のENI(Elastic Network Interface)を持つ。(プライマリプライベート IP アドレス、内部 DNS ホスト名)
- ENIに対して、VPCフローログ使えるので通信キャプチャ出来る
- 同じタスクに属するコンテナは、localhost インターフェイス経由で通信できる
タスクネットワーキング機能
ECSのタスクに対して、独自のネットワークNameSpaceを提供する機能(EC2バックエンドの時は、EC2のネットワークをbridgeだったりhostマウント形式で使っていたので使わなくてもよかった)
- Amazon ECS コンテナインスタンスには、タスクネットワーキングを有効にするために、コンテナエージェントのバージョン 1.15.0 以上が必要
- 現時点では、Amazon ECS 対応 AMI またはその他の ecs-init パッケージの Amazon Linux バリアントだけがサポート
- Application Load Balancer および ネットワークロードバランサーのみサポート(CLBは使えない)
- awsvpc 上で動くfargateタスクをELBにぶら下げる際は、ターゲットタイプとして instance ではなく、ip を選択する必要がある。これは大事。つまり、EC2で運用していたALBだったりにぶら下げる時は、新しくALBのターゲットグループを作りipタイプのターゲットで作ってあげる必要がある。
タスク定義
元々EC2で動かしていたタスク定義を、Fargate対応に切り替える想定で変更点を記載
ネットワークモード
- awsvpc選ぶ
Requires Compatibilities(互換性が必要)
- FARGATEを選ぶ
タスクサイズ
組み合わせがあるので、例えばメモリ2GBだと0.25vCPUから1vCPUまでの間から選ぶようなイメージ
- タスクメモリ 0.5〜30GB
- vCPU 0.25〜4
コンテナの定義
- ホストポートマッピングは使えない
- メモリ、CPUの総量がタスクサイズを超えないように調整
- ログドライバとして選べるのは、awslogsのみ
サービス
タスク定義でawsvpcネットワークモードを指定しているタスクを動かす場合に、VPCとセキュリティグループを指定することが出来る。
EC2バックエンド時は、EC2側に設定していた項目がここに来たイメージ。
- クラスタVPC
- サブネット
- せキュリティグループ
- パブリックIPの自動割当
- ALB・NLB使う際は、ターゲットグループがIPになっているものを選ぶ(なければ作っておく)
デプロイ(サービス更新)時は、EC2インスタンスの時と同じで、タスク起動数が最小数を満たすようにタスク新規作成が始まり、ALB(NLB)ターゲットのdraining期間が過ぎるのを待って旧タスクは落ちる
AutoScalling
Fargateにする一つの大きなメリット。これまでは、EC2(ASG)のスケールアウト+サービスのスケールアウトのつじつま合わせながら組まないといけなかったので障壁高かったが、Fargateならリソース負荷ベースで気軽にスケールアウトが組める
- スケールの単位は、CPU,Memory,ALBのリクエスト数もしくはCloudWatchアラーム
- スケジュール単位のスケールがほしいがなさそう(CloudwatchEventsとLambda組み合わせれば出来るかな)
メトリクス/ログ
メトリクス周りが若干弱いけど、これはせっかくEC2管理から逃れられるんだから、リソースとかあまり気にせずAutoScallingをうまく組んで自動で運用していくって流れがいいのかなと思ったり。 ログは、コンテナに直接ログイン出来ない点埋めるべく標準出力は簡単に見れるような仕組みが提供されている。
内部にはログ溜めずにツール使って外に飛ばしたり、標準出力をうまく使って状況把握出来るように運用していくのが吉。 デバッグは、コンテナなんだからローカルで動けば基本OKなはずで、どうしてもってときは同じイメージをEC2バックエンドで動かすしかないかなと思ったり。
- メトリクスはクラスタとしては出てこなくて、ECSサービス単位でCPUとmemoryが見れる
- 標準出力は、ECSコンソール上から閲覧可能
- ecs-cliコマンドから叩くことで
tail -f
的にリアルタイムでみることも出来る(awslogsを使ってCloudwatchLogsから同じように取得も可能)
ecs-cli logs - Amazon Elastic Container Service
ecs-cli logs --follow --task-id task-id [Tue Sep 04 04:03:41.332650 2018] メッセージ [Tue Sep 04 04:03:41.391128 2018] メッセージ
最後に
検証しながら気付いた点
- やはり、EC2バックエンド時と違い、ホスト側で行われていたdocker pull時のキャッシュがきかないので起動時間は長かった
- キャッシュでごまかされていたので、webの運用ではあまり気にならなかったが、デプロイ時間に直接響くのでDockerイメージを小さくしていくことが必要になってくる