Archive

ブログのホスティング先を Vultr から Cloud Run に移行した

タイトルの通り、これまでこのブログは 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 番号を環境変数に持たせてあげる必要がある。

独自ドメインの登録とマッピング、そしてVPCからの切り替え

ここが結構ハマったところ。 とりあえずコンテナ化をして deploy してみるまではできたのたのだけど、いざ自分のドメインをセットしようと「カスタムドメインを管理」からマッピングの設定に行くも、 対象となるサービスが真っ白で何だこりゃ... となってしまった。

ここで GCP に nameserver 移さなきゃダメかなーと勘違いをしてしまい、「これは見送りかな...」とまで考えてしまったのだけど、雑に Tweet したら中のひとから「 nameserver 移さなくてもできるよー」という旨の Tweet をいただいた。 これがなかったら諦めていたかもしれない... 感謝 :pray:

実際対象となるサービス部分が真っ白になってしまった原因は試しに作った Cloud Run のサービスを一回全部消してしまっていたためで、 ちゃんとデプロイされた状態で「カスタムドメイン管理」に移動したらちゃんと設定をすることができた。

カスタムドメインの設定は使いたいドメインを GCP に登録して、Cloud Run のサービスにドメインをマッピングするという流れでやる。 登録の際に検証するドメインはサブドメインでなくルートドメインでやる必要がある点に注意すれば大丈夫なはず。 指定された内容の TXT レコードを追加すればよい。

image

認証がされたらマッピングの設定が最後までいけるようになるのでやる。

image

その際に「この内容で CNAME レコードを設定してね」と出るのでここも従って対応する。

image

最初は /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 が使えるようになったので早速切り替えた。

image