タイトルの通り、これまでこのブログは Vultr の VPC 上で起動した h2o 経由で配信をしていたのだけど、 Cloud Run に移行したのでその辺もろもろ記録として書いておく。
Cloud Run
- GCP の新サービスで Docker コンテナをサーバレスで実行できるというもの。まだベータ。
- 自分で Docker image を用意さえできればそれ以外の縛りは無いっぽい(雑な解釈)
それ〇〇でよくね?
このブログは static site generator の pelican で Markdown or ReST をビルドしたものを利用した静的サイトなので、正直他にもっと楽にいい感じにブログ環境は整えられるとは思っている。 Netlity とかはよく聞くし、S3 + Cloudfront でもいいし、Github Pages でもよい。なんだけど、せっかく自分で好き勝手できるサイトでもあるので、興味のあるサービスとか技術まわりをさわる実験台にしたいという思いもあって敢えて手をかけているというところが大きい。
実際、現状の業務でなかなか触る機会がなかった GCP をそこそこ触ってなるほどなーと実感できる機会を今回は得た。
ざっくり before/after
before
- ブログのソースは gitlab.com で管理
- gitlab-ci を利用
- commit 発生時にビルド用の docker image laughk/pelican-sitebuilder を使って CI を回し、直接コマンドを実行してサイトを生成
- master commit の場合は生成したサイトコンテンツを rsync + ssh で VPC に転送する形で CI 経由でデプロイ
after
- ブログのソースは gitlab.com で管理
- gitlab-ci を利用
- commit 発生時に google/cloud-sdk で CI を回し、 dind で laughk/pelican-sitebuilder を docker run してサイト生成
- 生成したコンテンツを含んだ docker image の build と gcr への push
- master commit の場合に
gcloud beta run deploy
を実行
やったこと
そんなわけで今回の移設で大体以下のことをやった
- コンテンツを突っ込めばいいだけの dokcer image を作成
- GCP の使い方や gcloud コマンドの使い方を色々試行錯誤
- 独自ドメインの登録とマッピング、そしてVPCからの切り替え
- gitlab-ci.yaml の更新
コンテンツを突っ込めばいいだけの dokcer image を作成
このサイトは静的サイトなので適当な HTTP サーバを用意して配信する必要がある。特にこだわりが無いのであれば nginx の公式 image を使ってやるのが手っ取り早いし色々いいんだろうけど、 せっかくなので h2o の image を用意してやってみることにした。
で、これを用意。
h2o.conf
を用意して /etc/h2o.conf
に copy して、配信したい静的コンテンツは /srv
配下に置くということだけを前提にしている。
あとコンパイル周りで下手にハマりたくなかったので ubuntu の image を使っている。
自分用と割り切っていてドキュメントとか全く用意できていない...
GCP の使い方や gcloud コマンドの使い方を色々試行錯誤
まず、 gcloud コマンドや、そもそもの GCP の使い勝手が全然わかっていなかったのでコンパネからガチャガチャやったり、適当にコマンド実行して色々作ったり壊したりして感覚を掴んだ。 公式のドキュメントにもコンパネでやる場合と CLI でやる場合の両方が解説されてたりしてやりやすかった。
あと Cloud Run に関しては以下の記事も参考にさせてもらった。
この当たりで、以下の事を把握
- Cloud Run で実行するコンテナは GCR に push されてる image でないといけない (Gitlab の registory はダメだった)
gcloud builds submit
は必須じゃない。- むしろ git 管理下でないファイルを突っ込もうとしたら色々ハマった
- ローカルで build した image を
docker push gcr.io/:project_id/:image_name
しておけばよい
- docker container で Listen する PORT 番号を環境変数に持たせてあげる必要がある。
- ref. Migrating an Existing Service | Cloud Run Documentation | Google Cloud
- Dockerfile に
ENV PORT (PORT番号)
を入れとかないと上手く起動できない
独自ドメインの登録とマッピング、そしてVPCからの切り替え
ここが結構ハマったところ。 とりあえずコンテナ化をして deploy してみるまではできたのたのだけど、いざ自分のドメインをセットしようと「カスタムドメインを管理」からマッピングの設定に行くも、 対象となるサービスが真っ白で何だこりゃ... となってしまった。
ここで GCP に nameserver 移さなきゃダメかなーと勘違いをしてしまい、「これは見送りかな...」とまで考えてしまったのだけど、雑に Tweet したら中のひとから「 nameserver 移さなくてもできるよー」という旨の Tweet をいただいた。 これがなかったら諦めていたかもしれない... 感謝 :pray:
You should be able to keep your domain and DNS provider.
— Steren (@steren) July 15, 2019
When you setup a custom domain, you you be asked to update your DNS with a A or CNAME record
実際対象となるサービス部分が真っ白になってしまった原因は試しに作った Cloud Run のサービスを一回全部消してしまっていたためで、 ちゃんとデプロイされた状態で「カスタムドメイン管理」に移動したらちゃんと設定をすることができた。
カスタムドメインの設定は使いたいドメインを GCP に登録して、Cloud Run のサービスにドメインをマッピングするという流れでやる。 登録の際に検証するドメインはサブドメインでなくルートドメインでやる必要がある点に注意すれば大丈夫なはず。 指定された内容の TXT レコードを追加すればよい。
認証がされたらマッピングの設定が最後までいけるようになるのでやる。
その際に「この内容で CNAME レコードを設定してね」と出るのでここも従って対応する。
最初は /etc/hosts
でちゃんと表示されることを確認してから CNAME を設定しようとしたものの、
CNAME が反映されないと SSL 証明書も生成されずに表示の確認しようもなかったので、エイヤで切り替えまでやってしまった。
初回のSSL証明書生成に15分くらいかかってしまうので、切り替え中にブラウザでアクセスするとエラーになってしまうのだけど
「まあ自分のブログだし...」とそこは割り切った。
gitlab-ci.yaml の更新
無事に Cloud Run に切り替えられたところで、自動デプロイ周りも変更した。 static site generator によるブログの場合正直これが止まってしまうのはつらいので。
VPC 時代も直接コマンド叩いて生成したサイトのコンテンツを VPC にせっせと rsync してもらう感じに自動化はしていたのだけど、 マネージドな環境にのっかったのでもうちょっと今っぽいやり方に変更。
変更後の .gitlab-ci.yaml
は以下。
image: google/cloud-sdk:alpine
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
PELICAN_BUILDER_IMAGE: laughk/pelican-sitebuilder:2019-05-19T073000
BUILD_IMAGE: gcr.io/${PROJECT_ID}/memo.laughk.org
services:
- docker:dind
stages:
- build
- docker
- deploy
before_script:
- apk add --no-cache git docker
- gcloud auth activate-service-account --key-file ${GCLOUD_SERVICE_KEY}
- gcloud config set project ${PROJECT_ID}
site_build:
stage: build
script:
- git clone https://github.com/laughk/pelican-hss
- docker run -v "$(pwd):/project-root" -v "$(pwd)/pelican-hss:/my-theme" ${PELICAN_BUILDER_IMAGE} builder -T -c publish
artifacts:
paths:
- output/
docker_build_and_push:
stage: docker
script:
- gcloud auth configure-docker
- docker build -t ${BUILD_IMAGE}:${CI_COMMIT_SHORT_SHA} .
- docker push ${BUILD_IMAGE}:${CI_COMMIT_SHORT_SHA}
dependencies:
- site_build
deploy_to_cloudrun:
stage: deploy
script:
- gcloud components install beta
- gcloud beta run deploy memo-laughk-org --project ${PROJECT_ID} --image=${BUILD_IMAGE}:${CI_COMMIT_SHORT_SHA} --region us-central1 --platform=managed
only:
- master
dependencies:
- docker_build_and_push
簡単にポイントだけメモしておくと以下
service: ["docker:dind"]
で docker in docker ができるようになるGCLOUD_SERVICE_KEY
には GCP のサービスアカウントの秘密鍵(json形式)の中身を突っ込んでいる。 variables の type を file にしているので、この環境変数自体は file パスになる。cat > filename.json
とかしなくていいので便利。- このジョブを実行する際の最低限の Role は「Cloud Build 編集者」「サービス アカウント ユーザー」「Cloud Run 管理者」「ストレージ管理者」「閲覧者(project)」でいけた
- Cloud Run のデプロイには 「サービス アカウント ユーザー」 がないとダメだった
Cloud Run 移設やってみて
- ずっとやれてなかった GCP を触る時間がやっとつくれた
- Cloud Run の「Docker image さえ用意すればOK」感が静的サイトでも結構ガチャガチャクラウドサービス触れていい感じ
- デプロイ周りもシェルスクリプトで頑張る感じが減ってやりやすくなった
という感じで総じてやってよかったなというのが今の所の所感。あとは1ヶ月くらい動かしてコストも見ながら最終的にどうするか決めようかなという感じ。 Vultr も十分安いので...
追記 (2019-07-17)
日本リージョンでも Cloud Run が使えるようになったので早速切り替えた。
日本リージョン来たので早速切り替えた。追加で asia-northeast1 にデプロイしてドメインマッピングは一度削除してやり直したけど、結構スムーズに切り替わった感想
— Kei IWASAKI (@laugh_k) July 16, 2019