feat: at helm deployment

This commit is contained in:
Morten Olsen
2025-10-18 00:01:58 +02:00
parent 1f7837cabc
commit 47a8dd96c2
26 changed files with 2080 additions and 73 deletions

6
chart/Chart.yaml Normal file
View File

@@ -0,0 +1,6 @@
apiVersion: v2
name: backbone
description: A Helm chart for deploying the backbone server
type: application
version: 0.2.0
appVersion: '1.0.0'

View File

@@ -0,0 +1,60 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "backbone.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "backbone.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "backbone.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "backbone.labels" -}}
helm.sh/chart: {{ include "backbone.chart" . }}
{{ include "backbone.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "backbone.selectorLabels" -}}
app.kubernetes.io/name: {{ include "backbone.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "backbone.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "backbone.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,16 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "backbone.fullname" . }}
labels:
{{- include "backbone.labels" . | nindent 4 }}
rules:
- apiGroups: ['']
resources: ['secrets']
verbs: ['create', 'get', 'watch', 'list']
- apiGroups: ['backbone.mortenolsen.pro']
resources: ['*']
verbs: ['get', 'watch', 'list', 'patch', 'create', 'update', 'replace']
- apiGroups: ['apiextensions.k8s.io']
resources: ['customresourcedefinitions']
verbs: ['get', 'create', 'update', 'replace', 'patch']

View File

@@ -0,0 +1,14 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "backbone.fullname" . }}
labels:
{{- include "backbone.labels" . | nindent 4 }}
subjects:
- kind: ServiceAccount
name: {{ include "backbone.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: {{ include "backbone.fullname" . }}
apiGroup: rbac.authorization.k8s.io

View File

@@ -0,0 +1,133 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "backbone.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "backbone.labels" . | nindent 4 }}
spec:
replicas: 1
selector:
matchLabels:
{{- include "backbone.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "backbone.selectorLabels" . | nindent 8 }}
spec:
serviceAccountName: {{ include "backbone.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
ports:
- name: http
containerPort: {{ .Values.config.httpPort }}
protocol: TCP
- name: tcp
containerPort: {{ .Values.config.tcpPort }}
protocol: TCP
env:
- name: TZ
value: {{ .Values.timezone | quote }}
{{- if .Values.config.adminToken }}
- name: ADMIN_TOKEN
value: {{ .Values.config.adminToken | quote }}
{{- end }}
{{- if .Values.config.jwtSecret }}
- name: JWT_SECRET
value: {{ .Values.config.jwtSecret | quote }}
{{- end }}
- name: HTTP_PORT
value: {{ .Values.config.httpPort | quote }}
- name: TCP_PORT
value: {{ .Values.config.tcpPort | quote }}
- name: K8S_ENABLED
value: {{ .Values.k8s.enabled | quote }}
- name: WS_ENABLED
value: {{ .Values.ws.enabled | quote }}
- name: API_ENABLED
value: {{ .Values.api.enabled | quote }}
- name: TCP_ENABLED
value: {{ .Values.tcp.enabled | quote }}
{{- if .Values.oidc.enabled }}
- name: OIDC_ENABLED
value: "true"
- name: OIDC_DISCOVERY
value: {{ .Values.oidc.discovery | quote }}
- name: OIDC_CLIENT_ID
value: {{ .Values.oidc.clientId | quote }}
- name: OIDC_CLIENT_SECRET
value: {{ .Values.oidc.clientSecret | quote }}
- name: OIDC_GROUP_FIELD
value: {{ .Values.oidc.groupField | quote }}
{{- if .Values.oidc.adminGroup }}
- name: OIDC_ADMIN_GROUP
value: {{ .Values.oidc.adminGroup | quote }}
{{- end }}
{{- if .Values.oidc.writerGroup }}
- name: OIDC_WRITER_GROUP
value: {{ .Values.oidc.writerGroup | quote }}
{{- end }}
{{- if .Values.oidc.readerGroup }}
- name: OIDC_READER_GROUP
value: {{ .Values.oidc.readerGroup | quote }}
{{- end }}
{{- end }}
{{- if .Values.redis.enabled }}
- name: REDIS_ENABLED
value: "true"
- name: REDIS_HOST
value: {{ .Values.redis.host | quote }}
- name: REDIS_PORT
value: {{ .Values.redis.port | quote }}
{{- if .Values.redis.password }}
- name: REDIS_PASSWORD
value: {{ .Values.redis.password | quote }}
{{- end }}
- name: REDIS_DB
value: {{ .Values.redis.db | quote }}
{{- end }}
{{- if .Values.persistence.enabled }}
volumeMounts:
- name: data
mountPath: /data
{{- end }}
{{- if .Values.probes.liveness.enabled }}
livenessProbe:
{{- omit .Values.probes.liveness "enabled" | toYaml | nindent 12 }}
{{- end }}
{{- if .Values.probes.readiness.enabled }}
readinessProbe:
{{- omit .Values.probes.readiness "enabled" | toYaml | nindent 12 }}
{{- end }}
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.persistence.enabled }}
volumes:
- name: data
persistentVolumeClaim:
claimName: {{ include "backbone.fullname" . }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@@ -0,0 +1,14 @@
{{- if .Values.httpService.enabled -}}
apiVersion: homelab.mortenolsen.pro/v1
kind: HttpService
metadata:
name: '{{ include "backbone.fullname" . }}'
namespace: '{{ .Release.Namespace }}'
spec:
environment: '{{ .Values.httpService.environment }}'
subdomain: '{{ .Values.httpService.subdomain }}'
destination:
host: '{{ include "backbone.fullname" . }}'
port:
number: 80
{{- end }}

View File

@@ -0,0 +1,42 @@
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "backbone.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "backbone.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "backbone.fullname" $ }}-http
port:
number: {{ $.Values.service.http.port }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,22 @@
{{- if .Values.persistence.enabled -}}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "backbone.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "backbone.labels" . | nindent 4 }}
{{- with .Values.persistence.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
accessModes:
- {{ .Values.persistence.accessMode }}
{{- if .Values.persistence.storageClass }}
storageClassName: {{ .Values.persistence.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.size }}
{{- end }}

View File

@@ -0,0 +1,13 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "backbone.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "backbone.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,42 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "backbone.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "backbone.labels" . | nindent 4 }}
{{- with .Values.service.http.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.http.type }}
ports:
- port: {{ .Values.service.http.port }}
targetPort: {{ .Values.service.http.targetPort }}
protocol: TCP
name: http
selector:
{{- include "backbone.selectorLabels" . | nindent 4 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "backbone.fullname" . }}-tcp
namespace: {{ .Release.Namespace }}
labels:
{{- include "backbone.labels" . | nindent 4 }}
{{- with .Values.service.tcp.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.tcp.type }}
ports:
- port: {{ .Values.service.tcp.port }}
targetPort: {{ .Values.service.tcp.targetPort }}
protocol: TCP
name: tcp
selector:
{{- include "backbone.selectorLabels" . | nindent 4 }}

125
chart/values.yaml Normal file
View File

@@ -0,0 +1,125 @@
image:
repository: ghcr.io/morten-olsen/backbone
tag: main
pullPolicy: IfNotPresent
nameOverride: ''
fullnameOverride: ''
serviceAccount:
create: true
annotations: {}
name: ''
httpService:
enabled: false
subdomain: backbone
environment: ''
config:
adminToken: ''
jwtSecret: ''
httpPort: 8883
tcpPort: 1883
k8s:
enabled: true
ws:
enabled: true
api:
enabled: true
tcp:
enabled: true
oidc:
enabled: false
discovery: ''
clientId: ''
clientSecret: ''
groupField: 'groups'
adminGroup: ''
writerGroup: ''
readerGroup: ''
redis:
enabled: false
host: 'localhost'
port: 6379
password: ''
db: 0
persistence:
enabled: false
storageClass: ''
accessMode: ReadWriteOnce
size: 1Gi
annotations: {}
service:
http:
type: ClusterIP
port: 80
targetPort: 8883
annotations: {}
tcp:
type: ClusterIP
port: 1883
targetPort: 1883
annotations: {}
ingress:
enabled: false
className: ''
annotations: {}
hosts:
- host: chart-example.local
paths:
- path: /
pathType: Prefix
tls: []
resources: {}
probes:
liveness:
enabled: true
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readiness:
enabled: true
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
timezone: Europe/Amsterdam