前提とゴール
- 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のvolumeを、k8sでmountしてアプリを参照するの?
- localと各環境(production, ...)のyamlって絶対差分あるじゃん
今回はkustomizeを使って解消しています
kustomizeについてのサンプルはこちら
Kubernetes+kustomizeでmasterをスマートにさっとデプロイする
今回は利用しませんが、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をスマートにさっとデプロイする
大切な要素は3つです
- /skaffold.yaml
skaffoldが参照するファイル - /ops/app/
変更の監視をするフォルダ
Dockerfileと、アプリのビルド後のファイルを配置している - /ops/k8s/overlays/local/
kustomizeにて、ローカル環境の元になる設定
/skaffold.yaml
build.artifacts.contextで監視するフォルダを指定
useBuildkitはdockerのBuildKitという、buildが早くなる機能の有効可
docker v18.09以上で設定可
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/
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
images:
- name: app-image
newName: app-image-local
../../base
のファイル
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-name
spec:
replicas: 1
template:
spec:
containers:
- name: container-name
image: app-image:latest
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が勝手に再起動します