diff --git a/README.md b/README.md index 5863a87..b2cbc1f 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,35 @@ docker compose \ Read more: [Docker installation](docs/getting-started/docker.md) +### Kubernetes (Helm) + +A Helm chart lives in [`helm/incidentrelay`](helm/incidentrelay). It deploys the web UI plus the scheduler and Telegram workers, renders the application config from values into a Secret, and wires up the `/healthz` and `/readyz` probes. + +> **Note:** no public image is published yet — the default `image.repository` (`roxywi/incidentrelay`) does not exist on Docker Hub, so an out-of-the-box install ends in `ImagePullBackOff`. Build the image yourself, push it to your registry and set `image.repository` / `image.tag`. + +```bash +helm install incidentrelay ./helm/incidentrelay \ + --set image.repository=registry.example.com/incidentrelay \ + --set image.tag=1.0.15-beta \ + --set config.main.secret_key="$(openssl rand -hex 32)" +``` + +The default values use SQLite on a shared PersistentVolumeClaim. This is strictly a single-node setup: SQLite over network-backed `ReadWriteMany` storage (NFS and friends) is a known way to corrupt the database. Database migrations run on web pod start, so keep `web.replicaCount` at `1` (or disable `web.runMigrations` and migrate out of band). For anything multi-node or multi-replica, point `config.database` at PostgreSQL: + +```bash +helm install incidentrelay ./helm/incidentrelay \ + --set config.main.secret_key="$(openssl rand -hex 32)" \ + --set config.database.type=postgresql \ + --set config.database.host=postgres.example.svc \ + --set config.database.port=5432 \ + --set config.database.name=incidentrelay \ + --set config.database.user=incidentrelay \ + --set config.database.password=change-me \ + --set persistence.enabled=false +``` + +All settings from `incidentrelay.conf` are available under `config.*` in [values.yaml](helm/incidentrelay/values.yaml); you can also bring a pre-rendered config via `existingConfigSecret`. + ### RedHat-like distributions from RPM repository Recommended for RHEL, Rocky Linux, AlmaLinux, and CentOS Stream. diff --git a/helm/incidentrelay/.helmignore b/helm/incidentrelay/.helmignore new file mode 100644 index 0000000..e1ebf47 --- /dev/null +++ b/helm/incidentrelay/.helmignore @@ -0,0 +1,9 @@ +# Patterns to ignore when building packages. +*.tgz +.DS_Store +.git/ +.gitignore +*.swp +*.bak +*.tmp +*.orig diff --git a/helm/incidentrelay/Chart.yaml b/helm/incidentrelay/Chart.yaml new file mode 100644 index 0000000..0f3c2fa --- /dev/null +++ b/helm/incidentrelay/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +name: incidentrelay +description: On-call scheduling, alert routing and incident notification service +type: application +version: 0.1.0 +appVersion: "1.0.15-beta" +home: https://github.com/roxy-wi/IncidentRelay +sources: + - https://github.com/roxy-wi/IncidentRelay +keywords: + - oncall + - incident + - alerting + - notifications diff --git a/helm/incidentrelay/templates/NOTES.txt b/helm/incidentrelay/templates/NOTES.txt new file mode 100644 index 0000000..16f5e87 --- /dev/null +++ b/helm/incidentrelay/templates/NOTES.txt @@ -0,0 +1,44 @@ +IncidentRelay {{ .Chart.AppVersion }} has been deployed. + +Components: + web {{ .Values.web.replicaCount }} replica(s) + scheduler {{ .Values.scheduler.enabled | ternary "enabled" "disabled" }} + telegram {{ .Values.telegram.enabled | ternary "enabled" "disabled" }} + +Access the web UI: +{{- if .Values.ingress.enabled }} +{{- range .Values.ingress.hosts }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ .host }} +{{- end }} +{{- else }} + kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "incidentrelay.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }} + then open http://127.0.0.1:{{ .Values.service.port }} +{{- end }} + +{{- if eq .Values.image.repository "roxywi/incidentrelay" }} + +WARNING: image.repository is left at its default ("roxywi/incidentrelay"). +No public image is published under that name yet, so pods will sit in +ImagePullBackOff. Build the image yourself and set image.repository / +image.tag to your registry. +{{- end }} + +{{- $dbType := "" }} +{{- if .Values.config }}{{- if .Values.config.database }}{{- $dbType = .Values.config.database.type | default "" }}{{- end }}{{- end }} +{{- if eq ($dbType | toString) "sqlite" }} + +NOTE: you are running SQLite. All components share one +PersistentVolumeClaim, which is only safe while every pod runs on the +same node — SQLite over network-backed ReadWriteMany storage (NFS and +friends) is a known way to corrupt the database. For any multi-node +setup switch config.database to PostgreSQL. Migrations run on web pod +start: keep web.replicaCount at 1, or disable web.runMigrations and +migrate out of band before scaling. +{{- end }} + +{{- if not .Values.existingConfigSecret }} + +NOTE: the application config (including secret_key) is rendered from +values into Secret "{{ include "incidentrelay.configSecretName" . }}". +Change the default "change-me" values before exposing the service. +{{- end }} diff --git a/helm/incidentrelay/templates/_helpers.tpl b/helm/incidentrelay/templates/_helpers.tpl new file mode 100644 index 0000000..9e7f906 --- /dev/null +++ b/helm/incidentrelay/templates/_helpers.tpl @@ -0,0 +1,140 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "incidentrelay.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name (63 char limit). +*/}} +{{- define "incidentrelay.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 }} + +{{/* +Chart name and version for the chart label. +*/}} +{{- define "incidentrelay.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels. +*/}} +{{- define "incidentrelay.labels" -}} +helm.sh/chart: {{ include "incidentrelay.chart" . }} +{{ include "incidentrelay.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels. +*/}} +{{- define "incidentrelay.selectorLabels" -}} +app.kubernetes.io/name: {{ include "incidentrelay.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Service account name. +*/}} +{{- define "incidentrelay.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "incidentrelay.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Image reference. +*/}} +{{- define "incidentrelay.image" -}} +{{- printf "%s:%s" .Values.image.repository (default .Chart.AppVersion .Values.image.tag) }} +{{- end }} + +{{/* +Name of the Secret holding incidentrelay.conf. +*/}} +{{- define "incidentrelay.configSecretName" -}} +{{- default (printf "%s-config" (include "incidentrelay.fullname" .)) .Values.existingConfigSecret }} +{{- end }} + +{{/* +Render the values under .Values.config as an INI file. +*/}} +{{- define "incidentrelay.config" -}} +{{- range $section, $options := .Values.config }} +[{{ $section }}] +{{- range $key, $value := $options }} +{{ $key }} = {{ $value }} +{{- end }} +{{ end }} +{{- end }} + +{{/* +Name of the PVC backing /var/lib/incidentrelay. +*/}} +{{- define "incidentrelay.dataClaimName" -}} +{{- default (printf "%s-data" (include "incidentrelay.fullname" .)) .Values.persistence.existingClaim }} +{{- end }} + +{{/* +Volumes shared by every component. +*/}} +{{- define "incidentrelay.volumes" -}} +- name: config + secret: + secretName: {{ include "incidentrelay.configSecretName" . }} +- name: data + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ include "incidentrelay.dataClaimName" . }} + {{- else }} + emptyDir: {} + {{- end }} +- name: logs + emptyDir: {} +{{- with .Values.extraVolumes }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Volume mounts shared by every component. +*/}} +{{- define "incidentrelay.volumeMounts" -}} +- name: config + mountPath: /etc/incidentrelay + readOnly: true +- name: data + mountPath: /var/lib/incidentrelay +- name: logs + mountPath: /var/log/incidentrelay +{{- with .Values.extraVolumeMounts }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Pod annotation with the config checksum so config changes roll pods. +Empty when an existing Secret is used (the chart cannot see its content). +*/}} +{{- define "incidentrelay.configChecksum" -}} +{{- if not .Values.existingConfigSecret -}} +checksum/config: {{ include "incidentrelay.config" . | sha256sum }} +{{- end }} +{{- end }} diff --git a/helm/incidentrelay/templates/deployment-scheduler.yaml b/helm/incidentrelay/templates/deployment-scheduler.yaml new file mode 100644 index 0000000..42a940f --- /dev/null +++ b/helm/incidentrelay/templates/deployment-scheduler.yaml @@ -0,0 +1,80 @@ +{{- if .Values.scheduler.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "incidentrelay.fullname" . }}-scheduler + labels: + {{- include "incidentrelay.labels" . | nindent 4 }} + app.kubernetes.io/component: scheduler +spec: + replicas: 1 + {{- with .Values.scheduler.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "incidentrelay.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: scheduler + template: + metadata: + annotations: + {{- include "incidentrelay.configChecksum" . | nindent 8 }} + {{- with .Values.scheduler.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "incidentrelay.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: scheduler + {{- with .Values.scheduler.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "incidentrelay.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: scheduler + image: {{ include "incidentrelay.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: INCIDENTRELAY_CONFIG_FILE + value: /etc/incidentrelay/incidentrelay.conf + - name: INCIDENTRELAY_SERVICE + value: scheduler + - name: INCIDENTRELAY_RUN_MIGRATIONS + value: "0" + {{- with .Values.scheduler.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.scheduler.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + {{- include "incidentrelay.volumeMounts" . | nindent 12 }} + volumes: + {{- include "incidentrelay.volumes" . | nindent 8 }} + {{- with .Values.scheduler.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.scheduler.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.scheduler.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/helm/incidentrelay/templates/deployment-telegram.yaml b/helm/incidentrelay/templates/deployment-telegram.yaml new file mode 100644 index 0000000..b5225fe --- /dev/null +++ b/helm/incidentrelay/templates/deployment-telegram.yaml @@ -0,0 +1,82 @@ +{{- if .Values.telegram.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "incidentrelay.fullname" . }}-telegram + labels: + {{- include "incidentrelay.labels" . | nindent 4 }} + app.kubernetes.io/component: telegram +spec: + replicas: 1 + {{- with .Values.telegram.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "incidentrelay.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: telegram + template: + metadata: + annotations: + {{- include "incidentrelay.configChecksum" . | nindent 8 }} + {{- with .Values.telegram.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "incidentrelay.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: telegram + {{- with .Values.telegram.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "incidentrelay.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: telegram + image: {{ include "incidentrelay.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: INCIDENTRELAY_CONFIG_FILE + value: /etc/incidentrelay/incidentrelay.conf + - name: INCIDENTRELAY_SERVICE + value: telegram + - name: INCIDENTRELAY_RUN_MIGRATIONS + value: "0" + - name: PYTHONUNBUFFERED + value: "1" + {{- with .Values.telegram.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.telegram.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + {{- include "incidentrelay.volumeMounts" . | nindent 12 }} + volumes: + {{- include "incidentrelay.volumes" . | nindent 8 }} + {{- with .Values.telegram.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.telegram.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.telegram.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/helm/incidentrelay/templates/deployment-web.yaml b/helm/incidentrelay/templates/deployment-web.yaml new file mode 100644 index 0000000..00e164d --- /dev/null +++ b/helm/incidentrelay/templates/deployment-web.yaml @@ -0,0 +1,108 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "incidentrelay.fullname" . }}-web + labels: + {{- include "incidentrelay.labels" . | nindent 4 }} + app.kubernetes.io/component: web +spec: + replicas: {{ .Values.web.replicaCount }} + {{- with .Values.web.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "incidentrelay.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: web + template: + metadata: + annotations: + {{- include "incidentrelay.configChecksum" . | nindent 8 }} + {{- with .Values.web.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "incidentrelay.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: web + {{- with .Values.web.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "incidentrelay.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: web + image: {{ include "incidentrelay.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: INCIDENTRELAY_CONFIG_FILE + value: /etc/incidentrelay/incidentrelay.conf + - name: INCIDENTRELAY_SERVICE + value: web + - name: INCIDENTRELAY_RUN_MIGRATIONS + value: {{ .Values.web.runMigrations | ternary "1" "0" | quote }} + - name: INCIDENTRELAY_PORT + value: {{ .Values.web.port | quote }} + - name: INCIDENTRELAY_WEB_WORKERS + value: {{ .Values.web.gunicorn.workers | quote }} + - name: INCIDENTRELAY_WEB_THREADS + value: {{ .Values.web.gunicorn.threads | quote }} + - name: INCIDENTRELAY_WEB_TIMEOUT + value: {{ .Values.web.gunicorn.timeout | quote }} + {{- with .Values.web.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.web.port }} + protocol: TCP + startupProbe: + httpGet: + path: /healthz + port: http + periodSeconds: 5 + failureThreshold: 60 + livenessProbe: + httpGet: + path: /healthz + port: http + periodSeconds: 15 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /readyz + port: http + periodSeconds: 10 + timeoutSeconds: 5 + {{- with .Values.web.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + {{- include "incidentrelay.volumeMounts" . | nindent 12 }} + volumes: + {{- include "incidentrelay.volumes" . | nindent 8 }} + {{- with .Values.web.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.web.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.web.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/incidentrelay/templates/ingress.yaml b/helm/incidentrelay/templates/ingress.yaml new file mode 100644 index 0000000..1460e36 --- /dev/null +++ b/helm/incidentrelay/templates/ingress.yaml @@ -0,0 +1,41 @@ +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "incidentrelay.fullname" . }} + labels: + {{- include "incidentrelay.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- 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 "incidentrelay.fullname" $ }} + port: + name: http + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/incidentrelay/templates/pvc.yaml b/helm/incidentrelay/templates/pvc.yaml new file mode 100644 index 0000000..83b2bad --- /dev/null +++ b/helm/incidentrelay/templates/pvc.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "incidentrelay.dataClaimName" . }} + labels: + {{- include "incidentrelay.labels" . | nindent 4 }} + {{- with .Values.persistence.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + accessModes: + {{- toYaml .Values.persistence.accessModes | nindent 4 }} + resources: + requests: + storage: {{ .Values.persistence.size }} + {{- with .Values.persistence.storageClass }} + storageClassName: {{ . }} + {{- end }} +{{- end }} diff --git a/helm/incidentrelay/templates/secret-config.yaml b/helm/incidentrelay/templates/secret-config.yaml new file mode 100644 index 0000000..0edb9ef --- /dev/null +++ b/helm/incidentrelay/templates/secret-config.yaml @@ -0,0 +1,12 @@ +{{- if not .Values.existingConfigSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "incidentrelay.configSecretName" . }} + labels: + {{- include "incidentrelay.labels" . | nindent 4 }} +type: Opaque +stringData: + incidentrelay.conf: | + {{- include "incidentrelay.config" . | trim | nindent 4 }} +{{- end }} diff --git a/helm/incidentrelay/templates/service.yaml b/helm/incidentrelay/templates/service.yaml new file mode 100644 index 0000000..528e97a --- /dev/null +++ b/helm/incidentrelay/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "incidentrelay.fullname" . }} + labels: + {{- include "incidentrelay.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "incidentrelay.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: web diff --git a/helm/incidentrelay/templates/serviceaccount.yaml b/helm/incidentrelay/templates/serviceaccount.yaml new file mode 100644 index 0000000..e26c082 --- /dev/null +++ b/helm/incidentrelay/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "incidentrelay.serviceAccountName" . }} + labels: + {{- include "incidentrelay.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/helm/incidentrelay/values.yaml b/helm/incidentrelay/values.yaml new file mode 100644 index 0000000..3956440 --- /dev/null +++ b/helm/incidentrelay/values.yaml @@ -0,0 +1,159 @@ +# Default values for the IncidentRelay chart. + +image: + # NB: no public image is published under this name yet (neither + # Docker Hub nor GHCR) — installing with defaults ends in + # ImagePullBackOff. Build the image yourself and point repository/tag + # at your registry. + repository: roxywi/incidentrelay + # Defaults to the chart appVersion when empty. + tag: "" + pullPolicy: IfNotPresent + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + create: true + annotations: {} + # Defaults to the fullname when empty. + name: "" + +# IncidentRelay reads every setting from a single INI file mounted at +# /etc/incidentrelay/incidentrelay.conf. The map below is rendered into +# that file verbatim: top-level keys become INI sections, nested keys +# become options. It is stored as a Secret because it carries credentials +# (secret_key, database password, SMTP password, VAPID keys, ...). +config: + main: + secret_key: change-me + server: + host: 0.0.0.0 + port: 8080 + public_base_url: http://localhost:8080 + # SQLite works out of the box but requires the shared data volume below; + # with more than one node, switch to PostgreSQL: + # database: + # type: postgresql + # host: postgres.example.svc + # port: 5432 + # name: incidentrelay + # user: incidentrelay + # password: change-me + # NB: the SQLite file location option is `name` (not `path` — the app + # ignores `path`, see Config.DB_NAME in app/settings.py). + database: + type: sqlite + name: /var/lib/incidentrelay/incidentrelay.db + sqlite: + wal: true + busy_timeout: 5000 + logging: + level: INFO + file: /var/log/incidentrelay/incidentrelay.log + scheduler_file: /var/log/incidentrelay/incidentrelay-scheduler.log + telegram_worker_file: /var/log/incidentrelay/incidentrelay-telegram-worker.log + voice: + provider: stub + providers_dir: /usr/local/lib/incidentrelay/voice_providers + callback_secret: change-me + +# Name of an existing Secret holding the full config under the key +# `incidentrelay.conf`. When set, the `config` map above is ignored and +# no Secret is rendered by the chart. +existingConfigSecret: "" + +# Persistent storage for /var/lib/incidentrelay (the SQLite database). +# Every enabled component mounts this volume, which is only safe while +# all pods land on one node: SQLite over network-backed ReadWriteMany +# storage (NFS and friends) is a known way to corrupt the database. +# For anything multi-node switch config.database to PostgreSQL and +# disable persistence. +persistence: + enabled: true + accessModes: + - ReadWriteOnce + size: 1Gi + # Empty means the cluster default storage class. + storageClass: "" + # Use a pre-existing PVC instead of creating one. + existingClaim: "" + annotations: {} + +web: + replicaCount: 1 + # Recreate is the safe default while SQLite lives on the shared PVC: + # it prevents the old and new pod from writing one database file + # during a rollout (and a rollout deadlock on RWO volumes). With + # PostgreSQL feel free to switch to RollingUpdate. + strategy: + type: Recreate + # Run database migrations in the entrypoint before gunicorn starts. + # Keep replicaCount at 1 while this is on: several pods starting at + # once would race on the migrations. To scale web, set this to false + # and run migrations out of band (`python app/migrate.py migrate`). + runMigrations: true + port: 8080 + gunicorn: + workers: 1 + threads: 4 + timeout: 120 + resources: {} + podAnnotations: {} + podLabels: {} + nodeSelector: {} + tolerations: [] + affinity: {} + extraEnv: [] + +# Background worker that evaluates schedules, reminders and escalations. +scheduler: + enabled: true + strategy: + type: Recreate + resources: {} + podAnnotations: {} + podLabels: {} + nodeSelector: {} + tolerations: [] + affinity: {} + extraEnv: [] + +# Long-polling worker for Telegram callback buttons. Harmless without a +# configured bot (it idles), disable it if you do not use Telegram. +telegram: + enabled: true + strategy: + type: Recreate + resources: {} + podAnnotations: {} + podLabels: {} + nodeSelector: {} + tolerations: [] + affinity: {} + extraEnv: [] + +service: + type: ClusterIP + port: 8080 + annotations: {} + +ingress: + enabled: false + className: "" + annotations: {} + hosts: + - host: incidentrelay.local + paths: + - path: / + pathType: Prefix + tls: [] + +podSecurityContext: {} +securityContext: {} + +# Extra volumes / mounts added to every component, e.g. custom voice +# provider plugins for /usr/local/lib/incidentrelay/voice_providers. +extraVolumes: [] +extraVolumeMounts: []