前回からの続き。Proxmoxに作ったk8s1をクローンしてk8s3まで増やします。とりあえずk8s1で必要なソフトウェアのインストールとかセットアップとか済ませてからクローンしましょう。
セットアップ
ひとまずWebコンソールから設定していきます。

1. ホスト名の設定
$ sudo hostnamectl set-hostname k8s1 $ sudo sed "s/ubuntu/k8s1/" -i /etc/hosts
2. timezoneをJSTに
$ sudo timedatectl set-timezone Asia/Tokyo
3. opensshをインストール(オプショナル)
$ sudo apt install -U -y ssh
4. microk8sのインストール 素のK8sでもいいんですが、今回はmicrok8sにします。楽したい
$ sudo snap install microk8s --classic
インストールが完了したらstatusを確認してみましょう。
$ sudo microk8s status
microk8s is running
high-availability: no
datastore master nodes: 127.0.0.1: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
addonは必要なものを有効化するといいですが、今回はとりあえずhostpath-storageとingressくらい有効化しておきます。使うかはわかりません。
$ sudo microk8s enable hostpath-storage
Infer repository core for addon hostpath-storage
Enabling default storage class.
WARNING: Hostpath storage is not suitable for production environments.
A hostpath volume can grow beyond the size limit set in the volume claim manifest.
deployment.apps/hostpath-provisioner created
storageclass.storage.k8s.io/microk8s-hostpath created
serviceaccount/microk8s-hostpath created
clusterrole.rbac.authorization.k8s.io/microk8s-hostpath created
clusterrolebinding.rbac.authorization.k8s.io/microk8s-hostpath created
Storage will be available soon.
$ sudo microk8s enable ingress
Infer repository core for addon ingress
Enabling Ingress
ingressclass.networking.k8s.io/public created
ingressclass.networking.k8s.io/nginx created
namespace/ingress created
serviceaccount/nginx-ingress-microk8s-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-microk8s-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-microk8s-role created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-microk8s created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-microk8s created
configmap/nginx-load-balancer-microk8s-conf created
configmap/nginx-ingress-tcp-microk8s-conf created
configmap/nginx-ingress-udp-microk8s-conf created
daemonset.apps/nginx-ingress-microk8s-controller created
Ingress is enabled
実はmicrok8sをインストールした時点でK8sのインストールって終わってしまってるんですよね。K8sにアクセスできるか確認してみます。
$ sudo microk8s.kubectl get nodes NAME STATUS ROLES AGE VERSION ubuntu Ready <none> 9m39s v1.32.9
ノードが見れました。ただちょっとkubectlコマンドが叩きづらいので、先頭のmicrok8s.を省略できるようにしておきましょう。
$ sudo snap alias microk8s.kubectl kubectl
これでkubectlコマンド単体でも実行できるようになりました。
$ kubectl
Insufficient permissions to access MicroK8s.
You can either try again with sudo or add the user ubuntu to the 'microk8s' group:
sudo usermod -a -G microk8s ubuntu
sudo chown -R ubuntu ~/.kube
After this, reload the user groups either via a reboot or by running 'newgrp microk8s'.
sudoをつけ忘れて↑のようなエラーが出てしまいました。microk8sグループに所属する必要があるみたいですね。sudoなしで実行したい方は下記
$ sudo usermod -a -G microk8s ubuntu # `ubuntu`の部分はログイン中のユーザー名に変更 $ sudo chown -R ubuntu ~/.kube
~/.kubeがまだ存在していない環境ではchownはエラーになると思いますが、~/.kubeがないなら問題ないです。
一度ログアウト&ログインして再度確認
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ubuntu Ready <none> 15m v1.32.9
最後にローカルマシンからアクセスできるようにします。
ここまでの設定だけだとk8s1サーバーに乗り込んでK8sを操作することになりますが、それだと何かと不便です。そこでアクセスするための情報を出力してローカルマシンにコピーします。
microk8s config | sed "s/microk8s/$HOSTNAME/; s/admin/$HOSTNAME-admin/" > kubeconfig
ここで生成されたkubeconfigをローカルマシンの~/.kube/configにコピーしてください。すでに~/.kube/configが存在している場合はバックアップをとっておくのがいいでしょう。なお、ローカルマシンにkubectlコマンドが入っていない場合はこちらの手順でインストールしておきましょう。
$ mkdir ~/.kube $ scp k8s1:kubeconfig ~/.kube/config
ローカル環境からkubectlコマンドが実行できればOKです。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ubuntu Ready <none> 65m v1.32.9
初期設定はこの辺で
5. クローン
対象のVMを右クリックするとコンテキストメニューが出てきます。

