Conclusion
SSM を用いて RDS へのポートフォワーディングを行い、Docker 経由でコマンドを叩く
Motivation
AWS RDS はマネージドなリレーショナルデータベースサービスです
Amazon RDS(マネージドリレーショナルデータベース)| AWS
一般的にリソースはプライベートサブネット上に作成するためローカルマシンから直接クライアントコマンドを用いて接続することはできません
そこで多くの場合は RDS へアクセスできる IAM ロールを持つ踏み台 EC2 サーバを立ててセッションマネージャ等で RDS に接続します
ただし「データのダンプもしくはリストアを行いたい」という要件がある場合に、セッションマネージャだと EC2 内のファイルのやりとりに困ります
下記の方法などを用いることで可能ではありますがデメリットがあります
- S3 を介して EC2 とファイルやりとりを行う
- S3 バケットの作成と EC2 へのアクセス権の設定が必要
- Key Pair を用いて SCP コマンドで EC2 とファイルの転送を行う
- Key Pair の管理が必要、接続するユーザが
ssm-user
からec2-user
に変わってしまう
- Key Pair の管理が必要、接続するユーザが
そこで今回は AWS SSM を用いたリモートホストへのポートフォワーディング を用いて、ローカルマシンから RDS に対して直接コマンド操作できるようにするやり方を説明します
また今回は Docker を用いることでローカルマシンにクライアントツールをインストールを回避します、これによりクライアントとサーバのバージョンを合わせつつローカルマシンの環境を汚すことも回避できます
Prerequisite
- 下記の要件を満たす踏み台 EC2 サーバが用意されている
- RDS へアクセスできる IAM ロールがアタッチされている
- EC2 にはバージョン
3.1.1374.0
以上の SSM Agent がインストールされている
- ローカルマシンに AWS CLI / Docker / Session Manager Plugin がインストールされている
Method
aws ssm start-session
を用いてポートフォワードを用います
aws ssm start-session \ --target "<踏み台 EC2 インスタンスID>" \ --document-name AWS-StartPortForwardingSessionToRemoteHost \ --parameters \ '{ "host": ["<リモートホスト名>"], "portNumber": ["<リモートポート番号>"], "localPortNumber":["<ローカルポート番号>"] }'
リモートホスト名
リモートポート番号
は RDS のデータベースページから参照できます
成功すると下記のようなログが流れます
Starting session with SessionId: xxxxx Port 3306 opened for sessionId xxxxx. Waiting for connections...
Port 3306
の箇所は ローカルポート番号
で指定したポートになります
実行中の間は該当ポートにクライアントから接続することができます
次に別のシェルを開いて Docker を用いて接続を行います
# MySQL の場合 docker run --name <コンテナ名> --rm -it mysql:5.7 /bin/bash mysql -h host.docker.internal -P <ポート番号> -u <DB ユーザ名> -p # PostgreSQL の場合 docker run --name <コンテナ名> --rm -it postgres:11 /bin/bash psql -h host.docker.internal -p <ポート番号> -U <DB ユーザ名>
mysql:5.7
postgres:11
の箇所は RDS で利用しているバージョンに合わせてください
ホストオプションで host.docker.internal
を指定することで Docker コンテナ内からローカルマシンのネットワークにアクセスすることができます
※ macOS でのみ検証しているため、他 OS では異なる可能性があります
別途ダンプファイルのやり取りを行う場合は2通り方法があります
# コマンドでファイルの転送のやり取り docker cp /path/to/dump.sql $(docker ps -qf "name=<コンテナ名>"):/path/to/dump.sql # Volume マウントをアタッチ docker run -v /path/to/workspace:/path/to/workspace --name <コンテナ名> --rm -it ...