MENU
カテゴリー
アーカイブ

Kubernetes で Minecraft Server を設置する(その1)

目標は、前から気になっていた kubernetes をインストールして Minecraft Server を設置するところまで。
アプリを開発しているわけじゃないし、実際のところ Proxmox の仮想マシンやシステムコンテナで間に合っている。自鯖としての使いどころは無さそうな気もするけど、Web の情報も充実してきたから興味本位ということでやってみた。

構成は Master Node が1台、Worker Node が3台で始めてみる。全部 VM で、あとから様子を見て Master Node を追加することにする。
もし Master Node が壊れたら、とりあえずバックアップから復元すればいいや。

目次

仮想マシン Ubuntu Server 22.04 の作成・設定(すべてのノード)

Ubuntu のインストール手順は割愛。
公式サイト(kubernetes 1.28)の手順どおり kubernetes をインストールする。

VM は次��とおり計4台。

種類Master NodeWoker NodeWorker NodeWorker Node
ホスト名k8s-node1k8s-node4k8s-node5k8s-node6
IP address10.1.1.3/1610.1.1.6/1610.1.1.7/1610.1.1.8/16
strage32G(ceph)32G(local)32G(local)32G(local)
memory4G8G8G8G

Master Node のストレージは ceph。ホストの PVE に障害が生じたらライブマイグレーションで他のホストに引っ越しできる。
Woker Node のストレージはホストの local。ほとんど使っていないから空き領域は十分にある。

kubernetes の永続ボリュームには、Master Node に 適当な容量のストレージ(ceph より)を追加して、NFS Server をたてることにする。

カーネルモジュールの設定

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system

確認。

lsmod | grep br_netfilter
br_netfilter           32768  0
bridge                409600  1 br_netfilter

lsmod | grep overlay
overlay               188416  0

sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1

swap の無効化

オンプレミス(自鯖)で潤沢なメモリを確保できないから、多少のリスクを伴うことを承知で次のドキュメントを参考に swap を有効にしてみたけど、kubeadm init でエラーが出てインストールできなかった。
なお、swap を無効化して kubernetes のインストールを終えたあとからでも有効化は可能みたいだけど試してない。

swap

swap は cgroup v2 でのみサポートされており、cgroup v1 はサポートされていません。

cgroup v2

cgroup のバージョンを確認するには次のコマンドを実行して、

stat -fc %T /sys/fs/cgroup/

cgroup v2 の場合、出力は cgroup2fs 。
cgroup v1 の場合、出力は tmpfs 。

コマンドは次のとおり。

※一時的に無効化
swapoff -a

※続いて永続的に無効化
vi /etc/fstab

次の行をコメントアウト
# /swap.img     none    swap    sw      0       0

※再マウント
sudo mount -a

/etc/hosts の編集

各ノードで名前解決できるように編集する。
こんな感じ。

127.0.0.1 localhost
127.0.1.1 k8s-node1

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

# 以下を追記
10.1.1.3 k8s-node1
10.1.1.6 k8s-node4
10.1.1.7 k8s-node5
10.1.1.8 k8s-node6

コンテナランタイム(CRI-O)のインストール

CRI(Container Runtime Interface)には containerd と CRI-O のどちらにしようかと少考して、今まで Docker を使ってた訳じゃないしということで、CRI-O をインストールすることにした。
手順はこちらのとおり。kubernetes のバージョンは 1.28。

以下は sudo su で実行する。

sudo su

export VERSION=1.28
export OS=xUbuntu_22.04

echo "deb [signed-by=/usr/share/keyrings/libcontainers-archive-keyring.gpg] https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
echo "deb [signed-by=/usr/share/keyrings/libcontainers-crio-archive-keyring.gpg] https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list

mkdir -p /usr/share/keyrings
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-archive-keyring.gpg
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-crio-archive-keyring.gpg

apt-get update
apt-get install cri-o cri-o-runc

systemctl daemon-reload
systemctl start crio
systemctl enable crio

ここで root から user に戻る(続けてもいいけど)。

kubeadm、kubelet、kubectl のインストール

