Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/content/docs/operations/helm.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ The configurable parameters of the Helm chart and which default values as detail
| webhook.validator.create | Enable or disable validating webhook, overrides `webhook.create` | |
| webhook.keystore | The ConfigMap of webhook key store. | useDefaultPassword: true |
| webhook.serviceLabels | The labels for flink-operator-webhook-service-resource. | |
| blueGreenAdmissionPolicy.create | Whether to enable ValidatingAdmissionPolicy for protecting Blue/Green child deployments. | true |
| blueGreenAdmissionPolicy.failurePolicy | What happens if policy evaluation fails (Fail = block requests, Ignore = allow on policy errors). | Fail |
| blueGreenAdmissionPolicy.validationActions | Action to take on validation failures (Deny = block the request). | [Deny] |
| defaultConfiguration.create | Whether to enable default configuration to create for flink-kubernetes-operator. | true |
| defaultConfiguration.append | Whether to append configuration files with configs. | true |
| defaultConfiguration.flink-conf.yaml | The default configuration of flink-conf.yaml. | kubernetes.operator.metrics.reporter.slf4j.factory.class: org.apache.flink.metrics.slf4j.Slf4jReporterFactory<br/>kubernetes.operator.metrics.reporter.slf4j.interval: 5 MINUTE<br/>kubernetes.operator.reconcile.interval: 15 s<br/>kubernetes.operator.observer.progress-check.interval: 5 s |
Expand Down Expand Up @@ -144,6 +147,10 @@ kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.1

The webhooks can be disabled during helm install by passing the `--set webhook.create=false` parameter or editing the `values.yaml` directly.

## Blue/Green Admission Policy

If using `FlinkBlueGreenDeployment`, you should enable a `ValidatingAdmissionPolicy` to protect child FlinkDeployments from direct modifications by passing `--set blueGreenAdmissionPolicy.create=true`. This policy only affects FlinkDeployments owned by a FlinkBlueGreenDeployment, allowing updates only from the operator's service account. Requires Kubernetes 1.26+ (beta) or 1.30+ (GA). When rendering templates with `helm template`, ensure `--namespace` matches where the operator is deployed.

## Watching only specific namespaces

The operator supports watching a specific list of namespaces for FlinkDeployment resources. You can enable it by setting the `--set watchNamespaces={flink-test}` parameter.
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*/}}

{{/*
ValidatingAdmissionPolicy to prevent direct modifications to FlinkDeployments
that are managed by a FlinkBlueGreenDeployment.

This policy uses CEL expressions evaluated by the Kubernetes API server directly,
requiring no webhook server. Requires Kubernetes 1.30+ (GA) or 1.26+ (beta with
feature gate enabled).

When a user tries to UPDATE a FlinkDeployment that has an ownerReference to a
FlinkBlueGreenDeployment, the request is denied unless it comes from the
operator's service account.
*/}}

{{- if .Values.blueGreenAdmissionPolicy.create }}
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: {{ include "flink-operator.name" . }}-block-bluegreen-direct-updates
labels:
{{- include "flink-operator.labels" . | nindent 4 }}
spec:
failurePolicy: {{ .Values.blueGreenAdmissionPolicy.failurePolicy | default "Fail" }}
matchConstraints:
resourceRules:
- apiGroups: ["flink.apache.org"]
apiVersions: ["*"]
operations: ["UPDATE"]
resources: ["flinkdeployments"]
validations:
- expression: |
!has(object.metadata.ownerReferences) ||
!object.metadata.ownerReferences.exists(ref, ref.kind == 'FlinkBlueGreenDeployment') ||
request.userInfo.username == 'system:serviceaccount:{{ .Release.Namespace }}:{{ include "flink-operator.serviceAccountName" . }}'
message: >-
FlinkDeployments managed by FlinkBlueGreenDeployment cannot be modified directly.
Please update the parent FlinkBlueGreenDeployment instead.
reason: Forbidden

---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: {{ include "flink-operator.name" . }}-block-bluegreen-direct-updates-binding
labels:
{{- include "flink-operator.labels" . | nindent 4 }}
spec:
policyName: {{ include "flink-operator.name" . }}-block-bluegreen-direct-updates
validationActions:
{{- toYaml .Values.blueGreenAdmissionPolicy.validationActions | nindent 4 }}
{{- with .Values.blueGreenAdmissionPolicy.matchResources }}
matchResources:
{{- toYaml . | nindent 4 }}
{{- else }}
matchResources: {}
{{- end }}
{{- end }}

Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
################################################################################
# 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.
# limitations under the License.
################################################################################

suite: Test BlueGreen ValidatingAdmissionPolicy

templates:
- policies/bluegreen_admission_policy.yaml

release:
name: flink-operator
namespace: flink-operator

tests:
- it: Should not create admission policy if `blueGreenAdmissionPolicy.create` is `false`
set:
blueGreenAdmissionPolicy:
create: false
asserts:
- hasDocuments:
count: 0

- it: Should create ValidatingAdmissionPolicy and binding if `blueGreenAdmissionPolicy.create` is `true`
set:
blueGreenAdmissionPolicy:
create: true
failurePolicy: Fail
validationActions:
- Deny
asserts:
- hasDocuments:
count: 2
- containsDocument:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
name: flink-kubernetes-operator-block-bluegreen-direct-updates
- containsDocument:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
name: flink-kubernetes-operator-block-bluegreen-direct-updates-binding

- it: Should have correct CEL expression in policy
set:
blueGreenAdmissionPolicy:
create: true
failurePolicy: Fail
validationActions:
- Deny
asserts:
- equal:
path: spec.validations[0].expression
value: |
!has(object.metadata.ownerReferences) ||
!object.metadata.ownerReferences.exists(ref, ref.kind == 'FlinkBlueGreenDeployment') ||
request.userInfo.username == 'system:serviceaccount:flink-operator:flink-operator'
documentIndex: 0

- it: Should set correct failurePolicy
set:
blueGreenAdmissionPolicy:
create: true
failurePolicy: Ignore
validationActions:
- Deny
asserts:
- equal:
path: spec.failurePolicy
value: Ignore
documentIndex: 0

- it: Should set correct validationActions in binding
set:
blueGreenAdmissionPolicy:
create: true
failurePolicy: Fail
validationActions:
- Deny
asserts:
- equal:
path: spec.validationActions
value:
- Deny
documentIndex: 1

- it: Should only match UPDATE operations on flinkdeployments
set:
blueGreenAdmissionPolicy:
create: true
failurePolicy: Fail
validationActions:
- Deny
asserts:
- equal:
path: spec.matchConstraints.resourceRules[0].apiGroups
value:
- flink.apache.org
documentIndex: 0
- equal:
path: spec.matchConstraints.resourceRules[0].operations
value:
- UPDATE
documentIndex: 0
- equal:
path: spec.matchConstraints.resourceRules[0].resources
value:
- flinkdeployments
documentIndex: 0

- it: Should use custom service account name in CEL expression
set:
blueGreenAdmissionPolicy:
create: true
failurePolicy: Fail
validationActions:
- Deny
operatorServiceAccount:
create: true
name: "custom-operator-sa"
asserts:
- equal:
path: spec.validations[0].expression
value: |
!has(object.metadata.ownerReferences) ||
!object.metadata.ownerReferences.exists(ref, ref.kind == 'FlinkBlueGreenDeployment') ||
request.userInfo.username == 'system:serviceaccount:flink-operator:custom-operator-sa'
documentIndex: 0

10 changes: 10 additions & 0 deletions helm/flink-kubernetes-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,16 @@ webhook:
# key: password-key
serviceLabels: {}

# ValidatingAdmissionPolicy to protect child FlinkDeployments from direct modifications
# Uses Kubernetes native ValidatingAdmissionPolicy (requires K8s 1.30+ or 1.26+ with feature gate)
# This is NOT a webhook - it's evaluated directly by the K8s API server
# Enable this if using FlinkBlueGreenDeployment to prevent direct edits to child resources
blueGreenAdmissionPolicy:
create: false
failurePolicy: Fail
validationActions:
- Deny

defaultConfiguration:
# If set to true, creates ConfigMaps/VolumeMounts. If set to false, no configuration will be created.
# All below fields will be ignored if create is set to false.
Expand Down
Loading