Skip to content

Commit

Permalink
✨(helm) add the django base Helm chart
Browse files Browse the repository at this point in the history
to avoid rewriting a helm chart from scratch for all django based
applications, we need to create a generic base chart that can be used as a subchart
for django apps.
  • Loading branch information
rouaidakacem committed Jan 2, 2023
1 parent d6c25ce commit 4d13d1e
Show file tree
Hide file tree
Showing 14 changed files with 683 additions and 0 deletions.
23 changes: 23 additions & 0 deletions charts/base-django/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
29 changes: 29 additions & 0 deletions charts/base-django/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apiVersion: v2
name: django
description: A Helm chart for Kubernetes

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.1.0"
dependencies:
- condition: postgresql.enabled
name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 12.x.x
38 changes: 38 additions & 0 deletions charts/base-django/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Django Helm Chart

This chart's aims is to deploy a django app using Helm. This chart follows the structure of the Django apps developped by
France Université Numérique. Is is intended to be used as a subchart for Django app Deployments.

This chart allows the user to either create a Postgresql database or connect to an external database (it depends on the variable `postgreqsl.enabled`)

To deploy your own Django app, create your own Helm chart, add this one as a subchart and overwrite its parameters as needed. To do this you have to add a section in your own values file as follows:

```
django:
image:
repository: fundocker/<app_image>
pullPolicy: IfNotPresent
tag: <image_tag>
appDjangoSettingsModule: <settings_module>
appDjangoConfiguration: <app_configuration>
```
Since we have not yet created our own helm chart repository, in order to use this chart as a subchart, you need to:

1) Build this helm chart dependencies: ` helm dependency build `

2) Package this chart: ` helm package . ` , a .tgz file will be created.

3) Copy the .tgz in `<your-chart>/charts` directory

It is possible to use existing Secrets or ConfigMaps for the deployment. In order to do this, you need to set the `extraEnvVarsSecret` and the `extraEnvVarsCM` variables with the name of the corresponding resource.

One other way to set the environment variables is to deploy custom Secrets and ConfigMaps in the parent chart. For thsi to work, you need to deploy the custom secret with the following annotations:

```
"helm.sh/hook": pre-upgrade, pre-install
"helm.sh/hook-weight": "-5"
```

For additional custom nginx configuration, this can be done using the `ingress.nginxServerSnippet` variable.
Empty file.
75 changes: 75 additions & 0 deletions charts/base-django/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "django.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "django.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 "django.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "django.labels" -}}
helm.sh/chart: {{ include "django.chart" . }}
{{ include "django.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "django.selectorLabels" -}}
app.kubernetes.io/name: {{ include "django.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Return the proper Docker Image Registry Secret Names
*/}}
{{- define "django.imagePullSecrets" -}}
{{- $pullSecrets := .Values.imagePullSecrets }}
{{- if (not (empty $pullSecrets)) }}
imagePullSecrets:
{{- range $pullSecrets }}
- name: {{ . }}
{{- end }}
{{- end -}}
{{- end }}

{{/*
Return the host
*/}}
{{- define "django.host" -}}
{{- if .Values.appHost }}
{{- .Values.appHost }}
{{- else }}
{{ .Release.Name }}.{{ .Release.Namespace }}.{{ .Values.domainName }}
{{- end }}
{{- end }}
19 changes: 19 additions & 0 deletions charts/base-django/templates/app/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "django.fullname" . }}-dotenv
namespace: {{ .Release.Namespace | quote }}
labels: {{- include "django.labels" . | nindent 4 }}
{{- if .Values.commonLabels }}
{{ toYaml .Values.commonLabels | nindent 4 }}
{{- end }}
app.kubernetes.io/component: django
{{- if .Values.commonAnnotations }}
annotations: {{ toYaml .Values.commonAnnotations | nindent 4 }}
{{- end }}
data:
DJANGO_SILENCED_SYSTEM_CHECKS: "security.W008,security.W004"
{{- range .Values.djangoAppEnvVars }}
{{ .key }}: {{ .value }}
{{- end }}

