ce7cb702218693d08ea6d83464d2457c9250027c

This commit is contained in:
ms2k 2026-11-12 20:46:28 +09:00
commit 34c5f8963c
9 changed files with 145336 additions and 0 deletions

View file

@ -0,0 +1,199 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: minecraft
namespace: minecraft
labels:
app.kubernetes.io/name: minecraft
app.kubernetes.io/instance: skies
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: minecraft
app.kubernetes.io/instance: skies
template:
metadata:
labels:
app.kubernetes.io/name: minecraft
app.kubernetes.io/instance: skies
spec:
automountServiceAccountToken: false
dnsConfig:
options:
- name: ndots
value: "1"
imagePullSecrets:
- name: minecraft-pull
nodeSelector:
kubernetes.io/hostname: "********-nas"
terminationGracePeriodSeconds: 180
securityContext:
runAsUser: 1000
runAsGroup: 1000
runAsNonRoot: true
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
initContainers:
- name: bootstrap
image: registry.quorate.internal/quorate/fsharp-runner@sha256:d7b904f4f0cae9fdba7c7345cdf08c91162245834a8a13658d93396272aeec83
command: [/usr/share/dotnet/dotnet, /opt/fsi/fsi.dll, --exec]
args: [/bootstrap/run.fsx]
env:
- name: SSL_CERT_FILE
value: /artifacts/ca.crt
- name: HOME
value: /tmp
- name: DOTNET_NOLOGO
value: "true"
- name: DOTNET_CLI_TELEMETRY_OPTOUT
value: "1"
envFrom:
- secretRef:
name: minecraft
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 2Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
volumeMounts:
- name: runtime
mountPath: /data
- name: state
mountPath: /state
- name: backups
mountPath: /backups
- name: files
mountPath: /files
readOnly: true
- name: bootstrap
mountPath: /bootstrap
readOnly: true
- name: rcon
mountPath: /rcon
readOnly: true
- name: artifacts
mountPath: /artifacts
readOnly: true
containers:
- name: minecraft
image: ghcr.io/graalvm/jdk-community:25i4@sha256:3508f7c5ad1e211f353e3a90f5de263574c4b09e40635fdf5a6e5952241f605b
workingDir: /data
command: [/data/mc-server-runner]
args:
- --stop-duration
- 150s
- --named-pipe
- /data/console.in
- --
- java
- "@user_jvm_args.txt"
- "@server_args.txt"
- nogui
ports:
- name: minecraft
containerPort: 25565
protocol: TCP
- name: metrics
containerPort: 19565
protocol: TCP
- name: rcon
containerPort: 25575
protocol: TCP
resources:
requests:
cpu: "2"
memory: 20Gi
limits:
memory: 24Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
startupProbe:
exec:
command: [/data/mc-monitor, status, --host, 127.0.0.1, --port, "25565"]
periodSeconds: 10
failureThreshold: 90
timeoutSeconds: 5
readinessProbe:
exec:
command: [/data/mc-monitor, status, --host, 127.0.0.1, --port, "25565"]
periodSeconds: 10
timeoutSeconds: 5
volumeMounts:
- name: runtime
mountPath: /data
- name: state
mountPath: /data/ops.json
subPath: ops.json
- name: state
mountPath: /data/whitelist.json
subPath: whitelist.json
- name: state
mountPath: /data/banned-ips.json
subPath: banned-ips.json
- name: state
mountPath: /data/banned-players.json
subPath: banned-players.json
- name: state
mountPath: /data/usercache.json
subPath: usercache.json
- name: state
mountPath: /data/usernamecache.json
subPath: usernamecache.json
- name: state
mountPath: /data/world
subPath: world
- name: state
mountPath: /data/config/chunky/tasks
subPath: world/data/chunky
- name: state
mountPath: /data/local
subPath: local
- name: state
mountPath: /data/journeymap
subPath: journeymap
- name: backups
mountPath: /data/backups
volumes:
- name: artifacts
projected:
defaultMode: 0440
sources:
- secret:
name: minecraft-artifacts
- secret:
name: minecraft-ca
items:
- key: certificate
path: ca.crt
- name: rcon
secret:
secretName: minecraft-rcon
defaultMode: 0440
- name: bootstrap
configMap:
name: minecraft-boot
- name: state
persistentVolumeClaim:
claimName: minecraft
- name: backups
persistentVolumeClaim:
claimName: minecraft-backups
- name: runtime
emptyDir: {}
- name: files
secret:
secretName: minecraft-files
items:
- key: server.properties
path: server.properties

