This is an automated email from the ASF dual-hosted git repository.
jscheffl pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new c85246ce9bf Add missing support for: securityContexts and
containerLifecycleHooks (#60677)
c85246ce9bf is described below
commit c85246ce9bffbcd4d52e674e266086351dd94315
Author: Henry Chen <[email protected]>
AuthorDate: Wed Feb 25 06:34:20 2026 +0800
Add missing support for: securityContexts and containerLifecycleHooks
(#60677)
* keep consistency
* support kerberos init securityContext/lifecycle in workers
---
chart/files/pod-template-file.kubernetes-helm-yaml | 6 ++
chart/templates/workers/worker-deployment.yaml | 6 ++
.../airflow_aux/test_pod_template_file.py | 102 +++++++++++++++++++++
.../tests/helm_tests/airflow_core/test_worker.py | 59 ++++++++++++
.../helm_tests/airflow_core/test_worker_sets.py | 102 +++++++++++++++++++++
.../helm_tests/security/test_security_context.py | 43 +++++++++
6 files changed, 318 insertions(+)
diff --git a/chart/files/pod-template-file.kubernetes-helm-yaml
b/chart/files/pod-template-file.kubernetes-helm-yaml
index 51d2c50e63c..05be0e210db 100644
--- a/chart/files/pod-template-file.kubernetes-helm-yaml
+++ b/chart/files/pod-template-file.kubernetes-helm-yaml
@@ -24,6 +24,8 @@
{{- $securityContext := include "airflowPodSecurityContext" (list
.Values.workers.kubernetes .Values.workers .Values) }}
{{- $containerSecurityContextKerberosSidecar := include
"containerSecurityContext" (list .Values.workers.kerberosSidecar .Values) }}
{{- $containerLifecycleHooksKerberosSidecar := or
.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.containerLifecycleHooks
.Values.containerLifecycleHooks }}
{{- $safeToEvict := dict "cluster-autoscaler.kubernetes.io/safe-to-evict"
(.Values.workers.safeToEvict | toString) }}
@@ -57,6 +59,10 @@ spec:
- 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:
diff --git a/chart/templates/workers/worker-deployment.yaml
b/chart/templates/workers/worker-deployment.yaml
index 1ae802555c5..93e7efcdb7e 100644
--- a/chart/templates/workers/worker-deployment.yaml
+++ b/chart/templates/workers/worker-deployment.yaml
@@ -48,6 +48,8 @@
{{- $containerSecurityContextWaitForMigrations := include
"containerSecurityContext" (list .Values.workers.waitForMigrations .Values) }}
{{- $containerSecurityContextLogGroomerSidecar := include
"containerSecurityContext" (list .Values.workers.logGroomerSidecar .Values) }}
{{- $containerSecurityContextKerberosSidecar := include
"containerSecurityContext" (list .Values.workers.kerberosSidecar .Values) }}
+{{- $containerSecurityContextKerberosInitContainer := include
"containerSecurityContext" (list .Values.workers.kerberosInitContainer .Values)
}}
+{{- $containerLifecycleHooksKerberosInitContainer := or
.Values.workers.kerberosInitContainer.containerLifecycleHooks
.Values.containerLifecycleHooks }}
{{- $containerLifecycleHooks := or .Values.workers.containerLifecycleHooks
.Values.containerLifecycleHooks }}
{{- $containerLifecycleHooksLogGroomerSidecar := or
.Values.workers.logGroomerSidecar.containerLifecycleHooks
.Values.containerLifecycleHooks }}
{{- $containerLifecycleHooksKerberosSidecar := or
.Values.workers.kerberosSidecar.containerLifecycleHooks
.Values.containerLifecycleHooks }}
@@ -180,6 +182,10 @@ spec:
{{- if and (semverCompare ">=2.8.0" .Values.airflowVersion)
.Values.workers.kerberosInitContainer.enabled }}
- name: kerberos-init
image: {{ template "airflow_image" . }}
+ securityContext: {{ $containerSecurityContextKerberosInitContainer |
nindent 12 }}
+ {{- if $containerLifecycleHooksKerberosInitContainer }}
+ lifecycle: {{- tpl (toYaml
$containerLifecycleHooksKerberosInitContainer) . | nindent 12 }}
+ {{- end }}
imagePullPolicy: {{ .Values.images.airflow.pullPolicy }}
args: ["kerberos", "-o"]
resources: {{- toYaml
.Values.workers.kerberosInitContainer.resources | nindent 12 }}
diff --git a/helm-tests/tests/helm_tests/airflow_aux/test_pod_template_file.py
b/helm-tests/tests/helm_tests/airflow_aux/test_pod_template_file.py
index b9678ada1e5..bfce878fcd0 100644
--- a/helm-tests/tests/helm_tests/airflow_aux/test_pod_template_file.py
+++ b/helm-tests/tests/helm_tests/airflow_aux/test_pod_template_file.py
@@ -1384,3 +1384,105 @@ class TestPodTemplateFile:
"memory": "4Mi",
},
}
+
+ @pytest.mark.parametrize(
+ "workers_values",
+ [
+ {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "securityContexts": {"container": {"runAsUser": 2000}},
+ }
+ },
+ {
+ "kubernetes": {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "securityContexts": {"container": {"runAsUser": 2000}},
+ }
+ }
+ },
+ {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "securityContexts": {"container": {"runAsUser": 1000}},
+ },
+ "kubernetes": {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "securityContexts": {"container": {"runAsUser": 2000}},
+ }
+ },
+ },
+ ],
+ )
+ def test_kerberos_init_container_security_context(self, workers_values):
+ docs = render_chart(
+ values={
+ "workers": workers_values,
+ },
+ show_only=["templates/pod-template-file.yaml"],
+ chart_dir=self.temp_chart_dir,
+ )
+
+ assert jmespath.search(
+ "spec.initContainers[?name=='kerberos-init'] |
[0].securityContext", docs[0]
+ ) == {"runAsUser": 2000}
+
+ @pytest.mark.parametrize(
+ ("workers_values", "expected"),
+ [
+ (
+ {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "containerLifecycleHooks": {"postStart": {"exec":
{"command": ["echo", "base"]}}},
+ }
+ },
+ {"postStart": {"exec": {"command": ["echo", "base"]}}},
+ ),
+ (
+ {
+ "kubernetes": {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "containerLifecycleHooks": {
+ "postStart": {"exec": {"command": ["echo",
"kubernetes"]}}
+ },
+ }
+ }
+ },
+ {"postStart": {"exec": {"command": ["echo", "kubernetes"]}}},
+ ),
+ (
+ {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "containerLifecycleHooks": {"preStop": {"exec":
{"command": ["echo", "base"]}}},
+ },
+ "kubernetes": {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "containerLifecycleHooks": {
+ "postStart": {"exec": {"command": ["echo",
"kubernetes"]}}
+ },
+ }
+ },
+ },
+ {"postStart": {"exec": {"command": ["echo", "kubernetes"]}}},
+ ),
+ ],
+ )
+ def test_kerberos_init_container_lifecycle_hooks(self, workers_values,
expected):
+ docs = render_chart(
+ values={
+ "workers": workers_values,
+ },
+ show_only=["templates/pod-template-file.yaml"],
+ chart_dir=self.temp_chart_dir,
+ )
+
+ assert (
+ jmespath.search("spec.initContainers[?name=='kerberos-init'] |
[0].lifecycle", docs[0])
+ == expected
+ )
diff --git a/helm-tests/tests/helm_tests/airflow_core/test_worker.py
b/helm-tests/tests/helm_tests/airflow_core/test_worker.py
index 9d02691aad3..a8b93bb5f2e 100644
--- a/helm-tests/tests/helm_tests/airflow_core/test_worker.py
+++ b/helm-tests/tests/helm_tests/airflow_core/test_worker.py
@@ -1050,6 +1050,65 @@ class TestWorker:
},
}
+ @pytest.mark.parametrize(
+ ("workers_values", "expected"),
+ [
+ (
+ {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "containerLifecycleHooks": {"postStart": {"exec":
{"command": ["echo", "base"]}}},
+ }
+ },
+ {"postStart": {"exec": {"command": ["echo", "base"]}}},
+ ),
+ (
+ {
+ "celery": {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "containerLifecycleHooks": {
+ "postStart": {"exec": {"command": ["echo",
"celery"]}}
+ },
+ }
+ }
+ },
+ {"postStart": {"exec": {"command": ["echo", "celery"]}}},
+ ),
+ (
+ {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "containerLifecycleHooks": {"postStart": {"exec":
{"command": ["echo", "base"]}}},
+ },
+ "celery": {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "containerLifecycleHooks": {
+ "postStart": {"exec": {"command": ["echo",
"celery"]}}
+ },
+ }
+ },
+ },
+ {"postStart": {"exec": {"command": ["echo", "celery"]}}},
+ ),
+ ],
+ )
+ def test_kerberos_init_container_lifecycle_hooks(self, workers_values,
expected):
+ docs = render_chart(
+ values={
+ "workers": workers_values,
+ },
+ show_only=["templates/workers/worker-deployment.yaml"],
+ )
+
+ assert (
+ jmespath.search(
+ "spec.template.spec.initContainers[?name=='kerberos-init'] |
[0].lifecycle", docs[0]
+ )
+ == expected
+ )
+
@pytest.mark.parametrize(
("airflow_version", "expected_arg"),
[
diff --git a/helm-tests/tests/helm_tests/airflow_core/test_worker_sets.py
b/helm-tests/tests/helm_tests/airflow_core/test_worker_sets.py
index 44188918d70..1434094172a 100644
--- a/helm-tests/tests/helm_tests/airflow_core/test_worker_sets.py
+++ b/helm-tests/tests/helm_tests/airflow_core/test_worker_sets.py
@@ -841,6 +841,108 @@ class TestWorkerSets:
"limits": {"cpu": "3m", "memory": "4Mi"},
}
+ @pytest.mark.parametrize(
+ "values",
+ [
+ {
+ "celery": {
+ "enableDefault": False,
+ "sets": [
+ {
+ "name": "test",
+ "kerberosInitContainer": {
+ "enabled": True,
+ "securityContexts": {
+ "container": {"runAsUser": 10},
+ },
+ },
+ }
+ ],
+ }
+ },
+ {
+ "kerberosInitContainer": {
+ "securityContexts": {
+ "container": {"allowPrivilegeEscalation": False},
+ }
+ },
+ "celery": {
+ "enableDefault": False,
+ "sets": [
+ {
+ "name": "test",
+ "kerberosInitContainer": {
+ "enabled": True,
+ "securityContexts": {
+ "container": {"runAsUser": 10},
+ },
+ },
+ }
+ ],
+ },
+ },
+ ],
+ )
+ def test_overwrite_kerberos_init_container_security_context(self, values):
+ docs = render_chart(
+ values={"workers": values},
+ show_only=["templates/workers/worker-deployment.yaml"],
+ )
+
+ assert jmespath.search(
+ "spec.template.spec.initContainers[?name=='kerberos-init'] |
[0].securityContext", docs[0]
+ ) == {"runAsUser": 10}
+
+ @pytest.mark.parametrize(
+ "values",
+ [
+ {
+ "celery": {
+ "enableDefault": False,
+ "sets": [
+ {
+ "name": "test",
+ "kerberosInitContainer": {
+ "enabled": True,
+ "containerLifecycleHooks": {
+ "postStart": {"exec": {"command": ["echo",
"{{ .Release.Name }}"]}},
+ },
+ },
+ }
+ ],
+ }
+ },
+ {
+ "kerberosInitContainer": {
+ "containerLifecycleHooks": {"preStop": {"exec":
{"command": ["echo", "test"]}}}
+ },
+ "celery": {
+ "enableDefault": False,
+ "sets": [
+ {
+ "name": "test",
+ "kerberosInitContainer": {
+ "enabled": True,
+ "containerLifecycleHooks": {
+ "postStart": {"exec": {"command": ["echo",
"{{ .Release.Name }}"]}},
+ },
+ },
+ }
+ ],
+ },
+ },
+ ],
+ )
+ def test_overwrite_kerberos_init_container_lifecycle_hooks(self, values):
+ docs = render_chart(
+ values={"workers": values},
+ show_only=["templates/workers/worker-deployment.yaml"],
+ )
+
+ assert jmespath.search(
+ "spec.template.spec.initContainers[?name=='kerberos-init'] |
[0].lifecycle", docs[0]
+ ) == {"postStart": {"exec": {"command": ["echo", "release-name"]}}}
+
def test_overwrite_container_lifecycle_hooks(self):
docs = render_chart(
values={
diff --git a/helm-tests/tests/helm_tests/security/test_security_context.py
b/helm-tests/tests/helm_tests/security/test_security_context.py
index 916365e155e..1738520702a 100644
--- a/helm-tests/tests/helm_tests/security/test_security_context.py
+++ b/helm-tests/tests/helm_tests/security/test_security_context.py
@@ -632,6 +632,49 @@ class TestSecurityContext:
assert ctx_value ==
jmespath.search("spec.template.spec.containers[2].securityContext", docs[0])
+ @pytest.mark.parametrize(
+ "workers_values",
+ [
+ {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "securityContexts": {"container": {"runAsUser": 2000}},
+ }
+ },
+ {
+ "celery": {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "securityContexts": {"container": {"runAsUser": 2000}},
+ }
+ }
+ },
+ {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "securityContexts": {"container": {"runAsUser": 1000}},
+ },
+ "celery": {
+ "kerberosInitContainer": {
+ "enabled": True,
+ "securityContexts": {"container": {"runAsUser": 2000}},
+ }
+ },
+ },
+ ],
+ )
+ def test_worker_kerberos_init_container_security_context(self,
workers_values):
+ docs = render_chart(
+ values={
+ "workers": workers_values,
+ },
+ show_only=["templates/workers/worker-deployment.yaml"],
+ )
+
+ assert jmespath.search(
+ "spec.template.spec.initContainers[?name=='kerberos-init'] |
[0].securityContext", docs[0]
+ ) == {"runAsUser": 2000}
+
# Test securityContexts for the wait-for-migrations init containers
def test_wait_for_migrations_init_container_setting_airflow_2(self):
ctx_value = {"allowPrivilegeEscalation": False}