visit
Here's the scenario: You're organizing a full-day Minecraft class for local STEM students. You need to run your own Minecraft servers to ensure a kid-friendly multiplayer environment, restricted only to your students. One server won't be enough, so you'll run two servers simultaneously, expecting your load balancer to handle sending students to Server A or Server B, depending on the load.
In this article, we're going to explore port forwarding and load balancing with . We're going to do this by spinning up multiple Minecraft servers, and then placing Kong Gateway in front of these upstream services to handle port forwarding and load balancing.Before we dive in, let's briefly cover a few important technology concepts.Port Forwarding
Port forwarding is receiving network requests on a certain port of a machine and forwarding those requests to a different port. A router, firewall or API gateway usually handles this task. For example, you might have a web server listening on port 3000 and a database server listening on port 5000. Your API gateway would listen for requests from outside your network. Requests addressed to port 80 would be forwarded by the gateway to your web server at port 3000. Meanwhile, requests addressed to port 5432 would be forwarded to your database server at port 5000.Load Balancing
Load balancing is the task of distributing multiple requests to a server in a balanced manner across numerous replicas of that server. A specific piece of hardware or software called a load balancer usually handles this. The outside world is unaware that there are multiple replicas of a server running. They believe they’re making requests to a single server. The load balancer, however, distributes the request load to prevent any one server from being overwhelmed. In the case of a replica failing completely, the load balancer ensures that requests only go to healthy nodes.Kong Gateway
Kong Gateway is a thin API gateway layer that sits in front of upstream services, capable of performing these port forwarding and load balancing tasks. Whether those upstream services are web servers or databases or even Minecraft game servers, Kong is the front-door greeter to all requests. In addition to traffic control, Kong Gateway can manage , request transformations, analytics, and logging.TCP Stream Support
One aspect of our Minecraft project that sets it apart from deploying a typical web server or database is that Minecraft requires an established connection between the Minecraft client (the gamer) and server. Rather than expecting stateless HTTP requests, we'll need to handle TCP connections with streaming data. Fortunately, Kong Gateway fully supports TCP streaming.You don't actually need a lot of familiarity with Minecraft to progress through this mini-project. Since it’s easiest to spin up Minecraft servers within Docker containers, basic familiarity with Docker may be helpful.
You will need to on your local machine. Lastly, if you want to test that our project results are successful, you'll need to and log in as a paid owner of the game. The free trial of Minecraft doesn't allow connecting to multiplayer servers, which is what we'll be running for our project.Are you ready to do this? Here we go!~$ docker run -p 25000:25565 -e EULA=true itzg/minecraft-server
Unable to find image 'itzg/minecraft-server:latest' locally
latest: Pulling from itzg/minecraft-server
...
Status: Downloaded newer image for itzg/minecraft-server:latest
...
[init] Checking for JSON files.
[init] Setting initial memory to 1G and max to 1G
[init] Starting the Minecraft server...
...
[Server thread/INFO]: Preparing start region for dimension minecraft:overworld
[Worker-Main-5/INFO]: Preparing spawn area: 1%
...
[Server thread/INFO]: Done (40.436s)! For help, type "help"
...
-p
specifies a port on the host (your local machine) that Docker should bind to a port on the container. In this case, our local machine's port 25000 will point to the container's port 25565. By default, Minecraft servers run on port 25565. Typically, you will always bind to the container's port 25565, regardless of the port on the host that you choose to use.-e
EULA=true
provides an environment variable that the Docker container needs to use when starting up the server within the container. The Minecraft server application requires that you accept the EULA upon startup. Providing this environment variable is the Docker way to do that.If you look back at the terminal with the
docker run
command, you'll recall that it continues to output the log messages from the Minecraft server. It might look something like this:...
[User Authenticator #1/INFO]: UUID of player familycodingfun is 8b4fb92b-24c6-423a-bf32-fea282fc8a25
[Server thread/INFO]: familycodingfun[/172.17.0.1:53248] logged in with entity id 282 at (243.5, 65.0, -138.5)
[Server thread/INFO]: familycodingfun joined the game
The server notes that a new player (my username is
familycodingfun
) has joined the game. Our single game server setup is complete. Now, let's add Kong Gateway and port forwarding to the mix. For now, we'll exit the game and then kill our Docker container with the server.The first step is to . The vary depending on your unique setup. After installing Kong, we'll need to set up the initial configuration file. In your
/etc/kong
folder, you'll see a template file called kong.conf.default
. We will copy this file and rename it as kong.conf
, which is the file that Kong will look to for its startup configuration:~$ cd /etc/kong
/etc/kong$ sudo cp kong.conf.default kong.conf
/etc/kong$ tree
.
├── kong.conf
├── kong.conf.default
└── kong.logrotate
0 directories, 3 files
In
kong.conf
, we'll need to make the following three edits:# PATH: /etc/kong/kong.conf
#
# Around line 368. Uncomment and set for TCP listening on port 20000
#
stream_listen = 127.0.0.1:20000
#
# Around line 922. Uncomment and set database to off
#
database = off
#
# Around line 1106. Uncomment and set to a file we're about to create.
# Use the absolute path to a project folder
#
declarative_config = /PATH/TO/MY/project/minecraft-kong.yml
The
stream_listen
configuration tells Kong to listen for streaming TCP traffic. We're telling Kong to listen on port 20000 for this. For the needs of this mini project, we can configure Kong using its style. Kong will not need to use a database (database = off), and all of our configurations for port forwarding and load balancing will be stored in a single YAML file. That is the declarative_config
file path that we've set above.Before we start up Kong, we need to write that
minecraft-kong.yml
file with our port forwarding configuration. In a project folder (that matches the path you specified above), open up a new file called minecraft-kong.yml
:# PATH: ~/project/minecraft-kong.yml
_format_version: "2.1"
services:
- name: Minecraft-Server-A
url: tcp://localhost:25000
routes:
- name: Server-A-TCP-Routes
protocols: ["tcp", "tls"]
destinations:
- ip: 127.0.0.1
port: 20000
In this file, we declare a new named Minecraft-Server-A. The server uses the TCP protocol, listening on localhost port 25000, so we set these values together as the service's url. Next, we define a for the service, which associates our service with a URL path or an incoming connection destination that Kong will listen for. We provide a name for our route, telling Kong to listen for requests using TCP/TLS on the destination that we specified in our
kong.conf
file: ip 127.0.0.1 and port 20000.~/project$ docker run -p 25000:25565 -e EULA=true itzg/minecraft-server
That command might take a little time to run as the server starts up. Now, in a separate terminal window, we'll start up Kong:~/project$ sudo kong start
With our server up and running, we go back to our game client and, just like above, choose "Multiplayer" and try to establish a "Direct Connection" with a game server. We know that we could connect directly to localhost:25000, since that's the actual host port bound to the container's port; rather, we want to test Kong's port forwarding. We want to connect to the supposed game server on localhost:20000, pretending that we're the casual user who is unaware that port 20000 points to a port forwarding gateway.~/project$ docker run -p 25000:25565 -e EULA=true itzg/minecraft-server
Then, in a separate terminal window, we will start up Server B, this time binding the host's port 26000 to the container's port 25565:~/project$ docker run -p 26000:25565 -e EULA=true itzg/minecraft-server
Now, we have Servers A and B running, accessible at ports 25000 and 26000, respectively.Next, we want to edit our declarative configuration file (
minecraft-kong.yml
), configuring Kong for load balancing. Edit your file to reflect the following:# PATH: ~/project/minecraft-kong.yml
_format_version: "2.1"
upstreams:
- name: Minecraft-Servers
targets:
- target: localhost:25000
weight: 100
- target: localhost:26000
weight: 100
services:
- name: Load-Balancing-Service
host: Minecraft-Servers
protocol: tcp
routes:
- name: Load-Balancing-Route
protocols: ["tcp", "tls"]
destinations:
- ip: 127.0.0.1
port: 20000
~/project$ sudo kong restart
At this point, everything is up and running. We have our two Minecraft servers (Server A and Server B) running in Docker containers in two separate terminal windows. We have Kong configured to listen for TCP on port 20000, forwarding those requests to our load balancer, distributing connections across our two servers.Open the Minecraft game client again. Similar to previous steps, we will attempt to connect to the multiplayer server at localhost:20000 directly. As you connect, keep an eye on your two server terminal windows. As you repeatedly connect to the game, disconnect, and then reconnect, you will at times see a connection log message for Server A, and then at other times a message for Server B.And just like that, we have set up our load balancer to distribute connection requests across our two Minecraft servers!Also published on: //medium.com/geekculture/load-balancing-minecraft-servers-with-kong-gateway-99e7aee1bbcc