Home Deploying Minecraft Server on Kubernetes with ArgoCD
Post
Cancel

Deploying Minecraft Server on Kubernetes with ArgoCD

Introduction

This post outlines the process of deploying a Minecraft server on a Kubernetes cluster, managed through GitOps principles using ArgoCD. This setup ensures that your Minecraft server infrastructure is declarative, version-controlled, and easily reproducible.

Project Overview

The minecraft project demonstrates a robust and resilient approach to hosting a single Minecraft server, featuring:

  • Minecraft Server: Running the popular game server within a Kubernetes pod.
  • Kubernetes: Orchestrating the deployment, scaling, and management of the server.
  • ArgoCD: Implementing GitOps by continuously synchronizing the desired state defined in Git repositories with the live state of the Kubernetes cluster.
  • Persistent Storage: Ensuring game world data persists across restarts and upgrades.

Architecture and Components

The deployment consists of several key Kubernetes resources, all defined as YAML manifests and managed through ArgoCD:

1. Namespace

A dedicated minecraft namespace is created to logically isolate the application’s resources within the Kubernetes cluster.

1
2
3
4
5
6
apiVersion: v1
kind: Namespace
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "0"
  name: minecraft

2. Services

Two NodePort services are defined to expose the Minecraft game port and the RCON (Remote Console) port for management.

Minecraft Service

Exposes the standard Minecraft port (25565) as a NodePort.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Service
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "0"
  name: minecraft-service
  namespace: minecraft
spec:
  type: NodePort
  selector:
    app: minecraft
  ports:
    - protocol: TCP
      port: 25565
      targetPort: 25565
      nodePort: 32565

RCON Service

Exposes the RCON port (25575) for remote administration of the Minecraft server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Service
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "0"
  name: rcon-service
  namespace: minecraft
spec:
  type: NodePort
  selector:
    app: minecraft
  ports:
    - protocol: TCP
      port: 25575      # Changed from 27015
      targetPort: 25575 
      nodePort: 32575   # Changed from 32015 for consistency
RCON (Remote Console) is a protocol that allows server administrators to remotely execute commands on the Minecraft server. With the `rcon-service` configured as a `NodePort`, you can connect to your Minecraft server's RCON port (e.g., `NodeIP:32015`) using any RCON client or programmatically to manage the server, execute commands, broadcast messages, and more, without needing to be directly in the game or on the server's console. This is crucial for automation and remote administration.

3. Minecraft StatefulSet

To provide resilience and ensure persistent storage is correctly managed for our stateful Minecraft server, we deploy it as a Kubernetes StatefulSet. A StatefulSet is ideal for applications that require stable, unique network identifiers, stable persistent storage, and ordered, graceful deployment/scaling.

Key changes from a standard Deployment include:

  • kind: StatefulSet: Designates it as a StatefulSet.
  • serviceName: minecraft-service: Associates the StatefulSet with a Headless Service (which minecraft-service implicitly acts as for stable network identities).
  • nodeSelector removal: The pod is no longer pinned to a specific worker node, allowing Kubernetes to reschedule it on any healthy node if the current node fails.
  • volumeClaimTemplates: Instead of a standalone PersistentVolumeClaim, the storage is now dynamically provisioned and managed by the StatefulSet itself. This ensures that the persistent volume for the Minecraft world is automatically created and re-attached on failover. The accessModes is set to ReadWriteMany (RWX), indicating the underlying storage supports multiple readers/writers; however, it’s crucial to remember that the Minecraft server itself can only safely have one writer to the world data at a time to prevent corruption.

The Minecraft server uses the itzg/minecraft-server image, a flexible Docker image. Configurations include accepting the EULA, setting the server version and type (Paper recommended for performance), and allocating 1G of memory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: minecraft
  namespace: minecraft
  labels:
    app: minecraft
spec:
  replicas: 1
  selector:
    matchLabels:
      app: minecraft
  serviceName: minecraft-service # Important for StatefulSets
  template:
    metadata:
      labels:
        app: minecraft
    spec:
      # nodeSelector removed to allow scheduling on any available node
      containers:
      - name: minecraft
        image: itzg/minecraft-server:latest
        imagePullPolicy: Always
        ports:
        # Game Port
        - containerPort: 25565
          name: minecraft
          protocol: TCP
        
        # 🟢 RCON Port
        - containerPort: 25575
          name: rcon
          protocol: TCP
          
        env:
        # 1. Accept the License (Mandatory)
        - name: EULA
          value: "TRUE"
        # 2. Set the Version (Defaults to LATEST if removed)
        - name: VERSION
          value: "LATEST"
        # 3. Choose your flavor (VANILLA, PAPER, FORGE, FABRIC)
        # PAPER is highly recommended for performance!
        - name: TYPE
          value: "PAPER" 
        # 4. Set Memory Limits (Java loves RAM)
        - name: MEMORY
          value: "1G"
        - name: ENABLE_RCON # Explicitly enable RCON
          value: "true"
        - name: RCON_PASSWORD # Reference RCON password from a Kubernetes Secret
          valueFrom:
            secretKeyRef:
              name: minecraft-rcon-secret # Name of the Secret
              key: RCON_PASSWORD       # Key within the Secret
        volumeMounts:
        - name: data
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: data # This name must match the volumeMounts.name in the container spec
    spec:
      accessModes:
        - ReadWriteMany # Allows multiple pods to mount the volume simultaneously
      storageClassName: kubenfs  # <--- Your specific storage class
      resources:
        requests:
          storage: 10Gi # Adjust size as needed (10GB is plenty for a start)

Note on RCON_PASSWORD: For security best practices, the RCON_PASSWORD should be stored in a Kubernetes Secret rather than hardcoded in the manifest. You would create this secret using a command similar to the following:

1
kubectl create secret generic minecraft-rcon-secret --from-literal=RCON_PASSWORD='your-strong-password' -n minecraft

Remember to replace 'your-strong-password' with an actual strong, unique password.

5. GitOps with ArgoCD

The entire application configuration is stored in a Git repository. ArgoCD is configured to continuously monitor this repository and automatically synchronize the desired state with the Kubernetes cluster. The basic-application.yaml defines how ArgoCD points to the Minecraft server’s manifest.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: minecraft
  namespace: argocd
spec:
  project: default
  source:
    repoURL: git@github.com:<your-username>/minecraft.git
    targetRevision: HEAD
    path: gitops/basic
  destination:
    server: https://kubernetes.default.svc
    namespace: minecraft
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

Conclusion

This setup provides a robust and manageable Minecraft server on Kubernetes. By leveraging a StatefulSet, removing the nodeSelector, and utilizing persistent storage, your game worlds are safe and the server instance benefits from automatic rescheduling and re-attachment of its persistent data, significantly improving its resilience. The entire deployment is managed through GitOps with ArgoCD for declarative infrastructure management.

This post is licensed under CC BY 4.0 by the author.