diff --git a/docs/content/en/open_source/upgrading/2.52.md b/docs/content/en/open_source/upgrading/2.52.md index 20eef3fb214..96e8b6e6e31 100644 --- a/docs/content/en/open_source/upgrading/2.52.md +++ b/docs/content/en/open_source/upgrading/2.52.md @@ -75,6 +75,10 @@ Additionally, each deployment can specify its own pod and container security con Now each container can specify the resource requests and limits. +#### New values + +Added Helm chart support for Celery and Django deployments for Horizontal Pod Autoscaler using `.autoscaling` fields under each section. And Pod Disruption Budget using `.podDisruptionBudget` for any of Celery Beat/Worker or Django deployments. + #### Moved values The following Helm chart values have been modified in this release: diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index d7b18755fe9..2c2ba9c9495 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -45,3 +45,5 @@ annotations: description: Testing on the oldest officially supported k8s - kind: added description: Checker for maximal number of celery beats + - kind: added + description: Added HPA and PDB for celery worker and Django diff --git a/helm/defectdojo/README.md b/helm/defectdojo/README.md index 56e713001f1..2b6645a484a 100644 --- a/helm/defectdojo/README.md +++ b/helm/defectdojo/README.md @@ -553,6 +553,7 @@ A Helm chart for Kubernetes to install DefectDojo | celery.worker.annotations | object | `{}` | Annotations for the Celery worker deployment. | | celery.worker.appSettings.poolType | string | `"solo"` | Performance improved celery worker config when needing to deal with a lot of findings (e.g deduplication ops) poolType: prefork autoscaleMin: 2 autoscaleMax: 8 concurrency: 8 prefetchMultiplier: 128 | | celery.worker.automountServiceAccountToken | bool | `false` | | +| celery.worker.autoscaling | object | `{"behavior":{},"enabled":false,"maxReplicas":5,"minReplicas":2,"targetCPUUtilizationPercentage":80,"targetMemoryUtilizationPercentage":80}` | Autoscaling configuration for Celery worker deployment. | | celery.worker.containerSecurityContext | object | `{}` | Container security context for the Celery worker containers. | | celery.worker.extraEnv | list | `[]` | Additional environment variables injected to Celery worker containers. | | celery.worker.extraInitContainers | list | `[]` | A list of additional initContainers to run before celery worker containers. | @@ -561,7 +562,8 @@ A Helm chart for Kubernetes to install DefectDojo | celery.worker.image | object | `{"digest":"","registry":"","repository":"","tag":""}` | If empty, uses values from images.django.image | | celery.worker.livenessProbe | object | `{}` | Enable liveness probe for Celery worker containers. ``` exec: command: - bash - -c - celery -A dojo inspect ping -t 5 initialDelaySeconds: 30 periodSeconds: 60 timeoutSeconds: 10 ``` | | celery.worker.nodeSelector | object | `{}` | | -| celery.worker.podAnnotations | object | `{}` | Annotations for the Celery beat pods. | +| celery.worker.podAnnotations | object | `{}` | Annotations for the Celery worker pods. | +| celery.worker.podDisruptionBudget | object | `{"enabled":false,"minAvailable":"50%","unhealthyPodEvictionPolicy":"AlwaysAllow"}` | Configure pod disruption budgets for Celery worker ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget | | celery.worker.podSecurityContext | object | `{}` | Pod security context for the Celery worker pods. | | celery.worker.readinessProbe | object | `{}` | Enable readiness probe for Celery worker container. | | celery.worker.replicas | int | `1` | | @@ -570,6 +572,7 @@ A Helm chart for Kubernetes to install DefectDojo | celery.worker.resources.requests.cpu | string | `"100m"` | | | celery.worker.resources.requests.memory | string | `"128Mi"` | | | celery.worker.startupProbe | object | `{}` | Enable startup probe for Celery worker container. | +| celery.worker.terminationGracePeriodSeconds | int | `300` | | | celery.worker.tolerations | list | `[]` | | | cloudsql | object | `{"containerSecurityContext":{},"enable_iam_login":false,"enabled":false,"extraEnv":[],"extraVolumeMounts":[],"image":{"pullPolicy":"IfNotPresent","repository":"gcr.io/cloudsql-docker/gce-proxy","tag":"1.37.9"},"instance":"","resources":{},"use_private_ip":false,"verbose":true}` | Google CloudSQL support in GKE via gce-proxy | | cloudsql.containerSecurityContext | object | `{}` | Optional: security context for the CloudSQL proxy container. | @@ -595,6 +598,7 @@ A Helm chart for Kubernetes to install DefectDojo | django.affinity | object | `{}` | | | django.annotations | object | `{}` | | | django.automountServiceAccountToken | bool | `false` | | +| django.autoscaling | object | `{"behavior":{},"enabled":false,"maxReplicas":5,"minReplicas":2,"targetCPUUtilizationPercentage":80,"targetMemoryUtilizationPercentage":80}` | Autoscaling configuration for the Django deployment. | | django.extraEnv | list | `[]` | Additional environment variables injected to all Django containers and initContainers. | | django.extraInitContainers | list | `[]` | A list of additional initContainers to run before the uwsgi and nginx containers. | | django.extraVolumeMounts | list | `[]` | Array of additional volume mount points common to all containers and initContainers. | @@ -622,11 +626,13 @@ A Helm chart for Kubernetes to install DefectDojo | django.nginx.tls.enabled | bool | `false` | | | django.nginx.tls.generateCertificate | bool | `false` | | | django.nodeSelector | object | `{}` | | +| django.podDisruptionBudget | object | `{"enabled":false,"minAvailable":"50%","unhealthyPodEvictionPolicy":"AlwaysAllow"}` | Configure pod disruption budgets for django ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget | | django.podSecurityContext | object | `{"fsGroup":1001}` | Pod security context for the Django pods. | | django.replicas | int | `1` | | | django.service.annotations | object | `{}` | | | django.service.type | string | `""` | | | django.strategy | object | `{}` | | +| django.terminationGracePeriodSeconds | int | `60` | | | django.tolerations | list | `[]` | | | django.uwsgi.appSettings.maxFd | int | `0` | Use this value to set the maximum number of file descriptors. If set to 0 will be detected by uwsgi e.g. 102400 | | django.uwsgi.appSettings.processes | int | `4` | | diff --git a/helm/defectdojo/templates/celery-worker-deployment.yaml b/helm/defectdojo/templates/celery-worker-deployment.yaml index 14ddcf79f4b..9acf2cd49c6 100644 --- a/helm/defectdojo/templates/celery-worker-deployment.yaml +++ b/helm/defectdojo/templates/celery-worker-deployment.yaml @@ -170,6 +170,10 @@ spec: affinity: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.celery.worker.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: + {{- toYaml . | nindent 8 }} + {{- end }} {{- with .Values.celery.worker.tolerations }} tolerations: {{- toYaml . | nindent 8 }} diff --git a/helm/defectdojo/templates/celery-worker-hpa.yaml b/helm/defectdojo/templates/celery-worker-hpa.yaml new file mode 100644 index 00000000000..a47fd64a111 --- /dev/null +++ b/helm/defectdojo/templates/celery-worker-hpa.yaml @@ -0,0 +1,51 @@ +{{- if .Values.celery.worker.autoscaling.enabled -}} +{{- $fullName := include "defectdojo.fullname" . -}} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + {{- with mergeOverwrite dict .Values.extraAnnotations .Values.celery.annotations .Values.celery.worker.annotations }} + annotations: + {{- range $key, $value := . }} + {{ $key }}: {{ quote $value }} + {{- end }} + {{- end }} + name: {{ $fullName }}-celery-worker + namespace: {{ .Release.Namespace }} + labels: + defectdojo.org/component: celery + defectdojo.org/subcomponent: worker + app.kubernetes.io/name: {{ include "defectdojo.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ include "defectdojo.chart" . }} + {{- range $key, $value := .Values.extraLabels }} + {{ $key }}: {{ quote $value }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: "Deployment" + name: {{ $fullName }}-celery-worker + minReplicas: {{ .Values.celery.worker.autoscaling.minReplicas }} + maxReplicas: {{ .Values.celery.worker.autoscaling.maxReplicas }} + metrics: + {{- with .Values.celery.worker.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + averageUtilization: {{ . }} + type: Utilization + {{- end }} + {{- with .Values.celery.worker.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + averageUtilization: {{ . }} + type: Utilization + {{- end }} + {{- with .Values.celery.worker.autoscaling.behavior }} + behavior: {{ toYaml .Values.celery.worker.autoscaling.behavior | nindent 4 }} + {{- end }} +{{- end }} diff --git a/helm/defectdojo/templates/celery-worker-pdb.yaml b/helm/defectdojo/templates/celery-worker-pdb.yaml new file mode 100644 index 00000000000..d91da9e7224 --- /dev/null +++ b/helm/defectdojo/templates/celery-worker-pdb.yaml @@ -0,0 +1,31 @@ +{{- if and .Values.celery.worker.podDisruptionBudget.enabled (or (gt (int .Values.celery.worker.replicas) 1) .Values.celery.worker.autoscaling.enabled) }} +{{- $fullName := include "defectdojo.fullname" . -}} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + {{- with mergeOverwrite dict .Values.extraAnnotations .Values.celery.annotations .Values.celery.worker.annotations }} + annotations: + {{- range $key, $value := . }} + {{ $key }}: {{ quote $value }} + {{- end }} + {{- end }} + labels: + defectdojo.org/component: celery + defectdojo.org/subcomponent: worker + app.kubernetes.io/name: {{ include "defectdojo.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ include "defectdojo.chart" . }} + {{- range $key, $value := .Values.extraLabels }} + {{ $key }}: {{ quote $value }} + {{- end }} + name: {{ $fullName }}-celery-worker + namespace: {{ .Release.Namespace }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ include "defectdojo.name" . }} + defectdojo.org/component: celery + defectdojo.org/subcomponent: worker +{{ toYaml (omit .Values.celery.worker.podDisruptionBudget "enabled" ) | indent 2 }} +{{- end }} \ No newline at end of file diff --git a/helm/defectdojo/templates/django-deployment.yaml b/helm/defectdojo/templates/django-deployment.yaml index b4eee529383..ff2285908ee 100644 --- a/helm/defectdojo/templates/django-deployment.yaml +++ b/helm/defectdojo/templates/django-deployment.yaml @@ -372,6 +372,10 @@ spec: affinity: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.django.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: + {{- toYaml . | nindent 8 }} + {{- end }} {{- with .Values.django.tolerations }} tolerations: {{- toYaml . | nindent 8 }} diff --git a/helm/defectdojo/templates/django-hpa.yaml b/helm/defectdojo/templates/django-hpa.yaml new file mode 100644 index 00000000000..64999a80031 --- /dev/null +++ b/helm/defectdojo/templates/django-hpa.yaml @@ -0,0 +1,50 @@ +{{- if .Values.django.autoscaling.enabled -}} +{{- $fullName := include "defectdojo.fullname" . -}} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + {{- with mergeOverwrite dict .Values.extraAnnotations .Values.django.annotations }} + annotations: + {{- range $key, $value := . }} + {{ $key }}: {{ quote $value }} + {{- end }} + {{- end }} + name: {{ $fullName }}-django + namespace: {{ .Release.Namespace }} + labels: + defectdojo.org/component: django + app.kubernetes.io/name: {{ include "defectdojo.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ include "defectdojo.chart" . }} + {{- range $key, $value := .Values.extraLabels }} + {{ $key }}: {{ quote $value }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: "Deployment" + name: {{ $fullName }}-django + minReplicas: {{ .Values.django.autoscaling.minReplicas }} + maxReplicas: {{ .Values.django.autoscaling.maxReplicas }} + metrics: + {{- with .Values.django.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + averageUtilization: {{ . }} + type: Utilization + {{- end }} + {{- with .Values.django.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + averageUtilization: {{ . }} + type: Utilization + {{- end }} + {{- with .Values.django.autoscaling.behavior }} + behavior: {{ toYaml .Values.django.autoscaling.behavior | nindent 4 }} + {{- end }} +{{- end }} diff --git a/helm/defectdojo/templates/django-pdb.yaml b/helm/defectdojo/templates/django-pdb.yaml new file mode 100644 index 00000000000..f215ca58760 --- /dev/null +++ b/helm/defectdojo/templates/django-pdb.yaml @@ -0,0 +1,29 @@ +{{- if and .Values.django.podDisruptionBudget.enabled (or (gt (int .Values.django.replicas) 1) .Values.django.autoscaling.enabled) }} +{{- $fullName := include "defectdojo.fullname" . -}} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + {{- with mergeOverwrite dict .Values.extraAnnotations .Values.django.annotations }} + annotations: + {{- range $key, $value := . }} + {{ $key }}: {{ quote $value }} + {{- end }} + {{- end }} + labels: + defectdojo.org/component: django + app.kubernetes.io/name: {{ include "defectdojo.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + helm.sh/chart: {{ include "defectdojo.chart" . }} + {{- range $key, $value := .Values.extraLabels }} + {{ $key }}: {{ quote $value }} + {{- end }} + name: {{ $fullName }}-django + namespace: {{ .Release.Namespace }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ include "defectdojo.name" . }} + defectdojo.org/component: django +{{ toYaml (omit .Values.django.podDisruptionBudget "enabled" ) | indent 2 }} +{{- end }} \ No newline at end of file diff --git a/helm/defectdojo/values.schema.json b/helm/defectdojo/values.schema.json index 76b1411877d..2f6e984f208 100644 --- a/helm/defectdojo/values.schema.json +++ b/helm/defectdojo/values.schema.json @@ -181,6 +181,30 @@ "automountServiceAccountToken": { "type": "boolean" }, + "autoscaling": { + "description": "Autoscaling configuration for Celery worker deployment.", + "type": "object", + "properties": { + "behavior": { + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "maxReplicas": { + "type": "integer" + }, + "minReplicas": { + "type": "integer" + }, + "targetCPUUtilizationPercentage": { + "type": "integer" + }, + "targetMemoryUtilizationPercentage": { + "type": "integer" + } + } + }, "containerSecurityContext": { "description": "Container security context for the Celery worker containers.", "type": "object" @@ -227,9 +251,24 @@ "type": "object" }, "podAnnotations": { - "description": "Annotations for the Celery beat pods.", + "description": "Annotations for the Celery worker pods.", "type": "object" }, + "podDisruptionBudget": { + "description": "Configure pod disruption budgets for Celery worker ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget", + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "minAvailable": { + "type": "string" + }, + "unhealthyPodEvictionPolicy": { + "type": "string" + } + } + }, "podSecurityContext": { "description": "Pod security context for the Celery worker pods.", "type": "object" @@ -272,6 +311,10 @@ "description": "Enable startup probe for Celery worker container.", "type": "object" }, + "terminationGracePeriodSeconds": { + "description": "Termination grace period seconds for Celery worker pods.", + "type": "integer" + }, "tolerations": { "type": "array" } @@ -431,6 +474,30 @@ "automountServiceAccountToken": { "type": "boolean" }, + "autoscaling": { + "description": "Autoscaling configuration for the Django deployment.", + "type": "object", + "properties": { + "behavior": { + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "maxReplicas": { + "type": "integer" + }, + "minReplicas": { + "type": "integer" + }, + "targetCPUUtilizationPercentage": { + "type": "integer" + }, + "targetMemoryUtilizationPercentage": { + "type": "integer" + } + } + }, "extraEnv": { "description": "Additional environment variables injected to all Django containers and initContainers.", "type": "array" @@ -596,6 +663,21 @@ "nodeSelector": { "type": "object" }, + "podDisruptionBudget": { + "description": "Configure pod disruption budgets for django ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget", + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "minAvailable": { + "type": "string" + }, + "unhealthyPodEvictionPolicy": { + "type": "string" + } + } + }, "podSecurityContext": { "description": "Pod security context for the Django pods.", "type": "object", @@ -622,6 +704,10 @@ "strategy": { "type": "object" }, + "terminationGracePeriodSeconds": { + "description": "Termination grace period seconds for django pods.", + "type": "integer" + }, "tolerations": { "type": "array" }, diff --git a/helm/defectdojo/values.yaml b/helm/defectdojo/values.yaml index cd850ace3c1..c6c80e2e167 100644 --- a/helm/defectdojo/values.yaml +++ b/helm/defectdojo/values.yaml @@ -275,6 +275,14 @@ celery: repository: "" tag: "" digest: "" + # -- Autoscaling configuration for Celery worker deployment. + autoscaling: + enabled: false + minReplicas: 2 + maxReplicas: 5 + targetCPUUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + behavior: {} automountServiceAccountToken: false # -- Annotations for the Celery worker deployment. annotations: {} @@ -303,8 +311,13 @@ celery: # ``` livenessProbe: {} nodeSelector: {} - # -- Annotations for the Celery beat pods. + # -- Annotations for the Celery worker pods. podAnnotations: {} + # -- Configure pod disruption budgets for Celery worker ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget + podDisruptionBudget: + enabled: false + minAvailable: 50% + unhealthyPodEvictionPolicy: AlwaysAllow # -- Pod security context for the Celery worker pods. podSecurityContext: {} # -- Enable readiness probe for Celery worker container. @@ -319,6 +332,8 @@ celery: memory: 512Mi # -- Enable startup probe for Celery worker container. startupProbe: {} + # -- Termination grace period seconds for Celery worker pods. + terminationGracePeriodSeconds: 300 tolerations: [] appSettings: # -- Performance improved celery worker config when needing to deal with a lot of findings (e.g deduplication ops) @@ -330,6 +345,14 @@ celery: poolType: solo django: + # -- Autoscaling configuration for the Django deployment. + autoscaling: + enabled: false + minReplicas: 2 + maxReplicas: 5 + targetCPUUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + behavior: {} automountServiceAccountToken: false annotations: {} service: @@ -382,8 +405,15 @@ django: cpu: 2000m memory: 256Mi nodeSelector: {} + # -- Configure pod disruption budgets for django ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget + podDisruptionBudget: + enabled: false + minAvailable: 50% + unhealthyPodEvictionPolicy: AlwaysAllow replicas: 1 strategy: {} + # -- Termination grace period seconds for django pods. + terminationGracePeriodSeconds: 60 tolerations: [] uwsgi: # -- If empty, uses values from images.django.image