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 のパワーを使って開発したいというケースなどに活用できるのではないでしょうか。