CloudFormation下のFargateでECS Exec
CloudFormationで管理してたFargateでExecuteCommandを使ってみた際のメモ
間違いなどあれば、ご指摘お願いします!
FargateにExecuteCommandの設定を追加
AWS CLIの更新
自分の場合はv2がインストールされていたので、以下の2点を行いました
- CLIを最新にアップデート
- Session Managerプラグインのインストール
タスクロールにSession Managerの権限を追加する
ECS ExecはSSMの機能を使って実現しているので、ECSの実行ロールにIAM権限を追加することが必要です。
以下のJSONのポリシーを作成してタスクロールにアタッチします。
Fargateの場合はResourceの箇所になにを指定して権限を絞ればいいのでしょうか。いまいち分からなかったです
{
"Effect": "Allow",
"Action": [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
"Resource": "*"
},
EcsExecRolePolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: Ecs-exec-role
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "ssmmessages:CreateControlChannel"
- "ssmmessages:CreateDataChannel",
- "ssmmessages:OpenControlChannel",
- "ssmmessages:OpenDataChannel"
Resource: "*"
Roles:
- # タスクロールを指定する
Service定義でExecCommandのを許可する
ここで行うことは EnableExecuteCommand
をtrueにすることです。
これをtrueにすることで、実行コマンドが使用可能になります。
適当ですがサンプルコードです。
Service:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref Cluster
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 100
DesiredCount: !Ref DesiredCount # 読み替えてください
EnableExecuteCommand: true # ここを追加する
LaunchType: FARGATE
LoadBalancers:
- ContainerName: app
ContainerPort: 80
TargetGroupArn: arn # 読み替えてください
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- arn # 読み替えてください
Subnets:
- arn # 読み替えてください
- arn # 読み替えてください
ServiceName: SampleFargate
TaskDefinition: !Ref TaskDefinition # 読み替えてください
あとはCLIなどからexecute-command
を叩けばコンテナに入れるはずです。
ロギングの設定を追加してみる
ExecuteCommandのログはCloudTrail, S3, CloudWatchLogsに出力できます
他サービスと同じくCloudTrailにはAPIコールのみが記録されます。
なのでbin/bash
やbin/sh
などでコンテナに入ったあとのコマンドは記録されません。
その記録にはS3とCloudWatchLogsを使い、S3とCloudWatchLogsの両方を指定可能のようです。
この記事ではKMSを暗号化は行っていません。
タスクロールにS3とCloudWatchLogsの権限を追加する
以下のActionの追加が必要です
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:DescribeLogGroups"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
],
"Resource": "*" // Arnで絞る
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "*" // Arnで絞る
},
]
}
EcsExecLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: /ecs-exec/logs
EcsExecLogBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ecs-exec-log-bucket
AccessControl: Private
PublicAccessBlockConfiguration:
BlockPublicAcls: True
BlockPublicPolicy: True
IgnorePublicAcls: True
RestrictPublicBuckets: True
EcsExecLoggingRolePolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: Ecs-exec-role
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "logs:DescribeLogGroups"
Resource: "*"
- Effect: Allow
Action:
- "logs:CreateLogStream"
- "logs:DescribeLogStreams"
- "logs:PutLogEvents"
Resource: "*" # 必要に応じて絞る
- Effect: Allow
Action:
- "s3:PutObject"
Resource: "*" # 必要に応じて絞る
Roles:
- # タスクロールを指定する
Clusterの設定を追加する
ここで設定するのはLogConfiguration
とLogging
の2つです
Logging
をDEFAULT
に指定すると、タスク定義に設定したawslogs
の設定を使用します。
OVERRIDE
を指定するとその設定を上書きして、別のs3バケットなどに出力出来ます。
コンテナの標準出力とECS-execのログを一緒に記録することは無さそうなので、OVERRIDE
を指定します。
Cluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Ref ProjectName
# 以下を追加する
Configuration:
ExecuteCommandConfiguration:
KmsKeyId: # KMSを使用する場合
LogConfiguration:
CloudWatchLogGroupName: # 作成したもの
S3BucketName: # 上で作成したもの
S3KeyPrefix: # オプション
Logging: OVERRIDE
ログが送信出来ていない場合などは以下のコマンドでAgentログの確認が可能です
SSM Agentのデフォルトのロギング場所は/var/log/amazon/ssm/amazon-ssm-agent.log
なので以下のコマンドになります
$ cat /var/log/amazon/ssm/amazon-ssm-agent.log
# エラーのみを表示する場合
$ awk '$3 ~ /ERROR/ { print }' /var/log/amazon/ssm/amazon-ssm-agent.log
これでS3とCLoudWatchLogsに記録されるはずです
参考
Discussion