1.28 用のドキュメントはこちら。

必要なパッケージをインストールする。

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

公開鍵をダウンロードする。

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

リポジトリを追加する。

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

kubeadm、kubelet、kubectl をインストールする。

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl

# バージョンを固定するため、パッケージが更新されないようにする。
sudo apt-mark hold kubelet kubeadm kubectl

コマンド crictl が使用できるから確認してみる。無事に CRI-O がコンテナランタイムとして認識されているようだ。

sudo crictl info

{
  "status": {
    "conditions": [
      {
        "type": "RuntimeReady",
        "status": true,
        "reason": "",
        "message": ""
      },
      {
        "type": "NetworkReady",
        "status": true,
        "reason": "",
        "message": ""
      }
    ]
  },
  "config": {
    "sandboxImage": "registry.k8s.io/pause:3.9"
  }
}

ここまでは Master Node も Worker Node も同じ。

Worker Node 用の VM を作る

Master Node の VM のクローンで Worker Node を作る。ただし、自鯖の都合によりストレージは local に変更する。ライブマイグレーションができないという意味では物理マシンに近い構成(停止中ならマイグレーション可能)。
あと、ホスト名と ip アドレスの変更を忘れないように。

以降は Master Node と Worker Node で別々の設定していく。

Master Node の設定

まずはコントロールプレーンを初期化する。

sudo kubeadm init --control-plane-endpoint 10.1.1.3 --pod-network-cidr=10.244.0.0/16

公式ドキュメントによると「--control-plane-endpointを渡さずに構築したシングルコントロールプレーンのクラスターを高可用性クラスターに切り替えることはサポートされていません。」となっているので、後々 Worker Node を追加する予定があるならオプションありで実行するほうが無難。

--pod-network-cidr=10.244.0.0/16 を追加しているのは、このあと CNI として Flannel をインストールするため。

kubeadm init の実行結果は次のとおり。
無事 Your Kubernetes control-plane has initialized successfully! となっている。
��いから折りたたむ。

