2020/4/8, ついにFargateでEFSが使えるようになりました!
この記事では、Fargateサポートを待ちつつも無念の『ECS on EC2 + EFS』構成を取っていた環境を移行するまでにハマった落とし穴を紹介していきます。
Fargateに移行してしまえば、こんな悩みは解消されるはず。
- コンテナインスタンスのパッチ当てどうしよう...
- 定期的にインスタンス入れ替える?
- EFS以外のディスクは揮発性でいいのに、EBSの料金とか空き領域監視とかついてくる…
- デプロイするときにコンテナインスタンスを一時的に増やすの面倒
- スケールインとかインスタンス入れ替え時に乗ってるタスクが巻き添えにならない?
参考記事
新規でFargateを作成する場合や、全体像を知って動かしてみたい方は以下の記事が参考になります。
ネットワークモードがbridge
だった
ECSのEFSサポートがプレビュー版として使用可能になった2020/1/17から今日までの間、ECSタスク定義のefsVolumeConfiguration
を使用したEFSマウントはネットワークモードがawsvpc
の場合使用できませんでした。このため、移行前はネットワークモードをbridge
で構成していました。
EFS ファイルシステムのための Amazon ECS プレビューサポートが利用可能に
なお、efsVolumeConfiguration
以外にもEFSのマウント方法はいくつかあります。下記の方法の場合はawsvpc
モードでも使用可能です。ただ、ECSコンテナインスタンスへの依存ができてしまうためあまりやりたくありませんでした。
- バインドマウント方式: ECSコンテナインスタンス(EC2)でNFSを使ってマウントしておき、マウント先のパスをバインドマウントでコンテナに見せる
- Dockerボリューム方式:
dockerVolumeConfiguration
でNFSとしてEFSをマウントして使う
起動タイプをFargateに、ネットワークモードをawsvpc
に変更
起動タイプをEC2からFargateに変えると、Fargateはネットワークモードawsvpc
のみをサポートしているため、必然的にbridge
から変更する必要があります。今回のECSでのEFSサポートの発表の中で、明確にawsvpc
をサポートするようになったとの記載はありませんでしたが、問題ないようです。
タスクのコンテナで使用する Docker ネットワーキングモード。Fargate 起動タイプを使用している場合、awsvpc ネットワークモードが必要です。
セキュリティグループの設定先変更
ECSコンテナインスタンス(EC2)に設定していたセキュリティグループを、ECSサービスのセキュリティグループに変更します。設定内容は環境によりますが、今回は変更なしでそのまま付け替えました。
ECSサービス定義にnetworkConfiguration
を追加
networkConfiguration:
awsvpcConfiguration:
subnets:
- subnetid-1
securityGroups:
- sg-1
FireLensの環境変数FLUENT_HOST
, FLUENT_PORT
が挿入されなくなる
これはハマりました。ドキュメントには何も書いていませんが、awsvpc
モードの場合これらの環境変数は挿入されないようです。
AWSさん、これはどこかに書いておいてください…。
awsvpc
の場合、同一タスク内の通信はlocalhost
で可能なため、FireLensのようにサイドカー構成の場合は確かに環境変数で明示する必要はありません。でも、これに思い当たるまで時間がかかりました。bridge
のときはあったんだもの…。
同じタスクに属するコンテナが、localhost インターフェイス経由で通信できるようになります。
タスクネットワーキングと awsvpc ネットワークモード - Amazon ECS
なお、普通にfluentdなどをサイドカーでなく立ち上げていた場合は、サービスディスカバリを考える必要があります。
というわけで、タスク定義にfirelensを動かすコンテナにポートを定義しておきます。
portMappings:
- containerPort: 24224
protocol: tcp
元々、環境変数FLUENT_HOST
, FLUENT_PORT
を読んでアプリの設定を生成していたので、環境変数を自分で定義しておきます。
environment:
- name: FLUENT_HOST
value: localhost
- name: FLUENT_PORT
value: "24224"
ALBターゲットグループのターゲットタイプ変更は再作成が必要
ALBターゲットグループのターゲットタイプはbridge
ネットワークモードの場合はinstance
を指定します。awsvpc
モードの場合はip
に変える必要があります。これに伴い、ALBターゲットグループの再作成が必要になり、さらに、CloudFormationでターゲットグループのName
を指定している場合はリプレースに失敗するので名称を変える必要があります。RDS同様、Name
は未指定でもいいかもしれません。
ECSサービス削除後、ステータスがINACTIVE
になるまで待つ必要がある
ECSサービスを作成済みの場合、後からALBターゲットグループを変更できないので、ECSサービスも再作成が必要になります。awscliでdelete-service
しただけではすぐに消えないので、ステータスがINACTIVE
になるまで待ってから再作成する必要があります。
echo "delete service"
aws ecs delete-service --cluster hoge-ECSCluster --service hoge-ECSService
echo "wait until status is INACTIVE"
aws ecs wait services-inactive --cluster hoge-ECSCluster --service hoge-ECSService
ALBからの通信ポートが変わる
ネットワークモードbridge
の場合、ECSコンテナインスタンスがALBからの通信を受けるポートはエフェメラルポート(32768-65535)ですが、awsvpc
の場合はコンテナポートそのものになります。
- ECSContainerInstanceSecurityGroup:
+ ECSTaskSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: hoge-ECSContainerInstanceSecurityGroup
GroupDescription: ECS Allowed Ports
SecurityGroupIngress:
# ALBからの通信許可 (ephemeral port)
- IpProtocol: tcp
- FromPort: 32768
+ FromPort: 8080
- ToPort: 65535
+ ToPort: 8080
SourceSecurityGroupId: !ImportValue hoge-ALBSecurityGroup
VpcId: !ImportValue hoge-VPC:Id
SecretsManagerのJSONキーが指定できない
これも気付かずハマりました。シークレットをJSONで登録し、そのキーをタスク定義のsecrets
に指定して環境変数を挿入していた場合、シークレットをそれぞれバラして登録し直すか、コンテナ内でjq
等で読み出す必要があります。今回はそんなに数も多くなかったのでバラしました。
現時点(2020年2月26日)では、Fargateはこの機能未サポートです。
For tasks that use the Fargate launch type, the following should be considered:
It is only supported to inject the full contents of a secret as an environment variable. Specifying a specific JSON key or version is not supported at this time.
引用:Specifying Sensitive Data Using Secrets Manager - Amazon Elastic Container Service
ECSがSecrets ManagerのバージョンやJSONキーに対応。機密情報管理がめっちゃ便利になりました! | Developers.IO
ECSサービス定義で platformVersion
を指定する必要がある
FargateでEFSを使うためには1.4.0
以上が必要です。未指定のデフォルト値LATEST
が1.3.0
を向いています。これはこちらで紹介されていました。
そしてもう一つ重要なお知らせです.
— ポジティブな Tori (@toricls) April 8, 2020
これまで ECS/Fargate をご利用いただいていた方は、PV "LATEST" というタスク起動時に常に最新の PV を自動的に利用するエイリアスがあったことをご存知かもしれませんが、PV 1.4 を機に "LATEST" は即座に最新バージョンを向く挙動ではなくなります(続. (14/19)
続き) "LATEST" が PV 1.4 を向くようになるのは PV 1.4 のリリースからおよそ1ヵ月程度経った5月の中頃になる予定です. 今回のこの "LATEST" モデルの変更により、お客様は自身が利用するプラットフォームバージョンと移行のタイミングをこれまで以上に明示的に調整できるようになります(続. (15/19)
— ポジティブな Tori (@toricls) April 8, 2020
ECSタスク定義の無効なパラメータを消す
タスク定義、サービス定義のドキュメントを見直しておきましょう。
次のタスク定義パラメータは Fargate 起動タイプでは無効です。
...
上限値が違うパラメータもあります。
- stopTimeout: 300
+ stopTimeout: 120 # less than 120
まとめ
ネットワークモードを理解していればそれほど難しくないようです。同じECSとはいえ、起動タイプがEC2とFargateではサポートされている機能にそれなりに違いがあるため、注意が必要です。この機会にパラメータの見直しをしておくのもいいと思います。