こんにちは。よっしーです(^^)
今日は、Terraformで構築したECS環境のコンテナでコマンドを実行する方法についてご紹介します。
前提
構築するECS環境は下記のサイトをベースにしています。
また、この記事は下記の記事の続きとなっています。
背景
この記事では、これまでご紹介してきたTerraformを利用したECS環境のコンテナでコマンド実行する方法についてご紹介しています。
構成図
構築したECSの構成図は下記のとおりです。
修正内容
下記のファイルを更新します。下記の各セクションに各ファイルの修正内容を記載しています。
modified: main.tf
modified: iam/iam.tf
modified: iam/output.tf
modified: ecs/ecs.tf
modified: ecs/variables.tf
main.tf
62行目に下記の内容を追記します。
lb_target_group_arn = module.lb.lb_target_group_arn
+ task_role_arn = module.iam.task_role_arn
execution_role_arn = module.iam.execution_role_arn
public_a_id = module.vpc.public_a_id
public_c_id = module.vpc.public_c_id
iam/iam.tf
50行目に下記の内容を追記します。
resource "aws_iam_role" "learn_ecs_task_role" {
+ name = "${var.tag_name}_task_role"
+
+ assume_role_policy = <<-EOS
+ {
+ "Version": "2008-10-17",
+ "Statement": [
+ {
+ "Sid": "",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "ecs-tasks.amazonaws.com"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+ }
+ EOS
+}
+
+resource "aws_iam_policy" "learn_ecs_task_role_policy_ssmmessages" {
+ name = "${var.tag_name}_policy_ssmmessages"
+ policy = <<-EOS
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "ssmmessages:CreateControlChannel",
+ "ssmmessages:CreateDataChannel",
+ "ssmmessages:OpenControlChannel",
+ "ssmmessages:OpenDataChannel"
+ ],
+ "Resource": "*"
+ }
+ ]
+ }
+ EOS
+}
+
+resource "aws_iam_role_policy_attachment" "learn_ecs_task_role_policy_ssmmessages" {
+ role = aws_iam_role.learn_ecs_task_role.name
+ policy_arn = aws_iam_policy.learn_ecs_task_role_policy_ssmmessages.arn
+}
iam/output.tf
2行目に下記の内容を追記します。
+output "task_role_arn" {
+ value = "${aws_iam_role.learn_ecs_task_role.arn}"
+}
ecs/ecs.tf
15行目に下記の内容を追記します。
cpu = 512
memory = 1024
requires_compatibilities = ["FARGATE"]
+ task_role_arn = "${var.task_role_arn}"
execution_role_arn = "${var.execution_role_arn}"
network_mode = "awsvpc"
60行目に下記の内容を追記します。
name = var.tag_name
cluster = aws_ecs_cluster.learn_ecs_cluster.id
task_definition = aws_ecs_task_definition.learn_ecs_task.arn
+ enable_execute_command = true
launch_type = "FARGATE"
ecs/variables.tf
9行目に下記の内容を追記します。
+variable "task_role_arn" {}
variable "execution_role_arn" {}
variable "public_a_id" {}
variable "public_c_id" {}
ECS環境の構築
下記のコマンドを実行します。
terraform login
Yesで確認し、自動的に開くブラウザウィンドウでワークフローに従います。プロンプトが表示されたら、生成された API キーを Terminal に貼り付ける必要があります。
TerraformCloudで初めてワークスペースを利用する場合は、下記の環境変数を設定する必要があります。
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
詳しくは下記のサイトをご覧ください。
下記のコマンドを実行します。
# プロジェクトの初期化
terraform init
# フォーマット
terraform fmt
# バリデーション
terraform validate
# 作成内容の確認
terraform plan
ここまで特に問題なければ、下記のコマンドを実行します。
# AWSリソースの作成
terraform apply
下記のような出力なっていれば成功です。
Apply complete! Resources: 20 added, 0 changed, 0 destroyed.
Outputs:
lb_dns_name = "xxx.ap-northeast-1.elb.amazonaws.com"
動作確認
下記のコマンドを実行します。
aws ecs list-tasks --cluster learn-aws-ecr --profile terraform | jq -r '.taskArns[]' | awk -F'/' '{print $3}'
出力された文字列をメモしておきます。
% aws ecs list-tasks --cluster learn-aws-ecr --profile terraform | jq -r '.taskArns[]' | awk -F'/' '{print $3}'
xxx
yyy
上記でメモした値を利用して、下記のコマンドを実行します。
aws ecs execute-command --profile terraform --task=xxx --interactive --cluster=learn-aws-ecr --container=learn_ecs_nginx --command /bin/sh
下記のような出力になっていれば成功です。
% aws ecs execute-command --profile terraform --task=xxx --interactive --cluster=learn-aws-ecr --container=learn_ecs_nginx --command /bin/sh
The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.
Starting session with SessionId: ecs-execute-command-nnn
/ #
これで、コンテナでコマンドの実行ができます。yyyも同様にxxxをyyyにすることで、コンテナでコマンド実行することができます。
解説
main.tf
iamモジュールで作成したタスクロールのarnを変数として渡すために、task_role_arnを追記しています。
iam/iam.tf
このコードは、Terraformと呼ばれるインフラストラクチャコード管理ツールを使用して、AWSのリソースを作成および構成するためのものです。このコードは、AWS Identity and Access Management (IAM) リソースを作成し、ECS(Elastic Container Service)タスクに関する必要な権限を定義しています。
以下は、それぞれのリソースとその目的についての解説です。
aws_iam_role
リソース (learn_ecs_task_role): このリソースは、ECSタスクに関連するIAMロールを作成します。IAMロールは、AWSサービスやリソースにアクセスするための許可を提供するために使用されます。このロールは、ECSタスクが必要なアクションを実行できるようにする役割を果たします。name
パラメータは、ロールの名前を指定しています。${var.tag_name}_task_role
という名前が使用されます。assume_role_policy
は、このロールが信頼されるエンティティ(Principal)およびアクセス許可(AssumeRoleアクション)を定義しています。ECSタスクによってこのロールがアサインされることを想定しており、ecs-tasks.amazonaws.com
サービスがこのロールにアクセスする権限を持つことを示しています。aws_iam_policy
リソース (learn_ecs_task_role_policy_ssmmessages): このリソースは、ECSタスクロールにアタッチするIAMポリシーを作成します。IAMポリシーは、特定のアクションとリソースに対するアクセス許可を定義します。このポリシーは、Amazon Systems Manager (SSM) メッセージに関連するアクションへのアクセスを許可するために使用されます。name
パラメータは、ポリシーの名前を指定しています。${var.tag_name}_policy_ssmmessages
という名前が使用されます。policy
パラメータでは、ポリシーのJSON形式の定義が提供されています。このポリシーでは、SSMメッセージ関連の特定のアクション(CreateControlChannel、CreateDataChannel、OpenControlChannel、OpenDataChannel)へのアクセスを許可し、対象のリソースはすべてのリソースを対象にしています("*"
)。aws_iam_role_policy_attachment
リソース (learn_ecs_task_role_policy_ssmmessages): このリソースは、前述の IAM ポリシーを前述の IAM ロールにアタッチするために使用されます。つまり、このロールにポリシーのアクセス許可を追加します。これにより、ECSタスクがSSMメッセージアクションを実行できるようになります。role
パラメータでは、アタッチするロールの名前を指定しています。policy_arn
パラメータでは、アタッチするポリシーのARN(Amazonリソース名)を指定しています。
このコードの結果として、ECSタスク用のIAMロールが作成され、そのロールにはAmazon SSMメッセージアクションへのアクセス許可が付与されます。これにより、ECSタスクはSystems Managerを介してインスタンスと通信するための機能を持つことができます。
iam/output.tf
このコード片は、Terraformで出力 (output) を定義しています。Terraformの出力は、作成されたリソースの情報や値を表示するために使用されます。指定されたコードは、先に示したIAMロールリソース learn_ecs_task_role
のARN(Amazonリソース名)を出力するために使用されます。
output
: 出力を定義するキーワードです。"task_role_arn"
: 出力の名前を指定しています。この名前は、後でこの出力を参照する際に使用されます。value
: 出力の値を指定しています。ここでは、Terraformの補間構文${aws_iam_role.learn_ecs_task_role.arn}
を使用して、learn_ecs_task_role
という名前のIAMロールリソースのARNを取得しています。
この出力を定義することで、Terraformが実行されると、Terraformの適用 (apply) プロセス中に作成されたIAMロールのARNが表示されます。他のTerraformコードやスクリプトでこの出力を参照することができます。例えば、他のリソースでこのIAMロールを使用する場合に、そのARNを簡単に取得できるようになります。
ecs/ecs.tf
enable_execute_command
パラメータを true
に設定することにより、ECSタスクに対してAWS Systems ManagerのExecute Command機能を有効にすることができます。Execute Commandは、AWS Systems Managerを使用して、EC2インスタンスやFargateタスクに対してリモートでコマンドを実行したり、スクリプトを実行したりするための機能です。これにより、タスクやインスタンスに対して遠隔で操作を行ったり、トラブルシューティングを行ったりすることが可能となります。
例えば、ECSタスクが起動される際に、このパラメータを true
に設定すると、そのタスクに対してExecute Commandが有効になります。これにより、タスクに対してリモートでコマンドを実行したり、ファイルをアップロードしたりすることができるようになります。
ただし、この機能を利用するには適切なIAMロールと権限も必要です。Execute Commandを使用するためのIAMポリシーや設定が適切に行われていることが前提です。また、詳細な設定やセキュリティについても考慮する必要があります。
そのため、task_role_arn
を追記して、タスクで使用するIAMロールのARNを指定しています。
ecs/variables.tf
iamモジュールで作成したタスクロールのarnを変数として渡すために、task_role_arnを追記しています。
タスクロールとタスク実行ロールの違い
AWS ECS(Elastic Container Service)において、タスクロール(Task Role)とタスク実行ロール(Task Execution Role)は、異なる役割を果たすIAM(Identity and Access Management)ロールです。それぞれの役割と違いについて説明します。
- タスクロール(Task Role): タスクロールは、個々のECSタスクに関連付けられるIAMロールです。ECSタスクは、Dockerコンテナやその他のリソースを実行する単位です。タスクロールは、タスク内のコンテナが他のAWSサービスやリソースにアクセスするための権限を提供します。例えば、タスク内のコンテナがS3バケットからファイルを読み取る、DynamoDBテーブルに書き込む、またはAWS Secrets Managerから認証情報を取得する場合、タスクロールはこれらのアクションに対する適切なアクセス許可を持つ必要があります。タスクロールは、タスクの実行に必要な特定のアクションへのアクセスを許可するために使用されます。
- タスク実行ロール(Task Execution Role): タスク実行ロールは、ECSタスクの実行に関連するIAMロールです。ECSは、タスクの実行やスケジューリング、ネットワークの設定などを担当するため、これに関連するロールが必要です。タスク実行ロールは、ECSエージェント(EC2インスタンス上のエージェント)がタスクを管理する際に使用されるロールです。例えば、タスクがログをCloudWatch Logsに送信したり、タスク間のネットワーク接続を処理したりする場合、タスク実行ロールはこれらの操作に必要な権限を提供します。
簡潔に言えば、タスクロールはタスク内のコンテナが直接必要とする権限を提供し、タスク実行ロールはECS自体がタスクを適切に管理するための権限を提供します。両方のロールは、セキュリティとリソースの適切な管理を確保するために重要な役割を果たします。
おわりに
今日は、Terraformで構築したECS環境のコンテナでコマンドを実行する方法についてご紹介しました。
本記事でご紹介したソースは、下記のリポジトリにあります。
https://github.com/Gate-Yossi/Musica/releases/tag/v2023.08.31
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント