お金をかけずにサーバーの勉強をしよう

MicroK8sのクラスタ作成

2024年7月29日

メニューへ戻る

Kubernetesらしくクラスタ環境を作りますよ!

MicroK8sでKubernetesのお勉強」にて、シングル構成(1台だけ)の Kubernetes環境を作りましたが、Kubernetesの真髄はやはり分散環境によるロードの分散と冗長化ですので、ここでは 3台のクラスタ環境を作ります。

MicroK8sのクラスタ環境の作り方はこちら。
Create a MicroK8s cluster


1.環境

3つのサーバーは Ubuntu Server 24.04で作ります。

役割マシン名IPアドレスCPU数メモリ量
マスターノードmicrok8s-master192.168.1.12024GB
ワーカーノード1microk8s-worker1192.168.1.12124GB
ワーカーノード2microk8s-worker2192.168.1.12224GB

Ubuntu Server 24.04のインストールについては「Ubuntu 24.04 Server インストール」に書いていて、その手順で作りました。

MicroK8sのバージョンは 2024年7月29日時点で 1.30.1になっています。


2.事前準備

マスターノードの [microk8s-master] でワーカーノードの [microk8s-worker1][microk8s-worker2] のマシン名を解決できるよう、マスターノードの [/etc/hosts]ファイルに以下の行を追加しておきます。

192.168.1.121   microk8s-worker1
192.168.1.122   microk8s-worker2

それから3台全てで「MicroK8sでKubernetesのお勉強」でやっている通り、MicroK8sのインストールまでやっておきます。


3.クラスタ構築

では手順に従って進めていきます。

まずマスターノードで以下の作業を行います。
これによりワーカーノードで実行するべきコマンド行が生成されます。

コマンド行が 3種類ありますが、ピンク色の行が今回の対象です。
暗号のような箇所は add-nodeを実行する度に変わります。

subro@microk8s-master:~$ sudo microk8s add-node
From the node you wish to join to this cluster, run the following:
microk8s join 192.168.1.120:25000/c855d3b0126b0fdd22a462b8cddafba2/1a7d04600797

Use the '--worker' flag to join a node as a worker not running the control plane, eg:
microk8s join 192.168.1.120:25000/c855d3b0126b0fdd22a462b8cddafba2/1a7d04600797 --worker

If the node you are adding is not reachable through the default interface you can use one of the following:
microk8s join 192.168.1.120:25000/c855d3b0126b0fdd22a462b8cddafba2/1a7d04600797
microk8s join 2408:82:a8:0:20c:29ff:fef0:c166:25000/c855d3b0126b0fdd22a462b8cddafba2/1a7d04600797

ではピンク行を [microk8s-worker1]サーバーで実行します。

subro@microk8s-worker1:~$ sudo microk8s join 192.168.1.120:25000/c855d3b0126b0fdd22a462b8cddafba2/1a7d04600797
Contacting cluster at 192.168.1.120
Waiting for this node to finish joining the cluster. .. .. .. ..
Successfully joined the cluster.

うまくいったようです。

続けて [microk8s-worker2]サーバーでもやるんですが、[microk8s-master]サーバーで microk8s add-nodeコマンドの実行からやって下さい。
どうやらこれはクラスタに新規追加する度にやるようです。

終わったら、参加しているノードを確認してみます。
(この環境では状態確認のコマンドはどのノードで実行しても取れます。)

subro@microk8s-master:~$ sudo microk8s kubectl get no
NAME               STATUS   ROLES    AGE    VERSION
microk8s-master    Ready    <none>   10m    v1.30.1
microk8s-worker1   Ready    <none>   5m9s   v1.30.1
microk8s-worker2   Ready    <none>   34s    v1.30.1

クラスタにワーカーノードとなれるマシンが 3つになりました。

※本気の環境ではマスターノードを複数立てて冗長化し、マスターノードにはワーカーノードの役割をやらせず、また、ワーカーノードにはマスターノードの役割をやらせないようにする、というのが良い設計のようです。
しかし実験用の PCにメモリの余裕がないので、ここではマスターノードもワーカーノードを兼ねてもらうことにしています。

クラスタの状態を見てみると、HA(high-availability)が有効になっていることが分かります。

