2019-07-07 18:56:21 +02:00
[![GitHub issues ](https://img.shields.io/github/issues/itzg/mc-router.svg )](https://github.com/itzg/mc-router/issues)
[![Docker Pulls ](https://img.shields.io/docker/pulls/itzg/mc-router.svg )](https://cloud.docker.com/u/itzg/repository/docker/itzg/mc-router)
2021-11-14 20:23:42 +01:00
[![test ](https://github.com/itzg/mc-router/actions/workflows/test.yml/badge.svg )](https://github.com/itzg/mc-router/actions/workflows/test.yml)
2019-07-07 18:56:21 +02:00
[![GitHub release ](https://img.shields.io/github/release/itzg/mc-router.svg )](https://github.com/itzg/mc-router/releases)
2021-11-14 20:23:42 +01:00
[![Discord ](https://img.shields.io/discord/660567679458869252?label=discord )](https://discord.gg/JK2v3rJ9ec)
2019-07-07 18:56:21 +02:00
[![Buy me a coffee ](https://img.shields.io/badge/Donate-Buy%20me%20a%20coffee-orange.svg )](https://www.buymeacoffee.com/itzg)
2018-05-08 05:16:01 +02:00
Routes Minecraft client connections to backend servers based upon the requested server address.
2019-07-27 18:36:16 +02:00
# Usage
2018-05-08 05:16:01 +02:00
```text
2020-01-04 21:22:01 +01:00
-api-binding host:port
The host:port bound for servicing API requests (env API_BINDING)
2022-01-07 00:41:10 +01:00
-auto-scale-up
Increase Kubernetes StatefulSet Replicas (only) from 0 to 1 on respective backend servers when accessed (env AUTO_SCALE_UP)
2020-01-04 21:22:01 +01:00
-connection-rate-limit int
Max number of connections to allow per second (env CONNECTION_RATE_LIMIT) (default 1)
-cpu-profile string
Enables CPU profiling and writes to given path (env CPU_PROFILE)
-debug
Enable debug logs (env DEBUG)
-in-kube-cluster
2022-01-07 00:41:10 +01:00
Use in-cluster Kubernetes config (env IN_KUBE_CLUSTER)
2020-01-04 21:22:01 +01:00
-kube-config string
2022-01-07 00:41:10 +01:00
The path to a Kubernetes configuration file (env KUBE_CONFIG)
2020-01-04 21:22:01 +01:00
-mapping string
Comma-separated mappings of externalHostname=host:port (env MAPPING)
-metrics-backend string
Backend to use for metrics exposure/publishing: discard,expvar,influxdb (env METRICS_BACKEND) (default "discard")
-metrics-backend-config-influxdb-addr string
(env METRICS_BACKEND_CONFIG_INFLUXDB_ADDR)
-metrics-backend-config-influxdb-database string
(env METRICS_BACKEND_CONFIG_INFLUXDB_DATABASE)
-metrics-backend-config-influxdb-interval duration
(env METRICS_BACKEND_CONFIG_INFLUXDB_INTERVAL) (default 1m0s)
-metrics-backend-config-influxdb-password string
(env METRICS_BACKEND_CONFIG_INFLUXDB_PASSWORD)
-metrics-backend-config-influxdb-retention-policy string
(env METRICS_BACKEND_CONFIG_INFLUXDB_RETENTION_POLICY)
-metrics-backend-config-influxdb-tags value
any extra tags to be included with all reported metrics (env METRICS_BACKEND_CONFIG_INFLUXDB_TAGS)
-metrics-backend-config-influxdb-username string
(env METRICS_BACKEND_CONFIG_INFLUXDB_USERNAME)
-port port
The port bound to listen for Minecraft client connections (env PORT) (default 25565)
-version
Output version and exit (env VERSION)
2018-05-08 05:16:01 +02:00
```
2019-07-27 18:36:16 +02:00
# REST API
2018-05-08 05:16:01 +02:00
2021-08-10 23:53:51 +02:00
* `GET /routes` (with `Accept: application/json` )
2018-05-08 05:16:01 +02:00
Retrieves the currently configured routes
2021-08-10 23:53:51 +02:00
* `POST /routes` (with `Content-Type: application/json` )
Registers a route given a JSON body structured like:
```json
{
"serverAddress": "CLIENT REQUESTED SERVER ADDRESS",
"backend": "HOST:PORT"
}
```
2022-01-07 00:41:10 +01:00
2021-08-10 23:53:51 +02:00
* `POST /defaultRoute` (with `Content-Type: application/json` )
2022-01-07 00:41:10 +01:00
2019-04-20 03:27:14 +02:00
Registers a default route to the given backend. JSON body is structured as:
2021-08-10 23:53:51 +02:00
```json
{
"backend": "HOST:PORT"
}
```
2018-05-08 05:16:01 +02:00
* `DELETE /routes/{serverAddress}`
2021-08-10 23:53:51 +02:00
2018-05-25 03:19:14 +02:00
Deletes an existing route for the given `serverAddress`
2022-01-07 00:41:10 +01:00
2020-12-29 17:50:43 +01:00
# Docker Multi-Architecture Image
The [multi-architecture image published at Docker Hub ](https://hub.docker.com/repository/docker/itzg/mc-router ) supports amd64, arm64, and arm32v6 (i.e. RaspberryPi).
2019-07-27 18:36:16 +02:00
# Docker Compose Usage
The following diagram shows how [the example docker-compose.yml ](docs/docker-compose.yml )
configures two Minecraft server services named `vanilla` and `forge` , which also become the internal
network aliases. _Notice those services don't need their ports exposed since the internal
networking allows for the inter-container access._
2022-01-07 00:41:10 +01:00
The `router` service is only one of the services that needs to exposed on the external
2019-07-27 18:36:16 +02:00
network. The `--mapping` declares how the hostname users will enter into their Minecraft client
will map to the internal services.
![](docs/compose-diagram.png)
2022-01-07 00:41:10 +01:00
2019-07-27 18:36:16 +02:00
To test out this example, I added these two entries to my "hosts" file:
```
127.0.0.1 vanilla.example.com
127.0.0.1 forge.example.com
```
2022-01-07 00:41:10 +01:00
2019-07-27 18:36:16 +02:00
# Kubernetes Usage
2022-01-07 00:41:10 +01:00
## Using Kubernetes Service auto-discovery
2018-05-27 21:53:22 +02:00
2022-01-07 00:41:10 +01:00
When running `mc-router` as a Kubernetes Pod and you pass the `--in-kube-cluster` command-line argument, then
it will automatically watch for any services annotated with
2019-04-20 03:27:14 +02:00
- `mc-router.itzg.me/externalServerName` : The value of the annotation will be registered as the external hostname Minecraft clients would used to connect to the
2021-12-04 16:25:28 +01:00
routed service. The service's clusterIP and target port are used as the routed backend. You can use more hostnames by splitting them with comma.
2019-04-20 03:27:14 +02:00
- `mc-router.itzg.me/defaultServer` : The service's clusterIP and target port are used as the default if
no other `externalServiceName` annotations applies.
2018-05-27 21:53:22 +02:00
For example, start `mc-router` 's container spec with
```yaml
image: itzg/mc-router
name: mc-router
args: ["--in-kube-cluster"]
```
and configure the backend minecraft server's service with the annotation:
```yaml
apiVersion: v1
kind: Service
metadata:
name: mc-forge
annotations:
"mc-router.itzg.me/externalServerName": "external.host.name"
```
2021-12-04 16:25:28 +01:00
you can use multiple host names:
```yaml
apiVersion: v1
kind: Service
metadata:
name: mc-forge
annotations:
"mc-router.itzg.me/externalServerName": "external.host.name,other.host.name"
```
2022-01-07 00:41:10 +01:00
## Example Kubernetes deployment
2018-05-25 03:19:14 +02:00
2022-01-07 00:41:10 +01:00
[This example deployment ](docs/k8s-example-auto.yaml )
2018-05-26 21:03:04 +02:00
* 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
2022-01-07 00:41:10 +01:00
* Two "backend" Minecraft servers are declared each with an
2021-12-04 16:25:28 +01:00
`"mc-router.itzg.me/externalServerName"` annotation that declares their external server name(s)
2018-05-25 03:19:14 +02:00
```bash
2018-05-26 21:03:04 +02:00
kubectl apply -f https://raw.githubusercontent.com/itzg/mc-router/master/docs/k8s-example-auto.yaml
2018-05-25 03:19:14 +02:00
```
2018-05-26 21:03:04 +02:00
![](docs/example-deployment-auto.drawio.png)
2018-05-25 03:19:14 +02:00
2018-05-25 03:26:33 +02:00
#### Notes
* This deployment assumes two persistent volume claims: `mc-stable` and `mc-snapshot`
2022-01-07 00:41:10 +01:00
* 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
The `-auto-scale-up` flag argument makes the router "wake up" any stopped backend servers, by changing `replicas: 0` to `replicas: 1` .
This requires using `kind: StatefulSet` instead of `kind: Service` for the Minecraft backend servers.
It also requires 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"]
```
2019-07-15 00:02:12 +02:00
# Development
## Building locally with Docker
```bash
2021-12-05 01:31:18 +01:00
docker build -t mc-router .
2019-07-15 00:02:12 +02:00
```
2022-01-07 00:41:10 +01:00
## Build locally without Docker
After [installing Go ](https://go.dev/doc/install ) and doing a `go mod download` to install all required prerequisites, just like the [Dockerfile ](Dockerfile ) does, you can:
```bash
make test # go test -v ./...
go build ./cmd/mc-router/
```
2021-11-20 19:16:56 +01:00
## Skaffold
For "in-cluster development" it's convenient to use https://skaffold.dev. Any changes to Go source code
will trigger a go build, new container image pushed to registry with a new tag, and refresh in Kubernetes
2022-01-07 00:41:10 +01:00
with the image tag used in the deployment transparently updated to the new tag and thus new pod created pulling new images,
as configured by [skaffold.yaml ](skaffold.yaml ):
2021-11-20 19:16:56 +01:00
skaffold dev
When using Google Cloud (GCP), first create a _Docker Artifact Registry_ ,
2022-01-07 00:41:10 +01:00
then add the _Artifact Registry Reader_ Role to the _Compute Engine default service account_ of your _GKE `clusterService` Account_ (to avoid error like "container mc-router is waiting to start: ...-docker.pkg.dev/... can't be pulled"),
2021-11-20 19:16:56 +01:00
then use e.g. `gcloud auth configure-docker europe-docker.pkg.dev` or equivalent one time (to create a `~/.docker/config.json` ),
and then use e.g. `--default-repo=europe-docker.pkg.dev/YOUR-PROJECT/YOUR-ARTIFACT-REGISTRY` option for `skaffold dev` .
2019-07-15 00:02:12 +02:00
## Performing snapshot release with Docker
```bash
docker run -it --rm \
-v ${PWD}:/build -w /build \
-v /var/run/docker.sock:/var/run/docker.sock \
goreleaser/goreleaser \
release --snapshot --rm-dist
2020-12-29 17:50:43 +01:00
```
2021-11-08 15:44:07 +01:00
# Related Projects
* https://github.com/haveachin/infrared