Windows で VS Code + Remote Development + IAP で Google Compute Engine に接続する
はじめに
Google Cloud の開発をしている時に、Google Compute Engine(GCE) に Visual Studio Code(VS Code) をつなぎたいというケースがあると思います。
VS Code には Remote Development という拡張機能があり、ssh でリモートマシンに接続するということができるのですが、組織によってはインターネットへの ssh のポートが塞がれていたりするケースもあるため、GCE にはそのままでは接続できません。
今回はこのような場合に対応する方法をご紹介します。
コマンドラインなら接続できる
VS Code ではなく、Google Cloud のコマンドラインツールである、gcloud CLI から Identity-Aware Proxy(IAP)を経由して、GCE に ssh 接続するということは簡単にできます。
gcloud compute ssh INSTANCE --project=PROJECT_ID --zone=ZONE_NAME --tunnel-through-iap
あるいは、ポートフォワードする場合には、start-iap-tunnel
というコマンドも利用できます。
たとえば、下の例の場合は、ローカルホストの8080番ポートを GCE の80番ポートに転送する場合です。
gcloud compute start-iap-tunnel INSTANCE 80 --project=PROJECT_ID --zone=ZONE_NAME --local-host-port=localhost:8080
これらを使って接続ができるのではないか?と思い検索してみたところ、いくつか参考になる記事は見つけられたのですが、どれも少し説明が欠けていたりして、私の環境ではうまくいかないケースがありましたので、それらを補足しながら説明しようと思います。
事前準備
Google Cloud
- GCE には IAP で ssh の通信ができるようにファイアウォール設定済み
- GCE は外部IP、または Cloud NAT を通じてインターネットに接続可能(後ほど理由を説明します)
Windows マシン
gcloud
gcloud ツールはインストール済みで、gcloud auth login
でログイン済みという前提とします。
Windows 版 OpenSSH
gcloud で ssh を行うときには、gcloud に含まれる putty が起動してから接続するのですが、VS Code の拡張機能は Windows 標準の OpenSSH を利用するので、インストールされているかを確認して、未インストールであればインストールしてください。
# PowerShell(管理者として実行)でコマンドを打つ
Get-WindowsCapability -Online | ? Name -like 'OpenSSH.Client*'
Name : OpenSSH.Client~~~~0.0.1.0
State : NoPresent
# StateがNotPresentの場合は、OpenSSHクライアントをインストール
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
もちろん、VS Code には Remote Development 拡張機能をインストールしておいてください。
gcloudで接続パラメータを確認する
先ほど紹介した、IAP 経由で ssh 接続する際に、内部的にどのようなパラメータを実行しているかを --dry-run
モードで参照することができます。次のコマンドをコマンドプロンプト、または PowerShell で実行します。(管理者モードの必要はありません)
gcloud compute ssh INSTANCE --project=PROJECT_ID --zone=ZONE_NAME --tunnel-through-iap --dry-run
このとき、外部IPを持っている GCE に対してはじめて実行すると次のようなメッセージが表示されます。
# 出力が長いので途中で折り返しています
# google-cloud-sdk までのパスはインストール時に指定した場所に読み替えてください
Writing 3 keys to C:\Users\ユーザー名\.ssh\google_compute_known_hosts
C:\tools\google\google-cloud-sdk\bin\sdk\putty.exe -t
-i C:\Users\ユーザー名\.ssh\google_compute_engine.ppk
-proxycmd ""C:\\tools\\google\\google-cloud-sdk\\platform\\bundledpython\\python.exe"
"C:\\tools\\google\\google-cloud-sdk\\lib\\gcloud.py" compute start-iap-tunnel
"INSTANCE" "%port" --listen-on-stdin --project=PROJECT_ID
--zone=ZONE_NAME --verbosity=warning" ログインユーザー@compute.1234567890098765432
最初の行に出力されている Writing 3 keys ...
の通り、google_compute_known_hosts
を参照すると、GCE のインスタンス ID あたりに3行のキーが登録されているのがわかると思います。通常の ssh であれば、.ssh\known_hosts
ファイルにこれらのキーが登録されるのですが、gcloud コマンドを経由するとこのファイルに書き込まれます。
ただし、外部IPを持たない GCE に対して実行しても、これらのキーはどこにも書き込まれません。キーがないと ssh 接続ができないので問題ですが、後ほど解決します。
そして、2行目は ssh を実施する時に、putty の実行とそれに渡されるパラメータが列挙されています。
Windows 版 OpenSSH で実行する
パラメータの編集
上のステップで判明した putty に渡すパラメータを利用して、VS Code が内部で使用する OpenSSH を使って実行してみます。このとき putty のパラメータを ssh で解釈できるように編集します。
具体的には i
と -proxycmd
を次のように変更します。
# 変更前
-i C:\Users\ユーザー名\.ssh\google_compute_engine.ppk
# 変更後(ppkファイルでは ssh が実行できないため)
-i C:\Users\ユーザー名\.ssh\google_compute_engine
# 長いので改行していますが、変更前も変更後も 1 行です
# 変更前
-proxycmd ""C:\\tools\\google\\google-cloud-sdk\\platform\\bundledpython\\python.exe"
"C:\\tools\\google\\google-cloud-sdk\\lib\\gcloud.py" compute start-iap-tunnel
"INSTANCE" "%port" --listen-on-stdin --project=PROJECT_ID
--zone=ZONE_NAME --verbosity=warning"
# 変更後
# ssh のオプション ProxyCommand として実行します。python, gcloud.py はフルパスで記述してください。
# %port は %p に変更してください。
-o ProxyCommand='"C:\\tools\\google\\google-cloud-sdk\\platform\\bundledpython\\python.exe"
"C:\\tools\\google\\google-cloud-sdk\\lib\\gcloud.py" compute start-iap-tunnel
"INSTANCE" %p --listen-on-stdin --project=PROJECT_ID
--zone=ZONE_NAME --verbosity=warning'
変更したパラーメータで ssh を実行すると、接続できることが確認できるはずです。
# 長いので改行しています
ssh -t -i C:\Users\ユーザー名\.ssh\google_compute_engine
-o ProxyCommand='"C:\\tools\\google\\google-cloud-sdk\\platform\\bundledpython\\python.exe"
"C:\\tools\\google\\google-cloud-sdk\\lib\\gcloud.py" compute start-iap-tunnel
"INSTANCE" %p --listen-on-stdin --project=PROJECT_ID
--zone=ZONE_NAME --verbosity=warning' ログインユーザー@compute.1234567890098765432
このとき、外部IPを持つ GCE は .ssh\google_compute_known_hosts
にあるキーで接続しているので何も言われませんが、外部IPを持たない GCE の場合は次のように質問されるので yes
を入力することで .ssh\known_hosts
にキーが登録されて接続できるようになります。
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?
ssh の cofnig を編集する
.ssh\config
を編集すると上記のような長いパラメータを省略して ssh を実行できます。VS Code の拡張機能もこのファイルを参照するので編集します。
# google-cloud-sdk までのパスはインストール時に指定した場所に読み替えてください
# パスにスペースが含まれる場合はダブルクォーテーションで囲ってください
# Host は ssh を呼び出す際の任意の名称です
# 外部IPを持つ GCE の場合
# UserKnownHostsFile に google_compute_known_hosts を指定する
Host gce-A
HostName compute.1111111111111111111
IdentityFile C:\Users\ユーザー名\.ssh\google_compute_engine
ProxyCommand C:\tools\google\google-cloud-sdk\platform\bundledpython\python.exe -S C:\tools\google\google-cloud-sdk\lib\gcloud.py compute start-iap-tunnel INSTANCE_1 %p --listen-on-stdin --project=PROJECT_ID --zone=ZONE_NAME --verbosity warning
UserKnownHostsFile C:\Users\ユーザー名\.ssh\google_compute_known_hosts
User ログインユーザー
# 外部IPを持たない GCE の場合
Host gce-B
HostName compute.2222222222222222222
IdentityFile C:\Users\ユーザー名\.ssh\google_compute_engine
ProxyCommand C:\tools\google\google-cloud-sdk\platform\bundledpython\python.exe -S C:\tools\google\google-cloud-sdk\lib\gcloud.py compute start-iap-tunnel INSTANCE_2 %p --listen-on-stdin --project=PROJECT_ID --zone=ZONE_NAME --verbosity warning
User ログインユーザー
これで ssh gce-A
とコマンドを実行すると、GCE に接続できることが確認できます。
VS Code からリモート接続する
ここまで設定しておくと、VS Code からの接続は簡単です。
画面左下のリモート接続ボタンをクリックし、「ホストに接続する…」を選択します。
すると、先ほど .ssh\config
に記述した Host の一覧が表示されるので選択します。
別の VS Code ウィンドウが開き、接続先マシンの OS を選択するようにドロップダウンが出るので Linux を選択します。
接続が始まると、接続先の GCE の内部に、VS Code Server という VS Code のリモート接続に必要なツールのインストールが始まります。
このとき GCE がインターネットに接続できないと、VS Code Server をダウンロードしてくることができないため、GCE が外部IPを持っているか、持っていない場合は Cloud NAT を設定しておく必要があります。
接続が成功すると画面左下のマークが接続中であることが表示されます。
まとめ
Cloud Shell Editor や Cloud Workstations を使って開発環境を整える方法もありますが、ローカルの VS Code から接続して GCE のパワーを使って開発したいというケースなどに活用できるのではないでしょうか。