Help us understand the problem. What is going on with this article?

kindで軽量テスト用Kubernetesクラスタを作る&運用する時のTIPS

この記事は、Kubernetes3 Advent Calendarの第1日目です。

Kubernetes最軽量構築ツールkindのよさ、初回起動方法、仕組み、TIPS(ホストディレクトリのマウント)、メンテナンス方法を紹介します。仕掛けがわかるととても楽しいですよ。

image.png

[更新]2019/12/28 最新ドキュメントに合わせ apiVersion: kind.x-k8s.io/v1alpha4に変更。Kubernetesバージョン指定方法を追加。

kindのよさ

以下のような良さがあるKubernetes最軽量構築ツールです。

  • 軽量 = 前提としてDockerがインストールされたホストが一つあれば済む
  • クリーン = ホスト環境を何も汚さない
  • 作業ほぼゼロ = コマンド一発で作成、削除可能

まずkindを動かしてみるまで

参考になるドキュメント

本家Quick start

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

image.png

docker上に一つだけコンテナが起動します。

image.png

これは、control-planeというKubernetesのマスターノードに相当するコンテナが起動した状態です。

Kubernetesでは、デフォルト設定でマスターノードにコンテナを配置しないように制御されますので、それ以外のワーカーノードも必要になります。
一度今のクラスタを削除して、再度ワーカーノード込みで作り直してみましょう。

クラスタ削除

kind delete cluster

はい、全部消えました。とてもクリーンです。

ワーカーノードを含めたインストール

kind用の設定ファイルを新規作成し、ワーカーノードを追加することを記載します。

kind.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker

この設定を使ってクラスタを作成します。

kind create cluster --config kind.yaml

image.png

処理の中にJoining worker nodes処理が増えているのがわかります。
コンテナが2つ作成されています。

image.png

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を汚さないので非常にクリーンに運用できるわけです。

image.png

安定した構築方法を採用している

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というフィールドで設定します。

kind2.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
  extraMounts:
  - containerPath: /test
    hostPath: /mnt/test

次にコンテナの設定です。

container.yaml
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

それぞれは以下の①②に対応しています。

image.png

クラスタの作り直し

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などへの設定も同じファイルで記述できるためです。

kind3.yaml
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-servercontrol-planeというノードに配置されますので、今回はextraMountscontrol-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

まとめ

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

Hiroyuki_OSAKI
Certified engineer (CKA/CKAD), Sr. researcher(@Hitachi / Hitachi America) K8s/Helm/OPA/GraphQL/Python/Rails/Node.js/golang/Android/Scratch ここに記載の内容はあくまで個人的見解であり会社を代表するものではありません。
hitachi-services-computing
様々なサービスやOSSを活用して新しいサービスを創生・開発・運用するための技術を研究開発しています
https://www.hitachi.co.jp/rd/index.html
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away