祝・ITエンジニアブログ一周年 と CI/CD 開通
こんにちは ㊗️ ホシイです。
当ブログ、ちょっと日が過ぎてしまいましたが、先日一周年を迎えました ㊗️
こうしてご訪問いただく皆様のおかげです。これからもよろしくお願いいたします。
当ブログの運用
そしてようやくついこのあいだなのですが、ブログ運営に大きな仕組みのアップデートをしました。今更感もありますが、自動 build からの自動での preview 環境への反映をようやく達成したのです。
git commit → push すると、それを trigger としてサイトを build し、確認環境 (preview 環境) への反映までを行います。
以前の記事 に一度書いていましたが、これまでは preview 環境への反映も手動でした。当ブログ作成に使用している Hugo では test server の起動もかんたんなので手元でもすぐに確認はできるのですが、手元に環境がない人に記事のレビューを依頼するときなどはやはりすぐに閲覧ができるサイトがあると便利です。この反映が自動になることで、手間の軽減はもちろん、誰が記事を書いても確実に preview site に更新がされることで、レビューの確実性もあがりそうです。
以下、この仕組みを順にざっと説明します。
CI でやっていること
まず、当ブログのソースは、自前で構築した GitLab™1 環境で host しています。記事を書く人それぞれが git clone してソースを手元に置き、作業しています。
GitLab には GitLab CI/CD というツールが用意されています。git repo に .gitlab-ci.yml
という名前で pipeline 設定を書いておくとその指示に従って処理をしてくれる仕組みです。かんたんに言うとそこに、「Merge Request がある branch に push をされたら build & deploy をしてね」という指示を書いて動作させています。上の図で言うと CI Runner のところです。
以下、CI Runner 部分 (pipeline) でやっていることをかんたんに図にしてみました。
container image build には Kaniko を使い、build したら GCR に push しています。build は複数の段階に分かれていて、まず最初は VS Code devcontainer 用の image を build しています。これは、次の段階で特定 version の hugo
が必要になるのでそれを install するためです。(手元で devcontainer を使うときにも各自が自分で build するのではなく、既存の build image を pull して使えると省エネだなと思うのですが、その手順は知らないです…)
次の段階でいよいよ hugo
を実行し、blog のファイル群を生成します。ここの Dockerfile は multi-stage build になっていて、一段めでは hugo
実行を、二段階めでは nginx image をベースとしてそこに前段で生成したファイル群を COPY しています。これによって実稼働する image はとても小さくなります。(現状で数十 MB)
よくあるマルチステージビルドですが、せっかくなのでご参考までに Dockerfile をそのまま置いておきます。ディレクトリ構成など前提が必要だったりこれだけでは使えませんが、だいたいの流れは見えるのではと思います 🙏
# 1st stage は devcontainer を流用する
FROM us.gcr.io/<gcp-project>/iteng-blog-devcontainer:ci-latest as builder
USER blogger
COPY --chown=blogger . /workspaces/engineer-blog
WORKDIR /workspaces/engineer-blog
ARG urlbase="http://localhost:48090"
RUN echo building... && \
sed -ri 's@^(baseurl = ")https*://[a-z0-9\.-]*/(.*)$@\1'${urlbase}'/\2@g' config/preview/config.toml && \
git submodule update --init --single-branch && \
hugo --configDir ./config -e preview && \
echo "done."
# 2nd: 仕上がり確認用 container image
FROM nginx:alpine
# 1st stage で build した site を COPY します。
COPY --from=builder /workspaces/engineer-blog/iteng-blog-pre/ /usr/share/nginx/html/iteng-blog-pre/
再掲しますが、全体図に戻ります。
container image の build が終わったら、preview 環境に deploy します。preview 環境は GitLab とは別の GKE cluster (上図紫枠) を用意しており、(図では省略していますが) ここに Ingress や Deployment を置いています。
GitLab CI/CD では、操作する Kubernetes cluster に Agent (上図赤枠) を install してそれを経由して操作する方法が案内されています。認証情報を発行してどこかの Secret に入れて〜とやるよりは、最終的な手間とかセキュリティの観点からよくできているなと感じました。
Agent の詳細は、このあたり からご参照ください。
様々な状況に合わせて install や設定、使い方の説明がされています。
また、この Agent が動作するために GitLab の KAS (Kubernetes Agent Server) という service が動作している必要があります。図でも示していますが、KAS を経由して Agent に通信を行っています。
preview 環境の装備
preview 環境として構築している独立した GKE cluster には External DNS を deploy してあり、Ingress が生成されるとその domain name で Cloud DNS に record が入り、すぐに名前解決ができるように設定してあります。
また、SSL 証明書は Google-managed SSL certificates を使用していますのでこれも自動的に provision されます。
GitLab CI にある pipeline は container image build が終わると kubectl patch
を実行し、ブログ (nginx) Pod の image tag を、build したばかりのものに差し替えます。image tag には git commit の short hash もつけているので、gcr.io/xxxx/iteng-blog:9b0ff43d
のように直指名して更新しています。
これで記事を書く人は、次の記事公開用の Merge Request が作成されている branch へ commit & push するだけで、数分後には preview site で確認ができるようになりました。個人で書いているときは devcontainer 上の hugo server
のほうがもちろん早いですけどネ。
今後
上記からもしかしてお気づきのように、この仕組みが動いているのはまだ preview 環境だけであり、本番環境へのリリースはこれまでと変わっていません。手動です。
まだ予定はありませんが、今度は本番環境にもこの仕組みを延長させていこうと思っています。ただ、本番環境向けには周辺のサーバー事情や管理の都合もあるので事前にすこし検討が必要そうです。
まとめ
既存の仕組みを利用し、極力運用に手間がかからない仕組みを構築できました。記事更新の手作業が不要なだけでなく、SSL 証明書やパスワード等の管理も不要になっています。
めでたく一周年という記事ながら、今回はなんだか字ばっかりな内容ばかりになってしまいました。
まだまだこれからも、たくさん読んでいただける記事をつくっていけるよう精進して参ります。
繰り返しになりますが、これからもよろしくお願いいたします 🤗
-
GITLAB is a trademark of GitLab Inc. in the United States and other countries and regions. ↩︎