110 changes: 110 additions & 0 deletions charts/base-django/templates/app/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "django.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels: {{- include "django.labels" . | nindent 4 }}
{{- if .Values.commonLabels }}
{{ toYaml .Values.commonLabels | nindent 4 }}
{{- end }}
app.kubernetes.io/component: django
{{- if .Values.commonAnnotations }}
annotations: {{ toYaml .Values.commonAnnotations | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels: {{- include "django.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: django
template:
metadata:
labels: {{- include "django.labels" . | nindent 8 }}
app.kubernetes.io/component: django
{{- if .Values.podLabels }}
{{ toYaml .Values.podLabels | nindent 8 }}
{{- end }}
annotations:
{{- if .Values.podAnnotations }}
{{- toYaml .Values.podAnnotations | nindent 8 }}
{{- end }}
spec: {{- include "django.imagePullSecrets" . | nindent 6 }}
{{- if .Values.affinity }}
affinity: {{- toYaml .Values.affinity | nindent 8 }}
{{- else -}}
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchLabels: {{- include "django.selectorLabels" . | nindent 20 }}
app.kubernetes.io/component: django
namespaces:
- {{ .Release.Namespace | quote }}
topologyKey: kubernetes.io/hostname
weight: 100
{{- end }}
{{- if .Values.podSecurityContext }}
securityContext: {{ toYaml .Values.podSecurityContext | nindent 8 }}
{{- end }}
containers:
- name: django
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- if .Values.containerSecurityContext.enabled }}
securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }}
{{- end }}
env:
- name: DB_HOST
value: {{ include "django.fullname" . }}-postgresql
- name: DB_NAME
value: {{ .Values.databaseName }}
- name: DB_PORT
value: {{ .Values.databasePort | quote }}
- name: DJANGO_ALLOWED_HOSTS
value: {{ include "django.host" . }}
- name: DJANGO_CONFIGURATION
value: {{ .Values.appDjangoConfiguration }}
- name: DJANGO_SETTINGS_MODULE
value: {{ .Values.appDjangoSettingsModule }}
envFrom:
- secretRef:
name: {{ include "django.fullname" . }}
- configMapRef:
name: {{ include "django.fullname" . }}-dotenv
{{- if .Values.extraEnvVarsSecret }}
- secretRef:
name: {{ .Values.extraEnvVarsSecret }}
{{- end }}
{{- if .Values.extraEnvVarsCM }}
- configMapRef:
name: {{ .Values.extraEnvVarsCM }}
{{- end }}
{{- if .Values.customLivenessProbe }}
livenessProbe: {{- toYaml .Values.customLivenessProbe | nindent 12 }}
{{ else }}
livenessProbe:
httpGet:
path: {{.Values.livenessProbe.path }}
port: {{ .Values.service.port }}
httpHeaders:
- name: Host
value: "{{ include "django.host" . }}"
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.livenessProbe.periodeSeconds }}
{{- end }}
{{- if .Values.customReadinessProbe }}
readinessProbe: {{- toYaml .Values.customReadinessProbe | nindent 12 }}
{{ else }}
readinessProbe:
httpGet:
path: {{ .Values.readinessProbe.path }}
port: {{ .Values.service.port }}
httpHeaders:
- name: Host
value: "{{ include "django.host" . }}"
initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.readinessProbe.periodeSeconds }}
{{- end }}
{{- if .Values.resources }}
resources: {{ toYaml .Values.resources | nindent 12 }}
{{- end }}
82 changes: 82 additions & 0 deletions charts/base-django/templates/app/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "django.fullname" . }}-ingress
namespace: {{ .Release.Namespace | quote }}
labels: {{- include "django.labels" . | nindent 4 }}
{{- if .Values.commonLabels }}
{{ toYaml .Values.commonLabels | nindent 4 }}
{{- end }}
app.kubernetes.io/component: django
annotations:
{{- if .Values.commonAnnotations }}
{{- toYaml .Values.commonAnnotations | nindent 4 }}
{{- end }}
{{- if .Values.ingress.acmeIssuerName }}
cert-manager.io/issuer: {{ .Values.ingress.acmeIssuerName }}
{{- end }}
{{- if .Values.ingress.activateHttpBasicAuth }}
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: {{ .Values.ingress.htpasswdSecretName }}
nginx.ingress.kubernetes.io/auth-realm: {{ .Values.ingress.httpBasicAuthMessage }}
{{- end }}
{{- if and .Values.ingress.activateHttpBasicAuth .Values.ingress.bypassHtaccessIpWhitelist }}
nginx.ingress.kubernetes.io/satisfy: "any"
nginx.ingress.kubernetes.io/whitelist-source-range: {{ join "," .Values.ingress.bypassHtaccessIpWhitelist }}
{{- end }}
nginx.ingress.kubernetes.io/server-snippet: |
{{ .Values.ingress.nginxServerSnippet | nindent 6 }}
spec:
ingressClassName: nginx
rules:
- host: {{ include "django.host" . | quote }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ include "django.fullname" . }}
port:
number: {{ .Values.service.port }}
tls:
- hosts:
- {{ include "django.host" . }}
secretName: {{ .Values.ingress.tlsSecretName }}
---
{{ if .Values.ingress.adminIpWhitelist }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "django.fullname" . }}-ingress-admin
namespace: {{ .Release.Namespace | quote }}
labels: {{- include "django.labels" . | nindent 4 }}
{{- if .Values.commonLabels }}
{{ toYaml .Values.commonLabels | nindent 4 }}
{{- end }}
app.kubernetes.io/component: django
annotations:
{{- if .Values.ingress.acmeIssuerName -}}
cert-manager.io/issuer: {{ .Values.ingress.acmeIssuerName }}
{{ end }}
nginx.ingress.kubernetes.io/whitelist-source-range: {{ join "," .Values.ingress.adminIpWhitelist }}
nginx.ingress.kubernetes.io/server-snippet: |
{{ .Values.ingress.nginxServerSnippet | nindent 6 }}
spec:
ingressClassName: nginx
rules:
- host: {{ include "django.host" . | quote }}
http:
paths:
- path: /admin
pathType: Prefix
backend:
service:
name: {{ include "django.fullname" . }}
port:
number: {{ .Values.service.port }}
tls:
- hosts:
- {{ include "django.host" . }}
secretName: {{ .Values.ingress.tlsSecretName }}
{{ end }}
Loading

0 comments on commit 4d13d1e

Please sign in to comment.