ECS Fargate + RDS の構成でローカルPCからRDSに安全に接続する
はじめに
WEBアプリケーション開発をしていると、開発環境やステージング環境のRDSのデータを確認したくなったり、データを書き換えたくなることがあると思います。プライベートネットワーク配下に置かれているRDSに対して安全に接続し、DBeaverやpgAdminのようなGUIツールを使って接続できる方法を紹介します。
やりたいこと
- プライベートVPC内のRDSにローカルから直接アクセス
- SQLクライアントのGUIツール(pgAdmin、DBeaver等)でRDSに接続
- 開発・デバッグ作業の効率化
インフラ構成
ECS Fargate と RDS はプライベート VPC ネットワークに置かれているため、直接 ssh することはできません。
今回紹介する方法は、AWS Session Manager の AWS-StartPortForwardingSessionToRemoteHost
を使用してECSタスク内からRDSへのポートフォワーディングを実現します。
[ローカルPC] ←→ [AWS Session Manager] ←→ [ECS Fargate] ←→ [RDS]
事前準備
以下のツールを使用します:
1. AWS CLI
brew install awscli
※ 初期設定は割愛します(AWS認証情報の設定が必要です)
2. jq(JSONパーサー)
brew install jq
3. Session Manager Plugin
brew install session-manager-plugin
4. ECSタスクにSession Managerエージェントがインストールされている
以下のポリシーが ECS タスクロールに割当たっている必要があります
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
"Resource": "*"
}
]
}
接続スクリプト
rds_port_forward.sh
という名前で以下のファイルを作成します:
#!/bin/bash
set -eo pipefail
# 必要なツールの存在確認
check_tool() {
local tool_name=$1
local install_command=$2
if ! command -v $tool_name &> /dev/null; then
echo "$tool_name not found. Install with:"
echo " $install_command"
exit 1
fi
}
# ツールの存在確認
check_tool "aws" "brew install awscli"
check_tool "jq" "brew install jq"
check_tool "session-manager-plugin" "brew install session-manager-plugin"
# 設定値(環境に合わせて変更してください)
CLUSTER_NAME=example_cluster_name # ① ECSのクラスター名を設定します
SERVICE_NAME=example_service_name # ② ECSのサービス名を設定します
REMOTE_PORT_NUMBER=5432 # ③ 接続したい RDS のポート
LOCAL_PORT_NUMBER=5555 # ④ ポートフォワードで使用したいローカルのポート
echo "🚀 RDSポートフォワーディングを開始します..."
# 実行中のタスクARNを取得
TASK_ARN=$(aws ecs list-tasks \
--cluster $CLUSTER_NAME \
--service $SERVICE_NAME \
--desired-status RUNNING | jq -r .taskArns[0])
if [ "$TASK_ARN" = "null" ] || [ -z "$TASK_ARN" ]; then
echo "❌ 実行中のタスクが見つかりません。サービスが起動しているか確認してください。"
exit 1
fi
echo "📋 タスクARN: $TASK_ARN"
# タスクの詳細情報を取得してランタイムIDを取得
RUNTIME_ID=$(aws ecs describe-tasks \
--cluster $CLUSTER_NAME \
--task $TASK_ARN | jq -r .tasks[0].containers[0].runtimeId)
TASK_ID=${TASK_ARN##*/}
# RDSホスト名を取得(SSMパラメータストアから)
RDS_HOST=$(aws ssm get-parameter --name DATABASE_HOST --with-decryption | jq -r .Parameter.Value)
if [ "$RDS_HOST" = "null" ] || [ -z "$RDS_HOST" ]; then
echo "❌ DATABASE_HOSTパラメータが見つかりません。SSMパラメータストアを確認してください。"
exit 1
fi
echo "🗄️ RDSホスト: $RDS_HOST"
# Session Managerのターゲットを構築
TARGET=ecs:${CLUSTER_NAME}_${TASK_ID}_${RUNTIME_ID}
echo "🎯 ターゲット: $TARGET"
echo "🔌 ポートフォワーディング: localhost:$LOCAL_PORT_NUMBER → $RDS_HOST:$REMOTE_PORT_NUMBER"
echo "⏳ 接続を開始します...(Ctrl+Cで終了)"
# Session Managerでポートフォワーディングを開始
aws ssm start-session \
--target $TARGET \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters "{\"host\":[\"$RDS_HOST\"],\"portNumber\":[\"${REMOTE_PORT_NUMBER}\"], \"localPortNumber\":[\"${LOCAL_PORT_NUMBER}\"]}"
使用方法
1. パラメータ設定
環境に合わせて、以下の設定値を編集します:
CLUSTER_NAME=example_cluster_name # ① ECSのクラスター名を設定します
SERVICE_NAME=example_service_name # ② ECSのサービス名を設定します
REMOTE_PORT_NUMBER=5432 # ③ 接続したい RDS のポート
LOCAL_PORT_NUMBER=5555 # ④ ポートフォワードで使用したいローカルのポート
RDSのホストを取得する以下の部分
# RDSホスト名を取得(SSMパラメータストアから)
RDS_HOST=$(aws ssm get-parameter --name DATABASE_HOST --with-decryption | jq -r .Parameter.Value)
これは RDS のホスト名がパラメータストアに DATABASE_HOST
で登録されている場合の実装になっています。環境に合わせて編集してください。
2. スクリプトの実行
sh rds_port_forward.sh
3. SQLクライアントでの接続
ポートフォワードが開始されたら、SQLクライアントで以下の設定で接続:
-
ホスト:
localhost
-
ポート:
5555
- データベース名: RDSのデータベース名
- ユーザー名/パスワード: RDSのユーザー名/パスワード
4. 動作の仕組み
- ECSタスクの特定: 指定されたクラスターとサービスから実行中のタスクを取得
- Session Manager接続: ECSタスク内にSession Managerで接続
- ポートフォワーディング: ローカルポート5555からRDSポート5432への転送を開始
- GUIツール接続: ローカルポート5555経由でRDSにアクセス
この接続方法のメリット
AWS-StartPortForwardingSessionToRemoteHost
を使用してRDSに接続する方法は以下のメリットがあります
1. セキュリティの向上
暗号化通信: Session Manager経由で全ての通信が暗号化される
IAM認証: AWS認証情報のみでアクセス可能(SSH鍵管理不要)
監査ログ: CloudTrailでアクセス履歴が記録される
ネットワーク分離: プライベートVPC内のリソースに安全にアクセス
2. 運用負荷の軽減
SSH鍵管理不要: 従来のBastionホスト方式と違い、SSH鍵の管理が不要
ファイアウォール設定不要: セキュリティグループでSSHポート開放が不要
Bastionホスト不要: 追加のEC2インスタンスが不要
3. スケーラビリティ
ECSタスク自動選択: 実行中のタスクを自動で選択
複数環境対応: 開発・ステージング・本番環境で同じ方式が使える
一時的な接続: 必要な時だけ接続、不要時は切断
4. 開発効率の向上
GUIツール対応: DBeaver、pgAdmin等のGUIツールで直接接続可能
リアルタイム接続: データベースの状態をリアルタイムで確認
デバッグ効率化: 複雑なクエリの実行や結果確認が容易
従来方式との比較
項目 | 従来方式(Bastion) | Session Manager方式 |
---|---|---|
セキュリティ | SSH鍵管理が必要 | IAM認証のみ |
運用負荷 | Bastionホスト管理 | 管理不要 |
監査 | ログ設定が必要 | CloudTrailで自動記録 |
スケーラビリティ | 手動設定 | 自動選択 |
コスト | Bastionホスト費用 | 追加費用なし |
トラブルシューティング
よくある問題と解決方法
-
タスクが見つからない
- ECSサービスが起動しているか確認
- クラスター名とサービス名が正しいか確認
-
DATABASE_HOSTパラメータが見つからない
- SSMパラメータストアにDATABASE_HOSTが存在するか確認
- 適切な権限があるか確認
-
Session Manager接続エラー
- ECSタスクにSession Managerエージェントがインストールされているか確認
- 適切なIAMロールが設定されているか確認
セキュリティ上の注意点
- このスクリプトは開発用です
- 本番環境での使用は十分に注意してください
- 接続はAWS Session Manager経由で暗号化されています
- ローカルポート5555は一時的な接続用です
- 使用後は必ず接続を終了してください
関連ドキュメント
We are hiring!
TAIANでは、このような開発・技術・思想に向き合い、未来をつくる仲間を一人でも多く探しています。少しでも興味を持っていただいた方は弊社の紹介ページをご覧ください。
Discussion