はじめに
Cloud Datalabは簡単にGCP上でJupyter Notebook環境を構築できるサービスです。しかしGitレポジトリには同じGCPのCloud Source Repositoriesしか使えません。
この記事ではCloud DatalabでCloud Source RepositoriesのかわりにGitHubのレポジトリを使う方法を紹介します。
対象読者
こんな人
- Cloud Datalab使ってみたい
- Cloud DatalabでGitHubレポジトリ使いたい
- Jupyter Notebook運用したくない
- セキュリティもちゃんとしときたい
また、ある程度のJupyter Notebookの知識を前提としています。
TL; DR
-
startup.sh
を使う - https://github.com/nownabe/datalab-with-github の手順通りに操作すればOK
Datalab
Cloud DatalabはGCP上でマネージドなJupyter Notebookを提供するサービスです。
Jupyterに比べてUIがちょっとイケてる感じになってたり、使ってない時間は自動でVM停止して節約してくれたり、GCPと統合されてたり、何かと便利です。マネージドかつ使い捨てできるような仕組みが整っているので運用コストがあまりないのも魅力です。
ガッツリカスタマイズには向いていません。
GitHubを使う3つの方法
前提として、Datalabは各ユーザがそれぞれのDatalabインスタンスを持ち、Gitでコードを共有するというスタイルで利用します。そのため、全Datalabインスタンスから同じレポジトリを参照できるようにする必要があります。
GitHubのレポジトリを使う方法は3つあります。
- Jupyter Notebook上でGitHubのレポジトリをcloneする
-
startup.sh
を使ってDatalabをカスタマイズする - DatalabのDockerイメージをカスタマイズする
この記事では2番目のstartup.sh
による方法を紹介します。
1番目は最も簡単な方法です。しかし、Datalabインスタンスを立ち上げるたびにレポジトリをcloneする必要があります12。また、Source RepositoriesとGitHubのレポジトリが混在することになり、Git操作が複雑になったり運用でカバー的なルールが増えることが考えられます。Datalabの利用者にできるだけ負担をかけたくない、ルールを増やしたくないという理由からこの方法は却下しました。
2番目のstartup.sh
については後述します。
3番目は最も自由度が高い方法ですがヘビーです。DatalabはGCEインスタンス上のDockerコンテナとして動作します。Datalabインスタンス作成時にイメージを指定することができます。この方法では本家のイメージをカスタマイズしてDatalabを利用することができますが、本家の更新に追従する必要があり運用にコストがかかることが想定されます。Datalabを使う理由として運用コスト削減は大きいのでこの方法は却下しました。
startup.sh
startup.sh
はDatalabインスタンスをカスタマイズするために提供されている方法です。PyPIパッケージを追加するといった利用が想定されているようです。
Datalabインスタンス(コンテナ)内の/content/datalab/.config/startup.sh
に任意のシェルスクリプトを作成することでDatalabインスタンス立ち上げ時にstartup.sh
が実行されます3。スクリプトは次のようなコードをNotebookで実行することで作成できます。
%%bash
echo "pip install lib-name" >> /content/datalab/.config/startup.sh
要件・方針
以上を踏まえ、要件は次のようになります。
- Dockerイメージはカスタマイズしない
- Datalabインスタンスから扱えるGitレポジトリはGitHubのもののみとする
- プロジェクト内の全Datalabインスタンスは単一のGitHubレポジトリを使用する
- 誰がDatalabインスタンスを立ち上げても環境を再現できる
実装の方針は次のようになります。
- できるだけシンプル、安全に
-
startup.sh
を使う - GitHubへの認証にはレポジトリのDeploy keyを使う
- Deploy keyの暗号化にはCloud KMSを使う
Deploy keyを使うのは、個人のTokenだと権限がある人であればVMに入って盗み見ることが可能だからです。
この記事では必要最小限の手順のみ紹介します。
構築手順
準備
以下の準備をしておいてください。
- GCPのプロジェクトの用意
- KMS APIの有効化
- Compute Engine APIの有効化
-
jq
コマンドのインストール
環境変数設定
プロジェクト名やレポジトリ名を予め環境変数に設定しておきます。ここでは次のような設定を使用します。
export PROJECT=datalab-with-github-test
export ZONE=asia-northeast1-a
export KEYRING=testkeyring
export KEYNAME=testkey
export DATALAB_NAME=testlab
export REPOSITORY=nownabe/datalab-with-github-test
gcloudセットアップ
gcloud
はインストール済み、認証済みとします。インストールがまだの方はドキュメントを参考にインストールと設定をしてください。
Cloud SDK のインストール | Cloud SDK のドキュメント | Google Cloud Platform
プロジェクトとゾーンを設定しておきます。
gcloud config set project ${PROJECT}
gcloud config set compute/zone ${ZONE}
datalabコマンドインストール
Datalabを扱うdatalab
コマンドは別途インストールする必要があります。
gcloud components install datalab
Deploy Key生成
Deploy keyを生成してGitHubのレポジトリに追加します。
ssh-keygen -t rsa -b 4096 -N '' -f id_rsa
cat id_rsa.pub
生成されたid_rsa.pub
をレポジトリのDeploy keyとして追加してください。また、そのとき"Allow write access"にチェックをいれてください。
レポジトリのSettings > Deploy keysから追加できます。
Deploy Key暗号化
Cloud KMSを使ってDeploy keyを暗号化します。
まずはKMSのKeyRingを作成します。
gcloud kms keyrings create ${KEYRING} --location global
暗号化キーを作成します。今回はローテーションしないようにします。
gcloud kms keys create ${KEYNAME} --location global --keyring ${KEYRING} --purpose encryption
gcloud kms keys remove-rotation-schedule ${KEYNAME} --location global --keyring ${KEYRING}
また、Datalabインスタンスから復号できるようにGCE標準のサービスアカウントに復号の権限を付与します。
gcloud kms keys add-iam-policy-binding ${KEYNAME} \
--location global \
--keyring ${KEYRING} \
--member "serviceAccount:$(gcloud iam service-accounts list | grep "Compute Engine default service account" | awk '{ print $NF }')" \
--role "roles/cloudkms.cryptoKeyDecrypter"
Deploy keyの秘密鍵を暗号化してid_rsa.encrypted
に保存します。
curl -s -X POST \
"https://cloudkms.googleapis.com/v1/projects/${PROJECT}/locations/global/keyRings/${KEYRING}/cryptoKeys/${KEYNAME}:encrypt" \
-d "{\"plaintext\":\"$(<id_rsa base64)\"}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
| jq ".ciphertext" \
| tr -d '"' \
> id_rsa.encrypted
cat id_rsa.encrypted
で暗号化されたことを確認できます。
startup.sh作成Notebookコードの生成
startup.sh
スクリプトは若干複雑なので生成スクリプトを用意しています。
次のコマンドを実行するとstartup.sh
を生成するためのNotebook用のコードが出力されるのでコピーしてください。
curl -s https://raw.githubusercontent.com/nownabe/datalab-with-github/master/template.sh | bash
Datalab作成
Datalabのインスタンスを作成します。
datalab create ${DATALAB_NAME}
しばらくしてインスタンスが立ち上がると自動でブラウザが開きます。開かない場合は http://localhost:8081/
にアクセスしてください。
startup.sh作成
Datalabにアクセスできたら/datalab/notebooks
配下に新しいNotebookを作成してください。
先程のスクリプトを貼り付けてRunをクリックしてください。
これで/content/datalab/.config/startup.sh
が作成されました。
今はまだSource Repositoriesのdatalab-notebooks
というレポジトリが参照されている状態ですが、この状態でインスタンスを再起動するとGitHubのレポジトリが参照されるようになります。
NotebookのPush
再起動する前に、今の状態をSource RepositoriesのレポジトリにPushしておきます。なぜなら、新しくDatalabインスタンスを立ち上げた人が簡単にstartup.sh
を使えるようになるからです。
まず、Notebook上部のメニューからNotebook > Save and CheckpointとしてNotebookを保存します。
次にDatalab上部メニュー右側のGitアイコンからGitクライアントを開きます。
適当なメッセージを入れてNotebookをコミットします。
コミットしたらPushします。「master」をクリックすると「Push」ボタンが現れます。
これでPushされました。Web ConsoleのSource Repositoriesでも確認できます。
これで、あとからDatalabインスタンスを立ち上げた人も簡単にstartup.sh
を利用することができます。
インスタンス再起動
再起動してstartup.sh
を実行します。
Datalab上部メニューの人アイコンからAbout Datalabをクリックします。
Restart Serverというリンクをクリックします。
うまく再起動されない場合はVMを直接再起動してしまいましょう。
gcloud compute instances reset testlab
確認
しばらくすると、再起動されてDatalabに再びアクセスできるようになるのでブラウザでhttp://localhost:8081/
を開きます。
このようにGitHubのレポジトリが参照されているはずです。
先程と同じように新しいNotebookを作成してDatalabからPushするとGitHubに反映されます。
以上でGitHubレポジトリを使ったDatalabの構築が完了しました。
新しいDatalabインスタンス
新しいDatalabインスタンスから同じGitHubレポジトリを使うには最初に作成したNotebookを利用します。
確認してみましょう。
まず、最初に立ち上げたDatalabインスタンスへの接続を解除します。ProxyしているプロセスをCtrl+Cで殺してください。
新しいDatalabインスタンスを作成します。
datalab create testlab2
立ち上げた直後はまだSource Repositoriesのレポジトリを参照しています。初回の構築時とは異なりstartup.sh
を生成するNotebookがあります。
初回と同じようにこのNotebookを実行してstartup.sh
を生成し、インスタンスを再起動してください。
再起動が完了すれば同じGitHubレポジトリを参照できているはずです。
startup.shの解説
最後に、簡単にstartup.sh
の内容を説明をします。
ざっくりと次のことを順番に行っています。
- 新しいGitをインストール
- Datalabに標準で入っているGitクライアントが古く
core.sshCommand
を使えないため
- Datalabに標準で入っているGitクライアントが古く
- Deploy keyの復号
- Source Repositoriesのレポジトリを削除して、同じ場所にGitHubのレポジトリをclone
-
startup.sh
自身を削除- GitHubレポジトリの方で本来の使い方の
startup.sh
を管理できる
- GitHubレポジトリの方で本来の使い方の
おわりに
紹介した方法を利用すると専用のサービスアカウントを作成してさらに厳しくしたり、インスタンスごとに参照するレポジトリを変えたりということもできます。
なにかとSource Repositoriesではなく普段使っているGitサーバを使いたいことが多いと思うので、そのときは是非試してみてください。
-
1つのPersistent Diskを使い回せば不要ですが、Datalabはインスタンスごとにシングルユーザとなっていてユーザごとにインスタンスを作成するという前提なので現実的ではありません。 ↩
-
Source Repositoriesのレポジトリ内にGitHubのレポジトリをcloneするという方法もありますが複雑性は排除できません。 ↩
-
https://github.com/googledatalab/datalab/blob/master/containers/datalab/content/run.sh#L107-L114 ↩