下から3番目に「Clone」とあるのでこちらをクリック

VM名などの入力を促されるので「k8s2」と入力しましょう。
上記の手順で「k8s3」まで増やしておいてください。

k8s2と3はk8s1のノードとして追加します。
6. クローンしたVMの設定
クローンしたVMを起動してみましょう。
全ての設定が引き継がれているので、当然ですがk8s2のホスト名が「k8s1」になっています。
ホスト名だけならいいですが、IPアドレスを確認してみてください。1と2で同じIPになってると思います。


どちらも「192.168.100.142」になっています。
これはProxmoxのフォーラムでも言及されています。
IP Address duplicates/conflicts when cloning from a template | Proxmox Support Forum
簡単に説明すると、VMをクローンする際Proxmoxは新しいMACアドレスを割り当てますが、クローンされたVMは同じmachine-idが設定されているので同じIPを要求してしまいます。
フォーラムに解決方法も書いてあるので、k8s2で実行しましょう。
$ sudo rm -f /etc/machine-id && sudo dbus-uuidgen --ensure=/etc/machine-id && sudo rm /var/lib/dbus/machine-id && sudo dbus-uuidgen --ensure
ホスト名も変更
$ sudo hostnamectl set-hostname k8s2
SSHのホストキーも再生成しておきます。
$ sudo rm -f /etc/ssh/ssh_host_* $ sudo dpkg-reconfigure openssh-server
設定が終わったらRebootして再ログインしてみましょう。ホスト名とIPが変更されていることを確認します。

うまく変更されていれたら同じ設定をk8s3の方にも適用しておきます。
7. k8s2,3のk8s1のノードに設定する
ここからはコピペができないとだいぶつらいのでSSH経由で
ノードを追加するクラスター(今回はk8s1)でmicrok8s add-nodeコマンドを実行します。
$ microk8s add-node From the node you wish to join to this cluster, run the following: microk8s join 192.168.100.142:25000/a17cfad31f0f977c6c57a80a243da890/355581782afd Use the '--worker' flag to join a node as a worker not running the control plane, eg: microk8s join 192.168.100.142:25000/a17cfad31f0f977c6c57a80a243da890/355581782afd --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.100.142:25000/a17cfad31f0f977c6c57a80a243da890/355581782afd microk8s join fdfa:750d:b43d:1:be24:11ff:fef3:7c72:25000/a17cfad31f0f977c6c57a80a243da890/355581782afd
ノードを追加するための3つの選択肢が出てきました。
1つ目はフルノードとして追加されます。つまりコントロールプレーンも実行されるということですね。脳みそが複数あるキングギドラをみたいにしたい場合はこちら。
From the node you wish to join to this cluster, run the following: microk8s join 192.168.100.142:25000/a17cfad31f0f977c6c57a80a243da890/355581782afd
2つ目はワーカーノードとして追加されます。ワーカーノードはコンテナを実行するためのノードなので、ほとんどの場合これで十分です。
Use the '--worker' flag to join a node as a worker not running the control plane, eg: microk8s join 192.168.100.142:25000/a17cfad31f0f977c6c57a80a243da890/355581782afd --worker
3つ目は複数のNICを持っている場合、別のIPでアクセスできるようにするためのもので、今回の場合だと不要です。
If the node you are adding is not reachable through the default interface you can use one of the following: microk8s join 192.168.100.142:25000/a17cfad31f0f977c6c57a80a243da890/355581782afd microk8s join fdfa:750d:b43d:1:be24:11ff:fef3:7c72:25000/a17cfad31f0f977c6c57a80a243da890/355581782afd
k8s2で2つ目のmicrok8s join 192.168.100.142:25000/a17cfad31f0f977c6c57a80a243da890/355581782afd --workerを実行します。
k8s3で実行するコマンドはk8s1で再度add-nodeを実行してから行いましょう。

