Why not login to Qiita and try out its useful features?

We'll deliver articles that match you.

You can read useful information later.

1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS Fargate + セッションマネージャーをつかって、RDS接続用のbastionを構築する際に詰まったポイント

Posted at

1. はじめに

「AWSコンテナ設計・構築[本格]入門」という書籍に、
AWS Fargateを使ったbastion設計の章があります。(Chapter5-7)

個人開発している環境において、AWS Fargateとセッションマネージャーを使ったbastionを導入しようとしたのですが、
なかなかうまく実装できませんでした。

この記事では、実装するうえで行き詰った個所を振り返り、共有することを目的としています。

2. つまずいた箇所

今回つまずいたポイントは2か所です。

2.1. private subnet上のECSから、ECRに保存されているコンテナイメージがpullできなかった
2.2. Session Managerのアクティベーションコードを発行できなかった

2.1. private subnet上のECSから、ECRに保存されているコンテナイメージがpullできなかった

ECRはリージョナルサービスのため、VPC内には存在しません。
また、今回のECSはprivate subnet上に配置されています。
つまりECSとECRの間に、次のいずれかがないと通信できません。
(1)VPC Endpont
(2)NAT Gateway

(1)VPC Endpontを使う場合、インターネットへ出ることなくECRにアクセスでき、よりセキュアです。
(2)の場合、インターネットへの接続が必要になるのと、データ通信料がコストとしてかかってきてしまいます。
なるべくコストは抑えたかったので、(1)VPC Endpointを採用することにしました。

ECS ⇔ ECR間の通信に必要なEndpointは次の3つです。

  • ECR API ( com.amazonaws.<リージョン名>.ecr.api )
     「aws ecr get-login-password」などのECR APIを呼び出す際に利用
  • ECR DKR ( com.amazonaws.<リージョン名>.ecr.dkr )
     「docker push」などのDockerクライアントコマンドの呼び出しに利用
  • S3 ( com.amazonaws.<リージョン名>.s3 )
     Dockerイメージの取得に利用

これらのエンドポイントは、ECSタスク用のセキュリティグループに対して設定されている必要があります。
※S3はゲートウェイ型のためコストは発生しませんが、ECR APIおよびECR DKRはインターフェース型のため、コストがかかります。

また、ECSタスクのログをCloudWatchへ保管するためのVPC Endpointも作成しました。

  • CloudWatch Logs ( com.amazonaws.<リージョン名>.logs )

2.2. セッションマネージャーからECSタスクへ接続ができなかった

2.1. で無事にECSタスクが起動できるようになったのですが、
次はセッションマネージャーからECSタスクへ接続ができない事象が発生しました。
原因としては2つ考えられます。
(1)IAM権限が不足している
(2)ネットワーク設定が不足している

(1)IAM権限が不足している

セッションマネージャーからECSタスクへ接続するためには、
アクティベーションコードとIDを払い出し、
タスク内のSSMエージェントに対して登録する
必要があります。
ECSタスク内でアクティベーションコードを発行するので、ECSタスクに対してSystems Managerを操作する権限が必要でした。
また、アクティベーションコードを発行するコマンドでSystems Manager用のロールを指定する必要がありました。
したがって、次の権限が必要になります。

  • ECSタスクが利用するロールとポリシー
     ECSタスクのロールにアタッチ
# ECS TaskのIAMロールにSSM Activationのポリシーを追加
resource "aws_iam_role_policy" "ssm_activation_policy" {
  name = "ssm-activation-policy"
  role = aws_iam_role.ecs_task_role.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "ssm:CreateActivation",
          "ssm:DeleteActivation",
          "iam:PassRole"
        ]
        Resource = "*"
      }
    ]
  })
}

# SSM Service Role (if not already existing)
resource "aws_iam_role" "ssm_service_role" {
  name = "SSMServiceRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "ssm.amazonaws.com"
        }
      }
    ]
  })
}
  • ECSタスクがアクティベーションコード発行時に指定するロール
resource "aws_iam_role_policy_attachment" "ssm_service_role_policy" {
  role       = aws_iam_role.ssm_service_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

(2)ネットワーク設定が不足している

Systems ManagerへのVPCエンドポイントとして、次の2つを作成する必要があります。

  • ssm ( com.amazonaws.<リージョン名>.ssm )
     アクティベーションを作成するAPIなどで利用
  • ssmmessages ( com.amazonaws.<リージョン名>.ssmmessages )
     セッションマネージャーの接続を確立するために利用

これらのエンドポイントは、VPCエンドポイント用のセキュリティグループを選択する必要があります。

# VPCエンドポイント用のセキュリティグループ
resource "aws_security_group" "vpc_endpoint_sg" {
  name        = "vpc-endpoint-sg"
  description = "Security group for VPC endpoints"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = [aws_vpc.main.cidr_block]
  }
}

また、ECSとセッションマネージャーの通信を確立させるために、次のセキュリティグループも必要でした。

resource "aws_security_group_rule" "ecs_to_vpc_endpoints" {
  type                     = "egress"
  from_port                = 443
  to_port                  = 443
  protocol                 = "tcp"
  security_group_id        = aws_security_group.ecs_security_group.id
  source_security_group_id = aws_security_group.vpc_endpoint_sg.id
}

まとめ

上記の対応をすることで、無事にpraivate subnet上のECSタスクから、セッションマネージャーを利用して
praivate subnet上のRDSへ接続することができました。
大きくはネットワークの問題と権限周りの問題でした。

また、VPCエンドポイントは存在しているだけでコストがかかるので、bastionを利用しないときは
Terraformでコメントアウトして反映させています。
この辺も自動化できる仕組みを考えたいです。

本記事は「AWSコンテナ設計・構築[本格]入門」を参考にしていますので、まだ読んでない方はぜひ一読をおすすめします。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Comments

No comments

Let's comment your feelings that are more than good

Qiita Advent Calendar is held!

Qiita Advent Calendar is an article posting event where you post articles by filling a calendar 🎅

Some calendars come with gifts and some gifts are drawn from all calendars 👀

Please tie the article to your calendar and let's enjoy Christmas together!

1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Login to continue?

Login or Sign up with social account

Login or Sign up with your email address