kubeadm init 実行結果
[init] Using Kubernetes version: v1.28.3
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-node1 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.1.1.3]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8s-node1 localhost] and IPs [10.1.1.3 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8s-node1 localhost] and IPs [10.1.1.3 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 8.422280 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-node1 as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node k8s-node1 as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
[bootstrap-token] Using token: m7fy32.193g8woilczavy8f
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:

  kubeadm join 10.1.1.3:6443 --token upnaaa.pk・・・・・25 \
	--discovery-token-ca-cert-hash sha256:e1・・・・・00 \
	--control-plane 

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 10.1.1.3:6443 --token upnaaa.pk・・・・・25 \
	--discovery-token-ca-cert-hash sha256:e1・・・・・00 

最後のほうの join の2つはどこかに控えておくこと。

kubeadm init を最初からやり直すときは kubeadm reset と CNI 関係ファイルの削除(rm -rf /etc/cni/net.d/*)を実行しておくこと。

The reset process does not clean CNI configuration. To do so, you must remove /etc/cni/net.d

The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually by using the "iptables" command.

If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.

The reset process does not clean your kubeconfig files and you must remove them manually.
Please, check the contents of the $HOME/.kube/config file.

クラスター操作のための設定(コントロールプレーンの全て)

一般ユーザーで kubeadm init 実行時のメッセージに従って次のコマンドを実行する。今回の構成だとコントロールプレーンは k8s-node1 のみ。新たにコントロールプレーンとしてノードを追加したときは同様に実行する。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

CNI のインストール

Flannel 、Calico、Cilium などなど、多くの CNI があって何をどうやって選択すれば良いのか悩んだ。

今更かもしれないけど、まずは Flannel をデプロイしてみる。
コマンドはつぎのとおり。

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

確認。

kubectl get pod -A
NAMESPACE      NAME                                READY   STATUS             RESTARTS        AGE
kube-flannel   kube-flannel-ds-dj2v8               0/1     CrashLoopBackOff   19 (71s ago)    73m
kube-flannel   kube-flannel-ds-dml9k               0/1     CrashLoopBackOff   19 (111s ago)   74m
kube-flannel   kube-flannel-ds-j9kdr               0/1     CrashLoopBackOff   19 (50s ago)    73m
kube-flannel   kube-flannel-ds-rz778               1/1     Running            0               78m
kube-system    coredns-5dd5756b68-6ggxp            1/1     Running            0               85m
kube-system    coredns-5dd5756b68-qv9zs            1/1     Running            0               85m
kube-system    etcd-k8s-node1                      1/1     Running            1               85m
kube-system    kube-apiserver-k8s-node1            1/1     Running            0               85m
kube-system    kube-controller-manager-k8s-node1   1/1     Running            0               85m
kube-system    kube-proxy-7dxtx                    1/1     Running            0               74m
kube-system    kube-proxy-h4x97                    1/1     Running            0               73m
kube-system    kube-proxy-rxswk                    1/1     Running            0               73m
kube-system    kube-proxy-x9kz7                    1/1     Running            0               85m
kube-system    kube-scheduler-k8s-node1            1/1     Running            0               85m

Worker Node をクラスターに参加させる

控えておいた token を、クラスターに参加させたい Worker Node で実行する。

sudo kubeadm join 10.1.1.3:6443 --token upnaaa.pk・・・・・25 --discovery-token-ca-cert-hash sha256:e1・・・・・00

[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

Master Node で確認してみる。

kubectl get nodes

NAME        STATUS   ROLES           AGE   VERSION
k8s-node1   Ready    control-plane   43m    v1.28.3
k8s-node4   Ready    <none>          20m    v1.28.3
k8s-node5   Ready    <none>          2m8s   v1.28.3
k8s-node6   Ready    <none>          61s    v1.28.3

残りの Worker Node も同様に実行して無事に参加できた。
うまくいかなかったら原因を探してみて、Worker Node で kubeadm init を実行してから再度 join してみる。

Worker Node を追加するときの token は上(control-plane nodes)の join のところ。

次回に向けて

これでとりあえず kubernetes 環境構築はできた。

$ kubectl get all -A
NAMESPACE      NAME                                    READY   STATUS    RESTARTS   AGE
kube-flannel   pod/kube-flannel-ds-gz2hk               1/1     Running   0          97s
kube-flannel   pod/kube-flannel-ds-hg2jv               1/1     Running   0          22s
kube-flannel   pod/kube-flannel-ds-pcv8v               1/1     Running   0          46s
kube-flannel   pod/kube-flannel-ds-vb5gr               1/1     Running   1          24m
kube-system    pod/coredns-5dd5756b68-67dvx            1/1     Running   1          30m
kube-system    pod/coredns-5dd5756b68-qtd4k            1/1     Running   1          30m
kube-system    pod/etcd-k8s-node1                      1/1     Running   6          30m
kube-system    pod/kube-apiserver-k8s-node1            1/1     Running   5          30m
kube-system    pod/kube-controller-manager-k8s-node1   1/1     Running   11         30m
kube-system    pod/kube-proxy-2vhl6                    1/1     Running   0          97s
kube-system    pod/kube-proxy-ddnxk                    1/1     Running   1          30m
kube-system    pod/kube-proxy-fjmft                    1/1     Running   0          22s
kube-system    pod/kube-proxy-w2x8c                    1/1     Running   0          46s
kube-system    pod/kube-scheduler-k8s-node1            1/1     Running   11         30m

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

NAMESPACE      NAME                             DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-flannel   daemonset.apps/kube-flannel-ds   4         4         4       4            4           <none>                   24m
kube-system    daemonset.apps/kube-proxy        4         4         4       4            4           kubernetes.io/os=linux   30m

NAMESPACE     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   deployment.apps/coredns   2/2     2            2           30m

NAMESPACE     NAME                                 DESIRED   CURRENT   READY   AGE
kube-system   replicaset.apps/coredns-5dd5756b68   2         2         2       30m

Minecraft Server のデプロイまで、道程はまだまだ長い。

コメント

コメントする

目次