How to: Example Kubernetes deployment
[This example deployment](docs/k8s-example-auto.yaml)
* Declares an `mc-router` service that exposes a node port 25565
* Declares a service account with access to watch and list services
* Declares `--in-kube-cluster` in the `mc-router` container arguments
* Two "backend" Minecraft servers are declared each with an
  `"mc-router.itzg.me/externalServerName"` annotation that declares their external server name(s)

```bash
kubectl apply -f https://raw.githubusercontent.com/itzg/mc-router/main/docs/k8s-example-auto.yaml
```

![](docs/example-deployment-auto.drawio.png)

##### Notes
* This deployment assumes two persistent volume claims: `mc-stable` and `mc-snapshot`
* I extended the allowed node port range by adding `--service-node-port-range=25000-32767`
  to `/etc/kubernetes/manifests/kube-apiserver.yaml`

##### Auto Scale Up/Down

The `-auto-scale-up` flag argument makes the router "wake up" any stopped backend servers by changing `replicas: 0` to `replicas: 1`. The `-auto-scale-down` flag argument makes the router shut down any running backend servers with no active connections by changing `replicas: 1` to `replicas: 0`. The scale down will occur after a configurable (using the `-auto-scale-down-after` argument) waiting period, such as `10m` (10 minutes), `2h` (2 hours), etc. If any players connect to the server during this period the scale down will be canceled. It is recommended to set this value high enough so a temporary player disconnect will not immediately shut down the server (`1m` or higher).

Both options require using `kind: StatefulSet` instead of `kind: Service` for the Minecraft backend servers.

They also require the `ClusterRole` to permit `get` + `update` for `statefulsets` & `statefulsets/scale`,
e.g. like this (or some equivalent more fine-grained one to only watch/list services+statefulsets, and only get+update scale):

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: services-watcher
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["watch","list"]
- apiGroups: ["apps"]
  resources: ["statefulsets", "statefulsets/scale"]
  verbs: ["watch","list","get","update"]
```

Make sure to set `StatefulSet.metadata.name` and `StatefulSet.spec.serviceName` to the same value;
otherwise, autoscaling will not trigger:

```yaml
apiVersion: v1
kind: Service
metadata:
  name: mc-forge
  annotations:
    "mc-router.itzg.me/defaultServer": "true"
    "mc-router.itzg.me/externalServerName": "external.host.name"
spec:
  type: ClusterIP
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mc-forge
spec:
  serviceName: mc-forge
  selector:
    matchLabels:
      app: mc-forge
  template:
    metadata:
      labels:
        app: mc-forge
    spec:
      containers:
        - name: mc
```

You can also opt-out of auto-scaling per server by setting the following annotations on the `Service` object:
- `mc-router.itzg.me/autoScaleUp=false`
- `mc-router.itzg.me/autoScaleDown=false`

Example server with auto-scaling disabled explicitly:
```yaml
apiVersion: v1
kind: Service
metadata:
  name: mc-forge
  annotations:
    "mc-router.itzg.me/externalServerName": "external.host.name"
    "mc-router.itzg.me/autoScaleUp": "false"
    "mc-router.itzg.me/autoScaleDown": "false"
```