diff --git a/stable/minecraft/.helmignore b/stable/minecraft/.helmignore new file mode 100644 index 0000000000..f0c1319444 --- /dev/null +++ b/stable/minecraft/.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/stable/minecraft/Chart.yaml b/stable/minecraft/Chart.yaml new file mode 100755 index 0000000000..ef356e308b --- /dev/null +++ b/stable/minecraft/Chart.yaml @@ -0,0 +1,12 @@ +name: minecraft +version: 0.1.0 +description: Minecraft server +keywords: +- game +- server +sources: +- https://hub.docker.com/r/itzg/minecraft-server/~/dockerfile/ +- https://github.com/itzg/dockerfiles +maintainers: +- name: Greg Taylor + email: gtaylor@gc-taylor.com diff --git a/stable/minecraft/README.md b/stable/minecraft/README.md new file mode 100644 index 0000000000..c52db0ffba --- /dev/null +++ b/stable/minecraft/README.md @@ -0,0 +1,65 @@ +# Minecraft + +[Minecraft](https://minecraft.net/en/) Minecraft is a game about placing blocks and going on adventures. + +## Introduction + +This chart creates a single Minecraft Pod, plus Services for the Minecraft server and RCON. + +## Prerequisites + +- 512 MB of RAM +- Kubernetes 1.4+ with Beta APIs enabled +- PV provisioner support in the underlying infrastructure + +## Installing the Chart + +To install the chart with the release name `my-release`, read the [Minecraft EULA](https://account.mojang.com/documents/minecraft_eula) run: + +```bash +$ helm install --name my-release \ + --set minecraftServer.eula=true stable/minecraft +``` + +This command deploys a Minecraft dedicated server with sensible 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 Minecraft-related directives that map to environment variables in the [itzg/minecraft-server](https://hub.docker.com/r/itzg/minecraft-server/) Docker image. + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```bash +$ helm install --name my-release \ + --set minecraftServer.eula=true,minecraftServer.Difficulty=hard \ + stable/minecraft +``` + +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/minecraft +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Persistence + +The [itzg/minecraft-server](https://hub.docker.com/r/itzg/minecraft-server/) image stores the saved games and mods under /data. + +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/stable/minecraft/templates/NOTES.txt b/stable/minecraft/templates/NOTES.txt new file mode 100644 index 0000000000..103c5d1217 --- /dev/null +++ b/stable/minecraft/templates/NOTES.txt @@ -0,0 +1,51 @@ +{{- if eq (printf "%s" .Values.minecraftServer.eula) "FALSE" }} +############################################################################## +#### ERROR: You did not agree to the EULA in your 'helm install' call. #### +############################################################################## + +This deployment will be incomplete until you read the Minecraft EULA linked +in the README.md, then: + + helm upgrade {{ .Release.Name }} \ + --set minecraftServer.eula=true stable/minecraft +{{- else -}} + +Get the IP address of your Minecraft server by running these commands in the +same shell: + +{{- if contains "NodePort" .Values.minecraftServer.serviceType }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} \ + -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "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.minecraftServer.serviceType }} + +!! NOTE: It may take a few minutes for the LoadBalancer IP to be available. !! + +You can watch for EXTERNAL-IP to populate by running: + kubectl get svc -w {{ template "fullname" . }} + +{{- else if contains "ClusterIP" .Values.minecraftServer.serviceType }} + export POD_NAME=$(kubectl get pods \ + --namespace {{ .Release.Namespace }} \ + -l "component={{ template "fullname" . }}" \ + -o jsonpath="{.items[0].metadata.name}") + kubectl port-forward $POD_NAME 25565:25565 + echo "Point your Minecraft client at 127.0.0.1:22565" + +{{- end }} + +{{- if .Values.persistence.dataDir.enabled }} +{{- else }} + +############################################################################ +### WARNING: Persistence is disabled!!! You will lose your game state ### +### when the Minecraft pod is terminated. ### +### See values.yaml's persistence.dataDir.enabled directive. ### +############################################################################ +{{- end }} +{{- end }} diff --git a/stable/minecraft/templates/_helpers.tpl b/stable/minecraft/templates/_helpers.tpl new file mode 100644 index 0000000000..234480de71 --- /dev/null +++ b/stable/minecraft/templates/_helpers.tpl @@ -0,0 +1,16 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 24 -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 24 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 24 -}} +{{- end -}} diff --git a/stable/minecraft/templates/datadir-pvc.yaml b/stable/minecraft/templates/datadir-pvc.yaml new file mode 100644 index 0000000000..3577635afb --- /dev/null +++ b/stable/minecraft/templates/datadir-pvc.yaml @@ -0,0 +1,14 @@ +{{- if .Values.persistence.dataDir.enabled -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ template "fullname" . }}-datadir + annotations: + volume.alpha.kubernetes.io/storage-class: {{ .Values.persistence.storageClass | quote }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.persistence.dataDir.Size | quote }} +{{- end -}} diff --git a/stable/minecraft/templates/deployment.yaml b/stable/minecraft/templates/deployment.yaml new file mode 100644 index 0000000000..52cbc82e77 --- /dev/null +++ b/stable/minecraft/templates/deployment.yaml @@ -0,0 +1,113 @@ +{{- if ne (printf "%s" .Values.minecraftServer.eula) "FALSE" }} +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +spec: + template: + metadata: + labels: + app: {{ template "fullname" . }} + spec: + containers: + - name: {{ template "fullname" . }} + image: "{{ .Values.image }}:{{ .Values.imageTag }}" + imagePullPolicy: Always + resources: + {{ include "toYaml" .Values.resources | indent 10 }} + env: + - name: EULA + value: {{ .Values.minecraftServer.eula | quote }} + - name: VERSION + value: {{ .Values.minecraftServer.version | quote }} + - name: DIFFICULTY + value: {{ .Values.minecraftServer.difficulty | quote }} + - name: WHITELIST + value: {{ default "" .Values.minecraftServer.whitelist | quote }} + - name: OPS + value: {{ default "" .Values.minecraftServer.ops | quote }} + - name: ICON + value: {{ default "" .Values.minecraftServer.icon | quote }} + - name: MAX_PLAYERS + value: {{ .Values.minecraftServer.maxPlayers | quote }} + - name: MAX_WORLD_SIZE + value: {{ .Values.minecraftServer.maxWorldSize | quote }} + - name: ALLOW_NETHER + value: {{ .Values.minecraftServer.allowNether | quote }} + - name: ANNOUNCE_PLAYER_ACHIEVEMENTS + value: {{ .Values.minecraftServer.announcePlayerAchievements | quote }} + - name: ENABLE_COMMAND_BLOCK + value: {{ .Values.minecraftServer.enableCommandBlock | quote }} + - name: FORCE_gameMode + value: {{ .Values.minecraftServer.forcegameMode | quote }} + - name: GENERATE_STRUCTURES + value: {{ .Values.minecraftServer.generateStructures | quote }} + - name: HARDCORE + value: {{ .Values.minecraftServer.hardcore | quote }} + - name: MAX_BUILD_HEIGHT + value: {{ .Values.minecraftServer.maxBuildHeight | quote }} + - name: MAX_TICK_TIME + value: {{ .Values.minecraftServer.maxTickTime | quote }} + - name: SPAWN_ANIMALS + value: {{ .Values.minecraftServer.spawnAnimals | quote }} + - name: SPAWN_MONSTERS + value: {{ .Values.minecraftServer.spawnMonsters | quote }} + - name: SPAWN_NPCS + value: {{ .Values.minecraftServer.spawnNPCs | quote }} + - name: VIEW_DISTANCE + value: {{ .Values.minecraftServer.viewDistance | quote }} + - name: SEED + value: {{ default "" .Values.minecraftServer.levelSeed | quote }} + - name: MODE + value: {{ .Values.minecraftServer.gameMode | quote }} + - name: MOTD + value: {{ .Values.minecraftServer.motd | quote }} + - name: PVP + value: {{ .Values.minecraftServer.pvp | quote }} + - name: LEVEL_TYPE + value: {{ .Values.minecraftServer.levelType | quote }} + - name: GENERATOR_SETTINGS + value: {{ default "" .Values.minecraftServer.generatorSettings | quote }} + - name: LEVEL + value: {{ .Values.minecraftServer.worldSaveName | quote }} + - name: ONLINE_MODE + value: {{ .Values.minecraftServer.onlineMode | quote }} + - name: JVM_OPTS + value: {{ .Values.minecraftServer.jvmOpts | quote }} + + {{- if .Values.minecraftServer.rcon.enabled }} + - name: ENABLE_RCON + value: "true" + - name: RCON_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "fullname" . }} + key: rcon-password + {{- end }} + + ports: + - name: minecraft + containerPort: 25565 + protocol: TCP + {{- if .Values.minecraftServer.rcon.enabled }} + - name: rcon + containerPort: {{ .Values.minecraftServer.rcon.port }} + protocol: TCP + {{- end}} + volumeMounts: + - name: datadir + mountPath: /data + volumes: + - name: datadir + {{- if .Values.persistence.dataDir.enabled }} + persistentVolumeClaim: + claimName: {{template "fullname" .}}-datadir + {{- else }} + emptyDir: {} + {{- end }} +{{ end }} diff --git a/stable/minecraft/templates/minecraft-svc.yaml b/stable/minecraft/templates/minecraft-svc.yaml new file mode 100644 index 0000000000..466aee7d0f --- /dev/null +++ b/stable/minecraft/templates/minecraft-svc.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Name }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +spec: + type: {{ .Values.minecraftServer.serviceType }} + ports: + - name: minecraft + port: 25565 + targetPort: minecraft + protocol: TCP + selector: + app: {{ template "fullname" . }} diff --git a/stable/minecraft/templates/rcon-svc.yaml b/stable/minecraft/templates/rcon-svc.yaml new file mode 100644 index 0000000000..01c7ea6c98 --- /dev/null +++ b/stable/minecraft/templates/rcon-svc.yaml @@ -0,0 +1,20 @@ +{{- if default "" .Values.minecraftServer.rcon.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "fullname" . }}-rcon" + labels: + app: {{ template "fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Name }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +spec: + type: {{ .Values.minecraftServer.rcon.serviceType }} + ports: + - name: rcon + port: {{ .Values.minecraftServer.rcon.port }} + targetPort: rcon + protocol: TCP + selector: + app: {{ template "fullname" . }} +{{- end }} diff --git a/stable/minecraft/templates/secrets.yaml b/stable/minecraft/templates/secrets.yaml new file mode 100644 index 0000000000..16c5264d39 --- /dev/null +++ b/stable/minecraft/templates/secrets.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +type: Opaque +data: + rcon-password: {{ default "" .Values.minecraftServer.rcon.password | b64enc | quote }} diff --git a/stable/minecraft/values.yaml b/stable/minecraft/values.yaml new file mode 100644 index 0000000000..aa76ae1a78 --- /dev/null +++ b/stable/minecraft/values.yaml @@ -0,0 +1,88 @@ +# ref: https://hub.docker.com/r/itzg/minecraft-server/ +image: itzg/minecraft-server +imageTag: latest + +## 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 Minecraft for details: +# https://hub.docker.com/r/itzg/minecraft-server/ +minecraftServer: + # This must be overridden, since we can't accept this for the user. + eula: "FALSE" + # One of: LATEST, SNAPSHOT, or a specific version (ie: "1.7.9"). + version: "LATEST" + # One of: peaceful, easy, normal, and hard + difficulty: easy + # A comma-separated list of player names to whitelist. + whitelist: + # A comma-separated list of player names who should be admins. + ops: + # A server icon URL for server listings. Auto-scaled and transcoded. + icon: + # Max connected players. + maxPlayers: 20 + # This sets the maximum possible size in blocks, expressed as a radius, that the world border can obtain. + maxWorldSize: 10000 + # Allows players to travel to the Nether. + allowNether: true + # Allows server to announce when a player gets an achievement. + announcePlayerAchievements: true + # Enables command blocks. + enableCommandBlock: true + # If true, players will always join in the default gameMode even if they were previously set to something else. + forcegameMode: false + # Defines whether structures (such as villages) will be generated. + generateStructures: true + # If set to true, players will be set to spectator mode if they die. + hardcore: false + # The maximum height in which building is allowed. + maxBuildHeight: 256 + # The maximum number of milliseconds a single tick may take before the server watchdog stops the server with the message. -1 disables this entirely. + maxTickTime: 60000 + # Determines if animals will be able to spawn. + spawnAnimals: true + # Determines if monsters will be spawned. + spawnMonsters: true + # Determines if villagers will be spawned. + spawnNPCs: true + # Max view distance (in chunks). + viewDistance: 10 + # Define this if you want a specific map generation seed. + levelSeed: + # One of: creative, survival, adventure, spectator + gameMode: survival + # Message of the Day + motd: "Welcome to Minecraft on Kubernetes!" + # If true, enable player-vs-player damage. + pvp: false + # One of: DEFAULT, FLAT, LARGEBIOMES, AMPLIFIED, CUSTOMIZED + levelType: DEFAULT + # When levelType == FLAT or CUSTOMIZED, this can be used to further customize map generation. + # ref: https://hub.docker.com/r/itzg/minecraft-server/ + generatorSettings: + worldSaveName: world + # Check accounts against Minecraft account service. + onlineMode: true + # If you adjust this, you may need to adjust resources.requests above to match. + jvmOpts: "-Xmx512M -Xms512M" + serviceType: LoadBalancer + + rcon: + # If you enable this, make SURE to change your password below. + enabled: false + port: 25575 + password: "CHANGEME!" + serviceType: LoadBalancer + +persistence: + storageClass: generic + dataDir: + # Set this to false if you don't care to persist state between restarts. + enabled: true + Size: 1Gi