subro@microk8s-master:~$ sudo microk8s status --wait-ready
microk8s is running
high-availability: yes
  datastore master nodes: 192.168.1.120:19001 192.168.1.121:19001 192.168.1.122:19001
  datastore standby nodes: none
addons:
  enabled:
    dns                  # (core) CoreDNS
    ha-cluster           # (core) Configure high availability on the current node
    helm                 # (core) Helm - the package manager for Kubernetes
    helm3                # (core) Helm 3 - the package manager for Kubernetes
  disabled:
    cert-manager         # (core) Cloud native certificate management
    cis-hardening        # (core) Apply CIS K8s hardening
    community            # (core) The community addons repository
    dashboard            # (core) The Kubernetes dashboard
    gpu                  # (core) Alias to nvidia add-on
    host-access          # (core) Allow Pods connecting to Host services smoothly
    hostpath-storage     # (core) Storage class; allocates storage from host directory
    ingress              # (core) Ingress controller for external access
    kube-ovn             # (core) An advanced network fabric for Kubernetes
    mayastor             # (core) OpenEBS MayaStor
    metallb              # (core) Loadbalancer for your Kubernetes cluster
    metrics-server       # (core) K8s Metrics Server for API access to service metrics
    minio                # (core) MinIO object storage
    nvidia               # (core) NVIDIA hardware (GPU and network) support
    observability        # (core) A lightweight observability stack for logs, traces and metrics
    prometheus           # (core) Prometheus operator for monitoring and logging
    rbac                 # (core) Role-Based Access Control for authorisation
    registry             # (core) Private image registry exposed on localhost:32000
    rook-ceph            # (core) Distributed Ceph storage using Rook
    storage              # (core) Alias to hostpath-storage add-on, deprecated


とりあえずこれで kubernetesのクラスタ環境として負荷分散と冗長化をしているはずです。


4.クラスタへの Pod配備

NGiNXの Podを 9個ばかり動かしてみましょうか。

予想では 1台あたり Podが 3個ずつ動くような気がします。

Podのデプロイ用に [nginx.yaml]ファイルを以下の内容で作成しました。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 9
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

デプロイします。

subro@microk8s-master:~$ sudo microk8s kubectl apply -f nginx.yaml
deployment.apps/nginx-deployment created

Podがどうなったか見てみます。

subro@microk8s-master:~$ sudo microk8s kubectl get all --all-namespaces
NAMESPACE     NAME                                          READY   STATUS              RESTARTS   AGE
default       pod/nginx-deployment-6cfb64b7c5-6pcdd         0/1     ContainerCreating   0          19s
default       pod/nginx-deployment-6cfb64b7c5-7hvtz         0/1     ContainerCreating   0          19s
default       pod/nginx-deployment-6cfb64b7c5-7pxst         0/1     ContainerCreating   0          19s
default       pod/nginx-deployment-6cfb64b7c5-9hwcn         0/1     ContainerCreating   0          20s
default       pod/nginx-deployment-6cfb64b7c5-9jdqs         0/1     ContainerCreating   0          19s
default       pod/nginx-deployment-6cfb64b7c5-9ztcd         0/1     ContainerCreating   0          19s
default       pod/nginx-deployment-6cfb64b7c5-kkgcs         0/1     ContainerCreating   0          20s
default       pod/nginx-deployment-6cfb64b7c5-t7rkm         0/1     ContainerCreating   0          19s
default       pod/nginx-deployment-6cfb64b7c5-tpmp5         0/1     ContainerCreating   0          20s
kube-system   pod/calico-kube-controllers-796fb75cc-9bmbf   1/1     Running             0          23m
kube-system   pod/calico-node-9648k                         1/1     Running             0          18m
kube-system   pod/calico-node-mppgq                         1/1     Running             0          18m
kube-system   pod/calico-node-rkd96                         1/1     Running             0          13m
kube-system   pod/coredns-5986966c54-4lbp5                  1/1     Running             0          23m

NAMESPACE     NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
default       service/kubernetes   ClusterIP   10.152.183.1    <none>        443/TCP                  24m
kube-system   service/kube-dns     ClusterIP   10.152.183.10   <none>        53/UDP,53/TCP,9153/TCP   23m

