MENU
カテゴリー
アーカイブ

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

目次

バージョン確認

ここまでに使用した主なアプリのバージョンを整理してみる。

Ubuntu Server(VM) : 22.04.3

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 22.04.3 LTS
Release:	22.04
Codename:	jammy
Kubernetes : 1.28.3

$ kubectl version
Client Version: v1.28.3
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.3
CRI-O(CRI:Container Runtime Interface) : 1.28.1-0

$ sudo apt-show-versions cri-o
cri-o:amd64/unknown 1.28.1~0 uptodate
cri-o:arm64 not installed
cri-o:armhf not installed
cri-o:s390x not installed
Flannel(CNI:Container Network Interface) : 0.23.0
Flannel plugin : 1.2.0

$ kubectl get pods -n kube-flannel | grep flannel
kube-flannel-ds-97gjk   1/1     Running   0          9m9s
kube-flannel-ds-j8kt9   1/1     Running   0          9m40s
kube-flannel-ds-q88kf   1/1     Running   0          9m19s
kube-flannel-ds-wmb87   1/1     Running   0          9m30s

$ kubectl describe pod kube-flannel-ds-97gjk -n kube-flannel | grep Image
    Image:         docker.io/flannel/flannel-cni-plugin:v1.2.0
    Image ID:      a55d1bad692b776e7c632739dfbeffab2984ef399e1fa633e0751b1662ea8bb4
    Image:         docker.io/flannel/flannel:v0.23.0
    Image ID:      01cdfa8dd262f793cedbb1561d574a180c0fe09e795ca641445566ca32840830
    Image:         docker.io/flannel/flannel:v0.23.0
    Image ID:      01cdfa8dd262f793cedbb1561d574a180c0fe09e795ca641445566ca32840830
MetalLB(load balancers) : 0.13.12 ※指定してインストール

$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml
Helm : 3.13.1

$ helm version
version.BuildInfo{Version:"v3.13.1", GitCommit:"3547a4b5bf5edb5478ce352e18858d8a552a4110", GitTreeState:"clean", GoVersion:"go1.20.8"}
kubernetes-dashboard : 6.0.8 ※ダッシュボード画面から確認
NFS CSI Driver(Provisioner) : 4.4.0 ※指定してインストール

helm install csi-driver-nfs csi-driver-nfs/csi-driver-nfs --namespace kube-system --version v4.4.0
itzg/minecraft-server : 2023.10.1 ※github.comより

https://github.com/itzg/docker-minecraft-server

マニフェストを作る

いよいよ Minecraft をデプロイする。
何はともあれマニフェストを用意する。既に多くの人たちが作っているものを活用させてもらおう。
次のサイトがわかり易かった。

使用するイメージは定番?の itzg/minecraft-server
頻繁にアップデートされている docker image で利用者も多い。

永続ボリューム用の pvc も pod に含めたもの。pv は先にデプロイ済みの nfs-pv-java.yaml を使用している。

サーバーの詳細設定は README.md を参照。

$ vi mc-java.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: minecraft
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: minecraft
  namespace: minecraft
spec:
  selector:
    matchLabels:
      app: minecraft
  template:
    metadata:
      labels:
        app: minecraft
    spec:
      volumes:
      - name: minecraft-volumes
        persistentVolumeClaim:
          claimName: nfs-pvc-java
      containers:
      - name: minecraft
        image: itzg/minecraft-server
        env:
        - name: EULA
          value: "TRUE"
        - name: OPS
          value: "user_name"   # OP権限持ちのユーザ名を記述。複数の場合は「,」で区切る。
        - name: WHITELIST
          value: "user_name"   # 接続可能ユーザ名を記述。複数の場合は「,」で区切る。
        - name: LEVEL
          value: "1.20.2"     # マイクラのバージョン。
        - name: MOTD
          value: "MC-Kuvernetes"  # マイクラのランチャーでサーバリストに表示するサーバの説明。
        - name: TZ
          value: "Asia/Tokyo"
        - name: SERVER_NAME
          value: "mc.jisaba.life"     # サーバのドメイン名。
        - name: MEMORY
          value: "4G"         # 割り当てるメモリ。resourcelimitと同じ値にしておくこと。
        - name: SPAWN_PROTECTION
          value: "0"
        - name: MODE
          value: "survival"    # World生成時のゲームモード。
        - name: DIFFICULTY
          value: "easy"        # World生成時の難易度。
