Paper2 Blog

ともに、かける

Cloud Run上でシェルを実行し、素早くデバックする

Cloud Runで新しいツールなどを検証する際に修正してはデプロイを待ち、再検証というループを回したことはあると思います。 Kubernetesのkubectl execコマンドやdebugコマンドでコンテナ上で直接作業したいな〜と思うことありますよね。

そこでCloud Run上でシェルを実行し、検証などをしやすくする方法を紹介します。上記のexecやdebugコマンドほど便利ではないので定常運用には向かないと思いますが、Cloud Run上で色々検証したい時に役立つと思います。リポジトリはこちらです。

github.com

仕組み

SSHのようにこちらからCloud Runに向けて接続をすることができないので、netcat(nc)を用いてCloud Runからこちら側に向けて接続をしてもらいます。netcatはネットワーク管理およびデバッグのための多目的ツールです。特定のポートで接続を待機し、受け取ったデータをシェルに流して実行することや逆にデータを送ることなどもできます。

図にするとこんな感じです。

VM上で nc -vlp 1234 コマンドを実行し、Cloud Runからの接続を待ちます。

netcatやVMへの接続処理をパッケージしたCloud Run Debugger ContainerをCloud Run上でサイドカーコンテナとして起動します。 このコンテナからVMへの接続が完了すると、コマンドをVM上からCloud Run上のBashに伝えて実行することができます。

使い方

1. Google Projectの設定

$ gcloud config set project <Your Project ID>
$ export GOOGLE_PROJECT=<Your Project ID>

2. VMとCloud Runの作成

$ cd terraform
$ terraform apply    
...
Plan: 3 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
...

3. VM上でnetcatの接続を待つ、接続できたらコマンドを実行

$ gcloud compute ssh --zone asia-northeast1-b cloud-run-debugger -- nc -vlp 1234
listening on [any] 1234 ...
connect to [10.146.0.5] from 160.249.203.35.gae.googleusercontent.com [35.203.249.160] 44205

free   <--- Cloud Run上でfreeコマンドを実行している。
               total        used        free      shared  buff/cache   available
Mem:         1048576       16872     1031704           0       12448     1031704
Swap:              0           0           0

詳細解説

Cloud Run Debugger Container

DockerfileのCMDではnetcatで受け取った入力をスクリプトに渡すようになっています。

# Write a simple script to redirect the standard error output in Bash and send it via netcat.
CMD ["/bin/bash", "-c", "nc.traditional -v $PUBLIC_IP 1234 -e redirected_bash.sh"]

このスクリプト内では標準エラー出力を標準出力に向けてbashを実行しています。

#!/bin/bash
exec 2>&1
/bin/bash

このようにしないとCloud Runで実行するコマンドでエラーがでても、Cloud Run上のログに出力されてしまいVM上のプロンプトにはフィードバックがなくなってしまいます。Cloud Runのログとしてログエクスプローラーで確認はできます。出力されるまでの遅延などがあるのですぐフィードバックを得られるように工夫しました。

Cloud Runの設定

デバック中はインスタンスが0にならないようにmin_instance_countを1にしています。また、リクエストがないとCPUを割り当てられずデバック作業ができなくなってしまうのでCPUが常に割り当てられるようにしています。複数のインスタンスが立っているとnetcatのコネクション確立に失敗し続けるので、max_instance_countも1にしています。

resource "google_cloud_run_v2_service" "cloud_run_debugger" {
  ...
  template {
    scaling {
      # Prevent from zero scailing.
      min_instance_count = 1
      max_instance_count = 1
    }
    containers {
      ...
    }
    containers {
      ...
      resources {
        # Ensure the debugger container always has CPU resources.
        cpu_idle = false
      }
    }
  }
}

まとめ

Cloud Run上のシェルでインタラクティブにデバックする方法を紹介しました。私自身、まだこの仕組み自体を試してみた段階で色々検証はできいません。これから色々試していきたいと思っています。

参考