NAMESPACE     NAME                         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-system   daemonset.apps/calico-node   3         3         3       3            3           kubernetes.io/os=linux   23m

NAMESPACE     NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
default       deployment.apps/nginx-deployment          0/9     9            0           20s
kube-system   deployment.apps/calico-kube-controllers   1/1     1            1           23m
kube-system   deployment.apps/coredns                   1/1     1            1           23m

NAMESPACE     NAME                                                DESIRED   CURRENT   READY   AGE
default       replicaset.apps/nginx-deployment-6cfb64b7c5         9         9         0       20s
kube-system   replicaset.apps/calico-kube-controllers-796fb75cc   1         1         1       23m
kube-system   replicaset.apps/coredns-5986966c54                  1         1         1       23m

[pod/nginx-deployment-」で始まるのが 9行あり、Podは予定の数立ち上がっていることが分かります。

ワーカーノードへの分散っぷりを見てみます。

subro@microk8s-master:~$ sudo microk8s kubectl get pods -l app=nginx -o wide
NAME                                READY   STATUS    RESTARTS   AGE     IP             NODE               NOMINATED NODE   READINESS GATES
nginx-deployment-6cfb64b7c5-6pcdd   1/1     Running   0          7m29s   10.1.195.66    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-7hvtz   1/1     Running   0          7m29s   10.1.195.65    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-7pxst   1/1     Running   0          7m29s   10.1.166.132   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-9hwcn   1/1     Running   0          7m30s   10.1.195.67    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-9jdqs   1/1     Running   0          7m29s   10.1.166.133   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-9ztcd   1/1     Running   0          7m29s   10.1.170.66    microk8s-worker2   <none>           <none>
nginx-deployment-6cfb64b7c5-kkgcs   1/1     Running   0          7m30s   10.1.166.131   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-t7rkm   1/1     Running   0          7m29s   10.1.170.65    microk8s-worker2   <none>           <none>
nginx-deployment-6cfb64b7c5-tpmp5   1/1     Running   0          7m30s   10.1.170.67    microk8s-worker2   <none>           <none>

見事に 3個ずつ別れています。\(^o^)/


5.冗長化のテスト

折角ですから、冗長化の方もやってみます。

[microk8s-worker2]サーバーをシャットダウンしてみます。
3つの Podが落ちて他のノードで立ち上がれば OK。

subro@microk8s-worker2:~$ sudo poweroff

ノードの状態を見ると [microk8s-worker2]サーバーの状態が [NotReady]になりました。

subro@microk8s-master:~$ sudo microk8s kubectl get no
NAME               STATUS     ROLES    AGE   VERSION
microk8s-master    Ready      <none>    36m   v1.30.1
microk8s-worker1   Ready      <none>    30m   v1.30.1
microk8s-worker2   NotReady   <none>    25m   v1.30.1

5分くらい経ったでしょうか、自動的に他ノードへの切り替えが発生しました。
[microk8s-worker2]にあった Podが [Terminating]になり、他のノードで [ContainerCreating]になっているのが分かります。

subro@microk8s-master:~$ sudo microk8s kubectl get pods -l app=nginx -o wide
NAME                                READY   STATUS              RESTARTS   AGE   IP             NODE               NOMINATED NODE   READINESS GATES
nginx-deployment-6cfb64b7c5-6pcdd   1/1     Running             0          17m   10.1.195.66    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-6xzzd   0/1     ContainerCreating   0          1s    <none>         microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-7hvtz   1/1     Running             0          17m   10.1.195.65    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-7pxst   1/1     Running             0          17m   10.1.166.132   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-9hwcn   1/1     Running             0          17m   10.1.195.67    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-9jdqs   1/1     Running             0          17m   10.1.166.133   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-9ztcd   1/1     Terminating         0          17m   10.1.170.66    microk8s-worker2   <none>           <none>
nginx-deployment-6cfb64b7c5-kkgcs   1/1     Running             0          17m   10.1.166.131   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-rk9g2   0/1     ContainerCreating   0          1s    <none>         microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-t7rkm   1/1     Terminating         0          17m   10.1.170.65    microk8s-worker2   <none>           <none>
nginx-deployment-6cfb64b7c5-tpmp5   1/1     Terminating         0          17m   10.1.170.67    microk8s-worker2   <none>           <none>
nginx-deployment-6cfb64b7c5-zn7p5   0/1     ContainerCreating   0          1s    <none>         microk8s-worker1   <none>           <none>

その結果、[ microk8s-master]サーバーと [microk8s-worker1]サーバーに振り分けられたようです。

subro@microk8s-master:~$ sudo microk8s kubectl get pods -l app=nginx -o wide
NAME                                READY   STATUS        RESTARTS   AGE     IP             NODE               NOMINATED NODE   READINESS GATES
nginx-deployment-6cfb64b7c5-6pcdd   1/1     Running       0          26m     10.1.195.66    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-6xzzd   1/1     Running       0          8m57s   10.1.166.134   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-7hvtz   1/1     Running       0          26m     10.1.195.65    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-7pxst   1/1     Running       0          26m     10.1.166.132   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-9hwcn   1/1     Running       0          26m     10.1.195.67    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-9jdqs   1/1     Running       0          26m     10.1.166.133   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-9ztcd   1/1     Terminating   0          26m     10.1.170.66    microk8s-worker2   <none>           <none>
nginx-deployment-6cfb64b7c5-kkgcs   1/1     Running       0          26m     10.1.166.131   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-rk9g2   1/1     Running       0          8m57s   10.1.195.69    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-t7rkm   1/1     Terminating   0          26m     10.1.170.65    microk8s-worker2   <none>           <none>
nginx-deployment-6cfb64b7c5-tpmp5   1/1     Terminating   0          26m     10.1.170.67    microk8s-worker2   <none>           <none>
nginx-deployment-6cfb64b7c5-zn7p5   1/1     Running       0          8m57s   10.1.195.68    microk8s-worker1   <none>           <none>

ちゃんと HAになっていますね。

[microk8s-worker2]サーバーを起動します。

[microk8s-worker2]サーバーがクラスタに戻ってきました。

subro@microk8s-master:~$ sudo microk8s kubectl get no
NAME               STATUS   ROLES    AGE   VERSION
microk8s-master    Ready    <none>   58m   v1.30.1
microk8s-worker1   Ready    <none>   52m   v1.30.1
microk8s-worker2   Ready    <none>   47m   v1.30.1

また [microk8s-worker2]サーバーに元通り Podが分散されているような気がするので、再度分散っぷりを見てみます。

subro@microk8s-master:~$ sudo microk8s kubectl get pods -l app=nginx -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP             NODE               NOMINATED NODE   READINESS GATES
nginx-deployment-6cfb64b7c5-6pcdd   1/1     Running   0          36m   10.1.195.66    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-6xzzd   1/1     Running   0          19m   10.1.166.134   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-7hvtz   1/1     Running   0          36m   10.1.195.65    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-7pxst   1/1     Running   0          36m   10.1.166.132   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-9hwcn   1/1     Running   0          36m   10.1.195.67    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-9jdqs   1/1     Running   0          36m   10.1.166.133   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-kkgcs   1/1     Running   0          36m   10.1.166.131   microk8s-master    <none>           <none>
nginx-deployment-6cfb64b7c5-rk9g2   1/1     Running   0          19m   10.1.195.69    microk8s-worker1   <none>           <none>
nginx-deployment-6cfb64b7c5-zn7p5   1/1     Running   0          19m   10.1.195.68    microk8s-worker1   <none>           <none>

しかし、待てど暮せど一向に変化がありません。

実は Kubernetesは Podの再配置はしてくれないんですね〜。

これを実現するには Deschedulerという機能を使わないといけないようです。

しかし、このネタはここまでで終わりなのでした。
Deschedulerについてはいずれ別なところで書こうと思います。

更にここでもまだ NGINXの Podにクラスタ外の PCからアクセス出来ないのでした…。

この環境でクラスタ外部からアクセスできるようにする話を「オンプレ Kubernetes環境に LoadBalancerサービスを」に書いています。


==========
というわけでオンプレで Kubernetesクラスタを作りました。

非常に簡単にできましたね。

これならマスターノードの冗長化とワーカーノードの役割の分離までやればよかったかな?

これだけでもかなりそれっぽい環境になってきましたが、まだ外部からの通信ができないので、使い物になりません。

上記の次のネタでやっとそれを実現しますので、ご期待下さい。