feat: project skeleton
- infra (k8s, kind, helm, docker) backbone is implemented - security: implementation + unit tests are done
This commit is contained in:
15
helm/incidentops/Chart.yaml
Normal file
15
helm/incidentops/Chart.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v2
|
||||
name: incidentops
|
||||
description: A Helm chart for IncidentOps - Incident Management Platform
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "0.1.0"
|
||||
|
||||
keywords:
|
||||
- incidentops
|
||||
- incident-management
|
||||
- on-call
|
||||
- alerting
|
||||
|
||||
maintainers:
|
||||
- name: IncidentOps Team
|
||||
33
helm/incidentops/templates/NOTES.txt
Normal file
33
helm/incidentops/templates/NOTES.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
IncidentOps has been deployed!
|
||||
|
||||
{{- if .Values.ingress.enabled }}
|
||||
|
||||
Access the application at:
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ .Values.ingress.host }}
|
||||
|
||||
{{- else }}
|
||||
|
||||
To access the application, run:
|
||||
|
||||
API:
|
||||
kubectl port-forward svc/{{ include "incidentops.fullname" . }}-api {{ .Values.api.service.port }}:{{ .Values.api.service.port }} -n {{ .Release.Namespace }}
|
||||
Then open: http://localhost:{{ .Values.api.service.port }}
|
||||
|
||||
Web:
|
||||
kubectl port-forward svc/{{ include "incidentops.fullname" . }}-web {{ .Values.web.service.port }}:{{ .Values.web.service.port }} -n {{ .Release.Namespace }}
|
||||
Then open: http://localhost:{{ .Values.web.service.port }}
|
||||
|
||||
{{- end }}
|
||||
|
||||
To check the status of your deployment:
|
||||
kubectl get pods -n {{ .Release.Namespace }} -l "app.kubernetes.io/instance={{ .Release.Name }}"
|
||||
|
||||
{{- if .Values.migration.enabled }}
|
||||
|
||||
Database migrations will run automatically as a Helm hook.
|
||||
Check migration status:
|
||||
kubectl get jobs -n {{ .Release.Namespace }} -l "app.kubernetes.io/component=migration"
|
||||
|
||||
{{- end }}
|
||||
|
||||
For more information, visit the documentation.
|
||||
218
helm/incidentops/templates/_helpers.tpl
Normal file
218
helm/incidentops/templates/_helpers.tpl
Normal file
@@ -0,0 +1,218 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "incidentops.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
*/}}
|
||||
{{- define "incidentops.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 "incidentops.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "incidentops.labels" -}}
|
||||
helm.sh/chart: {{ include "incidentops.chart" . }}
|
||||
{{ include "incidentops.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "incidentops.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "incidentops.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
API labels
|
||||
*/}}
|
||||
{{- define "incidentops.api.labels" -}}
|
||||
{{ include "incidentops.labels" . }}
|
||||
app.kubernetes.io/component: api
|
||||
{{- end }}
|
||||
|
||||
{{- define "incidentops.api.selectorLabels" -}}
|
||||
{{ include "incidentops.selectorLabels" . }}
|
||||
app.kubernetes.io/component: api
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Worker labels
|
||||
*/}}
|
||||
{{- define "incidentops.worker.labels" -}}
|
||||
{{ include "incidentops.labels" . }}
|
||||
app.kubernetes.io/component: worker
|
||||
{{- end }}
|
||||
|
||||
{{- define "incidentops.worker.selectorLabels" -}}
|
||||
{{ include "incidentops.selectorLabels" . }}
|
||||
app.kubernetes.io/component: worker
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Web labels
|
||||
*/}}
|
||||
{{- define "incidentops.web.labels" -}}
|
||||
{{ include "incidentops.labels" . }}
|
||||
app.kubernetes.io/component: web
|
||||
{{- end }}
|
||||
|
||||
{{- define "incidentops.web.selectorLabels" -}}
|
||||
{{ include "incidentops.selectorLabels" . }}
|
||||
app.kubernetes.io/component: web
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "incidentops.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "incidentops.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
PostgreSQL host
|
||||
*/}}
|
||||
{{- define "incidentops.postgresql.host" -}}
|
||||
{{- if .Values.postgresql.enabled }}
|
||||
{{- printf "%s-postgresql" (include "incidentops.fullname" .) }}
|
||||
{{- else }}
|
||||
{{- .Values.externalDatabase.host }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
PostgreSQL port
|
||||
*/}}
|
||||
{{- define "incidentops.postgresql.port" -}}
|
||||
{{- if .Values.postgresql.enabled }}
|
||||
{{- printf "5432" }}
|
||||
{{- else }}
|
||||
{{- .Values.externalDatabase.port | default "5432" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Database URL
|
||||
*/}}
|
||||
{{- define "incidentops.databaseUrl" -}}
|
||||
{{- $host := include "incidentops.postgresql.host" . }}
|
||||
{{- $port := include "incidentops.postgresql.port" . }}
|
||||
{{- if .Values.postgresql.enabled }}
|
||||
{{- printf "postgresql://%s:%s@%s:%s/%s" .Values.postgresql.auth.username .Values.postgresql.auth.password $host $port .Values.postgresql.auth.database }}
|
||||
{{- else }}
|
||||
{{- printf "postgresql://%s:%s@%s:%s/%s" .Values.externalDatabase.user .Values.externalDatabase.password $host $port .Values.externalDatabase.database }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Redis host
|
||||
*/}}
|
||||
{{- define "incidentops.redis.host" -}}
|
||||
{{- if .Values.redis.enabled }}
|
||||
{{- printf "%s-redis" (include "incidentops.fullname" .) }}
|
||||
{{- else }}
|
||||
{{- .Values.externalRedis.host }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Redis URL
|
||||
*/}}
|
||||
{{- define "incidentops.redisUrl" -}}
|
||||
{{- $host := include "incidentops.redis.host" . }}
|
||||
{{- if .Values.redis.enabled }}
|
||||
{{- printf "redis://%s:6379/0" $host }}
|
||||
{{- else }}
|
||||
{{- printf "redis://%s:%s/%s" $host (.Values.externalRedis.port | default "6379") (.Values.externalRedis.database | default "0") }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Celery broker URL
|
||||
*/}}
|
||||
{{- define "incidentops.celeryBrokerUrl" -}}
|
||||
{{ include "incidentops.redisUrl" . }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Celery result backend URL
|
||||
*/}}
|
||||
{{- define "incidentops.celeryResultBackend" -}}
|
||||
{{- $host := include "incidentops.redis.host" . }}
|
||||
{{- if .Values.redis.enabled }}
|
||||
{{- printf "redis://%s:6379/1" $host }}
|
||||
{{- else }}
|
||||
{{- printf "redis://%s:%s/%s" $host (.Values.externalRedis.port | default "6379") (add (.Values.externalRedis.database | default 0) 1) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
API image
|
||||
*/}}
|
||||
{{- define "incidentops.api.image" -}}
|
||||
{{- $registry := .Values.global.imageRegistry | default "" }}
|
||||
{{- $repository := .Values.api.image.repository }}
|
||||
{{- $tag := .Values.api.image.tag | default .Chart.AppVersion }}
|
||||
{{- if $registry }}
|
||||
{{- printf "%s/%s:%s" $registry $repository $tag }}
|
||||
{{- else }}
|
||||
{{- printf "%s:%s" $repository $tag }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Worker image
|
||||
*/}}
|
||||
{{- define "incidentops.worker.image" -}}
|
||||
{{- $registry := .Values.global.imageRegistry | default "" }}
|
||||
{{- $repository := .Values.worker.image.repository }}
|
||||
{{- $tag := .Values.worker.image.tag | default .Chart.AppVersion }}
|
||||
{{- if $registry }}
|
||||
{{- printf "%s/%s:%s" $registry $repository $tag }}
|
||||
{{- else }}
|
||||
{{- printf "%s:%s" $repository $tag }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Web image
|
||||
*/}}
|
||||
{{- define "incidentops.web.image" -}}
|
||||
{{- $registry := .Values.global.imageRegistry | default "" }}
|
||||
{{- $repository := .Values.web.image.repository }}
|
||||
{{- $tag := .Values.web.image.tag | default .Chart.AppVersion }}
|
||||
{{- if $registry }}
|
||||
{{- printf "%s/%s:%s" $registry $repository $tag }}
|
||||
{{- else }}
|
||||
{{- printf "%s:%s" $repository $tag }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
76
helm/incidentops/templates/api-deployment.yaml
Normal file
76
helm/incidentops/templates/api-deployment.yaml
Normal file
@@ -0,0 +1,76 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-api
|
||||
labels:
|
||||
{{- include "incidentops.api.labels" . | nindent 4 }}
|
||||
spec:
|
||||
{{- if not .Values.api.autoscaling.enabled }}
|
||||
replicas: {{ .Values.api.replicaCount }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "incidentops.api.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
|
||||
{{- with .Values.api.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "incidentops.api.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.global.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "incidentops.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: api
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: {{ include "incidentops.api.image" . }}
|
||||
imagePullPolicy: {{ .Values.api.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8000
|
||||
protocol: TCP
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: {{ include "incidentops.fullname" . }}-config
|
||||
- secretRef:
|
||||
name: {{ include "incidentops.fullname" . }}-secret
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /v1/healthz
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /v1/readyz
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
resources:
|
||||
{{- toYaml .Values.api.resources | nindent 12 }}
|
||||
{{- with .Values.api.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.api.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.api.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
22
helm/incidentops/templates/api-hpa.yaml
Normal file
22
helm/incidentops/templates/api-hpa.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
{{- if .Values.api.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-api
|
||||
labels:
|
||||
{{- include "incidentops.api.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "incidentops.fullname" . }}-api
|
||||
minReplicas: {{ .Values.api.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.api.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.api.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
15
helm/incidentops/templates/api-service.yaml
Normal file
15
helm/incidentops/templates/api-service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-api
|
||||
labels:
|
||||
{{- include "incidentops.api.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.api.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.api.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "incidentops.api.selectorLabels" . | nindent 4 }}
|
||||
10
helm/incidentops/templates/configmap.yaml
Normal file
10
helm/incidentops/templates/configmap.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-config
|
||||
labels:
|
||||
{{- include "incidentops.labels" . | nindent 4 }}
|
||||
data:
|
||||
JWT_ALGORITHM: {{ .Values.config.jwtAlgorithm | quote }}
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: {{ .Values.config.accessTokenExpireMinutes | quote }}
|
||||
REFRESH_TOKEN_EXPIRE_DAYS: {{ .Values.config.refreshTokenExpireDays | quote }}
|
||||
51
helm/incidentops/templates/ingress.yaml
Normal file
51
helm/incidentops/templates/ingress.yaml
Normal file
@@ -0,0 +1,51 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}
|
||||
labels:
|
||||
{{- include "incidentops.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:
|
||||
- host: {{ .Values.ingress.host | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: /api
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "incidentops.fullname" . }}-api
|
||||
port:
|
||||
number: {{ .Values.api.service.port }}
|
||||
- path: /v1
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "incidentops.fullname" . }}-api
|
||||
port:
|
||||
number: {{ .Values.api.service.port }}
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "incidentops.fullname" . }}-web
|
||||
port:
|
||||
number: {{ .Values.web.service.port }}
|
||||
{{- end }}
|
||||
49
helm/incidentops/templates/migrate-job.yaml
Normal file
49
helm/incidentops/templates/migrate-job.yaml
Normal file
@@ -0,0 +1,49 @@
|
||||
{{- if .Values.migration.enabled }}
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-migrate
|
||||
labels:
|
||||
{{- include "incidentops.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: migration
|
||||
annotations:
|
||||
"helm.sh/hook": post-install,post-upgrade
|
||||
"helm.sh/hook-weight": "-5"
|
||||
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
||||
spec:
|
||||
backoffLimit: {{ .Values.migration.backoffLimit }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "incidentops.selectorLabels" . | nindent 8 }}
|
||||
app.kubernetes.io/component: migration
|
||||
spec:
|
||||
{{- with .Values.global.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "incidentops.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- name: migrate
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: {{ include "incidentops.api.image" . }}
|
||||
imagePullPolicy: {{ .Values.migration.image.pullPolicy }}
|
||||
command:
|
||||
- python
|
||||
- migrations/migrate.py
|
||||
- apply
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ include "incidentops.fullname" . }}-secret
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
{{- end }}
|
||||
91
helm/incidentops/templates/postgres-deployment.yaml
Normal file
91
helm/incidentops/templates/postgres-deployment.yaml
Normal file
@@ -0,0 +1,91 @@
|
||||
{{- if .Values.postgresql.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-postgresql
|
||||
labels:
|
||||
{{- include "incidentops.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: postgresql
|
||||
spec:
|
||||
serviceName: {{ include "incidentops.fullname" . }}-postgresql
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "incidentops.selectorLabels" . | nindent 6 }}
|
||||
app.kubernetes.io/component: postgresql
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "incidentops.selectorLabels" . | nindent 8 }}
|
||||
app.kubernetes.io/component: postgresql
|
||||
spec:
|
||||
containers:
|
||||
- name: postgresql
|
||||
image: "{{ .Values.postgresql.image.repository }}:{{ .Values.postgresql.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.postgresql.image.pullPolicy }}
|
||||
ports:
|
||||
- name: postgresql
|
||||
containerPort: 5432
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
value: {{ .Values.postgresql.auth.username | quote }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
value: {{ .Values.postgresql.auth.password | quote }}
|
||||
- name: POSTGRES_DB
|
||||
value: {{ .Values.postgresql.auth.database | quote }}
|
||||
- name: PGDATA
|
||||
value: /var/lib/postgresql/data/pgdata
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/postgresql/data
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- pg_isready
|
||||
- -U
|
||||
- {{ .Values.postgresql.auth.username }}
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- pg_isready
|
||||
- -U
|
||||
- {{ .Values.postgresql.auth.username }}
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
resources:
|
||||
{{- toYaml .Values.postgresql.resources | nindent 12 }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.postgresql.persistence.size }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-postgresql
|
||||
labels:
|
||||
{{- include "incidentops.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: postgresql
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 5432
|
||||
targetPort: postgresql
|
||||
protocol: TCP
|
||||
name: postgresql
|
||||
selector:
|
||||
{{- include "incidentops.selectorLabels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: postgresql
|
||||
{{- end }}
|
||||
80
helm/incidentops/templates/redis-deployment.yaml
Normal file
80
helm/incidentops/templates/redis-deployment.yaml
Normal file
@@ -0,0 +1,80 @@
|
||||
{{- if .Values.redis.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-redis
|
||||
labels:
|
||||
{{- include "incidentops.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: redis
|
||||
spec:
|
||||
serviceName: {{ include "incidentops.fullname" . }}-redis
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "incidentops.selectorLabels" . | nindent 6 }}
|
||||
app.kubernetes.io/component: redis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "incidentops.selectorLabels" . | nindent 8 }}
|
||||
app.kubernetes.io/component: redis
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: "{{ .Values.redis.image.repository }}:{{ .Values.redis.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.redis.image.pullPolicy }}
|
||||
ports:
|
||||
- name: redis
|
||||
containerPort: 6379
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- redis-cli
|
||||
- ping
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- redis-cli
|
||||
- ping
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
resources:
|
||||
{{- toYaml .Values.redis.resources | nindent 12 }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.redis.persistence.size }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-redis
|
||||
labels:
|
||||
{{- include "incidentops.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: redis
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 6379
|
||||
targetPort: redis
|
||||
protocol: TCP
|
||||
name: redis
|
||||
selector:
|
||||
{{- include "incidentops.selectorLabels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: redis
|
||||
{{- end }}
|
||||
13
helm/incidentops/templates/secret.yaml
Normal file
13
helm/incidentops/templates/secret.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-secret
|
||||
labels:
|
||||
{{- include "incidentops.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
DATABASE_URL: {{ include "incidentops.databaseUrl" . | quote }}
|
||||
REDIS_URL: {{ include "incidentops.redisUrl" . | quote }}
|
||||
CELERY_BROKER_URL: {{ include "incidentops.celeryBrokerUrl" . | quote }}
|
||||
CELERY_RESULT_BACKEND: {{ include "incidentops.celeryResultBackend" . | quote }}
|
||||
JWT_SECRET_KEY: {{ .Values.secrets.jwtSecretKey | quote }}
|
||||
12
helm/incidentops/templates/serviceaccount.yaml
Normal file
12
helm/incidentops/templates/serviceaccount.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "incidentops.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "incidentops.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
72
helm/incidentops/templates/web-deployment.yaml
Normal file
72
helm/incidentops/templates/web-deployment.yaml
Normal file
@@ -0,0 +1,72 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-web
|
||||
labels:
|
||||
{{- include "incidentops.web.labels" . | nindent 4 }}
|
||||
spec:
|
||||
{{- if not .Values.web.autoscaling.enabled }}
|
||||
replicas: {{ .Values.web.replicaCount }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "incidentops.web.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.web.podAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "incidentops.web.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.global.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "incidentops.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: web
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: {{ include "incidentops.web.image" . }}
|
||||
imagePullPolicy: {{ .Values.web.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 3000
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: NEXT_PUBLIC_API_URL
|
||||
value: "http://{{ include "incidentops.fullname" . }}-api:{{ .Values.api.service.port }}"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
resources:
|
||||
{{- toYaml .Values.web.resources | nindent 12 }}
|
||||
{{- 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 }}
|
||||
22
helm/incidentops/templates/web-hpa.yaml
Normal file
22
helm/incidentops/templates/web-hpa.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
{{- if .Values.web.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-web
|
||||
labels:
|
||||
{{- include "incidentops.web.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "incidentops.fullname" . }}-web
|
||||
minReplicas: {{ .Values.web.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.web.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.web.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
15
helm/incidentops/templates/web-service.yaml
Normal file
15
helm/incidentops/templates/web-service.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-web
|
||||
labels:
|
||||
{{- include "incidentops.web.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.web.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.web.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "incidentops.web.selectorLabels" . | nindent 4 }}
|
||||
79
helm/incidentops/templates/worker-deployment.yaml
Normal file
79
helm/incidentops/templates/worker-deployment.yaml
Normal file
@@ -0,0 +1,79 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-worker
|
||||
labels:
|
||||
{{- include "incidentops.worker.labels" . | nindent 4 }}
|
||||
spec:
|
||||
{{- if not .Values.worker.autoscaling.enabled }}
|
||||
replicas: {{ .Values.worker.replicaCount }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "incidentops.worker.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
|
||||
{{- with .Values.worker.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "incidentops.worker.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.global.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "incidentops.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: worker
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: {{ include "incidentops.worker.image" . }}
|
||||
imagePullPolicy: {{ .Values.worker.image.pullPolicy }}
|
||||
command:
|
||||
- celery
|
||||
- -A
|
||||
- worker.celery_app
|
||||
- worker
|
||||
- --loglevel=info
|
||||
- -Q
|
||||
- {{ .Values.worker.queues }}
|
||||
- --concurrency={{ .Values.worker.concurrency }}
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: {{ include "incidentops.fullname" . }}-config
|
||||
- secretRef:
|
||||
name: {{ include "incidentops.fullname" . }}-secret
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- celery
|
||||
- -A
|
||||
- worker.celery_app
|
||||
- inspect
|
||||
- ping
|
||||
- -d
|
||||
- celery@$HOSTNAME
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 60
|
||||
timeoutSeconds: 10
|
||||
failureThreshold: 3
|
||||
resources:
|
||||
{{- toYaml .Values.worker.resources | nindent 12 }}
|
||||
{{- with .Values.worker.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.worker.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.worker.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
22
helm/incidentops/templates/worker-hpa.yaml
Normal file
22
helm/incidentops/templates/worker-hpa.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
{{- if .Values.worker.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "incidentops.fullname" . }}-worker
|
||||
labels:
|
||||
{{- include "incidentops.worker.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "incidentops.fullname" . }}-worker
|
||||
minReplicas: {{ .Values.worker.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.worker.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.worker.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
82
helm/incidentops/values-production.yaml
Normal file
82
helm/incidentops/values-production.yaml
Normal file
@@ -0,0 +1,82 @@
|
||||
# Production values for incidentops
|
||||
# Use external secrets management in production
|
||||
|
||||
api:
|
||||
replicaCount: 3
|
||||
autoscaling:
|
||||
enabled: true
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 70
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
|
||||
worker:
|
||||
replicaCount: 3
|
||||
autoscaling:
|
||||
enabled: true
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 70
|
||||
concurrency: 8
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
|
||||
web:
|
||||
replicaCount: 3
|
||||
autoscaling:
|
||||
enabled: true
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 70
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
className: nginx
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
host: incidentops.example.com
|
||||
tls:
|
||||
- secretName: incidentops-tls
|
||||
hosts:
|
||||
- incidentops.example.com
|
||||
|
||||
postgresql:
|
||||
persistence:
|
||||
size: 50Gi
|
||||
resources:
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 1Gi
|
||||
limits:
|
||||
cpu: 2000m
|
||||
memory: 4Gi
|
||||
|
||||
redis:
|
||||
persistence:
|
||||
size: 10Gi
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
163
helm/incidentops/values.yaml
Normal file
163
helm/incidentops/values.yaml
Normal file
@@ -0,0 +1,163 @@
|
||||
# Default values for incidentops
|
||||
|
||||
global:
|
||||
imageRegistry: ""
|
||||
imagePullSecrets: []
|
||||
|
||||
api:
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: incidentops/api
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 8000
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
podAnnotations: {}
|
||||
nodeSelector: {}
|
||||
tolerations: []
|
||||
affinity: {}
|
||||
|
||||
# Worker Service (Celery)
|
||||
worker:
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: incidentops/worker
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
queues: "critical,default,low"
|
||||
concurrency: 4
|
||||
podAnnotations: {}
|
||||
nodeSelector: {}
|
||||
tolerations: []
|
||||
affinity: {}
|
||||
|
||||
# Web Frontend (Next.js)
|
||||
web:
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: incidentops/web
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 3000
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
podAnnotations: {}
|
||||
nodeSelector: {}
|
||||
tolerations: []
|
||||
affinity: {}
|
||||
|
||||
# Ingress configuration
|
||||
ingress:
|
||||
enabled: true
|
||||
className: nginx
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
|
||||
host: incidentops.local
|
||||
tls: []
|
||||
|
||||
# Database migration job
|
||||
migration:
|
||||
enabled: true
|
||||
image:
|
||||
repository: incidentops/api
|
||||
tag: latest
|
||||
pullPolicy: IfNotPresent
|
||||
backoffLimit: 3
|
||||
|
||||
# Application configuration
|
||||
config:
|
||||
jwtAlgorithm: HS256
|
||||
accessTokenExpireMinutes: 30
|
||||
refreshTokenExpireDays: 30
|
||||
|
||||
# Secrets (use external secrets in production)
|
||||
secrets:
|
||||
jwtSecretKey: "change-me-in-production"
|
||||
|
||||
# PostgreSQL configuration (using official postgres image)
|
||||
postgresql:
|
||||
enabled: true
|
||||
image:
|
||||
repository: postgres
|
||||
tag: "16-alpine"
|
||||
pullPolicy: IfNotPresent
|
||||
auth:
|
||||
username: incidentops
|
||||
password: incidentops
|
||||
database: incidentops
|
||||
persistence:
|
||||
size: 8Gi
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
|
||||
redis:
|
||||
enabled: true
|
||||
image:
|
||||
repository: redis
|
||||
tag: "7-alpine"
|
||||
pullPolicy: IfNotPresent
|
||||
persistence:
|
||||
size: 2Gi
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
|
||||
# Service Account
|
||||
serviceAccount:
|
||||
create: true
|
||||
annotations: {}
|
||||
name: ""
|
||||
|
||||
# Pod Security Context
|
||||
podSecurityContext:
|
||||
fsGroup: 1000
|
||||
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
Reference in New Issue
Block a user