LoginSignup
28
20

More than 1 year has passed since last update.

Kindを使ったKubernetes環境構築

Posted at

背景とか目的

  • 最近Kubernetesを使って、色々試したいことが多い。
  • 一発コマンドでマルチクラスタを作って、きれいさっぱりさよならしたい。
  • 物理マシン数台でclusterを構築したり、管理するのがめんどくさい。
  • 自分の開発マシンだけでマルチノードクラスタを立ち上げて、アプリの動作を確認したい。

Kindとは

Kubernetes IN Docker らしいです。少しだけ概要にも触れておきます。

diagram.png

Kubernetesのノードとしてdockerコンテナを起動しています。dockerコンテナ一つがKubernetesのノードとして割り当てられます。
dockerコンテナの中(仮想的なノードの中)ではコンテナランタイム(containerd)が起動しています。このコンテナランタイムがKubernetesのコンポーネントやアプリケーションをコンテナとして管理しています。dockerコンテナの中ではkubeletが起動してコンテナインスタンスをノードと勘違いさせています。
dockerコンテナ内でコンテナランタイムとkubeletが動作することで、コンテナの中でコンテナ制御を行えるようにしています。
ホストからのコマンド通信(例えばkubectl)はport mappingされて最終的にはdockerコンテナ内のapi-serverに通信するようにしています。

環境と事前準備

Ubuntu 20.04で動作確認しています。

まず、Dockerをインストールします。(docker.ceでもOK)

> sudo apt install docker.io

dockerがちゃんとインストールされたか確認します。

> docker version
Client:
 Version:           20.10.12
 API version:       1.41
 Go version:        go1.16.2
 Git commit:        20.10.12-0ubuntu2~20.04.1
 Built:             Wed Apr  6 02:14:38 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server:
 Engine:
  Version:          20.10.12
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.2
  Git commit:       20.10.12-0ubuntu2~20.04.1
  Built:            Thu Feb 10 15:03:35 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.5.9-0ubuntu1~20.04.1
  GitCommit:
 runc:
  Version:          1.1.0-0ubuntu1~20.04.1
  GitCommit:
 docker-init:
  Version:          0.19.0
  GitCommit:

次にKubernetesをインストールします。

> sudo apt install apt-transport-https curl

> curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add
> sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
> sudo apt install kubeadm kubelet kubectl kubernetes-cni

> kubectl version --client=true --short
Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
Client Version: v1.24.0
Kustomize Version: v4.5.4

Kindでクラスタ構築

Kindをインストール

> go install sigs.k8s.io/kind@v0.12.0
> kind version
kind v0.12.0 go1.18.1 linux/amd64

シングルノードクラスタ作成と削除

> kind create cluster

> kubectl cluster-info --context kind-kind
Kubernetes control plane is running at https://127.0.0.1:39857
CoreDNS is running at https://127.0.0.1:39857/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

これだけです。これでシングルノードのクラスタが構築されています。

> kubectl get nodes -o wide
NAME                 STATUS   ROLES                  AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE       KERNEL-VERSION      CONTAINER-RUNTIME
kind-control-plane   Ready    control-plane,master   72s   v1.23.4   172.18.0.2    <none>        Ubuntu 21.10   5.13.0-40-generic   containerd://1.5.10

KindはKubernetesを起動するときにconfigを${HOME}/.kube/configに追加し、ホストのポート6443をコンテナとして起動したapi-serverへマッピングしているため、ホストマシンからkubectlにてクラスタを管理することも可能です。

> docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS                       NAMES
10e90347f982   kindest/node:v1.23.4   "/usr/local/bin/entr…"   55 seconds ago   Up 52 seconds   127.0.0.1:39857->6443/tcp   kind-control-plane

kind-control-planeがKubernetesのcontrol-planeとして起動していることがわかります。

kind delete cluster
Deleting cluster "kind" ...

削除するときはこれだけです。

ただ、これだとシングルノードのマスターだけなのでさみしい。。。
なのでマルチノードクラスタをcontainerで作ってみます。(あくまで物理マシンは一台です。)

マルチノードクラスタ

以下のyamlをkindコマンドに渡して、マルチノードクラスタを作成します。


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

> kind create cluster --config=multi-node.yaml
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.23.4) 🖼
 ✓ Preparing nodes 📦 📦 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
 ✓ Joining worker nodes 🚜
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Not sure what to do next? 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/

すると、Kubernetesのノードとして複数のdockerコンテナが起動して、マルチノードクラスタを構築できます。

> kubectl get nodes -o wide
NAME                 STATUS   ROLES                  AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE       KERNEL-VERSION      CONTAINER-RUNTIME
kind-control-plane   Ready    control-plane,master   59s   v1.23.4   172.18.0.3    <none>        Ubuntu 21.10   5.13.0-40-generic   containerd://1.5.10
kind-worker          Ready    <none>                 34s   v1.23.4   172.18.0.4    <none>        Ubuntu 21.10   5.13.0-40-generic   containerd://1.5.10
kind-worker2         Ready    <none>                 34s   v1.23.4   172.18.0.2    <none>        Ubuntu 21.10   5.13.0-40-generic   containerd://1.5.10

> docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED              STATUS              PORTS                       NAMES
026f6377ccb8   kindest/node:v1.23.4   "/usr/local/bin/entr…"   About a minute ago   Up About a minute                               kind-worker2
cbf0ef62fc77   kindest/node:v1.23.4   "/usr/local/bin/entr…"   About a minute ago   Up About a minute                               kind-worker
84c9aab0833c   kindest/node:v1.23.4   "/usr/local/bin/entr…"   About a minute ago   Up About a minute   127.0.0.1:41081->6443/tcp   kind-control-plane

次にアプリ(Pods)をデプロイしてみます。

Kindに渡すyamlを少し修正して、ホストポート30070からWebにつなげるようにしておきます。

> cat multi-node.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30080
    hostPort: 30070
- role: worker
- role: worker

> kind create cluster --config=multi-node.yaml
...

KubernetesのServiceとしてポート30080を設定し、Podのポート80とマッピングしておきます。アプリケーションはDockerHubにあるnginxを利用します。

> cat app-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web-nginx
  name: web-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-nginx
  template:
    metadata:
      labels:
        app: web-nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-nginx
spec:
  selector:
    app: web-nginx
  type: NodePort
  ports:
    - port: 80
      nodePort: 30080

> kubectl create -f app-nginx.yaml

すると、kubectlでPod/Serviceが以下のように起動できたことが確認できます。

> kubectl get pods -o wide
NAME                         READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
web-nginx-585955c9c8-hkrk4   1/1     Running   0          73s   10.244.1.3   kind-worker2   <none>           <none>
web-nginx-585955c9c8-jrccb   1/1     Running   0          73s   10.244.1.2   kind-worker2   <none>           <none>
web-nginx-585955c9c8-kz49v   1/1     Running   0          73s   10.244.2.2   kind-worker    <none>           <none>

> kubectl get services -o wide
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE     SELECTOR
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP        5m46s   <none>
web-nginx    NodePort    10.96.10.179   <none>        80:30080/TCP   110s    app=web-nginx

port mappingは30070(host) --- 30080(k8s service) --- 80(pod)になっているので、http:/ホストマシンのIP/:30070/ にブラウザでアクセスすると以下が見えます。

image.png

これ以降は補足情報になりますが、

> docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED         STATUS         PORTS                                                 NAMES
05fca9ee8e9e   kindest/node:v1.23.4   "/usr/local/bin/entr…"   4 minutes ago   Up 4 minutes   0.0.0.0:30072->30080/tcp                              kind-worker2
8abd9d1e1926   kindest/node:v1.23.4   "/usr/local/bin/entr…"   4 minutes ago   Up 4 minutes   127.0.0.1:40971->6443/tcp, 0.0.0.0:30070->30080/tcp   kind-control-plane
b557b30529b4   kindest/node:v1.23.4   "/usr/local/bin/entr…"   4 minutes ago   Up 4 minutes   0.0.0.0:30071->30080/tcp                              kind-worker

なぜアプリケーションpodsのコンテナがホストから見えないかというと、dockerコンテナの中のcontainerdで管理されているからです。例えば、上記のデプロイメントの場合、アプリケーションPodは、kind-worker もしくは kind-worker2 のノードで起動していることがわかります。

一旦dockerコマンド(docker exec -it [container id] /bin/bashとか)を利用して、ホストマシンからkind-workerに乗り込みます。(これは特定のノードの中にログインした状態と同じです。)
dockerコンテナの中にはdockerはいないので、ctrコマンドを使ってcontainerdが管理するコンテナをチェックします。

> ctr -n k8s.io container list
CONTAINER                                                           IMAGE                                            RUNTIME     
32c712d22a7f60bec95c4d2d51c9d0057222fbd4d032a5f351bea7675188ef84    k8s.gcr.io/pause:3.6                             io.containerd.runc.v2
40a7ef598849e6709d11e0c6ae8bda1ac3047c0ee9f6b3e8cdfc7dcdcbac1cd8    k8s.gcr.io/kube-proxy:v1.23.4                    io.containerd.runc.v2
93496727074f147a1446d91d887d3e64a7d55710cec583e46de861fb84840628    k8s.gcr.io/pause:3.6                             io.containerd.runc.v2
943d7c26a01f3aef786c3f26e731a52362c6ec8844283d1a6bb83081c25c1a89    docker.io/kindest/kindnetd:v20211122-a2c10462    io.containerd.runc.v2
9a157042a8068975b92fc8091b73e5180936265612bd73a86a3905bb40ba857a    k8s.gcr.io/pause:3.6                             io.containerd.runc.v2
ea2c62477b749ef208f11c108a1396bbebca64c00398b8a5a169555af157ebc4    docker.io/library/nginx:latest                   io.containerd.runc.v2

上記の通り、Kubenretesのコンポーネント群とアプリケーションPod(nginx)が起動していることがわかります。
namespaceがk8s.gcr.ioになっていますが、調べ方はこちらを参照ください

最後にすべての過去を消し去ります。

> kind delete cluster
Deleting cluster "kind" ...

参照

28
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
20