nick.breen.kiwi

I’ve had two itzg/minecraft-bedrock-server containers running on a single node using docker-compose for a while now, but I wanted to move them to microk8s.

I wanted to have them announce themselves to the LAN so that the consoles could see them. This requires them to have a MACVLAN interface on the host’s network.

This was “easy” to do with docker, I had a systemd service that also created the “magic” MACVLAN network and the compose file attached the containers to it.

These are not complete files, only the relevant parts.

# /etc/systemd/system/docker-compose-minecraft.service
[Service]
ExecStartPre=-/snap/bin/docker network create -d macvlan -o parent=enp4s0 --subnet 192.168.1.0/24 --ip-range 192.168.1.128/27 --gateway 192.168.1.1 magic
ExecStart=/snap/bin/docker compose up --abort-on-container-exit
# docker-compose.yaml
networks:
  magic:
    external: true

services:
  minecraft:
    image: itzg/minecraft-bedrock-server
    networks:
      - magic

Converting this to kubernetes was not as straightforward as I had hoped. Mainly because working out what the magic JSON CNI configuration is was not obvious. I had to read the Multus CNI documentation and the MACVLAN CNI documentation. Still, only needed an arbitrary example to fill in the gaps.

Helpfully, there is also a helm chart for itzg/minecraft-bedrock-server, so I didn’t have to write a deployment myself. So, exploiting helm’s sub-chart dependency mechanism, I created a custom chart that creates the MACVLAN and assigns it to the minecraft server(s).

# Chart.yaml
apiVersion: v2
name: Minecraft
description: Minecraft
type: application
version: 0.0.0
appVersion: "0.0"
dependencies:
  - name: minecraft-bedrock
    version: 2.8.4
    repository: https://itzg.github.io/minecraft-server-charts/
# values.yaml
minecraft-bedrock:
   podAnnotations:
      k8s.v1.cni.cncf.io/networks: macvlan
# templates/macvlan.yaml
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
   name: macvlan
spec:
   config: |
      {
         "cniVersion": "0.3.1",
         "plugins": [
            {
               "cniVersion": "0.3.1",
               "type": "macvlan",
               "master": "enp4s0",
               "mode": "bridge",
               "ipam": {
                  "type": "host-local",
                  "ranges": [
                     [
                        {
                           "subnet": "192.168.1.0/24",
                           "gateway": "192.168.1.1",
                           "rangeStart": "192.168.1.129",
                           "rangeEnd": "192.168.1.159"
                        }
                     ]
                  ]
               }
            }
         ]
      }

Assuming one has already microk8s enable multus, the above files can be used to create a helm chart that will create the MACVLAN network and deploy the minecraft server(s) to it. I suspect that master and mode are redundant.

Crucially, the Multus CNI configuration wraps the actual CNI MACVLAN plugin configuration.

Every example I found online used the MACVLAN CNI configuration (without the Multus wrapper) and also specified the routes and dns options. When spefifying the routes option all traffic fails inside the pod. Apparently because it is the same subnet as the host’s network and routing is confused.