Add airflow
This commit is contained in:
parent
94d905fe08
commit
4e7c81af8c
23
argocd-apps/air-flow.yaml
Normal file
23
argocd-apps/air-flow.yaml
Normal file
@ -0,0 +1,23 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: air-flow
|
||||
namespace: argocd
|
||||
labels:
|
||||
env: dev-tools
|
||||
spec:
|
||||
project: dev-tools
|
||||
source:
|
||||
repoURL: ssh://git@gitea-ssh.dev-tools.svc.cluster.local:2222/dvirlabs/dev-tools.git
|
||||
targetRevision: HEAD
|
||||
path: charts/air-flow
|
||||
helm:
|
||||
valueFiles:
|
||||
- ../../manifests/air-flow/values.yaml
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: dev-tools
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
42
charts/airflow/.helmignore
Normal file
42
charts/airflow/.helmignore
Normal file
@ -0,0 +1,42 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# 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
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
bin
|
||||
|
||||
# We do not want to include our Python Helm Chart Unit test files
|
||||
tests
|
||||
118
charts/airflow/.pre-commit-config.yaml
Normal file
118
charts/airflow/.pre-commit-config.yaml
Normal file
@ -0,0 +1,118 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
---
|
||||
default_stages: [pre-commit, pre-push]
|
||||
minimum_prek_version: '0.2.0'
|
||||
default_language_version:
|
||||
python: python3
|
||||
node: 22.19.0
|
||||
golang: 1.24.0
|
||||
repos:
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: ad1b27d73581aa16cca06fc4a0761fc563ffe8e8 # frozen: v1.5.6
|
||||
hooks:
|
||||
- id: insert-license
|
||||
name: Add license for all Helm template files
|
||||
files: ^templates/.*
|
||||
args:
|
||||
- --comment-style
|
||||
- "{{/*||*/}}"
|
||||
- --license-filepath
|
||||
- ../scripts/ci/license-templates/LICENSE.txt
|
||||
- --fuzzy-match-generates-todo
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: update-chart-dependencies
|
||||
name: Update chart dependencies to latest (manual)
|
||||
entry: ../scripts/ci/prek/update_chart_dependencies.py
|
||||
stages: ['manual']
|
||||
language: python
|
||||
files: ^\.pre-commit-config\.yaml$|^../scripts/ci/prek/update_build_dependencies\.py$
|
||||
pass_filenames: false
|
||||
require_serial: true
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
|
||||
hooks:
|
||||
- id: pretty-format-json
|
||||
name: Format JSON files
|
||||
args:
|
||||
- --autofix
|
||||
- --no-sort-keys
|
||||
- --indent
|
||||
- "4"
|
||||
files:
|
||||
(?x)
|
||||
^values\.schema\.json$|
|
||||
^values_schema\.schema\.json$
|
||||
pass_filenames: true
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: lint-helm-chart
|
||||
name: Lint Helm Chart
|
||||
entry: ../scripts/ci/prek/lint_helm.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
files: ^.*
|
||||
require_serial: true
|
||||
- id: validate-chart-annotations
|
||||
name: Validate chart annotations
|
||||
entry: ../scripts/ci/prek/validate_chart_annotations.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
files: ^Chart\.yaml$
|
||||
- id: kubeconform
|
||||
name: Kubeconform check on our helm chart
|
||||
entry: ../scripts/ci/prek/check_kubeconform.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
files: ^.*
|
||||
require_serial: true
|
||||
- id: lint-json-schema
|
||||
name: Lint chart/values.schema.json
|
||||
entry: ../scripts/ci/prek/lint_json_schema.py
|
||||
args:
|
||||
- --spec-file
|
||||
- values_schema.schema.json
|
||||
- values.schema.json
|
||||
language: python
|
||||
pass_filenames: false
|
||||
files: ^values\.schema\.json$|^values_schema\.schema\.json$
|
||||
require_serial: true
|
||||
- id: update-vendored-in-k8s-json-schema
|
||||
name: Vendor k8s definitions into values.schema.json
|
||||
entry: ../scripts/ci/prek/vendor_k8s_json_schema.py
|
||||
language: python
|
||||
files: ^values\.schema\.json$
|
||||
- id: lint-json-schema
|
||||
name: Lint chart/values.yaml
|
||||
entry: ../scripts/ci/prek/lint_json_schema.py
|
||||
args:
|
||||
- --enforce-defaults
|
||||
- --spec-file
|
||||
- values.schema.json
|
||||
- values.yaml
|
||||
language: python
|
||||
pass_filenames: false
|
||||
files: ^values\.yaml$|^values\.schema\.json$
|
||||
require_serial: true
|
||||
- id: lint-chart-schema
|
||||
name: Lint chart/values.schema.json file
|
||||
entry: ../scripts/ci/prek/chart_schema.py
|
||||
language: python
|
||||
pass_filenames: false
|
||||
files: ^values\.schema\.json$
|
||||
require_serial: true
|
||||
6
charts/airflow/Chart.lock
Normal file
6
charts/airflow/Chart.lock
Normal file
@ -0,0 +1,6 @@
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
version: 13.2.24
|
||||
digest: sha256:07f12ed410f106bf13eca69df16a1ef6690c4d4bfcb037943bbff6e71a22201d
|
||||
generated: "2023-12-09T17:23:53.209725+01:00"
|
||||
155
charts/airflow/Chart.yaml
Normal file
155
charts/airflow/Chart.yaml
Normal file
@ -0,0 +1,155 @@
|
||||
annotations:
|
||||
artifacthub.io/changes: |
|
||||
- description: >
|
||||
Workers config options have been moved under workers.celery.* and workers.kubernetes.*:
|
||||
safeToEvict, hostAliases, priorityClassName, runtimeClassName, schedulerName,
|
||||
serviceAccount, extraContainers, extraInitContainers, extraVolumes, affinity,
|
||||
tolerations, topologySpreadConstraints, podAnnotations, labels, env, extraVolumeMounts
|
||||
are moved to both; extraPorts, volumeClaimTemplates, waitForMigrations, hpa,
|
||||
annotations, logGroomerSidecar are Celery-specific and moved under workers.celery.*
|
||||
kind: changed
|
||||
links:
|
||||
- name: '#61915'
|
||||
url: https://github.com/apache/airflow/pull/61915
|
||||
- name: '#61919'
|
||||
url: https://github.com/apache/airflow/pull/61919
|
||||
- name: '#61960'
|
||||
url: https://github.com/apache/airflow/pull/61960
|
||||
- name: '#61961'
|
||||
url: https://github.com/apache/airflow/pull/61961
|
||||
- name: '#61962'
|
||||
url: https://github.com/apache/airflow/pull/61962
|
||||
- name: '#62030'
|
||||
url: https://github.com/apache/airflow/pull/62030
|
||||
- name: '#62048'
|
||||
url: https://github.com/apache/airflow/pull/62048
|
||||
- name: '#62054'
|
||||
url: https://github.com/apache/airflow/pull/62054
|
||||
- name: '#64730'
|
||||
url: https://github.com/apache/airflow/pull/64730
|
||||
- name: '#64734'
|
||||
url: https://github.com/apache/airflow/pull/64734
|
||||
- name: '#64739'
|
||||
url: https://github.com/apache/airflow/pull/64739
|
||||
- name: '#64741'
|
||||
url: https://github.com/apache/airflow/pull/64741
|
||||
- name: '#64746'
|
||||
url: https://github.com/apache/airflow/pull/64746
|
||||
- name: '#64860'
|
||||
url: https://github.com/apache/airflow/pull/64860
|
||||
- name: '#64976'
|
||||
url: https://github.com/apache/airflow/pull/64976
|
||||
- name: '#64980'
|
||||
url: https://github.com/apache/airflow/pull/64980
|
||||
- name: '#64982'
|
||||
url: https://github.com/apache/airflow/pull/64982
|
||||
- name: '#65027'
|
||||
url: https://github.com/apache/airflow/pull/65027
|
||||
- name: '#65030'
|
||||
url: https://github.com/apache/airflow/pull/65030
|
||||
- name: '#65033'
|
||||
url: https://github.com/apache/airflow/pull/65033
|
||||
- name: '#65056'
|
||||
url: https://github.com/apache/airflow/pull/65056
|
||||
- name: '#65059'
|
||||
url: https://github.com/apache/airflow/pull/65059
|
||||
- description: Default Airflow image updated to 3.2.0
|
||||
kind: changed
|
||||
links:
|
||||
- name: '#64841'
|
||||
url: https://github.com/apache/airflow/pull/64841
|
||||
- description: Fix wrong broker URL secret ref
|
||||
kind: fixed
|
||||
links:
|
||||
- name: '#65006'
|
||||
url: https://github.com/apache/airflow/pull/65006
|
||||
- description: Add ttlSecondsAfterFinished to database cleanup job
|
||||
kind: added
|
||||
links:
|
||||
- name: '#64164'
|
||||
url: https://github.com/apache/airflow/pull/64164
|
||||
- description: >
|
||||
Support tpl rendering in ServiceAccount annotations, metadataConnection, and config ConfigMap names
|
||||
kind: added
|
||||
links:
|
||||
- name: '#64763'
|
||||
url: https://github.com/apache/airflow/pull/64763
|
||||
- description: Generate JWT Secret of recommended length
|
||||
kind: changed
|
||||
links:
|
||||
- name: '#65082'
|
||||
url: https://github.com/apache/airflow/pull/65082
|
||||
- description: Fix Helm chart image volume schema validation
|
||||
kind: fixed
|
||||
links:
|
||||
- name: '#65409'
|
||||
url: https://github.com/apache/airflow/pull/65409
|
||||
- description: Remove duplicate fallback branch in airflowPodSecurityContextsIds helper
|
||||
kind: fixed
|
||||
links:
|
||||
- name: '#65558'
|
||||
url: https://github.com/apache/airflow/pull/65558
|
||||
- description: Render cleanup RBAC only for KubernetesExecutor
|
||||
kind: fixed
|
||||
links:
|
||||
- name: '#65539'
|
||||
url: https://github.com/apache/airflow/pull/65539
|
||||
- description: Fix default args/command for database cleanup
|
||||
kind: fixed
|
||||
links:
|
||||
- name: '#63821'
|
||||
url: https://github.com/apache/airflow/pull/63821
|
||||
- description: Fix invalid deprecation warning in NOTES.txt
|
||||
kind: fixed
|
||||
links:
|
||||
- name: '#64296'
|
||||
url: https://github.com/apache/airflow/pull/64296
|
||||
- description: Add missing fields in schema file
|
||||
kind: fixed
|
||||
links:
|
||||
- name: '#64339'
|
||||
url: https://github.com/apache/airflow/pull/64339
|
||||
artifacthub.io/links: |
|
||||
- name: Documentation
|
||||
url: https://airflow.apache.org/docs/helm-chart/1.21.0/
|
||||
artifacthub.io/screenshots: |
|
||||
- title: Home Page
|
||||
url: https://airflow.apache.org/docs/apache-airflow/3.2.0/_images/home_dark.png
|
||||
- title: DAG Overview Dashboard
|
||||
url: https://airflow.apache.org/docs/apache-airflow/3.2.0/_images/dag_overview_dashboard.png
|
||||
- title: DAGs View
|
||||
url: https://airflow.apache.org/docs/apache-airflow/3.2.0/_images/dags.png
|
||||
- title: Assets View
|
||||
url: https://airflow.apache.org/docs/apache-airflow/3.2.0/_images/asset_view.png
|
||||
- title: Grid View
|
||||
url: https://airflow.apache.org/docs/apache-airflow/3.2.0/_images/dag_overview_grid.png
|
||||
- title: Graph View
|
||||
url: https://airflow.apache.org/docs/apache-airflow/3.2.0/_images/dag_overview_graph.png
|
||||
- title: Variable View
|
||||
url: https://airflow.apache.org/docs/apache-airflow/3.2.0/_images/variable_hidden.png
|
||||
- title: Code View
|
||||
url: https://airflow.apache.org/docs/apache-airflow/3.2.0/_images/dag_overview_code.png
|
||||
apiVersion: v2
|
||||
appVersion: 3.2.0
|
||||
dependencies:
|
||||
- condition: postgresql.enabled
|
||||
name: postgresql
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
version: 13.2.24
|
||||
description: The official Helm chart to deploy Apache Airflow, a platform to programmatically
|
||||
author, schedule, and monitor workflows
|
||||
home: https://airflow.apache.org/
|
||||
icon: https://airflow.apache.org/images/airflow_dark_bg.png
|
||||
keywords:
|
||||
- apache
|
||||
- airflow
|
||||
- workflow
|
||||
- scheduler
|
||||
maintainers:
|
||||
- email: dev@airflow.apache.org
|
||||
name: Apache Airflow PMC
|
||||
name: airflow
|
||||
sources:
|
||||
- https://github.com/apache/airflow
|
||||
type: application
|
||||
version: 1.21.0
|
||||
14
charts/airflow/INSTALL
Normal file
14
charts/airflow/INSTALL
Normal file
@ -0,0 +1,14 @@
|
||||
## INSTALL / BUILD instructions for Apache Airflow Chart
|
||||
|
||||
# The Assumption here is that you have a running Kubernetes cluster
|
||||
# and helm installed & configured to talk with the cluster
|
||||
|
||||
# Run `helm install` Command
|
||||
helm install airflow .
|
||||
|
||||
# If you want to install in a particular namespace
|
||||
## Create that namespace (example 'airflow' here, change it as needed)
|
||||
kubectl create namespace airflow
|
||||
|
||||
## Install the chart in that namespace
|
||||
helm install airflow -n airflow .
|
||||
201
charts/airflow/LICENSE
Normal file
201
charts/airflow/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
17
charts/airflow/NOTICE
Normal file
17
charts/airflow/NOTICE
Normal file
@ -0,0 +1,17 @@
|
||||
Apache Airflow
|
||||
Copyright 2016-2026 The Apache Software Foundation
|
||||
|
||||
This product includes software developed at The Apache Software
|
||||
Foundation (http://www.apache.org/).
|
||||
=======================================================================
|
||||
|
||||
postgresql:
|
||||
-----
|
||||
This product contains vendored-in postgresql Helm chart.
|
||||
|
||||
Copyright © 2022 Bitnami
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||
75
charts/airflow/README.md
Normal file
75
charts/airflow/README.md
Normal file
@ -0,0 +1,75 @@
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Helm Chart for Apache Airflow
|
||||
|
||||
[](https://artifacthub.io/packages/search?repo=apache-airflow)
|
||||
|
||||
[Apache Airflow](https://airflow.apache.org/) is a platform to programmatically author, schedule and monitor workflows.
|
||||
|
||||
## Introduction
|
||||
|
||||
This chart will bootstrap an [Airflow](https://airflow.apache.org) deployment on a [Kubernetes](http://kubernetes.io)
|
||||
cluster using the [Helm](https://helm.sh) package manager.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Kubernetes 1.30+ cluster
|
||||
- Helm 3.0+
|
||||
- PV provisioner support in the underlying infrastructure (optionally)
|
||||
|
||||
## Features
|
||||
|
||||
* Supported executors (all Airflow versions): ``LocalExecutor``, ``CeleryExecutor``, ``KubernetesExecutor``
|
||||
* Supported executors (Airflow version ``2.11.X``): ``LocalKubernetesExecutor``, ``CeleryKubernetesExecutor``
|
||||
* Supported multiple Executors (``2.11+``)
|
||||
* Supported AWS executors with AWS provider version ``8.21.0+``:
|
||||
* ``airflow.providers.amazon.aws.executors.batch.AwsBatchExecutor``
|
||||
* ``airflow.providers.amazon.aws.executors.ecs.AwsEcsExecutor``
|
||||
* Supported Edge executor with edge3 provider version ``1.0.0+``:
|
||||
* ``airflow.providers.edge3.executors.EdgeExecutor``
|
||||
* Supported Airflow version: ``2.11+``, ``3.0+``
|
||||
* Supported database backend: ``PostgreSQL``, ``MySQL``
|
||||
* Autoscaling for ``CeleryExecutor`` provided by KEDA
|
||||
* ``PostgreSQL`` and ``PgBouncer`` with a battle-tested configuration
|
||||
* **Security enhancements**:
|
||||
* Container-specific Service Account Token Volume configuration implementing Principle of Least Privilege
|
||||
* Only scheduler containers receive API access; init and sidecar containers operate without tokens
|
||||
* Defense-in-depth security with both ServiceAccount and Pod-level controls
|
||||
* Compatibility with security policies like Kyverno and compliance frameworks
|
||||
* Monitoring:
|
||||
* StatsD/Prometheus metrics for Airflow
|
||||
* Prometheus metrics for PgBouncer
|
||||
* Flower
|
||||
* Automatic database migration after a new deployment
|
||||
* Administrator account creation during deployment
|
||||
* Kerberos secure configuration
|
||||
* One-command deployment for any type of executor. You don't need to provide other services e.g. Redis/Database to test the Airflow.
|
||||
|
||||
## Documentation
|
||||
|
||||
Full documentation for Helm Chart (latest **stable** release) lives [on the website](https://airflow.apache.org/docs/helm-chart/).
|
||||
|
||||
> Note: If you're looking for documentation for main branch (latest development branch): you can find it on [s.apache.org/airflow-docs/](http://apache-airflow-docs.s3-website.eu-central-1.amazonaws.com/docs/helm-chart/stable/index.html).
|
||||
> Source code for documentation is in [../docs/helm-chart](https://github.com/apache/airflow/tree/main/docs/helm-chart)
|
||||
>
|
||||
|
||||
## Contributing
|
||||
|
||||
Want to help build Apache Airflow? Check out our [contributing documentation](https://github.com/apache/airflow/blob/main/contributing-docs/README.rst).
|
||||
1695
charts/airflow/RELEASE_NOTES.rst
Normal file
1695
charts/airflow/RELEASE_NOTES.rst
Normal file
File diff suppressed because it is too large
Load Diff
21
charts/airflow/charts/postgresql/.helmignore
Normal file
21
charts/airflow/charts/postgresql/.helmignore
Normal file
@ -0,0 +1,21 @@
|
||||
# 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
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
6
charts/airflow/charts/postgresql/Chart.lock
Normal file
6
charts/airflow/charts/postgresql/Chart.lock
Normal file
@ -0,0 +1,6 @@
|
||||
dependencies:
|
||||
- name: common
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
version: 2.13.3
|
||||
digest: sha256:9a971689db0c66ea95ac2e911c05014c2b96c6077c991131ff84f2982f88fb83
|
||||
generated: "2023-11-03T20:45:06.276989379Z"
|
||||
37
charts/airflow/charts/postgresql/Chart.yaml
Normal file
37
charts/airflow/charts/postgresql/Chart.yaml
Normal file
@ -0,0 +1,37 @@
|
||||
annotations:
|
||||
category: Database
|
||||
images: |
|
||||
- name: os-shell
|
||||
image: docker.io/bitnami/os-shell:11-debian-11-r91
|
||||
- name: postgres-exporter
|
||||
image: docker.io/bitnami/postgres-exporter:0.15.0-debian-11-r2
|
||||
- name: postgresql
|
||||
image: docker.io/bitnami/postgresql:16.1.0-debian-11-r15
|
||||
licenses: Apache-2.0
|
||||
apiVersion: v2
|
||||
appVersion: 16.1.0
|
||||
dependencies:
|
||||
- name: common
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
tags:
|
||||
- bitnami-common
|
||||
version: 2.x.x
|
||||
description: PostgreSQL (Postgres) is an open source object-relational database known
|
||||
for reliability and data integrity. ACID-compliant, it supports foreign keys, joins,
|
||||
views, triggers and stored procedures.
|
||||
home: https://bitnami.com
|
||||
icon: https://bitnami.com/assets/stacks/postgresql/img/postgresql-stack-220x234.png
|
||||
keywords:
|
||||
- postgresql
|
||||
- postgres
|
||||
- database
|
||||
- sql
|
||||
- replication
|
||||
- cluster
|
||||
maintainers:
|
||||
- name: VMware, Inc.
|
||||
url: https://github.com/bitnami/charts
|
||||
name: postgresql
|
||||
sources:
|
||||
- https://github.com/bitnami/charts/tree/main/bitnami/postgresql
|
||||
version: 13.2.24
|
||||
755
charts/airflow/charts/postgresql/README.md
Normal file
755
charts/airflow/charts/postgresql/README.md
Normal file
@ -0,0 +1,755 @@
|
||||
<!--- app-name: PostgreSQL -->
|
||||
|
||||
# Bitnami package for PostgreSQL
|
||||
|
||||
PostgreSQL (Postgres) is an open source object-relational database known for reliability and data integrity. ACID-compliant, it supports foreign keys, joins, views, triggers and stored procedures.
|
||||
|
||||
[Overview of PostgreSQL](http://www.postgresql.org)
|
||||
|
||||
Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement.
|
||||
|
||||
## TL;DR
|
||||
|
||||
```console
|
||||
helm install my-release oci://registry-1.docker.io/bitnamicharts/postgresql
|
||||
```
|
||||
|
||||
Looking to use PostgreSQL in production? Try [VMware Tanzu Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog.
|
||||
|
||||
## Introduction
|
||||
|
||||
This chart bootstraps a [PostgreSQL](https://github.com/bitnami/containers/tree/main/bitnami/postgresql) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
|
||||
|
||||
For HA, please see [this repo](https://github.com/bitnami/charts/tree/main/bitnami/postgresql-ha)
|
||||
|
||||
Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Kubernetes 1.23+
|
||||
- Helm 3.8.0+
|
||||
- PV provisioner support in the underlying infrastructure
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
To install the chart with the release name `my-release`:
|
||||
|
||||
```console
|
||||
helm install my-release oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql
|
||||
```
|
||||
|
||||
> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`.
|
||||
|
||||
The command deploys PostgreSQL on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation.
|
||||
|
||||
> **Tip**: List all releases using `helm list`
|
||||
|
||||
## Uninstalling the Chart
|
||||
|
||||
To uninstall/delete the `my-release` deployment:
|
||||
|
||||
```console
|
||||
helm delete my-release
|
||||
```
|
||||
|
||||
The command removes all the Kubernetes components but PVC's associated with the chart and deletes the release.
|
||||
|
||||
To delete the PVC's associated with `my-release`:
|
||||
|
||||
```console
|
||||
kubectl delete pvc -l release=my-release
|
||||
```
|
||||
|
||||
> **Note**: Deleting the PVC's will delete postgresql data as well. Please be cautious before doing it.
|
||||
|
||||
## Parameters
|
||||
|
||||
### Global parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
|
||||
| `global.imageRegistry` | Global Docker image registry | `""` |
|
||||
| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` |
|
||||
| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` |
|
||||
| `global.postgresql.auth.postgresPassword` | Password for the "postgres" admin user (overrides `auth.postgresPassword`) | `""` |
|
||||
| `global.postgresql.auth.username` | Name for a custom user to create (overrides `auth.username`) | `""` |
|
||||
| `global.postgresql.auth.password` | Password for the custom user to create (overrides `auth.password`) | `""` |
|
||||
| `global.postgresql.auth.database` | Name for a custom database to create (overrides `auth.database`) | `""` |
|
||||
| `global.postgresql.auth.existingSecret` | Name of existing secret to use for PostgreSQL credentials (overrides `auth.existingSecret`). | `""` |
|
||||
| `global.postgresql.auth.secretKeys.adminPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.adminPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. | `""` |
|
||||
| `global.postgresql.auth.secretKeys.userPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.userPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. | `""` |
|
||||
| `global.postgresql.auth.secretKeys.replicationPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.replicationPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. | `""` |
|
||||
| `global.postgresql.service.ports.postgresql` | PostgreSQL service port (overrides `service.ports.postgresql`) | `""` |
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------- | --------------- |
|
||||
| `kubeVersion` | Override Kubernetes version | `""` |
|
||||
| `nameOverride` | String to partially override common.names.fullname template (will maintain the release name) | `""` |
|
||||
| `fullnameOverride` | String to fully override common.names.fullname template | `""` |
|
||||
| `clusterDomain` | Kubernetes Cluster Domain | `cluster.local` |
|
||||
| `extraDeploy` | Array of extra objects to deploy with the release (evaluated as a template) | `[]` |
|
||||
| `commonLabels` | Add labels to all the deployed resources | `{}` |
|
||||
| `commonAnnotations` | Add annotations to all the deployed resources | `{}` |
|
||||
| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` |
|
||||
| `diagnosticMode.command` | Command to override all containers in the statefulset | `["sleep"]` |
|
||||
| `diagnosticMode.args` | Args to override all containers in the statefulset | `["infinity"]` |
|
||||
|
||||
### PostgreSQL common parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
|
||||
| `image.registry` | PostgreSQL image registry | `REGISTRY_NAME` |
|
||||
| `image.repository` | PostgreSQL image repository | `REPOSITORY_NAME/postgresql` |
|
||||
| `image.digest` | PostgreSQL image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` |
|
||||
| `image.pullPolicy` | PostgreSQL image pull policy | `IfNotPresent` |
|
||||
| `image.pullSecrets` | Specify image pull secrets | `[]` |
|
||||
| `image.debug` | Specify if debug values should be set | `false` |
|
||||
| `auth.enablePostgresUser` | Assign a password to the "postgres" admin user. Otherwise, remote access will be blocked for this user | `true` |
|
||||
| `auth.postgresPassword` | Password for the "postgres" admin user. Ignored if `auth.existingSecret` is provided | `""` |
|
||||
| `auth.username` | Name for a custom user to create | `""` |
|
||||
| `auth.password` | Password for the custom user to create. Ignored if `auth.existingSecret` is provided | `""` |
|
||||
| `auth.database` | Name for a custom database to create | `""` |
|
||||
| `auth.replicationUsername` | Name of the replication user | `repl_user` |
|
||||
| `auth.replicationPassword` | Password for the replication user. Ignored if `auth.existingSecret` is provided | `""` |
|
||||
| `auth.existingSecret` | Name of existing secret to use for PostgreSQL credentials. `auth.postgresPassword`, `auth.password`, and `auth.replicationPassword` will be ignored and picked up from this secret. The secret might also contains the key `ldap-password` if LDAP is enabled. `ldap.bind_password` will be ignored and picked from this secret in this case. | `""` |
|
||||
| `auth.secretKeys.adminPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. | `postgres-password` |
|
||||
| `auth.secretKeys.userPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. | `password` |
|
||||
| `auth.secretKeys.replicationPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. | `replication-password` |
|
||||
| `auth.usePasswordFiles` | Mount credentials as a files instead of using an environment variable | `false` |
|
||||
| `architecture` | PostgreSQL architecture (`standalone` or `replication`) | `standalone` |
|
||||
| `replication.synchronousCommit` | Set synchronous commit mode. Allowed values: `on`, `remote_apply`, `remote_write`, `local` and `off` | `off` |
|
||||
| `replication.numSynchronousReplicas` | Number of replicas that will have synchronous replication. Note: Cannot be greater than `readReplicas.replicaCount`. | `0` |
|
||||
| `replication.applicationName` | Cluster application name. Useful for advanced replication settings | `my_application` |
|
||||
| `containerPorts.postgresql` | PostgreSQL container port | `5432` |
|
||||
| `audit.logHostname` | Log client hostnames | `false` |
|
||||
| `audit.logConnections` | Add client log-in operations to the log file | `false` |
|
||||
| `audit.logDisconnections` | Add client log-outs operations to the log file | `false` |
|
||||
| `audit.pgAuditLog` | Add operations to log using the pgAudit extension | `""` |
|
||||
| `audit.pgAuditLogCatalog` | Log catalog using pgAudit | `off` |
|
||||
| `audit.clientMinMessages` | Message log level to share with the user | `error` |
|
||||
| `audit.logLinePrefix` | Template for log line prefix (default if not set) | `""` |
|
||||
| `audit.logTimezone` | Timezone for the log timestamps | `""` |
|
||||
| `ldap.enabled` | Enable LDAP support | `false` |
|
||||
| `ldap.server` | IP address or name of the LDAP server. | `""` |
|
||||
| `ldap.port` | Port number on the LDAP server to connect to | `""` |
|
||||
| `ldap.prefix` | String to prepend to the user name when forming the DN to bind | `""` |
|
||||
| `ldap.suffix` | String to append to the user name when forming the DN to bind | `""` |
|
||||
| `ldap.basedn` | Root DN to begin the search for the user in | `""` |
|
||||
| `ldap.binddn` | DN of user to bind to LDAP | `""` |
|
||||
| `ldap.bindpw` | Password for the user to bind to LDAP | `""` |
|
||||
| `ldap.searchAttribute` | Attribute to match against the user name in the search | `""` |
|
||||
| `ldap.searchFilter` | The search filter to use when doing search+bind authentication | `""` |
|
||||
| `ldap.scheme` | Set to `ldaps` to use LDAPS | `""` |
|
||||
| `ldap.tls.enabled` | Se to true to enable TLS encryption | `false` |
|
||||
| `ldap.uri` | LDAP URL beginning in the form `ldap[s]://host[:port]/basedn`. If provided, all the other LDAP parameters will be ignored. | `""` |
|
||||
| `postgresqlDataDir` | PostgreSQL data dir folder | `/bitnami/postgresql/data` |
|
||||
| `postgresqlSharedPreloadLibraries` | Shared preload libraries (comma-separated list) | `pgaudit` |
|
||||
| `shmVolume.enabled` | Enable emptyDir volume for /dev/shm for PostgreSQL pod(s) | `true` |
|
||||
| `shmVolume.sizeLimit` | Set this to enable a size limit on the shm tmpfs | `""` |
|
||||
| `tls.enabled` | Enable TLS traffic support | `false` |
|
||||
| `tls.autoGenerated` | Generate automatically self-signed TLS certificates | `false` |
|
||||
| `tls.preferServerCiphers` | Whether to use the server's TLS cipher preferences rather than the client's | `true` |
|
||||
| `tls.certificatesSecret` | Name of an existing secret that contains the certificates | `""` |
|
||||
| `tls.certFilename` | Certificate filename | `""` |
|
||||
| `tls.certKeyFilename` | Certificate key filename | `""` |
|
||||
| `tls.certCAFilename` | CA Certificate filename | `""` |
|
||||
| `tls.crlFilename` | File containing a Certificate Revocation List | `""` |
|
||||
|
||||
### PostgreSQL Primary parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------- |
|
||||
| `primary.name` | Name of the primary database (eg primary, master, leader, ...) | `primary` |
|
||||
| `primary.configuration` | PostgreSQL Primary main configuration to be injected as ConfigMap | `""` |
|
||||
| `primary.pgHbaConfiguration` | PostgreSQL Primary client authentication configuration | `""` |
|
||||
| `primary.existingConfigmap` | Name of an existing ConfigMap with PostgreSQL Primary configuration | `""` |
|
||||
| `primary.extendedConfiguration` | Extended PostgreSQL Primary configuration (appended to main or default configuration) | `""` |
|
||||
| `primary.existingExtendedConfigmap` | Name of an existing ConfigMap with PostgreSQL Primary extended configuration | `""` |
|
||||
| `primary.initdb.args` | PostgreSQL initdb extra arguments | `""` |
|
||||
| `primary.initdb.postgresqlWalDir` | Specify a custom location for the PostgreSQL transaction log | `""` |
|
||||
| `primary.initdb.scripts` | Dictionary of initdb scripts | `{}` |
|
||||
| `primary.initdb.scriptsConfigMap` | ConfigMap with scripts to be run at first boot | `""` |
|
||||
| `primary.initdb.scriptsSecret` | Secret with scripts to be run at first boot (in case it contains sensitive information) | `""` |
|
||||
| `primary.initdb.user` | Specify the PostgreSQL username to execute the initdb scripts | `""` |
|
||||
| `primary.initdb.password` | Specify the PostgreSQL password to execute the initdb scripts | `""` |
|
||||
| `primary.standby.enabled` | Whether to enable current cluster's primary as standby server of another cluster or not | `false` |
|
||||
| `primary.standby.primaryHost` | The Host of replication primary in the other cluster | `""` |
|
||||
| `primary.standby.primaryPort` | The Port of replication primary in the other cluster | `""` |
|
||||
| `primary.extraEnvVars` | Array with extra environment variables to add to PostgreSQL Primary nodes | `[]` |
|
||||
| `primary.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for PostgreSQL Primary nodes | `""` |
|
||||
| `primary.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for PostgreSQL Primary nodes | `""` |
|
||||
| `primary.command` | Override default container command (useful when using custom images) | `[]` |
|
||||
| `primary.args` | Override default container args (useful when using custom images) | `[]` |
|
||||
| `primary.livenessProbe.enabled` | Enable livenessProbe on PostgreSQL Primary containers | `true` |
|
||||
| `primary.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` |
|
||||
| `primary.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` |
|
||||
| `primary.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` |
|
||||
| `primary.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` |
|
||||
| `primary.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` |
|
||||
| `primary.readinessProbe.enabled` | Enable readinessProbe on PostgreSQL Primary containers | `true` |
|
||||
| `primary.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` |
|
||||
| `primary.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` |
|
||||
| `primary.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` |
|
||||
| `primary.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` |
|
||||
| `primary.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` |
|
||||
| `primary.startupProbe.enabled` | Enable startupProbe on PostgreSQL Primary containers | `false` |
|
||||
| `primary.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `30` |
|
||||
| `primary.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` |
|
||||
| `primary.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` |
|
||||
| `primary.startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` |
|
||||
| `primary.startupProbe.successThreshold` | Success threshold for startupProbe | `1` |
|
||||
| `primary.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` |
|
||||
| `primary.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` |
|
||||
| `primary.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` |
|
||||
| `primary.lifecycleHooks` | for the PostgreSQL Primary container to automate configuration before or after startup | `{}` |
|
||||
| `primary.resources.limits` | The resources limits for the PostgreSQL Primary containers | `{}` |
|
||||
| `primary.resources.requests.memory` | The requested memory for the PostgreSQL Primary containers | `256Mi` |
|
||||
| `primary.resources.requests.cpu` | The requested cpu for the PostgreSQL Primary containers | `250m` |
|
||||
| `primary.podSecurityContext.enabled` | Enable security context | `true` |
|
||||
| `primary.podSecurityContext.fsGroup` | Group ID for the pod | `1001` |
|
||||
| `primary.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` |
|
||||
| `primary.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` |
|
||||
| `primary.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` |
|
||||
| `primary.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` |
|
||||
| `primary.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` |
|
||||
| `primary.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` |
|
||||
| `primary.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` |
|
||||
| `primary.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` |
|
||||
| `primary.hostAliases` | PostgreSQL primary pods host aliases | `[]` |
|
||||
| `primary.hostNetwork` | Specify if host network should be enabled for PostgreSQL pod (postgresql primary) | `false` |
|
||||
| `primary.hostIPC` | Specify if host IPC should be enabled for PostgreSQL pod (postgresql primary) | `false` |
|
||||
| `primary.labels` | Map of labels to add to the statefulset (postgresql primary) | `{}` |
|
||||
| `primary.annotations` | Annotations for PostgreSQL primary pods | `{}` |
|
||||
| `primary.podLabels` | Map of labels to add to the pods (postgresql primary) | `{}` |
|
||||
| `primary.podAnnotations` | Map of annotations to add to the pods (postgresql primary) | `{}` |
|
||||
| `primary.podAffinityPreset` | PostgreSQL primary pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` |
|
||||
| `primary.podAntiAffinityPreset` | PostgreSQL primary pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `soft` |
|
||||
| `primary.nodeAffinityPreset.type` | PostgreSQL primary node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` |
|
||||
| `primary.nodeAffinityPreset.key` | PostgreSQL primary node label key to match Ignored if `primary.affinity` is set. | `""` |
|
||||
| `primary.nodeAffinityPreset.values` | PostgreSQL primary node label values to match. Ignored if `primary.affinity` is set. | `[]` |
|
||||
| `primary.affinity` | Affinity for PostgreSQL primary pods assignment | `{}` |
|
||||
| `primary.nodeSelector` | Node labels for PostgreSQL primary pods assignment | `{}` |
|
||||
| `primary.tolerations` | Tolerations for PostgreSQL primary pods assignment | `[]` |
|
||||
| `primary.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` |
|
||||
| `primary.priorityClassName` | Priority Class to use for each pod (postgresql primary) | `""` |
|
||||
| `primary.schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` |
|
||||
| `primary.terminationGracePeriodSeconds` | Seconds PostgreSQL primary pod needs to terminate gracefully | `""` |
|
||||
| `primary.updateStrategy.type` | PostgreSQL Primary statefulset strategy type | `RollingUpdate` |
|
||||
| `primary.updateStrategy.rollingUpdate` | PostgreSQL Primary statefulset rolling update configuration parameters | `{}` |
|
||||
| `primary.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the PostgreSQL Primary container(s) | `[]` |
|
||||
| `primary.extraVolumes` | Optionally specify extra list of additional volumes for the PostgreSQL Primary pod(s) | `[]` |
|
||||
| `primary.sidecars` | Add additional sidecar containers to the PostgreSQL Primary pod(s) | `[]` |
|
||||
| `primary.initContainers` | Add additional init containers to the PostgreSQL Primary pod(s) | `[]` |
|
||||
| `primary.extraPodSpec` | Optionally specify extra PodSpec for the PostgreSQL Primary pod(s) | `{}` |
|
||||
| `primary.service.type` | Kubernetes Service type | `ClusterIP` |
|
||||
| `primary.service.ports.postgresql` | PostgreSQL service port | `5432` |
|
||||
| `primary.service.nodePorts.postgresql` | Node port for PostgreSQL | `""` |
|
||||
| `primary.service.clusterIP` | Static clusterIP or None for headless services | `""` |
|
||||
| `primary.service.annotations` | Annotations for PostgreSQL primary service | `{}` |
|
||||
| `primary.service.loadBalancerIP` | Load balancer IP if service type is `LoadBalancer` | `""` |
|
||||
| `primary.service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` |
|
||||
| `primary.service.loadBalancerSourceRanges` | Addresses that are allowed when service is LoadBalancer | `[]` |
|
||||
| `primary.service.extraPorts` | Extra ports to expose in the PostgreSQL primary service | `[]` |
|
||||
| `primary.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` |
|
||||
| `primary.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` |
|
||||
| `primary.service.headless.annotations` | Additional custom annotations for headless PostgreSQL primary service | `{}` |
|
||||
| `primary.persistence.enabled` | Enable PostgreSQL Primary data persistence using PVC | `true` |
|
||||
| `primary.persistence.existingClaim` | Name of an existing PVC to use | `""` |
|
||||
| `primary.persistence.mountPath` | The path the volume will be mounted at | `/bitnami/postgresql` |
|
||||
| `primary.persistence.subPath` | The subdirectory of the volume to mount to | `""` |
|
||||
| `primary.persistence.storageClass` | PVC Storage Class for PostgreSQL Primary data volume | `""` |
|
||||
| `primary.persistence.accessModes` | PVC Access Mode for PostgreSQL volume | `["ReadWriteOnce"]` |
|
||||
| `primary.persistence.size` | PVC Storage Request for PostgreSQL volume | `8Gi` |
|
||||
| `primary.persistence.annotations` | Annotations for the PVC | `{}` |
|
||||
| `primary.persistence.labels` | Labels for the PVC | `{}` |
|
||||
| `primary.persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` |
|
||||
| `primary.persistence.dataSource` | Custom PVC data source | `{}` |
|
||||
| `primary.persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for Primary Statefulset | `false` |
|
||||
| `primary.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` |
|
||||
| `primary.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` |
|
||||
|
||||
### PostgreSQL read only replica parameters (only used when `architecture` is set to `replication`)
|
||||
|
||||
| Name | Description | Value |
|
||||
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------- |
|
||||
| `readReplicas.name` | Name of the read replicas database (eg secondary, slave, ...) | `read` |
|
||||
| `readReplicas.replicaCount` | Number of PostgreSQL read only replicas | `1` |
|
||||
| `readReplicas.extendedConfiguration` | Extended PostgreSQL read only replicas configuration (appended to main or default configuration) | `""` |
|
||||
| `readReplicas.extraEnvVars` | Array with extra environment variables to add to PostgreSQL read only nodes | `[]` |
|
||||
| `readReplicas.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for PostgreSQL read only nodes | `""` |
|
||||
| `readReplicas.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for PostgreSQL read only nodes | `""` |
|
||||
| `readReplicas.command` | Override default container command (useful when using custom images) | `[]` |
|
||||
| `readReplicas.args` | Override default container args (useful when using custom images) | `[]` |
|
||||
| `readReplicas.livenessProbe.enabled` | Enable livenessProbe on PostgreSQL read only containers | `true` |
|
||||
| `readReplicas.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` |
|
||||
| `readReplicas.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` |
|
||||
| `readReplicas.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` |
|
||||
| `readReplicas.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` |
|
||||
| `readReplicas.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` |
|
||||
| `readReplicas.readinessProbe.enabled` | Enable readinessProbe on PostgreSQL read only containers | `true` |
|
||||
| `readReplicas.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` |
|
||||
| `readReplicas.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` |
|
||||
| `readReplicas.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` |
|
||||
| `readReplicas.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` |
|
||||
| `readReplicas.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` |
|
||||
| `readReplicas.startupProbe.enabled` | Enable startupProbe on PostgreSQL read only containers | `false` |
|
||||
| `readReplicas.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `30` |
|
||||
| `readReplicas.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` |
|
||||
| `readReplicas.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` |
|
||||
| `readReplicas.startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` |
|
||||
| `readReplicas.startupProbe.successThreshold` | Success threshold for startupProbe | `1` |
|
||||
| `readReplicas.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` |
|
||||
| `readReplicas.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` |
|
||||
| `readReplicas.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` |
|
||||
| `readReplicas.lifecycleHooks` | for the PostgreSQL read only container to automate configuration before or after startup | `{}` |
|
||||
| `readReplicas.resources.limits` | The resources limits for the PostgreSQL read only containers | `{}` |
|
||||
| `readReplicas.resources.requests.memory` | The requested memory for the PostgreSQL read only containers | `256Mi` |
|
||||
| `readReplicas.resources.requests.cpu` | The requested cpu for the PostgreSQL read only containers | `250m` |
|
||||
| `readReplicas.podSecurityContext.enabled` | Enable security context | `true` |
|
||||
| `readReplicas.podSecurityContext.fsGroup` | Group ID for the pod | `1001` |
|
||||
| `readReplicas.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` |
|
||||
| `readReplicas.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` |
|
||||
| `readReplicas.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` |
|
||||
| `readReplicas.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` |
|
||||
| `readReplicas.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` |
|
||||
| `readReplicas.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` |
|
||||
| `readReplicas.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` |
|
||||
| `readReplicas.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` |
|
||||
| `readReplicas.hostAliases` | PostgreSQL read only pods host aliases | `[]` |
|
||||
| `readReplicas.hostNetwork` | Specify if host network should be enabled for PostgreSQL pod (PostgreSQL read only) | `false` |
|
||||
| `readReplicas.hostIPC` | Specify if host IPC should be enabled for PostgreSQL pod (postgresql primary) | `false` |
|
||||
| `readReplicas.labels` | Map of labels to add to the statefulset (PostgreSQL read only) | `{}` |
|
||||
| `readReplicas.annotations` | Annotations for PostgreSQL read only pods | `{}` |
|
||||
| `readReplicas.podLabels` | Map of labels to add to the pods (PostgreSQL read only) | `{}` |
|
||||
| `readReplicas.podAnnotations` | Map of annotations to add to the pods (PostgreSQL read only) | `{}` |
|
||||
| `readReplicas.podAffinityPreset` | PostgreSQL read only pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` |
|
||||
| `readReplicas.podAntiAffinityPreset` | PostgreSQL read only pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `soft` |
|
||||
| `readReplicas.nodeAffinityPreset.type` | PostgreSQL read only node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` |
|
||||
| `readReplicas.nodeAffinityPreset.key` | PostgreSQL read only node label key to match Ignored if `primary.affinity` is set. | `""` |
|
||||
| `readReplicas.nodeAffinityPreset.values` | PostgreSQL read only node label values to match. Ignored if `primary.affinity` is set. | `[]` |
|
||||
| `readReplicas.affinity` | Affinity for PostgreSQL read only pods assignment | `{}` |
|
||||
| `readReplicas.nodeSelector` | Node labels for PostgreSQL read only pods assignment | `{}` |
|
||||
| `readReplicas.tolerations` | Tolerations for PostgreSQL read only pods assignment | `[]` |
|
||||
| `readReplicas.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` |
|
||||
| `readReplicas.priorityClassName` | Priority Class to use for each pod (PostgreSQL read only) | `""` |
|
||||
| `readReplicas.schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` |
|
||||
| `readReplicas.terminationGracePeriodSeconds` | Seconds PostgreSQL read only pod needs to terminate gracefully | `""` |
|
||||
| `readReplicas.updateStrategy.type` | PostgreSQL read only statefulset strategy type | `RollingUpdate` |
|
||||
| `readReplicas.updateStrategy.rollingUpdate` | PostgreSQL read only statefulset rolling update configuration parameters | `{}` |
|
||||
| `readReplicas.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the PostgreSQL read only container(s) | `[]` |
|
||||
| `readReplicas.extraVolumes` | Optionally specify extra list of additional volumes for the PostgreSQL read only pod(s) | `[]` |
|
||||
| `readReplicas.sidecars` | Add additional sidecar containers to the PostgreSQL read only pod(s) | `[]` |
|
||||
| `readReplicas.initContainers` | Add additional init containers to the PostgreSQL read only pod(s) | `[]` |
|
||||
| `readReplicas.extraPodSpec` | Optionally specify extra PodSpec for the PostgreSQL read only pod(s) | `{}` |
|
||||
| `readReplicas.service.type` | Kubernetes Service type | `ClusterIP` |
|
||||
| `readReplicas.service.ports.postgresql` | PostgreSQL service port | `5432` |
|
||||
| `readReplicas.service.nodePorts.postgresql` | Node port for PostgreSQL | `""` |
|
||||
| `readReplicas.service.clusterIP` | Static clusterIP or None for headless services | `""` |
|
||||
| `readReplicas.service.annotations` | Annotations for PostgreSQL read only service | `{}` |
|
||||
| `readReplicas.service.loadBalancerIP` | Load balancer IP if service type is `LoadBalancer` | `""` |
|
||||
| `readReplicas.service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` |
|
||||
| `readReplicas.service.loadBalancerSourceRanges` | Addresses that are allowed when service is LoadBalancer | `[]` |
|
||||
| `readReplicas.service.extraPorts` | Extra ports to expose in the PostgreSQL read only service | `[]` |
|
||||
| `readReplicas.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` |
|
||||
| `readReplicas.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` |
|
||||
| `readReplicas.service.headless.annotations` | Additional custom annotations for headless PostgreSQL read only service | `{}` |
|
||||
| `readReplicas.persistence.enabled` | Enable PostgreSQL read only data persistence using PVC | `true` |
|
||||
| `readReplicas.persistence.existingClaim` | Name of an existing PVC to use | `""` |
|
||||
| `readReplicas.persistence.mountPath` | The path the volume will be mounted at | `/bitnami/postgresql` |
|
||||
| `readReplicas.persistence.subPath` | The subdirectory of the volume to mount to | `""` |
|
||||
| `readReplicas.persistence.storageClass` | PVC Storage Class for PostgreSQL read only data volume | `""` |
|
||||
| `readReplicas.persistence.accessModes` | PVC Access Mode for PostgreSQL volume | `["ReadWriteOnce"]` |
|
||||
| `readReplicas.persistence.size` | PVC Storage Request for PostgreSQL volume | `8Gi` |
|
||||
| `readReplicas.persistence.annotations` | Annotations for the PVC | `{}` |
|
||||
| `readReplicas.persistence.labels` | Labels for the PVC | `{}` |
|
||||
| `readReplicas.persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` |
|
||||
| `readReplicas.persistence.dataSource` | Custom PVC data source | `{}` |
|
||||
| `readReplicas.persistentVolumeClaimRetentionPolicy.enabled` | Enable Persistent volume retention policy for read only Statefulset | `false` |
|
||||
| `readReplicas.persistentVolumeClaimRetentionPolicy.whenScaled` | Volume retention behavior when the replica count of the StatefulSet is reduced | `Retain` |
|
||||
| `readReplicas.persistentVolumeClaimRetentionPolicy.whenDeleted` | Volume retention behavior that applies when the StatefulSet is deleted | `Retain` |
|
||||
|
||||
### Backup parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `backup.enabled` | Enable the logical dump of the database "regularly" | `false` |
|
||||
| `backup.cronjob.schedule` | Set the cronjob parameter schedule | `@daily` |
|
||||
| `backup.cronjob.timeZone` | Set the cronjob parameter timeZone | `""` |
|
||||
| `backup.cronjob.concurrencyPolicy` | Set the cronjob parameter concurrencyPolicy | `Allow` |
|
||||
| `backup.cronjob.failedJobsHistoryLimit` | Set the cronjob parameter failedJobsHistoryLimit | `1` |
|
||||
| `backup.cronjob.successfulJobsHistoryLimit` | Set the cronjob parameter successfulJobsHistoryLimit | `3` |
|
||||
| `backup.cronjob.startingDeadlineSeconds` | Set the cronjob parameter startingDeadlineSeconds | `""` |
|
||||
| `backup.cronjob.ttlSecondsAfterFinished` | Set the cronjob parameter ttlSecondsAfterFinished | `""` |
|
||||
| `backup.cronjob.restartPolicy` | Set the cronjob parameter restartPolicy | `OnFailure` |
|
||||
| `backup.cronjob.podSecurityContext.enabled` | Enable PodSecurityContext for CronJob/Backup | `true` |
|
||||
| `backup.cronjob.podSecurityContext.fsGroup` | Group ID for the CronJob | `1001` |
|
||||
| `backup.cronjob.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` |
|
||||
| `backup.cronjob.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` |
|
||||
| `backup.cronjob.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` |
|
||||
| `backup.cronjob.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` |
|
||||
| `backup.cronjob.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` |
|
||||
| `backup.cronjob.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` |
|
||||
| `backup.cronjob.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` |
|
||||
| `backup.cronjob.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` |
|
||||
| `backup.cronjob.command` | Set backup container's command to run | `["/bin/sh","-c","pg_dumpall --clean --if-exists --load-via-partition-root --quote-all-identifiers --no-password --file=${PGDUMP_DIR}/pg_dumpall-$(date '+%Y-%m-%d-%H-%M').pgdump"]` |
|
||||
| `backup.cronjob.labels` | Set the cronjob labels | `{}` |
|
||||
| `backup.cronjob.annotations` | Set the cronjob annotations | `{}` |
|
||||
| `backup.cronjob.nodeSelector` | Node labels for PostgreSQL backup CronJob pod assignment | `{}` |
|
||||
| `backup.cronjob.storage.existingClaim` | Provide an existing `PersistentVolumeClaim` (only when `architecture=standalone`) | `""` |
|
||||
| `backup.cronjob.storage.resourcePolicy` | Setting it to "keep" to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `""` |
|
||||
| `backup.cronjob.storage.storageClass` | PVC Storage Class for the backup data volume | `""` |
|
||||
| `backup.cronjob.storage.accessModes` | PV Access Mode | `["ReadWriteOnce"]` |
|
||||
| `backup.cronjob.storage.size` | PVC Storage Request for the backup data volume | `8Gi` |
|
||||
| `backup.cronjob.storage.annotations` | PVC annotations | `{}` |
|
||||
| `backup.cronjob.storage.mountPath` | Path to mount the volume at | `/backup/pgdump` |
|
||||
| `backup.cronjob.storage.subPath` | Subdirectory of the volume to mount at | `""` |
|
||||
| `backup.cronjob.storage.volumeClaimTemplates.selector` | A label query over volumes to consider for binding (e.g. when using local volumes) | `{}` |
|
||||
|
||||
### NetworkPolicy parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| `networkPolicy.enabled` | Enable network policies | `false` |
|
||||
| `networkPolicy.metrics.enabled` | Enable network policies for metrics (prometheus) | `false` |
|
||||
| `networkPolicy.metrics.namespaceSelector` | Monitoring namespace selector labels. These labels will be used to identify the prometheus' namespace. | `{}` |
|
||||
| `networkPolicy.metrics.podSelector` | Monitoring pod selector labels. These labels will be used to identify the Prometheus pods. | `{}` |
|
||||
| `networkPolicy.ingressRules.primaryAccessOnlyFrom.enabled` | Enable ingress rule that makes PostgreSQL primary node only accessible from a particular origin. | `false` |
|
||||
| `networkPolicy.ingressRules.primaryAccessOnlyFrom.namespaceSelector` | Namespace selector label that is allowed to access the PostgreSQL primary node. This label will be used to identified the allowed namespace(s). | `{}` |
|
||||
| `networkPolicy.ingressRules.primaryAccessOnlyFrom.podSelector` | Pods selector label that is allowed to access the PostgreSQL primary node. This label will be used to identified the allowed pod(s). | `{}` |
|
||||
| `networkPolicy.ingressRules.primaryAccessOnlyFrom.customRules` | Custom network policy for the PostgreSQL primary node. | `[]` |
|
||||
| `networkPolicy.ingressRules.readReplicasAccessOnlyFrom.enabled` | Enable ingress rule that makes PostgreSQL read-only nodes only accessible from a particular origin. | `false` |
|
||||
| `networkPolicy.ingressRules.readReplicasAccessOnlyFrom.namespaceSelector` | Namespace selector label that is allowed to access the PostgreSQL read-only nodes. This label will be used to identified the allowed namespace(s). | `{}` |
|
||||
| `networkPolicy.ingressRules.readReplicasAccessOnlyFrom.podSelector` | Pods selector label that is allowed to access the PostgreSQL read-only nodes. This label will be used to identified the allowed pod(s). | `{}` |
|
||||
| `networkPolicy.ingressRules.readReplicasAccessOnlyFrom.customRules` | Custom network policy for the PostgreSQL read-only nodes. | `[]` |
|
||||
| `networkPolicy.egressRules.denyConnectionsToExternal` | Enable egress rule that denies outgoing traffic outside the cluster, except for DNS (port 53). | `false` |
|
||||
| `networkPolicy.egressRules.customRules` | Custom network policy rule | `[]` |
|
||||
|
||||
### Volume Permissions parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
|
||||
| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume | `false` |
|
||||
| `volumePermissions.image.registry` | Init container volume-permissions image registry | `REGISTRY_NAME` |
|
||||
| `volumePermissions.image.repository` | Init container volume-permissions image repository | `REPOSITORY_NAME/os-shell` |
|
||||
| `volumePermissions.image.digest` | Init container volume-permissions image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` |
|
||||
| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` |
|
||||
| `volumePermissions.image.pullSecrets` | Init container volume-permissions image pull secrets | `[]` |
|
||||
| `volumePermissions.resources.limits` | Init container volume-permissions resource limits | `{}` |
|
||||
| `volumePermissions.resources.requests` | Init container volume-permissions resource requests | `{}` |
|
||||
| `volumePermissions.containerSecurityContext.runAsUser` | User ID for the init container | `0` |
|
||||
| `volumePermissions.containerSecurityContext.runAsGroup` | Group ID for the init container | `0` |
|
||||
| `volumePermissions.containerSecurityContext.runAsNonRoot` | runAsNonRoot for the init container | `false` |
|
||||
| `volumePermissions.containerSecurityContext.seccompProfile.type` | seccompProfile.type for the init container | `RuntimeDefault` |
|
||||
|
||||
### Other Parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| `serviceBindings.enabled` | Create secret for service binding (Experimental) | `false` |
|
||||
| `serviceAccount.create` | Enable creation of ServiceAccount for PostgreSQL pod | `false` |
|
||||
| `serviceAccount.name` | The name of the ServiceAccount to use. | `""` |
|
||||
| `serviceAccount.automountServiceAccountToken` | Allows auto mount of ServiceAccountToken on the serviceAccount created | `true` |
|
||||
| `serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` |
|
||||
| `rbac.create` | Create Role and RoleBinding (required for PSP to work) | `false` |
|
||||
| `rbac.rules` | Custom RBAC rules to set | `[]` |
|
||||
| `psp.create` | Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later | `false` |
|
||||
|
||||
### Metrics Parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------- |
|
||||
| `metrics.enabled` | Start a prometheus exporter | `false` |
|
||||
| `metrics.image.registry` | PostgreSQL Prometheus Exporter image registry | `REGISTRY_NAME` |
|
||||
| `metrics.image.repository` | PostgreSQL Prometheus Exporter image repository | `REPOSITORY_NAME/postgres-exporter` |
|
||||
| `metrics.image.digest` | PostgreSQL image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag | `""` |
|
||||
| `metrics.image.pullPolicy` | PostgreSQL Prometheus Exporter image pull policy | `IfNotPresent` |
|
||||
| `metrics.image.pullSecrets` | Specify image pull secrets | `[]` |
|
||||
| `metrics.collectors` | Control enabled collectors | `{}` |
|
||||
| `metrics.customMetrics` | Define additional custom metrics | `{}` |
|
||||
| `metrics.extraEnvVars` | Extra environment variables to add to PostgreSQL Prometheus exporter | `[]` |
|
||||
| `metrics.containerSecurityContext.enabled` | Enabled containers' Security Context | `true` |
|
||||
| `metrics.containerSecurityContext.runAsUser` | Set containers' Security Context runAsUser | `1001` |
|
||||
| `metrics.containerSecurityContext.runAsNonRoot` | Set container's Security Context runAsNonRoot | `true` |
|
||||
| `metrics.containerSecurityContext.privileged` | Set container's Security Context privileged | `false` |
|
||||
| `metrics.containerSecurityContext.readOnlyRootFilesystem` | Set container's Security Context readOnlyRootFilesystem | `false` |
|
||||
| `metrics.containerSecurityContext.allowPrivilegeEscalation` | Set container's Security Context allowPrivilegeEscalation | `false` |
|
||||
| `metrics.containerSecurityContext.capabilities.drop` | List of capabilities to be dropped | `["ALL"]` |
|
||||
| `metrics.containerSecurityContext.seccompProfile.type` | Set container's Security Context seccomp profile | `RuntimeDefault` |
|
||||
| `metrics.livenessProbe.enabled` | Enable livenessProbe on PostgreSQL Prometheus exporter containers | `true` |
|
||||
| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` |
|
||||
| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` |
|
||||
| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` |
|
||||
| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` |
|
||||
| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` |
|
||||
| `metrics.readinessProbe.enabled` | Enable readinessProbe on PostgreSQL Prometheus exporter containers | `true` |
|
||||
| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` |
|
||||
| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` |
|
||||
| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` |
|
||||
| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` |
|
||||
| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` |
|
||||
| `metrics.startupProbe.enabled` | Enable startupProbe on PostgreSQL Prometheus exporter containers | `false` |
|
||||
| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` |
|
||||
| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` |
|
||||
| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` |
|
||||
| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` |
|
||||
| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` |
|
||||
| `metrics.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` |
|
||||
| `metrics.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` |
|
||||
| `metrics.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` |
|
||||
| `metrics.containerPorts.metrics` | PostgreSQL Prometheus exporter metrics container port | `9187` |
|
||||
| `metrics.resources.limits` | The resources limits for the PostgreSQL Prometheus exporter container | `{}` |
|
||||
| `metrics.resources.requests` | The requested resources for the PostgreSQL Prometheus exporter container | `{}` |
|
||||
| `metrics.service.ports.metrics` | PostgreSQL Prometheus Exporter service port | `9187` |
|
||||
| `metrics.service.clusterIP` | Static clusterIP or None for headless services | `""` |
|
||||
| `metrics.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` |
|
||||
| `metrics.service.annotations` | Annotations for Prometheus to auto-discover the metrics endpoint | `{}` |
|
||||
| `metrics.serviceMonitor.enabled` | Create ServiceMonitor Resource for scraping metrics using Prometheus Operator | `false` |
|
||||
| `metrics.serviceMonitor.namespace` | Namespace for the ServiceMonitor Resource (defaults to the Release Namespace) | `""` |
|
||||
| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. | `""` |
|
||||
| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` |
|
||||
| `metrics.serviceMonitor.labels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` |
|
||||
| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` |
|
||||
| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping | `[]` |
|
||||
| `metrics.serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion | `[]` |
|
||||
| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` |
|
||||
| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` |
|
||||
| `metrics.prometheusRule.enabled` | Create a PrometheusRule for Prometheus Operator | `false` |
|
||||
| `metrics.prometheusRule.namespace` | Namespace for the PrometheusRule Resource (defaults to the Release Namespace) | `""` |
|
||||
| `metrics.prometheusRule.labels` | Additional labels that can be used so PrometheusRule will be discovered by Prometheus | `{}` |
|
||||
| `metrics.prometheusRule.rules` | PrometheusRule definitions | `[]` |
|
||||
|
||||
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
|
||||
|
||||
```console
|
||||
helm install my-release \
|
||||
--set auth.postgresPassword=secretpassword
|
||||
oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql
|
||||
```
|
||||
|
||||
> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`.
|
||||
|
||||
The above command sets the PostgreSQL `postgres` account password to `secretpassword`.
|
||||
|
||||
> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available.
|
||||
> **Warning** Setting a password will be ignored on new installation in case when previous PostgreSQL release was deleted through the helm command. In that case, old PVC will have an old password, and setting it through helm won't take effect. Deleting persistent volumes (PVs) will solve the issue. Refer to [issue 2061](https://github.com/bitnami/charts/issues/2061) for more details
|
||||
|
||||
Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example,
|
||||
|
||||
```console
|
||||
helm install my-release -f values.yaml oci://REGISTRY_NAME/REPOSITORY_NAME/postgresql
|
||||
```
|
||||
|
||||
> Note: You need to substitute the placeholders `REGISTRY_NAME` and `REPOSITORY_NAME` with a reference to your Helm chart registry and repository. For example, in the case of Bitnami, you need to use `REGISTRY_NAME=registry-1.docker.io` and `REPOSITORY_NAME=bitnamicharts`.
|
||||
> **Tip**: You can use the default [values.yaml](https://github.com/bitnami/charts/tree/main/bitnami/postgresql/values.yaml)
|
||||
|
||||
## Configuration and installation details
|
||||
|
||||
### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/)
|
||||
|
||||
It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image.
|
||||
|
||||
Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist.
|
||||
|
||||
### Customizing primary and read replica services in a replicated configuration
|
||||
|
||||
At the top level, there is a service object which defines the services for both primary and readReplicas. For deeper customization, there are service objects for both the primary and read types individually. This allows you to override the values in the top level service object so that the primary and read can be of different service types and with different clusterIPs / nodePorts. Also in the case you want the primary and read to be of type nodePort, you will need to set the nodePorts to different values to prevent a collision. The values that are deeper in the primary.service or readReplicas.service objects will take precedence over the top level service object.
|
||||
|
||||
### Use a different PostgreSQL version
|
||||
|
||||
To modify the application version used in this chart, specify a different version of the image using the `image.tag` parameter and/or a different repository using the `image.repository` parameter. Refer to the [chart documentation for more information on these parameters and how to use them with images from a private registry](https://docs.bitnami.com/kubernetes/infrastructure/postgresql/configuration/change-image-version/).
|
||||
|
||||
### postgresql.conf / pg_hba.conf files as configMap
|
||||
|
||||
This helm chart also supports to customize the PostgreSQL configuration file. You can add additional PostgreSQL configuration parameters using the `primary.extendedConfiguration`/`readReplicas.extendedConfiguration` parameters as a string. Alternatively, to replace the entire default configuration use `primary.configuration`.
|
||||
|
||||
You can also add a custom pg_hba.conf using the `primary.pgHbaConfiguration` parameter.
|
||||
|
||||
In addition to these options, you can also set an external ConfigMap with all the configuration files. This is done by setting the `primary.existingConfigmap` parameter. Note that this will override the two previous options.
|
||||
|
||||
### Initialize a fresh instance
|
||||
|
||||
The [Bitnami PostgreSQL](https://github.com/bitnami/containers/tree/main/bitnami/postgresql) image allows you to use your custom scripts to initialize a fresh instance. In order to execute the scripts, you can specify custom scripts using the `primary.initdb.scripts` parameter as a string.
|
||||
|
||||
In addition, you can also set an external ConfigMap with all the initialization scripts. This is done by setting the `primary.initdb.scriptsConfigMap` parameter. Note that this will override the two previous options. If your initialization scripts contain sensitive information such as credentials or passwords, you can use the `primary.initdb.scriptsSecret` parameter.
|
||||
|
||||
The allowed extensions are `.sh`, `.sql` and `.sql.gz`.
|
||||
|
||||
### Securing traffic using TLS
|
||||
|
||||
TLS support can be enabled in the chart by specifying the `tls.` parameters while creating a release. The following parameters should be configured to properly enable the TLS support in the chart:
|
||||
|
||||
- `tls.enabled`: Enable TLS support. Defaults to `false`
|
||||
- `tls.certificatesSecret`: Name of an existing secret that contains the certificates. No defaults.
|
||||
- `tls.certFilename`: Certificate filename. No defaults.
|
||||
- `tls.certKeyFilename`: Certificate key filename. No defaults.
|
||||
|
||||
For example:
|
||||
|
||||
- First, create the secret with the cetificates files:
|
||||
|
||||
```console
|
||||
kubectl create secret generic certificates-tls-secret --from-file=./cert.crt --from-file=./cert.key --from-file=./ca.crt
|
||||
```
|
||||
|
||||
- Then, use the following parameters:
|
||||
|
||||
```console
|
||||
volumePermissions.enabled=true
|
||||
tls.enabled=true
|
||||
tls.certificatesSecret="certificates-tls-secret"
|
||||
tls.certFilename="cert.crt"
|
||||
tls.certKeyFilename="cert.key"
|
||||
```
|
||||
|
||||
> Note TLS and VolumePermissions: PostgreSQL requires certain permissions on sensitive files (such as certificate keys) to start up. Due to an on-going [issue](https://github.com/kubernetes/kubernetes/issues/57923) regarding kubernetes permissions and the use of `containerSecurityContext.runAsUser`, you must enable `volumePermissions` to ensure everything works as expected.
|
||||
|
||||
### Sidecars
|
||||
|
||||
If you need additional containers to run within the same pod as PostgreSQL (e.g. an additional metrics or logging exporter), you can do so via the `sidecars` config parameter. Simply define your container according to the Kubernetes container spec.
|
||||
|
||||
```yaml
|
||||
# For the PostgreSQL primary
|
||||
primary:
|
||||
sidecars:
|
||||
- name: your-image-name
|
||||
image: your-image
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: portname
|
||||
containerPort: 1234
|
||||
# For the PostgreSQL replicas
|
||||
readReplicas:
|
||||
sidecars:
|
||||
- name: your-image-name
|
||||
image: your-image
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: portname
|
||||
containerPort: 1234
|
||||
```
|
||||
|
||||
### Metrics
|
||||
|
||||
The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). The metrics endpoint (port 9187) is not exposed and it is expected that the metrics are collected from inside the k8s cluster using something similar as the described in the [example Prometheus scrape configuration](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml).
|
||||
|
||||
The exporter allows to create custom metrics from additional SQL queries. See the Chart's `values.yaml` for an example and consult the [exporters documentation](https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file) for more details.
|
||||
|
||||
### Use of global variables
|
||||
|
||||
In more complex scenarios, we may have the following tree of dependencies
|
||||
|
||||
```text
|
||||
+--------------+
|
||||
| |
|
||||
+------------+ Chart 1 +-----------+
|
||||
| | | |
|
||||
| --------+------+ |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
v v v
|
||||
+-------+------+ +--------+------+ +--------+------+
|
||||
| | | | | |
|
||||
| PostgreSQL | | Sub-chart 1 | | Sub-chart 2 |
|
||||
| | | | | |
|
||||
+--------------+ +---------------+ +---------------+
|
||||
```
|
||||
|
||||
The three charts below depend on the parent chart Chart 1. However, subcharts 1 and 2 may need to connect to PostgreSQL as well. In order to do so, subcharts 1 and 2 need to know the PostgreSQL credentials, so one option for deploying could be deploy Chart 1 with the following parameters:
|
||||
|
||||
```text
|
||||
postgresql.auth.username=testuser
|
||||
subchart1.postgresql.auth.username=testuser
|
||||
subchart2.postgresql.auth.username=testuser
|
||||
postgresql.auth.password=testpass
|
||||
subchart1.postgresql.auth.password=testpass
|
||||
subchart2.postgresql.auth.password=testpass
|
||||
postgresql.auth.database=testdb
|
||||
subchart1.postgresql.auth.database=testdb
|
||||
subchart2.postgresql.auth.database=testdb
|
||||
```
|
||||
|
||||
If the number of dependent sub-charts increases, installing the chart with parameters can become increasingly difficult. An alternative would be to set the credentials using global variables as follows:
|
||||
|
||||
```text
|
||||
global.postgresql.auth.username=testuser
|
||||
global.postgresql.auth.password=testpass
|
||||
global.postgresql.auth.database=testdb
|
||||
```
|
||||
|
||||
This way, the credentials will be available in all of the subcharts.
|
||||
|
||||
## Persistence
|
||||
|
||||
The [Bitnami PostgreSQL](https://github.com/bitnami/containers/tree/main/bitnami/postgresql) image stores the PostgreSQL data and configurations at the `/bitnami/postgresql` path of the container.
|
||||
|
||||
Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube.
|
||||
See the [Parameters](#parameters) section to configure the PVC or to disable persistence.
|
||||
|
||||
If you already have data in it, you will fail to sync to standby nodes for all commits, details can refer to the [code present in the container repository](https://github.com/bitnami/containers/tree/main/bitnami/postgresql). If you need to use those data, please covert them to sql and import after `helm install` finished.
|
||||
|
||||
## NetworkPolicy
|
||||
|
||||
To enable network policy for PostgreSQL, install [a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin), and set `networkPolicy.enabled` to `true`.
|
||||
|
||||
For Kubernetes v1.5 & v1.6, you must also turn on NetworkPolicy by setting the DefaultDeny namespace annotation. Note: this will enforce policy for _all_ pods in the namespace:
|
||||
|
||||
```console
|
||||
kubectl annotate namespace default "net.beta.kubernetes.io/network-policy={\"ingress\":{\"isolation\":\"DefaultDeny\"}}"
|
||||
```
|
||||
|
||||
With NetworkPolicy enabled, traffic will be limited to just port 5432.
|
||||
|
||||
For more precise policy, set `networkPolicy.allowExternal=false`. This will only allow pods with the generated client label to connect to PostgreSQL.
|
||||
This label will be displayed in the output of a successful install.
|
||||
|
||||
## Differences between Bitnami PostgreSQL image and [Docker Official](https://hub.docker.com/_/postgres) image
|
||||
|
||||
- The Docker Official PostgreSQL image does not support replication. If you pass any replication environment variable, this would be ignored. The only environment variables supported by the Docker Official image are POSTGRES_USER, POSTGRES_DB, POSTGRES_PASSWORD, POSTGRES_INITDB_ARGS, POSTGRES_INITDB_WALDIR and PGDATA. All the remaining environment variables are specific to the Bitnami PostgreSQL image.
|
||||
- The Bitnami PostgreSQL image is non-root by default. This requires that you run the pod with `securityContext` and updates the permissions of the volume with an `initContainer`. A key benefit of this configuration is that the pod follows security best practices and is prepared to run on Kubernetes distributions with hard security constraints like OpenShift.
|
||||
- For OpenShift up to 4.10, let set the volume permissions, security context, runAsUser and fsGroup automatically by OpenShift and disable the predefined settings of the helm chart: primary.securityContext.enabled=false,primary.containerSecurityContext.enabled=false,volumePermissions.enabled=false,shmVolume.enabled=false
|
||||
- For OpenShift 4.11 and higher, let set OpenShift the runAsUser and fsGroup automatically. Configure the pod and container security context to restrictive defaults and disable the volume permissions setup: primary.
|
||||
podSecurityContext.fsGroup=null,primary.podSecurityContext.seccompProfile.type=RuntimeDefault,primary.containerSecurityContext.runAsUser=null,primary.containerSecurityContext.allowPrivilegeEscalation=false,primary.containerSecurityContext.runAsNonRoot=true,primary.containerSecurityContext.seccompProfile.type=RuntimeDefault,primary.containerSecurityContext.capabilities.drop=['ALL'],volumePermissions.enabled=false,shmVolume.enabled=false
|
||||
|
||||
### Setting Pod's affinity
|
||||
|
||||
This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity).
|
||||
|
||||
As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/main/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues).
|
||||
|
||||
## Upgrading
|
||||
|
||||
### To 13.0.0
|
||||
|
||||
This major version changes the default PostgreSQL image from 15.x to 16.x. Follow the [official instructions](https://www.postgresql.org/docs/16/upgrading.html) to upgrade to 16.x.
|
||||
|
||||
### To 12.0.0
|
||||
|
||||
This major version changes the default PostgreSQL image from 14.x to 15.x. Follow the [official instructions](https://www.postgresql.org/docs/15/upgrading.html) to upgrade to 15.x.
|
||||
|
||||
### To any previous version
|
||||
|
||||
Refer to the [chart documentation for more information about how to upgrade from previous releases](https://docs.bitnami.com/kubernetes/infrastructure/postgresql/administration/upgrade/).
|
||||
|
||||
## License
|
||||
|
||||
Copyright © 2023 VMware, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
<http://www.apache.org/licenses/LICENSE-2.0>
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
22
charts/airflow/charts/postgresql/charts/common/.helmignore
Normal file
22
charts/airflow/charts/postgresql/charts/common/.helmignore
Normal file
@ -0,0 +1,22 @@
|
||||
# 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
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
23
charts/airflow/charts/postgresql/charts/common/Chart.yaml
Normal file
23
charts/airflow/charts/postgresql/charts/common/Chart.yaml
Normal file
@ -0,0 +1,23 @@
|
||||
annotations:
|
||||
category: Infrastructure
|
||||
licenses: Apache-2.0
|
||||
apiVersion: v2
|
||||
appVersion: 2.13.3
|
||||
description: A Library Helm Chart for grouping common logic between bitnami charts.
|
||||
This chart is not deployable by itself.
|
||||
home: https://bitnami.com
|
||||
icon: https://bitnami.com/downloads/logos/bitnami-mark.png
|
||||
keywords:
|
||||
- common
|
||||
- helper
|
||||
- template
|
||||
- function
|
||||
- bitnami
|
||||
maintainers:
|
||||
- name: VMware, Inc.
|
||||
url: https://github.com/bitnami/charts
|
||||
name: common
|
||||
sources:
|
||||
- https://github.com/bitnami/charts
|
||||
type: library
|
||||
version: 2.13.3
|
||||
235
charts/airflow/charts/postgresql/charts/common/README.md
Normal file
235
charts/airflow/charts/postgresql/charts/common/README.md
Normal file
@ -0,0 +1,235 @@
|
||||
# Bitnami Common Library Chart
|
||||
|
||||
A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between Bitnami charts.
|
||||
|
||||
## TL;DR
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
- name: common
|
||||
version: 2.x.x
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
```
|
||||
|
||||
```console
|
||||
helm dependency update
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "common.names.fullname" . }}
|
||||
data:
|
||||
myvalue: "Hello World"
|
||||
```
|
||||
|
||||
## Introduction
|
||||
|
||||
This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager.
|
||||
|
||||
Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters.
|
||||
|
||||
Looking to use our applications in production? Try [VMware Application Catalog](https://bitnami.com/enterprise), the enterprise edition of Bitnami Application Catalog.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Kubernetes 1.23+
|
||||
- Helm 3.8.0+
|
||||
|
||||
## Parameters
|
||||
|
||||
## Special input schemas
|
||||
|
||||
### ImageRoot
|
||||
|
||||
```yaml
|
||||
registry:
|
||||
type: string
|
||||
description: Docker registry where the image is located
|
||||
example: docker.io
|
||||
|
||||
repository:
|
||||
type: string
|
||||
description: Repository and image name
|
||||
example: bitnami/nginx
|
||||
|
||||
tag:
|
||||
type: string
|
||||
description: image tag
|
||||
example: 1.16.1-debian-10-r63
|
||||
|
||||
pullPolicy:
|
||||
type: string
|
||||
description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
|
||||
|
||||
pullSecrets:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Optionally specify an array of imagePullSecrets (evaluated as templates).
|
||||
|
||||
debug:
|
||||
type: boolean
|
||||
description: Set to true if you would like to see extra information on logs
|
||||
example: false
|
||||
|
||||
## An instance would be:
|
||||
# registry: docker.io
|
||||
# repository: bitnami/nginx
|
||||
# tag: 1.16.1-debian-10-r63
|
||||
# pullPolicy: IfNotPresent
|
||||
# debug: false
|
||||
```
|
||||
|
||||
### Persistence
|
||||
|
||||
```yaml
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether enable persistence.
|
||||
example: true
|
||||
|
||||
storageClass:
|
||||
type: string
|
||||
description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning.
|
||||
example: "-"
|
||||
|
||||
accessMode:
|
||||
type: string
|
||||
description: Access mode for the Persistent Volume Storage.
|
||||
example: ReadWriteOnce
|
||||
|
||||
size:
|
||||
type: string
|
||||
description: Size the Persistent Volume Storage.
|
||||
example: 8Gi
|
||||
|
||||
path:
|
||||
type: string
|
||||
description: Path to be persisted.
|
||||
example: /bitnami
|
||||
|
||||
## An instance would be:
|
||||
# enabled: true
|
||||
# storageClass: "-"
|
||||
# accessMode: ReadWriteOnce
|
||||
# size: 8Gi
|
||||
# path: /bitnami
|
||||
```
|
||||
|
||||
### ExistingSecret
|
||||
|
||||
```yaml
|
||||
name:
|
||||
type: string
|
||||
description: Name of the existing secret.
|
||||
example: mySecret
|
||||
keyMapping:
|
||||
description: Mapping between the expected key name and the name of the key in the existing secret.
|
||||
type: object
|
||||
|
||||
## An instance would be:
|
||||
# name: mySecret
|
||||
# keyMapping:
|
||||
# password: myPasswordKey
|
||||
```
|
||||
|
||||
#### Example of use
|
||||
|
||||
When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets.
|
||||
|
||||
```yaml
|
||||
# templates/secret.yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "common.names.fullname" . }}
|
||||
labels:
|
||||
app: {{ include "common.names.fullname" . }}
|
||||
type: Opaque
|
||||
data:
|
||||
password: {{ .Values.password | b64enc | quote }}
|
||||
|
||||
# templates/dpl.yaml
|
||||
---
|
||||
...
|
||||
env:
|
||||
- name: PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }}
|
||||
key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }}
|
||||
...
|
||||
|
||||
# values.yaml
|
||||
---
|
||||
name: mySecret
|
||||
keyMapping:
|
||||
password: myPasswordKey
|
||||
```
|
||||
|
||||
### ValidateValue
|
||||
|
||||
#### NOTES.txt
|
||||
|
||||
```console
|
||||
{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}}
|
||||
{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}}
|
||||
|
||||
{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }}
|
||||
```
|
||||
|
||||
If we force those values to be empty we will see some alerts
|
||||
|
||||
```console
|
||||
helm install test mychart --set path.to.value00="",path.to.value01=""
|
||||
'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value:
|
||||
|
||||
export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d)
|
||||
|
||||
'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value:
|
||||
|
||||
export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d)
|
||||
```
|
||||
|
||||
## Upgrading
|
||||
|
||||
### To 1.0.0
|
||||
|
||||
[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL.
|
||||
|
||||
#### What changes were introduced in this major version?
|
||||
|
||||
- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field.
|
||||
- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information.
|
||||
- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts
|
||||
|
||||
#### Considerations when upgrading to this version
|
||||
|
||||
- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues
|
||||
- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore
|
||||
- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3
|
||||
|
||||
#### Useful links
|
||||
|
||||
- <https://docs.bitnami.com/tutorials/resolve-helm2-helm3-post-migration-issues/>
|
||||
- <https://helm.sh/docs/topics/v2_v3_migration/>
|
||||
- <https://helm.sh/blog/migrate-from-helm-v2-to-helm-v3/>
|
||||
|
||||
## License
|
||||
|
||||
Copyright © 2023 VMware, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
<http://www.apache.org/licenses/LICENSE-2.0>
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@ -0,0 +1,139 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
|
||||
{{/*
|
||||
Return a soft nodeAffinity definition
|
||||
{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}}
|
||||
*/}}
|
||||
{{- define "common.affinities.nodes.soft" -}}
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- preference:
|
||||
matchExpressions:
|
||||
- key: {{ .key }}
|
||||
operator: In
|
||||
values:
|
||||
{{- range .values }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
weight: 1
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return a hard nodeAffinity definition
|
||||
{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}}
|
||||
*/}}
|
||||
{{- define "common.affinities.nodes.hard" -}}
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: {{ .key }}
|
||||
operator: In
|
||||
values:
|
||||
{{- range .values }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return a nodeAffinity definition
|
||||
{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}}
|
||||
*/}}
|
||||
{{- define "common.affinities.nodes" -}}
|
||||
{{- if eq .type "soft" }}
|
||||
{{- include "common.affinities.nodes.soft" . -}}
|
||||
{{- else if eq .type "hard" }}
|
||||
{{- include "common.affinities.nodes.hard" . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return a topologyKey definition
|
||||
{{ include "common.affinities.topologyKey" (dict "topologyKey" "BAR") -}}
|
||||
*/}}
|
||||
{{- define "common.affinities.topologyKey" -}}
|
||||
{{ .topologyKey | default "kubernetes.io/hostname" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return a soft podAffinity/podAntiAffinity definition
|
||||
{{ include "common.affinities.pods.soft" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}}
|
||||
*/}}
|
||||
{{- define "common.affinities.pods.soft" -}}
|
||||
{{- $component := default "" .component -}}
|
||||
{{- $customLabels := default (dict) .customLabels -}}
|
||||
{{- $extraMatchLabels := default (dict) .extraMatchLabels -}}
|
||||
{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}}
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 10 }}
|
||||
{{- if not (empty $component) }}
|
||||
{{ printf "app.kubernetes.io/component: %s" $component }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := $extraMatchLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }}
|
||||
weight: 1
|
||||
{{- range $extraPodAffinityTerms }}
|
||||
- podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 10 }}
|
||||
{{- if not (empty $component) }}
|
||||
{{ printf "app.kubernetes.io/component: %s" $component }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .extraMatchLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }}
|
||||
weight: {{ .weight | default 1 -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return a hard podAffinity/podAntiAffinity definition
|
||||
{{ include "common.affinities.pods.hard" (dict "component" "FOO" "customLabels" .Values.podLabels "extraMatchLabels" .Values.extraMatchLabels "topologyKey" "BAR" "extraPodAffinityTerms" .Values.extraPodAffinityTerms "context" $) -}}
|
||||
*/}}
|
||||
{{- define "common.affinities.pods.hard" -}}
|
||||
{{- $component := default "" .component -}}
|
||||
{{- $customLabels := default (dict) .customLabels -}}
|
||||
{{- $extraMatchLabels := default (dict) .extraMatchLabels -}}
|
||||
{{- $extraPodAffinityTerms := default (list) .extraPodAffinityTerms -}}
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" .context )) | nindent 8 }}
|
||||
{{- if not (empty $component) }}
|
||||
{{ printf "app.kubernetes.io/component: %s" $component }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := $extraMatchLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }}
|
||||
{{- range $extraPodAffinityTerms }}
|
||||
- labelSelector:
|
||||
matchLabels: {{- (include "common.labels.matchLabels" ( dict "customLabels" $customLabels "context" $.context )) | nindent 8 }}
|
||||
{{- if not (empty $component) }}
|
||||
{{ printf "app.kubernetes.io/component: %s" $component }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .extraMatchLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
topologyKey: {{ include "common.affinities.topologyKey" (dict "topologyKey" .topologyKey) }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return a podAffinity/podAntiAffinity definition
|
||||
{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}}
|
||||
*/}}
|
||||
{{- define "common.affinities.pods" -}}
|
||||
{{- if eq .type "soft" }}
|
||||
{{- include "common.affinities.pods.soft" . -}}
|
||||
{{- else if eq .type "hard" }}
|
||||
{{- include "common.affinities.pods.hard" . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,229 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
|
||||
{{/*
|
||||
Return the target Kubernetes version
|
||||
*/}}
|
||||
{{- define "common.capabilities.kubeVersion" -}}
|
||||
{{- if .Values.global }}
|
||||
{{- if .Values.global.kubeVersion }}
|
||||
{{- .Values.global.kubeVersion -}}
|
||||
{{- else }}
|
||||
{{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}}
|
||||
{{- end -}}
|
||||
{{- else }}
|
||||
{{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for poddisruptionbudget.
|
||||
*/}}
|
||||
{{- define "common.capabilities.policy.apiVersion" -}}
|
||||
{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "policy/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "policy/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for networkpolicy.
|
||||
*/}}
|
||||
{{- define "common.capabilities.networkPolicy.apiVersion" -}}
|
||||
{{- if semverCompare "<1.7-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "extensions/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "networking.k8s.io/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for cronjob.
|
||||
*/}}
|
||||
{{- define "common.capabilities.cronjob.apiVersion" -}}
|
||||
{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "batch/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "batch/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for daemonset.
|
||||
*/}}
|
||||
{{- define "common.capabilities.daemonset.apiVersion" -}}
|
||||
{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "extensions/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "apps/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for deployment.
|
||||
*/}}
|
||||
{{- define "common.capabilities.deployment.apiVersion" -}}
|
||||
{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "extensions/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "apps/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for statefulset.
|
||||
*/}}
|
||||
{{- define "common.capabilities.statefulset.apiVersion" -}}
|
||||
{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "apps/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "apps/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for ingress.
|
||||
*/}}
|
||||
{{- define "common.capabilities.ingress.apiVersion" -}}
|
||||
{{- if .Values.ingress -}}
|
||||
{{- if .Values.ingress.apiVersion -}}
|
||||
{{- .Values.ingress.apiVersion -}}
|
||||
{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "extensions/v1beta1" -}}
|
||||
{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "networking.k8s.io/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "networking.k8s.io/v1" -}}
|
||||
{{- end }}
|
||||
{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "extensions/v1beta1" -}}
|
||||
{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "networking.k8s.io/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "networking.k8s.io/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for RBAC resources.
|
||||
*/}}
|
||||
{{- define "common.capabilities.rbac.apiVersion" -}}
|
||||
{{- if semverCompare "<1.17-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "rbac.authorization.k8s.io/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "rbac.authorization.k8s.io/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for CRDs.
|
||||
*/}}
|
||||
{{- define "common.capabilities.crd.apiVersion" -}}
|
||||
{{- if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "apiextensions.k8s.io/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "apiextensions.k8s.io/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for APIService.
|
||||
*/}}
|
||||
{{- define "common.capabilities.apiService.apiVersion" -}}
|
||||
{{- if semverCompare "<1.10-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "apiregistration.k8s.io/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "apiregistration.k8s.io/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for Horizontal Pod Autoscaler.
|
||||
*/}}
|
||||
{{- define "common.capabilities.hpa.apiVersion" -}}
|
||||
{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}}
|
||||
{{- if .beta2 -}}
|
||||
{{- print "autoscaling/v2beta2" -}}
|
||||
{{- else -}}
|
||||
{{- print "autoscaling/v2beta1" -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- print "autoscaling/v2" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for Vertical Pod Autoscaler.
|
||||
*/}}
|
||||
{{- define "common.capabilities.vpa.apiVersion" -}}
|
||||
{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}}
|
||||
{{- if .beta2 -}}
|
||||
{{- print "autoscaling/v2beta2" -}}
|
||||
{{- else -}}
|
||||
{{- print "autoscaling/v2beta1" -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- print "autoscaling/v2" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Returns true if PodSecurityPolicy is supported
|
||||
*/}}
|
||||
{{- define "common.capabilities.psp.supported" -}}
|
||||
{{- if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Returns true if AdmissionConfiguration is supported
|
||||
*/}}
|
||||
{{- define "common.capabilities.admissionConfiguration.supported" -}}
|
||||
{{- if semverCompare ">=1.23-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for AdmissionConfiguration.
|
||||
*/}}
|
||||
{{- define "common.capabilities.admissionConfiguration.apiVersion" -}}
|
||||
{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "apiserver.config.k8s.io/v1alpha1" -}}
|
||||
{{- else if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "apiserver.config.k8s.io/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "apiserver.config.k8s.io/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for PodSecurityConfiguration.
|
||||
*/}}
|
||||
{{- define "common.capabilities.podSecurityConfiguration.apiVersion" -}}
|
||||
{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "pod-security.admission.config.k8s.io/v1alpha1" -}}
|
||||
{{- else if semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "pod-security.admission.config.k8s.io/v1beta1" -}}
|
||||
{{- else -}}
|
||||
{{- print "pod-security.admission.config.k8s.io/v1" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Returns true if the used Helm version is 3.3+.
|
||||
A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure.
|
||||
This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error.
|
||||
**To be removed when the catalog's minimun Helm version is 3.3**
|
||||
*/}}
|
||||
{{- define "common.capabilities.supportsHelmVersion" -}}
|
||||
{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,28 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Through error when upgrading using empty passwords values that must not be empty.
|
||||
|
||||
Usage:
|
||||
{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}}
|
||||
{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}}
|
||||
{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }}
|
||||
|
||||
Required password params:
|
||||
- validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error.
|
||||
- context - Context - Required. Parent context.
|
||||
*/}}
|
||||
{{- define "common.errors.upgrade.passwords.empty" -}}
|
||||
{{- $validationErrors := join "" .validationErrors -}}
|
||||
{{- if and $validationErrors .context.Release.IsUpgrade -}}
|
||||
{{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}}
|
||||
{{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}}
|
||||
{{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}}
|
||||
{{- $errorString = print $errorString "\n%s" -}}
|
||||
{{- printf $errorString $validationErrors | fail -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,117 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Return the proper image name
|
||||
{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global ) }}
|
||||
*/}}
|
||||
{{- define "common.images.image" -}}
|
||||
{{- $registryName := .imageRoot.registry -}}
|
||||
{{- $repositoryName := .imageRoot.repository -}}
|
||||
{{- $separator := ":" -}}
|
||||
{{- $termination := .imageRoot.tag | toString -}}
|
||||
{{- if .global }}
|
||||
{{- if .global.imageRegistry }}
|
||||
{{- $registryName = .global.imageRegistry -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if .imageRoot.digest }}
|
||||
{{- $separator = "@" -}}
|
||||
{{- $termination = .imageRoot.digest | toString -}}
|
||||
{{- end -}}
|
||||
{{- if $registryName }}
|
||||
{{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s%s%s" $repositoryName $separator $termination -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead)
|
||||
{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }}
|
||||
*/}}
|
||||
{{- define "common.images.pullSecrets" -}}
|
||||
{{- $pullSecrets := list }}
|
||||
|
||||
{{- if .global }}
|
||||
{{- range .global.imagePullSecrets -}}
|
||||
{{- if kindIs "map" . -}}
|
||||
{{- $pullSecrets = append $pullSecrets .name -}}
|
||||
{{- else -}}
|
||||
{{- $pullSecrets = append $pullSecrets . -}}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range .images -}}
|
||||
{{- range .pullSecrets -}}
|
||||
{{- if kindIs "map" . -}}
|
||||
{{- $pullSecrets = append $pullSecrets .name -}}
|
||||
{{- else -}}
|
||||
{{- $pullSecrets = append $pullSecrets . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if (not (empty $pullSecrets)) }}
|
||||
imagePullSecrets:
|
||||
{{- range $pullSecrets | uniq }}
|
||||
- name: {{ . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the proper Docker Image Registry Secret Names evaluating values as templates
|
||||
{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.images.renderPullSecrets" -}}
|
||||
{{- $pullSecrets := list }}
|
||||
{{- $context := .context }}
|
||||
|
||||
{{- if $context.Values.global }}
|
||||
{{- range $context.Values.global.imagePullSecrets -}}
|
||||
{{- if kindIs "map" . -}}
|
||||
{{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}}
|
||||
{{- else -}}
|
||||
{{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range .images -}}
|
||||
{{- range .pullSecrets -}}
|
||||
{{- if kindIs "map" . -}}
|
||||
{{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" .name "context" $context)) -}}
|
||||
{{- else -}}
|
||||
{{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if (not (empty $pullSecrets)) }}
|
||||
imagePullSecrets:
|
||||
{{- range $pullSecrets | uniq }}
|
||||
- name: {{ . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion)
|
||||
{{ include "common.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }}
|
||||
*/}}
|
||||
{{- define "common.images.version" -}}
|
||||
{{- $imageTag := .imageRoot.tag | toString -}}
|
||||
{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}}
|
||||
{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}}
|
||||
{{- $version := semver $imageTag -}}
|
||||
{{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}}
|
||||
{{- else -}}
|
||||
{{- print .chart.AppVersion -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
@ -0,0 +1,73 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
|
||||
{{/*
|
||||
Generate backend entry that is compatible with all Kubernetes API versions.
|
||||
|
||||
Usage:
|
||||
{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }}
|
||||
|
||||
Params:
|
||||
- serviceName - String. Name of an existing service backend
|
||||
- servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer.
|
||||
- context - Dict - Required. The context for the template evaluation.
|
||||
*/}}
|
||||
{{- define "common.ingress.backend" -}}
|
||||
{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}}
|
||||
{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}}
|
||||
serviceName: {{ .serviceName }}
|
||||
servicePort: {{ .servicePort }}
|
||||
{{- else -}}
|
||||
service:
|
||||
name: {{ .serviceName }}
|
||||
port:
|
||||
{{- if typeIs "string" .servicePort }}
|
||||
name: {{ .servicePort }}
|
||||
{{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }}
|
||||
number: {{ .servicePort | int }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Print "true" if the API pathType field is supported
|
||||
Usage:
|
||||
{{ include "common.ingress.supportsPathType" . }}
|
||||
*/}}
|
||||
{{- define "common.ingress.supportsPathType" -}}
|
||||
{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}}
|
||||
{{- print "false" -}}
|
||||
{{- else -}}
|
||||
{{- print "true" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Returns true if the ingressClassname field is supported
|
||||
Usage:
|
||||
{{ include "common.ingress.supportsIngressClassname" . }}
|
||||
*/}}
|
||||
{{- define "common.ingress.supportsIngressClassname" -}}
|
||||
{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}}
|
||||
{{- print "false" -}}
|
||||
{{- else -}}
|
||||
{{- print "true" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return true if cert-manager required annotations for TLS signed
|
||||
certificates are set in the Ingress annotations
|
||||
Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations
|
||||
Usage:
|
||||
{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }}
|
||||
*/}}
|
||||
{{- define "common.ingress.certManagerRequest" -}}
|
||||
{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,46 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
|
||||
{{/*
|
||||
Kubernetes standard labels
|
||||
{{ include "common.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}}
|
||||
*/}}
|
||||
{{- define "common.labels.standard" -}}
|
||||
{{- if and (hasKey . "customLabels") (hasKey . "context") -}}
|
||||
{{- $default := dict "app.kubernetes.io/name" (include "common.names.name" .context) "helm.sh/chart" (include "common.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}}
|
||||
{{- with .context.Chart.AppVersion -}}
|
||||
{{- $_ := set $default "app.kubernetes.io/version" . -}}
|
||||
{{- end -}}
|
||||
{{ template "common.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }}
|
||||
{{- else -}}
|
||||
app.kubernetes.io/name: {{ include "common.names.name" . }}
|
||||
helm.sh/chart: {{ include "common.names.chart" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- with .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ . | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector
|
||||
{{ include "common.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}}
|
||||
|
||||
We don't want to loop over custom labels appending them to the selector
|
||||
since it's very likely that it will break deployments, services, etc.
|
||||
However, it's important to overwrite the standard labels if the user
|
||||
overwrote them on metadata.labels fields.
|
||||
*/}}
|
||||
{{- define "common.labels.matchLabels" -}}
|
||||
{{- if and (hasKey . "customLabels") (hasKey . "context") -}}
|
||||
{{ merge (pick (include "common.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "common.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }}
|
||||
{{- else -}}
|
||||
app.kubernetes.io/name: {{ include "common.names.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,71 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "common.names.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "common.names.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | 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 "common.names.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 a default fully qualified dependency 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.
|
||||
Usage:
|
||||
{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.names.dependency.fullname" -}}
|
||||
{{- if .chartValues.fullnameOverride -}}
|
||||
{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- $name := default .chartName .chartValues.nameOverride -}}
|
||||
{{- if contains $name .context.Release.Name -}}
|
||||
{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Allow the release namespace to be overridden for multi-namespace deployments in combined charts.
|
||||
*/}}
|
||||
{{- define "common.names.namespace" -}}
|
||||
{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a fully qualified app name adding the installation's namespace.
|
||||
*/}}
|
||||
{{- define "common.names.fullname.namespace" -}}
|
||||
{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,172 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Generate secret name.
|
||||
|
||||
Usage:
|
||||
{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }}
|
||||
|
||||
Params:
|
||||
- existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user
|
||||
to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility.
|
||||
+info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret
|
||||
- defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment.
|
||||
- context - Dict - Required. The context for the template evaluation.
|
||||
*/}}
|
||||
{{- define "common.secrets.name" -}}
|
||||
{{- $name := (include "common.names.fullname" .context) -}}
|
||||
|
||||
{{- if .defaultNameSuffix -}}
|
||||
{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- with .existingSecret -}}
|
||||
{{- if not (typeIs "string" .) -}}
|
||||
{{- with .name -}}
|
||||
{{- $name = . -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- $name = . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- printf "%s" $name -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Generate secret key.
|
||||
|
||||
Usage:
|
||||
{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }}
|
||||
|
||||
Params:
|
||||
- existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user
|
||||
to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility.
|
||||
+info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret
|
||||
- key - String - Required. Name of the key in the secret.
|
||||
*/}}
|
||||
{{- define "common.secrets.key" -}}
|
||||
{{- $key := .key -}}
|
||||
|
||||
{{- if .existingSecret -}}
|
||||
{{- if not (typeIs "string" .existingSecret) -}}
|
||||
{{- if .existingSecret.keyMapping -}}
|
||||
{{- $key = index .existingSecret.keyMapping $.key -}}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{- printf "%s" $key -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Generate secret password or retrieve one if already created.
|
||||
|
||||
Usage:
|
||||
{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }}
|
||||
|
||||
Params:
|
||||
- secret - String - Required - Name of the 'Secret' resource where the password is stored.
|
||||
- key - String - Required - Name of the key in the secret.
|
||||
- providedValues - List<String> - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value.
|
||||
- length - int - Optional - Length of the generated random password.
|
||||
- strong - Boolean - Optional - Whether to add symbols to the generated random password.
|
||||
- chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart.
|
||||
- context - Context - Required - Parent context.
|
||||
- failOnNew - Boolean - Optional - Default to true. If set to false, skip errors adding new keys to existing secrets.
|
||||
The order in which this function returns a secret password:
|
||||
1. Already existing 'Secret' resource
|
||||
(If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned)
|
||||
2. Password provided via the values.yaml
|
||||
(If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned)
|
||||
3. Randomly generated secret password
|
||||
(A new random secret password with the length specified in the 'length' parameter will be generated and returned)
|
||||
|
||||
*/}}
|
||||
{{- define "common.secrets.passwords.manage" -}}
|
||||
|
||||
{{- $password := "" }}
|
||||
{{- $subchart := "" }}
|
||||
{{- $failOnNew := default true .failOnNew }}
|
||||
{{- $chartName := default "" .chartName }}
|
||||
{{- $passwordLength := default 10 .length }}
|
||||
{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }}
|
||||
{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }}
|
||||
{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data }}
|
||||
{{- if $secretData }}
|
||||
{{- if hasKey $secretData .key }}
|
||||
{{- $password = index $secretData .key | quote }}
|
||||
{{- else if $failOnNew }}
|
||||
{{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}}
|
||||
{{- end -}}
|
||||
{{- else if $providedPasswordValue }}
|
||||
{{- $password = $providedPasswordValue | toString | b64enc | quote }}
|
||||
{{- else }}
|
||||
|
||||
{{- if .context.Values.enabled }}
|
||||
{{- $subchart = $chartName }}
|
||||
{{- end -}}
|
||||
|
||||
{{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}}
|
||||
{{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}}
|
||||
{{- $passwordValidationErrors := list $requiredPasswordError -}}
|
||||
{{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}}
|
||||
|
||||
{{- if .strong }}
|
||||
{{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }}
|
||||
{{- $password = randAscii $passwordLength }}
|
||||
{{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }}
|
||||
{{- $password = printf "%s%s" $subStr $password | toString | shuffle | b64enc | quote }}
|
||||
{{- else }}
|
||||
{{- $password = randAlphaNum $passwordLength | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
{{- printf "%s" $password -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Reuses the value from an existing secret, otherwise sets its value to a default value.
|
||||
|
||||
Usage:
|
||||
{{ include "common.secrets.lookup" (dict "secret" "secret-name" "key" "keyName" "defaultValue" .Values.myValue "context" $) }}
|
||||
|
||||
Params:
|
||||
- secret - String - Required - Name of the 'Secret' resource where the password is stored.
|
||||
- key - String - Required - Name of the key in the secret.
|
||||
- defaultValue - String - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value.
|
||||
- context - Context - Required - Parent context.
|
||||
|
||||
*/}}
|
||||
{{- define "common.secrets.lookup" -}}
|
||||
{{- $value := "" -}}
|
||||
{{- $secretData := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret).data -}}
|
||||
{{- if and $secretData (hasKey $secretData .key) -}}
|
||||
{{- $value = index $secretData .key -}}
|
||||
{{- else if .defaultValue -}}
|
||||
{{- $value = .defaultValue | toString | b64enc -}}
|
||||
{{- end -}}
|
||||
{{- if $value -}}
|
||||
{{- printf "%s" $value -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Returns whether a previous generated secret already exists
|
||||
|
||||
Usage:
|
||||
{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }}
|
||||
|
||||
Params:
|
||||
- secret - String - Required - Name of the 'Secret' resource where the password is stored.
|
||||
- context - Context - Required - Parent context.
|
||||
*/}}
|
||||
{{- define "common.secrets.exists" -}}
|
||||
{{- $secret := (lookup "v1" "Secret" (include "common.names.namespace" .context) .secret) }}
|
||||
{{- if $secret }}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,28 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Return the proper Storage Class
|
||||
{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }}
|
||||
*/}}
|
||||
{{- define "common.storage.class" -}}
|
||||
|
||||
{{- $storageClass := .persistence.storageClass -}}
|
||||
{{- if .global -}}
|
||||
{{- if .global.storageClass -}}
|
||||
{{- $storageClass = .global.storageClass -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $storageClass -}}
|
||||
{{- if (eq "-" $storageClass) -}}
|
||||
{{- printf "storageClassName: \"\"" -}}
|
||||
{{- else }}
|
||||
{{- printf "storageClassName: %s" $storageClass -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
@ -0,0 +1,38 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Renders a value that contains template perhaps with scope if the scope is present.
|
||||
Usage:
|
||||
{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }}
|
||||
{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }}
|
||||
*/}}
|
||||
{{- define "common.tplvalues.render" -}}
|
||||
{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }}
|
||||
{{- if contains "{{" (toJson .value) }}
|
||||
{{- if .scope }}
|
||||
{{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }}
|
||||
{{- else }}
|
||||
{{- tpl $value .context }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- $value }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Merge a list of values that contains template after rendering them.
|
||||
Merge precedence is consistent with http://masterminds.github.io/sprig/dicts.html#merge-mustmerge
|
||||
Usage:
|
||||
{{ include "common.tplvalues.merge" ( dict "values" (list .Values.path.to.the.Value1 .Values.path.to.the.Value2) "context" $ ) }}
|
||||
*/}}
|
||||
{{- define "common.tplvalues.merge" -}}
|
||||
{{- $dst := dict -}}
|
||||
{{- range .values -}}
|
||||
{{- $dst = include "common.tplvalues.render" (dict "value" . "context" $.context "scope" $.scope) | fromYaml | merge $dst -}}
|
||||
{{- end -}}
|
||||
{{ $dst | toYaml }}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,77 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Print instructions to get a secret value.
|
||||
Usage:
|
||||
{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.utils.secret.getvalue" -}}
|
||||
{{- $varname := include "common.utils.fieldToEnvVar" . -}}
|
||||
export {{ $varname }}=$(kubectl get secret --namespace {{ include "common.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d)
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Build env var name given a field
|
||||
Usage:
|
||||
{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }}
|
||||
*/}}
|
||||
{{- define "common.utils.fieldToEnvVar" -}}
|
||||
{{- $fieldNameSplit := splitList "-" .field -}}
|
||||
{{- $upperCaseFieldNameSplit := list -}}
|
||||
|
||||
{{- range $fieldNameSplit -}}
|
||||
{{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{ join "_" $upperCaseFieldNameSplit }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Gets a value from .Values given
|
||||
Usage:
|
||||
{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.utils.getValueFromKey" -}}
|
||||
{{- $splitKey := splitList "." .key -}}
|
||||
{{- $value := "" -}}
|
||||
{{- $latestObj := $.context.Values -}}
|
||||
{{- range $splitKey -}}
|
||||
{{- if not $latestObj -}}
|
||||
{{- printf "please review the entire path of '%s' exists in values" $.key | fail -}}
|
||||
{{- end -}}
|
||||
{{- $value = ( index $latestObj . ) -}}
|
||||
{{- $latestObj = $value -}}
|
||||
{{- end -}}
|
||||
{{- printf "%v" (default "" $value) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Returns first .Values key with a defined value or first of the list if all non-defined
|
||||
Usage:
|
||||
{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.utils.getKeyFromList" -}}
|
||||
{{- $key := first .keys -}}
|
||||
{{- $reverseKeys := reverse .keys }}
|
||||
{{- range $reverseKeys }}
|
||||
{{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }}
|
||||
{{- if $value -}}
|
||||
{{- $key = . }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- printf "%s" $key -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Checksum a template at "path" containing a *single* resource (ConfigMap,Secret) for use in pod annotations, excluding the metadata (see #18376).
|
||||
Usage:
|
||||
{{ include "common.utils.checksumTemplate" (dict "path" "/configmap.yaml" "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.utils.checksumTemplate" -}}
|
||||
{{- $obj := include (print .context.Template.BasePath .path) .context | fromYaml -}}
|
||||
{{ omit $obj "apiVersion" "kind" "metadata" | toYaml | sha256sum }}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,19 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Warning about using rolling tag.
|
||||
Usage:
|
||||
{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }}
|
||||
*/}}
|
||||
{{- define "common.warnings.rollingTag" -}}
|
||||
|
||||
{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }}
|
||||
WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment.
|
||||
+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/
|
||||
{{- end }}
|
||||
|
||||
{{- end -}}
|
||||
@ -0,0 +1,77 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Validate Cassandra required passwords are not empty.
|
||||
|
||||
Usage:
|
||||
{{ include "common.validations.values.cassandra.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
|
||||
Params:
|
||||
- secret - String - Required. Name of the secret where Cassandra values are stored, e.g: "cassandra-passwords-secret"
|
||||
- subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.validations.values.cassandra.passwords" -}}
|
||||
{{- $existingSecret := include "common.cassandra.values.existingSecret" . -}}
|
||||
{{- $enabled := include "common.cassandra.values.enabled" . -}}
|
||||
{{- $dbUserPrefix := include "common.cassandra.values.key.dbUser" . -}}
|
||||
{{- $valueKeyPassword := printf "%s.password" $dbUserPrefix -}}
|
||||
|
||||
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}}
|
||||
{{- $requiredPasswords := list -}}
|
||||
|
||||
{{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "cassandra-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredPassword -}}
|
||||
|
||||
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for existingSecret.
|
||||
|
||||
Usage:
|
||||
{{ include "common.cassandra.values.existingSecret" (dict "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.cassandra.values.existingSecret" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- .context.Values.cassandra.dbUser.existingSecret | quote -}}
|
||||
{{- else -}}
|
||||
{{- .context.Values.dbUser.existingSecret | quote -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for enabled cassandra.
|
||||
|
||||
Usage:
|
||||
{{ include "common.cassandra.values.enabled" (dict "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.cassandra.values.enabled" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- printf "%v" .context.Values.cassandra.enabled -}}
|
||||
{{- else -}}
|
||||
{{- printf "%v" (not .context.Values.enabled) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for the key dbUser
|
||||
|
||||
Usage:
|
||||
{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.cassandra.values.key.dbUser" -}}
|
||||
{{- if .subchart -}}
|
||||
cassandra.dbUser
|
||||
{{- else -}}
|
||||
dbUser
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,108 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Validate MariaDB required passwords are not empty.
|
||||
|
||||
Usage:
|
||||
{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
|
||||
Params:
|
||||
- secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret"
|
||||
- subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.validations.values.mariadb.passwords" -}}
|
||||
{{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}}
|
||||
{{- $enabled := include "common.mariadb.values.enabled" . -}}
|
||||
{{- $architecture := include "common.mariadb.values.architecture" . -}}
|
||||
{{- $authPrefix := include "common.mariadb.values.key.auth" . -}}
|
||||
{{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}}
|
||||
{{- $valueKeyUsername := printf "%s.username" $authPrefix -}}
|
||||
{{- $valueKeyPassword := printf "%s.password" $authPrefix -}}
|
||||
{{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}}
|
||||
|
||||
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}}
|
||||
{{- $requiredPasswords := list -}}
|
||||
|
||||
{{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}}
|
||||
|
||||
{{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }}
|
||||
{{- if not (empty $valueUsername) -}}
|
||||
{{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredPassword -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if (eq $architecture "replication") -}}
|
||||
{{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for existingSecret.
|
||||
|
||||
Usage:
|
||||
{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.mariadb.values.auth.existingSecret" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- .context.Values.mariadb.auth.existingSecret | quote -}}
|
||||
{{- else -}}
|
||||
{{- .context.Values.auth.existingSecret | quote -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for enabled mariadb.
|
||||
|
||||
Usage:
|
||||
{{ include "common.mariadb.values.enabled" (dict "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.mariadb.values.enabled" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- printf "%v" .context.Values.mariadb.enabled -}}
|
||||
{{- else -}}
|
||||
{{- printf "%v" (not .context.Values.enabled) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for architecture
|
||||
|
||||
Usage:
|
||||
{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.mariadb.values.architecture" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- .context.Values.mariadb.architecture -}}
|
||||
{{- else -}}
|
||||
{{- .context.Values.architecture -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for the key auth
|
||||
|
||||
Usage:
|
||||
{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.mariadb.values.key.auth" -}}
|
||||
{{- if .subchart -}}
|
||||
mariadb.auth
|
||||
{{- else -}}
|
||||
auth
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,113 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Validate MongoDB® required passwords are not empty.
|
||||
|
||||
Usage:
|
||||
{{ include "common.validations.values.mongodb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
|
||||
Params:
|
||||
- secret - String - Required. Name of the secret where MongoDB® values are stored, e.g: "mongodb-passwords-secret"
|
||||
- subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.validations.values.mongodb.passwords" -}}
|
||||
{{- $existingSecret := include "common.mongodb.values.auth.existingSecret" . -}}
|
||||
{{- $enabled := include "common.mongodb.values.enabled" . -}}
|
||||
{{- $authPrefix := include "common.mongodb.values.key.auth" . -}}
|
||||
{{- $architecture := include "common.mongodb.values.architecture" . -}}
|
||||
{{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}}
|
||||
{{- $valueKeyUsername := printf "%s.username" $authPrefix -}}
|
||||
{{- $valueKeyDatabase := printf "%s.database" $authPrefix -}}
|
||||
{{- $valueKeyPassword := printf "%s.password" $authPrefix -}}
|
||||
{{- $valueKeyReplicaSetKey := printf "%s.replicaSetKey" $authPrefix -}}
|
||||
{{- $valueKeyAuthEnabled := printf "%s.enabled" $authPrefix -}}
|
||||
|
||||
{{- $authEnabled := include "common.utils.getValueFromKey" (dict "key" $valueKeyAuthEnabled "context" .context) -}}
|
||||
|
||||
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") (eq $authEnabled "true") -}}
|
||||
{{- $requiredPasswords := list -}}
|
||||
|
||||
{{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mongodb-root-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}}
|
||||
|
||||
{{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }}
|
||||
{{- $valueDatabase := include "common.utils.getValueFromKey" (dict "key" $valueKeyDatabase "context" .context) }}
|
||||
{{- if and $valueUsername $valueDatabase -}}
|
||||
{{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mongodb-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredPassword -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if (eq $architecture "replicaset") -}}
|
||||
{{- $requiredReplicaSetKey := dict "valueKey" $valueKeyReplicaSetKey "secret" .secret "field" "mongodb-replica-set-key" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredReplicaSetKey -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for existingSecret.
|
||||
|
||||
Usage:
|
||||
{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.mongodb.values.auth.existingSecret" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- .context.Values.mongodb.auth.existingSecret | quote -}}
|
||||
{{- else -}}
|
||||
{{- .context.Values.auth.existingSecret | quote -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for enabled mongodb.
|
||||
|
||||
Usage:
|
||||
{{ include "common.mongodb.values.enabled" (dict "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.mongodb.values.enabled" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- printf "%v" .context.Values.mongodb.enabled -}}
|
||||
{{- else -}}
|
||||
{{- printf "%v" (not .context.Values.enabled) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for the key auth
|
||||
|
||||
Usage:
|
||||
{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.mongodb.values.key.auth" -}}
|
||||
{{- if .subchart -}}
|
||||
mongodb.auth
|
||||
{{- else -}}
|
||||
auth
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for architecture
|
||||
|
||||
Usage:
|
||||
{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.mongodb.values.architecture" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- .context.Values.mongodb.architecture -}}
|
||||
{{- else -}}
|
||||
{{- .context.Values.architecture -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,108 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Validate MySQL required passwords are not empty.
|
||||
|
||||
Usage:
|
||||
{{ include "common.validations.values.mysql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
|
||||
Params:
|
||||
- secret - String - Required. Name of the secret where MySQL values are stored, e.g: "mysql-passwords-secret"
|
||||
- subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.validations.values.mysql.passwords" -}}
|
||||
{{- $existingSecret := include "common.mysql.values.auth.existingSecret" . -}}
|
||||
{{- $enabled := include "common.mysql.values.enabled" . -}}
|
||||
{{- $architecture := include "common.mysql.values.architecture" . -}}
|
||||
{{- $authPrefix := include "common.mysql.values.key.auth" . -}}
|
||||
{{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}}
|
||||
{{- $valueKeyUsername := printf "%s.username" $authPrefix -}}
|
||||
{{- $valueKeyPassword := printf "%s.password" $authPrefix -}}
|
||||
{{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}}
|
||||
|
||||
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}}
|
||||
{{- $requiredPasswords := list -}}
|
||||
|
||||
{{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mysql-root-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}}
|
||||
|
||||
{{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }}
|
||||
{{- if not (empty $valueUsername) -}}
|
||||
{{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mysql-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredPassword -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if (eq $architecture "replication") -}}
|
||||
{{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mysql-replication-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for existingSecret.
|
||||
|
||||
Usage:
|
||||
{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.mysql.values.auth.existingSecret" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- .context.Values.mysql.auth.existingSecret | quote -}}
|
||||
{{- else -}}
|
||||
{{- .context.Values.auth.existingSecret | quote -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for enabled mysql.
|
||||
|
||||
Usage:
|
||||
{{ include "common.mysql.values.enabled" (dict "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.mysql.values.enabled" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- printf "%v" .context.Values.mysql.enabled -}}
|
||||
{{- else -}}
|
||||
{{- printf "%v" (not .context.Values.enabled) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for architecture
|
||||
|
||||
Usage:
|
||||
{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.mysql.values.architecture" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- .context.Values.mysql.architecture -}}
|
||||
{{- else -}}
|
||||
{{- .context.Values.architecture -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for the key auth
|
||||
|
||||
Usage:
|
||||
{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.mysql.values.key.auth" -}}
|
||||
{{- if .subchart -}}
|
||||
mysql.auth
|
||||
{{- else -}}
|
||||
auth
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,134 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Validate PostgreSQL required passwords are not empty.
|
||||
|
||||
Usage:
|
||||
{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
|
||||
Params:
|
||||
- secret - String - Required. Name of the secret where postgresql values are stored, e.g: "postgresql-passwords-secret"
|
||||
- subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.validations.values.postgresql.passwords" -}}
|
||||
{{- $existingSecret := include "common.postgresql.values.existingSecret" . -}}
|
||||
{{- $enabled := include "common.postgresql.values.enabled" . -}}
|
||||
{{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}}
|
||||
{{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}}
|
||||
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}}
|
||||
{{- $requiredPasswords := list -}}
|
||||
{{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}}
|
||||
|
||||
{{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}}
|
||||
{{- if (eq $enabledReplication "true") -}}
|
||||
{{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to decide whether evaluate global values.
|
||||
|
||||
Usage:
|
||||
{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }}
|
||||
Params:
|
||||
- key - String - Required. Field to be evaluated within global, e.g: "existingSecret"
|
||||
*/}}
|
||||
{{- define "common.postgresql.values.use.global" -}}
|
||||
{{- if .context.Values.global -}}
|
||||
{{- if .context.Values.global.postgresql -}}
|
||||
{{- index .context.Values.global.postgresql .key | quote -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for existingSecret.
|
||||
|
||||
Usage:
|
||||
{{ include "common.postgresql.values.existingSecret" (dict "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.postgresql.values.existingSecret" -}}
|
||||
{{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}}
|
||||
|
||||
{{- if .subchart -}}
|
||||
{{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}}
|
||||
{{- else -}}
|
||||
{{- default (.context.Values.existingSecret | quote) $globalValue -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for enabled postgresql.
|
||||
|
||||
Usage:
|
||||
{{ include "common.postgresql.values.enabled" (dict "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.postgresql.values.enabled" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- printf "%v" .context.Values.postgresql.enabled -}}
|
||||
{{- else -}}
|
||||
{{- printf "%v" (not .context.Values.enabled) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for the key postgressPassword.
|
||||
|
||||
Usage:
|
||||
{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.postgresql.values.key.postgressPassword" -}}
|
||||
{{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}}
|
||||
|
||||
{{- if not $globalValue -}}
|
||||
{{- if .subchart -}}
|
||||
postgresql.postgresqlPassword
|
||||
{{- else -}}
|
||||
postgresqlPassword
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
global.postgresql.postgresqlPassword
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for enabled.replication.
|
||||
|
||||
Usage:
|
||||
{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.postgresql.values.enabled.replication" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- printf "%v" .context.Values.postgresql.replication.enabled -}}
|
||||
{{- else -}}
|
||||
{{- printf "%v" .context.Values.replication.enabled -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for the key replication.password.
|
||||
|
||||
Usage:
|
||||
{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.postgresql.values.key.replicationPassword" -}}
|
||||
{{- if .subchart -}}
|
||||
postgresql.replication.password
|
||||
{{- else -}}
|
||||
replication.password
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,81 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Validate Redis® required passwords are not empty.
|
||||
|
||||
Usage:
|
||||
{{ include "common.validations.values.redis.passwords" (dict "secret" "secretName" "subchart" false "context" $) }}
|
||||
Params:
|
||||
- secret - String - Required. Name of the secret where redis values are stored, e.g: "redis-passwords-secret"
|
||||
- subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.validations.values.redis.passwords" -}}
|
||||
{{- $enabled := include "common.redis.values.enabled" . -}}
|
||||
{{- $valueKeyPrefix := include "common.redis.values.keys.prefix" . -}}
|
||||
{{- $standarizedVersion := include "common.redis.values.standarized.version" . }}
|
||||
|
||||
{{- $existingSecret := ternary (printf "%s%s" $valueKeyPrefix "auth.existingSecret") (printf "%s%s" $valueKeyPrefix "existingSecret") (eq $standarizedVersion "true") }}
|
||||
{{- $existingSecretValue := include "common.utils.getValueFromKey" (dict "key" $existingSecret "context" .context) }}
|
||||
|
||||
{{- $valueKeyRedisPassword := ternary (printf "%s%s" $valueKeyPrefix "auth.password") (printf "%s%s" $valueKeyPrefix "password") (eq $standarizedVersion "true") }}
|
||||
{{- $valueKeyRedisUseAuth := ternary (printf "%s%s" $valueKeyPrefix "auth.enabled") (printf "%s%s" $valueKeyPrefix "usePassword") (eq $standarizedVersion "true") }}
|
||||
|
||||
{{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}}
|
||||
{{- $requiredPasswords := list -}}
|
||||
|
||||
{{- $useAuth := include "common.utils.getValueFromKey" (dict "key" $valueKeyRedisUseAuth "context" .context) -}}
|
||||
{{- if eq $useAuth "true" -}}
|
||||
{{- $requiredRedisPassword := dict "valueKey" $valueKeyRedisPassword "secret" .secret "field" "redis-password" -}}
|
||||
{{- $requiredPasswords = append $requiredPasswords $requiredRedisPassword -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right value for enabled redis.
|
||||
|
||||
Usage:
|
||||
{{ include "common.redis.values.enabled" (dict "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.redis.values.enabled" -}}
|
||||
{{- if .subchart -}}
|
||||
{{- printf "%v" .context.Values.redis.enabled -}}
|
||||
{{- else -}}
|
||||
{{- printf "%v" (not .context.Values.enabled) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Auxiliary function to get the right prefix path for the values
|
||||
|
||||
Usage:
|
||||
{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }}
|
||||
Params:
|
||||
- subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false
|
||||
*/}}
|
||||
{{- define "common.redis.values.keys.prefix" -}}
|
||||
{{- if .subchart -}}redis.{{- else -}}{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Checks whether the redis chart's includes the standarizations (version >= 14)
|
||||
|
||||
Usage:
|
||||
{{ include "common.redis.values.standarized.version" (dict "context" $) }}
|
||||
*/}}
|
||||
{{- define "common.redis.values.standarized.version" -}}
|
||||
|
||||
{{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}}
|
||||
{{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }}
|
||||
|
||||
{{- if $standarizedAuthValues -}}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,51 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Validate values must not be empty.
|
||||
|
||||
Usage:
|
||||
{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}}
|
||||
{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}}
|
||||
{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }}
|
||||
|
||||
Validate value params:
|
||||
- valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password"
|
||||
- secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret"
|
||||
- field - String - Optional. Name of the field in the secret data, e.g: "mysql-password"
|
||||
*/}}
|
||||
{{- define "common.validations.values.multiple.empty" -}}
|
||||
{{- range .required -}}
|
||||
{{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Validate a value must not be empty.
|
||||
|
||||
Usage:
|
||||
{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }}
|
||||
|
||||
Validate value params:
|
||||
- valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password"
|
||||
- secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret"
|
||||
- field - String - Optional. Name of the field in the secret data, e.g: "mysql-password"
|
||||
- subchart - String - Optional - Name of the subchart that the validated password is part of.
|
||||
*/}}
|
||||
{{- define "common.validations.values.single.empty" -}}
|
||||
{{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }}
|
||||
{{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }}
|
||||
|
||||
{{- if not $value -}}
|
||||
{{- $varname := "my-value" -}}
|
||||
{{- $getCurrentValue := "" -}}
|
||||
{{- if and .secret .field -}}
|
||||
{{- $varname = include "common.utils.fieldToEnvVar" . -}}
|
||||
{{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}}
|
||||
{{- end -}}
|
||||
{{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@ -0,0 +1,8 @@
|
||||
# Copyright VMware, Inc.
|
||||
# SPDX-License-Identifier: APACHE-2.0
|
||||
|
||||
## bitnami/common
|
||||
## It is required by CI/CD tools and processes.
|
||||
## @skip exampleValue
|
||||
##
|
||||
exampleValue: common-chart
|
||||
115
charts/airflow/charts/postgresql/templates/NOTES.txt
Normal file
115
charts/airflow/charts/postgresql/templates/NOTES.txt
Normal file
@ -0,0 +1,115 @@
|
||||
CHART NAME: {{ .Chart.Name }}
|
||||
CHART VERSION: {{ .Chart.Version }}
|
||||
APP VERSION: {{ .Chart.AppVersion }}
|
||||
|
||||
** Please be patient while the chart is being deployed **
|
||||
|
||||
{{- if .Values.diagnosticMode.enabled }}
|
||||
The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with:
|
||||
|
||||
command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }}
|
||||
args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }}
|
||||
|
||||
Get the list of pods by executing:
|
||||
|
||||
kubectl get pods --namespace {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }}
|
||||
|
||||
Access the pod you want to debug by executing
|
||||
|
||||
kubectl exec --namespace {{ .Release.Namespace }} -ti <NAME OF THE POD> -- /opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash
|
||||
|
||||
In order to replicate the container startup scripts execute this command:
|
||||
|
||||
/opt/bitnami/scripts/postgresql/entrypoint.sh /opt/bitnami/scripts/postgresql/run.sh
|
||||
|
||||
{{- else }}
|
||||
|
||||
{{- $customUser := include "postgresql.v1.username" . }}
|
||||
{{- $postgresPassword := include "common.secrets.lookup" (dict "secret" (include "common.names.fullname" .) "key" .Values.auth.secretKeys.adminPasswordKey "defaultValue" (ternary .Values.auth.postgresPassword .Values.auth.password (eq $customUser "postgres")) "context" $) -}}
|
||||
{{- $authEnabled := and (not (or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret)) (or $postgresPassword .Values.auth.enablePostgresUser (and (not (empty $customUser)) (ne $customUser "postgres"))) }}
|
||||
{{- if not $authEnabled }}
|
||||
|
||||
WARNING: PostgreSQL has been configured without authentication, this is not recommended for production environments.
|
||||
{{- end }}
|
||||
|
||||
PostgreSQL can be accessed via port {{ include "postgresql.v1.service.port" . }} on the following DNS names from within your cluster:
|
||||
|
||||
{{ include "postgresql.v1.primary.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - Read/Write connection
|
||||
|
||||
{{- if eq .Values.architecture "replication" }}
|
||||
|
||||
{{ include "postgresql.v1.readReplica.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - Read only connection
|
||||
|
||||
{{- end }}
|
||||
|
||||
{{- if and (not (empty $customUser)) (ne $customUser "postgres") }}
|
||||
{{- if .Values.auth.enablePostgresUser }}
|
||||
|
||||
To get the password for "postgres" run:
|
||||
|
||||
export POSTGRES_ADMIN_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "postgresql.v1.secretName" . }} -o jsonpath="{.data.{{include "postgresql.v1.adminPasswordKey" .}}}" | base64 -d)
|
||||
{{- end }}
|
||||
|
||||
To get the password for "{{ $customUser }}" run:
|
||||
|
||||
export POSTGRES_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "postgresql.v1.secretName" . }} -o jsonpath="{.data.{{include "postgresql.v1.userPasswordKey" .}}}" | base64 -d)
|
||||
{{- else }}
|
||||
{{- if .Values.auth.enablePostgresUser }}
|
||||
|
||||
To get the password for "{{ default "postgres" $customUser }}" run:
|
||||
|
||||
export POSTGRES_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "postgresql.v1.secretName" . }} -o jsonpath="{.data.{{ ternary "password" (include "postgresql.v1.adminPasswordKey" .) (and (not (empty $customUser)) (ne $customUser "postgres")) }}}" | base64 -d)
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
To connect to your database run the following command:
|
||||
{{- if $authEnabled }}
|
||||
|
||||
kubectl run {{ include "common.names.fullname" . }}-client --rm --tty -i --restart='Never' --namespace {{ .Release.Namespace }} --image {{ include "postgresql.v1.image" . }} --env="PGPASSWORD=$POSTGRES_PASSWORD" \
|
||||
--command -- psql --host {{ include "postgresql.v1.primary.fullname" . }} -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} -p {{ include "postgresql.v1.service.port" . }}
|
||||
{{- else }}
|
||||
|
||||
kubectl run {{ include "common.names.fullname" . }}-client --rm --tty -i --restart='Never' --namespace {{ .Release.Namespace }} --image {{ include "postgresql.v1.image" . }} \
|
||||
--command -- psql --host {{ include "postgresql.v1.primary.fullname" . }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} -p {{ include "postgresql.v1.service.port" . }}
|
||||
{{- end }}
|
||||
|
||||
> NOTE: If you access the container using bash, make sure that you execute "/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash" in order to avoid the error "psql: local user with ID {{ .Values.primary.containerSecurityContext.runAsUser }}} does not exist"
|
||||
|
||||
To connect to your database from outside the cluster execute the following commands:
|
||||
|
||||
{{- if contains "NodePort" .Values.primary.service.type }}
|
||||
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "postgresql.v1.primary.fullname" . }})
|
||||
{{- if $authEnabled }}
|
||||
PGPASSWORD="$POSTGRES_PASSWORD" psql --host $NODE_IP --port $NODE_PORT -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }}
|
||||
{{- else }}
|
||||
psql --host $NODE_IP --port $NODE_PORT -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }}
|
||||
{{- end }}
|
||||
{{- else if contains "LoadBalancer" .Values.primary.service.type }}
|
||||
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ include "postgresql.v1.primary.fullname" . }}'
|
||||
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "postgresql.v1.primary.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}")
|
||||
{{- if $authEnabled }}
|
||||
PGPASSWORD="$POSTGRES_PASSWORD" psql --host $SERVICE_IP --port {{ include "postgresql.v1.service.port" . }} -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }}
|
||||
{{- else }}
|
||||
psql --host $SERVICE_IP --port {{ include "postgresql.v1.service.port" . }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }}
|
||||
{{- end }}
|
||||
{{- else if contains "ClusterIP" .Values.primary.service.type }}
|
||||
|
||||
kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "postgresql.v1.primary.fullname" . }} {{ include "postgresql.v1.service.port" . }}:{{ include "postgresql.v1.service.port" . }} &
|
||||
{{- if $authEnabled }}
|
||||
PGPASSWORD="$POSTGRES_PASSWORD" psql --host 127.0.0.1 -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} -p {{ include "postgresql.v1.service.port" . }}
|
||||
{{- else }}
|
||||
psql --host 127.0.0.1 -d {{- if include "postgresql.v1.database" . }} {{ include "postgresql.v1.database" . }}{{- else }} postgres{{- end }} -p {{ include "postgresql.v1.service.port" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
WARNING: The configured password will be ignored on new installation in case when previous PostgreSQL release was deleted through the helm command. In that case, old PVC will have an old password, and setting it through helm won't take effect. Deleting persistent volumes (PVs) will solve the issue.
|
||||
|
||||
{{- include "postgresql.v1.validateValues" . -}}
|
||||
{{- include "common.warnings.rollingTag" .Values.image -}}
|
||||
{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }}
|
||||
406
charts/airflow/charts/postgresql/templates/_helpers.tpl
Normal file
406
charts/airflow/charts/postgresql/templates/_helpers.tpl
Normal file
@ -0,0 +1,406 @@
|
||||
{{/*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name for PostgreSQL Primary objects
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
*/}}
|
||||
{{- define "postgresql.v1.primary.fullname" -}}
|
||||
{{- if eq .Values.architecture "replication" -}}
|
||||
{{- printf "%s-%s" (include "common.names.fullname" .) .Values.primary.name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- include "common.names.fullname" . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name for PostgreSQL read-only replicas objects
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
*/}}
|
||||
{{- define "postgresql.v1.readReplica.fullname" -}}
|
||||
{{- printf "%s-%s" (include "common.names.fullname" .) .Values.readReplicas.name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the default FQDN for PostgreSQL primary headless service
|
||||
We truncate at 63 chars because of the DNS naming spec.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.primary.svc.headless" -}}
|
||||
{{- printf "%s-hl" (include "postgresql.v1.primary.fullname" .) | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the default FQDN for PostgreSQL read-only replicas headless service
|
||||
We truncate at 63 chars because of the DNS naming spec.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.readReplica.svc.headless" -}}
|
||||
{{- printf "%s-hl" (include "postgresql.v1.readReplica.fullname" .) | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the proper PostgreSQL image name
|
||||
*/}}
|
||||
{{- define "postgresql.v1.image" -}}
|
||||
{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the proper PostgreSQL metrics image name
|
||||
*/}}
|
||||
{{- define "postgresql.v1.metrics.image" -}}
|
||||
{{ include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the proper image name (for the init container volume-permissions image)
|
||||
*/}}
|
||||
{{- define "postgresql.v1.volumePermissions.image" -}}
|
||||
{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the proper Docker Image Registry Secret Names
|
||||
*/}}
|
||||
{{- define "postgresql.v1.imagePullSecrets" -}}
|
||||
{{ include "common.images.renderPullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image) "context" $) }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the name for a custom user to create
|
||||
*/}}
|
||||
{{- define "postgresql.v1.username" -}}
|
||||
{{- if .Values.global.postgresql.auth.username -}}
|
||||
{{- .Values.global.postgresql.auth.username -}}
|
||||
{{- else -}}
|
||||
{{- .Values.auth.username -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the name for a custom database to create
|
||||
*/}}
|
||||
{{- define "postgresql.v1.database" -}}
|
||||
{{- if .Values.global.postgresql.auth.database -}}
|
||||
{{- printf "%s" (tpl .Values.global.postgresql.auth.database $) -}}
|
||||
{{- else if .Values.auth.database -}}
|
||||
{{- printf "%s" (tpl .Values.auth.database $) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get the password secret.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.secretName" -}}
|
||||
{{- if .Values.global.postgresql.auth.existingSecret -}}
|
||||
{{- printf "%s" (tpl .Values.global.postgresql.auth.existingSecret $) -}}
|
||||
{{- else if .Values.auth.existingSecret -}}
|
||||
{{- printf "%s" (tpl .Values.auth.existingSecret $) -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s" (include "common.names.fullname" .) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get the replication-password key.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.replicationPasswordKey" -}}
|
||||
{{- if or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret -}}
|
||||
{{- if .Values.global.postgresql.auth.secretKeys.replicationPasswordKey -}}
|
||||
{{- printf "%s" (tpl .Values.global.postgresql.auth.secretKeys.replicationPasswordKey $) -}}
|
||||
{{- else if .Values.auth.secretKeys.replicationPasswordKey -}}
|
||||
{{- printf "%s" (tpl .Values.auth.secretKeys.replicationPasswordKey $) -}}
|
||||
{{- else -}}
|
||||
{{- "replication-password" -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- "replication-password" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get the admin-password key.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.adminPasswordKey" -}}
|
||||
{{- if or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret -}}
|
||||
{{- if .Values.global.postgresql.auth.secretKeys.adminPasswordKey -}}
|
||||
{{- printf "%s" (tpl .Values.global.postgresql.auth.secretKeys.adminPasswordKey $) -}}
|
||||
{{- else if .Values.auth.secretKeys.adminPasswordKey -}}
|
||||
{{- printf "%s" (tpl .Values.auth.secretKeys.adminPasswordKey $) -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- "postgres-password" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get the user-password key.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.userPasswordKey" -}}
|
||||
{{- if or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret -}}
|
||||
{{- if or (empty (include "postgresql.v1.username" .)) (eq (include "postgresql.v1.username" .) "postgres") -}}
|
||||
{{- printf "%s" (include "postgresql.v1.adminPasswordKey" .) -}}
|
||||
{{- else -}}
|
||||
{{- if .Values.global.postgresql.auth.secretKeys.userPasswordKey -}}
|
||||
{{- printf "%s" (tpl .Values.global.postgresql.auth.secretKeys.userPasswordKey $) -}}
|
||||
{{- else if .Values.auth.secretKeys.userPasswordKey -}}
|
||||
{{- printf "%s" (tpl .Values.auth.secretKeys.userPasswordKey $) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- "password" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return true if a secret object should be created
|
||||
*/}}
|
||||
{{- define "postgresql.v1.createSecret" -}}
|
||||
{{- $customUser := include "postgresql.v1.username" . -}}
|
||||
{{- $postgresPassword := include "common.secrets.lookup" (dict "secret" (include "common.names.fullname" .) "key" .Values.auth.secretKeys.adminPasswordKey "defaultValue" (ternary (coalesce .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword .Values.global.postgresql.auth.password .Values.auth.password) (coalesce .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword) (or (empty $customUser) (eq $customUser "postgres"))) "context" $) -}}
|
||||
{{- if and (not (or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret)) (or $postgresPassword .Values.auth.enablePostgresUser (and (not (empty $customUser)) (ne $customUser "postgres")) (eq .Values.architecture "replication") (and .Values.ldap.enabled (or .Values.ldap.bind_password .Values.ldap.bindpw))) -}}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return PostgreSQL service port
|
||||
*/}}
|
||||
{{- define "postgresql.v1.service.port" -}}
|
||||
{{- if .Values.global.postgresql.service.ports.postgresql -}}
|
||||
{{- .Values.global.postgresql.service.ports.postgresql -}}
|
||||
{{- else -}}
|
||||
{{- .Values.primary.service.ports.postgresql -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return PostgreSQL service port
|
||||
*/}}
|
||||
{{- define "postgresql.v1.readReplica.service.port" -}}
|
||||
{{- if .Values.global.postgresql.service.ports.postgresql -}}
|
||||
{{- .Values.global.postgresql.service.ports.postgresql -}}
|
||||
{{- else -}}
|
||||
{{- .Values.readReplicas.service.ports.postgresql -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get the PostgreSQL primary configuration ConfigMap name.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.primary.configmapName" -}}
|
||||
{{- if .Values.primary.existingConfigmap -}}
|
||||
{{- printf "%s" (tpl .Values.primary.existingConfigmap $) -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-configuration" (include "postgresql.v1.primary.fullname" .) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return true if a configmap object should be created for PostgreSQL primary with the configuration
|
||||
*/}}
|
||||
{{- define "postgresql.v1.primary.createConfigmap" -}}
|
||||
{{- if and (or .Values.primary.configuration .Values.primary.pgHbaConfiguration) (not .Values.primary.existingConfigmap) -}}
|
||||
{{- true -}}
|
||||
{{- else -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get the PostgreSQL primary extended configuration ConfigMap name.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.primary.extendedConfigmapName" -}}
|
||||
{{- if .Values.primary.existingExtendedConfigmap -}}
|
||||
{{- printf "%s" (tpl .Values.primary.existingExtendedConfigmap $) -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-extended-configuration" (include "postgresql.v1.primary.fullname" .) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get the PostgreSQL read replica extended configuration ConfigMap name.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.readReplicas.extendedConfigmapName" -}}
|
||||
{{- printf "%s-extended-configuration" (include "postgresql.v1.readReplica.fullname" .) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return true if a configmap object should be created for PostgreSQL primary with the extended configuration
|
||||
*/}}
|
||||
{{- define "postgresql.v1.primary.createExtendedConfigmap" -}}
|
||||
{{- if and .Values.primary.extendedConfiguration (not .Values.primary.existingExtendedConfigmap) -}}
|
||||
{{- true -}}
|
||||
{{- else -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return true if a configmap object should be created for PostgreSQL read replica with the extended configuration
|
||||
*/}}
|
||||
{{- define "postgresql.v1.readReplicas.createExtendedConfigmap" -}}
|
||||
{{- if .Values.readReplicas.extendedConfiguration -}}
|
||||
{{- true -}}
|
||||
{{- else -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "postgresql.v1.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{ default (include "common.names.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else -}}
|
||||
{{ default "default" .Values.serviceAccount.name }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return true if a configmap should be mounted with PostgreSQL configuration
|
||||
*/}}
|
||||
{{- define "postgresql.v1.mountConfigurationCM" -}}
|
||||
{{- if or .Values.primary.configuration .Values.primary.pgHbaConfiguration .Values.primary.existingConfigmap -}}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get the initialization scripts ConfigMap name.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.initdb.scriptsCM" -}}
|
||||
{{- if .Values.primary.initdb.scriptsConfigMap -}}
|
||||
{{- printf "%s" (tpl .Values.primary.initdb.scriptsConfigMap $) -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-init-scripts" (include "postgresql.v1.primary.fullname" .) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return true if TLS is enabled for LDAP connection
|
||||
*/}}
|
||||
{{- define "postgresql.v1.ldap.tls.enabled" -}}
|
||||
{{- if and (kindIs "string" .Values.ldap.tls) (not (empty .Values.ldap.tls)) -}}
|
||||
{{- true -}}
|
||||
{{- else if and (kindIs "map" .Values.ldap.tls) .Values.ldap.tls.enabled -}}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get the readiness probe command
|
||||
*/}}
|
||||
{{- define "postgresql.v1.readinessProbeCommand" -}}
|
||||
{{- $customUser := include "postgresql.v1.username" . -}}
|
||||
- |
|
||||
{{- if (include "postgresql.v1.database" .) }}
|
||||
exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.v1.database" . }} {{- if .Values.tls.enabled }} sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }}
|
||||
{{- else }}
|
||||
exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if .Values.tls.enabled }} -d "sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }}
|
||||
{{- end }}
|
||||
{{- if contains "bitnami/" .Values.image.repository }}
|
||||
[ -f /opt/bitnami/postgresql/tmp/.initialized ] || [ -f /bitnami/postgresql/.initialized ]
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Compile all warnings into a single message, and call fail.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.validateValues" -}}
|
||||
{{- $messages := list -}}
|
||||
{{- $messages := append $messages (include "postgresql.v1.validateValues.ldapConfigurationMethod" .) -}}
|
||||
{{- $messages := append $messages (include "postgresql.v1.validateValues.psp" .) -}}
|
||||
{{- $messages := without $messages "" -}}
|
||||
{{- $message := join "\n" $messages -}}
|
||||
|
||||
{{- if $message -}}
|
||||
{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Validate values of Postgresql - If ldap.url is used then you don't need the other settings for ldap
|
||||
*/}}
|
||||
{{- define "postgresql.v1.validateValues.ldapConfigurationMethod" -}}
|
||||
{{- if and .Values.ldap.enabled (and (not (empty .Values.ldap.url)) (not (empty .Values.ldap.server))) -}}
|
||||
postgresql: ldap.url, ldap.server
|
||||
You cannot set both `ldap.url` and `ldap.server` at the same time.
|
||||
Please provide a unique way to configure LDAP.
|
||||
More info at https://www.postgresql.org/docs/current/auth-ldap.html
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Validate values of Postgresql - If PSP is enabled RBAC should be enabled too
|
||||
*/}}
|
||||
{{- define "postgresql.v1.validateValues.psp" -}}
|
||||
{{- if and .Values.psp.create (not .Values.rbac.create) -}}
|
||||
postgresql: psp.create, rbac.create
|
||||
RBAC should be enabled if PSP is enabled in order for PSP to work.
|
||||
More info at https://kubernetes.io/docs/concepts/policy/pod-security-policy/#authorizing-policies
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the path to the cert file.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.tlsCert" -}}
|
||||
{{- if .Values.tls.autoGenerated -}}
|
||||
{{- printf "/opt/bitnami/postgresql/certs/tls.crt" -}}
|
||||
{{- else -}}
|
||||
{{- required "Certificate filename is required when TLS in enabled" .Values.tls.certFilename | printf "/opt/bitnami/postgresql/certs/%s" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the path to the cert key file.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.tlsCertKey" -}}
|
||||
{{- if .Values.tls.autoGenerated -}}
|
||||
{{- printf "/opt/bitnami/postgresql/certs/tls.key" -}}
|
||||
{{- else -}}
|
||||
{{- required "Certificate Key filename is required when TLS in enabled" .Values.tls.certKeyFilename | printf "/opt/bitnami/postgresql/certs/%s" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the path to the CA cert file.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.tlsCACert" -}}
|
||||
{{- if .Values.tls.autoGenerated -}}
|
||||
{{- printf "/opt/bitnami/postgresql/certs/ca.crt" -}}
|
||||
{{- else -}}
|
||||
{{- printf "/opt/bitnami/postgresql/certs/%s" .Values.tls.certCAFilename -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the path to the CRL file.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.tlsCRL" -}}
|
||||
{{- if .Values.tls.crlFilename -}}
|
||||
{{- printf "/opt/bitnami/postgresql/certs/%s" .Values.tls.crlFilename -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return true if a TLS credentials secret object should be created
|
||||
*/}}
|
||||
{{- define "postgresql.v1.createTlsSecret" -}}
|
||||
{{- if and .Values.tls.autoGenerated (not .Values.tls.certificatesSecret) -}}
|
||||
{{- true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Return the path to the CA cert file.
|
||||
*/}}
|
||||
{{- define "postgresql.v1.tlsSecretName" -}}
|
||||
{{- if .Values.tls.autoGenerated -}}
|
||||
{{- printf "%s-crt" (include "common.names.fullname" .) -}}
|
||||
{{- else -}}
|
||||
{{ required "A secret containing TLS certificates is required when TLS is enabled" .Values.tls.certificatesSecret }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
114
charts/airflow/charts/postgresql/templates/backup/cronjob.yaml
Normal file
114
charts/airflow/charts/postgresql/templates/backup/cronjob.yaml
Normal file
@ -0,0 +1,114 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if .Values.backup.enabled }}
|
||||
{{- $customUser := include "postgresql.v1.username" . }}
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.primary.fullname" . }}-pgdumpall
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.labels .Values.commonLabels ) "context" . ) }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: pg_dumpall
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
{{- if $annotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
schedule: {{ quote .Values.backup.cronjob.schedule }}
|
||||
{{- if .Values.backup.cronjob.timezone }}
|
||||
timeZone: {{ .Values.backup.cronjob.timezone | quote }}
|
||||
{{- end }}
|
||||
concurrencyPolicy: {{ .Values.backup.cronjob.concurrencyPolicy }}
|
||||
failedJobsHistoryLimit: {{ .Values.backup.cronjob.failedJobsHistoryLimit }}
|
||||
successfulJobsHistoryLimit: {{ .Values.backup.cronjob.successfulJobsHistoryLimit }}
|
||||
{{- if .Values.backup.cronjob.startingDeadlineSeconds }}
|
||||
startingDeadlineSeconds: {{ .Values.backup.cronjob.startingDeadlineSeconds }}
|
||||
{{- end }}
|
||||
jobTemplate:
|
||||
spec:
|
||||
{{- if .Values.backup.cronjob.ttlSecondsAfterFinished }}
|
||||
ttlSecondsAfterFinished: {{ .Values.backup.cronjob.ttlSecondsAfterFinished }}
|
||||
{{- end }}
|
||||
template:
|
||||
metadata:
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 12 }}
|
||||
app.kubernetes.io/component: pg_dumpall
|
||||
{{- if $annotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- include "postgresql.v1.imagePullSecrets" . | nindent 10 }}
|
||||
{{- if .Values.backup.cronjob.nodeSelector }}
|
||||
nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.nodeSelector "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ include "postgresql.v1.primary.fullname" . }}-pgdumpall
|
||||
image: {{ include "postgresql.v1.image" . }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
|
||||
env:
|
||||
- name: PGUSER
|
||||
{{- if .Values.auth.enablePostgresUser }}
|
||||
value: postgres
|
||||
{{- else }}
|
||||
value: {{ $customUser | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: PGPASSFILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.adminPasswordKey" .) }}
|
||||
{{- else }}
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ include "postgresql.v1.adminPasswordKey" . }}
|
||||
{{- end }}
|
||||
- name: PGHOST
|
||||
value: {{ include "postgresql.v1.primary.fullname" . }}
|
||||
- name: PGPORT
|
||||
value: {{ include "postgresql.v1.service.port" . | quote }}
|
||||
- name: PGDUMP_DIR
|
||||
value: {{ .Values.backup.cronjob.storage.mountPath }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: PGSSLROOTCERT
|
||||
{{- if .Values.tls.autoGenerated -}}
|
||||
value: /tmp/certs/ca.crt
|
||||
{{- else }}
|
||||
value: {{- printf "/tmp/certs/%s" .Values.tls.certCAFilename -}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
command: {{- include "common.tplvalues.render" (dict "value" .Values.backup.cronjob.command "context" $) | nindent 14 }}
|
||||
volumeMounts:
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: certs
|
||||
mountPath: /certs
|
||||
{{- end }}
|
||||
- name: datadir
|
||||
mountPath: {{ .Values.backup.cronjob.storage.mountPath }}
|
||||
subPath: {{ .Values.backup.cronjob.storage.subPath }}
|
||||
{{- if .Values.backup.cronjob.containerSecurityContext.enabled }}
|
||||
securityContext: {{- omit .Values.backup.cronjob.containerSecurityContext "enabled" | toYaml | nindent 14 }}
|
||||
{{- end }}
|
||||
restartPolicy: {{ .Values.backup.cronjob.restartPolicy }}
|
||||
{{- if .Values.backup.cronjob.podSecurityContext.enabled }}
|
||||
securityContext:
|
||||
fsGroup: {{ .Values.backup.cronjob.podSecurityContext.fsGroup }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: raw-certificates
|
||||
emptyDir: /tmp/certs
|
||||
{{- end }}
|
||||
{{- if .Values.backup.cronjob.storage.existingClaim }}
|
||||
- name: datadir
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ printf "%s" (tpl .Values.backup.cronjob.storage.existingClaim .) }}
|
||||
{{- else }}
|
||||
- name: datadir
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ include "postgresql.v1.primary.fullname" . }}-pgdumpall
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
34
charts/airflow/charts/postgresql/templates/backup/pvc.yaml
Normal file
34
charts/airflow/charts/postgresql/templates/backup/pvc.yaml
Normal file
@ -0,0 +1,34 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.backup.enabled (not .Values.backup.cronjob.storage.existingClaim) -}}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.primary.fullname" . }}-pgdumpall
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.labels .Values.commonLabels ) "context" . ) }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: pg_dumpall
|
||||
{{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations .Values.backup.cronjob.storage.resourcePolicy }}
|
||||
annotations:
|
||||
{{- if or .Values.backup.cronjob.annotations .Values.commonAnnotations }}
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.backup.cronjob.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- if .Values.backup.cronjob.storage.resourcePolicy }}
|
||||
helm.sh/resource-policy: {{ .Values.backup.cronjob.storage.resourcePolicy | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
spec:
|
||||
accessModes:
|
||||
{{- range .Values.backup.cronjob.storage.accessModes }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.backup.cronjob.storage.size | quote }}
|
||||
{{ include "common.storage.class" (dict "persistence" .Values.backup.cronjob.storage "global" .Values.global) }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,9 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- range .Values.extraDeploy }}
|
||||
---
|
||||
{{ include "common.tplvalues.render" (dict "value" . "context" $) }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,34 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.networkPolicy.enabled (or .Values.networkPolicy.egressRules.denyConnectionsToExternal .Values.networkPolicy.egressRules.customRules) }}
|
||||
apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }}
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ printf "%s-egress" (include "common.names.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 6 }}
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
{{- if .Values.networkPolicy.egressRules.denyConnectionsToExternal }}
|
||||
- ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
- port: 53
|
||||
protocol: TCP
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
{{- end }}
|
||||
{{- if .Values.networkPolicy.egressRules.customRules }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.egressRules.customRules "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,26 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if (include "postgresql.v1.primary.createConfigmap" .) }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ printf "%s-configuration" (include "postgresql.v1.primary.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: primary
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
data:
|
||||
{{- if .Values.primary.configuration }}
|
||||
postgresql.conf: |
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.primary.configuration "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.pgHbaConfiguration }}
|
||||
pg_hba.conf: |
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.primary.pgHbaConfiguration "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,20 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if (include "postgresql.v1.primary.createExtendedConfigmap" .) }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ printf "%s-extended-configuration" (include "postgresql.v1.primary.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: primary
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
data:
|
||||
override.conf: |-
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.primary.extendedConfiguration "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,17 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.primary.initdb.scripts (not .Values.primary.initdb.scriptsConfigMap) }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ printf "%s-init-scripts" (include "postgresql.v1.primary.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
data: {{- include "common.tplvalues.render" (dict "value" .Values.primary.initdb.scripts "context" .) | nindent 2 }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,18 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.metrics.enabled .Values.metrics.customMetrics }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ printf "%s-metrics" (include "postgresql.v1.primary.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
data:
|
||||
custom-metrics.yaml: {{ toYaml .Values.metrics.customMetrics | quote }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,31 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if .Values.metrics.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ printf "%s-metrics" (include "postgresql.v1.primary.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: metrics
|
||||
{{- if or .Values.commonAnnotations .Values.metrics.service.annotations }}
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
sessionAffinity: {{ .Values.metrics.service.sessionAffinity }}
|
||||
{{- if .Values.metrics.service.clusterIP }}
|
||||
clusterIP: {{ .Values.metrics.service.clusterIP }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http-metrics
|
||||
port: {{ .Values.metrics.service.ports.metrics }}
|
||||
targetPort: http-metrics
|
||||
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: primary
|
||||
{{- end }}
|
||||
@ -0,0 +1,61 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.networkPolicy.enabled (or .Values.networkPolicy.metrics.enabled .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.enabled) }}
|
||||
apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }}
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ printf "%s-ingress" (include "postgresql.v1.primary.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: primary
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- $primaryPodLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
podSelector:
|
||||
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $primaryPodLabels "context" $ ) | nindent 6 }}
|
||||
app.kubernetes.io/component: primary
|
||||
ingress:
|
||||
{{- if and .Values.metrics.enabled .Values.networkPolicy.metrics.enabled (or .Values.networkPolicy.metrics.namespaceSelector .Values.networkPolicy.metrics.podSelector) }}
|
||||
- from:
|
||||
{{- if .Values.networkPolicy.metrics.namespaceSelector }}
|
||||
- namespaceSelector:
|
||||
matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.metrics.namespaceSelector "context" $) | nindent 14 }}
|
||||
{{- end }}
|
||||
{{- if .Values.networkPolicy.metrics.podSelector }}
|
||||
- podSelector:
|
||||
matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.metrics.podSelector "context" $) | nindent 14 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- port: {{ .Values.metrics.containerPorts.metrics }}
|
||||
{{- end }}
|
||||
{{- if and .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.enabled (or .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.namespaceSelector .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.podSelector) }}
|
||||
- from:
|
||||
{{- if .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.namespaceSelector }}
|
||||
- namespaceSelector:
|
||||
matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.namespaceSelector "context" $) | nindent 14 }}
|
||||
{{- end }}
|
||||
{{- if .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.podSelector }}
|
||||
- podSelector:
|
||||
matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.podSelector "context" $) | nindent 14 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- port: {{ .Values.containerPorts.postgresql }}
|
||||
{{- end }}
|
||||
{{- if and .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.enabled (eq .Values.architecture "replication") }}
|
||||
- from:
|
||||
{{- $readPodLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
- podSelector:
|
||||
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $readPodLabels "context" $ ) | nindent 14 }}
|
||||
app.kubernetes.io/component: read
|
||||
ports:
|
||||
- port: {{ .Values.containerPorts.postgresql }}
|
||||
{{- end }}
|
||||
{{- if .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.customRules }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.customRules "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,46 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.primary.fullname" . }}
|
||||
namespace: {{ default .Release.Namespace .Values.metrics.serviceMonitor.namespace | quote }}
|
||||
{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: metrics
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.metrics.serviceMonitor.jobLabel }}
|
||||
jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }}
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- $svcLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.selector .Values.commonLabels ) "context" . ) }}
|
||||
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $svcLabels "context" $ ) | nindent 6 }}
|
||||
app.kubernetes.io/component: metrics
|
||||
endpoints:
|
||||
- port: http-metrics
|
||||
{{- if .Values.metrics.serviceMonitor.interval }}
|
||||
interval: {{ .Values.metrics.serviceMonitor.interval }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.serviceMonitor.scrapeTimeout }}
|
||||
scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.serviceMonitor.relabelings }}
|
||||
relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.serviceMonitor.metricRelabelings }}
|
||||
metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.serviceMonitor.honorLabels }}
|
||||
honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }}
|
||||
{{- end }}
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- {{ .Release.Namespace | quote }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,661 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- $customUser := include "postgresql.v1.username" . }}
|
||||
apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }}
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.primary.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.labels .Values.commonLabels ) "context" . ) }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: primary
|
||||
{{- if or .Values.commonAnnotations .Values.primary.annotations }}
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
replicas: 1
|
||||
serviceName: {{ include "postgresql.v1.primary.svc.headless" . }}
|
||||
{{- if .Values.primary.updateStrategy }}
|
||||
updateStrategy: {{- toYaml .Values.primary.updateStrategy | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
selector:
|
||||
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }}
|
||||
app.kubernetes.io/component: primary
|
||||
template:
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.primary.fullname" . }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }}
|
||||
app.kubernetes.io/component: primary
|
||||
{{- if or (include "postgresql.v1.primary.createConfigmap" .) (include "postgresql.v1.primary.createExtendedConfigmap" .) .Values.primary.podAnnotations }}
|
||||
annotations:
|
||||
{{- if (include "postgresql.v1.primary.createConfigmap" .) }}
|
||||
checksum/configuration: {{ pick (include (print $.Template.BasePath "/primary/configmap.yaml") . | fromYaml) "data" | toYaml | sha256sum }}
|
||||
{{- end }}
|
||||
{{- if (include "postgresql.v1.primary.createExtendedConfigmap" .) }}
|
||||
checksum/extended-configuration: {{ pick (include (print $.Template.BasePath "/primary/extended-configmap.yaml") . | fromYaml) "data" | toYaml | sha256sum }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.podAnnotations }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.primary.podAnnotations "context" $ ) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.primary.extraPodSpec }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.primary.extraPodSpec "context" $) | nindent 6 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "postgresql.v1.serviceAccountName" . }}
|
||||
{{- include "postgresql.v1.imagePullSecrets" . | nindent 6 }}
|
||||
{{- if .Values.primary.hostAliases }}
|
||||
hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.primary.hostAliases "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.affinity }}
|
||||
affinity: {{- include "common.tplvalues.render" (dict "value" .Values.primary.affinity "context" $) | nindent 8 }}
|
||||
{{- else }}
|
||||
affinity:
|
||||
podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAffinityPreset "component" "primary" "customLabels" $podLabels "context" $) | nindent 10 }}
|
||||
podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAntiAffinityPreset "component" "primary" "customLabels" $podLabels "context" $) | nindent 10 }}
|
||||
nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.primary.nodeAffinityPreset.type "key" .Values.primary.nodeAffinityPreset.key "values" .Values.primary.nodeAffinityPreset.values) | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.nodeSelector }}
|
||||
nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.nodeSelector "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.tolerations }}
|
||||
tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.primary.tolerations "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.topologySpreadConstraints }}
|
||||
topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.primary.topologySpreadConstraints "context" .) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.priorityClassName }}
|
||||
priorityClassName: {{ .Values.primary.priorityClassName }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.schedulerName }}
|
||||
schedulerName: {{ .Values.primary.schedulerName | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.terminationGracePeriodSeconds }}
|
||||
terminationGracePeriodSeconds: {{ .Values.primary.terminationGracePeriodSeconds }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.podSecurityContext.enabled }}
|
||||
securityContext: {{- omit .Values.primary.podSecurityContext "enabled" | toYaml | nindent 8 }}
|
||||
{{- end }}
|
||||
hostNetwork: {{ .Values.primary.hostNetwork }}
|
||||
hostIPC: {{ .Values.primary.hostIPC }}
|
||||
{{- if or (and .Values.tls.enabled (not .Values.volumePermissions.enabled)) (and .Values.volumePermissions.enabled (or .Values.primary.persistence.enabled .Values.shmVolume.enabled)) .Values.primary.initContainers }}
|
||||
initContainers:
|
||||
{{- if and .Values.tls.enabled (not .Values.volumePermissions.enabled) }}
|
||||
- name: copy-certs
|
||||
image: {{ include "postgresql.v1.volumePermissions.image" . }}
|
||||
imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }}
|
||||
{{- if .Values.primary.resources }}
|
||||
resources: {{- toYaml .Values.primary.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
# We don't require a privileged container in this case
|
||||
{{- if .Values.primary.containerSecurityContext.enabled }}
|
||||
securityContext: {{- omit .Values.primary.containerSecurityContext "enabled" | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
command:
|
||||
- /bin/sh
|
||||
- -ec
|
||||
- |
|
||||
cp /tmp/certs/* /opt/bitnami/postgresql/certs/
|
||||
chmod 600 {{ include "postgresql.v1.tlsCertKey" . }}
|
||||
volumeMounts:
|
||||
- name: raw-certificates
|
||||
mountPath: /tmp/certs
|
||||
- name: postgresql-certificates
|
||||
mountPath: /opt/bitnami/postgresql/certs
|
||||
{{- else if and .Values.volumePermissions.enabled (or .Values.primary.persistence.enabled .Values.shmVolume.enabled) }}
|
||||
- name: init-chmod-data
|
||||
image: {{ include "postgresql.v1.volumePermissions.image" . }}
|
||||
imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }}
|
||||
{{- if .Values.volumePermissions.resources }}
|
||||
resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
command:
|
||||
- /bin/sh
|
||||
- -ec
|
||||
- |
|
||||
{{- if .Values.primary.persistence.enabled }}
|
||||
{{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }}
|
||||
chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.primary.persistence.mountPath }}
|
||||
{{- else }}
|
||||
chown {{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }} {{ .Values.primary.persistence.mountPath }}
|
||||
{{- end }}
|
||||
mkdir -p {{ .Values.primary.persistence.mountPath }}/data {{- if (include "postgresql.v1.mountConfigurationCM" .) }} {{ .Values.primary.persistence.mountPath }}/conf {{- end }}
|
||||
chmod 700 {{ .Values.primary.persistence.mountPath }}/data {{- if (include "postgresql.v1.mountConfigurationCM" .) }} {{ .Values.primary.persistence.mountPath }}/conf {{- end }}
|
||||
find {{ .Values.primary.persistence.mountPath }} -mindepth 1 -maxdepth 1 {{- if not (include "postgresql.v1.mountConfigurationCM" .) }} -not -name "conf" {{- end }} -not -name ".snapshot" -not -name "lost+found" | \
|
||||
{{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }}
|
||||
xargs -r chown -R `id -u`:`id -G | cut -d " " -f2`
|
||||
{{- else }}
|
||||
xargs -r chown -R {{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.shmVolume.enabled }}
|
||||
chmod -R 777 /dev/shm
|
||||
{{- end }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
cp /tmp/certs/* /opt/bitnami/postgresql/certs/
|
||||
{{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }}
|
||||
chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/
|
||||
{{- else }}
|
||||
chown -R {{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }} /opt/bitnami/postgresql/certs/
|
||||
{{- end }}
|
||||
chmod 600 {{ include "postgresql.v1.tlsCertKey" . }}
|
||||
{{- end }}
|
||||
{{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }}
|
||||
securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }}
|
||||
{{- else }}
|
||||
securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- if .Values.primary.persistence.enabled }}
|
||||
- name: data
|
||||
mountPath: {{ .Values.primary.persistence.mountPath }}
|
||||
{{- if .Values.primary.persistence.subPath }}
|
||||
subPath: {{ .Values.primary.persistence.subPath }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.shmVolume.enabled }}
|
||||
- name: dshm
|
||||
mountPath: /dev/shm
|
||||
{{- end }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: raw-certificates
|
||||
mountPath: /tmp/certs
|
||||
- name: postgresql-certificates
|
||||
mountPath: /opt/bitnami/postgresql/certs
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.initContainers }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.primary.initContainers "context" $ ) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: postgresql
|
||||
image: {{ include "postgresql.v1.image" . }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
|
||||
{{- if .Values.primary.containerSecurityContext.enabled }}
|
||||
securityContext: {{- omit .Values.primary.containerSecurityContext "enabled" | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.diagnosticMode.enabled }}
|
||||
command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }}
|
||||
{{- else if .Values.primary.command }}
|
||||
command: {{- include "common.tplvalues.render" (dict "value" .Values.primary.command "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.diagnosticMode.enabled }}
|
||||
args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }}
|
||||
{{- else if .Values.primary.args }}
|
||||
args: {{- include "common.tplvalues.render" (dict "value" .Values.primary.args "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
- name: BITNAMI_DEBUG
|
||||
value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }}
|
||||
- name: POSTGRESQL_PORT_NUMBER
|
||||
value: {{ .Values.containerPorts.postgresql | quote }}
|
||||
- name: POSTGRESQL_VOLUME_DIR
|
||||
value: {{ .Values.primary.persistence.mountPath | quote }}
|
||||
{{- if .Values.primary.persistence.mountPath }}
|
||||
- name: PGDATA
|
||||
value: {{ .Values.postgresqlDataDir | quote }}
|
||||
{{- end }}
|
||||
# Authentication
|
||||
{{- if or (eq $customUser "postgres") (empty $customUser) }}
|
||||
{{- if .Values.auth.enablePostgresUser }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: POSTGRES_PASSWORD_FILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.adminPasswordKey" .) }}
|
||||
{{- else }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ include "postgresql.v1.adminPasswordKey" . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
- name: ALLOW_EMPTY_PASSWORD
|
||||
value: "true"
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
- name: POSTGRES_USER
|
||||
value: {{ $customUser | quote }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: POSTGRES_PASSWORD_FILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.userPasswordKey" .) }}
|
||||
{{- else }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ include "postgresql.v1.userPasswordKey" . }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth.enablePostgresUser }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: POSTGRES_POSTGRES_PASSWORD_FILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.adminPasswordKey" .) }}
|
||||
{{- else }}
|
||||
- name: POSTGRES_POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ include "postgresql.v1.adminPasswordKey" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if (include "postgresql.v1.database" .) }}
|
||||
- name: POSTGRES_DATABASE
|
||||
value: {{ (include "postgresql.v1.database" .) | quote }}
|
||||
{{- end }}
|
||||
# Replication
|
||||
{{- if or (eq .Values.architecture "replication") .Values.primary.standby.enabled }}
|
||||
- name: POSTGRES_REPLICATION_MODE
|
||||
value: {{ ternary "slave" "master" .Values.primary.standby.enabled | quote }}
|
||||
- name: POSTGRES_REPLICATION_USER
|
||||
value: {{ .Values.auth.replicationUsername | quote }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: POSTGRES_REPLICATION_PASSWORD_FILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.replicationPasswordKey" .) }}
|
||||
{{- else }}
|
||||
- name: POSTGRES_REPLICATION_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ include "postgresql.v1.replicationPasswordKey" . }}
|
||||
{{- end }}
|
||||
{{- if ne .Values.replication.synchronousCommit "off" }}
|
||||
- name: POSTGRES_SYNCHRONOUS_COMMIT_MODE
|
||||
value: {{ .Values.replication.synchronousCommit | quote }}
|
||||
- name: POSTGRES_NUM_SYNCHRONOUS_REPLICAS
|
||||
value: {{ .Values.replication.numSynchronousReplicas | quote }}
|
||||
{{- end }}
|
||||
- name: POSTGRES_CLUSTER_APP_NAME
|
||||
value: {{ .Values.replication.applicationName }}
|
||||
{{- end }}
|
||||
# Initdb
|
||||
{{- if .Values.primary.initdb.args }}
|
||||
- name: POSTGRES_INITDB_ARGS
|
||||
value: {{ .Values.primary.initdb.args | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.initdb.postgresqlWalDir }}
|
||||
- name: POSTGRES_INITDB_WALDIR
|
||||
value: {{ .Values.primary.initdb.postgresqlWalDir | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.initdb.user }}
|
||||
- name: POSTGRES_INITSCRIPTS_USERNAME
|
||||
value: {{ .Values.primary.initdb.user }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.initdb.password }}
|
||||
- name: POSTGRES_INITSCRIPTS_PASSWORD
|
||||
value: {{ .Values.primary.initdb.password | quote }}
|
||||
{{- end }}
|
||||
# Standby
|
||||
{{- if .Values.primary.standby.enabled }}
|
||||
- name: POSTGRES_MASTER_HOST
|
||||
value: {{ .Values.primary.standby.primaryHost }}
|
||||
- name: POSTGRES_MASTER_PORT_NUMBER
|
||||
value: {{ .Values.primary.standby.primaryPort | quote }}
|
||||
{{- end }}
|
||||
# LDAP
|
||||
- name: POSTGRESQL_ENABLE_LDAP
|
||||
value: {{ ternary "yes" "no" .Values.ldap.enabled | quote }}
|
||||
{{- if .Values.ldap.enabled }}
|
||||
{{- if or .Values.ldap.url .Values.ldap.uri }}
|
||||
- name: POSTGRESQL_LDAP_URL
|
||||
value: {{ coalesce .Values.ldap.url .Values.ldap.uri }}
|
||||
{{- else }}
|
||||
- name: POSTGRESQL_LDAP_SERVER
|
||||
value: {{ .Values.ldap.server }}
|
||||
- name: POSTGRESQL_LDAP_PORT
|
||||
value: {{ .Values.ldap.port | quote }}
|
||||
- name: POSTGRESQL_LDAP_SCHEME
|
||||
value: {{ .Values.ldap.scheme }}
|
||||
{{- if (include "postgresql.v1.ldap.tls.enabled" .) }}
|
||||
- name: POSTGRESQL_LDAP_TLS
|
||||
value: "1"
|
||||
{{- end }}
|
||||
- name: POSTGRESQL_LDAP_PREFIX
|
||||
value: {{ .Values.ldap.prefix | quote }}
|
||||
- name: POSTGRESQL_LDAP_SUFFIX
|
||||
value: {{ .Values.ldap.suffix | quote }}
|
||||
- name: POSTGRESQL_LDAP_BASE_DN
|
||||
value: {{ coalesce .Values.ldap.baseDN .Values.ldap.basedn }}
|
||||
- name: POSTGRESQL_LDAP_BIND_DN
|
||||
value: {{ coalesce .Values.ldap.bindDN .Values.ldap.binddn}}
|
||||
{{- if or (not (empty .Values.ldap.bind_password)) (not (empty .Values.ldap.bindpw)) }}
|
||||
- name: POSTGRESQL_LDAP_BIND_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: ldap-password
|
||||
{{- end }}
|
||||
- name: POSTGRESQL_LDAP_SEARCH_ATTR
|
||||
value: {{ coalesce .Values.ldap.search_attr .Values.ldap.searchAttribute }}
|
||||
- name: POSTGRESQL_LDAP_SEARCH_FILTER
|
||||
value: {{ coalesce .Values.ldap.search_filter .Values.ldap.searchFilter }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
# TLS
|
||||
- name: POSTGRESQL_ENABLE_TLS
|
||||
value: {{ ternary "yes" "no" .Values.tls.enabled | quote }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS
|
||||
value: {{ ternary "yes" "no" .Values.tls.preferServerCiphers | quote }}
|
||||
- name: POSTGRESQL_TLS_CERT_FILE
|
||||
value: {{ include "postgresql.v1.tlsCert" . }}
|
||||
- name: POSTGRESQL_TLS_KEY_FILE
|
||||
value: {{ include "postgresql.v1.tlsCertKey" . }}
|
||||
{{- if .Values.tls.certCAFilename }}
|
||||
- name: POSTGRESQL_TLS_CA_FILE
|
||||
value: {{ include "postgresql.v1.tlsCACert" . }}
|
||||
{{- end }}
|
||||
{{- if .Values.tls.crlFilename }}
|
||||
- name: POSTGRESQL_TLS_CRL_FILE
|
||||
value: {{ include "postgresql.v1.tlsCRL" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
# Audit
|
||||
- name: POSTGRESQL_LOG_HOSTNAME
|
||||
value: {{ .Values.audit.logHostname | quote }}
|
||||
- name: POSTGRESQL_LOG_CONNECTIONS
|
||||
value: {{ .Values.audit.logConnections | quote }}
|
||||
- name: POSTGRESQL_LOG_DISCONNECTIONS
|
||||
value: {{ .Values.audit.logDisconnections | quote }}
|
||||
{{- if .Values.audit.logLinePrefix }}
|
||||
- name: POSTGRESQL_LOG_LINE_PREFIX
|
||||
value: {{ .Values.audit.logLinePrefix | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.audit.logTimezone }}
|
||||
- name: POSTGRESQL_LOG_TIMEZONE
|
||||
value: {{ .Values.audit.logTimezone | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.audit.pgAuditLog }}
|
||||
- name: POSTGRESQL_PGAUDIT_LOG
|
||||
value: {{ .Values.audit.pgAuditLog | quote }}
|
||||
{{- end }}
|
||||
- name: POSTGRESQL_PGAUDIT_LOG_CATALOG
|
||||
value: {{ .Values.audit.pgAuditLogCatalog | quote }}
|
||||
# Others
|
||||
- name: POSTGRESQL_CLIENT_MIN_MESSAGES
|
||||
value: {{ .Values.audit.clientMinMessages | quote }}
|
||||
- name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES
|
||||
value: {{ .Values.postgresqlSharedPreloadLibraries | quote }}
|
||||
{{- if .Values.primary.extraEnvVars }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.primary.extraEnvVars "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.primary.extraEnvVarsCM .Values.primary.extraEnvVarsSecret }}
|
||||
envFrom:
|
||||
{{- if .Values.primary.extraEnvVarsCM }}
|
||||
- configMapRef:
|
||||
name: {{ .Values.primary.extraEnvVarsCM }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.extraEnvVarsSecret }}
|
||||
- secretRef:
|
||||
name: {{ .Values.primary.extraEnvVarsSecret }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: tcp-postgresql
|
||||
containerPort: {{ .Values.containerPorts.postgresql }}
|
||||
{{- if not .Values.diagnosticMode.enabled }}
|
||||
{{- if .Values.primary.customStartupProbe }}
|
||||
startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customStartupProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.primary.startupProbe.enabled }}
|
||||
startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.startupProbe "enabled") "context" $) | nindent 12 }}
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
{{- if (include "postgresql.v1.database" .) }}
|
||||
- exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.v1.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }}
|
||||
{{- else }}
|
||||
- exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.customLivenessProbe }}
|
||||
livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customLivenessProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.primary.livenessProbe.enabled }}
|
||||
livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.livenessProbe "enabled") "context" $) | nindent 12 }}
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
{{- if (include "postgresql.v1.database" .) }}
|
||||
- exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.v1.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }}
|
||||
{{- else }}
|
||||
- exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.customReadinessProbe }}
|
||||
readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customReadinessProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.primary.readinessProbe.enabled }}
|
||||
readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.readinessProbe "enabled") "context" $) | nindent 12 }}
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- -e
|
||||
{{- include "postgresql.v1.readinessProbeCommand" . | nindent 16 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.resources }}
|
||||
resources: {{- toYaml .Values.primary.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.lifecycleHooks }}
|
||||
lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.primary.lifecycleHooks "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- if or .Values.primary.initdb.scriptsConfigMap .Values.primary.initdb.scripts }}
|
||||
- name: custom-init-scripts
|
||||
mountPath: /docker-entrypoint-initdb.d/
|
||||
{{- end }}
|
||||
{{- if .Values.primary.initdb.scriptsSecret }}
|
||||
- name: custom-init-scripts-secret
|
||||
mountPath: /docker-entrypoint-initdb.d/secret
|
||||
{{- end }}
|
||||
{{- if or .Values.primary.extendedConfiguration .Values.primary.existingExtendedConfigmap }}
|
||||
- name: postgresql-extended-config
|
||||
mountPath: {{ .Values.primary.persistence.mountPath }}/conf/conf.d/
|
||||
{{- end }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: postgresql-password
|
||||
mountPath: /opt/bitnami/postgresql/secrets/
|
||||
{{- end }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: postgresql-certificates
|
||||
mountPath: /opt/bitnami/postgresql/certs
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{- if .Values.shmVolume.enabled }}
|
||||
- name: dshm
|
||||
mountPath: /dev/shm
|
||||
{{- end }}
|
||||
{{- if .Values.primary.persistence.enabled }}
|
||||
- name: data
|
||||
mountPath: {{ .Values.primary.persistence.mountPath }}
|
||||
{{- if .Values.primary.persistence.subPath }}
|
||||
subPath: {{ .Values.primary.persistence.subPath }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if or .Values.primary.configuration .Values.primary.pgHbaConfiguration .Values.primary.existingConfigmap }}
|
||||
- name: postgresql-config
|
||||
mountPath: {{ .Values.primary.persistence.mountPath }}/conf
|
||||
{{- end }}
|
||||
{{- if .Values.primary.extraVolumeMounts }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.primary.extraVolumeMounts "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.enabled }}
|
||||
- name: metrics
|
||||
image: {{ include "postgresql.v1.metrics.image" . }}
|
||||
imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }}
|
||||
{{- if .Values.metrics.containerSecurityContext.enabled }}
|
||||
securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.diagnosticMode.enabled }}
|
||||
command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }}
|
||||
args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }}
|
||||
{{- else if or .Values.metrics.customMetrics .Values.metrics.collectors }}
|
||||
args:
|
||||
{{- if .Values.metrics.customMetrics }}
|
||||
- --extend.query-path
|
||||
- /conf/custom-metrics.yaml
|
||||
{{- end }}
|
||||
{{- range $name, $enabled := .Values.metrics.collectors }}
|
||||
- --{{ if not $enabled }}no-{{ end }}collector.{{ $name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- $database := required "In order to enable metrics you need to specify a database (.Values.auth.database or .Values.global.postgresql.auth.database)" (include "postgresql.v1.database" .) }}
|
||||
- name: DATA_SOURCE_URI
|
||||
value: {{ printf "127.0.0.1:%d/%s?sslmode=disable" (int (include "postgresql.v1.service.port" .)) $database }}
|
||||
{{- $pwdKey := ternary (include "postgresql.v1.adminPasswordKey" .) (include "postgresql.v1.userPasswordKey" .) (or (eq $customUser "postgres") (empty $customUser)) }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: DATA_SOURCE_PASS_FILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" $pwdKey }}
|
||||
{{- else }}
|
||||
- name: DATA_SOURCE_PASS
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ $pwdKey }}
|
||||
{{- end }}
|
||||
- name: DATA_SOURCE_USER
|
||||
value: {{ default "postgres" $customUser | quote }}
|
||||
{{- if .Values.metrics.extraEnvVars }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http-metrics
|
||||
containerPort: {{ .Values.metrics.containerPorts.metrics }}
|
||||
{{- if not .Values.diagnosticMode.enabled }}
|
||||
{{- if .Values.metrics.customStartupProbe }}
|
||||
startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.metrics.startupProbe.enabled }}
|
||||
startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }}
|
||||
tcpSocket:
|
||||
port: http-metrics
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.customLivenessProbe }}
|
||||
livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.metrics.livenessProbe.enabled }}
|
||||
livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }}
|
||||
httpGet:
|
||||
path: /
|
||||
port: http-metrics
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.customReadinessProbe }}
|
||||
readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.metrics.readinessProbe.enabled }}
|
||||
readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }}
|
||||
httpGet:
|
||||
path: /
|
||||
port: http-metrics
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: postgresql-password
|
||||
mountPath: /opt/bitnami/postgresql/secrets/
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.customMetrics }}
|
||||
- name: custom-metrics
|
||||
mountPath: /conf
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.resources }}
|
||||
resources: {{- toYaml .Values.metrics.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.sidecars }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.primary.sidecars "context" $ ) | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
{{- if or .Values.primary.configuration .Values.primary.pgHbaConfiguration .Values.primary.existingConfigmap }}
|
||||
- name: postgresql-config
|
||||
configMap:
|
||||
name: {{ include "postgresql.v1.primary.configmapName" . }}
|
||||
{{- end }}
|
||||
{{- if or .Values.primary.extendedConfiguration .Values.primary.existingExtendedConfigmap }}
|
||||
- name: postgresql-extended-config
|
||||
configMap:
|
||||
name: {{ include "postgresql.v1.primary.extendedConfigmapName" . }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: postgresql-password
|
||||
secret:
|
||||
secretName: {{ include "postgresql.v1.secretName" . }}
|
||||
{{- end }}
|
||||
{{- if or .Values.primary.initdb.scriptsConfigMap .Values.primary.initdb.scripts }}
|
||||
- name: custom-init-scripts
|
||||
configMap:
|
||||
name: {{ include "postgresql.v1.initdb.scriptsCM" . }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.initdb.scriptsSecret }}
|
||||
- name: custom-init-scripts-secret
|
||||
secret:
|
||||
secretName: {{ tpl .Values.primary.initdb.scriptsSecret $ }}
|
||||
{{- end }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: raw-certificates
|
||||
secret:
|
||||
secretName: {{ include "postgresql.v1.tlsSecretName" . }}
|
||||
- name: postgresql-certificates
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.extraVolumes }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.primary.extraVolumes "context" $ ) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if and .Values.metrics.enabled .Values.metrics.customMetrics }}
|
||||
- name: custom-metrics
|
||||
configMap:
|
||||
name: {{ printf "%s-metrics" (include "postgresql.v1.primary.fullname" .) }}
|
||||
{{- end }}
|
||||
{{- if .Values.shmVolume.enabled }}
|
||||
- name: dshm
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
{{- if .Values.shmVolume.sizeLimit }}
|
||||
sizeLimit: {{ .Values.shmVolume.sizeLimit }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if and .Values.primary.persistence.enabled .Values.primary.persistence.existingClaim }}
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ tpl .Values.primary.persistence.existingClaim $ }}
|
||||
{{- else if not .Values.primary.persistence.enabled }}
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
{{- else }}
|
||||
{{- if .Values.primary.persistentVolumeClaimRetentionPolicy.enabled }}
|
||||
persistentVolumeClaimRetentionPolicy:
|
||||
whenDeleted: {{ .Values.primary.persistentVolumeClaimRetentionPolicy.whenDeleted }}
|
||||
whenScaled: {{ .Values.primary.persistentVolumeClaimRetentionPolicy.whenScaled }}
|
||||
{{- end }}
|
||||
volumeClaimTemplates:
|
||||
- apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: data
|
||||
{{- if .Values.primary.persistence.annotations }}
|
||||
annotations: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.annotations "context" $) | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.persistence.labels }}
|
||||
labels: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.labels "context" $) | nindent 10 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
accessModes:
|
||||
{{- range .Values.primary.persistence.accessModes }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.persistence.dataSource }}
|
||||
dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.dataSource "context" $) | nindent 10 }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.primary.persistence.size | quote }}
|
||||
{{- if .Values.primary.persistence.selector }}
|
||||
selector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.selector "context" $) | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- include "common.storage.class" (dict "persistence" .Values.primary.persistence "global" .Values.global) | nindent 8 }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,36 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.primary.svc.headless" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: primary
|
||||
annotations:
|
||||
{{- if or .Values.primary.service.headless.annotations .Values.commonAnnotations }}
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.service.headless.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
# Use this annotation in addition to the actual publishNotReadyAddresses
|
||||
# field below because the annotation will stop being respected soon but the
|
||||
# field is broken in some versions of Kubernetes:
|
||||
# https://github.com/kubernetes/kubernetes/issues/58662
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
spec:
|
||||
type: ClusterIP
|
||||
clusterIP: None
|
||||
# We want all pods in the StatefulSet to have their addresses published for
|
||||
# the sake of the other Postgresql pods even before they're ready, since they
|
||||
# have to be able to talk to each other in order to become ready.
|
||||
publishNotReadyAddresses: true
|
||||
ports:
|
||||
- name: tcp-postgresql
|
||||
port: {{ template "postgresql.v1.service.port" . }}
|
||||
targetPort: tcp-postgresql
|
||||
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: primary
|
||||
51
charts/airflow/charts/postgresql/templates/primary/svc.yaml
Normal file
51
charts/airflow/charts/postgresql/templates/primary/svc.yaml
Normal file
@ -0,0 +1,51 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.primary.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: primary
|
||||
{{- if or .Values.commonAnnotations .Values.primary.service.annotations }}
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.service.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: {{ .Values.primary.service.type }}
|
||||
{{- if or (eq .Values.primary.service.type "LoadBalancer") (eq .Values.primary.service.type "NodePort") }}
|
||||
externalTrafficPolicy: {{ .Values.primary.service.externalTrafficPolicy | quote }}
|
||||
{{- end }}
|
||||
{{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerSourceRanges)) }}
|
||||
loadBalancerSourceRanges: {{ .Values.primary.service.loadBalancerSourceRanges | toJson}}
|
||||
{{- end }}
|
||||
{{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerIP)) }}
|
||||
loadBalancerIP: {{ .Values.primary.service.loadBalancerIP }}
|
||||
{{- end }}
|
||||
{{- if and .Values.primary.service.clusterIP (eq .Values.primary.service.type "ClusterIP") }}
|
||||
clusterIP: {{ .Values.primary.service.clusterIP }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.service.sessionAffinity }}
|
||||
sessionAffinity: {{ .Values.primary.service.sessionAffinity }}
|
||||
{{- end }}
|
||||
{{- if .Values.primary.service.sessionAffinityConfig }}
|
||||
sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.sessionAffinityConfig "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: tcp-postgresql
|
||||
port: {{ template "postgresql.v1.service.port" . }}
|
||||
targetPort: tcp-postgresql
|
||||
{{- if and (or (eq .Values.primary.service.type "NodePort") (eq .Values.primary.service.type "LoadBalancer")) (not (empty .Values.primary.service.nodePorts.postgresql)) }}
|
||||
nodePort: {{ .Values.primary.service.nodePorts.postgresql }}
|
||||
{{- else if eq .Values.primary.service.type "ClusterIP" }}
|
||||
nodePort: null
|
||||
{{- end }}
|
||||
{{- if .Values.primary.service.extraPorts }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.primary.service.extraPorts "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.primary.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: primary
|
||||
@ -0,0 +1,22 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: PrometheusRule
|
||||
metadata:
|
||||
name: {{ include "common.names.fullname" . }}
|
||||
namespace: {{ default .Release.Namespace .Values.metrics.prometheusRule.namespace | quote }}
|
||||
{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.prometheusRule.labels .Values.commonLabels ) "context" . ) }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: metrics
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
groups:
|
||||
- name: {{ include "common.names.fullname" . }}
|
||||
rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 8 }}
|
||||
{{- end }}
|
||||
42
charts/airflow/charts/postgresql/templates/psp.yaml
Normal file
42
charts/airflow/charts/postgresql/templates/psp.yaml
Normal file
@ -0,0 +1,42 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and (include "common.capabilities.psp.supported" .) .Values.psp.create }}
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodSecurityPolicy
|
||||
metadata:
|
||||
name: {{ include "common.names.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
privileged: false
|
||||
volumes:
|
||||
- 'configMap'
|
||||
- 'secret'
|
||||
- 'persistentVolumeClaim'
|
||||
- 'emptyDir'
|
||||
- 'projected'
|
||||
hostNetwork: false
|
||||
hostIPC: false
|
||||
hostPID: false
|
||||
runAsUser:
|
||||
rule: 'RunAsAny'
|
||||
seLinux:
|
||||
rule: 'RunAsAny'
|
||||
supplementalGroups:
|
||||
rule: 'MustRunAs'
|
||||
ranges:
|
||||
- min: 1
|
||||
max: 65535
|
||||
fsGroup:
|
||||
rule: 'MustRunAs'
|
||||
ranges:
|
||||
- min: 1
|
||||
max: 65535
|
||||
readOnlyRootFilesystem: false
|
||||
{{- end }}
|
||||
@ -0,0 +1,20 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if (include "postgresql.v1.readReplicas.createExtendedConfigmap" .) }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ printf "%s-extended-configuration" (include "postgresql.v1.readReplica.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: read
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
data:
|
||||
override.conf: |-
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.extendedConfiguration "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,18 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.metrics.enabled .Values.metrics.customMetrics (eq .Values.architecture "replication") }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ printf "%s-metrics" (include "postgresql.v1.readReplica.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
data:
|
||||
custom-metrics.yaml: {{ toYaml .Values.metrics.customMetrics | quote }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,31 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.metrics.enabled (eq .Values.architecture "replication") }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ printf "%s-metrics" (include "postgresql.v1.readReplica.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: metrics-read
|
||||
{{- if or .Values.commonAnnotations .Values.metrics.service.annotations }}
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.service.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
sessionAffinity: {{ .Values.metrics.service.sessionAffinity }}
|
||||
{{- if .Values.metrics.service.clusterIP }}
|
||||
clusterIP: {{ .Values.metrics.service.clusterIP }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http-metrics
|
||||
port: {{ .Values.metrics.service.ports.metrics }}
|
||||
targetPort: http-metrics
|
||||
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: read
|
||||
{{- end }}
|
||||
@ -0,0 +1,39 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.networkPolicy.enabled (eq .Values.architecture "replication") .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.enabled }}
|
||||
apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }}
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ printf "%s-ingress" (include "postgresql.v1.readReplica.fullname" .) }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: read
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
podSelector:
|
||||
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }}
|
||||
app.kubernetes.io/component: read
|
||||
ingress:
|
||||
{{- if and .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.enabled (or .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.namespaceSelector .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.podSelector) }}
|
||||
- from:
|
||||
{{- if .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.namespaceSelector }}
|
||||
- namespaceSelector:
|
||||
matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.namespaceSelector "context" $) | nindent 14 }}
|
||||
{{- end }}
|
||||
{{- if .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.podSelector }}
|
||||
- podSelector:
|
||||
matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.podSelector "context" $) | nindent 14 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- port: {{ .Values.containerPorts.postgresql }}
|
||||
{{- end }}
|
||||
{{- if .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.customRules }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.customRules "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,46 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled (eq .Values.architecture "replication") }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.readReplica.fullname" . }}
|
||||
namespace: {{ default .Release.Namespace .Values.metrics.serviceMonitor.namespace | quote }}
|
||||
{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.labels .Values.commonLabels ) "context" . ) }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: metrics-read
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.metrics.serviceMonitor.jobLabel }}
|
||||
jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }}
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- $svcLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.metrics.serviceMonitor.selector .Values.commonLabels ) "context" . ) }}
|
||||
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $svcLabels "context" $ ) | nindent 6 }}
|
||||
app.kubernetes.io/component: metrics-read
|
||||
endpoints:
|
||||
- port: http-metrics
|
||||
{{- if .Values.metrics.serviceMonitor.interval }}
|
||||
interval: {{ .Values.metrics.serviceMonitor.interval }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.serviceMonitor.scrapeTimeout }}
|
||||
scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.serviceMonitor.relabelings }}
|
||||
relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.serviceMonitor.metricRelabelings }}
|
||||
metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.serviceMonitor.honorLabels }}
|
||||
honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }}
|
||||
{{- end }}
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- {{ .Release.Namespace | quote }}
|
||||
{{- end }}
|
||||
552
charts/airflow/charts/postgresql/templates/read/statefulset.yaml
Normal file
552
charts/airflow/charts/postgresql/templates/read/statefulset.yaml
Normal file
@ -0,0 +1,552 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if eq .Values.architecture "replication" }}
|
||||
{{- $customUser := include "postgresql.v1.username" . }}
|
||||
apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }}
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.readReplica.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
{{- $labels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.labels .Values.commonLabels ) "context" . ) }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" $labels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: read
|
||||
{{- if or .Values.commonAnnotations .Values.readReplicas.annotations }}
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
replicas: {{ .Values.readReplicas.replicaCount }}
|
||||
serviceName: {{ include "postgresql.v1.readReplica.svc.headless" . }}
|
||||
{{- if .Values.readReplicas.updateStrategy }}
|
||||
updateStrategy: {{- toYaml .Values.readReplicas.updateStrategy | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
selector:
|
||||
matchLabels: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 6 }}
|
||||
app.kubernetes.io/component: read
|
||||
template:
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.readReplica.fullname" . }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" $podLabels "context" $ ) | nindent 8 }}
|
||||
app.kubernetes.io/component: read
|
||||
{{- if or (include "postgresql.v1.readReplicas.createExtendedConfigmap" .) .Values.readReplicas.podAnnotations }}
|
||||
annotations:
|
||||
{{- if (include "postgresql.v1.readReplicas.createExtendedConfigmap" .) }}
|
||||
checksum/extended-configuration: {{ pick (include (print $.Template.BasePath "/primary/extended-configmap.yaml") . | fromYaml) "data" | toYaml | sha256sum }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.podAnnotations }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.podAnnotations "context" $ ) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.readReplicas.extraPodSpec }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.extraPodSpec "context" $) | nindent 6 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "postgresql.v1.serviceAccountName" . }}
|
||||
{{- include "postgresql.v1.imagePullSecrets" . | nindent 6 }}
|
||||
{{- if .Values.readReplicas.hostAliases }}
|
||||
hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.hostAliases "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.affinity }}
|
||||
affinity: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.affinity "context" $) | nindent 8 }}
|
||||
{{- else }}
|
||||
affinity:
|
||||
podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.readReplicas.podAffinityPreset "component" "read" "customLabels" $podLabels "context" $) | nindent 10 }}
|
||||
podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.readReplicas.podAntiAffinityPreset "component" "read" "customLabels" $podLabels "context" $) | nindent 10 }}
|
||||
nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.readReplicas.nodeAffinityPreset.type "key" .Values.readReplicas.nodeAffinityPreset.key "values" .Values.readReplicas.nodeAffinityPreset.values) | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.nodeSelector }}
|
||||
nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.nodeSelector "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.tolerations }}
|
||||
tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.tolerations "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.topologySpreadConstraints }}
|
||||
topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.topologySpreadConstraints "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.priorityClassName }}
|
||||
priorityClassName: {{ .Values.readReplicas.priorityClassName }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.schedulerName }}
|
||||
schedulerName: {{ .Values.readReplicas.schedulerName | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.terminationGracePeriodSeconds }}
|
||||
terminationGracePeriodSeconds: {{ .Values.readReplicas.terminationGracePeriodSeconds }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.podSecurityContext.enabled }}
|
||||
securityContext: {{- omit .Values.readReplicas.podSecurityContext "enabled" | toYaml | nindent 8 }}
|
||||
{{- end }}
|
||||
hostNetwork: {{ .Values.readReplicas.hostNetwork }}
|
||||
hostIPC: {{ .Values.readReplicas.hostIPC }}
|
||||
{{- if or (and .Values.tls.enabled (not .Values.volumePermissions.enabled)) (and .Values.volumePermissions.enabled (or .Values.readReplicas.persistence.enabled .Values.shmVolume.enabled)) .Values.readReplicas.initContainers }}
|
||||
initContainers:
|
||||
{{- if and .Values.tls.enabled (not .Values.volumePermissions.enabled) }}
|
||||
- name: copy-certs
|
||||
image: {{ include "postgresql.v1.volumePermissions.image" . }}
|
||||
imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }}
|
||||
{{- if .Values.readReplicas.resources }}
|
||||
resources: {{- toYaml .Values.readReplicas.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
# We don't require a privileged container in this case
|
||||
{{- if .Values.readReplicas.containerSecurityContext.enabled }}
|
||||
securityContext: {{- omit .Values.readReplicas.containerSecurityContext "enabled" | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
command:
|
||||
- /bin/sh
|
||||
- -ec
|
||||
- |
|
||||
cp /tmp/certs/* /opt/bitnami/postgresql/certs/
|
||||
chmod 600 {{ include "postgresql.v1.tlsCertKey" . }}
|
||||
volumeMounts:
|
||||
- name: raw-certificates
|
||||
mountPath: /tmp/certs
|
||||
- name: postgresql-certificates
|
||||
mountPath: /opt/bitnami/postgresql/certs
|
||||
{{- else if and .Values.volumePermissions.enabled (or .Values.readReplicas.persistence.enabled .Values.shmVolume.enabled) }}
|
||||
- name: init-chmod-data
|
||||
image: {{ include "postgresql.v1.volumePermissions.image" . }}
|
||||
imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }}
|
||||
{{- if .Values.readReplicas.resources }}
|
||||
resources: {{- toYaml .Values.readReplicas.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
command:
|
||||
- /bin/sh
|
||||
- -ec
|
||||
- |
|
||||
{{- if .Values.readReplicas.persistence.enabled }}
|
||||
{{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }}
|
||||
chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.readReplicas.persistence.mountPath }}
|
||||
{{- else }}
|
||||
chown {{ .Values.readReplicas.containerSecurityContext.runAsUser }}:{{ .Values.readReplicas.podSecurityContext.fsGroup }} {{ .Values.readReplicas.persistence.mountPath }}
|
||||
{{- end }}
|
||||
mkdir -p {{ .Values.readReplicas.persistence.mountPath }}/data {{- if (include "postgresql.v1.mountConfigurationCM" .) }} {{ .Values.readReplicas.persistence.mountPath }}/conf {{- end }}
|
||||
chmod 700 {{ .Values.readReplicas.persistence.mountPath }}/data {{- if (include "postgresql.v1.mountConfigurationCM" .) }} {{ .Values.readReplicas.persistence.mountPath }}/conf {{- end }}
|
||||
find {{ .Values.readReplicas.persistence.mountPath }} -mindepth 1 -maxdepth 1 {{- if not (include "postgresql.v1.mountConfigurationCM" .) }} -not -name "conf" {{- end }} -not -name ".snapshot" -not -name "lost+found" | \
|
||||
{{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }}
|
||||
xargs -r chown -R `id -u`:`id -G | cut -d " " -f2`
|
||||
{{- else }}
|
||||
xargs -r chown -R {{ .Values.readReplicas.containerSecurityContext.runAsUser }}:{{ .Values.readReplicas.podSecurityContext.fsGroup }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.shmVolume.enabled }}
|
||||
chmod -R 777 /dev/shm
|
||||
{{- end }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
cp /tmp/certs/* /opt/bitnami/postgresql/certs/
|
||||
{{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }}
|
||||
chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/
|
||||
{{- else }}
|
||||
chown -R {{ .Values.readReplicas.containerSecurityContext.runAsUser }}:{{ .Values.readReplicas.podSecurityContext.fsGroup }} /opt/bitnami/postgresql/certs/
|
||||
{{- end }}
|
||||
chmod 600 {{ include "postgresql.v1.tlsCertKey" . }}
|
||||
{{- end }}
|
||||
{{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }}
|
||||
securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }}
|
||||
{{- else }}
|
||||
securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{ if .Values.readReplicas.persistence.enabled }}
|
||||
- name: data
|
||||
mountPath: {{ .Values.readReplicas.persistence.mountPath }}
|
||||
{{- if .Values.readReplicas.persistence.subPath }}
|
||||
subPath: {{ .Values.readReplicas.persistence.subPath }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.shmVolume.enabled }}
|
||||
- name: dshm
|
||||
mountPath: /dev/shm
|
||||
{{- end }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: raw-certificates
|
||||
mountPath: /tmp/certs
|
||||
- name: postgresql-certificates
|
||||
mountPath: /opt/bitnami/postgresql/certs
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.initContainers }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.initContainers "context" $ ) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: postgresql
|
||||
image: {{ include "postgresql.v1.image" . }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
|
||||
{{- if .Values.readReplicas.containerSecurityContext.enabled }}
|
||||
securityContext: {{- omit .Values.readReplicas.containerSecurityContext "enabled" | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.diagnosticMode.enabled }}
|
||||
command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }}
|
||||
{{- else if .Values.readReplicas.command }}
|
||||
command: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.command "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.diagnosticMode.enabled }}
|
||||
args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }}
|
||||
{{- else if .Values.readReplicas.args }}
|
||||
args: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.args "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
- name: BITNAMI_DEBUG
|
||||
value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }}
|
||||
- name: POSTGRESQL_PORT_NUMBER
|
||||
value: {{ .Values.containerPorts.postgresql | quote }}
|
||||
- name: POSTGRESQL_VOLUME_DIR
|
||||
value: {{ .Values.readReplicas.persistence.mountPath | quote }}
|
||||
{{- if .Values.readReplicas.persistence.mountPath }}
|
||||
- name: PGDATA
|
||||
value: {{ .Values.postgresqlDataDir | quote }}
|
||||
{{- end }}
|
||||
# Authentication
|
||||
{{- if or (eq $customUser "postgres") (empty $customUser) }}
|
||||
{{- if .Values.auth.enablePostgresUser }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: POSTGRES_PASSWORD_FILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.adminPasswordKey" .) }}
|
||||
{{- else }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ include "postgresql.v1.adminPasswordKey" . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
- name: ALLOW_EMPTY_PASSWORD
|
||||
value: "true"
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
- name: POSTGRES_USER
|
||||
value: {{ $customUser | quote }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: POSTGRES_PASSWORD_FILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.userPasswordKey" .) }}
|
||||
{{- else }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ include "postgresql.v1.userPasswordKey" . }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth.enablePostgresUser }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: POSTGRES_POSTGRES_PASSWORD_FILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.adminPasswordKey" .) }}
|
||||
{{- else }}
|
||||
- name: POSTGRES_POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ include "postgresql.v1.adminPasswordKey" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
# Replication
|
||||
- name: POSTGRES_REPLICATION_MODE
|
||||
value: "slave"
|
||||
- name: POSTGRES_REPLICATION_USER
|
||||
value: {{ .Values.auth.replicationUsername | quote }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: POSTGRES_REPLICATION_PASSWORD_FILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.replicationPasswordKey" .) }}
|
||||
{{- else }}
|
||||
- name: POSTGRES_REPLICATION_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ include "postgresql.v1.replicationPasswordKey" . }}
|
||||
{{- end }}
|
||||
- name: POSTGRES_CLUSTER_APP_NAME
|
||||
value: {{ .Values.replication.applicationName }}
|
||||
- name: POSTGRES_MASTER_HOST
|
||||
value: {{ include "postgresql.v1.primary.fullname" . }}
|
||||
- name: POSTGRES_MASTER_PORT_NUMBER
|
||||
value: {{ include "postgresql.v1.service.port" . | quote }}
|
||||
# TLS
|
||||
- name: POSTGRESQL_ENABLE_TLS
|
||||
value: {{ ternary "yes" "no" .Values.tls.enabled | quote }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS
|
||||
value: {{ ternary "yes" "no" .Values.tls.preferServerCiphers | quote }}
|
||||
- name: POSTGRESQL_TLS_CERT_FILE
|
||||
value: {{ include "postgresql.v1.tlsCert" . }}
|
||||
- name: POSTGRESQL_TLS_KEY_FILE
|
||||
value: {{ include "postgresql.v1.tlsCertKey" . }}
|
||||
{{- if .Values.tls.certCAFilename }}
|
||||
- name: POSTGRESQL_TLS_CA_FILE
|
||||
value: {{ include "postgresql.v1.tlsCACert" . }}
|
||||
{{- end }}
|
||||
{{- if .Values.tls.crlFilename }}
|
||||
- name: POSTGRESQL_TLS_CRL_FILE
|
||||
value: {{ include "postgresql.v1.tlsCRL" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
# Audit
|
||||
- name: POSTGRESQL_LOG_HOSTNAME
|
||||
value: {{ .Values.audit.logHostname | quote }}
|
||||
- name: POSTGRESQL_LOG_CONNECTIONS
|
||||
value: {{ .Values.audit.logConnections | quote }}
|
||||
- name: POSTGRESQL_LOG_DISCONNECTIONS
|
||||
value: {{ .Values.audit.logDisconnections | quote }}
|
||||
{{- if .Values.audit.logLinePrefix }}
|
||||
- name: POSTGRESQL_LOG_LINE_PREFIX
|
||||
value: {{ .Values.audit.logLinePrefix | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.audit.logTimezone }}
|
||||
- name: POSTGRESQL_LOG_TIMEZONE
|
||||
value: {{ .Values.audit.logTimezone | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.audit.pgAuditLog }}
|
||||
- name: POSTGRESQL_PGAUDIT_LOG
|
||||
value: {{ .Values.audit.pgAuditLog | quote }}
|
||||
{{- end }}
|
||||
- name: POSTGRESQL_PGAUDIT_LOG_CATALOG
|
||||
value: {{ .Values.audit.pgAuditLogCatalog | quote }}
|
||||
# Others
|
||||
- name: POSTGRESQL_CLIENT_MIN_MESSAGES
|
||||
value: {{ .Values.audit.clientMinMessages | quote }}
|
||||
- name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES
|
||||
value: {{ .Values.postgresqlSharedPreloadLibraries | quote }}
|
||||
{{- if .Values.readReplicas.extraEnvVars }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.extraEnvVars "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.readReplicas.extraEnvVarsCM .Values.readReplicas.extraEnvVarsSecret }}
|
||||
envFrom:
|
||||
{{- if .Values.readReplicas.extraEnvVarsCM }}
|
||||
- configMapRef:
|
||||
name: {{ .Values.readReplicas.extraEnvVarsCM }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.extraEnvVarsSecret }}
|
||||
- secretRef:
|
||||
name: {{ .Values.readReplicas.extraEnvVarsSecret }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: tcp-postgresql
|
||||
containerPort: {{ .Values.containerPorts.postgresql }}
|
||||
{{- if not .Values.diagnosticMode.enabled }}
|
||||
{{- if .Values.readReplicas.customStartupProbe }}
|
||||
startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.customStartupProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.readReplicas.startupProbe.enabled }}
|
||||
startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readReplicas.startupProbe "enabled") "context" $) | nindent 12 }}
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
{{- if (include "postgresql.v1.database" .) }}
|
||||
- exec pg_isready -U {{ default "postgres" $customUser| quote }} -d "dbname={{ include "postgresql.v1.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }}
|
||||
{{- else }}
|
||||
- exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.customLivenessProbe }}
|
||||
livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.customLivenessProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.readReplicas.livenessProbe.enabled }}
|
||||
livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readReplicas.livenessProbe "enabled") "context" $) | nindent 12 }}
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
{{- if (include "postgresql.v1.database" .) }}
|
||||
- exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.v1.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }}
|
||||
{{- else }}
|
||||
- exec pg_isready -U {{default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.v1.tlsCert" . }} sslkey={{ include "postgresql.v1.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.customReadinessProbe }}
|
||||
readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.customReadinessProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.readReplicas.readinessProbe.enabled }}
|
||||
readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readReplicas.readinessProbe "enabled") "context" $) | nindent 12 }}
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- -e
|
||||
{{- include "postgresql.v1.readinessProbeCommand" . | nindent 16 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.resources }}
|
||||
resources: {{- toYaml .Values.readReplicas.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.lifecycleHooks }}
|
||||
lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.lifecycleHooks "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: postgresql-password
|
||||
mountPath: /opt/bitnami/postgresql/secrets/
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.extendedConfiguration }}
|
||||
- name: postgresql-extended-config
|
||||
mountPath: {{ .Values.readReplicas.persistence.mountPath }}/conf/conf.d/
|
||||
{{- end }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: postgresql-certificates
|
||||
mountPath: /opt/bitnami/postgresql/certs
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{- if .Values.shmVolume.enabled }}
|
||||
- name: dshm
|
||||
mountPath: /dev/shm
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.persistence.enabled }}
|
||||
- name: data
|
||||
mountPath: {{ .Values.readReplicas.persistence.mountPath }}
|
||||
{{- if .Values.readReplicas.persistence.subPath }}
|
||||
subPath: {{ .Values.readReplicas.persistence.subPath }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.extraVolumeMounts }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.extraVolumeMounts "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.enabled }}
|
||||
- name: metrics
|
||||
image: {{ include "postgresql.v1.metrics.image" . }}
|
||||
imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }}
|
||||
{{- if .Values.metrics.containerSecurityContext.enabled }}
|
||||
securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.diagnosticMode.enabled }}
|
||||
command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }}
|
||||
args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }}
|
||||
{{- else if .Values.metrics.customMetrics }}
|
||||
args: [ "--extend.query-path", "/conf/custom-metrics.yaml" ]
|
||||
{{- end }}
|
||||
env:
|
||||
{{- $database := required "In order to enable metrics you need to specify a database (.Values.auth.database or .Values.global.postgresql.auth.database)" (include "postgresql.v1.database" .) }}
|
||||
- name: DATA_SOURCE_URI
|
||||
value: {{ printf "127.0.0.1:%d/%s?sslmode=disable" (int (include "postgresql.v1.service.port" .)) $database }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: DATA_SOURCE_PASS_FILE
|
||||
value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (include "postgresql.v1.userPasswordKey" .) }}
|
||||
{{- else }}
|
||||
- name: DATA_SOURCE_PASS
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "postgresql.v1.secretName" . }}
|
||||
key: {{ include "postgresql.v1.userPasswordKey" . }}
|
||||
{{- end }}
|
||||
- name: DATA_SOURCE_USER
|
||||
value: {{ default "postgres" $customUser | quote }}
|
||||
{{- if .Values.metrics.extraEnvVars }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http-metrics
|
||||
containerPort: {{ .Values.metrics.containerPorts.metrics }}
|
||||
{{- if not .Values.diagnosticMode.enabled }}
|
||||
{{- if .Values.metrics.customStartupProbe }}
|
||||
startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.metrics.startupProbe.enabled }}
|
||||
startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }}
|
||||
tcpSocket:
|
||||
port: http-metrics
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.customLivenessProbe }}
|
||||
livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.metrics.livenessProbe.enabled }}
|
||||
livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }}
|
||||
httpGet:
|
||||
path: /
|
||||
port: http-metrics
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.customReadinessProbe }}
|
||||
readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }}
|
||||
{{- else if .Values.metrics.readinessProbe.enabled }}
|
||||
readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }}
|
||||
httpGet:
|
||||
path: /
|
||||
port: http-metrics
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: postgresql-password
|
||||
mountPath: /opt/bitnami/postgresql/secrets/
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.customMetrics }}
|
||||
- name: custom-metrics
|
||||
mountPath: /conf
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{- if .Values.metrics.resources }}
|
||||
resources: {{- toYaml .Values.metrics.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.sidecars }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.sidecars "context" $ ) | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
{{- if .Values.readReplicas.extendedConfiguration }}
|
||||
- name: postgresql-extended-config
|
||||
configMap:
|
||||
name: {{ include "postgresql.v1.readReplicas.extendedConfigmapName" . }}
|
||||
{{- end }}
|
||||
{{- if .Values.auth.usePasswordFiles }}
|
||||
- name: postgresql-password
|
||||
secret:
|
||||
secretName: {{ include "postgresql.v1.secretName" . }}
|
||||
{{- end }}
|
||||
{{- if .Values.tls.enabled }}
|
||||
- name: raw-certificates
|
||||
secret:
|
||||
secretName: {{ include "postgresql.v1.tlsSecretName" . }}
|
||||
- name: postgresql-certificates
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- if and .Values.metrics.enabled .Values.metrics.customMetrics }}
|
||||
- name: custom-metrics
|
||||
configMap:
|
||||
name: {{ printf "%s-metrics" (include "postgresql.v1.readReplica.fullname" .) }}
|
||||
{{- end }}
|
||||
{{- if .Values.shmVolume.enabled }}
|
||||
- name: dshm
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
{{- if .Values.shmVolume.sizeLimit }}
|
||||
sizeLimit: {{ .Values.shmVolume.sizeLimit }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.extraVolumes }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.extraVolumes "context" $ ) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if and .Values.readReplicas.persistence.enabled .Values.readReplicas.persistence.existingClaim }}
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ tpl .Values.readReplicas.persistence.existingClaim $ }}
|
||||
{{- else if not .Values.readReplicas.persistence.enabled }}
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
{{- else }}
|
||||
{{- if .Values.readReplicas.persistentVolumeClaimRetentionPolicy.enabled }}
|
||||
persistentVolumeClaimRetentionPolicy:
|
||||
whenDeleted: {{ .Values.readReplicas.persistentVolumeClaimRetentionPolicy.whenDeleted }}
|
||||
whenScaled: {{ .Values.readReplicas.persistentVolumeClaimRetentionPolicy.whenScaled }}
|
||||
{{- end }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
{{- if .Values.readReplicas.persistence.annotations }}
|
||||
annotations: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.persistence.annotations "context" $) | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.persistence.labels }}
|
||||
labels: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.persistence.labels "context" $) | nindent 10 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
accessModes:
|
||||
{{- range .Values.readReplicas.persistence.accessModes }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.persistence.dataSource }}
|
||||
dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.persistence.dataSource "context" $) | nindent 10 }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.readReplicas.persistence.size | quote }}
|
||||
{{- if .Values.readReplicas.persistence.selector }}
|
||||
selector: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.persistence.selector "context" $) | nindent 10 }}
|
||||
{{- end -}}
|
||||
{{- include "common.storage.class" (dict "persistence" .Values.readReplicas.persistence "global" .Values.global) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,38 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if eq .Values.architecture "replication" }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.readReplica.svc.headless" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: read
|
||||
annotations:
|
||||
{{- if or .Values.readReplicas.service.headless.annotations .Values.commonAnnotations }}
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.service.headless.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
# Use this annotation in addition to the actual publishNotReadyAddresses
|
||||
# field below because the annotation will stop being respected soon but the
|
||||
# field is broken in some versions of Kubernetes:
|
||||
# https://github.com/kubernetes/kubernetes/issues/58662
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
spec:
|
||||
type: ClusterIP
|
||||
clusterIP: None
|
||||
# We want all pods in the StatefulSet to have their addresses published for
|
||||
# the sake of the other Postgresql pods even before they're ready, since they
|
||||
# have to be able to talk to each other in order to become ready.
|
||||
publishNotReadyAddresses: true
|
||||
ports:
|
||||
- name: tcp-postgresql
|
||||
port: {{ include "postgresql.v1.readReplica.service.port" . }}
|
||||
targetPort: tcp-postgresql
|
||||
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: read
|
||||
{{- end }}
|
||||
53
charts/airflow/charts/postgresql/templates/read/svc.yaml
Normal file
53
charts/airflow/charts/postgresql/templates/read/svc.yaml
Normal file
@ -0,0 +1,53 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if eq .Values.architecture "replication" }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.readReplica.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: read
|
||||
{{- if or .Values.commonAnnotations .Values.readReplicas.service.annotations }}
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.service.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: {{ .Values.readReplicas.service.type }}
|
||||
{{- if or (eq .Values.readReplicas.service.type "LoadBalancer") (eq .Values.readReplicas.service.type "NodePort") }}
|
||||
externalTrafficPolicy: {{ .Values.readReplicas.service.externalTrafficPolicy | quote }}
|
||||
{{- end }}
|
||||
{{- if and (eq .Values.readReplicas.service.type "LoadBalancer") (not (empty .Values.readReplicas.service.loadBalancerSourceRanges)) }}
|
||||
loadBalancerSourceRanges: {{ .Values.readReplicas.service.loadBalancerSourceRanges }}
|
||||
{{- end }}
|
||||
{{- if and (eq .Values.readReplicas.service.type "LoadBalancer") (not (empty .Values.readReplicas.service.loadBalancerIP)) }}
|
||||
loadBalancerIP: {{ .Values.readReplicas.service.loadBalancerIP }}
|
||||
{{- end }}
|
||||
{{- if and .Values.readReplicas.service.clusterIP (eq .Values.readReplicas.service.type "ClusterIP") }}
|
||||
clusterIP: {{ .Values.readReplicas.service.clusterIP }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.service.sessionAffinity }}
|
||||
sessionAffinity: {{ .Values.readReplicas.service.sessionAffinity }}
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.service.sessionAffinityConfig }}
|
||||
sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.service.sessionAffinityConfig "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: tcp-postgresql
|
||||
port: {{ include "postgresql.v1.readReplica.service.port" . }}
|
||||
targetPort: tcp-postgresql
|
||||
{{- if and (or (eq .Values.readReplicas.service.type "NodePort") (eq .Values.readReplicas.service.type "LoadBalancer")) (not (empty .Values.readReplicas.service.nodePorts.postgresql)) }}
|
||||
nodePort: {{ .Values.readReplicas.service.nodePorts.postgresql }}
|
||||
{{- else if eq .Values.readReplicas.service.type "ClusterIP" }}
|
||||
nodePort: null
|
||||
{{- end }}
|
||||
{{- if .Values.readReplicas.service.extraPorts }}
|
||||
{{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.service.extraPorts "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.readReplicas.podLabels .Values.commonLabels ) "context" . ) }}
|
||||
selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }}
|
||||
app.kubernetes.io/component: read
|
||||
{{- end }}
|
||||
32
charts/airflow/charts/postgresql/templates/role.yaml
Normal file
32
charts/airflow/charts/postgresql/templates/role.yaml
Normal file
@ -0,0 +1,32 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if .Values.rbac.create }}
|
||||
kind: Role
|
||||
apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }}
|
||||
metadata:
|
||||
name: {{ include "common.names.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
# yamllint disable rule:indentation
|
||||
rules:
|
||||
{{- if and (include "common.capabilities.psp.supported" .) .Values.psp.create }}
|
||||
- apiGroups:
|
||||
- 'policy'
|
||||
resources:
|
||||
- 'podsecuritypolicies'
|
||||
verbs:
|
||||
- 'use'
|
||||
resourceNames:
|
||||
- {{ include "common.names.fullname" . }}
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.rules }}
|
||||
{{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }}
|
||||
{{- end }}
|
||||
# yamllint enable rule:indentation
|
||||
{{- end }}
|
||||
24
charts/airflow/charts/postgresql/templates/rolebinding.yaml
Normal file
24
charts/airflow/charts/postgresql/templates/rolebinding.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if .Values.rbac.create }}
|
||||
kind: RoleBinding
|
||||
apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }}
|
||||
metadata:
|
||||
name: {{ include "common.names.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: {{ include "common.names.fullname" . }}
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "postgresql.v1.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
{{- end }}
|
||||
99
charts/airflow/charts/postgresql/templates/secrets.yaml
Normal file
99
charts/airflow/charts/postgresql/templates/secrets.yaml
Normal file
@ -0,0 +1,99 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- $host := include "postgresql.v1.primary.fullname" . }}
|
||||
{{- $port := include "postgresql.v1.service.port" . }}
|
||||
{{- $customUser := include "postgresql.v1.username" . }}
|
||||
{{- $postgresPassword := include "common.secrets.lookup" (dict "secret" (include "postgresql.v1.secretName" .) "key" (coalesce .Values.global.postgresql.auth.secretKeys.adminPasswordKey .Values.auth.secretKeys.adminPasswordKey) "defaultValue" (ternary (coalesce .Values.global.postgresql.auth.password .Values.auth.password .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword) (coalesce .Values.global.postgresql.auth.postgresPassword .Values.auth.postgresPassword) (or (empty $customUser) (eq $customUser "postgres"))) "context" $) | trimAll "\"" | b64dec }}
|
||||
{{- if and (not $postgresPassword) .Values.auth.enablePostgresUser }}
|
||||
{{- $postgresPassword = randAlphaNum 10 }}
|
||||
{{- end }}
|
||||
{{- $replicationPassword := "" }}
|
||||
{{- if eq .Values.architecture "replication" }}
|
||||
{{- $replicationPassword = include "common.secrets.passwords.manage" (dict "secret" (include "postgresql.v1.secretName" .) "key" (coalesce .Values.global.postgresql.auth.secretKeys.replicationPasswordKey .Values.auth.secretKeys.replicationPasswordKey) "providedValues" (list "auth.replicationPassword") "context" $) | trimAll "\"" | b64dec }}
|
||||
{{- end }}
|
||||
{{- $ldapPassword := "" }}
|
||||
{{- if and .Values.ldap.enabled (or .Values.ldap.bind_password .Values.ldap.bindpw) }}
|
||||
{{- $ldapPassword = coalesce .Values.ldap.bind_password .Values.ldap.bindpw }}
|
||||
{{- end }}
|
||||
{{- $password := "" }}
|
||||
{{- if and (not (empty $customUser)) (ne $customUser "postgres") }}
|
||||
{{- $password = include "common.secrets.passwords.manage" (dict "secret" (include "postgresql.v1.secretName" .) "key" (coalesce .Values.global.postgresql.auth.secretKeys.userPasswordKey .Values.auth.secretKeys.userPasswordKey) "providedValues" (list "global.postgresql.auth.password" "auth.password") "context" $) | trimAll "\"" | b64dec }}
|
||||
{{- end }}
|
||||
{{- $database := include "postgresql.v1.database" . }}
|
||||
{{- if (include "postgresql.v1.createSecret" .) }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "common.names.fullname" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
type: Opaque
|
||||
data:
|
||||
{{- if $postgresPassword }}
|
||||
postgres-password: {{ $postgresPassword | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- if $password }}
|
||||
password: {{ $password | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- if $replicationPassword }}
|
||||
replication-password: {{ $replicationPassword | b64enc | quote }}
|
||||
{{- end }}
|
||||
# We don't auto-generate LDAP password when it's not provided as we do for other passwords
|
||||
{{- if and .Values.ldap.enabled (or .Values.ldap.bind_password .Values.ldap.bindpw) }}
|
||||
ldap-password: {{ $ldapPassword | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.serviceBindings.enabled }}
|
||||
{{- if $postgresPassword }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "common.names.fullname" . }}-svcbind-postgres
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
type: servicebinding.io/postgresql
|
||||
data:
|
||||
provider: {{ print "bitnami" | b64enc | quote }}
|
||||
type: {{ print "postgresql" | b64enc | quote }}
|
||||
host: {{ $host | b64enc | quote }}
|
||||
port: {{ $port | b64enc | quote }}
|
||||
username: {{ print "postgres" | b64enc | quote }}
|
||||
database: {{ print "postgres" | b64enc | quote }}
|
||||
password: {{ $postgresPassword | b64enc | quote }}
|
||||
uri: {{ printf "postgresql://postgres:%s@%s:%s/postgres" $postgresPassword $host $port | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- if $password }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "common.names.fullname" . }}-svcbind-custom-user
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
type: servicebinding.io/postgresql
|
||||
data:
|
||||
provider: {{ print "bitnami" | b64enc | quote }}
|
||||
type: {{ print "postgresql" | b64enc | quote }}
|
||||
host: {{ $host | b64enc | quote }}
|
||||
port: {{ $port | b64enc | quote }}
|
||||
username: {{ $customUser | b64enc | quote }}
|
||||
password: {{ $password | b64enc | quote }}
|
||||
{{- if $database }}
|
||||
database: {{ $database | b64enc | quote }}
|
||||
{{- end }}
|
||||
uri: {{ printf "postgresql://%s:%s@%s:%s/%s" $customUser $password $host $port $database | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,18 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "postgresql.v1.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }}
|
||||
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.serviceAccount.annotations .Values.commonAnnotations ) "context" . ) }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
|
||||
{{- end }}
|
||||
30
charts/airflow/charts/postgresql/templates/tls-secrets.yaml
Normal file
30
charts/airflow/charts/postgresql/templates/tls-secrets.yaml
Normal file
@ -0,0 +1,30 @@
|
||||
{{- /*
|
||||
Copyright VMware, Inc.
|
||||
SPDX-License-Identifier: APACHE-2.0
|
||||
*/}}
|
||||
|
||||
{{- if (include "postgresql.v1.createTlsSecret" . ) }}
|
||||
{{- $secretName := printf "%s-crt" (include "common.names.fullname" .) }}
|
||||
{{- $ca := genCA "postgresql-ca" 365 }}
|
||||
{{- $fullname := include "common.names.fullname" . }}
|
||||
{{- $releaseNamespace := .Release.Namespace }}
|
||||
{{- $clusterDomain := .Values.clusterDomain }}
|
||||
{{- $primaryHeadlessServiceName := include "postgresql.v1.primary.svc.headless" . }}
|
||||
{{- $readHeadlessServiceName := include "postgresql.v1.readReplica.svc.headless" . }}
|
||||
{{- $altNames := list (printf "*.%s.%s.svc.%s" $fullname $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $fullname $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $primaryHeadlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $primaryHeadlessServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $readHeadlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $readHeadlessServiceName $releaseNamespace $clusterDomain) $fullname }}
|
||||
{{- $cert := genSignedCert $fullname nil $altNames 365 $ca }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ $secretName }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
|
||||
{{- if .Values.commonAnnotations }}
|
||||
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
|
||||
{{- end }}
|
||||
type: kubernetes.io/tls
|
||||
data:
|
||||
tls.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.crt" "defaultValue" $cert.Cert "context" $) }}
|
||||
tls.key: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "tls.key" "defaultValue" $cert.Key "context" $) }}
|
||||
ca.crt: {{ include "common.secrets.lookup" (dict "secret" $secretName "key" "ca.crt" "defaultValue" $ca.Cert "context" $) }}
|
||||
{{- end }}
|
||||
156
charts/airflow/charts/postgresql/values.schema.json
Normal file
156
charts/airflow/charts/postgresql/values.schema.json
Normal file
@ -0,0 +1,156 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"architecture": {
|
||||
"type": "string",
|
||||
"title": "PostgreSQL architecture",
|
||||
"form": true,
|
||||
"description": "Allowed values: `standalone` or `replication`"
|
||||
},
|
||||
"auth": {
|
||||
"type": "object",
|
||||
"title": "Authentication configuration",
|
||||
"form": true,
|
||||
"properties": {
|
||||
"enablePostgresUser": {
|
||||
"type": "boolean",
|
||||
"title": "Enable \"postgres\" admin user",
|
||||
"description": "Assign a password to the \"postgres\" admin user. Otherwise, remote access will be blocked for this user",
|
||||
"form": true
|
||||
},
|
||||
"postgresPassword": {
|
||||
"type": "string",
|
||||
"title": "Password for the \"postgres\" admin user",
|
||||
"description": "Defaults to a random 10-character alphanumeric string if not set",
|
||||
"form": true
|
||||
},
|
||||
"database": {
|
||||
"type": "string",
|
||||
"title": "PostgreSQL custom database",
|
||||
"description": "Name of the custom database to be created during the 1st initialization of PostgreSQL",
|
||||
"form": true
|
||||
},
|
||||
"username": {
|
||||
"type": "string",
|
||||
"title": "PostgreSQL custom user",
|
||||
"description": "Name of the custom user to be created during the 1st initialization of PostgreSQL. This user only has permissions on the PostgreSQL custom database",
|
||||
"form": true
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"title": "Password for the custom user to create",
|
||||
"description": "Defaults to a random 10-character alphanumeric string if not set",
|
||||
"form": true
|
||||
},
|
||||
"replicationUsername": {
|
||||
"type": "string",
|
||||
"title": "PostgreSQL replication user",
|
||||
"description": "Name of user used to manage replication.",
|
||||
"form": true,
|
||||
"hidden": {
|
||||
"value": "standalone",
|
||||
"path": "architecture"
|
||||
}
|
||||
},
|
||||
"replicationPassword": {
|
||||
"type": "string",
|
||||
"title": "Password for PostgreSQL replication user",
|
||||
"description": "Defaults to a random 10-character alphanumeric string if not set",
|
||||
"form": true,
|
||||
"hidden": {
|
||||
"value": "standalone",
|
||||
"path": "architecture"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"persistence": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"size": {
|
||||
"type": "string",
|
||||
"title": "Persistent Volume Size",
|
||||
"form": true,
|
||||
"render": "slider",
|
||||
"sliderMin": 1,
|
||||
"sliderMax": 100,
|
||||
"sliderUnit": "Gi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"title": "Required Resources",
|
||||
"description": "Configure resource requests",
|
||||
"form": true,
|
||||
"properties": {
|
||||
"requests": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"memory": {
|
||||
"type": "string",
|
||||
"form": true,
|
||||
"render": "slider",
|
||||
"title": "Memory Request",
|
||||
"sliderMin": 10,
|
||||
"sliderMax": 2048,
|
||||
"sliderUnit": "Mi"
|
||||
},
|
||||
"cpu": {
|
||||
"type": "string",
|
||||
"form": true,
|
||||
"render": "slider",
|
||||
"title": "CPU Request",
|
||||
"sliderMin": 10,
|
||||
"sliderMax": 2000,
|
||||
"sliderUnit": "m"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"replication": {
|
||||
"type": "object",
|
||||
"form": true,
|
||||
"title": "Replication Details",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"title": "Enable Replication",
|
||||
"form": true
|
||||
},
|
||||
"readReplicas": {
|
||||
"type": "integer",
|
||||
"title": "read Replicas",
|
||||
"form": true,
|
||||
"hidden": {
|
||||
"value": "standalone",
|
||||
"path": "architecture"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"volumePermissions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"form": true,
|
||||
"title": "Enable Init Containers",
|
||||
"description": "Change the owner of the persist volume mountpoint to RunAsUser:fsGroup"
|
||||
}
|
||||
}
|
||||
},
|
||||
"metrics": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"title": "Configure metrics exporter",
|
||||
"form": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1613
charts/airflow/charts/postgresql/values.yaml
Normal file
1613
charts/airflow/charts/postgresql/values.yaml
Normal file
File diff suppressed because it is too large
Load Diff
28
charts/airflow/dockerfiles/README.md
Normal file
28
charts/airflow/dockerfiles/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
Those are images that are needed for the Helm Chart.
|
||||
|
||||
In each of the images you can find "build_and_push.sh" script that builds and pushes the image.
|
||||
|
||||
You need to be a PMC member with direct push access to "apache/airflow" DockerHub registry
|
||||
to be able to push to the Airflow DockerHub registry.
|
||||
|
||||
You can set the DOCKERHUB_USER variable to push to your own DockerHub user if you want
|
||||
to test the image or build your own image.
|
||||
60
charts/airflow/dockerfiles/pgbouncer-exporter/Dockerfile
Normal file
60
charts/airflow/dockerfiles/pgbouncer-exporter/Dockerfile
Normal file
@ -0,0 +1,60 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
ARG ALPINE_VERSION="3.19"
|
||||
ARG GO_VERSION
|
||||
|
||||
FROM golang:${GO_VERSION} AS builder
|
||||
|
||||
ARG PGBOUNCER_EXPORTER_VERSION
|
||||
|
||||
WORKDIR /usr/src/myapp
|
||||
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-e", "-u", "-x", "-c"]
|
||||
|
||||
RUN URL="https://github.com/jbub/pgbouncer_exporter/archive/v${PGBOUNCER_EXPORTER_VERSION}.tar.gz" \
|
||||
&& curl -L "${URL}" | tar -zx --strip-components 1 \
|
||||
&& PLATFORM=$([ "$(uname -m)" = "aarch64" ] && echo "arm64" || echo "amd64" )\
|
||||
&& GOOS=linux GOARCH="${PLATFORM}" CGO_ENABLED=0 go build -v
|
||||
|
||||
FROM alpine:${ALPINE_VERSION} AS final
|
||||
|
||||
# We want to make sure this one includes latest security fixes.
|
||||
# "Pin versions in apk add" https://github.com/hadolint/hadolint/wiki/DL3018
|
||||
# hadolint ignore=DL3018
|
||||
RUN apk --no-cache add libressl libressl-dev openssl
|
||||
|
||||
COPY --from=builder /usr/src/myapp/pgbouncer_exporter /bin
|
||||
|
||||
ARG PGBOUNCER_EXPORTER_VERSION
|
||||
ARG AIRFLOW_PGBOUNCER_EXPORTER_VERSION
|
||||
ARG GO_VERSION
|
||||
ARG COMMIT_SHA
|
||||
|
||||
LABEL org.apache.airflow.component="pgbouncer-exporter" \
|
||||
org.apache.airflow.pgbouncer-exporter.version="${PGBOUNCER_EXPORTER_VERSION}" \
|
||||
org.apache.airflow.go.version="${GO_VERSION}" \
|
||||
org.apache.airflow.airflow-pgbouncer-exporter.version="${AIRFLOW_PGBOUNCER_EXPORTER_VERSION}" \
|
||||
org.apache.airflow.commit-sha="${COMMIT_SHA}" \
|
||||
maintainer="Apache Airflow Community <dev@airflow.apache.org>"
|
||||
|
||||
HEALTHCHECK CMD ["/bin/pgbouncer_exporter", "health"]
|
||||
|
||||
USER nobody
|
||||
|
||||
ENTRYPOINT ["/bin/pgbouncer_exporter"]
|
||||
CMD ["server"]
|
||||
@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
set -euo pipefail
|
||||
DOCKERHUB_USER=${DOCKERHUB_USER:="apache"}
|
||||
readonly DOCKERHUB_USER
|
||||
DOCKERHUB_REPO=${DOCKERHUB_REPO:="airflow"}
|
||||
readonly DOCKERHUB_REPO
|
||||
|
||||
PGBOUNCER_EXPORTER_VERSION="0.18.0"
|
||||
readonly PGBOUNCER_EXPORTER_VERSION
|
||||
|
||||
AIRFLOW_PGBOUNCER_EXPORTER_VERSION="2025.03.05"
|
||||
readonly AIRFLOW_PGBOUNCER_EXPORTER_VERSION
|
||||
|
||||
EXPECTED_GO_VERSION="1.23.7"
|
||||
readonly EXPECTED_GO_VERSION
|
||||
|
||||
COMMIT_SHA=$(git rev-parse HEAD)
|
||||
readonly COMMIT_SHA
|
||||
|
||||
TAG="${DOCKERHUB_USER}/${DOCKERHUB_REPO}:airflow-pgbouncer-exporter-${AIRFLOW_PGBOUNCER_EXPORTER_VERSION}-${PGBOUNCER_EXPORTER_VERSION}"
|
||||
readonly TAG
|
||||
|
||||
function center_text() {
|
||||
columns=$(tput cols || echo 80)
|
||||
printf "%*s\n" $(( (${#1} + columns) / 2)) "$1"
|
||||
}
|
||||
|
||||
cd "$( dirname "${BASH_SOURCE[0]}" )" || exit 1
|
||||
|
||||
center_text "Building image"
|
||||
|
||||
# Note, you need buildx and qemu installed for your docker. They come pre-installed with docker-desktop, but
|
||||
# as described in:
|
||||
# * https://docs.docker.com/build/install-buildx/
|
||||
# * https://docs.docker.com/build/building/multi-platform/
|
||||
# You can also install them easily on all docker-based systems
|
||||
# You might also need to create a different builder to build multi-platform images
|
||||
# For example by running `docker buildx create --use`
|
||||
|
||||
docker buildx build . \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--pull \
|
||||
--push \
|
||||
--build-arg "PGBOUNCER_EXPORTER_VERSION=${PGBOUNCER_EXPORTER_VERSION}" \
|
||||
--build-arg "AIRFLOW_PGBOUNCER_EXPORTER_VERSION=${AIRFLOW_PGBOUNCER_EXPORTER_VERSION}"\
|
||||
--build-arg "COMMIT_SHA=${COMMIT_SHA}" \
|
||||
--build-arg "GO_VERSION=${EXPECTED_GO_VERSION}" \
|
||||
--tag "${TAG}"
|
||||
|
||||
center_text "Checking image"
|
||||
|
||||
docker run --rm "${TAG}" --version
|
||||
78
charts/airflow/dockerfiles/pgbouncer/Dockerfile
Normal file
78
charts/airflow/dockerfiles/pgbouncer/Dockerfile
Normal file
@ -0,0 +1,78 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
ARG ALPINE_VERSION="3.19"
|
||||
FROM alpine:${ALPINE_VERSION} AS builder
|
||||
SHELL ["/bin/ash", "-e", "-x", "-c", "-o", "pipefail"]
|
||||
|
||||
ARG PGBOUNCER_TAG
|
||||
ARG PGBOUNCER_VERSION
|
||||
ARG AIRFLOW_PGBOUNCER_VERSION
|
||||
|
||||
ARG PGBOUNCER_SHA256
|
||||
|
||||
# Those are build deps only but still we want the latest versions of those
|
||||
# "Pin versions in apk add" https://github.com/hadolint/hadolint/wiki/DL3018
|
||||
# hadolint ignore=DL3018
|
||||
RUN apk --no-cache add make pkgconfig build-base libtool wget gcc g++ libevent-dev openssl-dev c-ares-dev ca-certificates
|
||||
# We are not using Dash so we can safely ignore the "Dash warning"
|
||||
# "In dash, something is not supported." https://github.com/koalaman/shellcheck/wiki/SC2169
|
||||
# hadolint ignore=SC2169,SC3060
|
||||
RUN wget --progress=dot:giga "https://github.com/pgbouncer/pgbouncer/releases/download/${PGBOUNCER_TAG}/pgbouncer-${PGBOUNCER_VERSION}.tar.gz" \
|
||||
&& echo "${PGBOUNCER_SHA256} pgbouncer-${PGBOUNCER_VERSION}.tar.gz" | sha256sum -c - \
|
||||
&& tar -xzvf pgbouncer-$PGBOUNCER_VERSION.tar.gz
|
||||
|
||||
WORKDIR /pgbouncer-$PGBOUNCER_VERSION
|
||||
RUN ./configure --prefix=/usr --disable-debug && make && make install \
|
||||
&& mkdir /etc/pgbouncer \
|
||||
&& cp ./etc/pgbouncer.ini /etc/pgbouncer/ \
|
||||
&& touch /etc/pgbouncer/userlist.txt \
|
||||
&& sed -i -e "s|logfile = |#logfile = |" \
|
||||
-e "s|pidfile = |#pidfile = |" \
|
||||
-e "s|listen_addr = .*|listen_addr = 0.0.0.0|" \
|
||||
-e "s|auth_type = .*|auth_type = md5|" \
|
||||
/etc/pgbouncer/pgbouncer.ini
|
||||
|
||||
FROM alpine:${ALPINE_VERSION}
|
||||
|
||||
ARG PGBOUNCER_VERSION
|
||||
ARG AIRFLOW_PGBOUNCER_VERSION
|
||||
ARG COMMIT_SHA
|
||||
|
||||
|
||||
# We want to make sure this one includes latest security fixes.
|
||||
# "Pin versions in apk add" https://github.com/hadolint/hadolint/wiki/DL3018
|
||||
# hadolint ignore=DL3018
|
||||
RUN apk --no-cache add libevent libressl c-ares
|
||||
|
||||
COPY --from=builder /etc/pgbouncer /etc/pgbouncer
|
||||
COPY --from=builder /usr/bin/pgbouncer /usr/bin/pgbouncer
|
||||
|
||||
LABEL org.apache.airflow.component="pgbouncer" \
|
||||
org.apache.airflow.pgbouncer.version="${PGBOUNCER_VERSION}" \
|
||||
org.apache.airflow.airflow-pgbouncer.version="${AIRFLOW_PGBOUNCER_VERSION}" \
|
||||
org.apache.airflow.commit-sha="${COMMIT_SHA}" \
|
||||
maintainer="Apache Airflow Community <dev@airflow.apache.org>"
|
||||
|
||||
# Healthcheck
|
||||
HEALTHCHECK --interval=10s --timeout=3s CMD stat /tmp/.s.PGSQL.*
|
||||
|
||||
EXPOSE 6432
|
||||
|
||||
USER nobody
|
||||
|
||||
# pgbouncer can't run as root, so let's drop to 'nobody'
|
||||
ENTRYPOINT ["/usr/bin/pgbouncer", "-u", "nobody", "/etc/pgbouncer/pgbouncer.ini" ]
|
||||
75
charts/airflow/dockerfiles/pgbouncer/build_and_push.sh
Normal file
75
charts/airflow/dockerfiles/pgbouncer/build_and_push.sh
Normal file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
set -euo pipefail
|
||||
DOCKERHUB_USER=${DOCKERHUB_USER:="apache"}
|
||||
readonly DOCKERHUB_USER
|
||||
|
||||
DOCKERHUB_REPO=${DOCKERHUB_REPO:="airflow"}
|
||||
readonly DOCKERHUB_REPO
|
||||
|
||||
# Sometimes the pgbouncer tag does not reliably correspond with the version name
|
||||
# For example, it may have a `-fixed` suffix
|
||||
PGBOUNCER_TAG="pgbouncer_1_23_1-fixed"
|
||||
readonly PGBOUNCER_TAG
|
||||
|
||||
PGBOUNCER_VERSION="1.23.1"
|
||||
readonly PGBOUNCER_VERSION
|
||||
|
||||
PGBOUNCER_SHA256="1963b497231d9a560a62d266e4a2eae6881ab401853d93e5d292c3740eec5084"
|
||||
readonly PGBOUNCER_SHA256
|
||||
|
||||
AIRFLOW_PGBOUNCER_VERSION="2025.03.05"
|
||||
readonly AIRFLOW_PGBOUNCER_VERSION
|
||||
|
||||
COMMIT_SHA=$(git rev-parse HEAD)
|
||||
readonly COMMIT_SHA
|
||||
|
||||
TAG="${DOCKERHUB_USER}/${DOCKERHUB_REPO}:airflow-pgbouncer-${AIRFLOW_PGBOUNCER_VERSION}-${PGBOUNCER_VERSION}"
|
||||
readonly TAG
|
||||
|
||||
function center_text() {
|
||||
columns=$(tput cols || echo 80)
|
||||
printf "%*s\n" $(( (${#1} + columns) / 2)) "$1"
|
||||
}
|
||||
|
||||
cd "$( dirname "${BASH_SOURCE[0]}" )" || exit 1
|
||||
|
||||
center_text "Building image"
|
||||
|
||||
# Note, you need buildx and qemu installed for your docker. They come pre-installed with docker-desktop, but
|
||||
# as described in:
|
||||
# * https://docs.docker.com/build/install-buildx/
|
||||
# * https://docs.docker.com/build/building/multi-platform/
|
||||
# You can also install them easily on all docker-based systems
|
||||
# You might also need to create a different builder to build multi-platform images
|
||||
# For example by running `docker buildx create --use`
|
||||
|
||||
docker buildx build . \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--pull \
|
||||
--push \
|
||||
--build-arg "PGBOUNCER_TAG=${PGBOUNCER_TAG}" \
|
||||
--build-arg "PGBOUNCER_VERSION=${PGBOUNCER_VERSION}" \
|
||||
--build-arg "AIRFLOW_PGBOUNCER_VERSION=${AIRFLOW_PGBOUNCER_VERSION}"\
|
||||
--build-arg "PGBOUNCER_SHA256=${PGBOUNCER_SHA256}"\
|
||||
--build-arg "COMMIT_SHA=${COMMIT_SHA}" \
|
||||
--tag "${TAG}"
|
||||
|
||||
center_text "Checking image"
|
||||
|
||||
docker run --rm "${TAG}" pgbouncer --version
|
||||
89
charts/airflow/docs/adding-connections-and-variables.rst
Normal file
89
charts/airflow/docs/adding-connections-and-variables.rst
Normal file
@ -0,0 +1,89 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
|
||||
Adding Connections, Variables and Environment Variables
|
||||
=======================================================
|
||||
|
||||
You can programmatically add Connections, Variables and arbitrary Environment Variables to your
|
||||
Airflow deployment using the Helm Chart.
|
||||
|
||||
|
||||
Connections and Sensitive Environment Variables
|
||||
-----------------------------------------------
|
||||
Under the ``secret`` and ``extraSecret`` sections of the ``values.yaml``, you can pass connection strings and sensitive
|
||||
environment variables into Airflow using the Helm Chart. To illustrate, lets create a yaml file called ``override.yaml``
|
||||
to override values under these sections of the ``values.yaml`` file.
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: override.yaml
|
||||
|
||||
secret:
|
||||
- envName: "AIRFLOW_CONN_GCP"
|
||||
secretName: "my-airflow-connections"
|
||||
secretKey: "AIRFLOW_CONN_GCP"
|
||||
- envName: "my-env"
|
||||
secretName: "my-secret-name"
|
||||
secretKey: "my-secret-key"
|
||||
|
||||
extraSecrets:
|
||||
my-airflow-connections:
|
||||
data: |
|
||||
AIRFLOW_CONN_GCP: 'base64_encoded_gcp_conn_string'
|
||||
my-secret-name:
|
||||
stringData: |
|
||||
my-secret-key: my-secret
|
||||
|
||||
.. warning::
|
||||
|
||||
Due to security concerns, it is not advised to define sensitive secrets values within ``values.yaml`` file.
|
||||
|
||||
Variables
|
||||
---------
|
||||
Airflow supports Variables which enable users to craft dynamic Dags. You can set Variables in Airflow in three ways - UI,
|
||||
command line, and within your Dag file. See :doc:`apache-airflow:howto/variable` for more.
|
||||
|
||||
With the Helm Chart, you can also inject environment variables into Airflow. In the ``override.yaml`` example file,
|
||||
we can override values of interest in the ``env`` section of the ``values.yaml`` file.
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: override.yaml
|
||||
|
||||
env:
|
||||
- name: "AIRFLOW_VAR_KEY"
|
||||
value: "value_1"
|
||||
- name: "AIRFLOW_VAR_ANOTHER_KEY"
|
||||
value: "value_2"
|
||||
|
||||
|
||||
You can also utilize ``extraEnv`` and ``extraEnvFrom`` if you need the name or value to be templated.
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: override.yaml
|
||||
|
||||
extraEnv: |
|
||||
- name: AIRFLOW_VAR_HELM_RELEASE_NAME
|
||||
value: '{{ .Release.Name }}'
|
||||
|
||||
extraEnvFrom: |
|
||||
- configMapRef:
|
||||
name: '{{ .Release.Name }}-airflow-variables'
|
||||
|
||||
extraConfigMaps:
|
||||
'{{ .Release.Name }}-airflow-variables':
|
||||
data: |
|
||||
AIRFLOW_VAR_HELLO_MESSAGE: "Hi!"
|
||||
42
charts/airflow/docs/airflow-configuration.rst
Normal file
42
charts/airflow/docs/airflow-configuration.rst
Normal file
@ -0,0 +1,42 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Configuring Airflow
|
||||
===================
|
||||
|
||||
The Helm Chart allows for setting arbitrary Airflow configuration in values file under the ``config`` key.
|
||||
Some of the defaults in the chart may differ from those of core Airflow and can be found in
|
||||
`values.yaml <https://github.com/apache/airflow/blob/main/chart/values.yaml>`__.
|
||||
|
||||
As an example of setting arbitrary configuration, the following ``override.yaml`` file demonstrates how one would
|
||||
allow Airflow UI users to view the Airflow configuration directly via UI:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: override.yaml
|
||||
|
||||
config:
|
||||
api:
|
||||
expose_config: 'True' # by default this is 'False'
|
||||
|
||||
Generally speaking, it is useful to familiarize oneself with the Airflow
|
||||
configuration prior to installing and deploying the service.
|
||||
|
||||
.. note::
|
||||
|
||||
The recommended way to load example Dags using the official Docker image and chart is to configure the ``AIRFLOW__CORE__LOAD_EXAMPLES`` environment variable
|
||||
in ``extraEnv`` (see :doc:`Parameters reference <parameters-ref>`). The official Docker image has ``AIRFLOW__CORE__LOAD_EXAMPLES=False``
|
||||
set within the image, so you need to override it with an environment variable, when deploying the chart, in order for the examples to be present.
|
||||
379
charts/airflow/docs/conf.py
Normal file
379
charts/airflow/docs/conf.py
Normal file
@ -0,0 +1,379 @@
|
||||
# Disable Flake8 because of all the sphinx imports
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""Configuration of Airflow Chart Docs."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
# Airflow documentation build configuration file, created by
|
||||
# sphinx-quickstart on Thu Oct 9 20:50:01 2014.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
import yaml
|
||||
from docs.utils.conf_constants import (
|
||||
AIRFLOW_FAVICON_PATH,
|
||||
AIRFLOW_REPO_ROOT_PATH,
|
||||
AUTOAPI_OPTIONS,
|
||||
BASIC_AUTOAPI_IGNORE_PATTERNS,
|
||||
BASIC_SPHINX_EXTENSIONS,
|
||||
SMARTQUOTES_EXCLUDES,
|
||||
SPELLING_WORDLIST_PATH,
|
||||
SPHINX_DESIGN_STATIC_PATH,
|
||||
SUPPRESS_WARNINGS,
|
||||
filter_autoapi_ignore_entries,
|
||||
get_autodoc_mock_imports,
|
||||
get_html_context,
|
||||
get_html_sidebars,
|
||||
get_html_theme_options,
|
||||
get_intersphinx_mapping,
|
||||
get_rst_epilogue,
|
||||
)
|
||||
from packaging.version import parse as parse_version
|
||||
|
||||
import airflow
|
||||
|
||||
PACKAGE_NAME = "helm-chart"
|
||||
CHART_ROOT_PATH = AIRFLOW_REPO_ROOT_PATH / "chart"
|
||||
CHART_DOC_PATH = CHART_ROOT_PATH / "docs"
|
||||
CHART_STATIC_PATH = CHART_DOC_PATH / "static"
|
||||
os.environ["AIRFLOW_PACKAGE_NAME"] = PACKAGE_NAME
|
||||
|
||||
CHART_YAML_FILE_PATH = CHART_ROOT_PATH / "Chart.yaml"
|
||||
with CHART_YAML_FILE_PATH.open() as chart_file:
|
||||
chart_yaml_contents = yaml.safe_load(chart_file)
|
||||
|
||||
PACKAGE_VERSION: str = chart_yaml_contents["version"]
|
||||
|
||||
# Adds to environment variables for easy access from other plugins like airflow_intersphinx.
|
||||
os.environ["AIRFLOW_PACKAGE_NAME"] = PACKAGE_NAME
|
||||
|
||||
# Hack to allow changing for piece of the code to behave differently while
|
||||
# the docs are being built. The main objective was to alter the
|
||||
# behavior of the utils.apply_default that was hiding function headers
|
||||
os.environ["BUILDING_AIRFLOW_DOCS"] = "TRUE"
|
||||
|
||||
# Use for generate rst_epilog and other post-generation substitutions
|
||||
global_substitutions = {
|
||||
"version": PACKAGE_VERSION,
|
||||
"airflow-version": airflow.__version__,
|
||||
"experimental": "This is an :ref:`experimental feature <experimental>`.",
|
||||
}
|
||||
|
||||
# == Sphinx configuration ======================================================
|
||||
|
||||
# -- Project information -------------------------------------------------------
|
||||
# See: https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
# General information about the project.
|
||||
project = PACKAGE_NAME
|
||||
# # The version info for the project you're documenting
|
||||
version = PACKAGE_VERSION
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = PACKAGE_VERSION
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
# See: https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
rst_epilog = get_rst_epilogue(PACKAGE_VERSION, False)
|
||||
|
||||
smartquotes_excludes = SMARTQUOTES_EXCLUDES
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = BASIC_SPHINX_EXTENSIONS
|
||||
|
||||
extensions.append("sphinx_jinja")
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns: list[str] = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["templates"]
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
keep_warnings = True
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
# See: https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = "sphinx_airflow_theme"
|
||||
|
||||
html_title = f"{PACKAGE_NAME} Documentation"
|
||||
|
||||
conf_py_path = "/chart/docs/"
|
||||
# A dictionary of values to pass into the template engine's context for all pages.
|
||||
html_context = get_html_context(conf_py_path)
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
html_short_title = ""
|
||||
|
||||
# given, this must be the name of an image file (path relative to the
|
||||
# configuration directory) that is the favicon of the docs. Modern browsers
|
||||
# use this as the icon for tabs, windows and bookmarks. It should be a
|
||||
# Windows-style icon file (.ico), which is 16x16 or 32x32 pixels large.
|
||||
html_favicon = AIRFLOW_FAVICON_PATH.as_posix()
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = [CHART_STATIC_PATH.as_posix(), SPHINX_DESIGN_STATIC_PATH.as_posix()]
|
||||
|
||||
html_js_files = ["gh-jira-links.js"]
|
||||
|
||||
html_css_files = ["custom.css"]
|
||||
|
||||
# -- Theme configuration -------------------------------------------------------
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
html_sidebars = get_html_sidebars(PACKAGE_VERSION)
|
||||
|
||||
# If false, no index is generated.
|
||||
html_use_index = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
html_show_copyright = False
|
||||
|
||||
html_theme_options: dict[str, Any] = get_html_theme_options()
|
||||
|
||||
# A dictionary of values to pass into the template engine's context for all pages.
|
||||
html_context = get_html_context(conf_py_path)
|
||||
|
||||
# == Extensions configuration ==================================================
|
||||
|
||||
# -- Options for sphinx_jinja ------------------------------------------
|
||||
# See: https://github.com/tardyp/sphinx-jinja
|
||||
|
||||
airflow_version = parse_version(
|
||||
re.search( # type: ignore[union-attr,arg-type]
|
||||
r"__version__ = \"([0-9\.]*)(\.dev[0-9]*)?\"",
|
||||
(AIRFLOW_REPO_ROOT_PATH / "airflow-core" / "src" / "airflow" / "__init__.py").read_text(),
|
||||
).groups(0)[0]
|
||||
)
|
||||
|
||||
|
||||
def _str_representer(dumper, data):
|
||||
style = "|" if "\n" in data else None # show as a block scalar if we have more than 1 line
|
||||
return dumper.represent_scalar("tag:yaml.org,2002:str", data, style)
|
||||
|
||||
|
||||
yaml.add_representer(str, _str_representer)
|
||||
|
||||
|
||||
def _format_default(value: Any) -> str:
|
||||
if value == "":
|
||||
return '""'
|
||||
if value is None:
|
||||
return "~"
|
||||
return str(value)
|
||||
|
||||
|
||||
def _format_examples(param_name: str, schema: dict) -> str | None:
|
||||
if not schema.get("examples"):
|
||||
return None
|
||||
|
||||
# Nicer to have the parameter name shown as well
|
||||
out = ""
|
||||
for ex_data in schema["examples"]:
|
||||
ex = [ex_data] if schema["type"] == "array" else ex_data
|
||||
out += yaml.dump({param_name: ex})
|
||||
return out
|
||||
|
||||
|
||||
def _get_params(root_schema: dict, prefix: str = "", default_section: str = "") -> list[dict]:
|
||||
"""
|
||||
Retrieve params.
|
||||
|
||||
Given an jsonschema objects properties dict, return a flattened list of all parameters
|
||||
from that object and any nested objects
|
||||
"""
|
||||
out = []
|
||||
for param_name, schema in root_schema.items():
|
||||
prefixed_name = f"{prefix}.{param_name}" if prefix else param_name
|
||||
section_name = schema["x-docsSection"] if "x-docsSection" in schema else default_section
|
||||
common_out = {
|
||||
"section": section_name,
|
||||
"name": prefixed_name,
|
||||
}
|
||||
if section_name and "description" in schema and schema["description"] and "default" in schema:
|
||||
out.append(
|
||||
{
|
||||
**common_out,
|
||||
"description": schema["description"],
|
||||
"default": _format_default(schema["default"]),
|
||||
"examples": _format_examples(param_name, schema),
|
||||
}
|
||||
)
|
||||
if schema.get("properties"):
|
||||
out += _get_params(schema["properties"], prefixed_name, section_name)
|
||||
items = schema.get("items")
|
||||
if items:
|
||||
out.extend(_process_array_items(items, prefixed_name, param_name, section_name))
|
||||
return out
|
||||
|
||||
|
||||
def _process_array_items(items: dict, parent_name: str, param_name: str, default_section: str) -> list[dict]:
|
||||
"""Extract parameters from array item schemas."""
|
||||
item_prefix = f"{parent_name}[]"
|
||||
section_name = items.get("x-docsSection", default_section)
|
||||
|
||||
if items.get("properties"):
|
||||
return _get_params(items["properties"], item_prefix, section_name)
|
||||
|
||||
if section_name and items.get("description") and "default" in items:
|
||||
return [
|
||||
{
|
||||
"section": section_name,
|
||||
"name": item_prefix,
|
||||
"description": items["description"],
|
||||
"default": _format_default(items["default"]),
|
||||
"examples": _format_examples(param_name, items),
|
||||
}
|
||||
]
|
||||
|
||||
return []
|
||||
|
||||
|
||||
schema_file = CHART_ROOT_PATH / "values.schema.json"
|
||||
with schema_file.open() as config_file:
|
||||
chart_schema = json.load(config_file)
|
||||
|
||||
params = _get_params(chart_schema["properties"])
|
||||
|
||||
# Now, split into sections
|
||||
sections: dict[str, list[dict[str, str]]] = {}
|
||||
for param in params:
|
||||
if param["section"] not in sections:
|
||||
sections[param["section"]] = []
|
||||
|
||||
sections[param["section"]].append(param)
|
||||
|
||||
# and order each section
|
||||
for section in sections.values(): # type: ignore
|
||||
section.sort(key=lambda i: i["name"]) # type: ignore
|
||||
|
||||
# and finally order the sections!
|
||||
ordered_sections = []
|
||||
for name in chart_schema["x-docsSectionOrder"]:
|
||||
if name not in sections:
|
||||
raise ValueError(f"Unable to find any parameters for section: {name}")
|
||||
ordered_sections.append({"name": name, "params": sections.pop(name)})
|
||||
|
||||
if sections:
|
||||
raise ValueError(f"Found section(s) which were not in `section_order`: {list(sections.keys())}")
|
||||
|
||||
jinja_contexts = {
|
||||
"params_ctx": {"sections": ordered_sections},
|
||||
"official_download_page": {
|
||||
"base_url": "https://downloads.apache.org/airflow/helm-chart",
|
||||
"closer_lua_url": "https://www.apache.org/dyn/closer.lua/airflow/helm-chart",
|
||||
"package_name": PACKAGE_NAME,
|
||||
"package_version": PACKAGE_VERSION,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# -- Options for sphinx.ext.autodoc --------------------------------------------
|
||||
# See: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html
|
||||
|
||||
# This value contains a list of modules to be mocked up. This is useful when some external dependencies
|
||||
# are not met at build time and break the building process.
|
||||
autodoc_mock_imports = get_autodoc_mock_imports()
|
||||
|
||||
# The default options for autodoc directives. They are applied to all autodoc directives automatically.
|
||||
autodoc_default_options = {"show-inheritance": True, "members": True}
|
||||
|
||||
autodoc_typehints = "description"
|
||||
autodoc_typehints_description_target = "documented"
|
||||
autodoc_typehints_format = "short"
|
||||
|
||||
|
||||
# -- Options for sphinx.ext.intersphinx ----------------------------------------
|
||||
# See: https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html
|
||||
|
||||
# This config value contains names of other projects that should
|
||||
# be linked to in this documentation.
|
||||
# Inventories are only downloaded once by docs/exts/docs_build/fetch_inventories.py.
|
||||
intersphinx_mapping = get_intersphinx_mapping()
|
||||
|
||||
# -- Options for sphinx.ext.viewcode -------------------------------------------
|
||||
# See: https://www.sphinx-doc.org/es/master/usage/extensions/viewcode.html
|
||||
|
||||
# If this is True, viewcode extension will emit viewcode-follow-imported event to resolve the name of
|
||||
# the module by other extensions. The default is True.
|
||||
viewcode_follow_imported_members = True
|
||||
|
||||
# -- Options for sphinx-autoapi ------------------------------------------------
|
||||
# See: https://sphinx-autoapi.readthedocs.io/en/latest/config.html
|
||||
|
||||
# Paths (relative or absolute) to the source code that you wish to generate
|
||||
# your API documentation from.
|
||||
autoapi_dirs = [CHART_ROOT_PATH.as_posix()]
|
||||
|
||||
# A list of patterns to ignore when finding files
|
||||
autoapi_ignore = BASIC_AUTOAPI_IGNORE_PATTERNS
|
||||
|
||||
autoapi_log = logging.getLogger("sphinx.autoapi.mappers.base")
|
||||
autoapi_log.addFilter(filter_autoapi_ignore_entries)
|
||||
|
||||
# Keep the AutoAPI generated files on the filesystem after the run.
|
||||
# Useful for debugging.
|
||||
autoapi_keep_files = True
|
||||
|
||||
# Relative path to output the AutoAPI files into. This can also be used to place the generated documentation
|
||||
# anywhere in your documentation hierarchy.
|
||||
autoapi_root = "_api"
|
||||
|
||||
# Whether to insert the generated documentation into the TOC tree. If this is False, the default AutoAPI
|
||||
# index page is not generated and you will need to include the generated documentation in a
|
||||
# TOC tree entry yourself.
|
||||
autoapi_add_toctree_entry = False
|
||||
|
||||
# By default autoapi will include private members -- we don't want that!
|
||||
autoapi_options = AUTOAPI_OPTIONS
|
||||
|
||||
suppress_warnings = SUPPRESS_WARNINGS
|
||||
|
||||
# -- Options for ext.exampleinclude --------------------------------------------
|
||||
exampleinclude_sourceroot = os.path.abspath("..")
|
||||
|
||||
# -- Options for ext.redirects -------------------------------------------------
|
||||
redirects_file = "redirects.txt"
|
||||
|
||||
# -- Options for sphinxcontrib-spelling ----------------------------------------
|
||||
spelling_word_list_filename = [SPELLING_WORDLIST_PATH.as_posix()]
|
||||
spelling_exclude_patterns = ["changelog.rst"]
|
||||
spelling_ignore_contributor_names = False
|
||||
spelling_ignore_importable_modules = True
|
||||
|
||||
graphviz_output_format = "svg"
|
||||
125
charts/airflow/docs/customizing-labels.rst
Normal file
125
charts/airflow/docs/customizing-labels.rst
Normal file
@ -0,0 +1,125 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Customizing Labels and Annotations for Pods
|
||||
===========================================
|
||||
|
||||
Customizing Pod Labels
|
||||
----------------------
|
||||
|
||||
The Helm Chart allows you to customize labels for your Airflow objects. You can set global labels that apply to all objects and pods defined in the chart, as well as component-specific labels for individual Airflow components.
|
||||
|
||||
Global Labels
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Global labels can be set using the ``labels`` parameter in your values file. These labels will be applied to all Airflow objects and pods defined in the chart:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
labels:
|
||||
environment: production
|
||||
|
||||
Component-Specific Labels
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can also set specific labels for individual Airflow components, which will be merged with the global labels.
|
||||
|
||||
If the same label key exists in both global and component-specific labels, the component-specific value takes precedence (overrides the global value).
|
||||
|
||||
This allows you to customize labels for specific components while still maintaining common global labels across all resources.
|
||||
For example, to add specific labels to different components like scheduler or api-server:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
# Global labels applied to all pods
|
||||
labels:
|
||||
environment: production
|
||||
|
||||
# Scheduler specific labels
|
||||
scheduler:
|
||||
labels:
|
||||
role: scheduler
|
||||
|
||||
# API Server specific labels
|
||||
apiServer:
|
||||
labels:
|
||||
role: ui
|
||||
|
||||
Customizing Pod Annotations
|
||||
---------------------------
|
||||
|
||||
Pod annotations can be customized similarly to labels using ``podAnnotations`` and ``airflowPodAnnotations``.
|
||||
|
||||
Global Pod Annotations
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Global pod annotations can be set using ``airflowPodAnnotations``. These are applied to all Airflow component pods (scheduler, api-server/webserver, triggerer, dag-processor and workers):
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
airflowPodAnnotations:
|
||||
example.com/team: data-platform
|
||||
|
||||
Component-Specific Pod Annotations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Each component also supports its own ``podAnnotations``. Component-specific annotations take precedence over global ones:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
podAnnotations:
|
||||
example.com/component: scheduler
|
||||
|
||||
Templated Pod Annotations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Both ``airflowPodAnnotations`` and ``podAnnotations`` support Helm template expressions. This allows annotations to reference release metadata or compute checksums of chart-managed resources, so that pods automatically restart when those resources change.
|
||||
|
||||
For example, to restart scheduler pods whenever the chart's extra ConfigMaps change:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
extraConfigMaps:
|
||||
my-listener-config:
|
||||
data: |
|
||||
listener.py: ...
|
||||
|
||||
scheduler:
|
||||
podAnnotations:
|
||||
checksum/extra-configmaps: '{{ include (print $.Template.BasePath "/configmaps/extra-configmaps.yaml") . | sha256sum }}'
|
||||
|
||||
You can also reference release metadata:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
airflowPodAnnotations:
|
||||
release: '{{ .Release.Name }}'
|
||||
|
||||
.. note::
|
||||
|
||||
The ``include``/``sha256sum`` pattern only works for resources managed by this chart
|
||||
(e.g., those created via ``extraConfigMaps`` or ``extraSecrets``).
|
||||
For ConfigMaps or Secrets created outside the chart, consider using a tool like
|
||||
`Stakater Reloader <https://github.com/stakater/Reloader>`__ to trigger pod restarts
|
||||
automatically.
|
||||
73
charts/airflow/docs/customizing-workers.rst
Normal file
73
charts/airflow/docs/customizing-workers.rst
Normal file
@ -0,0 +1,73 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Customizing Workers
|
||||
===================
|
||||
|
||||
Both ``CeleryExecutor`` and ``KubernetesExecutor`` workers can be highly customized with the :ref:`workers parameters <parameters:workers>`.
|
||||
For example, to set resources on workers:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
workers:
|
||||
resources:
|
||||
requests:
|
||||
cpu: 1
|
||||
limits:
|
||||
cpu: 1
|
||||
|
||||
One notable exception for ``KubernetesExecutor`` is that the default anti-affinity applied to ``CeleryExecutor`` workers to spread them across nodes
|
||||
is not applied to ``KubernetesExecutor`` workers, as there is no reason to spread out per-task workers.
|
||||
|
||||
Custom ``pod_template_file``
|
||||
----------------------------
|
||||
|
||||
With ``KubernetesExecutor`` or ``CeleryKubernetesExecutor`` you can also provide a complete ``pod_template_file``
|
||||
to fully override default Kubernetes workers configuration. This may be useful if you need different configuration between
|
||||
worker types for ``CeleryKubernetesExecutor`` or if you need to customize something not possible with :ref:`workers parameters <parameters:workers>` alone.
|
||||
|
||||
.. note::
|
||||
|
||||
Some configuration options between Celery and Kubernetes workers can be overwritten by new ``workers.celery`` and ``workers.kubernetes`` sections.
|
||||
Implementation of ``workers.celery`` and ``workers.kubernetes`` is not yet fully completed.
|
||||
|
||||
As an example, let's say you want to set ``priorityClassName`` on your workers:
|
||||
|
||||
.. note::
|
||||
|
||||
The following example is NOT functional, but meant to be illustrative of how you can provide a custom ``pod_template_file``.
|
||||
You're better off starting with the default `pod_template_file`_ instead.
|
||||
|
||||
.. _pod_template_file: https://github.com/apache/airflow/blob/main/chart/files/pod-template-file.kubernetes-helm-yaml
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
podTemplate: |
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: placeholder-name
|
||||
labels:
|
||||
tier: airflow
|
||||
component: worker
|
||||
release: {{ .Release.Name }}
|
||||
spec:
|
||||
priorityClassName: high-priority
|
||||
containers:
|
||||
- name: base
|
||||
121
charts/airflow/docs/extending-the-chart.rst
Normal file
121
charts/airflow/docs/extending-the-chart.rst
Normal file
@ -0,0 +1,121 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Extending the Chart
|
||||
===================
|
||||
|
||||
The Airflow Helm Chart can be easily extended by creating a custom chart which will depend on the Airflow chart.
|
||||
That can be useful in cases where there is a need for custom templates deployment (e.g. maintenance CronJobs),
|
||||
which are not directly related to the Airflow Helm Chart and should not be added to it in the source repository.
|
||||
During installation of custom chart, the Airflow chart will also be installed too.
|
||||
|
||||
You can extend the official Airflow chart by applying the following steps.
|
||||
|
||||
Create your custom Helm Chart
|
||||
-----------------------------
|
||||
|
||||
First, you will need to create you own chart directory. You can do it by running the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm create my-custom-chart
|
||||
|
||||
|
||||
This command will create a directory called ``my-custom-chart`` with the following structure:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
my-custom-chart/
|
||||
├── .helmignore
|
||||
├── Chart.yaml
|
||||
├── values.yaml
|
||||
├── charts/
|
||||
└── templates/
|
||||
└── tests/
|
||||
|
||||
Add Airflow Helm Chart as dependency
|
||||
------------------------------------
|
||||
|
||||
Second, you will need to add the Airflow chart as dependency to the custom chart.
|
||||
This will give you the ability to add your custom templates without the need to modify the Airflow chart itself.
|
||||
In order to add the Airflow chart as a dependency (often called ``subcharts``) to your chart,
|
||||
add the following lines to your ``Chart.yaml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: Chart.yaml
|
||||
|
||||
dependencies:
|
||||
- name: airflow
|
||||
version: 1.11.0
|
||||
repository: https://airflow.apache.org
|
||||
|
||||
.. note::
|
||||
|
||||
Make sure you have already added the Airflow repo locally by running: ``helm repo add apache-airflow https://airflow.apache.org``.
|
||||
|
||||
.. tip::
|
||||
|
||||
You can also use the name of the repo instead of the URL by replacing
|
||||
``https://airflow.apache.org`` with ``"@apache-airflow"``.
|
||||
|
||||
Adding the Airflow chart as a dependency means that it will be deployed together with your custom chart.
|
||||
You can disable the installation of Airflow by adding the ``condition`` field to the ``dependencies`` section
|
||||
like in the example below:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: Chart.yaml
|
||||
|
||||
dependencies:
|
||||
- name: airflow
|
||||
version: 1.11.0
|
||||
repository: https://airflow.apache.org
|
||||
condition: airflow.enabled
|
||||
|
||||
This will check if the value of ``airflow.enabled`` inside your ``values.yaml`` is ``true``.
|
||||
If it is, the Airflow chart will be deployed together with your custom chart.
|
||||
Otherwise, only your templates will be deployed.
|
||||
|
||||
Download the Airflow Helm Chart
|
||||
-------------------------------
|
||||
|
||||
Third, after you have specified the Airflow chart inside the ``dependencies`` section in ``Chart.yaml`` file,
|
||||
you can download it by running the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm dependency build
|
||||
|
||||
.. note::
|
||||
|
||||
Make sure you are inside the directory which contains the ``Chart.yaml`` file.
|
||||
|
||||
The chart will be downloaded and saved inside the ``charts/`` directory.
|
||||
|
||||
Overriding default values
|
||||
-------------------------
|
||||
|
||||
When you add a chart as a subchart to your chart,
|
||||
you have the ability to override the default values of the subchart in your ``values.yaml``.
|
||||
This is useful when your chart needs a specific configuration for your custom chart.
|
||||
E.g. if you want that the Airflow chart be installed with the ``KubernetesExecutor``,
|
||||
you can do it by adding the following section to your ``values.yaml``:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
airflow:
|
||||
executor: KubernetesExecutor
|
||||
28
charts/airflow/docs/img/helm-logo.svg
Normal file
28
charts/airflow/docs/img/helm-logo.svg
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="351" viewBox="0 0 304 351" width="304">
|
||||
<mask id="a" fill="#fff">
|
||||
<path d="m0 0h313.303155v159.864865h-313.303155z" fill="#fff" fill-rule="evenodd"/>
|
||||
</mask>
|
||||
<mask id="b" fill="#fff">
|
||||
<path d="m0 0h313.303155v159.864865h-313.303155z" fill="#fff" fill-rule="evenodd"/>
|
||||
</mask>
|
||||
<g fill="none" fill-rule="evenodd" transform="translate(-11 -51)">
|
||||
<path d="m11.6785714 189h19.7858357v26.789h23.9037v-26.789h19.7858358v75.25h-19.7858358v-28.695333h-23.9037v28.695333h-19.7858357zm86.1738429 75.25v-75.25h46.8030427v16.354333h-27.017207v12.240667h23.9037v16.655333h-23.9037v13.846h27.017207v16.153667zm68.4971567 0v-75.25h19.785836v55.384h27.117643v19.866zm77.536372-75.25 30.733328 27.892667 30.632893-27.892667h8.938779v75.25h-19.886272v-38.628333l-19.6854 17.959666-19.785835-17.859333v38.528h-19.886272v-75.25z" fill="#0f1689"/>
|
||||
<g transform="matrix(1 0 0 -1 11.958136 455)">
|
||||
<g fill="#0f1689" mask="url(#a)">
|
||||
<path d="m203.460676 95.6875425c6.93631 0 12.559301-14.8092194 12.559301-33.0773172s-5.622991-33.0773172-12.559301-33.0773172c-6.936311 0-12.559301 14.8092194-12.559301 33.0773172s5.62299 33.0773172 12.559301 33.0773172z" transform="matrix(.81915204 .57357644 -.57357644 .81915204 111.870091 -51.706556)"/>
|
||||
<path d="m30.1423223 95.6875425c6.9363104 0 12.559301-14.8092194 12.559301-33.0773172s-5.6229906-33.0773172-12.559301-33.0773172-12.5593009 14.8092194-12.5593009 33.0773172 5.6229905 33.0773172 12.5593009 33.0773172z" transform="matrix(-.81915204 .57357644 .57357644 .81915204 58.084611 47.704768)"/>
|
||||
<path d="m116.732815 66.2752676c6.936311 0 12.559301-14.8092193 12.559301-33.0773172 0-18.2680978-5.62299-33.07731713-12.559301-33.07731713-6.93631 0-12.559301 14.80921933-12.559301 33.07731713 0 18.2680979 5.622991 33.0773172 12.559301 33.0773172z" transform="matrix(-1 0 0 1 272.628524 53.670762)"/>
|
||||
</g>
|
||||
<path d="m251.467006 173.099849c-20.230076-33.609969-56.889565-56.067908-98.755776-56.067908-40.720798 0-76.5158766 21.245901-97.0586959 53.334588m2.1981107 129.169534c20.8403036 30.232701 55.5559042 50.026591 94.8605852 50.026591 39.376099 0 74.146424-19.865887 94.974049-50.191495" mask="url(#a)" stroke="#0f1689" stroke-width="20"/>
|
||||
</g>
|
||||
<g transform="translate(11.958136)">
|
||||
<g fill="#0f1689" mask="url(#b)">
|
||||
<path d="m203.460676 95.6875425c6.93631 0 12.559301-14.8092194 12.559301-33.0773172s-5.622991-33.0773172-12.559301-33.0773172c-6.936311 0-12.559301 14.8092194-12.559301 33.0773172s5.62299 33.0773172 12.559301 33.0773172z" transform="matrix(.81915204 .57357644 -.57357644 .81915204 111.870091 -54.166016)"/>
|
||||
<path d="m30.1423223 95.6875425c6.9363104 0 12.559301-14.8092194 12.559301-33.0773172s-5.6229906-33.0773172-12.559301-33.0773172-12.5593009 14.8092194-12.5593009 33.0773172 5.6229905 33.0773172 12.5593009 33.0773172z" transform="matrix(-.81915204 .57357644 .57357644 .81915204 58.084611 45.245308)"/>
|
||||
<path d="m116.732815 66.2752676c6.936311 0 12.559301-14.8092193 12.559301-33.0773172 0-18.2680978-5.62299-33.07731713-12.559301-33.07731713-6.93631 0-12.559301 14.80921933-12.559301 33.07731713 0 18.2680979 5.622991 33.0773172 12.559301 33.0773172z" transform="matrix(-1 0 0 1 272.628524 51.211302)"/>
|
||||
</g>
|
||||
<path d="m251.467006 170.64039c-20.230076-33.609969-56.889565-56.067908-98.755776-56.067908-40.720798 0-76.5158766 21.2459-97.0586959 53.334587m2.1981107 129.169534c20.8403036 30.232702 55.5559042 50.026591 94.8605852 50.026591 39.376099 0 74.146424-19.865886 94.974049-50.191494" mask="url(#b)" stroke="#0f1689" stroke-width="20"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
240
charts/airflow/docs/index.rst
Normal file
240
charts/airflow/docs/index.rst
Normal file
@ -0,0 +1,240 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
.. image:: /img/helm-logo.svg
|
||||
:width: 100
|
||||
:class: no-scaled-link
|
||||
|
||||
Helm Chart for Apache Airflow
|
||||
=============================
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
Home <self>
|
||||
quick-start
|
||||
airflow-configuration
|
||||
adding-connections-and-variables
|
||||
manage-dag-files
|
||||
manage-logs
|
||||
setting-resources-for-containers
|
||||
keda
|
||||
using-additional-containers
|
||||
customizing-workers
|
||||
customizing-labels
|
||||
Installing from sources<installing-helm-chart-from-sources>
|
||||
Extending the Chart<extending-the-chart>
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
:caption: Guides
|
||||
|
||||
production-guide
|
||||
service-account-token-examples
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
:caption: References
|
||||
|
||||
Parameters <parameters-ref>
|
||||
release_notes
|
||||
|
||||
|
||||
This chart bootstraps an `Airflow <https://airflow.apache.org>`__
|
||||
deployment on a `Kubernetes <http://kubernetes.io>`__ cluster using the
|
||||
`Helm <https://helm.sh>`__ package manager.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
- Kubernetes 1.30+ cluster
|
||||
- Helm 3.10+
|
||||
- PV provisioner support in the underlying infrastructure (optionally)
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Supported executors (all Airflow versions): ``LocalExecutor``, ``CeleryExecutor``, ``KubernetesExecutor``
|
||||
* Supported hybrid static executors (Airflow version ``2.11.X``): ``LocalKubernetesExecutor``, ``CeleryKubernetesExecutor``
|
||||
* Supported multiple Executors (``2.11+``)
|
||||
* Supported AWS executors with AWS provider version ``8.21.0+``:
|
||||
|
||||
* ``airflow.providers.amazon.aws.executors.batch.AwsBatchExecutor``
|
||||
* ``airflow.providers.amazon.aws.executors.ecs.AwsEcsExecutor``
|
||||
|
||||
* Supported AWS executors with AWS provider version ``9.9.0+``:
|
||||
|
||||
* ``airflow.providers.amazon.aws.executors.aws_lambda.lambda_executor.AwsLambdaExecutor``
|
||||
|
||||
* Supported Edge executor with edge3 provider version ``1.0.0+``:
|
||||
|
||||
* ``airflow.providers.edge3.executors.EdgeExecutor``
|
||||
|
||||
* Supported Airflow version: ``2.11+``, ``3.0+``
|
||||
* Supported database backend: ``PostgreSQL``, ``MySQL``
|
||||
* Autoscaling for ``CeleryExecutor`` provided by KEDA
|
||||
* ``PostgreSQL`` and ``PgBouncer`` with a battle-tested configuration
|
||||
* Monitoring:
|
||||
|
||||
* StatsD/Prometheus metrics for Airflow
|
||||
* Prometheus metrics for PgBouncer
|
||||
* Flower
|
||||
|
||||
* Automatic database migration after a new deployment
|
||||
* Administrator account creation during deployment
|
||||
* Kerberos secure configuration
|
||||
* One-command deployment for any type of executor. You don't need to provide other services e.g. Redis/Database to test the Airflow
|
||||
|
||||
.. _helm_chart_install:
|
||||
|
||||
Installing the Helm Chart
|
||||
-------------------------
|
||||
|
||||
To install this chart using Helm 3, run the following commands:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm repo add apache-airflow https://airflow.apache.org
|
||||
helm upgrade --install airflow apache-airflow/airflow --namespace airflow --create-namespace
|
||||
|
||||
The command deploys Airflow on the Kubernetes cluster with the default configuration in the airflow namespace.
|
||||
The :doc:`parameters-ref` section lists the parameters that can be configured during installation.
|
||||
|
||||
|
||||
.. tip::
|
||||
|
||||
List all releases using ``helm list``.
|
||||
|
||||
Upgrading the deployed Helm Chart
|
||||
---------------------------------
|
||||
|
||||
To upgrade the chart with the release name ``airflow``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade airflow apache-airflow/airflow --namespace airflow
|
||||
|
||||
.. note::
|
||||
|
||||
To upgrade to a new version of the chart, run ``helm repo update`` first.
|
||||
|
||||
.. tip::
|
||||
|
||||
By setting ``--install`` flag on the ``helm upgrade`` command, Helm Chart will be installed if it wasn't deployed before.
|
||||
|
||||
Uninstalling the deployed Helm Chart
|
||||
------------------------------------
|
||||
|
||||
To uninstall/delete the ``airflow`` deployment:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm delete airflow --namespace airflow
|
||||
|
||||
The command removes all the Kubernetes components associated with the chart and deletes the release.
|
||||
|
||||
.. note::
|
||||
|
||||
Some Kubernetes resources created by the chart `helm hooks <https://helm.sh/docs/topics/charts_hooks/#hook-resources-are-not-managed-with-corresponding-releases>`__ might be left in the namespace after executing ``helm uninstall``.
|
||||
|
||||
Installing the Helm Chart with Argo CD, Flux, Rancher or Terraform
|
||||
------------------------------------------------------------------
|
||||
|
||||
When installing the chart using Argo CD, Flux, Rancher or Terraform, you **must** set the four following values, or your application
|
||||
will not start as the migrations will not be run:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
createUserJob:
|
||||
useHelmHooks: false
|
||||
applyCustomEnv: false
|
||||
migrateDatabaseJob:
|
||||
useHelmHooks: false
|
||||
applyCustomEnv: false
|
||||
|
||||
This is so these CI/CD services can perform updates without issues and preserve the immutability of Kubernetes Job manifests.
|
||||
|
||||
.. note::
|
||||
|
||||
This applies to the chart installation with usage of ``--wait`` flag in ``helm install`` or ``helm upgrade`` command.
|
||||
|
||||
.. note::
|
||||
|
||||
While deploying this Helm Chart with Argo, you might encounter issues with database migrations not running automatically on upgrade.
|
||||
|
||||
To run database migrations with Argo CD automatically, you will need to add:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
migrateDatabaseJob:
|
||||
jobAnnotations:
|
||||
"argocd.argoproj.io/hook": Sync
|
||||
|
||||
This will run database migrations every time there is a ``Sync`` event in Argo CD. While it is not ideal to run the migrations on every sync, it is a trade-off that allows them to be run automatically.
|
||||
|
||||
If you use the ``CeleryExecutor`` or ``CeleryKubernetesExecutor`` with the built-in Redis, it is recommended that you set up a static Redis password either by supplying ``redis.passwordSecretName`` and ``data.brokerUrlSecretName`` or ``redis.password``.
|
||||
|
||||
.. note::
|
||||
|
||||
By default, Helm hooks are also enabled for ``extraSecrets`` or ``extraConfigMaps``. When using the above CI/CD tools, you might encounter issues due to these default hooks.
|
||||
|
||||
To avoid potential problems, it is recommended to disable these hooks by setting ``useHelmHooks=false`` as shown in the following examples:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
extraSecrets:
|
||||
'{{ .Release.Name }}-example':
|
||||
useHelmHooks: false
|
||||
data: |
|
||||
AIRFLOW_VAR_HELLO_MESSAGE: "Hi!"
|
||||
|
||||
extraConfigMaps:
|
||||
'{{ .Release.Name }}-example':
|
||||
useHelmHooks: false
|
||||
data: |
|
||||
AIRFLOW_VAR_HELLO_MESSAGE: "Hi!"
|
||||
|
||||
Naming Conventions
|
||||
------------------
|
||||
|
||||
For new installations it is highly recommended to start using standard naming conventions.
|
||||
It is not enabled by default as this may cause unexpected behaviours on existing installations. However you can enable it using ``useStandardNaming``:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
useStandardNaming: true
|
||||
|
||||
For existing installations, all your resources will be recreated with a new name and helm will delete previous resources.
|
||||
|
||||
This won't delete existing PVCs for logs used by StatefulSets/Deployments, but it will recreate them with brand new PVCs.
|
||||
If you do want to preserve logs history you'll need to manually copy the data of these volumes into the new volumes after
|
||||
deployment. Depending on what storage backend/class you're using, this procedure may vary. If you don't mind starting
|
||||
with fresh logs/redis volumes, you can delete the old persistent volume claims, for example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl delete pvc -n airflow logs-gta-triggerer-0
|
||||
kubectl delete pvc -n airflow logs-gta-worker-0
|
||||
kubectl delete pvc -n airflow redis-db-gta-redis-0
|
||||
|
||||
.. note::
|
||||
|
||||
If you do not change ``useStandardNaming`` or ``fullnameOverride`` after upgrade, you can proceed as usual and no unexpected behaviours will be presented.
|
||||
128
charts/airflow/docs/installing-helm-chart-from-sources.rst
Normal file
128
charts/airflow/docs/installing-helm-chart-from-sources.rst
Normal file
@ -0,0 +1,128 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Installing Helm Chart from sources
|
||||
==================================
|
||||
|
||||
Released packages
|
||||
-----------------
|
||||
|
||||
.. jinja:: official_download_page
|
||||
|
||||
This page describes downloading and verifying ``Apache Airflow Official Helm Chart`` version
|
||||
``{{ package_version }}`` using officially released source packages. You can also install the chart
|
||||
directly from the ``airflow.apache.org`` repo as described in :ref:`helm_chart_install`.
|
||||
You can choose different version of the chart by selecting different version from the drop-down at
|
||||
the top-left of the page.
|
||||
|
||||
|
||||
The sources and packages released are the "official" sources of installation that you can use if
|
||||
you want to verify the origin of the packages and want to verify checksums and signatures of the packages.
|
||||
The packages are available via the
|
||||
`Official Apache Software Foundations Downloads <https://dlcdn.apache.org/>`_
|
||||
|
||||
The downloads are available at:
|
||||
|
||||
.. jinja:: official_download_page
|
||||
|
||||
* `Sources package <{{ closer_lua_url }}/{{ package_version }}/airflow-chart-{{ package_version }}-source.tar.gz>`__ (`asc <{{ base_url }}/{{ package_version }}/airflow-chart-{{ package_version }}-source.tar.gz.asc>`__, `sha512 <{{ base_url }}/{{ package_version }}/airflow-chart-{{ package_version }}-source.tar.gz.sha512>`__)
|
||||
* `Installable package <{{ closer_lua_url }}/{{ package_version }}/airflow-{{ package_version }}.tgz>`__ (`asc <{{ base_url }}/{{ package_version }}/airflow-{{ package_version }}.tgz.asc>`__, `sha512 <{{ base_url }}/{{ package_version }}/airflow-{{ package_version }}.tgz.sha512>`__)
|
||||
|
||||
If you want to install from the source code, you can download from the sources link above, which will contain
|
||||
an ``INSTALL`` file containing details on how you can build and install the chart.
|
||||
|
||||
Release integrity
|
||||
-----------------
|
||||
|
||||
`PGP signatures KEYS <https://downloads.apache.org/airflow/KEYS>`_
|
||||
|
||||
It is essential that you verify the integrity of the downloaded files using the PGP or SHA signatures.
|
||||
The PGP signatures can be verified using GPG or PGP. Please download the KEYS as well as the asc
|
||||
signature files for relevant distribution. It is recommended to get these files from the
|
||||
main distribution directory and not from the mirrors.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
gpg -i KEYS
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pgpk -a KEYS
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pgp -ka KEYS
|
||||
|
||||
To verify the binaries/sources you can download the relevant asc files for it from main
|
||||
distribution directory and follow the below guide.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
gpg --verify airflow-********.asc airflow-*********
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pgpv airflow-********.asc
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pgp airflow-********.asc
|
||||
|
||||
Example:
|
||||
|
||||
.. jinja:: official_download_page
|
||||
|
||||
.. code-block:: console
|
||||
:substitutions:
|
||||
|
||||
$ gpg --verify airflow-{{ package_version }}.tgz.asc airflow-{{ package_version }}.tgz
|
||||
gpg: Signature made Sat 11 Sep 12:49:54 2021 BST
|
||||
gpg: using RSA key CDE15C6E4D3A8EC4ECF4BA4B6674E08AD7DE406F
|
||||
gpg: issuer "kaxilnaik@apache.org"
|
||||
gpg: Good signature from "Kaxil Naik <kaxilnaik@apache.org>" [unknown]
|
||||
gpg: aka "Kaxil Naik <kaxilnaik@gmail.com>" [unknown]
|
||||
gpg: WARNING: The key's User ID is not certified with a trusted signature!
|
||||
gpg: There is no indication that the signature belongs to the owner.
|
||||
Primary key fingerprint: CDE1 5C6E 4D3A 8EC4 ECF4 BA4B 6674 E08A D7DE 406F
|
||||
|
||||
The "Good signature from ..." is indication that the signatures are correct.
|
||||
Do not worry about the "not certified with a trusted signature" warning. Most of the certificates used
|
||||
by release managers are self signed, that's why you get this warning. By importing the server in the
|
||||
previous step and importing it via ID from ``KEYS`` page, you know that this is a valid Key already.
|
||||
|
||||
For SHA512 sum check, download the relevant ``sha512`` and run the following:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
shasum -a 512 airflow-******** | diff - airflow-********.sha512
|
||||
|
||||
The ``SHASUM`` of the file should match the one provided in ``.sha512`` file.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: bash
|
||||
:substitutions:
|
||||
|
||||
shasum -a 512 airflow-{{ package_version }}.tgz | diff - airflow-{{ package_version }}.tgz.sha512
|
||||
123
charts/airflow/docs/keda.rst
Normal file
123
charts/airflow/docs/keda.rst
Normal file
@ -0,0 +1,123 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Autoscaling with KEDA
|
||||
=====================
|
||||
|
||||
KEDA stands for Kubernetes Event Driven Autoscaling.
|
||||
`KEDA <https://github.com/kedacore/keda>`__ is a custom controller that
|
||||
allows users to create custom bindings to the Kubernetes `Horizontal Pod
|
||||
Autoscaler <https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/>`__.
|
||||
The autoscaler will adjust the number of active Celery workers based on the number
|
||||
of tasks in ``queued`` or ``running`` state.
|
||||
|
||||
One advantage of KEDA is that it allows you to scale your application to/from 0 workers, meaning no workers are idle when there are no tasks.
|
||||
|
||||
KEDA Installation and usage
|
||||
---------------------------
|
||||
|
||||
To install KEDA in your Kubernetes cluster, run the following commands:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm repo add kedacore https://kedacore.github.io/charts
|
||||
helm repo update
|
||||
kubectl create namespace keda
|
||||
helm install keda kedacore/keda \
|
||||
--namespace keda \
|
||||
--version "v2.0.0"
|
||||
|
||||
To enable KEDA for the Airflow instance, it has to be enabled by setting ``workers.celery.keda.enabled=true``
|
||||
in your Helm command or in the ``values.yaml`` like:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl create namespace airflow
|
||||
helm repo add apache-airflow https://airflow.apache.org
|
||||
helm install airflow apache-airflow/airflow \
|
||||
--namespace airflow \
|
||||
--set executor=CeleryExecutor \
|
||||
--set workers.celery.keda.enabled=true
|
||||
|
||||
.. note::
|
||||
|
||||
Make sure ``values.yaml`` shows that either KEDA or HPA is enabled, but not both. It is recommended not
|
||||
to use both KEDA and HPA to scale the same workload. They will compete with each other resulting in odd scaling behavior.
|
||||
|
||||
After installation, the KEDA ``ScaledObject`` and an ``HPA`` will be created in the Airflow namespace.
|
||||
|
||||
In the default configuration, KEDA will derive the desired number of Celery workers by querying Airflow metadata database with following SQL statement:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
SELECT
|
||||
ceil(COUNT(*)::decimal / {{ .Values.config.celery.worker_concurrency }})
|
||||
FROM
|
||||
task_instance
|
||||
WHERE
|
||||
(state='running' OR state='queued')
|
||||
AND queue IN <queue names>
|
||||
|
||||
where ``<queue names>`` is a list of queue names used by
|
||||
`Celery worker queues <https://airflow.apache.org/docs/apache-airflow-providers-celery/stable/celery_executor.html#queues>`_
|
||||
mechanism (with default configuration it has one element ``default``).
|
||||
|
||||
.. note::
|
||||
|
||||
Set Celery worker concurrency through the Helm Chart value
|
||||
``config.celery.worker_concurrency`` (e.g. instead of airflow.cfg or
|
||||
environment variables), so that the KEDA trigger will be consistent with
|
||||
the worker concurrency setting.
|
||||
|
||||
Triggers (aka Scalers)
|
||||
----------------------
|
||||
|
||||
Triggers refer to the metrics (or formulae) that KEDA should refer to when scaling workers.
|
||||
|
||||
It is recommended to use multiple triggers within a ScaledObject, rather than creating different objects for different triggers.
|
||||
This keeps all your rules and formulae in one place, and it avoids multiple ScaledObjects being created by the same workload.
|
||||
|
||||
ScaledObject
|
||||
------------
|
||||
|
||||
To configure KEDA's triggers and scaling behaviors, you need to create a ScaledObject. Below ScaledObject parameters:
|
||||
|
||||
* ``cooldownPeriod`` specifies the number of seconds to wait before downscaling to 0 workers, does not apply to downscaling to n workers while n >= 1.
|
||||
* ``idleReplicaCount`` can be set to any number less than ``minReplicaCount``, but it must be set to 0, otherwise KEDA will not work. Change ``minReplicaCount`` to n > 0 if you need idle workers.
|
||||
|
||||
Triggerers value ``targetQueryValue`` is used as ``TargetValue`` of workers, which must be between ScaledObject ``minReplicaCount`` and ``maxReplicaCount`` values.
|
||||
|
||||
.. note::
|
||||
|
||||
To avoid strange behavior, best practice is to set ``cooldownPeriod`` to an integer slightly larger than ``terminationGracePeriodSeconds`` so that your cluster does not downscale to 0 workers before cleanup is finished.
|
||||
|
||||
Metrics
|
||||
-------
|
||||
|
||||
The HPA controller, refreshes metrics defined in triggers every ``--horizontal-pod-autoscaler-sync-period`` and the values are routed to
|
||||
KEDA Metrics Server directly. To reduce the load on the KEDA Scaler, you can set ``useCachedMetrics`` to true, to enabling reading metrics
|
||||
from cache first. Cache is updated periodically every ``pollingInterval``.
|
||||
|
||||
.. note::
|
||||
|
||||
When number of workers = 0, KEDA will still poll for metrics using ``pollingInterval``.
|
||||
When number of workers >= 1, both KEDA and the HPA will poll your defined triggers.
|
||||
|
||||
KEDA offers two ``metricTypes`` that provide more granular scaling control than the standard HPA ``Target`` metric:
|
||||
|
||||
* AverageValue (default) controls a per-worker average.
|
||||
* Value controls total system load.
|
||||
261
charts/airflow/docs/manage-dag-files.rst
Normal file
261
charts/airflow/docs/manage-dag-files.rst
Normal file
@ -0,0 +1,261 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
|
||||
Manage Dag files
|
||||
================
|
||||
|
||||
When you create new or modify existing Dag files, it is necessary to deploy them into the environment. This section will describe some basic techniques which you can use.
|
||||
|
||||
Bake Dags in docker image
|
||||
-------------------------
|
||||
|
||||
With this approach, you include your Dag files and related code in the Airflow image.
|
||||
|
||||
This method requires redeploying the services in the helm chart with the new docker image in order to deploy the new Dag code. This can work well particularly if Dag code is not expected to change frequently.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker build --pull --tag "my-company/airflow:8a0da78" . -f - <<EOF
|
||||
FROM apache/airflow
|
||||
|
||||
COPY ./dags/ \${AIRFLOW_HOME}/dags/
|
||||
|
||||
EOF
|
||||
|
||||
Then publish it in the accessible registry:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker push my-company/airflow:8a0da78
|
||||
|
||||
Finally, update the Airflow pods with that image:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set images.airflow.repository=my-company/airflow \
|
||||
--set images.airflow.tag=8a0da78
|
||||
|
||||
If you are deploying an image with a constant tag, you need to make sure that the image is pulled every time as e.g. presented in the code below:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set images.airflow.repository=my-company/airflow \
|
||||
--set images.airflow.tag=8a0da78 \
|
||||
--set images.airflow.pullPolicy=Always \
|
||||
--set airflowPodAnnotations.random=r$(uuidgen)
|
||||
|
||||
The randomly generated pod annotation will ensure that pods are refreshed on helm upgrade.
|
||||
|
||||
.. warning::
|
||||
|
||||
Using constant tag should be used only for testing/development purpose. It is a bad practice to use the same tag as you'll lose the history of your code.
|
||||
|
||||
If you are deploying an image from a private repository, you need to create a secret, e.g. ``gitlab-registry-credentials`` (refer `Pull an Image from a Private Registry <https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/>`_ for details), and specify it using ``--set registry.secretName`` like:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set images.airflow.repository=my-company/airflow \
|
||||
--set images.airflow.tag=8a0da78 \
|
||||
--set images.airflow.pullPolicy=Always \
|
||||
--set registry.secretName=gitlab-registry-credentials
|
||||
|
||||
Using Git-Sync
|
||||
--------------
|
||||
|
||||
Mounting Dags using Git-Sync sidecar with persistence enabled
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This option will use a Persistent Volume Claim with ``ReadWriteMany`` access mode.
|
||||
The dag-processor pod (if standalone dag-processor is disabled it will be scheduler pod) will sync Dags from
|
||||
a git repository onto the PVC every configured number of seconds. The other pods will read the synced Dags.
|
||||
Not all volume plugins have support for ``ReadWriteMany`` access mode.
|
||||
Refer `Persistent Volume Access Modes <https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes>`__
|
||||
for details.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set dags.persistence.enabled=true \
|
||||
--set dags.gitSync.enabled=true
|
||||
# You can also override the other persistence or gitSync values
|
||||
# by setting the dags.persistence.* and dags.gitSync.* values
|
||||
# Please refer to values.yaml for details
|
||||
|
||||
Mounting Dags using Git-Sync sidecar without persistence
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This option will always use running Git-Sync sidecar on every dag-processor, worker and triggerer pods
|
||||
(In Airflow 2.11, if separate dag-processor is not enabled, the Git-Sync sidecar will run on scheduler for Dag parsing as well).
|
||||
|
||||
The Git-Sync sidecar containers will sync Dags from a git repository every configured number of
|
||||
seconds. If you are using the ``KubernetesExecutor``, Git-Sync will run as an init container on your worker pods.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set dags.persistence.enabled=false \
|
||||
--set dags.gitSync.enabled=true
|
||||
# You can also override the other gitSync values
|
||||
# by setting the dags.gitSync.* values
|
||||
# Refer values.yaml for details
|
||||
|
||||
Notes for combining Git-Sync and persistence
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
While using git-sync and persistence for Dags is possible, it is generally not recommended unless the
|
||||
Deployment Manager carefully considered the trade-offs it brings. There are cases when git-sync without
|
||||
persistence has other trade-offs (for example delays in synchronization of Dags vs. rate-limiting of Git
|
||||
servers) that can often be mitigated (for example by sending signals to git-sync containers via web-hooks
|
||||
when new commits are pushed to the repository), but there might be cases where you still might want to choose
|
||||
git-sync and persistence together.
|
||||
|
||||
Git-sync solution is primarily designed to be used for local, POSIX-compliant volumes to checkout Git
|
||||
repositories. Part of the process of commits synchronization from git-sync involves checking out
|
||||
new version of files in a freshly created folder and swapping symbolic links to the new folder, after the
|
||||
checkout is complete. This is done to ensure that the whole Dags folder is consistent at all times. The way
|
||||
git-sync works with symbolic-link swaps, makes sure that Parsing the Dags always work on a consistent
|
||||
(single-commit-based) set of files in the whole Dag folder.
|
||||
|
||||
This approach, however might have undesirable side effects when the folder that git-sync works on is not
|
||||
a local volume, but is a persistent volume (so effectively a networked, distributed volume). Depending on
|
||||
the technology behind the persistent volumes might handle git-sync approach differently and with non-obvious
|
||||
consequences. There are a lot of persistence solutions available for various K8S installations and each of
|
||||
them has different characteristics, so you need to carefully test and monitor your filesystem to make sure
|
||||
those undesired side effects do not affect you. Those effects might change over time or depend on parameters
|
||||
like how often the files are being scanned by the Dag Processor, the number and complexity of your
|
||||
Dags, how remote and how distributed your persistent volumes are, how many IOPS you allocate for some of
|
||||
the filesystem (usually highly paid feature of such filesystems is how many IOPS you can get) and many other
|
||||
factors.
|
||||
|
||||
The way git-sync works with symbolic links swapping generally causes a linear growth of the throughput and
|
||||
potential delays in synchronization. The networking traffic from checkouts comes in bursts and the bursts
|
||||
are linearly proportional to the number and size of files you have in the repository, makes it vulnerable
|
||||
to pretty sudden and unexpected demand increase. Most of the persistence solution work "good enough" for
|
||||
smaller/shorter burst of traffic, but when they outgrow certain thresholds, you need to upgrade the
|
||||
networking to a much more capable and expensive options. This is difficult to control and impossible to
|
||||
mitigate, so you might be suddenly faced with situation to pay a lot more for IOPS/persistence option to
|
||||
keep your Dags sufficiently synchronized to avoid inconsistencies and delays in synchronization.
|
||||
|
||||
The side-effects that you might observe are:
|
||||
|
||||
* bursts of networking/communication at the moment when new commit is checked out, because of the quick
|
||||
succession of deleting old files, creating new files, symbolic link swapping.
|
||||
* temporary lack of consistency between files in Dag folders while Dags are being synced, because of delays
|
||||
in distributing changes to individual files for various nodes in the cluster.
|
||||
* visible drops of performance of the persistence solution when your Dag number grows, drops that might
|
||||
amplify the side effects described above.
|
||||
* some of persistence solutions might lack filesystem functionality that git-sync needs to perform the sync
|
||||
(for example changing permissions or creating symbolic links). While those can often be mitigated, it is
|
||||
only recommended to use git-sync with fully POSIX-filesystem compliant persistence filesystems.
|
||||
|
||||
General recommendation is to use git-sync with local volumes only, and if you want to it with persistence, you
|
||||
need to make sure that the persistence solution you use is POSIX-compliant and you monitor the side-effects
|
||||
it might have.
|
||||
|
||||
Synchronizing multiple Git repositories with Git-Sync
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Airflow git-sync integration in the Helm Chart does not allow synchronization of multiple repositories at
|
||||
the same time. The Dag folder must come from single git repository. However, it is possible
|
||||
to use `submodules <https://git-scm.com/book/en/v2/Git-Tools-Submodules>`_ to create an "umbrella" repository
|
||||
that you can use to bring a number of git repositories checked out together (with ``--submodules recursive``
|
||||
option). There are success stories of Airflow users using such approach with 100s of repositories put
|
||||
together as submodules via such "umbrella" repo approach. When you choose this solution, you need to work out
|
||||
the way how to link the submodules, when to update the umbrella repo when "submodule" repository change and
|
||||
work out versioning approach and automate it. This might be as simple as always using latest versions of all
|
||||
the submodule repositories, or as complex as managing versioning of shared libraries, Dags and code across
|
||||
multiple teams and doing that following your release process.
|
||||
|
||||
An example of such complex approach can found in this
|
||||
`Manage Dags at scale <https://s.apache.org/airflow-manage-dags-at-scale>`_ presentation from the Airflow
|
||||
Summit.
|
||||
|
||||
Mounting Dags from an externally populated PVC
|
||||
----------------------------------------------
|
||||
|
||||
In this approach, Airflow will read the Dags from a PVC which has ``ReadOnlyMany`` or ``ReadWriteMany`` access mode.
|
||||
You will have to ensure that the PVC is populated/updated with the required Dags (this won't be handled by the chart).
|
||||
You can pass the name of the volume claim to the chart by using ``dags.persistence.existingClaim`` parameter:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set dags.persistence.enabled=true \
|
||||
--set dags.persistence.existingClaim=my-volume-claim \
|
||||
--set dags.gitSync.enabled=false
|
||||
|
||||
Mounting Dags from a private GitHub repo using Git-Sync sidecar
|
||||
---------------------------------------------------------------
|
||||
|
||||
To configure mounting Dags from private GitHub repository, follow below steps:
|
||||
|
||||
1. Create a private repo on GitHub if you have not created one already.
|
||||
2. Then create your ssh keys:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
|
||||
|
||||
3. Add the public key to your private repo under ``Settings > Deploy keys``.
|
||||
4. Convert the private ssh key to a base64 string and save it's value.
|
||||
|
||||
.. note::
|
||||
|
||||
You can convert the private ssh key file like:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
base64 <my-private-ssh-key> -w 0 > temp.txt
|
||||
|
||||
Then copy the string from the ``temp.txt`` file.
|
||||
|
||||
The converted to base64 string will be used in the ``override-values.yaml`` file.
|
||||
|
||||
5. Create a yaml file called ``override-values.yaml`` to override default values, instead of using ``--set``:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: override-values.yaml
|
||||
|
||||
dags:
|
||||
gitSync:
|
||||
enabled: true
|
||||
repo: git@github.com:<username>/<private-repo-name>.git
|
||||
branch: <branch-name>
|
||||
subPath: ""
|
||||
sshKeySecret: airflow-ssh-secret
|
||||
extraSecrets:
|
||||
airflow-ssh-secret:
|
||||
data: |
|
||||
gitSshKey: '<base64-converted-ssh-private-key>'
|
||||
|
||||
Copied base64 string should be as a value for the ``gitSshKey`` key.
|
||||
|
||||
6. Finally, from the context of your Airflow Helm chart directory, install Airflow:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow -f override-values.yaml
|
||||
|
||||
If you have done everything correctly, Git-Sync will pick up the changes you make to the Dags
|
||||
in your private GitHub repo.
|
||||
|
||||
You should take this a step further and set ``dags.gitSync.knownHosts``, so you are not susceptible to man-in-the-middle
|
||||
attacks. This process is documented in the :ref:`production guide <production-guide:knownhosts>`.
|
||||
100
charts/airflow/docs/manage-logs.rst
Normal file
100
charts/airflow/docs/manage-logs.rst
Normal file
@ -0,0 +1,100 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Manage logs
|
||||
===========
|
||||
|
||||
You have a number of options when it comes to managing your Airflow logs.
|
||||
|
||||
No persistence
|
||||
--------------
|
||||
|
||||
With this option, Airflow will log locally to each pod. As such, the logs will only be available during the lifetime of the pod.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set logs.persistence.enabled=false
|
||||
|
||||
.. note::
|
||||
|
||||
Setting the ``workers.celery.persistence.enabled=false`` is required when ``CeleryExecutor`` is used.
|
||||
|
||||
Celery worker log persistence
|
||||
-----------------------------
|
||||
|
||||
If you are using ``CeleryExecutor``, workers persist logs by default to a volume claim created with a ``volumeClaimTemplate``.
|
||||
|
||||
You can modify the template:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set executor=CeleryExecutor \
|
||||
--set workers.celery.persistence.size=10Gi
|
||||
|
||||
.. note::
|
||||
|
||||
With this option only task logs are persisted, unlike when log persistence is enabled which will also persist scheduler logs.
|
||||
|
||||
Log persistence enabled
|
||||
-----------------------
|
||||
|
||||
This option will provision a ``PersistentVolumeClaim`` with an access mode of ``ReadWriteMany``. Each component of Airflow will
|
||||
then log onto the same volume.
|
||||
|
||||
Not all volume plugins have support for ``ReadWriteMany`` access mode.
|
||||
Refer `Persistent Volume Access Modes <https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes>`__
|
||||
for details.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set logs.persistence.enabled=true
|
||||
# You can also override the other persistence
|
||||
# by setting the logs.persistence.* values
|
||||
# Please refer to values.yaml for details
|
||||
|
||||
Externally provisioned PVC
|
||||
--------------------------
|
||||
|
||||
In this approach, Airflow will log to an existing ``ReadWriteMany`` PVC. You pass in the name of the volume claim to the chart
|
||||
by using the ``logs.persistence.existingClaim`` parameter:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set logs.persistence.enabled=true \
|
||||
--set logs.persistence.existingClaim=my-volume-claim
|
||||
|
||||
.. note::
|
||||
|
||||
The volume has to be writable by the Airflow user. The easiest way to do this is to ensure GID ``0`` has a write permission.
|
||||
More information can be found in the :ref:`Docker image entrypoint documentation <docker-stack:arbitrary-docker-user>`.
|
||||
|
||||
Elasticsearch
|
||||
-------------
|
||||
|
||||
If your cluster forwards logs to Elasticsearch, you can configure Airflow to retrieve task logs from it.
|
||||
See the :doc:`Elasticsearch providers guide <apache-airflow-providers-elasticsearch:logging/index>` for more details.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade --install airflow apache-airflow/airflow \
|
||||
--set elasticsearch.enabled=true \
|
||||
--set elasticsearch.secretName=my-es-secret
|
||||
# Other choices exist. Please refer to values.yaml for details.
|
||||
77
charts/airflow/docs/parameters-ref.rst
Normal file
77
charts/airflow/docs/parameters-ref.rst
Normal file
@ -0,0 +1,77 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Parameters reference
|
||||
====================
|
||||
|
||||
The following tables lists the configurable parameters of the Airflow chart and their default values:
|
||||
|
||||
.. jinja:: params_ctx
|
||||
|
||||
{% for section in sections %}
|
||||
|
||||
.. _parameters:{{ section["name"] }}:
|
||||
|
||||
{{ section["name"] }}
|
||||
{{ "=" * (section["name"]|length + 2) }}
|
||||
|
||||
.. list-table::
|
||||
:widths: 15 10 30
|
||||
:header-rows: 1
|
||||
|
||||
* - Parameter
|
||||
- Description
|
||||
- Default
|
||||
|
||||
{% for param in section["params"] %}
|
||||
* - ``{{ param["name"] }}``
|
||||
- {{ param["description"] }}
|
||||
- ``{{ param["default"] }}``
|
||||
{% if param["examples"] %}
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: Examples
|
||||
|
||||
{{ param["examples"] | indent(width=10) }}
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
|
||||
Specify each parameter using the ``--set key=value[,key=value]`` argument to ``helm install``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm install my-release apache-airflow/airflow \
|
||||
--set executor=CeleryExecutor \
|
||||
--set enablePodLaunching=false
|
||||
|
||||
or override values by using the ``override-values.yaml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: override-values.yaml
|
||||
|
||||
executor: CeleryExecutor
|
||||
enablePodLaunching: false
|
||||
|
||||
and install the chart:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm install my-release apache-airflow/airflow --values override-values.yaml
|
||||
892
charts/airflow/docs/production-guide.rst
Normal file
892
charts/airflow/docs/production-guide.rst
Normal file
@ -0,0 +1,892 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Production Guide
|
||||
================
|
||||
|
||||
The following are things to consider when using this Helm chart in a production environment.
|
||||
|
||||
Database
|
||||
--------
|
||||
|
||||
It is advised to set up an external database for the Airflow metastore. The default Helm chart deploys a
|
||||
Postgres database running in a container. For **production** usage, a database running on a dedicated machine or
|
||||
leveraging a cloud provider's database service such as AWS RDS, should be used. Embedded Postgres
|
||||
lacks stability, monitoring and persistence features that you need for a production database. It is only there to
|
||||
make it easier to test the Helm Chart in a "standalone" version, but you might experience data loss when you
|
||||
are using it. Supported databases and versions can be found at :doc:`Set up a Database Backend <apache-airflow:howto/set-up-database>`.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
When using the helm chart, you do not need to initialize the db with ``airflow db migrate``
|
||||
as outlined in :doc:`Set up a Database Backend <apache-airflow:howto/set-up-database>`.
|
||||
|
||||
To disable deployment of Postgres pod, set below values in your ``values.yaml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
postgresql:
|
||||
enabled: false
|
||||
|
||||
To provide the database credentials to Airflow, you have 2 options - in your values file or in a Kubernetes Secret.
|
||||
|
||||
Values file
|
||||
^^^^^^^^^^^
|
||||
|
||||
This is the simpler options, as the chart will create a Kubernetes Secret for you. However, keep in mind your credentials will be in your values file.
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
data:
|
||||
metadataConnection:
|
||||
user: <username>
|
||||
pass: <password>
|
||||
protocol: postgresql
|
||||
host: <hostname>
|
||||
port: 5432
|
||||
db: <database name>
|
||||
|
||||
.. warning::
|
||||
|
||||
Due to security concerns, it is not advised to store Airflow database user credentials directly in the ``values.yaml`` file.
|
||||
|
||||
Kubernetes Secret
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can store the credentials in a Kubernetes Secret (it requires manual creation).
|
||||
|
||||
.. note::
|
||||
|
||||
Any special character in the username/password must be URL encoded.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl create secret generic mydatabase --from-literal=connection=postgresql://user:pass@host:5432/db
|
||||
|
||||
After secret creation, configure the chart to use the secret:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
data:
|
||||
metadataSecretName: mydatabase
|
||||
|
||||
.. _production-guide:pgbouncer:
|
||||
|
||||
Metadata DB Cleanup
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is recommended to periodically clean up the Airflow metadata database to remove old records and keep the database size manageable.
|
||||
A Kubernetes CronJob can be enabled for this purpose:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
databaseCleanup:
|
||||
enabled: true
|
||||
retentionDays: 90
|
||||
|
||||
For details regarding the ``airflow db clean`` command, see :ref:`db clean usage <cli-db-clean>` and for additional options which
|
||||
can be configured via helm chart values, see :doc:`parameters reference <parameters-ref>`.
|
||||
|
||||
PgBouncer
|
||||
---------
|
||||
|
||||
If you are using PostgreSQL as your database, you will likely want to enable `PgBouncer <https://www.pgbouncer.org/>`_ as well.
|
||||
Due to distributed nature of Airflow, it can open a lot of database connections. Using a connection pooler can significantly
|
||||
reduce the number of open connections on the database.
|
||||
|
||||
Database credentials stored Values file
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
pgbouncer:
|
||||
enabled: true
|
||||
|
||||
|
||||
Database credentials stored Kubernetes Secret
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The default connection string in this case will not work. You need to modify accordingly the Kubernetes secret:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl create secret generic mydatabase --from-literal=connection=postgresql://user:pass@pgbouncer_svc_name.deployment_namespace:6543/airflow-metadata
|
||||
|
||||
Furthermore, two additional Kubernetes Secret are required for PgBouncer to be able to properly work:
|
||||
|
||||
1. ``airflow-pgbouncer-stats`` secret:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl create secret generic airflow-pgbouncer-stats --from-literal=connection=postgresql://user:pass@127.0.0.1:6543/pgbouncer?sslmode=disable
|
||||
|
||||
2. ``airflow-pgbouncer-config`` secret:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: airflow-pgbouncer-config
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: airflow-pgbouncer-config
|
||||
data:
|
||||
pgbouncer.ini: dmFsdWUtMg0KDQo=
|
||||
users.txt: dmFsdWUtMg0KDQo=
|
||||
|
||||
where:
|
||||
|
||||
1. ``pgbouncer.ini`` value is equal to the base64 encoded version of below text:
|
||||
|
||||
.. code-block:: text
|
||||
:caption: pgbouncer.ini
|
||||
|
||||
[databases]
|
||||
airflow-metadata = host={external_database_host} dbname={external_database_dbname} port=5432 pool_size=10
|
||||
|
||||
[pgbouncer]
|
||||
pool_mode = transaction
|
||||
listen_port = 6543
|
||||
listen_addr = *
|
||||
auth_type = scram-sha-256
|
||||
auth_file = /etc/pgbouncer/users.txt
|
||||
stats_users = postgres
|
||||
ignore_startup_parameters = extra_float_digits
|
||||
max_client_conn = 100
|
||||
verbose = 0
|
||||
log_disconnections = 0
|
||||
log_connections = 0
|
||||
|
||||
server_tls_sslmode = prefer
|
||||
server_tls_ciphers = normal
|
||||
|
||||
2. ``users.txt`` value is equal to the base64 encoded version of below text:
|
||||
|
||||
.. code-block:: text
|
||||
:caption: users.txt
|
||||
|
||||
"{ external_database_username }" "{ external_database_pass }"
|
||||
|
||||
In the ``values.yaml`` below secret-related parameters should be adjusted like:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
pgbouncer:
|
||||
enabled: true
|
||||
configSecretName: airflow-pgbouncer-config
|
||||
metricsExporterSidecar:
|
||||
statsSecretName: airflow-pgbouncer-stats
|
||||
|
||||
.. note::
|
||||
|
||||
Depending on the size of your Airflow instance, you may want to adjust the following as well (defaults are shown):
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
pgbouncer:
|
||||
# The maximum number of connections to PgBouncer
|
||||
maxClientConn: 100
|
||||
# The maximum number of server connections to the metadata database from PgBouncer
|
||||
metadataPoolSize: 10
|
||||
# The maximum number of server connections to the result backend database from PgBouncer
|
||||
resultBackendPoolSize: 5
|
||||
|
||||
API Secret Key
|
||||
--------------
|
||||
|
||||
You should set a static API secret key when deploying with Airflow chart as it will help ensure
|
||||
your Airflow components only restart when necessary.
|
||||
|
||||
.. note::
|
||||
|
||||
This section also applies to the webserver for Airflow 2 (simply replace ``api`` with ``webserver``).
|
||||
|
||||
.. warning::
|
||||
|
||||
You should use a different secret key for every instance you run, as this key is used to sign
|
||||
session cookies and perform other security related functions.
|
||||
|
||||
Follow below steps to create static API secret key:
|
||||
|
||||
1. Generate a strong secret key:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python3 -c 'import secrets; print(secrets.token_hex(16))'
|
||||
|
||||
2. Add the secret to your values file:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
apiSecretKey: <secret_key>
|
||||
|
||||
or create a Kubernetes Secret and use ``apiSecretKeySecretName``:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
apiSecretKeySecretName: my-api-secret
|
||||
# Where the random key is under `webserver-secret-key` in the k8s Secret
|
||||
|
||||
.. warning::
|
||||
|
||||
Due to security concerns, it is advised to use Kubernetes Secret instead of setting API secret key directly in the values file.
|
||||
|
||||
Example to create a Kubernetes Secret from ``kubectl``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl create secret generic my-api-secret --from-literal="api-secret-key=$(python3 -c 'import secrets; print(secrets.token_hex(16))')"
|
||||
|
||||
The API secret key is also used to authorize requests to Celery workers when logs are retrieved. The token
|
||||
generated using the secret key has a short expiry time though. Make sure that time on ALL the machines
|
||||
that you run Airflow components on is synchronized (for example using ntpd). You might get
|
||||
"forbidden" errors when the logs are accessed otherwise.
|
||||
|
||||
JWT Secret
|
||||
----------
|
||||
|
||||
You should set a static JWT Secret key when deploying with Airflow chart as it will increase environment
|
||||
stability. It can be achieved by using ``jwtSecretName`` field in the ``values.yaml`` file.
|
||||
|
||||
.. note::
|
||||
|
||||
For increase security of production setup, consider creating custom JWT Secret rollover procedure which will
|
||||
not cause failures in dag runs due to mismatch in tokens.
|
||||
|
||||
Eviction configuration
|
||||
----------------------
|
||||
When running Airflow along with the `Kubernetes Cluster Autoscaler <https://github.com/kubernetes/autoscaler>`_, it is important to configure whether pods can be safely evicted.
|
||||
This setting can be configured in the Airflow chart at different levels:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
workers:
|
||||
safeToEvict: true
|
||||
scheduler:
|
||||
safeToEvict: true
|
||||
apiServer:
|
||||
safeToEvict: true
|
||||
|
||||
``workers.safeToEvict`` defaults to ``false``, and when using ``KubernetesExecutor``
|
||||
``workers.safeToEvict`` shouldn't be set to ``true`` as the workers may be removed before finishing.
|
||||
|
||||
Extending and customizing Airflow Image
|
||||
---------------------------------------
|
||||
|
||||
The Apache Airflow community, releases Docker Images which are ``reference images`` for Apache Airflow.
|
||||
However, Airflow has more than 60 community managed providers (installable via extras) and some of the
|
||||
default extras/providers installed are not used by everyone. Sometimes other extras/providers
|
||||
are needed, sometimes (very often actually) you need to add your own custom dependencies,
|
||||
packages or even custom providers, or add custom tools and binaries that are needed in
|
||||
your deployment.
|
||||
|
||||
In Kubernetes and Docker terms, this means that you need another image with your specific requirements.
|
||||
This is why you should learn how to build your own ``Docker`` (or more properly ``Container``) image.
|
||||
|
||||
Typical scenarios where you would like to use your custom image are adding:
|
||||
|
||||
* ``apt`` packages,
|
||||
* ``PyPI`` packages,
|
||||
* binary resources necessary for your deployment,
|
||||
* custom tools needed in your deployment.
|
||||
|
||||
See :ref:`Extending Airflow Image <quick-start:extending-airflow-image>` and/or
|
||||
`Building the image <https://airflow.apache.org/docs/docker-stack/build.html>`_ for more
|
||||
details on how you can extend, customize and test the modifications of Airflow image.
|
||||
|
||||
Managing Dag Files
|
||||
------------------
|
||||
|
||||
See :doc:`manage-dag-files`.
|
||||
|
||||
.. _production-guide:knownhosts:
|
||||
|
||||
knownHosts
|
||||
^^^^^^^^^^
|
||||
|
||||
If you are using ``dags.gitSync.sshKeySecret``, you should also set ``dags.gitSync.knownHosts``. Here we will show the process
|
||||
for GitHub, but the same can be done for any provider:
|
||||
|
||||
1. Grab GitHub's public key:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ssh-keyscan -t rsa github.com > github_public_key
|
||||
|
||||
2. Print the fingerprint for the public key:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ssh-keygen -lf github_public_key
|
||||
|
||||
3. Compare that output with `GitHub's SSH key fingerprints <https://docs.github.com/en/github/authenticating-to-github/githubs-ssh-key-fingerprints>`_.
|
||||
4. If values are the same, add the public key to your values. It'll look something like this:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
dags:
|
||||
gitSync:
|
||||
knownHosts: |
|
||||
github.com ssh-rsa AAAA...1/wsjk=
|
||||
|
||||
External Scheduler
|
||||
------------------
|
||||
|
||||
To use an external Scheduler instance:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
enabled: false
|
||||
|
||||
Ensure that your external scheduler is connected to the same redis host as workers.
|
||||
|
||||
Accessing the Airflow UI
|
||||
------------------------
|
||||
|
||||
How you access the Airflow UI will depend on your environment; however, the chart does support various options.
|
||||
|
||||
External API Server
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To use an external API Server:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
apiServer:
|
||||
enabled: false
|
||||
|
||||
Ingress
|
||||
^^^^^^^
|
||||
|
||||
You can create and configure ``Ingress`` objects. See the :ref:`Ingress chart parameters <parameters:ingress>`.
|
||||
For more information on ``Ingress``, see the
|
||||
`Kubernetes Ingress documentation <https://kubernetes.io/docs/concepts/services-networking/ingress/>`_.
|
||||
|
||||
LoadBalancer Service
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can change the Service type for the API Server to be ``LoadBalancer``, and set any necessary annotations:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
apiServer:
|
||||
service:
|
||||
type: LoadBalancer
|
||||
|
||||
For more information on ``LoadBalancer`` Services, see the `Kubernetes LoadBalancer Service Documentation
|
||||
<https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer>`_.
|
||||
|
||||
Logging
|
||||
-------
|
||||
|
||||
Depending on your choice of executor, task logs may not work out of the box. All logging choices can be found
|
||||
at :doc:`manage-logs`.
|
||||
|
||||
Metrics
|
||||
-------
|
||||
|
||||
The chart supports sending metrics to an existing StatsD instance or provide a Prometheus endpoint.
|
||||
|
||||
Prometheus Endpoint
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The metrics endpoint is available at ``svc/{{ .Release.Name }}-statsd:9102/metrics``.
|
||||
|
||||
External StatsD
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
To use an external StatsD instance:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
statsd:
|
||||
enabled: false
|
||||
config:
|
||||
metrics:
|
||||
statsd_on: true
|
||||
statsd_host: ...
|
||||
statsd_port: ...
|
||||
|
||||
IPv6 StatsD
|
||||
^^^^^^^^^^^
|
||||
|
||||
To use an StatsD instance with IPv6 address. Example with Kubernetes with IPv6 enabled:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
statsd:
|
||||
enabled: true
|
||||
config:
|
||||
metrics:
|
||||
statsd_on: 'True'
|
||||
statsd_host: ...
|
||||
statsd_ipv6: 'True'
|
||||
statsd_port: ...
|
||||
statsd_prefix: airflow
|
||||
|
||||
Datadog
|
||||
^^^^^^^
|
||||
If you are using a Datadog agent in your environment, this will enable Airflow to export metrics to the Datadog agent.
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
statsd:
|
||||
enabled: false
|
||||
config:
|
||||
metrics:
|
||||
statsd_on: true
|
||||
statsd_port: 8125
|
||||
extraEnv: |-
|
||||
- name: AIRFLOW__METRICS__STATSD_HOST
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.hostIP
|
||||
|
||||
Celery Backend
|
||||
--------------
|
||||
|
||||
If you are using ``CeleryExecutor`` or ``CeleryKubernetesExecutor``, you can bring your own Celery backend.
|
||||
|
||||
By default, the chart will deploy Redis. However, you can use any supported Celery backend instead:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
redis:
|
||||
enabled: false
|
||||
data:
|
||||
brokerUrl: redis://redis-user:password@redis-host:6379/0
|
||||
|
||||
For more information about setting up a Celery broker, refer to the
|
||||
exhaustive `Celery documentation on the topic <http://docs.celeryproject.org/en/latest/getting-started/>`_.
|
||||
|
||||
Security Context
|
||||
----------------
|
||||
|
||||
Constraints
|
||||
^^^^^^^^^^^
|
||||
|
||||
A ``Security Context Constraint`` (SCC) is a OpenShift construct that works as a RBAC rule. However, it targets Pods instead of users.
|
||||
When defining a SCC, one can control actions and resources a POD can perform or access during startup and runtime.
|
||||
|
||||
The SCCs are split into different levels or categories with the ``restricted`` SCC being the default one assigned to Pods.
|
||||
When deploying Airflow to OpenShift, one can leverage the SCCs and allow the Pods to start containers utilizing the ``anyuid`` SCC.
|
||||
|
||||
In order to enable the usage of SCCs, one must set the parameter ``rbac.createSCCRoleBinding`` to ``true`` as shown below:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
rbac:
|
||||
create: true
|
||||
createSCCRoleBinding: true
|
||||
|
||||
In this chart, SCCs are bound to the Pods via RoleBindings meaning that the option ``rbac.create`` must also be set to ``true`` in order to fully enable the SCC usage.
|
||||
|
||||
For more information about SCCs and what can be achieved with this construct, please refer to `Managing security context constraints <https://docs.openshift.com/container-platform/latest/authentication/managing-security-context-constraints.html#scc-prioritization_configuring-internal-oauth/>`_.
|
||||
|
||||
Configuration
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
In Kubernetes a ``securityContext`` can be used to define user ids, group ids and capabilities such as running a container in privileged mode.
|
||||
|
||||
When deploying an application to Kubernetes, it is recommended to give the least privilege to containers
|
||||
to reduce access and protect the host where the container is running.
|
||||
|
||||
In the Airflow Helm chart, the ``securityContext`` can be configured in several ways:
|
||||
|
||||
* :ref:`uid <parameters:Airflow>` - configures the global uid or RunAsUser
|
||||
* :ref:`gid <parameters:Airflow>` - configures the global gid or fsGroup
|
||||
* :ref:`securityContexts <parameters:Kubernetes>` - same as ``uid``, but allows for setting all `Pod securityContext options <https://kubernetes.io/docs/reference/generated/kubernetes-api/latest/#podsecuritycontext-v1-core>`_ and `Container securityContext options <https://kubernetes.io/docs/reference/generated/kubernetes-api/latest/#securitycontext-v1-core>`_
|
||||
|
||||
The same way one can configure the global :ref:`securityContexts <parameters:Kubernetes>`. It is also possible to configure different values for specific workloads by setting their local ``securityContexts`` as follows:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
securityContexts:
|
||||
pod:
|
||||
runAsUser: 5000
|
||||
fsGroup: 0
|
||||
containers:
|
||||
allowPrivilegeEscalation: false
|
||||
|
||||
|
||||
In the example above, the scheduler pod ``securityContext`` will be set to ``runAsUser: 5000`` and ``fsGroup: 0``. The scheduler container ``securityContext`` will be set to ``allowPrivilegeEscalation: false``.
|
||||
|
||||
As one can see, the local setting will take precedence over the global setting when defined. The following explains the precedence rule for ``securityContexts`` options in this chart:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
uid: 40000
|
||||
gid: 0
|
||||
|
||||
securityContexts:
|
||||
pod:
|
||||
runAsUser: 50000
|
||||
fsGroup: 0
|
||||
|
||||
scheduler:
|
||||
securityContexts:
|
||||
pod:
|
||||
runAsUser: 1001
|
||||
fsGroup: 0
|
||||
|
||||
This will generate the following scheduler deployment:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: airflow-scheduler
|
||||
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: airflow-scheduler
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
securityContext: # As the securityContexts was defined in ``scheduler``, its value will take priority
|
||||
runAsUser: 1001
|
||||
fsGroup: 0
|
||||
|
||||
If we remove both the ``securityContexts`` and ``scheduler.securityContexts`` from the example above:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
uid: 40000
|
||||
gid: 0
|
||||
|
||||
securityContexts: {}
|
||||
|
||||
scheduler:
|
||||
securityContexts: {}
|
||||
|
||||
it will generate the following scheduler deployment:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: airflow-scheduler
|
||||
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: airflow-scheduler
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: 40000 # As the securityContext was not defined in ``scheduler`` or ``podSecurity``, the value from uid will be used
|
||||
fsGroup: 0 # As the securityContext was not defined in ``scheduler`` or ``podSecurity``, the value from gid will be used
|
||||
initContainers:
|
||||
- name: wait-for-airflow-migrations
|
||||
...
|
||||
containers:
|
||||
- name: scheduler
|
||||
...
|
||||
|
||||
And finally if we set ``securityContexts``, but not ``scheduler.securityContexts``:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
uid: 40000
|
||||
gid: 0
|
||||
|
||||
securityContexts:
|
||||
pod:
|
||||
runAsUser: 50000
|
||||
fsGroup: 0
|
||||
|
||||
scheduler:
|
||||
securityContexts: {}
|
||||
|
||||
This will generate the following scheduler deployment:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: airflow-scheduler
|
||||
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: airflow-scheduler
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
securityContext: # As the securityContexts was not defined in ``scheduler``, the values from securityContexts will take priority
|
||||
runAsUser: 50000
|
||||
fsGroup: 0
|
||||
initContainers:
|
||||
- name: wait-for-airflow-migrations
|
||||
...
|
||||
containers:
|
||||
- name: scheduler
|
||||
...
|
||||
|
||||
Built-in secrets and environment variables
|
||||
------------------------------------------
|
||||
|
||||
The Helm Chart by default uses Kubernetes Secrets to store secrets that are needed by Airflow.
|
||||
The contents of those secrets are by default turned into environment variables that are read by
|
||||
Airflow.
|
||||
|
||||
.. note::
|
||||
|
||||
Some of the environment variables have several variants to support older versions of Airflow.
|
||||
|
||||
By default, the secret names are determined from the Release Name used when the Helm Chart,
|
||||
but you can also use a different secret to set the variables or disable using secrets
|
||||
entirely and rely on environment variables (specifically if you want to use ``_CMD`` or ``__SECRET`` variant
|
||||
of the environment variable).
|
||||
|
||||
However, Airflow supports other variants of setting secret configuration. You can specify a system
|
||||
command to retrieve and automatically rotate the secret (by defining variable with ``_CMD`` suffix) or
|
||||
to retrieve a variable from secret backed (by defining the variable with ``_SECRET`` suffix).
|
||||
|
||||
If the ``<VARIABLE_NAME>`` is set, it takes precedence over the ``_CMD`` and ``_SECRET`` variant, so
|
||||
if you want to set one of the ``_CMD`` or ``_SECRET`` variants, you **must** disable the built in
|
||||
variables retrieved from Kubernetes secrets, by setting ``.Values.enableBuiltInSecretEnvVars.<VARIABLE_NAME>``
|
||||
to ``false``.
|
||||
|
||||
For example in order to use a command to retrieve the DB connection, you should (in your ``values.yaml``
|
||||
file) specify:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
extraEnv:
|
||||
AIRFLOW_CONN_AIRFLOW_DB_CMD: "/usr/local/bin/retrieve_connection_url"
|
||||
enableBuiltInSecretEnvVars:
|
||||
AIRFLOW_CONN_AIRFLOW_DB: false
|
||||
|
||||
Here is the full list of secrets that can be disabled and replaced by ``_CMD`` and ``_SECRET`` variants:
|
||||
|
||||
+-------------------------------------------------------+------------------------------------------+--------------------------------------------------+
|
||||
| Default secret name if secret name not specified | Use a different Kubernetes Secret | Airflow Environment Variable |
|
||||
+=======================================================+==========================================+==================================================+
|
||||
| ``<RELEASE_NAME>-airflow-metadata`` | ``.Values.data.metadataSecretName`` | | ``AIRFLOW_CONN_AIRFLOW_DB`` |
|
||||
| | | | ``AIRFLOW__DATABASE__SQL_ALCHEMY_CONN`` |
|
||||
+-------------------------------------------------------+------------------------------------------+--------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-fernet-key`` | ``.Values.fernetKeySecretName`` | ``AIRFLOW__CORE__FERNET_KEY`` |
|
||||
+-------------------------------------------------------+------------------------------------------+--------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-api-secret-key`` | ``.Values.apiSecretKeySecretName`` | ``AIRFLOW__API__SECRET_KEY`` |
|
||||
+-------------------------------------------------------+------------------------------------------+--------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-jwt-secret`` | ``.Values.jwtSecretName`` | ``AIRFLOW__API_AUTH__JWT_SECRET`` |
|
||||
+-------------------------------------------------------+------------------------------------------+--------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-webserver-secret-key`` | ``.Values.webserverSecretKeySecretName`` | ``AIRFLOW__WEBSERVER__SECRET_KEY`` |
|
||||
+-------------------------------------------------------+------------------------------------------+--------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-airflow-result-backend`` | ``.Values.data.resultBackendSecretName`` | ``AIRFLOW__CELERY__RESULT_BACKEND`` |
|
||||
+-------------------------------------------------------+------------------------------------------+--------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-airflow-broker-url`` | ``.Values.data.brokerUrlSecretName`` | ``AIRFLOW__CELERY__BROKER_URL`` |
|
||||
+-------------------------------------------------------+------------------------------------------+--------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-elasticsearch`` | ``.Values.elasticsearch.secretName`` | ``AIRFLOW__ELASTICSEARCH__HOST`` |
|
||||
+-------------------------------------------------------+------------------------------------------+--------------------------------------------------+
|
||||
|
||||
There are also a number of secrets, which names are also determined from the release name, that do not need to
|
||||
be disabled. This is because either they do not follow the ``_CMD`` or ``_SECRET`` pattern, are variables
|
||||
which do not start with ``AIRFLOW__``, or they do not have a corresponding variable.
|
||||
|
||||
There is also ``AIRFLOW__CELERY__FLOWER_BASIC_AUTH``, that does not need to be disabled,
|
||||
even if you want set the ``_CMD`` and ``_SECRET`` variant. This variable is not set by default. It is only set
|
||||
when ``.Values.flower.secretName`` is set or when ``.Values.flower.user`` and ``.Values.flower.password``
|
||||
are set. If you do not set any of the ``.Values.flower.*`` variables, you can freely configure
|
||||
flower Basic Auth using the ``_CMD`` or ``_SECRET`` variant without disabling the basic variant.
|
||||
|
||||
+-------------------------------------------------------+------------------------------------------+------------------------------------------------+
|
||||
| Default secret name if secret name not specified | Use a different Kubernetes Secret | Airflow Environment Variable |
|
||||
+=======================================================+==========================================+================================================+
|
||||
| ``<RELEASE_NAME>-redis-password`` | ``.Values.redis.passwordSecretName`` | ``REDIS_PASSWORD`` |
|
||||
+-------------------------------------------------------+------------------------------------------+------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-pgbouncer-config`` | ``.Values.pgbouncer.configSecretName`` | |
|
||||
+-------------------------------------------------------+------------------------------------------+------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-pgbouncer-certificates`` | | |
|
||||
+-------------------------------------------------------+------------------------------------------+------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-kerberos-keytab`` | | |
|
||||
+-------------------------------------------------------+------------------------------------------+------------------------------------------------+
|
||||
| ``<RELEASE_NAME>-flower`` | ``.Values.flower.secretName`` | ``AIRFLOW__CELERY__FLOWER_BASIC_AUTH`` |
|
||||
+-------------------------------------------------------+------------------------------------------+------------------------------------------------+
|
||||
|
||||
A secret named ``<RELEASE_NAME>-registry`` is also created when ``.Values.registry.connection`` is
|
||||
defined and neither ``.Values.registry.secretName`` nor ``.Values.imagePullSecrets`` is set. However,
|
||||
this behavior is deprecated in favor of explicitly defining ``.Values.imagePullSecrets``.
|
||||
|
||||
You can read more about advanced ways of setting configuration variables in the
|
||||
:doc:`apache-airflow:howto/set-config`.
|
||||
|
||||
Service Account Token Volume Configuration
|
||||
------------------------------------------
|
||||
|
||||
When using pod-launching executors (``CeleryExecutor``, ``CeleryKubernetesExecutor``, ``KubernetesExecutor``, ``LocalKubernetesExecutor``),
|
||||
you can configure how Kubernetes service account tokens are mounted into pods. This provides enhanced security control
|
||||
and compatibility with security policies like Kyverno.
|
||||
|
||||
Background
|
||||
^^^^^^^^^^
|
||||
|
||||
By default, Kubernetes automatically mounts service account tokens into pods via the ``automountServiceAccountToken`` setting.
|
||||
However, for security reasons, you might want to disable automatic mounting and manually configure service account token volumes instead.
|
||||
|
||||
This feature addresses Bug `#59099 <https://github.com/apache/airflow/issues/59099>`_ where ``scheduler.serviceAccount.automountServiceAccountToken: false`` was ignored
|
||||
when using the KubernetesExecutor. The solution implements a defense-in-depth approach with both ServiceAccount-level
|
||||
and Pod-level controls.
|
||||
|
||||
Container-Specific Security
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The Service Account Token Volume is mounted **only** in containers that require Kubernetes API access, implementing the
|
||||
**Principle of Least Privilege**:
|
||||
|
||||
* **Scheduler Container**: Receives Service Account Token as it needs API access for pod management
|
||||
* **Init Container "wait-for-airflow-migrations"**: No Service Account Token as it only performs database migrations
|
||||
* **Sidecar Container "scheduler-log-groomer"**: No Service Account Token as it only performs log cleanup operations
|
||||
|
||||
This container-specific approach ensures that:
|
||||
|
||||
* **Database Migration Container**: Only accesses the database for schema updates as no Kubernetes API access required
|
||||
* **Log Groomer Container**: Only performs filesystem operations for log cleanup as no API access required
|
||||
* **Scheduler Container**: Requires API access for launching and managing pods with pod-launching executors
|
||||
|
||||
**Security Benefits:**
|
||||
|
||||
* **Explicit control**: Manual configuration makes token mounting intentional and visible
|
||||
* **Policy compliance**: Compatible with security policies that restrict ``automountServiceAccountToken: true``
|
||||
* **Defense-in-depth**: Provides both ServiceAccount-level and Pod-level security controls
|
||||
* **Custom expiration**: Allows setting shorter token lifetimes for enhanced security
|
||||
* **Container isolation**: Only scheduler container receives API access, reducing attack surface
|
||||
* **Principle of Least Privilege**: Each container receives only the minimum required permissions
|
||||
|
||||
Configuration Options
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The service account token volume configuration is available for the scheduler component and includes the following options:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
|
||||
volumeName: kube-api-access
|
||||
expirationSeconds: 3600
|
||||
audience: ~
|
||||
|
||||
Security Implications
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Manual token volumes should be used when:
|
||||
|
||||
* Security policies require explicit control over service account token mounting
|
||||
* Using security policy engines like Kyverno that restrict automatic token mounting
|
||||
* Implementing defense-in-depth security strategies
|
||||
* You need custom token expiration times or audiences
|
||||
* Compliance frameworks mandate container-specific privilege assignment
|
||||
|
||||
Use Cases and Examples
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For comprehensive configuration examples, security scenarios, and detailed use cases,
|
||||
see :doc:`service-account-token-examples`.
|
||||
|
||||
Supported Executors
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The service account token volume configuration is only effective for pod-launching executors:
|
||||
|
||||
* ``CeleryExecutor`` - when launching Celery worker pods
|
||||
* ``CeleryKubernetesExecutor`` - for both Celery workers and Kubernetes task pods
|
||||
* ``KubernetesExecutor`` - when launching task pods in Kubernetes
|
||||
* ``LocalKubernetesExecutor`` - for Kubernetes task pods in local mode
|
||||
|
||||
For other executors (``LocalExecutor``, ``SequentialExecutor``), this configuration has no effect
|
||||
as they don't launch additional pods.
|
||||
|
||||
Migration from Automatic to Manual Token Mounting
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To migrate from automatic to manual token mounting:
|
||||
|
||||
1. Test the configuration in a non-production environment first
|
||||
2. Update your ``values.yaml``:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
|
||||
3. Deploy the changes using Helm upgrade
|
||||
4. Verify that the scheduler can still launch pods successfully
|
||||
5. Monitor for any authentication issues in the logs
|
||||
|
||||
Troubleshooting
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
**Common Issues:**
|
||||
|
||||
* **Authentication failures**: Ensure ``serviceAccountTokenVolume.enabled`` is set to ``true`` when ``automountServiceAccountToken`` is ``false``
|
||||
* **Permission denied**: Verify that the service account has the necessary RBAC permissions
|
||||
* **Token expiration**: Check if ``expirationSeconds`` is too short for your workload patterns
|
||||
|
||||
**Debugging:**
|
||||
|
||||
Check the scheduler logs for authentication-related errors:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl logs deployment/airflow-scheduler -n <namespace>
|
||||
|
||||
Verify the projected volume is mounted correctly:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl describe pod <scheduler-pod-name> -n <namespace>
|
||||
|
||||
Backward Compatibility
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This feature maintains full backward compatibility:
|
||||
|
||||
* Existing deployments with ``automountServiceAccountToken: true`` continue to work unchanged
|
||||
* The ``serviceAccountTokenVolume`` configuration is only applied when explicitly enabled
|
||||
* Default values ensure no breaking changes for existing installations
|
||||
|
||||
For more information about Kubernetes service account tokens and projected volumes, see the
|
||||
`Kubernetes documentation on service account tokens <https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#serviceaccount-token-volume-projection>`_.
|
||||
228
charts/airflow/docs/quick-start.rst
Normal file
228
charts/airflow/docs/quick-start.rst
Normal file
@ -0,0 +1,228 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Quick start with kind
|
||||
=====================
|
||||
|
||||
This article will show you how to install Airflow using Helm Chart on `Kind <https://kind.sigs.k8s.io/>`__.
|
||||
|
||||
Run Airflow on Kind cluster
|
||||
---------------------------
|
||||
|
||||
Install kind and create a cluster
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
We recommend testing with Kubernetes 1.30+, example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kind create cluster --image kindest/node:v1.30.13
|
||||
|
||||
Confirm it's up:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl cluster-info --context kind-kind
|
||||
|
||||
Add Airflow Helm Stable Repo
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm repo add apache-airflow https://airflow.apache.org
|
||||
helm repo update
|
||||
|
||||
Create namespace
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
export NAMESPACE=example-namespace
|
||||
kubectl create namespace $NAMESPACE
|
||||
|
||||
.. note::
|
||||
|
||||
Same exported ``NAMESPACE`` variable will be used in the next instructions.
|
||||
|
||||
Install the chart
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
export RELEASE_NAME=example-release
|
||||
helm install $RELEASE_NAME apache-airflow/airflow --namespace $NAMESPACE
|
||||
|
||||
.. note::
|
||||
|
||||
Same exported ``RELEASE_NAME`` variable will be used in the next instructions.
|
||||
|
||||
Use the following code to install the chart with example Dags:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm install $RELEASE_NAME apache-airflow/airflow \
|
||||
--namespace $NAMESPACE \
|
||||
--set-string "env[0].name=AIRFLOW__CORE__LOAD_EXAMPLES" \
|
||||
--set-string "env[0].value=True"
|
||||
|
||||
It may take a few minutes. Confirm the pods are up:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl get pods --namespace $NAMESPACE
|
||||
helm list --namespace $NAMESPACE
|
||||
|
||||
Run the following command to port-forward the Airflow UI to http://localhost:8080/ to confirm
|
||||
Airflow is working.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl port-forward svc/$RELEASE_NAME-api-server 8080:8080 --namespace $NAMESPACE
|
||||
|
||||
.. _quick-start:extending-airflow-image:
|
||||
|
||||
Extending Airflow Image
|
||||
-----------------------
|
||||
|
||||
The Apache Airflow community, releases Docker Images which are ``reference images`` for Apache Airflow.
|
||||
However, when you try it out you want to add your own Dags, custom dependencies, packages, or even custom providers.
|
||||
|
||||
.. note::
|
||||
|
||||
Creating custom images means that you need to maintain also a level of automation as you need to re-create the images
|
||||
when either the packages you want to install or Airflow is upgraded. Do not forget about keeping these scripts.
|
||||
Also keep in mind, that in cases when you run pure Python tasks, you can use the
|
||||
`Python Virtualenv functions <https://airflow.apache.org/docs/apache-airflow/stable/howto/operator/python.html#pythonvirtualenvoperator>`_
|
||||
which will dynamically source and install python dependencies during runtime. Virtualenvs can also be cached.
|
||||
|
||||
The best way to achieve it, is to build your own, custom image.
|
||||
|
||||
Adding Dags to your image
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. Create a project:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir my-airflow-project && cd my-airflow-project
|
||||
mkdir dags # put dags here
|
||||
cat <<EOM > Dockerfile
|
||||
FROM apache/airflow
|
||||
COPY . .
|
||||
EOM
|
||||
|
||||
2. Then build the image:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker build --pull --tag my-dags:0.0.1 .
|
||||
|
||||
3. Load the image into kind:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kind load docker-image my-dags:0.0.1
|
||||
|
||||
4. Upgrade Helm deployment:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade $RELEASE_NAME apache-airflow/airflow --namespace $NAMESPACE \
|
||||
--set images.airflow.repository=my-dags \
|
||||
--set images.airflow.tag=0.0.1
|
||||
|
||||
Adding ``apt`` packages to your image
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Example below adds ``vim`` apt package.
|
||||
|
||||
1. Create a project:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir my-airflow-project && cd my-airflow-project
|
||||
cat <<EOM > Dockerfile
|
||||
FROM apache/airflow
|
||||
USER root
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends vim \
|
||||
&& apt-get autoremove -yqq --purge \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
USER airflow
|
||||
EOM
|
||||
|
||||
2. Then build the image:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker build --pull --tag my-image:0.0.1 .
|
||||
|
||||
3. Load the image into kind:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kind load docker-image my-image:0.0.1
|
||||
|
||||
4. Upgrade Helm deployment:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade $RELEASE_NAME apache-airflow/airflow --namespace $NAMESPACE \
|
||||
--set images.airflow.repository=my-image \
|
||||
--set images.airflow.tag=0.0.1
|
||||
|
||||
Adding ``PyPI`` packages to your image
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Example below adds ``lxml`` PyPI package.
|
||||
|
||||
1. Create a project:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir my-airflow-project && cd my-airflow-project
|
||||
cat <<EOM > Dockerfile
|
||||
FROM apache/airflow
|
||||
RUN pip install --no-cache-dir lxml
|
||||
EOM
|
||||
|
||||
2. Then build the image:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker build --pull --tag my-image:0.0.1 .
|
||||
|
||||
3. Load the image into kind:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kind load docker-image my-image:0.0.1
|
||||
|
||||
4. Upgrade Helm deployment:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
helm upgrade $RELEASE_NAME apache-airflow/airflow --namespace $NAMESPACE \
|
||||
--set images.airflow.repository=my-image \
|
||||
--set images.airflow.tag=0.0.1
|
||||
|
||||
Further extending and customizing the image
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See `Building the image <https://airflow.apache.org/docs/docker-stack/build.html>`_ for more
|
||||
details on how you can extend and customize the Airflow image.
|
||||
20
charts/airflow/docs/redirects.txt
Normal file
20
charts/airflow/docs/redirects.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# Release Notes
|
||||
changelog.rst release_notes.rst
|
||||
updating.rst release_notes.rst
|
||||
23
charts/airflow/docs/release_notes.rst
Normal file
23
charts/airflow/docs/release_notes.rst
Normal file
@ -0,0 +1,23 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
|
||||
|
||||
Release Notes
|
||||
=============
|
||||
|
||||
.. include:: ../RELEASE_NOTES.rst
|
||||
426
charts/airflow/docs/service-account-token-examples.rst
Normal file
426
charts/airflow/docs/service-account-token-examples.rst
Normal file
@ -0,0 +1,426 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Service Account Token Volume Examples
|
||||
=====================================
|
||||
|
||||
This document provides comprehensive examples for configuring Service Account Token Volumes
|
||||
in the Apache Airflow Helm Chart. These examples demonstrate various security scenarios and
|
||||
use cases for pod-launching executors.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Service Account Token Volume configuration allows you to manually control how Kubernetes
|
||||
service account tokens are mounted into pods launched by Airflow. This feature implements the
|
||||
**Principle of Least Privilege** by providing tokens only to containers that require Kubernetes API access.
|
||||
|
||||
**Container-Specific Security Model:**
|
||||
|
||||
- **Scheduler Container**: Receives Service Account Token as it requires API access for pod management
|
||||
- **Init Container**: No Service Account Token as it only performs database migrations
|
||||
- **Sidecar Container**: No Service Account Token as it only performs log cleanup operations
|
||||
|
||||
**This feature is particularly useful for**:
|
||||
|
||||
- Compliance with security policies that restrict automatic token mounting
|
||||
- Implementation of defense-in-depth security strategies
|
||||
- Custom token expiration and audience configuration
|
||||
- Compatibility with security policy engines like Kyverno
|
||||
- Meeting compliance frameworks that mandate container-specific privilege assignment
|
||||
|
||||
Basic Configuration Examples
|
||||
----------------------------
|
||||
|
||||
Default Automatic Token Mounting
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This is the default behavior that continues to work without any changes:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: true # Default value
|
||||
|
||||
Manual Token Volume Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Basic manual configuration that disables automatic mounting and enables manual token volume:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
|
||||
This configuration:
|
||||
|
||||
- Disables automatic service account token mounting at the ServiceAccount level
|
||||
- Enables manual token volume mounting at the Pod level
|
||||
- Uses default values for all other token volume settings
|
||||
|
||||
Security-Focused Examples
|
||||
-------------------------
|
||||
|
||||
High-Security Environment
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For environments requiring enhanced security with shorter token lifetimes:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
expirationSeconds: 1800 # 30 minutes instead of default 1 hour
|
||||
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
|
||||
volumeName: secure-kube-access
|
||||
|
||||
**Security Benefits:**
|
||||
|
||||
- **Shorter token lifetime** reduces exposure window if compromised
|
||||
- **Explicit control** over token mounting makes security intentional
|
||||
- **Container isolation** as only scheduler container receives API access
|
||||
- **Clear naming** for security auditing and compliance reporting
|
||||
|
||||
Kyverno Policy Compliance
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Configuration that complies with Kyverno policies requiring ``automountServiceAccountToken: false``
|
||||
(`Restrict Auto-Mount of Service Account Tokens in Service Account`_ and `Restrict Auto-Mount of Service Account Tokens`_):
|
||||
|
||||
.. _Restrict Auto-Mount of Service Account Tokens in Service Account: https://kyverno.io/policies/other/restrict-sa-automount-sa-token/restrict-sa-automount-sa-token/
|
||||
.. _Restrict Auto-Mount of Service Account Tokens: https://kyverno.io/policies/other/restrict-sa-automount-sa-token/restrict-sa-automount-sa-token/
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false # Required by Kyverno policy
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
expirationSeconds: 3600
|
||||
audience: "https://kubernetes.default.svc.cluster.local"
|
||||
|
||||
Custom Mount Path Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For applications that expect service account tokens at custom locations:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
mountPath: /custom/sa-token
|
||||
volumeName: custom-service-account-token
|
||||
expirationSeconds: 7200 # 2 hours
|
||||
|
||||
This configuration mounts the token at ``/custom/sa-token`` instead of the default location.
|
||||
|
||||
Executor-Specific Examples
|
||||
--------------------------
|
||||
|
||||
KubernetesExecutor Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Optimal configuration for ``KubernetesExecutor`` with security focus:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
executor: KubernetesExecutor
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
expirationSeconds: 3600
|
||||
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
|
||||
volumeName: k8s-executor-token
|
||||
|
||||
# Ensure RBAC permissions for KubernetesExecutor
|
||||
rbac:
|
||||
create: true
|
||||
|
||||
CeleryKubernetesExecutor Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Configuration for hybrid executor that launches both Celery workers and Kubernetes task pods:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
executor: CeleryKubernetesExecutor
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
expirationSeconds: 5400 # 1.5 hours for longer-running tasks
|
||||
volumeName: hybrid-executor-token
|
||||
|
||||
# Redis configuration for Celery
|
||||
redis:
|
||||
enabled: true
|
||||
|
||||
Multi-Environment Examples
|
||||
--------------------------
|
||||
|
||||
Development Environment
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Relaxed configuration for development with longer token lifetimes:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values-dev.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
expirationSeconds: 14400 # 4 hours for development convenience
|
||||
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
|
||||
|
||||
Production Environment
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Strict production configuration with enhanced security:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values-prod.yaml
|
||||
|
||||
# Additional production security settings
|
||||
securityContexts:
|
||||
pod:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 50000
|
||||
fsGroup: 0
|
||||
container:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
expirationSeconds: 1800 # 30 minutes for production security
|
||||
audience: "https://kubernetes.default.svc.cluster.local"
|
||||
volumeName: prod-airflow-token
|
||||
|
||||
.. note::
|
||||
|
||||
Remember that it is a good practice to have the production configuration on the test environment to ensure
|
||||
reliable testing before moving changes to production.
|
||||
|
||||
Migration Examples
|
||||
------------------
|
||||
|
||||
Gradual Migration from Automatic to Manual
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. Test manual configuration alongside automatic (for validation):
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values-test.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: true # Keep automatic for now
|
||||
serviceAccountTokenVolume:
|
||||
enabled: false # Disable manual for testing
|
||||
|
||||
2. Enable manual configuration while keeping automatic (transition phase):
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values-transition.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: true # Still automatic
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true # Test manual mounting
|
||||
expirationSeconds: 3600
|
||||
|
||||
3. Complete migration to manual-only:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values-final.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false # Disable automatic
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true # Use manual only
|
||||
expirationSeconds: 3600
|
||||
|
||||
Troubleshooting Examples
|
||||
------------------------
|
||||
|
||||
Debug Configuration
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Configuration with extended token lifetime for troubleshooting:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values-debug.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
expirationSeconds: 86400 # 24 hours for debugging
|
||||
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
|
||||
volumeName: debug-sa-token
|
||||
|
||||
# Enable debug logging
|
||||
config:
|
||||
logging:
|
||||
logging_level: DEBUG
|
||||
|
||||
Validation Commands
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Commands to validate the configuration is working correctly:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Check if the service account token is mounted correctly
|
||||
kubectl exec -it deployment/airflow-scheduler -- ls -la /var/run/secrets/kubernetes.io/serviceaccount/
|
||||
|
||||
# Verify token content and expiration
|
||||
kubectl exec -it deployment/airflow-scheduler -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | base64 -d
|
||||
|
||||
# Check scheduler logs for authentication issues
|
||||
kubectl logs deployment/airflow-scheduler | grep -i "auth\|token\|permission"
|
||||
|
||||
# Describe the scheduler pod to see volume mounts
|
||||
kubectl describe pod -l component=scheduler
|
||||
|
||||
Advanced Configuration Examples
|
||||
-------------------------------
|
||||
|
||||
Custom Audience Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For environments requiring specific token audiences:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
audience: "https://my-custom-api-server.example.com"
|
||||
expirationSeconds: 3600
|
||||
|
||||
Multi-Cluster Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Configuration for multi-cluster deployments:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values-cluster-a.yaml
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
audience: "https://cluster-a.k8s.example.com"
|
||||
volumeName: cluster-a-token
|
||||
expirationSeconds: 3600
|
||||
|
||||
Integration with External Security Tools
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Configuration compatible with external security scanning and policy tools:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values-security-compliant.yaml
|
||||
|
||||
# Additional security annotations
|
||||
airflowPodAnnotations:
|
||||
security.policy/scanned: "true"
|
||||
security.policy/compliant: "service-account-token-manual"
|
||||
|
||||
scheduler:
|
||||
serviceAccount:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountTokenVolume:
|
||||
enabled: true
|
||||
expirationSeconds: 1800 # Short-lived tokens
|
||||
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
|
||||
volumeName: security-compliant-token
|
||||
|
||||
Best Practices Summary
|
||||
----------------------
|
||||
|
||||
**Container Security:**
|
||||
|
||||
1. **Understand container roles**: Only the scheduler container requires Kubernetes API access
|
||||
2. **Verify token isolation**: Ensure init and sidecar containers operate without service account tokens
|
||||
3. **Implement least privilege**: Each container should receive only the minimum required permissions
|
||||
|
||||
**Configuration Management:**
|
||||
|
||||
1. **Always test** manual token configuration in non-production environments first
|
||||
2. **Use shorter token lifetimes** around 1800-3600 seconds
|
||||
3. **Set explicit audiences** when integrating with external systems
|
||||
4. **Use descriptive volume names** for easier troubleshooting and security auditing
|
||||
|
||||
**Security Monitoring:**
|
||||
|
||||
1. **Monitor logs** for authentication issues after migration
|
||||
2. **Document your configuration** for security auditing and compliance purposes
|
||||
3. **Audit container permissions** regularly to ensure compliance with security policies
|
||||
4. **Combine with other security measures** like Pod Security Standards and network policies
|
||||
|
||||
**Migration Strategy:**
|
||||
|
||||
1. **Plan gradual migration** from automatic to manual token mounting
|
||||
2. **Validate functionality** of each container type after configuration changes
|
||||
3. **Maintain backward compatibility** during transition periods
|
||||
|
||||
**Why This Approach is More Secure:**
|
||||
|
||||
1. **Reduced attack surface**: Containers without API access cannot be used to compromise the cluster
|
||||
2. **Clear security boundaries**: Explicit definition of which containers have API privileges
|
||||
3. **Compliance ready**: Meets requirements for container-specific privilege assignment
|
||||
4. **Audit friendly**: Clear documentation of security controls for compliance reporting
|
||||
|
||||
For more detailed information, see the :doc:`production-guide` section on Service Account Token Volume Configuration.
|
||||
75
charts/airflow/docs/setting-resources-for-containers.rst
Normal file
75
charts/airflow/docs/setting-resources-for-containers.rst
Normal file
@ -0,0 +1,75 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Setting resources for containers
|
||||
================================
|
||||
|
||||
It is possible to set `resources <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/>`__ for the containers managed by the chart.
|
||||
You can define different resources for various Airflow containers. By default the resources are not set.
|
||||
|
||||
.. note::
|
||||
|
||||
The Kubernetes scheduler can use resources to decide which node to place the pod on. Since a pod resource request/limit is the sum of
|
||||
the resource requests/limits for each container in the pod, it is advised to specify resources for each container in the pod.
|
||||
|
||||
Possible containers where resources can be configured include:
|
||||
|
||||
* Main Airflow containers and their sidecars. You can add the resources for these containers through the following parameters:
|
||||
|
||||
* ``workers.resources``
|
||||
* ``workers.celery.logGroomerSidecar.resources``
|
||||
* ``workers.kerberosSidecar.resources``
|
||||
* ``workers.kerberosInitContainer.resources``
|
||||
* ``scheduler.resources``
|
||||
* ``scheduler.logGroomerSidecar.resources``
|
||||
* ``dags.gitSync.resources``
|
||||
* ``apiServer.resources``
|
||||
* ``webserver.resources``
|
||||
* ``flower.resources``
|
||||
* ``dagProcessor.resources``
|
||||
* ``dagProcessor.logGroomerSidecar.resources``
|
||||
* ``triggerer.resources``
|
||||
* ``triggerer.logGroomerSidecar.resources``
|
||||
|
||||
* Containers used for Airflow Kubernetes jobs or cron jobs. You can add the resources for these containers through the following parameters:
|
||||
|
||||
* ``cleanup.resources``
|
||||
* ``createUserJob.resources``
|
||||
* ``migrateDatabaseJob.resources``
|
||||
* ``databaseCleanup.resources``
|
||||
|
||||
* Other containers that can be deployed by the chart. You can add the resources for these containers through the following parameters:
|
||||
|
||||
* ``statsd.resources``
|
||||
* ``pgbouncer.resources``
|
||||
* ``pgbouncer.metricsExporterSidecar.resources``
|
||||
* ``redis.resources``
|
||||
|
||||
For example, specifying resources for worker Kerberos sidecar:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
workers:
|
||||
kerberosSidecar:
|
||||
resources:
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
34
charts/airflow/docs/static/gh-jira-links.js
vendored
Normal file
34
charts/airflow/docs/static/gh-jira-links.js
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
/*!
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var el = document.getElementById('release-notes');
|
||||
if (el !== null ) {
|
||||
// [AIRFLOW-...]
|
||||
el.innerHTML = el.innerHTML.replace(
|
||||
/\[(AIRFLOW-[\d]+)\]/g,
|
||||
`<a href="https://issues.apache.org/jira/browse/$1">[$1]</a>`
|
||||
);
|
||||
// (#...)
|
||||
el.innerHTML = el.innerHTML.replace(
|
||||
/\(#([\d]+)\)/g,
|
||||
`<a href="https://github.com/apache/airflow/pull/$1">(#$1)</a>`
|
||||
);
|
||||
};
|
||||
})
|
||||
68
charts/airflow/docs/using-additional-containers.rst
Normal file
68
charts/airflow/docs/using-additional-containers.rst
Normal file
@ -0,0 +1,68 @@
|
||||
.. Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Using additional containers
|
||||
===========================
|
||||
|
||||
Sidecar Containers
|
||||
------------------
|
||||
|
||||
If you want to deploy your own sidecar container, you can add it through the ``extraContainers`` parameter.
|
||||
You can define different containers for the scheduler, webserver/api-server, Kubernetes/Celery workers, triggerer, dag processor, flower, create user job and migrate database job pods.
|
||||
|
||||
For example, sidecars that sync Dags from object storage:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
extraContainers:
|
||||
- name: s3-sync
|
||||
image: my-company/s3-sync:latest
|
||||
imagePullPolicy: Always
|
||||
|
||||
workers:
|
||||
kubernetes:
|
||||
extraContainers:
|
||||
- name: s3-sync
|
||||
image: my-company/s3-sync:latest
|
||||
imagePullPolicy: Always
|
||||
|
||||
.. note::
|
||||
|
||||
If you use ``workers.kubernetes.extraContainers`` (dedicated for ``KubernetesExecutor``), you are responsible for signaling
|
||||
sidecars to exit when the main container finishes so Airflow can continue the worker shutdown process.
|
||||
|
||||
|
||||
Init Containers
|
||||
---------------
|
||||
|
||||
You can also deploy extra init containers through the ``extraInitContainers`` parameter.
|
||||
You can define different containers for the scheduler, webserver/api-server, Celery/Kubernetes workers, triggerer, dag processor, create user job and migrate database job pods.
|
||||
|
||||
For example, an init container that just says hello:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: values.yaml
|
||||
|
||||
scheduler:
|
||||
extraInitContainers:
|
||||
- name: hello
|
||||
image: debian
|
||||
args:
|
||||
- echo
|
||||
- hello
|
||||
292
charts/airflow/files/pod-template-file.kubernetes-helm-yaml
Normal file
292
charts/airflow/files/pod-template-file.kubernetes-helm-yaml
Normal file
@ -0,0 +1,292 @@
|
||||
{{/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/}}
|
||||
---
|
||||
{{- $nodeSelector := or .Values.workers.kubernetes.nodeSelector .Values.workers.nodeSelector .Values.nodeSelector }}
|
||||
{{- $affinity := or .Values.workers.kubernetes.affinity .Values.workers.affinity .Values.affinity }}
|
||||
{{- $tolerations := or .Values.workers.kubernetes.tolerations .Values.workers.tolerations .Values.tolerations }}
|
||||
{{- $topologySpreadConstraints := or .Values.workers.kubernetes.topologySpreadConstraints .Values.workers.topologySpreadConstraints .Values.topologySpreadConstraints }}
|
||||
{{- $securityContext := include "airflowPodSecurityContext" (list .Values.workers.kubernetes .Values.workers .Values) }}
|
||||
{{- $containerSecurityContextKerberosSidecar := include "containerSecurityContext" (list .Values.workers.kubernetes.kerberosSidecar .Values.workers.kerberosSidecar .Values) }}
|
||||
{{- $containerLifecycleHooksKerberosSidecar := or .Values.workers.kubernetes.kerberosSidecar.containerLifecycleHooks .Values.workers.kerberosSidecar.containerLifecycleHooks .Values.containerLifecycleHooks }}
|
||||
{{- $containerSecurityContextKerberosInitContainer := include "containerSecurityContext" (list .Values.workers.kubernetes.kerberosInitContainer .Values.workers.kerberosInitContainer .Values) }}
|
||||
{{- $containerLifecycleHooksKerberosInitContainer := or .Values.workers.kubernetes.kerberosInitContainer.containerLifecycleHooks .Values.workers.kerberosInitContainer.containerLifecycleHooks .Values.containerLifecycleHooks }}
|
||||
{{- $containerSecurityContext := include "containerSecurityContext" (list .Values.workers.kubernetes .Values.workers .Values) }}
|
||||
{{- $containerLifecycleHooks := or .Values.workers.kubernetes.containerLifecycleHooks .Values.workers.containerLifecycleHooks .Values.containerLifecycleHooks }}
|
||||
{{- $safeToEvict := dict "cluster-autoscaler.kubernetes.io/safe-to-evict" (or .Values.workers.kubernetes.safeToEvict (and (not (has .Values.workers.kubernetes.safeToEvict (list true false))) .Values.workers.safeToEvict) | toString) }}
|
||||
{{- $podAnnotations := mergeOverwrite (deepCopy .Values.airflowPodAnnotations) $safeToEvict (.Values.workers.kubernetes.podAnnotations | default .Values.workers.podAnnotations) }}
|
||||
{{- $schedulerName := or .Values.workers.kubernetes.schedulerName .Values.workers.schedulerName .Values.schedulerName }}
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: placeholder-name
|
||||
labels:
|
||||
tier: airflow
|
||||
component: worker
|
||||
release: {{ .Release.Name }}
|
||||
{{- if or .Values.labels .Values.workers.labels .Values.workers.kubernetes.labels }}
|
||||
{{- mustMerge (.Values.workers.kubernetes.labels | default .Values.workers.labels) .Values.labels | toYaml | nindent 4 }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
{{- tpl (toYaml $podAnnotations) . | nindent 4 }}
|
||||
{{- if or .Values.workers.kubernetes.kerberosInitContainer.enabled .Values.workers.kerberosInitContainer.enabled }}
|
||||
checksum/kerberos-keytab: {{ include (print $.Template.BasePath "/secrets/kerberos-keytab-secret.yaml") . | sha256sum }}
|
||||
{{- end }}
|
||||
spec:
|
||||
initContainers:
|
||||
{{- if and .Values.dags.gitSync.enabled (not .Values.dags.persistence.enabled) }}
|
||||
{{- include "git_sync_container" (dict "Values" .Values "is_init" "true" "Template" .Template) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.workers.kubernetes.extraInitContainers .Values.workers.extraInitContainers }}
|
||||
{{- tpl (toYaml (.Values.workers.kubernetes.extraInitContainers | default .Values.workers.extraInitContainers)) . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.workers.kubernetes.kerberosInitContainer.enabled .Values.workers.kerberosInitContainer.enabled }}
|
||||
- name: kerberos-init
|
||||
image: {{ template "airflow_image" . }}
|
||||
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
|
||||
securityContext: {{ $containerSecurityContextKerberosInitContainer | nindent 8 }}
|
||||
{{- if $containerLifecycleHooksKerberosInitContainer }}
|
||||
lifecycle: {{- tpl (toYaml $containerLifecycleHooksKerberosInitContainer) . | nindent 8 }}
|
||||
{{- end }}
|
||||
args: ["kerberos", "-o"]
|
||||
resources: {{- toYaml (.Values.workers.kubernetes.kerberosInitContainer.resources | default .Values.workers.kerberosInitContainer.resources) | nindent 8 }}
|
||||
volumeMounts:
|
||||
- name: logs
|
||||
mountPath: {{ template "airflow_logs" . }}
|
||||
{{- if .Values.logs.persistence.subPath }}
|
||||
subPath: {{ .Values.logs.persistence.subPath }}
|
||||
{{- end }}
|
||||
{{- include "airflow_config_mount" . | nindent 8 }}
|
||||
- name: config
|
||||
mountPath: {{ .Values.kerberos.configPath | quote }}
|
||||
subPath: krb5.conf
|
||||
readOnly: true
|
||||
- name: kerberos-keytab
|
||||
subPath: "kerberos.keytab"
|
||||
mountPath: {{ .Values.kerberos.keytabPath | quote }}
|
||||
readOnly: true
|
||||
- name: kerberos-ccache
|
||||
mountPath: {{ .Values.kerberos.ccacheMountPath | quote }}
|
||||
readOnly: false
|
||||
{{- if .Values.volumeMounts }}
|
||||
{{- toYaml .Values.volumeMounts | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.workers.extraVolumeMounts .Values.workers.kubernetes.extraVolumeMounts }}
|
||||
{{- tpl (toYaml (.Values.workers.kubernetes.extraVolumeMounts | default .Values.workers.extraVolumeMounts)) . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=3.0.0" .Values.airflowVersion }}
|
||||
{{- if or .Values.apiServer.apiServerConfig .Values.apiServer.apiServerConfigConfigMapName }}
|
||||
{{- include "airflow_api_server_config_mount" . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if or .Values.webserver.webserverConfig .Values.webserver.webserverConfigConfigMapName }}
|
||||
{{- include "airflow_webserver_config_mount" . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
envFrom: {{- include "custom_airflow_environment_from" . | default "\n []" | indent 6 }}
|
||||
env:
|
||||
- name: KRB5_CONFIG
|
||||
value: {{ .Values.kerberos.configPath | quote }}
|
||||
- name: KRB5CCNAME
|
||||
value: {{ include "kerberos_ccache_path" . | quote }}
|
||||
{{- include "custom_airflow_environment" . | indent 6 }}
|
||||
{{- include "standard_airflow_environment" . | indent 6 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- envFrom: {{- include "custom_airflow_environment_from" . | default "\n []" | indent 6 }}
|
||||
env:
|
||||
- name: AIRFLOW__CORE__EXECUTOR
|
||||
value: {{ .Values.executor | quote }}
|
||||
{{- if or .Values.workers.kubernetes.kerberosSidecar.enabled .Values.workers.kerberosSidecar.enabled .Values.workers.kubernetes.kerberosInitContainer.enabled .Values.workers.kerberosInitContainer.enabled }}
|
||||
- name: KRB5_CONFIG
|
||||
value: {{ .Values.kerberos.configPath | quote }}
|
||||
- name: KRB5CCNAME
|
||||
value: {{ include "kerberos_ccache_path" . | quote }}
|
||||
{{- end }}
|
||||
{{- include "standard_airflow_environment" . | indent 6}}
|
||||
{{- include "custom_airflow_environment" . | indent 6 }}
|
||||
{{- include "container_extra_envs" (list . (.Values.workers.kubernetes.env | default .Values.workers.env)) | indent 6 }}
|
||||
image: {{ template "pod_template_image" . }}
|
||||
imagePullPolicy: {{ .Values.images.pod_template.pullPolicy }}
|
||||
securityContext: {{ $containerSecurityContext | nindent 8 }}
|
||||
{{- if $containerLifecycleHooks }}
|
||||
lifecycle: {{- tpl (toYaml $containerLifecycleHooks) . | nindent 8 }}
|
||||
{{- end }}
|
||||
name: base
|
||||
{{- if or .Values.workers.kubernetes.command .Values.workers.command }}
|
||||
command: {{ tpl (toYaml (.Values.workers.kubernetes.command | default .Values.workers.command)) . | nindent 8 }}
|
||||
{{- end }}
|
||||
resources: {{- toYaml (.Values.workers.kubernetes.resources | default .Values.workers.resources) | nindent 8 }}
|
||||
volumeMounts:
|
||||
- mountPath: {{ template "airflow_logs" . }}
|
||||
name: logs
|
||||
{{- if .Values.logs.persistence.subPath }}
|
||||
subPath: {{ .Values.logs.persistence.subPath }}
|
||||
{{- end }}
|
||||
{{- include "airflow_config_mount" . | nindent 8 }}
|
||||
{{- if or .Values.dags.gitSync.enabled .Values.dags.persistence.enabled }}
|
||||
{{- include "airflow_dags_mount" . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.volumeMounts }}
|
||||
{{- toYaml .Values.volumeMounts | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.workers.extraVolumeMounts .Values.workers.kubernetes.extraVolumeMounts }}
|
||||
{{- tpl (toYaml (.Values.workers.kubernetes.extraVolumeMounts | default .Values.workers.extraVolumeMounts)) . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberos.enabled }}
|
||||
- name: kerberos-keytab
|
||||
subPath: "kerberos.keytab"
|
||||
mountPath: {{ .Values.kerberos.keytabPath | quote }}
|
||||
readOnly: true
|
||||
- name: config
|
||||
mountPath: {{ .Values.kerberos.configPath | quote }}
|
||||
subPath: krb5.conf
|
||||
readOnly: true
|
||||
- name: kerberos-ccache
|
||||
mountPath: {{ .Values.kerberos.ccacheMountPath | quote }}
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{- if or .Values.workers.kubernetes.kerberosSidecar.enabled .Values.workers.kerberosSidecar.enabled }}
|
||||
- name: worker-kerberos
|
||||
image: {{ template "airflow_image" . }}
|
||||
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
|
||||
securityContext: {{ $containerSecurityContextKerberosSidecar | nindent 8 }}
|
||||
{{- if $containerLifecycleHooksKerberosSidecar }}
|
||||
lifecycle: {{- tpl (toYaml $containerLifecycleHooksKerberosSidecar) . | nindent 8 }}
|
||||
{{- end }}
|
||||
args: ["kerberos"]
|
||||
resources: {{- toYaml (.Values.workers.kubernetes.kerberosSidecar.resources | default .Values.workers.kerberosSidecar.resources) | nindent 8 }}
|
||||
volumeMounts:
|
||||
- name: logs
|
||||
mountPath: {{ template "airflow_logs" . }}
|
||||
{{- if .Values.logs.persistence.subPath }}
|
||||
subPath: {{ .Values.logs.persistence.subPath }}
|
||||
{{- end }}
|
||||
{{- include "airflow_config_mount" . | nindent 8 }}
|
||||
- name: config
|
||||
mountPath: {{ .Values.kerberos.configPath | quote }}
|
||||
subPath: krb5.conf
|
||||
readOnly: true
|
||||
- name: kerberos-keytab
|
||||
subPath: "kerberos.keytab"
|
||||
mountPath: {{ .Values.kerberos.keytabPath | quote }}
|
||||
readOnly: true
|
||||
- name: kerberos-ccache
|
||||
mountPath: {{ .Values.kerberos.ccacheMountPath | quote }}
|
||||
readOnly: false
|
||||
{{- if .Values.volumeMounts }}
|
||||
{{- toYaml .Values.volumeMounts | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.workers.extraVolumeMounts .Values.workers.kubernetes.extraVolumeMounts }}
|
||||
{{- tpl (toYaml (.Values.workers.kubernetes.extraVolumeMounts | default .Values.workers.extraVolumeMounts)) . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=3.0.0" .Values.airflowVersion }}
|
||||
{{- if or .Values.apiServer.apiServerConfig .Values.apiServer.apiServerConfigConfigMapName }}
|
||||
{{- include "airflow_api_server_config_mount" . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if or .Values.webserver.webserverConfig .Values.webserver.webserverConfigConfigMapName }}
|
||||
{{- include "airflow_webserver_config_mount" . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
envFrom: {{- include "custom_airflow_environment_from" . | default "\n []" | indent 6 }}
|
||||
env:
|
||||
- name: KRB5_CONFIG
|
||||
value: {{ .Values.kerberos.configPath | quote }}
|
||||
- name: KRB5CCNAME
|
||||
value: {{ include "kerberos_ccache_path" . | quote }}
|
||||
{{- include "custom_airflow_environment" . | indent 6 }}
|
||||
{{- include "standard_airflow_environment" . | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.workers.kubernetes.extraContainers .Values.workers.extraContainers }}
|
||||
{{- tpl (toYaml (.Values.workers.kubernetes.extraContainers | default .Values.workers.extraContainers)) . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.workers.kubernetes.priorityClassName .Values.workers.priorityClassName }}
|
||||
priorityClassName: {{ .Values.workers.kubernetes.priorityClassName | default .Values.workers.priorityClassName }}
|
||||
{{- end }}
|
||||
{{- if or .Values.workers.kubernetes.runtimeClassName .Values.workers.runtimeClassName }}
|
||||
runtimeClassName: {{ .Values.workers.kubernetes.runtimeClassName | default .Values.workers.runtimeClassName }}
|
||||
{{- end }}
|
||||
imagePullSecrets: {{- include "image_pull_secrets" . | nindent 4 }}
|
||||
{{- if or .Values.workers.kubernetes.hostAliases .Values.workers.hostAliases }}
|
||||
hostAliases: {{- toYaml (.Values.workers.kubernetes.hostAliases | default .Values.workers.hostAliases) | nindent 4 }}
|
||||
{{- end }}
|
||||
restartPolicy: Never
|
||||
securityContext: {{ $securityContext | nindent 4 }}
|
||||
nodeSelector: {{- toYaml $nodeSelector | nindent 4 }}
|
||||
affinity: {{- toYaml $affinity | nindent 4 }}
|
||||
{{- if $schedulerName }}
|
||||
schedulerName: {{ $schedulerName }}
|
||||
{{- end }}
|
||||
terminationGracePeriodSeconds: {{ .Values.workers.kubernetes.terminationGracePeriodSeconds | default .Values.workers.terminationGracePeriodSeconds }}
|
||||
tolerations: {{- toYaml $tolerations | nindent 4 }}
|
||||
topologySpreadConstraints: {{- toYaml $topologySpreadConstraints | nindent 4 }}
|
||||
{{- if .Values.workers.kubernetes.serviceAccount.create }}
|
||||
serviceAccountName: {{ include "worker.kubernetes.serviceAccountName" . }}
|
||||
{{- else }}
|
||||
serviceAccountName: {{ include "worker.serviceAccountName" . }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
{{- if .Values.dags.persistence.enabled }}
|
||||
- name: dags
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ template "airflow_dags_volume_claim" . }}
|
||||
{{- else if .Values.dags.gitSync.enabled }}
|
||||
- name: dags
|
||||
emptyDir: {{- toYaml (default (dict) .Values.dags.gitSync.emptyDirConfig) | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.logs.persistence.enabled }}
|
||||
- name: logs
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ template "airflow_logs_volume_claim" . }}
|
||||
{{- else }}
|
||||
- emptyDir: {{- toYaml (default (dict) .Values.logs.emptyDirConfig) | nindent 6 }}
|
||||
name: logs
|
||||
{{- end }}
|
||||
{{- if and .Values.dags.gitSync.enabled (or .Values.dags.gitSync.sshKeySecret .Values.dags.gitSync.sshKey) }}
|
||||
{{- include "git_sync_ssh_key_volume" . | nindent 2 }}
|
||||
{{- end }}
|
||||
- configMap:
|
||||
name: {{ include "airflow_config" . }}
|
||||
name: config
|
||||
{{- if semverCompare ">=3.0.0" .Values.airflowVersion }}
|
||||
{{- if and (or .Values.apiServer.apiServerConfig .Values.apiServer.apiServerConfigConfigMapName) (or .Values.workers.kubernetes.kerberosInitContainer.enabled .Values.workers.kerberosInitContainer.enabled .Values.workers.kubernetes.kerberosSidecar.enabled .Values.workers.kerberosSidecar.enabled) }}
|
||||
- name: api-server-config
|
||||
configMap:
|
||||
name: {{ template "airflow_api_server_config_configmap_name" . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- if and (or .Values.webserver.webserverConfig .Values.webserver.webserverConfigConfigMapName) (or .Values.workers.kubernetes.kerberosInitContainer.enabled .Values.workers.kerberosInitContainer.enabled .Values.workers.kubernetes.kerberosSidecar.enabled .Values.workers.kerberosSidecar.enabled) }}
|
||||
- name: webserver-config
|
||||
configMap:
|
||||
name: {{ template "airflow_webserver_config_configmap_name" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.volumes }}
|
||||
{{- toYaml .Values.volumes | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberos.enabled }}
|
||||
- name: kerberos-keytab
|
||||
secret:
|
||||
secretName: {{ include "kerberos_keytab_secret" . | quote }}
|
||||
- name: kerberos-ccache
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- if or .Values.workers.kubernetes.extraVolumes .Values.workers.extraVolumes }}
|
||||
{{- tpl (toYaml (.Values.workers.kubernetes.extraVolumes | default .Values.workers.extraVolumes)) . | nindent 2 }}
|
||||
{{- end }}
|
||||
142
charts/airflow/files/statsd-mappings.yml
Normal file
142
charts/airflow/files/statsd-mappings.yml
Normal file
@ -0,0 +1,142 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
---
|
||||
# {{/*
|
||||
# WARNING: Be aware that most changes to these mappings will break backwards compatibility!
|
||||
# E.g. moving to labels will break existing dashboards.
|
||||
# instead utilize `statsd.extraMappings` or `statsd.overrideMappings` in your environment,
|
||||
# until we have version 2 of the helm chart.
|
||||
# */}}
|
||||
mappings:
|
||||
# Map dot separated stats to labels
|
||||
- match: airflow.dagrun.dependency-check.*.*
|
||||
name: "airflow_dagrun_dependency_check"
|
||||
labels:
|
||||
dag_id: "$1"
|
||||
|
||||
- match: airflow.operator_successes_(.*)
|
||||
match_type: regex
|
||||
name: "airflow_operator_successes"
|
||||
labels:
|
||||
operator: "$1"
|
||||
|
||||
- match: airflow.operator_failures_(.*)
|
||||
match_type: regex
|
||||
name: "airflow_operator_failures"
|
||||
labels:
|
||||
operator: "$1"
|
||||
|
||||
- match: airflow.scheduler_heartbeat
|
||||
match_type: regex
|
||||
name: "airflow_scheduler_heartbeat"
|
||||
labels:
|
||||
type: counter
|
||||
|
||||
- match: airflow.dag_processor_heartbeat
|
||||
match_type: regex
|
||||
name: "airflow_dag_processor_heartbeat"
|
||||
labels:
|
||||
type: counter
|
||||
|
||||
- match: airflow.dag.*.*.duration
|
||||
name: "airflow_task_duration"
|
||||
labels:
|
||||
dag_id: "$1"
|
||||
task_id: "$2"
|
||||
|
||||
- match: airflow.dagrun.duration.success.*
|
||||
name: "airflow_dagrun_duration"
|
||||
labels:
|
||||
dag_id: "$1"
|
||||
|
||||
- match: airflow.dagrun.duration.failed.*
|
||||
name: "airflow_dagrun_failed"
|
||||
labels:
|
||||
dag_id: "$1"
|
||||
|
||||
- match: airflow.dagrun.schedule_delay.*
|
||||
name: "airflow_dagrun_schedule_delay"
|
||||
labels:
|
||||
dag_id: "$1"
|
||||
|
||||
- match: airflow.dag_processing.last_runtime.*
|
||||
name: "airflow_dag_processing_last_runtime"
|
||||
labels:
|
||||
dag_file: "$1"
|
||||
|
||||
- match: airflow.dag_processing.last_run.seconds_ago.*
|
||||
name: "airflow_dag_processing_last_run_seconds_ago"
|
||||
labels:
|
||||
dag_file: "$1"
|
||||
|
||||
- match: airflow.pool.open_slots.*
|
||||
name: "airflow_pool_open_slots"
|
||||
labels:
|
||||
pool: "$1"
|
||||
|
||||
- match: airflow.pool.used_slots.*
|
||||
name: "airflow_pool_used_slots"
|
||||
labels:
|
||||
pool: "$1"
|
||||
|
||||
- match: airflow.pool.starving_tasks.*
|
||||
name: "airflow_pool_starving_tasks"
|
||||
labels:
|
||||
pool: "$1"
|
||||
|
||||
- match: airflow.executor.open_slots.*
|
||||
name: "airflow_executor_open_slots"
|
||||
labels:
|
||||
executor: "$1"
|
||||
|
||||
- match: airflow.executor.queued_tasks.*
|
||||
name: "airflow_executor_queued_tasks"
|
||||
labels:
|
||||
executor: "$1"
|
||||
|
||||
- match: airflow.executor.running_tasks.*
|
||||
name: "airflow_executor_running_tasks"
|
||||
labels:
|
||||
executor: "$1"
|
||||
|
||||
- match: airflow.ti.running.*.*.*
|
||||
name: "airflow_ti_running"
|
||||
labels:
|
||||
queue: "$1"
|
||||
dag_id: "$2"
|
||||
task_id: "$3"
|
||||
|
||||
- match: airflow.ti.queued.*.*.*
|
||||
name: "airflow_ti_queued"
|
||||
labels:
|
||||
queue: "$1"
|
||||
dag_id: "$2"
|
||||
task_id: "$3"
|
||||
|
||||
- match: airflow.ti.scheduled.*.*.*
|
||||
name: "airflow_ti_scheduled"
|
||||
labels:
|
||||
queue: "$1"
|
||||
dag_id: "$2"
|
||||
task_id: "$3"
|
||||
|
||||
- match: airflow.ti.deferred.*.*.*
|
||||
name: "airflow_ti_deferred"
|
||||
labels:
|
||||
queue: "$1"
|
||||
dag_id: "$2"
|
||||
task_id: "$3"
|
||||
50
charts/airflow/newsfragments/config.toml
Normal file
50
charts/airflow/newsfragments/config.toml
Normal file
@ -0,0 +1,50 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
[tool.towncrier]
|
||||
name = "Airflow Helm Chart"
|
||||
filename = "RELEASE_NOTES.rst"
|
||||
underlines = ["-", '^']
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "significant"
|
||||
name = "Significant Changes"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "feature"
|
||||
name = "Features"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "improvement"
|
||||
name = "Improvements"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "bugfix"
|
||||
name = "Bug Fixes"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "doc"
|
||||
name = "Doc only Changes"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "misc"
|
||||
name = "Misc"
|
||||
showcontent = true
|
||||
85
charts/airflow/pyproject.toml
Normal file
85
charts/airflow/pyproject.toml
Normal file
@ -0,0 +1,85 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
[build-system]
|
||||
requires = [
|
||||
"hatchling==1.29.0",
|
||||
"packaging==26.0",
|
||||
"pathspec==1.0.4",
|
||||
"pluggy==1.6.0",
|
||||
"tomli==2.4.0; python_version < '3.11'",
|
||||
"trove-classifiers==2026.1.14.14",
|
||||
]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "apache-airflow-helm-chart"
|
||||
description = "Programmatically author, schedule and monitor data pipelines"
|
||||
requires-python = ">=3.10,!=3.15"
|
||||
authors = [
|
||||
{ name = "Apache Software Foundation", email = "dev@airflow.apache.org" },
|
||||
]
|
||||
maintainers = [
|
||||
{ name = "Apache Software Foundation", email="dev@airflow.apache.org" },
|
||||
]
|
||||
keywords = [ "airflow", "orchestration", "workflow", "dag", "pipelines", "automation", "data" ]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Environment :: Console",
|
||||
"Environment :: Web Environment",
|
||||
"Framework :: Apache Airflow",
|
||||
"Intended Audience :: Developers",
|
||||
"Intended Audience :: System Administrators",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3.14",
|
||||
"Topic :: System :: Monitoring",
|
||||
"Topic :: System :: Monitoring",
|
||||
]
|
||||
|
||||
version = "0.0.1"
|
||||
|
||||
dependencies = [
|
||||
"apache-airflow-core",
|
||||
]
|
||||
|
||||
[tool.hatch.build.targets.sdist]
|
||||
exclude = ["*"]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
bypass-selection = true
|
||||
|
||||
[dependency-groups]
|
||||
# To build docs run:
|
||||
#
|
||||
# uv run --group docs sphinx-build -T --color -b html . _build
|
||||
#
|
||||
# To check spelling:
|
||||
#
|
||||
# uv run --group docs sphinx-build -T --color -b spelling . _build
|
||||
#
|
||||
# To enable auto-refreshing build with server:
|
||||
#
|
||||
# uv run --group docs sphinx-autobuild -T --color -b html . _build
|
||||
#
|
||||
docs = [
|
||||
"apache-airflow-devel-common[docs]"
|
||||
]
|
||||
|
||||
packages = []
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user