ECS with awsvpc on EC2
10年ぶりくらいに書くので口調を忘れました。昔の記事と違ってたらすいません。
TL;DR
ENI上限を引き上げるには デフォルトのawsvpcTrunkingをenabledにすれば良い
EC2 vs Fargate
ECSはVPCネットワーキング(awsvpc)で使う方が楽で、かつVPCを使う場合はFargateを使う方が楽です。
ただ、敢えて苦難の道を選びEC2コンテナインスタンスを使うメリットももちろんあります。
EC2のメリット
Fargateより安い
Fargateが値下げされたので今は変わらないかも。
ログドライバにawslogs以外を選べる
Fargateだとawslogsしか(splunkも選べるようになったけど)選べません。
特にデバッグの時にcloudwatchを見るのはとてもつらいので、jsonfileやfluentdを使いたくなります。
docker execで中に入れる
コンテナインスタンスにsshして docker exec
でコンテナの中に入ることができます。
Fargateではできませんが、将来sshできるようにするという計画が発表されてるようなので今だけかも。
今回のプロダクトの場合、本番運用はFargateで、ステージング環境をEC2にすることにしました。
ENIの上限
さて、ネットワーキングをbridgeにすると、同じインスタンス上で走るコンテナ同士でポートがぶつからないよう工夫する必要があります。
特にマイクロサービス化されている場合、これはとてもやってられないですね。
VPCを使うとポートは使いたい放題(ただし外部との接続はロードバランサを経由する必要がある)、同じタスク内のコンテナ同士もlocalhostでやり取りできます。
が、VPCの場合コンテナごとにENI(Elastic Network Interface)が割り当てられ、その上限がEC2インスタンスごとに決まっています。
上限がlarge
インスタンスでも2個とかなので、現実的にVPCでの運用は不可能です。
で、この上限を大幅に緩和するオプションがあって、awsvpcTrunking
というのを有効にすると一気に5倍くらいに緩和されます。
large
インスタンスで10個になるのでこれなら普通に運用できるでしょう。
上限緩和の方法
consoleのECSのメニューにAccount Settings
というのがあります。
この中にawsvpcTrunking
という項目があって、これをチェックすれば有効になります。
わぁ簡単。
と思いきや。説明を良く読みましょう。
ここをチェックしても自分のロールにしか有効にならないので、ECSのサービスロールに対して?awsvpcTrunkingを有効にする必要があるようです。
というわけでサービスロールに付与してみます。
aws ecs put-account-setting --name awsvpcTrunking --value enabled --principal-arn arn:aws:iam::xxxx:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS
が、rootアカウントでないとサービスロールに権限は付与できないよ、と言われてしまいました。
(なんだか複雑な)ドキュメントを読むと、コマンドラインを使用して、引き上げられた ENI 制限にアカウントのすべての IAM ユーザーまたはロールをオプトインするには
という項目があり、全てのロールについて有効にできるようです。
やってみます。
aws ecs put-account-setting-default --name awsvpcTrunking --value enabled
できました。
有効にした後に起動したインスタンスのみ、awsvpcTrunkingが有効になっています。
確認
画面からでは分からない
(この「ポート」が増えるわけではないらしい)
aws-sdkで確認
% aws ecs list-attributes --cluster hoge-cluster --target-type container-instance --attribute-name ecs.awsvpc-trunk-id
{
"attributes": [
{
"name": "ecs.awsvpc-trunk-id",
"value": "xxxx",
"targetId": "arn:aws:ecs:ap-northeast-1:xxxx:container-instance/xxxx"
}
]
}
試しにタスクを大幅に増やしてみたところちゃんと走ったので成功したようです。