この記事ではKubernetesな環境を想定してSkaffoldとHelmで開発環境を構築する方法を解説します。
もっとも、この記事でお伝えする方法が「最善」かと言われるとかなり怪しいですが、一応ある程度実用的な開発環境を考えました。
この記事を読むことで、ローカルに以下の要件を満たす開発環境を構築できます。
- ソースコードを変更したら自動でDockerfileに記載した内容でコンテナをビルド(ホットリロード)
- ソースコードを変更し、ビルドが完了したらそれをKubernetesクラスタにデプロイ(Helm利用)
docker compose
のように、関連するサービスをコマンド1つで起動してすぐに開発をスタートできる。
後で見ますが、これらはSkaffoldが実現します。
背景
開発中のWebサービスをKubernetesに移行するにあたり、開発環境をどうするかが問題となりました。
現状、ローカルでの開発はdocker compose
を利用していますが、本番環境をKubernetesに移行するにあたり、ローカルの開発環境もそれに合わせる方向で考えました。
そこで、今回は以下のツールを使ってローカルの開発環境を整備します。
- Kubernetes
- minikube
- Helm
- Skaffold
なお、この記事のソースコードは以下にあります。
https://github.com/SRsawaguchi/kubernetes-hanson
こちらのリポジトリのREADME.mdからより詳細な手順に飛べます。
前提
kubectl, minikubeの環境が整っていること。
追加で、以下のソフトウェアをインストールします。
Helm
Skaffold
プロジェクトの構造
今回はシンプルなWebサービスを前提とします。
APIサーバがHTTP通信を受け付け、Backendサーバに処理を依頼、処理結果をクライアントに返すというシンプルなものです。
今回のサンプルプロジェクトは以下のようになっています。
※各ファイルの中身はリポジトリを参照してください。
. ├── api ├── backend ├── chart
apiにはAPIサーバのソースコード(Go)が、backendにはバックエンドサーバのソースコード(Go)が入っています。
※今回はBackendサーバについては触れません。
chart
ディレクトリにはHelmチャートが入っています。
※Helmチャートの作成手順や中身について詳しく知りたい方は、こちらの2. Helmと3. Helmハンズオンをご覧ください。
そして、api
ディレクトリには以下のコンテンツが入っています。
. ├── Dockerfile ├── Makefile ├── go.mod ├── main.go └── skaffold.yaml
重要なファイルのみ取り上げます。
Dockerfile
はこのAPIサーバのイメージを生成するDockerfileです。main.go
のソースコード変更すると、このDockerfile
を元にイメージをビルドするようにします。skaffold.yaml
はSkaffoldの設定ファイルです。
後ほど見ていきます。
HelmチャートをSkaffoldに対応させる
Skaffoldはソースコードを監視し、変更を検出したらDockerfileを元にイメージを再生成し、自動でHelmにデプロイしてくれます。
デプロイのため、新しく作成したイメージにはタグを自動で付与します。
そのため、HelmチャートのKubetetesリソースのテンプレートにおいて、イメージの指定を変数化(variables.yaml
に外だし)する必要があります。
今回のプロジェクトで関連するファイルを見てみましょう。
./chart/templates/api-deploy.yaml
https://github.com/SRsawaguchi/kubernetes-hanson/blob/main/chart/templates/api-deploy.yaml
省略... spec: containers: - image: {{ .Values.images.api }}. <--------イメージの指定を変数化 imagePullPolicy: {{ .Values.imageConfig.pullPolicy }} name: msvcapi 省略...
そして、values.yaml
では以下のように記述しています。
https://github.com/SRsawaguchi/kubernetes-hanson/blob/main/chart/values.yaml
images: api: msvcapi:1.0.0 backend: msvcbackend:0.0.1
Skaffoldでは、helm install
する際に--set
で値を指定するのと同じく、デプロイのたびにこれらの変数を介して新しいイメージの情報をtemplates/
配下のファイルに反映させます。
続いて、Skaffoldの設定ファイルskaffold.yaml
を作成しましょう。
skaffold.yamlを準備
続いてskaffold.yamlを準備していきましょう。
今回はapi
ディレクトリの中に作成します。(アプリと同じディレクトリに作成します。)
./api/skaffold.yaml
https://github.com/SRsawaguchi/kubernetes-hanson/blob/main/api/skaffold.yaml
apiVersion: skaffold/v2beta16 kind: Config metadata: name: hanson-api-skaffold build: artifacts: - image: skaffold-api docker: dockerfile: Dockerfile deploy: helm: releases: - name: hanson chartPath: ../chart setValues: api: message: "This is a message from skaffold!!" imageConfig: pullPolicy: IfNotPresent artifactOverrides: images.api: skaffold-api recreatePods: false skipBuildDependencies: false useHelmSecrets: false wait: false
この中で重要なのはartifactOverrides
です。
artifactOverrides: images.api: skaffold-api
artifactOverrides
は、Skaffoldが作成したイメージの情報をhelmに渡すために使います。
もう一度先ほどのvalues.yaml
を見てみましょう。
images: api: msvcapi:1.0.0 backend: msvcbackend:0.0.1
ご覧の通り、今回のvalues.yaml
では、images.api
でAPIサーバ向けのイメージを指定しています。
そのため、artifactOverrides
では、images.api
の値をoverrideするように設定します。
なお、skaffold.yaml
では、環境変数などの開発用のパラメータを与える便利な機能があります。
一例は。。。
setValues
:helm install
の--set
と同じ要領で定義した値を渡すsetValueTemplates
: ホストの開発変数の値を--set
と同じ容量で渡す
全ての設定項目はこちらにまとまっています。
実行
これで必要な設定は全て完了です。
早速実行してみましょう。
cd api skaffold dev
この状態で./api/main.go
を書き換えると、イメージが再生成され、そのままデプロイされます。
このような環境を構築することで、複数のサービスで構成されるアプリであっても、docker compose up
と同じように一度に全て立ち上げ、コードを書いて結果をチェックするlことができます。
まとめ
今回はSkaffoldとHelmをつかって、ローカルの開発環境を整えました。
Skaffoldはkubectlを使ったデプロイが最もお手軽ですが、複数のサービスにより動作しているアプリの場合はやや手間です。
そこでSkaffoldのデプロイ先をHelmにすることで、docker compose
と同じようにコマンド一つで手軽に開発をはじめられ、終わったらまるごとuninstallできます。
効率的な開発環境は生産性向上に欠かせませんね!!
参考リンク