ローカルとAWS ECS上のマイクロサービスをSSH経由でつなぐmogura
マイクロサービス開発向けに、moguraというツールを開発しています。Twitterではちょいちょいリリースを呟いて、細かいバージョンアップを行っています。一旦落ち着いたので、moguraが何を解決するためのツールで、何をしてくれるのか紹介します。
背景と課題
マイクロサービス化を進めていて、複数のサービスがECS上で動作しています。それらをまとめて使うサービスを開発しようとした時に、全てローカル環境で構築するのは困難で、AWS上の開発環境に接続したくなります。RDSやelasticsearch service、他EC2で動かしているサービスは、Aレコード、CNAMEのドメインと特定のポートに対して、トンネルを作れば動いていたので、シェルでsshコマンドを実行するだけでも何とかなっていました。
例えば、以下のようにbastion.example.com
サーバにSSH接続して、localhost:8080
にremote.example.com:80
への通信をバインドするという形が取れます。
ssh bastion.example.com -L 8080:remote.example.com:80
しかし、ECSのサービスを起動すると各タスクは、クラスタ上のホストと自由なポート番号で動き、それがSRVレコードとして登録されます*1。sshトンネルはAレコードやCNAMEは解決してくれますが、SRVレコードを解決してポート含めて対応をしてくれません。そのため、ECSにデプロイするたびに、自分でECSコンソールを見る or SRVレコードを引いて、結果をもとにsshトンネルコマンドを実行するという作業をする必要がありました。
課題一覧
- ECSが作るSRVレコードが解決できない(これはSRVレコード自体が解析できないことと、VPC上でのみで解決可能なPrivateDNSの2つがあります)
- デプロイのたびに変わる接続先を手動で解決する必要がある
- それらに対するSSHトンネリングを作り直す必要がある(SSHコマンド再実行)
流石にそれは非効率すぎるので、少し前に書いた以下をベースにmoguraを実装しました。
修正やエラー制御等々を追加したので、その時からは実装がだいぶ変わっています。
moguraは何をしてくれるのか
moguraに以下を設定します。
まず、VPC環境にアクセスするための踏み台サーバ(bastion)へssh接続を行います。そこから、bastion上でDNSを解決し、繋ぎたいサービスの接続先とポートを取得してトンネルを作り、ローカルポートへの接続があったら、トンネルを通してデータを送受信しています。
moguraを使えば、設定に書いてある接続先がSRVレコードでも解決してくれるので、まず自分でSRVレコードを引く必要がありません。複数を設定に書いて一気に起動できるので、例えばマイクロサービスA,B,CとMySQLサーバ、elasticsearchサーバへの接続を一気に確立する(localポートにバインドする)といったことが可能です。また、定期的なDNSの再解決、接続が切れたら再接続をしてくれるので、スムーズにECS上の他のサービスやRDSなどとの接続を使うことができます。
細かい使い方についてはmoguraのREADMEをご覧ください。
今後の展望
とりあえず、面倒臭い部分の解決が実現でき、再接続などの使用中の細かい挙動については修正できました。ツールとしては、一定使える状態になっています。同僚などに使ってもらい、便利、楽といった感想をもらえているので満足です。
以下のような部分を実装すると面白そうだなと思いつつ、そんなにすぐ必要性を感じていないので、保留状態です。
- SRVレコードの解決で、優先順位の判断やバランシングは行なっていないといった細かいもの
- System Manager/Instance connectの機能で、IAMユーザでのSSH接続確立ができるようになったので、それを使ったbastionへの接続対応
- fault injection? (通信断の意図的な発生)
- ECSサービスを自動で検出する(今は設定に明示的に書く必要があるので、動的か、実行して設定ファイルを自動生成するか)
- bastionサーバがEC2前提なので、それもFargateなどで動的に起動して使えるといった自動構成
System ManagerのSSHあたりは、mogura作って以降、(たまたま)急に拡充されだしました。
- EC2のSSHアクセスをIAMで制御できるEC2 Instance Connectが発表されました | DevelopersIO
- セッションマネージャーが SSH と SCP のトンネリングサポートを開始
- AWS System Manager Sessions Manager を使用した新しい機能 – Port Forwarding | Amazon Web Services ブログ
fault injectionは本当はenvoyなどのサイドカーで行うの良さそうですが、開発中のテスト用に簡易的なものはmoguraに入れといてもいいかなと思っています。 - envoy/examples/fault-injection at master · envoyproxy/envoy · GitHub
bastionサーバは、必要な時にFargateで起動して使えるとかだとEC2を管理する必要のなくなり、運用しやすそうなので、うまいこと作りたいです。
*1:ServiceDiscoveryを指定した場合