TL;DR
- 手元の docker for desktop の k8s 内で shell を使って何かしたい。
- k8s 内のPod間でファイルを共有したい、さらに作成したファイルを永続化したい。
- サンプルは全てこちらにあります https://github.com/Bugfire/k8s-workspace
はじめに
自分は k8s を使って開発を行ったことがなく、ドキュメントを読みながら手探りで試しています。一般的用法から外れている、記法がよろしくない、簡潔にかける等、コメントがあるととても助かります!
kubectl は以下の版です
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:16:51Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:07:57Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}
目的
Docker を使った開発で、複数コンテナ間で永続的な Volume で開発・テストを行う。これを k8s で実現したい。
自分は Docker 内のみに存在する Volume で開発を行うのが好きです。これと、一般的なホスト側のファイルを用いるケースと両方で作ってみます。
実装
Docker内Volume - NFS
ドキュメントをみた感じ local, hostPath Volume は、永続的ですがホスト側FSにマッピングされ、emptyDir はホストFSに依存しませんが Pod の寿命に依存するので、永続性がないので目的を果たせません。
k8s からすでに外れますが、k8s 外の NFS を用いることにしました。k8s 外であれば Volume は Pod の寿命に依存せず、NFS Persistent Volume を用いることで k8s からマウントして利用します。
便利な NFS 用の Docker image があります、それをそのまま使います。
$ docker run -d --rm --name nfs -p 2049:2049 -v nfs:/nfs --privileged -e SHARED_DIRECTORY=/nfs itsthenetwork/nfs-server-alpine:latest
注意、NFSへのアクセス制限はかかっていません。ファイアウォールの設定を確認してください。
ファイアウォールで外部からの2049ポートへのアクセスを全て落とすか、
NFS 側で -e PERMITTED="192.168.*.*"
等の制限をかけてください。
上のワンライナーで nfs と言う名前の Volume を提供する NFS を起動し、
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-volume
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
storageClassName: nfs
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.x.x
path: /
このような NFS の Persistent Volume を生成することにしました。
PVC は以下の通り
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: local-volume-claim
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs
resources:
requests:
storage: 5Gi
ホスト側ファイルを用いたVolume
これは、ホスト側をそのまま用います。特にひねりはありません。
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-volume
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
local:
path: /PATH-TO-SHARE
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- docker-for-desktop
- docker-desktop
PVC はこちら
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: local-volume-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-storage
resources:
requests:
storage: 5Gi
ConfigMap
複数の ConfigMap を合成したり、Immutable な ConfigMap にしたいと、いろいろな記事を参考に、ファイルを合成した上で hash の suffix を追加などを試していたりしました。
しかし kustomize が kubectl に入っていることに気がつき、これを利用することにしました。
k8s は変化が速いので、ググって出た記事が最近の情勢にあってるともかぎらないですね。
ConfigMapGenerator
base 側に
configMapGenerator:
- name: common-env
env: common.env
を記述しておき、overlay 側で
configMapGenerator:
- name: common-env
behavior: merge
env: common.env
としておくとマージされます、便利ですね。
最終的に base 側で
apiVersion: v1
kind: Pod
metadata:
name: workspace
labels:
app: k8s-workspace
spec:
containers:
- name: workspace
image: node:lts-stretch
command: [ "/bin/bash", "-c", "while true; do sleep 1; done" ]
resources:
requests:
cpu: 1000m
memory: 1000Mi
envFrom:
- configMapRef:
name: common-env
とすることで、環境変数にマージ後のものを読み込んでいます。
Kustomize
Kustomize をせっかく使うので、上の Volume 等も合わせて、階層構造化してみました
- base_common
-
kustomization.yaml
- 共通設定
-
common.env
- 共通環境変数
-
workspace.yaml
- Pod の共通設定
-
kustomization.yaml
- base_volume_localpath
- base_volume_nfs
- config
-
kustomization.yaml
- base_common 及び base_volume_localpath もしくは base_volume_nfs を派生した上でディレクトリ・IP・環境変数を独自に設定します。
-
volume-nfs.yaml.sample
- オーバレイ設定 volume-nfs.yaml のサンプル。
-
volume-localpath.yaml.sample
- オーバレイ設定 volume-localpath.yaml のサンプル。
-
common.env
- ユーザ設定環境変数
-
workspace.yaml
- workspace Pod のオーバレイ設定。今回は base_common 側に記述しても問題はないが、Volume を使用していることを明示したいので、こちらに記述しました。
-
kustomization.yaml
Helm
せっかくなので、helm
$ helm version
version.BuildInfo{Version:"v3.2.1", GitCommit:"fe51cd1e31e6a202cba7dead9552a6d418ded79a", GitTreeState:"clean", GoVersion:"go1.13.10"}
を用いた版を、https://github.com/Bugfire/k8s-workspace/blob/master/helm に作りました。
ここでは、ほぼテンプレートエンジンとしてだけ使い、config.yaml を定義して使う形になります。