mirror of
https://github.com/helm/charts.git
synced 2026-08-23 22:37:45 +00:00
[stable/airflow] Improve handling of existing secrets (#14715)
* Cleaning up the existing-secret handling for Airflow Signed-off-by: Steven Anton <steven.m.anton@gmail.com> * Bumping chart version Signed-off-by: Steven Anton <steven.m.anton@gmail.com> * Cleaning up the existing-secret handling for Airflow Signed-off-by: Steven Anton <steven.m.anton@gmail.com> * Bumping chart version Signed-off-by: Steven Anton <steven.m.anton@gmail.com> * Update the README Signed-off-by: Steven Anton <steven.m.anton@gmail.com> * A major overhaul of how secrets are handled Signed-off-by: Steven Anton <steven.m.anton@gmail.com> * Major version bump; adding documentation Signed-off-by: Steven Anton <steven.m.anton@gmail.com>
This commit is contained in:
committed by
Kubernetes Prow Robot
parent
bf53797903
commit
158265ea08
@@ -1,7 +1,7 @@
|
||||
apiVersion: v1
|
||||
description: Airflow is a platform to programmatically author, schedule and monitor workflows
|
||||
name: airflow
|
||||
version: 2.8.8
|
||||
version: 3.0.0
|
||||
appVersion: 1.10.2
|
||||
icon: https://airflow.apache.org/_images/pin_large.png
|
||||
home: https://airflow.apache.org/
|
||||
|
||||
+65
-22
@@ -184,30 +184,50 @@ $ kubectl create secret generic redshift-user --from-file=redshift-user=~/secret
|
||||
```
|
||||
Where `redshift-user.txt` contains the user secret as a single text string.
|
||||
|
||||
### Use precreated secret for airflow secrets or environment variables
|
||||
### Database connection credentials
|
||||
|
||||
You can use a precreated secret for the connection credentials, or general environment variables. To do
|
||||
so specify in values.yaml `existingAirflowSecret`, where the value is the name of the secret which has
|
||||
postgresUser, postgresPassword, and redisPassword etc. is defined. If not specified, it will fall back to using
|
||||
`secrets.yaml` to store the connection credentials by default.
|
||||
In this chart, postgres is used as the database backing Airflow.
|
||||
Additionally, if you're using the `CeleryExecutor` then redis is used.
|
||||
By default, insecure username/password combinations are used.
|
||||
|
||||
Map each specific secret to specific environment variables in your values.yaml. Where envVar is the airflow environment
|
||||
variable to populate and secretKey is the key that contains your secret value in your kubernetes secret:
|
||||
For a real production deployment, it's a good idea to create secure credentials before installing the Helm chart.
|
||||
For example, from the command line, run:
|
||||
```bash
|
||||
kubectl create secret generic airflow-postgres --from-literal=postgres-password=$(openssl rand -base64 13)
|
||||
kubectl create secret generic airflow-redis --from-literal=redis-password=$(openssl rand -base64 13)
|
||||
```
|
||||
Next, you can use those secrets with the Helm chart:
|
||||
```yaml
|
||||
existingAirflowSecret: my-airflow-secrets
|
||||
airflow:
|
||||
secretsMapping:
|
||||
- envVar: AIRFLOW__LDAP__BIND_PASSWORD
|
||||
secretKey: ldapBindPassword
|
||||
# values.yaml
|
||||
|
||||
- envVar: POSTGRES_USER
|
||||
secretKey: airflowPostgresUser
|
||||
postgres:
|
||||
existingSecret: airflow-postgres
|
||||
|
||||
- envVar: POSTGRES_PASSWORD
|
||||
secretKey: airflowPostgresPassword
|
||||
redis:
|
||||
existingSecret: airflow-redis
|
||||
```
|
||||
This approach has the additional advantage of keeping secrets outside of the Helm upgrade process.
|
||||
|
||||
- envVar: REDIS_PASSWORD
|
||||
secretKey: airflowRedisPassword
|
||||
### Additional environment variables
|
||||
|
||||
It is possible to specify additional environment variables using the same format as in a pod's `.spec.containers.env` definition.
|
||||
These environment variables will be mounted in the web, scheduler, and worker pods.
|
||||
You can use this feature to pass additional secret environment variables to Airflow.
|
||||
|
||||
Here is a simple example showing how to pass in a Fernet key and LDAP password.
|
||||
Of course, for this example to work, both the `airflow` and `ldap` Kubernetes secrets must already exist in the proper namespace; be sure to create those before running Helm.
|
||||
```yaml
|
||||
extraEnv:
|
||||
- name: AIRFLOW__CORE__FERNET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: airflow
|
||||
key: fernet-key
|
||||
- name: AIRFLOW__LDAP__BIND_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: ldap
|
||||
key: password
|
||||
```
|
||||
|
||||
### Local binaries
|
||||
@@ -322,7 +342,7 @@ The following table lists the configurable parameters of the Airflow chart and t
|
||||
| `airflow.webReplicas` | how many replicas for web server | `1` |
|
||||
| `airflow.config` | custom airflow configuration env variables | `{}` |
|
||||
| `airflow.podDisruptionBudget` | control pod disruption budget | `{'maxUnavailable': 1}` |
|
||||
| `airflow.secretsMapping` | override any environment variable with a secret | |
|
||||
| `airflow.extraEnv` | specify additional environment variables to mount | `{}` |
|
||||
| `airflow.extraConfigmapMounts` | Additional configMap volume mounts on the airflow pods. | `[]` |
|
||||
| `airflow.podAnnotations` | annotations for scheduler, worker and web pods | `{}` |
|
||||
| `airflow.extraContainers` | additional containers to run in the scheduler, worker & web pods | `[]` |
|
||||
@@ -343,7 +363,6 @@ The following table lists the configurable parameters of the Airflow chart and t
|
||||
| `workers.podAnnotations` | annotations for the worker pods | `{}` |
|
||||
| `workers.secretsDir` | directory in which to mount secrets on worker nodes | /var/airflow/secrets |
|
||||
| `workers.secrets` | secrets to mount as volumes on worker nodes | [] |
|
||||
| `existingAirflowSecret` | secret to use for postgres and redis connection | |
|
||||
| `nodeSelector` | Node labels for pod assignment | `{}` |
|
||||
| `affinity` | Affinity labels for pod assignment | `{}` |
|
||||
| `tolerations` | Toleration labels for pod assignment | `[]` |
|
||||
@@ -386,6 +405,7 @@ The following table lists the configurable parameters of the Airflow chart and t
|
||||
| `serviceAccount.create` | create a service account | `true` |
|
||||
| `serviceAccount.name` | the service account name | `` |
|
||||
| `postgresql.enabled` | create a postgres server | `true` |
|
||||
| `postgresql.existingSecret` | The name of an existing secret with a key `postgresql-password` to use as the password | `nil` |
|
||||
| `postgresql.uri` | full URL to custom postgres setup | (undefined) |
|
||||
| `postgresql.portgresHost` | PostgreSQL Hostname | (undefined) |
|
||||
| `postgresql.postgresUser` | PostgreSQL User | `postgres` |
|
||||
@@ -395,6 +415,7 @@ The following table lists the configurable parameters of the Airflow chart and t
|
||||
| `postgresql.persistance.storageClass` | Persistant class | (undefined) |
|
||||
| `postgresql.persistance.accessMode` | Access mode | `ReadWriteOnce` |
|
||||
| `redis.enabled` | Create a Redis cluster | `true` |
|
||||
| `redis.existingSecret` | The name of an existing secret with a key `redis-password` to use as the password | `nil` |
|
||||
| `redis.redisHost` | Redis Hostname | (undefined) |
|
||||
| `redis.password` | Redis password | `airflow` |
|
||||
| `redis.master.persistence.enabled` | Enable Redis PVC | `false` |
|
||||
@@ -411,8 +432,30 @@ The following table lists the configurable parameters of the Airflow chart and t
|
||||
Full and up-to-date documentation can be found in the comments of the `values.yaml` file.
|
||||
|
||||
## Upgrading
|
||||
|
||||
### To 3.0.0
|
||||
This version introduces a simplified way of managing secrets, including the database credentials to postgres and redis.
|
||||
With the default settings in prior versions, database credentials were generated and stored in an Airflow-managed Kubernetes secret.
|
||||
However, these credentials were also stored in postgres- and redis-managed secrets (created by the respective subcharts), leading to duplication.
|
||||
Moreover, it was tricky to bring your own passwords and to load additional secrets as environment variables.
|
||||
|
||||
To deal with these issues, we've removed the Airflow-managed Kubernetes secret (`templates/secret-env.yaml`).
|
||||
If your deployment was called `airflow`, this upgrade will delete the `airflow-env` secret.
|
||||
Instead, the pods now source the database secrets from the postgres- and redis-managed secrets, i.e. the postgres password is in the `airflow-postgres` secret.
|
||||
This upgrade _shouldn't_ break the deployment, but you may need to make some adjustments if you were doing something nonstandard.
|
||||
|
||||
For production, it's better create random passwords before installing the Helm chart.
|
||||
You can use these passwords by specifying the newly added `postgres.existingSecret` and `redis.existingSecret` parameters.
|
||||
|
||||
We've also added `airflow.extraEnv`, which provides a flexible way to inject environment variables into your pods.
|
||||
This parameter is great for things like the Fernet key and LDAP password.
|
||||
|
||||
The following parameters are no longer necessary and have been removed: `airflow.defaultSecretsMapping`, `airflow.secretsMapping`, `airflow.existingAirflowSecret`.
|
||||
If you were using them, you'll have to migrate your settings to `postgres.existingSecret`, `redis.existingSecret`, and `airflow.extraEnv`, which are described in greater depth in the documentation above.
|
||||
|
||||
### To 2.8.3+
|
||||
The parameter `airflow.service.type` no longer applies to the Flower service, but the default of `ClusterIP` has been maintained. If using a custom values file and have changed the service type, also specify `flower.service.type`.
|
||||
|
||||
### To 2.0.0
|
||||
The parameter `workers.pod.annotations` has been renamed to `workers.podAnnotations`. If using a
|
||||
custom values file, rename this parameter.
|
||||
### To 2.8.3+
|
||||
The parameter `airflow.service.type` no longer applies to the Flower service, but the default of `ClusterIP` has been maintained. If using a custom values file and have changed the service type, also specify `flower.service.type`.
|
||||
|
||||
@@ -45,11 +45,31 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
|
||||
{{- end -}}
|
||||
{{- 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.
|
||||
NOTE: This is copied from the redis sub-chart and modified slightly:
|
||||
*/}}
|
||||
{{- define "airflow.redis.fullname" -}}
|
||||
{{- if .Values.redis.fullnameOverride -}}
|
||||
{{- .Values.redis.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- $name := default "redis" .Values.redis.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 a default fully qualified redis cluster name or use the `redisHost` value if defined
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
*/}}
|
||||
{{- define "airflow.redis.fullname" -}}
|
||||
{{- define "airflow.redis.host" -}}
|
||||
{{- if .Values.redis.redisHost }}
|
||||
{{- .Values.redis.redisHost -}}
|
||||
{{- else }}
|
||||
@@ -70,39 +90,26 @@ Create a random string if the supplied key does not exist
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the name for the airflow secret.
|
||||
Create a set of environment variables to be mounted in web, scheduler, and woker pods.
|
||||
For the database passwords, we actually use the secretes created by the postgres and redis sub-charts.
|
||||
Note that the environment variables themselves are determined by the puckel/docker-airflow image.
|
||||
See script/entrypoint.sh in that repo for more info.
|
||||
The key names for postgres and redis are fixed, which is consistent with the subcharts.
|
||||
*/}}
|
||||
{{- define "airflow.secret" -}}
|
||||
{{- if .Values.existingAirflowSecret -}}
|
||||
{{- .Values.existingAirflowSecret -}}
|
||||
{{- else -}}
|
||||
{{ template "airflow.fullname" . }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Map environment vars to secrets
|
||||
*/}}
|
||||
{{- define "airflow.mapenvsecrets" -}}
|
||||
{{- $secretName := printf "%s-env" (include "airflow.fullname" .) }}
|
||||
{{- $mapping := .Values.airflow.defaultSecretsMapping }}
|
||||
{{- if .Values.existingAirflowSecret }}
|
||||
{{- $secretName := .Values.existingAirflowSecret }}
|
||||
{{- if .Values.airflow.secretsMapping }}
|
||||
{{- $mapping := .Values.airflow.secretsMapping }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $val := $mapping }}
|
||||
{{- if $val }}
|
||||
- name: {{ $val.envVar }}
|
||||
{{- define "airflow.mapenvsecrets" }}
|
||||
- name: POSTGRES_USER
|
||||
value: {{ default "postgres" .Values.postgresql.postgresUser | quote }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
{{- if $val.secretName }}
|
||||
name: {{ $val.secretName }}
|
||||
{{- else }}
|
||||
name: {{ $secretName }}
|
||||
{{- end }}
|
||||
key: {{ $val.secretKey }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
name: {{ default (include "airflow.postgresql.fullname" .) .Values.postgresql.existingSecret }}
|
||||
key: postgres-password
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ default (include "airflow.redis.fullname" .) .Values.redis.existingSecret }}
|
||||
key: redis-password
|
||||
{{- if .Values.airflow.extraEnv }}
|
||||
{{ toYaml .Values.airflow.extraEnv | indent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -15,7 +15,7 @@ data:
|
||||
POSTGRES_PORT: "{{ .Values.postgresql.service.port }}"
|
||||
POSTGRES_DB: "{{ .Values.postgresql.postgresDatabase }}"
|
||||
## Redis DB configuration
|
||||
REDIS_HOST: "{{ template "airflow.redis.fullname" . }}"
|
||||
REDIS_HOST: "{{ template "airflow.redis.host" . }}"
|
||||
REDIS_PORT: "{{ .Values.redis.master.port }}"
|
||||
## Flower PORT
|
||||
FLOWER_PORT: "5555"
|
||||
|
||||
@@ -26,7 +26,6 @@ spec:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config-env: {{ include (print $.Template.BasePath "/configmap-env.yaml") . | sha256sum }}
|
||||
checksum/secret-env: {{ include (print $.Template.BasePath "/secret-env.yaml") . | sha256sum }}
|
||||
labels:
|
||||
app: {{ template "airflow.name" . }}
|
||||
component: flower
|
||||
|
||||
@@ -30,7 +30,6 @@ spec:
|
||||
checksum/config-scripts: {{ include (print $.Template.BasePath "/configmap-scripts.yaml") . | sha256sum }}
|
||||
checksum/config-variables-pools: {{ include (print $.Template.BasePath "/configmap-variables-pools.yaml") . | sha256sum }}
|
||||
checksum/secret-connections: {{ include (print $.Template.BasePath "/secret-connections.yaml") . | sha256sum }}
|
||||
checksum/secret-env: {{ include (print $.Template.BasePath "/secret-env.yaml") . | sha256sum }}
|
||||
{{- if .Values.airflow.podAnnotations }}
|
||||
{{ toYaml .Values.airflow.podAnnotations | indent 8 }}
|
||||
{{- end }}
|
||||
|
||||
@@ -28,7 +28,6 @@ spec:
|
||||
checksum/config-env: {{ include (print $.Template.BasePath "/configmap-env.yaml") . | sha256sum }}
|
||||
checksum/config-git-clone: {{ include (print $.Template.BasePath "/configmap-git-clone.yaml") . | sha256sum }}
|
||||
checksum/config-scripts: {{ include (print $.Template.BasePath "/configmap-scripts.yaml") . | sha256sum }}
|
||||
checksum/secret-env: {{ include (print $.Template.BasePath "/secret-env.yaml") . | sha256sum }}
|
||||
{{- if .Values.airflow.podAnnotations }}
|
||||
{{ toYaml .Values.airflow.podAnnotations | indent 8 }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
{{- if not .Values.existingAirflowSecret -}}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ template "airflow.fullname" . }}-env
|
||||
labels:
|
||||
app: {{ template "airflow.fullname" . }}
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
release: "{{ .Release.Name }}"
|
||||
heritage: "{{ .Release.Service }}"
|
||||
type: Opaque
|
||||
data:
|
||||
postgresUser: {{ .Values.postgresql.postgresUser | b64enc | quote }}
|
||||
postgresPassword: {{ .Values.postgresql.postgresPassword | b64enc | quote }}
|
||||
redisPassword: {{ .Values.redis.password | b64enc | quote }}
|
||||
{{- end -}}
|
||||
@@ -32,7 +32,6 @@ spec:
|
||||
checksum/config-env: {{ include (print $.Template.BasePath "/configmap-env.yaml") . | sha256sum }}
|
||||
checksum/config-git-clone: {{ include (print $.Template.BasePath "/configmap-git-clone.yaml") . | sha256sum }}
|
||||
checksum/config-scripts: {{ include (print $.Template.BasePath "/configmap-scripts.yaml") . | sha256sum }}
|
||||
checksum/secret-env: {{ include (print $.Template.BasePath "/secret-env.yaml") . | sha256sum }}
|
||||
{{- if .Values.airflow.podAnnotations }}
|
||||
{{ toYaml .Values.airflow.podAnnotations | indent 8 }}
|
||||
{{- end }}
|
||||
|
||||
+25
-37
@@ -17,41 +17,21 @@ airflow:
|
||||
# subPath: file.yaml
|
||||
|
||||
|
||||
## When existingAirflowSecret is defined, secretsMapping can be
|
||||
## overridden. When no secretName is given then the value of
|
||||
## existingAirflowSecret is assumed.
|
||||
## secretsMapping:
|
||||
## - envVar: AIRFLOW__LDAP__BIND_PASSWORD
|
||||
## secretName: ldap
|
||||
## secretKey: ldapBindPassword
|
||||
## - envVar: AIRFLOW__ATLAS__PASSWORD
|
||||
## secretKey: atlasPassword
|
||||
## - envVar: AIRFLOW__SMTP__PASSWORD
|
||||
## secretKey: smtpPassword
|
||||
## - envVar: AIRFLOW__KUBERNETES__GIT_PASSWORD
|
||||
## secretKey: kubernetesGitPassword
|
||||
## - envVar: POSTGRES_USER
|
||||
## secretName: postgres
|
||||
## secretKey: postgresUser
|
||||
## - envVar: POSTGRES_PASSWORD
|
||||
## secretName: postgres
|
||||
## secretKey: postgresPassword
|
||||
## - envVar: REDIS_PASSWORD
|
||||
## secretName: redis
|
||||
## secretKey: redisPassword
|
||||
secretsMapping:
|
||||
##
|
||||
## Extra environment variables to mount in the web, scheduler, and worker pods:
|
||||
extraEnv:
|
||||
# - name: AIRFLOW__CORE__FERNET_KEY
|
||||
# valueFrom:
|
||||
# secretKeyRef:
|
||||
# name: airflow
|
||||
# key: fernet_key
|
||||
# - name: AIRFLOW__LDAP__BIND_PASSWORD
|
||||
# valueFrom:
|
||||
# secretKeyRef:
|
||||
# name: ldap
|
||||
# key: password
|
||||
|
||||
|
||||
## Used only when existingAirflowSecret is null, in which case
|
||||
## a secret will be created with a default name and the following mapping.
|
||||
defaultSecretsMapping:
|
||||
- envVar: POSTGRES_USER
|
||||
secretKey: postgresUser
|
||||
- envVar: POSTGRES_PASSWORD
|
||||
secretKey: postgresPassword
|
||||
- envVar: REDIS_PASSWORD
|
||||
secretKey: redisPassword
|
||||
|
||||
##
|
||||
## You will need to define your fernet key:
|
||||
## Generate fernetKey with:
|
||||
@@ -468,10 +448,6 @@ serviceAccount:
|
||||
## If not set and create is true, a name is generated using the fullname template
|
||||
name:
|
||||
|
||||
##
|
||||
## Define existing secret for postgresql and redis
|
||||
## If not specified, creates secret with postgres and redis values
|
||||
existingAirflowSecret: ""
|
||||
|
||||
##
|
||||
## Configuration values for the postgresql dependency.
|
||||
@@ -481,6 +457,12 @@ postgresql:
|
||||
## Use the PostgreSQL chart dependency.
|
||||
## Set to false if bringing your own PostgreSQL.
|
||||
enabled: true
|
||||
|
||||
##
|
||||
## The name of an existing secret that contains the postgres password.
|
||||
## Note that the secret must have a key called postgres-password.
|
||||
existingSecret:
|
||||
|
||||
##
|
||||
## If you are bringing your own PostgreSQL, you should set postgresHost and
|
||||
## also probably service.port, postgresUser, postgresPassword, and postgresDatabase
|
||||
@@ -520,6 +502,12 @@ redis:
|
||||
## Use the redis chart dependency.
|
||||
## Set to false if bringing your own redis.
|
||||
enabled: true
|
||||
|
||||
##
|
||||
## The name of an existing secret that contains the redis password.
|
||||
## Note that the secret must have a key called redis-password.
|
||||
existingSecret:
|
||||
|
||||
##
|
||||
## If you are bringing your own redis, you can set the host in redisHost.
|
||||
## redisHost:
|
||||
|
||||
Reference in New Issue
Block a user