View file

@ -0,0 +1,18 @@
apiVersion: kyverno.io/v2
kind: PolicyException
metadata:
name: minecraft-singleton
namespace: kyverno
annotations:
policies.kyverno.io/reason: Minecraft owns one local world and permits one active server.
quorate.internal/exception-owner: workloads
spec:
exceptions:
- policyName: min-replicas
ruleNames: [min-replicas]
match:
any:
- resources:
kinds: [Deployment]
namespaces: [minecraft]
names: [minecraft]

View file

@ -0,0 +1,53 @@
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMPodScrape
metadata:
name: minecraft
namespace: victoriametrics
labels:
observability.quorate.internal/scrape: "true"
spec:
namespaceSelector:
matchNames: [minecraft]
selector:
matchLabels:
app.kubernetes.io/name: minecraft
app.kubernetes.io/instance: skies
podMetricsEndpoints:
- port: metrics
path: /metrics
interval: 30s
scrapeTimeout: 10s
relabelConfigs:
- targetLabel: application
replacement: minecraft
- sourceLabels:
- __meta_kubernetes_pod_label_app_kubernetes_io_instance
targetLabel: instance
- action: labeldrop
regex: pod
metricRelabelConfigs:
- action: labeldrop
regex: pod
- action: labeldrop
regex: (?i)(.*password.*|.*passwd.*|.*secret.*|.*token.*|.*auth.*|.*bearer.*|.*cookie.*|.*dsn.*|.*uri.*|.*url.*|.*cmdline.*|.*command.*|.*args.*|.*env.*)
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: vmagent-minecraft
namespace: victoriametrics
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/name: vmagent
app.kubernetes.io/instance: main
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/instance: skies
toPorts:
- ports:
- port: "19565"
protocol: TCP

View file

@ -0,0 +1,5 @@
apiVersion: v1
kind: Namespace
metadata:
name: minecraft
labels: {gateway.quorate.internal/allow-short: "true"}

View file

@ -0,0 +1,104 @@
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: minecraft
namespace: minecraft
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/name: minecraft
app.kubernetes.io/instance: skies
ingress:
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: grafana
app.kubernetes.io/name: grafana
app.kubernetes.io/instance: grafana
toPorts:
- ports:
- port: "25575"
protocol: TCP
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: victoriametrics
app.kubernetes.io/name: vmagent
app.kubernetes.io/instance: main
toPorts:
- ports:
- port: "19565"
protocol: TCP
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: short
app.kubernetes.io/name: tunnel
app.kubernetes.io/instance: short
toPorts:
- ports: [{port: "25565", protocol: TCP}]
- fromEntities: [host]
toPorts:
- ports:
- port: "25565"
protocol: TCP
- fromCIDR:
- 10.115.187.218/24
- 10.63.81.107/24
- 10.162.8.60/24
- 10.82.151.234/24
toPorts:
- ports:
- port: "25565"
protocol: TCP
egress:
- toFQDNs:
- matchName: s3.quorate.internal
toPorts:
- ports: [{port: "443", protocol: TCP}]
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: versitygw
app.kubernetes.io/name: versitygw
app.kubernetes.io/instance: versitygw
toPorts:
- ports: [{port: "7070", protocol: TCP}]
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
rules:
dns:
- matchName: sessionserver.mojang.com
- matchName: api.minecraftservices.com
- matchName: s3.quorate.internal
- toFQDNs:
- matchName: sessionserver.mojang.com
- matchName: api.minecraftservices.com
toPorts:
- ports:
- port: "443"
protocol: TCP
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: minecraft-artifacts
namespace: versitygw
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/name: versitygw
app.kubernetes.io/instance: versitygw
ingress:
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/instance: skies
toPorts:
- ports: [{port: "7070", protocol: TCP}]

