254 lines
6.8 KiB
Markdown
254 lines
6.8 KiB
Markdown
# ServerManager Kubernetes Operator
|
|
|
|
A kubernetes operator used to manage servers using CRDs
|
|
|
|
## Description
|
|
|
|
This is a kubernetes operator used to manage game servers and is used in the implementation of the kubernetes instance manager in the [ServerManager backend](https://git.acooldomain.co/server-manager/backend)
|
|
|
|
## Important
|
|
|
|
Currently the only supported ingress is traefik using the `IngressRoute` CRD
|
|
|
|
## Adding ServerManager operator to your cluster
|
|
|
|
### Install the CRDs
|
|
|
|
To install the CRDs you must first clone this repository using:
|
|
|
|
```sh
|
|
git clone https://git.acooldomain.co/server-manager/kubernetes-operator servermanager-operator
|
|
cd servermanager-operator
|
|
```
|
|
|
|
After the repository is cloned to install the CRDs just apply them using:
|
|
|
|
```sh
|
|
kubectl -f config/crd
|
|
```
|
|
|
|
### Setting up the ServerManager Operator
|
|
|
|
#### Configuration
|
|
|
|
The server-manager operator takes a configuration file called config.yaml and expects to find it in the same namespace under the name `server-manager-config` with a key named `config.yaml` containing a yaml file in the following schema
|
|
|
|
```yaml
|
|
domain_label: string
|
|
default_domain: string
|
|
browser:
|
|
domain: string
|
|
sub_path: string
|
|
auth_header: string
|
|
cert_resolver: string
|
|
entrypoints:
|
|
- string
|
|
|
|
additional_routes:
|
|
- IngressRouteRoute
|
|
|
|
middleware:
|
|
name: string
|
|
namespace: string
|
|
```
|
|
|
|
#### Configuration values
|
|
|
|
> **domain_label**
|
|
> optional
|
|
> type: string
|
|
> description: The name of a label on the node that it's value is a DNS record that points to that node.
|
|
|
|
> **default_domain**
|
|
> type: string
|
|
> description: The domain to use if the label in `domain_label` is not present on the node the pod runs on
|
|
|
|
> **browser.domain**
|
|
> type: string
|
|
> description: The domain that all file browsers would run on
|
|
|
|
> **browser.sub_path**
|
|
> type: string
|
|
> description: A path prefix that all browsers will run under
|
|
|
|
> **browser.auth_header**
|
|
> type: string
|
|
> description: The header used to identify a user on the browser container
|
|
|
|
> **browser.additional_routes**
|
|
> type: IngressRouteRoute
|
|
> description: Any additional routes that would point to anything other than the browser, usually needed for some forwardAuth middlewares
|
|
|
|
> **browser.middleware**
|
|
> type: MiddlewareRef
|
|
> description: A reference to the middleware that will handle authentication for the browsers
|
|
|
|
#### Example configuration
|
|
|
|
An example configuration that is close to what is used in [ServerManager](https://games.acooldomain.co)
|
|
|
|
```yaml
|
|
domain_label: "ddns.acooldomain.co/hostname"
|
|
default_domain: "acooldomain.co"
|
|
browser:
|
|
domain: games.acooldomain.co
|
|
sub_path: /browsers
|
|
auth_header: x-authentik-username
|
|
cert_resolver: letsencrypt
|
|
entrypoints:
|
|
- websecure
|
|
|
|
additional_routes: # This additional route is required for the Authentik middleware
|
|
- kind: Rule
|
|
match: "Host(`games.acooldomain.co`) && PathPrefix(`/outpost.goauthentik.io/`)"
|
|
priority: 15
|
|
services:
|
|
- kind: Service
|
|
name: ak-outpost-traefik
|
|
namespace: authentik
|
|
port: 9000
|
|
|
|
middleware:
|
|
name: authentik
|
|
namespace: authentik
|
|
```
|
|
|
|
And in a `ConfigMap` it looks as follows (replace `<namespace>` with the desired namespace):
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: server-manager-config
|
|
namespace: <namespace>
|
|
data:
|
|
config.yaml: |
|
|
domain_label: "ddns.acooldomain.co/hostname"
|
|
default_domain: "acooldomain.co"
|
|
browser:
|
|
domain: games.acooldomain.co
|
|
sub_path: /browsers
|
|
auth_header: x-authentik-username
|
|
cert_resolver: letsencrypt
|
|
entrypoints:
|
|
- websecure
|
|
|
|
additional_routes:
|
|
- kind: Rule
|
|
match: "Host(`games.acooldomain.co`) && PathPrefix(`/outpost.goauthentik.io/`)"
|
|
priority: 15
|
|
services:
|
|
- kind: Service
|
|
name: ak-outpost-traefik
|
|
namespace: authentik
|
|
port: 9000
|
|
|
|
middleware:
|
|
name: authentik
|
|
namespace: authentik
|
|
|
|
```
|
|
|
|
### Roles
|
|
|
|
The servermanager-operator requires permissions to **modify/create/delete** `pods`, `pvcs`, `services`, and `ingressroutes.traefik.io` to allow full functionality
|
|
to create a service account with these permissions run the following commands where `<namespace>` is the namespace the operator would be deployed to
|
|
|
|
```sh
|
|
kubectl apply -n <namespace> -f https://git.acooldomain.co/server-manager/kubernetes-operator/raw/branch/main/config/rbac/service-account.yaml
|
|
kubectl apply -n <namespace> -f https://git.acooldomain.co/server-manager/kubernetes-operator/raw/branch/main/config/rbac/role.yaml
|
|
kubectl apply -n <namespace> -f https://git.acooldomain.co/server-manager/kubernetes-operator/raw/branch/main/config/rbac/role-binding.yaml
|
|
```
|
|
|
|
### Manager
|
|
|
|
To install the operator itself after all the setup is complete simply run:
|
|
|
|
```sh
|
|
kubectl apply -n <namespace> -f https://git.acooldomain.co/server-manager/kubernetes-operator/raw/branch/main/config/manager/manager.yaml
|
|
```
|
|
|
|
### Verify
|
|
|
|
After all the setup is applied you can test that the kubernetes-operator is working by creating a game image and a server that uses it.
|
|
Below are exxamples for an Image that runs a minecraft paper server on version 1.21.5 and a Server using that image.
|
|
|
|
#### Example Image
|
|
|
|
```yaml
|
|
apiVersion: server-manager.acooldomain.co/v1alpha1
|
|
kind: Image
|
|
metadata:
|
|
name: minecraft-paper-1-21-5
|
|
spec:
|
|
location: git.acooldomain.co/server-manager/minecraft:paper-1.21.5
|
|
name: minecraft
|
|
tag: paper-1.21.5
|
|
working_dir: /opt/server
|
|
ports:
|
|
- port: 25565
|
|
protocol: TCP
|
|
|
|
init_script:
|
|
image: alpine:latest
|
|
command:
|
|
- /bin/sh
|
|
args:
|
|
- /bin/sh
|
|
- "-c"
|
|
- "echo eula=true >> /data/eula.txt"
|
|
```
|
|
|
|
#### Example Server
|
|
|
|
```yaml
|
|
apiVersion: server-manager.acooldomain.co/v1alpha1
|
|
kind: ServerManager
|
|
metadata:
|
|
name: test-server
|
|
spec:
|
|
storage: 10Gi
|
|
browser:
|
|
"on": true
|
|
server:
|
|
"on": true
|
|
image: minecraft-paper-1-21-5
|
|
ports:
|
|
```
|
|
|
|
#### Examples result
|
|
|
|
After applying the following resources your environment should have several new resources created
|
|
|
|
* PVCs
|
|
* test-server
|
|
* test-server-browser
|
|
|
|
* services
|
|
* test-server
|
|
* type: NodePort
|
|
* ContainerPort: 25565
|
|
* NodePort: Random Port
|
|
|
|
* Pods
|
|
* test-server
|
|
* test-server-browser
|
|
|
|
To delete the server and the related resources it is enough to delete the `server-manager.acooldomain.co` resource we created
|
|
|
|
## License
|
|
|
|
Copyright 2025.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|