Skaffold + k3sでローカルPC上で自動k8sデプロイしながら開発する方法

## この記事って？

* Kubernetesを利用した開発をいちいち自前クラスタ組んでやるのが大変  :sweat_drops:
* かつ借りるのも :moneybag: がかかるので避けたい
* Dockerイメージも手軽にアップできてk8sクラスタに展開して本番さながらにサクサク開発したい :sparkles:

という気持ちから、k8sの開発便利ツールの**Skaffold**と軽量k8sである**k3s**を組み合わせてローカルPC上で開発できる環境を作ったときのメモ。**ただし、Linux限定**。

## 使うもの

### Skaffold

https://skaffold.dev/

k8sを利用した開発で使える便利ツール。
scaffold.yamlを作成して `skaffold dev` コマンドを打つと、そのディレクトリにあるファイルを監視して変更があれば自動的にk8sクラスタにも反映してくれるすぐれもの。
たとえば、ソースコードを少し修正して保存すると「Dockerビルド→Docker Registryにアップロード→k8s deploy」を自動的でやってくれて即座に動作を確認することができる。

### k3s

https://k3s.io/

軽量なk8s。ローカルPCで開発するのでk8sも軽いやつがいい。

### Docker Registry

https://docs.docker.com/registry/

Dockerイメージを保存してくれるサーバーアプリケーション。
RegistryのDockerイメージをpullして起動しておけば自前Registryがあっという間に出来上がって便利。

## 手順

### 構築したときの環境

- Lubuntu 18.04
- 事前にDockerインストール済

Windows, Mac環境の方は残念ながらk3sが未対応のため、k3sが予めインストールされた[k3os](https://k3os.io/)を手元の仮想マシンで動かして頑張るか、もしくは素直に[minikube](https://github.com/kubernetes/minikube)でk8sクラスタを立てたほうがいいと思います。

### 各ツールのインストールと起動

インストールの詳細な手順は各ツールのページをみれば良いと思います。
ここでは使ったコマンドだけ列挙。

```bash
# Skaffold
# https://skaffold.dev/docs/getting-started/#installing-skaffold
$ curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
$ chmod +x skaffold
$ sudo mv skaffold /usr/local/bin

# k3s
$ curl -sfL https://get.k3s.io | sh -
$ sudo systemctl restart k3s

# Docker Registry
# https://docs.docker.com/registry/
$ sudo docker pull registry
$ sudo docker run -d -p 5000:5000 --name registry registry
```

### Skaffoldで開発を試してみる

https://skaffold.dev/docs/getting-started/#skaffold-dev-build-and-deploy-your-app-every-time-your-code-changes を参考に実際にソースコードを修正したらSkaffoldがk3s上にデプロイしてくれるかどうか試してみる。

まずはサンプルプロジェクトを含むSkaffoldのレポジトリをクローンしてサンプルプロジェクトに移動する。

```
$ git clone https://github.com/GoogleContainerTools/skaffold
$ cd examples/getting-started
```

kubectlの設定。k3sのクラスタ設定は `/etc/rancher/k3s/k3s.yaml` にあるので、それを `~/.kube/config` にシンボリックリンクする。すでに設定がある場合はk3sの設定をコピペしてすでに作成済のconfigへ設定する。

```
$ ln -s /etc/rancher/k3s/k3s.yaml ~/.kube/config
```

最後にプロジェクトの設定。`skaffold.yaml`と`k8s-pod.yaml`を修正しDocker Registryの参照先をlocalhostに向ける。

```
gcr.io/k8s-skaffold/skaffold-example
↓
localhost:5000/skaffold-example
```

ここまでできたら起動。

```
$ sudo skaffold dev --default-repo localhost:5000
```

Skaffoldのサイトに書いてある内容と一緒だけど、以下のような出力になれば動いてる。
最後の行の `[getting-started] Hello world!` がアプリからの出力になっている。

```
Generating tags...
 - localhost:5000/localhost_5000_skaffold-example -> localhost:5000/localhost_5000_skaffold-example:v0.31.0-50-ge8302bbe-dirty
Tags generated in 7.64677ms
Starting build...
Building [localhost:5000/localhost_5000_skaffold-example]...
Sending build context to Docker daemon  3.072kB
Step 1/6 : FROM golang:1.12.5-alpine3.9 as builder
 ---> c7330979841b
Step 2/6 : COPY main.go .
 ---> Using cache
 ---> 0825db0a1340
Step 3/6 : RUN go build -o /app main.go
 ---> Using cache
 ---> 209e9777c672
Step 4/6 : FROM alpine:3.9
 ---> 055936d39205
Step 5/6 : CMD ["./app"]
 ---> Running in 9c4986239070
Removing intermediate container 9c4986239070
 ---> 29a14bbfc1b9
Step 6/6 : COPY --from=builder /app .
 ---> fd10d59c9bf9
Successfully built fd10d59c9bf9
Successfully tagged localhost:5000/localhost_5000_skaffold-example:v0.31.0-50-ge8302bbe-dirty
The push refers to repository [localhost:5000/localhost_5000_skaffold-example]
95c46ee30abb: Preparing
f1b5933fe4b5: Preparing
95c46ee30abb: Layer already exists
f1b5933fe4b5: Layer already exists
v0.31.0-50-ge8302bbe-dirty: digest: sha256:9a251e9101e629fbfc833593c15fe80cd0b7aeae13e44d1802119a9068beeea8 size: 739
Build complete in 997.53284ms
Starting test...
Test complete in 16.077µs
Starting deploy...
kubectl client version: 1.14
pod/getting-started created
Deploy complete in 942.964237ms
Watching for changes every 1s...
[getting-started] Hello world!
```

Skaffoldを起動した状態で`main.go`の内容を修正すると、Skaffoldが修正を検知してDockerビルドして再デプロイしてくれる。なんて便利。

## 最後に

さくっと試せる環境があると開発する気になるので非常に良い感じ。PCリソースも上記ツール起動時でメモリ使用率が1〜2GBぐらいだったのでまぁ許せる。CPUもファンがうなるほどではない。（スペックにもよるが）

ただ、k3s自体がまだ開発途上で動かない機能とか、そもそもk8sには機能として存在するけどk3sだと機能が削ぎ落とされて動かないとかありそうなので、そういう状況になったら本腰を入れてk8sクラスタに移動すればいいかなと思った。