View file

@ -0,0 +1,9 @@
apiVersion: gateway.networking.k8s.io/v1
kind: TCPRoute
metadata: {name: minecraft, namespace: minecraft}
spec:
parentRefs:
- {name: gateway-short, namespace: kube-system, sectionName: minecraft}
rules:
- backendRefs:
- {name: minecraft, port: 25565}

View file

@ -0,0 +1,36 @@
apiVersion: v1
kind: Service
metadata:
name: minecraft
namespace: minecraft
labels:
io.cilium/bgp-announce: "true"
annotations:
lbipam.cilium.io/ips: 10.197.181.214
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app.kubernetes.io/name: minecraft
app.kubernetes.io/instance: skies
ports:
- name: minecraft
port: 25565
targetPort: minecraft
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: minecraft-rcon
namespace: minecraft
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: minecraft
app.kubernetes.io/instance: skies
ports:
- name: rcon
port: 25575
targetPort: rcon
protocol: TCP

View file

@ -0,0 +1,23 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: minecraft
namespace: minecraft
spec:
accessModes: [ReadWriteOnce]
storageClassName: openebs-hostpath
resources:
requests:
storage: 50Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: minecraft-backups
namespace: minecraft
spec:
accessModes: [ReadWriteOnce]
storageClassName: openebs-zfspv-1m-zstd
resources:
requests:
storage: 100Gi

View file

@ -0,0 +1,148 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: minecraft-vso
namespace: minecraft
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: default
namespace: minecraft
spec:
method: kubernetes
mount: kubernetes
kubernetes:
role: minecraft
serviceAccount: minecraft-vso
vaultConnectionRef: vault/vault
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: minecraft-artifacts
namespace: minecraft
spec:
type: kv-v2
mount: secret
path: versitygw/users/minecraft
refreshAfter: 1h
destination:
name: minecraft-artifacts
create: true
transformation:
excludeRaw: true
excludes: [.*]
templates:
accesskey:
text: minecraft
secretkey:
text: '{{ get .Secrets "secretAccessKey" }}'
vaultAuthRef: default
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: minecraft-ca
namespace: minecraft
spec:
type: kv-v2
mount: secret
path: ca/internal
refreshAfter: 1h
destination:
name: minecraft-ca
create: true
transformation:
excludeRaw: true
vaultAuthRef: default
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: minecraft
namespace: minecraft
spec:
type: kv-v2
mount: secret
path: minecraft/server
destination:
name: minecraft
create: true
overwrite: true
refreshAfter: 1h
vaultAuthRef: default
rolloutRestartTargets:
- kind: Deployment
name: minecraft
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: minecraft-files
namespace: minecraft
spec:
type: kv-v2
mount: secret
path: minecraft/files
destination:
name: minecraft-files
create: true
overwrite: true
transformation:
excludeRaw: true
excludes: [.*]
templates:
server.properties:
text: '{{ get .Secrets "server.properties" }}'
refreshAfter: 1h
vaultAuthRef: default
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: minecraft-rcon
namespace: minecraft
spec:
type: kv-v2
mount: secret
path: minecraft/rcon
destination:
name: minecraft-rcon
create: true
transformation:
excludeRaw: true
excludes: [.*]
templates:
password:
text: '{{ get .Secrets "password" }}'
refreshAfter: 1h
vaultAuthRef: default
rolloutRestartTargets:
- kind: Deployment
name: minecraft
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: minecraft-pull
namespace: minecraft
spec:
type: kv-v2
mount: secret
path: quay/oauth/project-delivery-reader
refreshAfter: 5m
destination:
name: minecraft-pull
create: true
overwrite: true
type: kubernetes.io/dockerconfigjson
transformation:
excludeRaw: true
excludes: [.*]
templates:
.dockerconfigjson:
text: |
{{- $token := get .Secrets "token" -}}
{"auths":{"registry.quorate.internal":{"username":"$oauthtoken","password":"{{ $token }}","auth":"{{ printf "%s:%s" "$oauthtoken" $token | b64enc }}"}}}
vaultAuthRef: default