#        - name: SEED
#          value: '3427891657823464'    # World生成時のseed値を指定する場合はコメントイン。
        resources:
          limits:
            memory: "4Gi"     # worker node内で割り当ててもらうメモリの上限。worker nodeに積んでる以上のメモリサイズは不可。
        ports:
        - containerPort: 25565 # コンテナ側で開けてるポートを明示。
        volumeMounts:
        - name: minecraft-volumes
          mountPath: "/data"
---
# 以下はロードバランサーを使用している場合。
apiVersion: v1
kind: Service
metadata:
  name: minecraft
  namespace: minecraft
  labels:
    app: minecraft
spec:
  type: LoadBalancer 
  ports:
    - name: minecraft-port
      port: 25565
      protocol: TCP
      targetPort: 25565
  selector:
    app: minecraft
---
# 以下は永続ボリュームを適用する場合。pvは作成済みとします。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc-java
  namespace: minecraft
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: ""
  resources:
    requests:
      storage: 5Gi
  volumeName: nfs-pv-java

デプロイする

kubectl apply -f mc-java.yaml でデプロイして確認する。

$ kubectl get pods --namespace=minecraft
NAME                         READY   STATUS    RESTARTS   AGE
minecraft-5d4d97bcd4-m76jv   1/1     Running   0          6m36s

詳細はこんな感じ。
お一人さま用の自鯖だから namespace も default で良いとは思いつつ、マイクラ用に分けている。

$ kubectl get pods --namespace=minecraft
NAME                         READY   STATUS    RESTARTS   AGE
minecraft-5fd8ccd9bf-7lxvm   1/1     Running   0          17m

$ kubectl -n minecraft describe pod minecraft-5fd8ccd9bf-7lxvm
Name:             minecraft-5fd8ccd9bf-7lxvm
Namespace:        minecraft
Priority:         0
Service Account:  default
Node:             k8s-node4/10.1.1.6
Start Time:       Sat, 04 Nov 2023 11:09:45 +0900
Labels:           app=minecraft
                  pod-template-hash=5fd8ccd9bf
Annotations:      <none>
Status:           Running
IP:               10.244.1.13
IPs:
  IP:           10.244.1.13
