From 56d66cf204bcdd35f8ef3671860607912b62bc76 Mon Sep 17 00:00:00 2001 From: Jonathan Ervine Date: Wed, 12 Aug 2020 12:32:21 +0800 Subject: [PATCH] Added factorio --- bedrock/Chart.yaml | 4 +- factorio/.helmignore | 21 ++++++ factorio/Chart.yaml | 15 ++++ factorio/README.md | 71 +++++++++++++++++++ factorio/templates/NOTES.txt | 40 +++++++++++ factorio/templates/_helpers.tpl | 16 +++++ factorio/templates/deployment.yaml | 101 +++++++++++++++++++++++++++ factorio/templates/factorio-svc.yaml | 18 +++++ factorio/templates/mods-pvc.yaml | 24 +++++++ factorio/templates/rcon-svc.yaml | 20 ++++++ factorio/templates/saves-pvc.yaml | 24 +++++++ factorio/templates/secrets.yaml | 15 ++++ factorio/values.yaml | 66 +++++++++++++++++ 13 files changed, 433 insertions(+), 2 deletions(-) create mode 100755 factorio/.helmignore create mode 100755 factorio/Chart.yaml create mode 100755 factorio/README.md create mode 100755 factorio/templates/NOTES.txt create mode 100755 factorio/templates/_helpers.tpl create mode 100755 factorio/templates/deployment.yaml create mode 100755 factorio/templates/factorio-svc.yaml create mode 100755 factorio/templates/mods-pvc.yaml create mode 100755 factorio/templates/rcon-svc.yaml create mode 100755 factorio/templates/saves-pvc.yaml create mode 100755 factorio/templates/secrets.yaml create mode 100755 factorio/values.yaml diff --git a/bedrock/Chart.yaml b/bedrock/Chart.yaml index df30d2f..25eff88 100644 --- a/bedrock/Chart.yaml +++ b/bedrock/Chart.yaml @@ -14,10 +14,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. -version: 0.1.4 +version: 0.1.5 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. -appVersion: 1.16.1.02 +appVersion: 1.16.20.03 icon: https://git.ervine.org/jonny/x86_64-debian-bedrock/raw/branch/master/bedrock.jpg diff --git a/factorio/.helmignore b/factorio/.helmignore new file mode 100755 index 0000000..f0c1319 --- /dev/null +++ b/factorio/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/factorio/Chart.yaml b/factorio/Chart.yaml new file mode 100755 index 0000000..f78c9bf --- /dev/null +++ b/factorio/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +appVersion: 0.17.79 +description: Factorio dedicated server. +home: https://www.factorio.com/ +icon: https://us1.factorio.com/assets/img/factorio-logo.png +keywords: +- game +- server +maintainers: +- email: docker@ervine.org + name: Jonathan +name: factorio +sources: +- https://git.ervine.org/jonny/x86_64-suse-factorio +version: 1.0.0 diff --git a/factorio/README.md b/factorio/README.md new file mode 100755 index 0000000..a0be6d2 --- /dev/null +++ b/factorio/README.md @@ -0,0 +1,71 @@ +# Factorio + +[Factorio](https://www.factorio.com/) is a game in which you build and maintain factories. + +## Introduction + +This chart creates a single [Factorio Headless](https://www.factorio.com/download-headless) Pod, plus Services for the Factorio server and RCON. + +## Prerequisites + +- Kubernetes 1.4+ with Beta APIs enabled +- PV provisioner support in the underlying infrastructure + +## Provider-specific Prerequisites + +Amazon's Elastic Loadbalancer lacks support for UDP. You'll need to set `factorioServer.ServiceType` to `NodePort` and expose the port that gets selected (see `kubectl describe svc `) via a security group. You may need to do something similar for certain bare metal deployments. + +You need not worry about this on Google Cloud Platform. + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```bash +$ helm install --name my-release stable/factorio +``` + +This command deploys a Factorio dedicated server with sane defaults. + +> **Tip**: List all releases using `helm list` + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```bash +$ helm delete my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Configuration + +Refer to [values.yaml](values.yaml) for the full run-down on defaults. These are a mixture of Kubernetes and Factorio-related directives that map to environment variables in [docker-factorio](https://github.com/games-on-k8s/docker-factorio). + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```bash +$ helm install --name my-release \ + --set factorioServer.factorioServer=My Server,ImageTag=0.15.39 \ + stable/factorio +``` + +The above command deploys Factorio dedicated with a server name of `My Server` and docker-factorio image version `0.15.39`. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```bash +$ helm install --name my-release -f values.yaml stable/factorio +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Persistence + +The [docker-factorio](https://github.com/games-on-k8s/docker-factorio) image stores the saved games and mods under /opt/factorio. + +By default a PersistentVolumeClaim is created and mounted for saves but not mods. In order to disable this functionality +you can change the values.yaml to disable persistence under the sub-sections under `Persistence`. + +> *"An emptyDir volume is first created when a Pod is assigned to a Node, and exists as long as that Pod is running on that node. When a Pod is removed from a node for any reason, the data in the emptyDir is deleted forever."* diff --git a/factorio/templates/NOTES.txt b/factorio/templates/NOTES.txt new file mode 100755 index 0000000..08b09f2 --- /dev/null +++ b/factorio/templates/NOTES.txt @@ -0,0 +1,40 @@ +Get the IP address of your Factorio server by running these commands in the +same shell: + +{{- if contains "NodePort" .Values.factorioServer.serviceType }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} \ + -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "factorio.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} \ + -o jsonpath="{.items[0].status.addresses[0].address}") + echo "You'll need to expose this node through your security groups/firewall" + echo "for it to be world-accessible." + echo $NODE_IP:$NODE_PORT + +{{- else if contains "LoadBalancer" .Values.factorioServer.serviceType }} +!! NOTE: It may take a few minutes for the LoadBalancer IP to be available. + +!! NOTE: If you installed this on an AWS cluster, your game will be + un-reachable. AWS ELB does not support UDP. You'll need to use a NodePort + value for factorioServer.serviceType. See the README.md for more info. + +You can watch for EXTERNAL-IP to populate by running: + kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "factorio.fullname" . }} + +{{- else if contains "ClusterIP" .Values.factorioServer.serviceType }} + export POD_NAME=$(kubectl get pods \ + --namespace {{ .Release.Namespace }} \ + -l "component={{ template "factorio.fullname" . }}" \ + -o jsonpath="{.items[0].metadata.name}") + kubectl port-forward $POD_NAME 34197:34197 + echo "Point your Minecraft client at 127.0.0.1:34197" + +{{- end }} + +{{- if .Values.persistence.savedGames.enabled }} +{{- else }} +############################################################################ +### WARNING: Persistence is disabled!!! You will lose your game state ### +### when the Factorio pod is terminated. ### +### See values.yaml's Persistence.SavedGames.Enabled directive. ### +############################################################################ +{{- end }} diff --git a/factorio/templates/_helpers.tpl b/factorio/templates/_helpers.tpl new file mode 100755 index 0000000..b6e8d48 --- /dev/null +++ b/factorio/templates/_helpers.tpl @@ -0,0 +1,16 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "factorio.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "factorio.fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/factorio/templates/deployment.yaml b/factorio/templates/deployment.yaml new file mode 100755 index 0000000..03b8ad6 --- /dev/null +++ b/factorio/templates/deployment.yaml @@ -0,0 +1,101 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: {{ template "factorio.fullname" . }} + labels: + app: {{ template "factorio.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +spec: + template: + metadata: + labels: + app: {{ template "factorio.fullname" . }} + spec: + containers: + - name: {{ template "factorio.fullname" . }} + image: "{{ .Values.image }}:{{ .Values.imageTag }}" + imagePullPolicy: Always + resources: +{{ toYaml .Values.resources | indent 10 }} + env: + - name: FACTORIO_SERVER_NAME + value: {{ .Values.factorioServer.name | quote }} + - name: FACTORIO_DESCRIPTION + value: {{ .Values.factorioServer.description | quote }} + - name: FACTORIO_PORT + value: {{ .Values.factorioServer.port | quote }} + - name: FACTORIO_MAX_PLAYERS + value: {{ .Values.factorioServer.maxPlayers | quote }} + - name: FACTORIO_IS_PUBLIC + value: {{ .Values.factorioServer.isPublic | quote }} + - name: FACTORIO_REQUIRE_USER_VERIFICATION + value: {{ .Values.factorioServer.verifyIdentity | quote }} + - name: FACTORIO_ALLOW_COMMANDS + value: {{ .Values.factorioServer.allowCommands | quote }} + - name: FACTORIO_NO_AUTO_PAUSE + value: {{ .Values.factorioServer.noAutoPause | quote }} + - name: FACTORIO_AUTOSAVE_INTERVAL + value: {{ .Values.factorioServer.autosave.interval | quote }} + - name: FACTORIO_AUTOSAVE_SLOTS + value: {{ .Values.factorioServer.autosave.slots | quote }} + + {{- if .Values.factorioServer.password }} + - name: FACTORIO_GAME_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "factorio.fullname" . }} + key: server-password + {{- end }} + + {{- if .Values.factorioServer.isPublic }} + - name: FACTORIO_USER_USERNAME + valueFrom: + secretKeyRef: + name: {{ template "factorio.fullname" . }} + key: factorio-username + - name: FACTORIO_USER_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "factorio.fullname" . }} + key: factorio-password + {{- end }} + + {{- if .Values.factorioServer.rcon.enabled }} + - name: FACTORIO_RCON_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "factorio.fullname" . }} + key: rcon-password + {{- end }} + + ports: + - name: factorio + containerPort: 34197 + protocol: UDP + {{- if .Values.factorioServer.rcon.enabled }} + - name: rcon + containerPort: {{ .Values.factorioServer.rcon.port }} + protocol: TCP + {{- end }} + volumeMounts: + - name: saves + mountPath: /opt/factorio/saves + - name: mods + mountPath: /opt/factorio/mods + volumes: + - name: saves + {{- if .Values.persistence.savedGames.enabled }} + persistentVolumeClaim: + claimName: {{ template "factorio.fullname" . }}-savedgames + {{- else }} + emptyDir: {} + {{- end }} + - name: mods + {{- if .Values.persistence.mods.enabled }} + persistentVolumeClaim: + claimName: {{ template "factorio.fullname" . }}-mods + {{- else }} + emptyDir: {} + {{- end }} diff --git a/factorio/templates/factorio-svc.yaml b/factorio/templates/factorio-svc.yaml new file mode 100755 index 0000000..bf500ff --- /dev/null +++ b/factorio/templates/factorio-svc.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "factorio.fullname" . }} + labels: + app: {{ template "factorio.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +spec: + type: {{ .Values.factorioServer.serviceType }} + ports: + - name: factorio + port: {{ .Values.factorioServer.port | int }} + targetPort: factorio + protocol: UDP + selector: + app: {{ template "factorio.fullname" . }} diff --git a/factorio/templates/mods-pvc.yaml b/factorio/templates/mods-pvc.yaml new file mode 100755 index 0000000..3732673 --- /dev/null +++ b/factorio/templates/mods-pvc.yaml @@ -0,0 +1,24 @@ +{{- if .Values.persistence.mods.enabled -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ template "factorio.fullname" . }}-mods + labels: + app: {{ template "factorio.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.persistence.mods.size | quote }} +{{- if .Values.persistence.storageClass }} +{{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.persistence.storageClass }}" +{{- end }} +{{- end }} +{{- end -}} diff --git a/factorio/templates/rcon-svc.yaml b/factorio/templates/rcon-svc.yaml new file mode 100755 index 0000000..112f4d0 --- /dev/null +++ b/factorio/templates/rcon-svc.yaml @@ -0,0 +1,20 @@ +{{- if default "" .Values.factorioServer.rcon.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "factorio.fullname" . }}-rcon" + labels: + app: {{ template "factorio.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +spec: + type: {{ .Values.factorioServer.rcon.serviceType }} + ports: + - name: rcon + port: {{ .Values.factorioServer.rcon.port }} + targetPort: rcon + protocol: TCP + selector: + app: {{ template "factorio.fullname" . }} +{{- end }} diff --git a/factorio/templates/saves-pvc.yaml b/factorio/templates/saves-pvc.yaml new file mode 100755 index 0000000..88a99fd --- /dev/null +++ b/factorio/templates/saves-pvc.yaml @@ -0,0 +1,24 @@ +{{- if .Values.persistence.savedGames.enabled -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ template "factorio.fullname" . }}-savedgames + labels: + app: {{ template "factorio.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.persistence.savedGames.size | quote }} +{{- if .Values.persistence.storageClass }} +{{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.persistence.storageClass }}" +{{- end }} +{{- end }} +{{- end -}} diff --git a/factorio/templates/secrets.yaml b/factorio/templates/secrets.yaml new file mode 100755 index 0000000..67b75c5 --- /dev/null +++ b/factorio/templates/secrets.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "factorio.fullname" . }} + labels: + app: {{ template "factorio.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +type: Opaque +data: + server-password: {{ default "" .Values.factorioServer.password | b64enc | quote }} + rcon-password: {{ default "" .Values.factorioServer.rcon.password | b64enc | quote }} + factorio-username: {{ default "" .Values.factorio.user.username | b64enc | quote }} + factorio-password: {{ default "" .Values.factorio.user.password | b64enc | quote }} diff --git a/factorio/values.yaml b/factorio/values.yaml new file mode 100755 index 0000000..6971bf0 --- /dev/null +++ b/factorio/values.yaml @@ -0,0 +1,66 @@ +# Factorio image version +# ref: https://quay.io/repository/games_on_k8s/factorio?tab=tags +image: harbor.ervine.dev/public/x86_64/suse/factorio +imageTag: 0.17.79 + +# Configure resource requests and limits +# ref: http://kubernetes.io/docs/user-guide/compute-resources/ +resources: + requests: + memory: 512Mi + cpu: 500m + +# Most of these map to environment variables. See docker-factorio for details: +# https://github.com/games-on-k8s/docker-factorio/blob/master/README.md#environment-variable-reference +factorioServer: + name: Kubernetes Server + description: Factorio running on Kubernetes + port: 34197 + # Lock this server down with a password. + # password: change.me + maxPlayers: 255 + # Publishes this server in the server browser if true. + # You'll want to set Factorio.User below if true, as it becomes required. + isPublic: false + verifyIdentity: false + # Allows or disallows console commands. Must be one of: `true`, `false`, or `admins-only`. + allowCommands: admins-only + # Pause the server when nobody is connected? + noAutoPause: "false" + # You'll want to change this to NodePort if you are on AWS. + serviceType: ClusterIP + + autosave: + # Auto-save interval in minutes. + interval: 2 + slots: 3 + + rcon: + enabled: false + port: 27015 + # Empty value here enables an auto-generated password. + password: "" + serviceType: ClusterIP + +factorio: + # Your factorio.com User/pass is needed if factorioServer.IsPublic is true. + user: + username: your.username + password: your.password + +persistence: + ## factorio data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "nfs-client-hestia" + savedGames: + # Set this to false if you don't care to persist saved games between restarts. + enabled: true + size: 1Gi + mods: + enabled: true + size: 128Mi