Golangでビルドした社内ツールの接続問題調査記録
こんにちは。estieでソフトウェアエンジニアをしている木村です。
最近、社内で利用するツールの開発中に興味深い調査を行いました。このツールは、ローカル環境から社内の開発環境に接続しやすくするためのもので、内部でAWSのSession Manager Pluginを活用しています。開発の過程で、このPluginをGolangでビルドして組み込む(RustからGoを呼び出す話も面白いので興味があればぜひ
Rust から Go で書かれた関数を呼ぶ - estie inside blog も!)ことを試みたところ、接続が30秒で切断されるという問題に直面しました。この記事では、その問題をどのように特定し解決したかについて紹介します。
調査の手がかり
いきなり結論に近いのですが問題の原因を探る中で、以下のGitHub Issueを見つけました。
これらのIssueを読み解くと、Session Manager PluginのビルドにおいてVERSIONというファイルが重要な役割を果たしていることがわかります。公式ビルドでは、このVERSIONファイルが適切に更新された上でmakeが実行されているようです。(READMEの通りにビルドするとこの手順は書かれていないので結構な罠です……。)
手元の環境で公式のビルドプロセスを模倣するために、VERSIONファイルを編集して公式ビルドのバージョン番号を設定し再ビルドをしてみました。その結果、30秒で接続が切れる問題は解消されました。驚いたことに、ソースコードそのものにほぼ変更は加えず、バージョン番号の変更だけで問題は解決されました!
原因をもっと深掘りしてみる
一件落着と言いたいところですが、ソースコード自体はほぼ変わっていないのにバージョンを変えただけで動くようになるのは謎です。さらに深ぼってみると、以下のことが判明しました。
session-manager-pluginはhandshakeの際にCLIのversionをリクエストのパラメータとして送っていて、
amazon-ssm-agent側では
送られてきたバージョンを元に処理を分岐していそうなことがわかります。
Disable smux KeepAlive or else it breaks Session Manager idle timeout.
コメントにあるように、smux
のKeepAlive設定がSession Managerのアイドルタイムアウトに影響を与えるバグがあったようで、バージョンに応じてsmux
の設定が分岐していました。そのため、送信されるバージョン番号を変更するだけで挙動が変化していました。
まとめ
今回はソースコードから session-manager-pluginをビルドした時だけに起こる謎のバグについての記録でした。この問題に関するissueは探してみると複数件あり、他の人が同じ問題に直面しないようにプルリクエストを作成しましたが、session-manager-plugin は外部のコントリビューターのプルリクエストを受け付けていない雰囲気があり、マージされる可能性は低そうです……。
もし、session-manager-pluginをソースコードからビルドすることがあれば?この記事が何かの参考になれば幸いです。
社内ツール開発が面白そうだなと思った方、一緒に課題解決に取り組んでみたいという方がいらっしゃいましたらぜひ下記カジュアル面談のフォームからご連絡ください!