I probably spent one too many hours of my teenage years playing the pocket edition of Minecraft. If you are reading this, chances are, you like Minecraft or Kubernetes, or perhaps you’re like me and like both. In this tutorial, we’ll explore how to set up and expose a Minecraft server in Kubernetes.

Prerequisites

This tutorial assumes some familiarity with Kubernetes. In addition, you would need the following installed to follow along:

Preparing the Kubernetes cluster

We’ll begin by creating a Kubernetes cluster, feel free to skip this step if you have a cluster created already.

For simplicity, we will be doing it from the CLI:

civo k3s create --create-firewall --nodes 2 -m --save --switch --wait mc-k8s

This would launch a two-node cluster, and this would also point your kube-context to the cluster we just launched.

Creating a Deployment

To deploy the Minecraft server within our cluster, we would be creating a Deployment as well as a PersistentVolumeClaim. This would ensure we have stable persistent storage, which is essential for storing world data.

For the Image, we’ll be using docker-minecraft-bedrock-server by Geoff Bourne. In a directory of your choosing, create a file called server.yaml and add the following code:

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: minecraft-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: civo-mc-bedrock 
  labels:
    app: civo-mc-bedrock
spec:
  replicas: 1
  selector:
    matchLabels:
      app: civo-mc-bedrock
  template:
    metadata:
      labels:
        app: civo-mc-bedrock
    spec:
      containers:
      - name: civo-mc-bedrock
        image: itzg/minecraft-bedrock-server
        imagePullPolicy: Always
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
        env:
        - name: EULA
          value: "TRUE"
        volumeMounts:
        - name: data
          mountPath: /data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: minecraft-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: civo-mc-bedrock
  labels:
    app: civo-mc-bedrock
spec:
  selector:
    app: civo-mc-bedrock
  ports:
    - port: 19132
      protocol: UDP
    

There’s quite a bit of configuration going on in the file above. Here are the important parts:

  • We set replicas to 1 since we only need a single Minecraft server.
  • The PersistentVolumeClaim provides 1Gi of storage for world data.
  • The container mounts this storage to /data inside the container.
  • We also specify the protocol of the service as UDP
⚠️ This will create a load balancer in your Kubernetes cluster

Apply the configuration using Kubectl:

kubectl apply -f server.yaml

To retrieve the external IP of the service, you can use the following command:

kubectl get svc civo-mc-server -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

Connecting to the Server

For this demonstration I would be using the pocket edition of Minecraft, but the process is generally the same across devices.

Launch Minecraft, and click on the server tab ↓

Connecting to the Minecraft Server Part 1

Click on add server

Connecting to the Minecraft Server Part 2

Add the IP of the load balancer you copied earlier and click play. If all goes well, you should be logged in to your server ↓

Connecting to the Minecraft Server Part 3

Things to consider when deploying a Minecraft Server

While this guide focuses on the Bedrock Edition setup, it's important to note that memory management is crucial for smooth performance in Minecraft servers, especially the Java Edition.

Java Edition servers require careful consideration of memory allocation. As your world size increases and you accommodate more players, memory demands growth. Allocate too little, and you'll face performance issues and crashes. Start with a reasonable amount, monitor memory usage, and scale up as needed for optimal server health.

Persistent storage volumes are highly recommended for preserving world data, whether using a cloud platform or physical hardware. Without persistent storage, world data is lost when the server container or virtual machine is restarted or replaced. Leverage persistent volumes to maintain state and prevent loss of often hundreds of hours of collaborative player progress.

Closely watch memory usage even after launch, as mods, expansions, and growth in your player-base will necessitate additional memory. Performance monitoring and auto-scaling tools can remove some server management headaches. Prepare to scale your server up or out as needed to maintain good performance

Summary

In this tutorial, we discussed how to deploy a Minecraft server on Kubernetes as well as some things to consider when deploying one.

A big shout out to Geoff Bourne once more, a lot of this was made easier because of him. If you’re looking to monitor your Minecraft server, consider checking out mc-monitor, it provides a Prometheus exporter, which is useful for collecting metrics and visualization.