この記事は、Kubernetes3 Advent Calendarの第1日目です。
Kubernetes最軽量構築ツールkind
のよさ、初回起動方法、仕組み、TIPS(ホストディレクトリのマウント)、メンテナンス方法を紹介します。仕掛けがわかるととても楽しいですよ。
[更新]2021/4/27 kubeconfigの書き出し方法を追記
[更新]2019/12/28 最新ドキュメントに合わせ apiVersion: kind.x-k8s.io/v1alpha4
に変更。Kubernetesバージョン指定方法を追加。
kind
のよさ
以下のような良さがあるKubernetes最軽量構築ツールです。
- 軽量 = 前提としてDockerがインストールされたホストが一つあれば済む
- クリーン = ホスト環境を何も汚さない
- 作業ほぼゼロ = コマンド一発で作成、削除可能
まずkind
を動かしてみるまで
参考になるドキュメント
kind
を動かす環境の前提
- dockerがインストールされている
- kubectlがインストールされている
今回は検証のため、Windows上のVirtualBox上のVMでDocker本体を動かして確認しましたが、私自身Ubuntu上でもMacでも同じ構成を作った実績があります。
kind
コマンドのインストール
以下はすべてDockerインストール済みのVM上で実行します。
curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.6.0/kind-$(uname)-amd64
chmod +x ./kind
sudo mv ./kind /usr/bin/kind
別のMacの環境では以下のコマンドだけでインストールできました。
brew install kind
クラスタ構築
kind create cluster
docker上に一つだけコンテナが起動します。
これは、control-planeというKubernetesのマスターノードに相当するコンテナが起動した状態です。
Kubernetesでは、デフォルト設定でマスターノードにコンテナを配置しないように制御されますので、それ以外のワーカーノードも必要になります。
一度今のクラスタを削除して、再度ワーカーノード込みで作り直してみましょう。
クラスタ削除
kind delete cluster
はい、全部消えました。とてもクリーンです。
ワーカーノードを含めたインストール
kind
用の設定ファイルを新規作成し、ワーカーノードを追加することを記載します。
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
この設定を使ってクラスタを作成します。
kind create cluster --config kind.yaml
処理の中にJoining worker nodes
処理が増えているのがわかります。
コンテナが2つ作成されています。
kubectl
で操作する
クラスタ作成後に表示されるkubectl cluster-info
をたたくと、ちゃんとコンテキストが追加されていることがわかります。
~$ kubectl cluster-info --context kind-kind
Kubernetes master is running at https://127.0.0.1:38921
KubeDNS is running at https://127.0.0.1:38921/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
ではこのコンテキストを使ってkubectl
で操作しましょう。
$ kubectl config use-context kind-kind
Switched to context "kind-kind".
実際にコンテナを起動してみます。
$ kubectl run --generator=run-pod/v1 test --image=nginx
pod/test created
動いたかどうかを確認してみます。
~$ kubectl get po
NAME READY STATUS RESTARTS AGE
test 1/1 Running 0 2m39s
コンテナの中にも入ってみます。
$ kubectl exec -ti test /bin/bash
root@test:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
コンテナを消してみます。
$ kubectl delete po test
pod "test" deleted
kind
の仕組み
2重のコンテナエンジン
Dockerの中にKubernetesのマスターノード(kind-control-plane
)やワーカーノード(kind-worker
)が起動し、それぞれの中にまたcontainerdというコンテナエンジンが起動する形になっています。
ユーザがKubernetes上に作るPodなどのコンテナは、この内部のcontainerdの中に作られます。だから、クラスタを削除したいときはこのcontainerdをまるごと消せばよく、ホストのDockerを汚さないので非常にクリーンに運用できるわけです。
安定した構築方法を採用している
Kubernetesの構築の仕方の中では老舗に部類される、安定した構築ツールkubeadm
を内部で使っています。
したがって、kubeadm
でできることはこのkind
でもできるという嬉しさもあります。
kind
のTIPS
ホストのディスクをkind上のpodに見せる
kind
の仕組みで説明した通り、kind
は2重のコンテナエンジン(Docker/containerd)で起動されています。コンテナエンジン自体はホストのディレクトリをコンテナに見せる機能を持っていますが、2重のコンテナエンジンの設定を一括でやってくれるわけではありません。
したがって、ホストのファイルをkind上のコンテナに見せるには、以下のような2重の設定が必要になります。
-
kind
自体が使っているdockerにホストのディレクトリAをBという名前でマウントする設定をする -
kind
内部のcontainerdに、BというディレクトリをCという名前でマウントする
では、ホスト上の/mnt/test/
というディレクトリをコンテナに見せてみます。
/mnt/test/
はこうなっています。
$ ls /mnt/test/
myfile.txt
このmyfile.txt
をPodに見せるのがゴールです。
ではまずkind
の設定です。extraMounts
というフィールドで設定します。
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
extraMounts:
- containerPath: /test
hostPath: /mnt/test
次にコンテナの設定です。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /test
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /test
type: Directory
それぞれは以下の①②に対応しています。
クラスタの作り直し
kind create cluster --config kind2.yaml
確認
$ docker exec -it kind-worker ls /test
myfile.txt
$ kubectl apply -f container.yaml
pod/nginx created
$ kubectl exec pod/nginx -it ls /test
myfile.txt
ちゃんとPodからホスト上のmyfile.txt
が見えました。
アプリのログなどのファイルを永続化したい場合に、このテクニックでホストのディレクトリに書き込むことで、kind
やその上のPodが消えてもファイルを残すことができます。
ホストのディスクをkind上のapi-server等に見せる
api-serverなどKubernetes自身が持つサービスにもホストのディスクをマウントすることができます。api-serverなどはコンテナとして起動されるという仕組みになっているので、今回もやはり前節と同じで、2重コンテナ構造のため2階層にディレクトリをマウントするという設定がそれぞれ必要となります。
ただし、今回はkind
起動時の設定ファイルkind3.yaml
のみで設定可能です。理由は、kubeadm
を利用しているkind
では、そのapi-serverなどへの設定も同じファイルで記述できるためです。
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraMounts:
- containerPath: /test
hostPath: /mnt/test
- role: worker
kubeadmConfigPatches:
- |
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
metadata:
name: config
apiServer:
extraVolumes:
- name: "test"
hostPath: /test
mountPath: /test
ポイントは2つ。
- まず、
api-server
はcontrol-plane
というノードに配置されますので、今回はextraMounts
をcontrol-plane
に記載します。。 - 次にこの
KubeadmConfigPatch
の部分です。ここにkubeadm
への設定の差分が書けるというのがkind
の嬉しさの一つでもあります。ディレクトリをマウントする設定のフィールドは、extraVolumes
です。このお作法は、kubeadm
のドキュメントを参考にできます。
さて再掲ですが、ホストのディレクトリはこうなっています。
$ ls /mnt/test/
myfile.txt
では、実際にクラスタを構築して確認してみます。
$ kind create cluster --config kind3.yaml
確認
$ kubectl exec -n kube-system kube-apiserver-kind-control-plane
myfile.txt
ちゃんとマウントされましたね。api-serverからaudit logなどをホストに書き出したいときにぴったりです。
もうこんなに設定ファイル一個だけでかんたんにKubernetesクラスタがいじれると、楽しくてしょうがなくなりますね。
もしVM上のDockerがこんなエラーをはいたら
docker: Error response from daemon: cgroups: cannot find cgroup mount destination: unknown.
VMのcgroupの使われ方が少し変なようなので、以下をたたくと回避できます。
sudo mkdir /sys/fs/cgroup/systemd
sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd
[2019/12/28追加] Kubernetesバージョンを指定する
通常構築したクラスタのKubernetesは、Kind
が対応した最新版になります。
最新版では現時点で v0.16.3
です。
ただ、昔のKubernetesでないと動かないツールもあります。
そういう場合には、kind create cluster
コマンドのオプション--image
が使えます。
--image
ではkind
のノードイメージを指定するのですが、デフォルトはkindest/node:v<最新版>
となっています。
このノードイメージはdockerhubで管理されており、どんなバージョンが用意されているかを確認することができます。
今回はv0.15.6
を指定して起動してみます。
kind create cluster --image kindest/node:v0.15.6
正常に終了すると、以下のように各ノードのバージョンを確認できます。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready master 43s v1.15.6
kind-worker Ready <none> 10s v1.15.6
kind
のメンテナンス
コンテナイメージを追加する
ホスト上でアプリを開発して、アプリを同梱したコンテナをPodとしてkind上で実行したいときがあります。しかし、kind内のcontainerdはホストのdockerのイメージを直接読めませんので、そのままではPodが起動しません。
ホストのイメージをkind内のcontainerdにアップロードする便利コマンドがあるので、それを使います。
kind load docker-image <image:tag>
注意が必要なのは、これをすることによってcontrol-planeやworkerすべての内部にイメージがアップロードされるため、ノード数分ディスクを消費することです。
もし特定のノード、たとえばワーカーだけにイメージをアップロードしたい場合は以下のようにします。
kind load docker-image <image:tag> --nodes=<nodename>
複数のノードにアップロードする場合には、ノード名をコンマで連結して入れればよいです。
kind load docker-image <image:tag> --nodes=<nodename1>,<nodename2>
コンテナイメージを消す
ディスクを圧迫してきたら、使わないコンテナイメージを削除することをお勧めします。
まず確認する
$ docker exec kind-control-plane crictl images
IMAGE TAG IMAGE ID SIZE
k8s.gcr.io/coredns 1.6.2 bf261d1579144 44.2MB
k8s.gcr.io/etcd 3.3.15-0 b2756210eeabf 248MB
k8s.gcr.io/kube-apiserver v1.16.3 6750aac993260 185MB
k8s.gcr.io/kube-controller-manager v1.16.3 74308f46cf2d3 128MB
k8s.gcr.io/kube-proxy v1.16.3 2388adcec48cf 103MB
k8s.gcr.io/kube-scheduler v1.16.3 0f7390a0dfb32 105MB
docker.io/kindest/kindnetd <none> aa67fec7d7ef7 32.4MB
k8s.gcr.io/pause 3.1 da86e6ba6ca19 746kB
test 0.1 xxxxxxxxxxxxx 1.0GB
見つけたイメージを消す
docker exec kind-control-plane crictl rmi test:0.1
同じことをworkerに対しても実行する
kind-control-plane
のところをkind-worker-1
などに変えると同じ事が実行できます。
ログを一括して吐き出す
Kubernetes周りのサービス(たとえばapi-server)のログを出力したいとき、便利コマンドが用意されています。
kind export logs
kubeconfig(kubectl
接続設定)を再度書き出す
通常はkind create cluster
時に自動的に$HOME/.kube/config
に書き出されるのですが、何かの拍子に消えてしまった場合には、以下コマンドで復元することができます。
kind export kubeconfig
また、kind create cluster
時に書き出すファイルを変えるには
kind create cluster --kubeconfig <filepath>
で別のファイルに書き出すことができます。このときには、kubectl
の前に
export KUBECONFIG=<filepath>
を実行しておいてからkubectl
を実行すると、kindで作成したクラスタに接続することができます。
まとめ
kind
は軽量、クリーンなKubernetesテスト環境で、とても便利です。さまざまなKubernetes関係の開発者が利用していることも知られています。
TIPSで紹介したように、うまくすればホストのディレクトリもマウントできます。
開発者は「本番系には使わないでね」、と言っていますので、使い方は気を付けたほうがよさそうです。
参考情報
https://qiita.com/it__chago/items/c7d057d968da934199da
https://speakerdeck.com/ytaka23/cloud-native-developer-jp-13th
https://qiita.com/sourjp/items/281d2189516823950291