Kubernetesでのローカルの開発をskaffoldで加速させる

# 前提とゴール
- k8sでのデプロイはなんとなくわかる  
DeploymentとServiceのyaml用意して、kubectl applyすればいいんでしょ？くらい
- しかし、k8sでのローカルってどうしたらいいか、なにもわからない  
    - localのvolumeを、k8sでmountしてアプリを参照するの？  
    これは一見シンプルに見えて、アプリビルド後に、podの再起動（=再適用）が必要になる  
    - docker imageはproductionに(近い)registryに置けばいいの？  
    いいけど、GCRとかに、いちいちpushしてpullするのはなんか無駄っぽい  
    - docker imageはlocalでdocker buildしたimageを使えばいいの？  
    これでいきます  
- localと各環境(production, ...)のyamlって絶対差分あるじゃん  
今回はkustomizeを使って解消しています  
kustomizeについてのサンプルはこちら  
[Kubernetes+kustomizeでmasterをスマートにさっとデプロイする](https://qiita.com/yakisuzu/items/6b6a65d9cbc0422f4b3d)  
今回は利用しませんが、skaffoldはHelmにも対応しています  
- productionはskaffoldなしでデプロイまでできてるから、skaffoldいらないんだけど？  
**全てをskaffoldに置き換える必要はありません** （自分は最初勘違いしていました）   
今回はローカルの開発 **だけ** skaffoldを使います  

# skaffoldについて
ざっくり言うと、ファイルを監視して、変更があったらdocker buildして、kubectl applyまでやってくれるツールです、超快適です
**ローカル専用ではないです** が、今回はローカル専用として使います

細かくは公式を読みましょう
https://skaffold.dev/docs/
https://github.com/GoogleContainerTools/skaffold

## skaffoldの準備
### 1. skaffoldコマンドをインストール  
macであれば `brew install skaffold`  

### 2. skaffold.yamlを書く  
公式でサンプルコードをいくつも用意してくれています
https://github.com/GoogleContainerTools/skaffold/tree/master/examples
getting startやれば雰囲気は掴めます
https://skaffold.dev/docs/getting-started/

一番大切なのはskaffold.yamlのリファレンスで、これを確認しながら書くことになります
https://skaffold.dev/docs/references/yaml/

# 実際のディレクトリ構成
```
repository
├── ops
│   ├── app
│   │   ├── Dockerfile
│   │   └── app.jar
│   └── k8s
│       ├── base
│       │   ├── deployment.yaml
│       │   └── kustomization.yaml
│       ├── manifest
│       │   ├── local-k8s.yaml
│       │   └── prd-k8s.yaml
│       └── overlays
│           ├── local
│           │   ├── build.sh
│           │   └── kustomization.yaml
│           └── production
│               ├── build.sh
│               ├── deployment.yaml
│               └── kustomization.yaml
├── いろいろ
└── skaffold.yaml
```

kustomizeまわりの詳細についてはこちら
[Kubernetes+kustomizeでmasterをスマートにさっとデプロイする](https://qiita.com/yakisuzu/items/6b6a65d9cbc0422f4b3d)

大切な要素は3つです

- /skaffold.yaml  
skaffoldが参照するファイル  
- /ops/app/  
変更の監視をするフォルダ  
Dockerfileと、アプリのビルド後のファイルを配置している  
- /ops/k8s/overlays/local/  
kustomizeにて、ローカル環境の元になる設定  

## /skaffold.yaml
build.artifacts.contextで監視するフォルダを指定
useBuildkitはdockerのBuildKitという、buildが早くなる機能の有効可
**docker v18.09以上で設定可**

```/skaffold.yaml
apiVersion: skaffold/v1beta12
kind: Config
build:
  artifacts:
    - image: app-image-local
      context: ops/app/
  tagPolicy:
    dateTime:
      format: "20060102_150405"
      timezone: "Local"
  local:
    useBuildkit: true
deploy:
  kustomize:
    path: ops/k8s/overlays/local
```

## /ops/k8s/overlays/local/

```/ops/k8s/overlays/local/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
images:
- name: app-image
  newName: app-image-local
```

`../../base` のファイル

```/ops/k8s/base/deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-name
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: container-name
          image: app-image:latest
```

```/ops/k8s/base/kustomization.yaml
commonLabels:
  app: app-label
resources:
  - deployment.yaml
```

## (2019/07) `skaffold v0.33.0` 依存っぽい話
よくあるcontainersの設定である、
`imagePullPolicy: Always` は、ローカル環境ではあえて外しています
Alwaysつけると、下記のエラーが出るため

```
pull access denied for app-image-local, repository does not exist or may require 'docker login'
Back-off pulling image "app-image-local:hash"
```

また、skaffoldをググるとよく出てくる、ローカルのレジストリを参照するため、
docker imageにlocalhostつけて `localhost:5000/hoge:fuga` にする手順は不要でした
公式のリファレンスを探しましたが、localhostつける元ネタわからず、、

## リポジトリ内にあるサンプルコードは、ソースファイルをDockerfileでコピーしてマルチステージビルドしてる件
元々ローカルでアプリをビルド後、Dockerfileでコピーする構成にしていたので、
どうすればいいのか悩んだポイントでしたが、
反映したいタイミングで自分でビルドし、 `/ops/app` に配置すれば、
再起動までskaffoldがやってくれるので、これはこれでいいかなという感じです

# 実行手順
`skaffold dev` でskaffoldの実行しますが、監視しづづけているので、このコンソールはそのままにします
`Ctrl+C` で終了できますが、k8sも綺麗にしてくれます！
しかし `docker images` はいろいろ残ります、、

別のコンソールで、監視しているcontextのファイルを更新（ `sbt assembly` などでjarを再配置）すると、skaffoldが勝手に再起動します