Controlled By:  ReplicaSet/minecraft-5fd8ccd9bf
Containers:
  minecraft:
    Container ID:   cri-o://71d73cc60f52692a30a21e2578e21caa5783c7595eb7243f711f33d19f1f9d91
    Image:          itzg/minecraft-server
    Image ID:       f73dab1b631c716f0e7d464bd54518123455ecd0edd7789fad057831fdf4e0c6
    Port:           25565/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sat, 04 Nov 2023 11:09:48 +0900
    Ready:          True
    Restart Count:  0
    Limits:
      memory:  4Gi
    Requests:
      memory:  4Gi
    Environment:
      EULA:              TRUE
      OPS:               user_name
      LEVEL:             1.20.2
      MOTD:              MC-Kuvernetes
      TZ:                Asia/Tokyo
      SERVER_NAME:       mc.jisaba.life
      MEMORY:            4G
      SPAWN_PROTECTION:  0
      MODE:              survival
      DIFFICULTY:        easy
    Mounts:
      /data from minecraft-volumes (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-7xsng (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  minecraft-volumes:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  nfs-pvc-java
    ReadOnly:   false
  kube-api-access-7xsng:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  18m   default-scheduler  Successfully assigned minecraft/minecraft-5fd8ccd9bf-7lxvm to k8s-node4
  Normal  Pulling    18m   kubelet            Pulling image "itzg/minecraft-server"
  Normal  Pulled     18m   kubelet            Successfully pulled image "itzg/minecraft-server" in 2.067s (2.067s including waiting)
  Normal  Created    18m   kubelet            Created container minecraft
  Normal  Started    18m   kubelet            Started container minecraft

クラスター外から接続するための service/minecraft のアドレスを固定するのを忘れてた。
service に loadBalancerIP: 10.1.11.11 を追加する。

〜〜〜(省略)〜〜〜
---
apiVersion: v1
kind: Service
metadata:
  name: minecraft
  namespace: minecraft
  labels:
    app: minecraft
spec:
  type: LoadBalancer
  loadBalancerIP: 10.1.11.11    # IPアドレスの固定化
  ports:
    - name: minecraft-port
      port: 25565
      protocol: TCP
      targetPort: 25565
  selector:
    app: minecraft
---
〜〜〜(省略)〜〜〜

現時点の最終的なクラスターの様子は次の通り。

$ kubectl get all -A
NAMESPACE              NAME                                        READY   STATUS        RESTARTS        AGE
kube-flannel           pod/kube-flannel-ds-gz2hk                   1/1     Running       2               6d18h
kube-flannel           pod/kube-flannel-ds-hg2jv                   1/1     Running       2               6d18h
kube-flannel           pod/kube-flannel-ds-pcv8v                   1/1     Running       1               6d18h
kube-flannel           pod/kube-flannel-ds-vb5gr                   1/1     Running       9               6d18h
kube-system            pod/coredns-5dd5756b68-67dvx                1/1     Running       9               6d19h
kube-system            pod/coredns-5dd5756b68-qtd4k                1/1     Running       9               6d19h
kube-system            pod/csi-nfs-controller-c544c88c-k5hdt       4/4     Running       6 (141m ago)    12h
kube-system            pod/csi-nfs-node-cvvfx                      3/3     Running       0               12h
kube-system            pod/csi-nfs-node-tv7sc                      3/3     Running       0               12h
kube-system            pod/csi-nfs-node-x6shz                      3/3     Running       0               12h
kube-system            pod/csi-nfs-node-xzqjm                      3/3     Running       3               12h
kube-system            pod/etcd-k8s-node1                          1/1     Running       14              6d19h
kube-system            pod/kube-apiserver-k8s-node1                1/1     Running       13              6d19h
kube-system            pod/kube-controller-manager-k8s-node1       1/1     Running       35              6d19h
kube-system            pod/kube-proxy-2vhl6                        1/1     Running       2               6d18h
kube-system            pod/kube-proxy-ddnxk                        1/1     Running       9               6d19h
kube-system            pod/kube-proxy-fjmft                        1/1     Running       1               6d18h
kube-system            pod/kube-proxy-w2x8c                        1/1     Running       1               6d18h
kube-system            pod/kube-scheduler-k8s-node1                1/1     Running       36              6d19h
kube-system            pod/snapshot-controller-6597bcc578-2tw98    1/1     Running       5 (140m ago)    12h
kubernetes-dashboard   pod/kubernetes-dashboard-798dd48467-bssc9   1/1     Running       9 (140m ago)    6d2h
metallb-system         pod/controller-786f9df989-7fm7n             1/1     Running       0               16h
metallb-system         pod/speaker-568dn                           1/1     Running       16 (140m ago)   6d18h
metallb-system         pod/speaker-5h8rf                           1/1     Running       4 (15h ago)     6d18h
metallb-system         pod/speaker-vxr4n                           1/1     Running       2 (2d15h ago)   6d18h
metallb-system         pod/speaker-wqpkz                           1/1     Running       2 (2d15h ago)   6d18h
minecraft              pod/minecraft-5fd8ccd9bf-7lxvm              1/1     Terminating   0               73m
minecraft              pod/minecraft-6b854f7d5c-hc264              1/1     Running       0               4s

NAMESPACE              NAME                           TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
default                service/kubernetes             ClusterIP      10.96.0.1        <none>        443/TCP                  6d19h
kube-system            service/kube-dns               ClusterIP      10.96.0.10       <none>        53/UDP,53/TCP,9153/TCP   6d19h
kubernetes-dashboard   service/kubernetes-dashboard   ClusterIP      10.96.253.32     <none>        443/TCP                  6d2h
metallb-system         service/webhook-service        ClusterIP      10.106.140.148   <none>        443/TCP                  6d18h
minecraft              service/minecraft              LoadBalancer   10.107.254.76    10.1.11.11    25565:32739/TCP          93m

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>                   6d18h
kube-system      daemonset.apps/csi-nfs-node      4         4         4       4            4           kubernetes.io/os=linux   12h
kube-system      daemonset.apps/kube-proxy        4         4         4       4            4           kubernetes.io/os=linux   6d19h
metallb-system   daemonset.apps/speaker           4         4         4       4            4           kubernetes.io/os=linux   6d18h

NAMESPACE              NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
kube-system            deployment.apps/coredns                2/2     2            2           6d19h
kube-system            deployment.apps/csi-nfs-controller     1/1     1            1           12h
kube-system            deployment.apps/snapshot-controller    1/1     1            1           12h
kubernetes-dashboard   deployment.apps/kubernetes-dashboard   1/1     1            1           6d2h
metallb-system         deployment.apps/controller             1/1     1            1           6d18h
minecraft              deployment.apps/minecraft              1/1     1            1           93m

NAMESPACE              NAME                                              DESIRED   CURRENT   READY   AGE
kube-system            replicaset.apps/coredns-5dd5756b68                2         2         2       6d19h
kube-system            replicaset.apps/csi-nfs-controller-c544c88c       1         1         1       12h
kube-system            replicaset.apps/snapshot-controller-6597bcc578    1         1         1       12h
kubernetes-dashboard   replicaset.apps/kubernetes-dashboard-798dd48467   1         1         1       6d2h
metallb-system         replicaset.apps/controller-786f9df989             1         1         1       6d18h
minecraft              replicaset.apps/minecraft-5fd8ccd9bf              0         0         0       73m
minecraft              replicaset.apps/minecraft-668448c6ff              0         0         0       93m
minecraft              replicaset.apps/minecraft-6b854f7d5c              1         1         1       4s
minecraft              replicaset.apps/minecraft-7b4d9f849f              0         0         0       75m

Minecraft が動作している node が故障したとき

replicaset: 1(または未設定)の場合

mc-java.yaml に replicas: 1 を追加してデプロイ(kubectl apply -f mc-java.yaml)してから、ノード k8s-node5 を Proxmox VE 管理画面からシャットダウンする。もちろん ssh でノードにログインして shutdown でも同じ。

〜〜〜(省略)〜〜〜
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: minecraft
  namespace: minecraft
spec:
  replicas: 1    # これが無い、または1の場合
  selector:
    matchLabels:
      app: minecraft
  template:
    metadata:
      labels:
        app: minecraft
    spec:
〜〜〜(省略)〜〜〜

ノードの停止直後 $ kubectl get pods -o wide -n minecraft は変化が無い。でも実際には Minecraft のランチャーから接続できなくなっている(pod は落ちている)。

数分すると、次のよ���にシャットダウンしたノードの pod は Terminating になる。併せて別のノード(k8s-node4)に新しい pod が生えてくる。

$ kubectl get pods -o wide -n minecraft
NAME                         READY   STATUS        RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
minecraft-6b854f7d5c-tvnsh   1/1     Terminating   0          42m   10.244.2.21   k8s-node5   <none>           <none>
minecraft-6b854f7d5c-wpp4w   1/1     Running       0          45s   10.244.1.16   k8s-node4   <none>           <none>

改めて k8s-node5 を立ち上げると、

$ kubectl get pods -o wide -n minecraft
NAME                         READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
minecraft-6b854f7d5c-wpp4w   1/1     Running   0          4m18s   10.244.1.16   k8s-node4   <none>           <none>

このとおり、Terminating だった pod は解消されて、k8s-node4 の pod が引き続き動作する。

replicaset: 2 以上の場合

replicaset を2にすると、pod の一つは STATUS が CrashLoopBackOff となって、リスタートを繰り返す。

$ kubectl get pods -o wide -n minecraft
NAME                         READY   STATUS             RESTARTS      AGE     IP            NODE        NOMINATED NODE   READINESS GATES
minecraft-6b854f7d5c-hc264   1/1     Running            2             45m     10.244.2.19   k8s-node5   <none>           <none>
minecraft-6b854f7d5c-hpcvk   0/1     CrashLoopBackOff   6 (62s ago)   9m22s   10.244.1.14   k8s-node4   <none>           <none>

リスタートを繰り返す方の pod のログを見るとこんな感じ。

$ kubectl logs -n minecraft minecraft-6b854f7d5c-hpcvk
[init] Running as uid=1000 gid=1000 with /data as 'drwxrwxr-x 7 1000 1000 4096 Nov  4 10:49 /data'
[init] Resolving type given VANILLA
[init] Resolved version given LATEST into 1.20.2
[init] Enabling whitelist functionality
[init] Setting mode
[mc-image-helper] 13:40:11.265 INFO  : Created/updated 1 property in /data/server.properties
[mc-image-helper] 13:40:12.404 INFO  : The file ./ops.json already exists, so no changes will be made
[mc-image-helper] 13:40:13.570 INFO  : The file ./whitelist.json already exists, so no changes will be made
[init] Setting initial memory to 4G and max to 4G
[init] Starting the Minecraft server...
Starting net.minecraft.server.Main
[13:40:26] [ServerMain/INFO]: Environment: Environment[accountsHost=https://api.mojang.com, sessionHost=https://sessionserver.mojang.com, servicesHost=https://api.minecraftservices.com, name=PROD]
[13:40:26] [ServerMain/ERROR]: Failed to start the minecraft server
ard$a: /data/./1.20.2/session.lock: already locked (possibly by other Minecraft instance?)
	at ard$a.a(SourceFile:95) ~[server-1.20.2.jar:?]
	at ard.a(SourceFile:41) ~[server-1.20.2.jar:?]
	at ecg$c.<init>(SourceFile:419) ~[server-1.20.2.jar:?]
	at ecg.d(SourceFile:398) ~[server-1.20.2.jar:?]
	at net.minecraft.server.Main.main(SourceFile:133) ~[server-1.20.2.jar:?]
	at net.minecraft.bundler.Main.lambda$run$0(Main.java:54) ~[?:?]
	at java.lang.Thread.run(Unknown Source) ~[?:?]

/data/1.20.2/session.lock されているから2つ目が起動できないらしい。
これは、Minecraft の仕様で、最初にサーバーが起動されたときに session.lock ファイルが作られて、以降常に監視しているため。
/data 内を、中身は同じでも別の pod(minecraft) で共有しているから2つ目は起動できない。

(参考)https://minecraft.fandom.com/wiki/Java_Edition_level_format#session.lock_format

ただし、あくまでも永続ボリュームに異なる pod(replica)が同時アクセスする場合は注意が必要、という話。

外部からの接続

自宅の LAN 内ではなく、インターネットから接続のこと。
ここまでの設定で、Minecraft には 10.1.11.11 で接続できることを確認している。

あとは、ルーターのポート開放で、service/minecraft のアドレス(10.1.11.11)に向ければ外部からも接続できる。

終わりに

とりあえず Minecraft が遊べる状態にはなった。
以降はセキュリティアップデート(Image: itzg/minecraft-server の更新)や Kubernetes 関係のアップグレードを適宜、実行する。

慣れた人なら Kubernetes の環境構築から Minecraft のデプロイまで半日も要しないかな。

コメント

コメントする

目次