エラーが出なければ上手く追加できていると思うので、kubectl get nodesを実行し、ノードが追加されたか確認します。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION k8s1 Ready <none> 40m v1.32.9 k8s2 Ready <none> 36s v1.32.9 k8s3 Ready <none> 5s v1.32.9 ubuntu NotReady <none> 72m v1.32.9
私の環境だとホスト名が「ubuntu」だった頃にmicrok8sをインストールしてしまったのでubuntuというノードがNotReadyで生えてしまいました。
不要なので削除します。
$ microk8s remove-node ubuntu $ kubectl get nodes NAME STATUS ROLES AGE VERSION k8s1 Ready <none> 46m v1.32.9 k8s2 Ready <none> 6m20s v1.32.9 k8s3 Ready <none> 5m49s v1.32.9
これでK8s環境の準備は完了です。
試してみる
Kubernetesの公式チュートリアルで使用されているguestbookというのをデプロイしてみましょう。
Redisをデプロイします。
$ kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-deployment.yaml
Podを見てみましょう。
$ kubectl get pods NAME READY STATUS RESTARTS AGE redis-leader-5f4cc9b47d-t2drd 1/1 Running 0 18s
どのノードで実行されているかもみるには-o wideオプションを使用します。
$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES redis-leader-5f4cc9b47d-t2drd 1/1 Running 0 41s 10.1.219.2 k8s3 <none> <none>
k8s3で動いてるのがわかりましたね。
どんどん行きましょう。
$ kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-service.yaml $ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 83m redis-leader ClusterIP 10.152.183.56 <none> 6379/TCP 7s $ kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES redis-follower-854f6dcbd5-lbwkj 1/1 Running 0 29s 10.1.109.66 k8s2 <none> <none> redis-follower-854f6dcbd5-njfbr 1/1 Running 0 29s 10.1.219.3 k8s3 <none> <none> redis-leader-5f4cc9b47d-t2drd 1/1 Running 0 3m50s 10.1.219.2 k8s3 <none> <none> $ kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml $ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 85m redis-follower ClusterIP 10.152.183.216 <none> 6379/TCP 3s redis-leader ClusterIP 10.152.183.56 <none> 6379/TCP 2m37s $ kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml $ kubectl get pods -l app=guestbook -l tier=frontend -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-7c457c988c-9vlt7 1/1 Running 0 83s 10.1.219.4 k8s3 <none> <none> frontend-7c457c988c-gm8ld 1/1 Running 0 83s 10.1.109.67 k8s2 <none> <none> frontend-7c457c988c-ldh64 1/1 Running 0 83s 10.1.166.196 k8s1 <none> <none> $ kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml $ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE frontend ClusterIP 10.152.183.252 <none> 80/TCP 3s kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 87m redis-follower ClusterIP 10.152.183.216 <none> 6379/TCP 2m5s redis-leader ClusterIP 10.152.183.56 <none> 6379/TCP 4m39s
必要なアプリケーションとサービスを作成できました。get pods を確認するとk8s1~3のノードで動いてるのが確認できたと思います。
最後にサービスにポートフォワードしてアプリケーションにアクセスできるか確認しましょう。
注意:ローカルの8080とServiceの80番ポートをポートフォワードしているので、このコマンドはローカルマシンで実行する必要があります。
$ kubectl port-forward svc/frontend 8080:80
http://localhost:8080にアクセスするとデプロイしたアプリケーションが確認できます。

おわり
microk8sで簡単にK8sを実行できました。今回はUbuntu上で簡単に構築できるmicork8sを使用しましたが、k3sを使っても簡単にK8sクラスターを構築できます。ご興味があれば試してみるのがいいかもしれません。 minikubeやkindはローカルで動かすのには最適ですが、複数クラスターで設定するとなると???やり方を知りません。
