This file provides guidance for AI coding agents working with the Apache Flink Kubernetes Operator codebase.
- Java 17 (the build compiles and targets Java 17; see
maven.compiler.source/targetin the rootpom.xml) - Maven 3.8.6 or later. There is no Maven wrapper in this repository — use the system
mvn. - Git
- Docker (to build operator images and run Testcontainers-based integration tests)
- A local Kubernetes cluster (
minikubeorkind),kubectl, andhelmto deploy the operator and run end-to-end tests - Unix-like environment (Linux, macOS, WSL)
- This operator builds against Apache Flink
1.20.x(flink.versionin the rootpom.xml)
- Fast dev build:
mvn clean install -DskipTests -T1C - Full build with tests:
mvn clean verify - Single module:
mvn clean install -DskipTests -pl flink-kubernetes-operator -am - Single module with tests:
mvn clean verify -pl flink-kubernetes-operator -am - Build the operator Docker image:
docker build -t flink-kubernetes-operator .
- Single test class:
mvn -pl flink-kubernetes-operator -Dtest=FlinkConfigManagerTest test - Single test method:
mvn -pl flink-kubernetes-operator -Dtest=FlinkConfigManagerTest#testConfigUpdate test - End-to-end tests are shell scripts under
e2e-tests/(e.g.test_application_operations.sh); they require a running Kubernetes cluster (minikube) with the operator installed via the Helm chart inhelm/.
- Format code:
mvn spotless:apply(google-java-format, AOSP style; version pinned in the rootpom.xml) - Check formatting:
mvn spotless:check - Checkstyle:
mvn checkstyle:check(config:tools/maven/checkstyle.xml, suppressions:tools/maven/suppressions.xml) - Apache license header check (Rat) runs as part of the build.
- Spotless-check and checkstyle are bound to the
validatephase, so any build (even-DskipTests) fails on unformatted or non-compliant code — runmvn spotless:applybefore building.
- Regenerate the configuration reference docs:
mvn clean package -pl flink-kubernetes-docs -am -Pgenerate-docs(runsConfigOptionsDocGenerator; output lands underdocs/layouts/shortcodes/generated). Do not hand-edit generated reference files.
Every module from the root pom.xml, plus the supporting directories.
flink-kubernetes-operator-api— Custom Resource (CRD) types:FlinkDeployment,FlinkSessionJob,FlinkStateSnapshot,FlinkBlueGreenDeploymentand their specs/status. This is the user-facing public API surface (CustomResourceDescriptors).flink-kubernetes-operator— The operator itself: JOSDK controllers, observers, reconcilers, the Flink service abstraction, validation, mutation, metrics, and config. The primary module.flink-kubernetes-standalone— Standalone-mode (non-native) Kubernetes deployment support used by the operator.flink-kubernetes-webhook— Admission webhook for validating and mutating custom resources.flink-autoscaler— Generic Flink job autoscaler, decoupled from Kubernetes so it can be reused outside the operator.flink-autoscaler-standalone— Runs the autoscaler as a standalone process against existing Flink clusters.flink-autoscaler-plugin-jdbc— JDBC-backed state store / event handler plugin for the autoscaler.flink-kubernetes-docs— Documentation build module; auto-generates the config and CRD reference.examples/— Example projects (flink-sql-runner-example,flink-beam-example,kubernetes-client-examples,autoscaling).
helm/— Helm chart used to install the operator.e2e-tests/— End-to-end test scripts run against a real cluster.docs/— User-facing documentation (Hugo site) and generated shortcodes.tools/— Maven config (checkstyle.xml,suppressions.xml), license tooling, OLM, and release scripts..github/— CI workflows and the PR template.
controller/— JOSDKReconcilerentry points, one per CRD (FlinkDeploymentController,FlinkSessionJobController,FlinkStateSnapshotController,FlinkBlueGreenDeploymentController).observer/— Read the actual state of Flink jobs and Kubernetes resources (deployment/,sessionjob/,snapshot/).reconciler/— Drive resources toward their desired spec: deploy, upgrade, suspend, savepoint, rollback (deployment/,sessionjob/,snapshot/,diff/).service/— Abstraction over the Flink REST/native client used by observers and reconcilers.config/—KubernetesOperatorConfigOptionsand configuration management.validation/,mutator/— Resource validation and mutation logic.autoscaler/— Operator-side glue around theflink-autoscalermodule.metrics/,health/,listener/,artifact/,resources/,ssl/,utils/— Supporting subsystems.
The operator follows the standard Kubernetes operator (control loop) pattern, built on the Java Operator SDK (JOSDK) and the fabric8 Kubernetes client.
- Custom Resources (
flink-kubernetes-operator-api) define the user-facing contract:FlinkDeployment(Application/Session clusters),FlinkSessionJob(jobs on a session cluster),FlinkStateSnapshot(savepoints/checkpoints), andFlinkBlueGreenDeployment. - Controller — the JOSDK reconciliation entry point for each CRD. It delegates to an observer and a reconciler; it does not contain business logic itself.
- Observer — reads the actual state (Flink job status via REST, Kubernetes resource
status) and records it on the resource
status. - Reconciler — compares desired
specagainst observedstatusand takes action (deploy, upgrade with the configured upgrade mode, trigger savepoint, suspend, roll back). - FlinkService — the boundary to a running Flink cluster (REST client / native or standalone deployment). Observers and reconcilers go through this abstraction.
- Autoscaler —
flink-autoscaleris deliberately independent of Kubernetes so it can be embedded in the operator and run standalone. Operator-specific wiring lives in the operator'sautoscaler/package. - Webhook (
flink-kubernetes-webhook) validates and mutates resources at admission time, mirroring the in-process validation/mutation logic.
Key separations:
- API vs implementation: CRD types live in
flink-kubernetes-operator-apiand are the public contract; implementation lives inflink-kubernetes-operator. Changing the API affects every user's resources. - Observe vs reconcile: Observers only read and record state; reconcilers only act on it. Keep these responsibilities separate.
- Operator vs autoscaler: Do not introduce Kubernetes dependencies into
flink-autoscaler; keep it reusable for the standalone autoscaler.
- Define a
ConfigOption<T>inKubernetesOperatorConfigOptions(or the relevant config class) using theConfigOptions.key(...)builder with type, default, and description. - Add the appropriate
@Documentationannotation so it appears in the generated reference. - Regenerate docs (
mvn ... -Pgenerate-docs) and document user-facing behavior underdocs/. - Verify: unit test for the default and for the behavior the option controls.
- Edit the spec/status type in
flink-kubernetes-operator-api. - Maintain backward compatibility — existing resources must continue to deserialize and reconcile. New fields should be optional with sensible defaults.
- Add/extend validation in
validation/(and the webhook) and mutation inmutator/as needed. - Regenerate the CRD YAML and reference docs; do not hand-edit generated output.
- Verify: API/serialization tests plus reconciler coverage for the new field.
- Locate the relevant
observer/orreconciler/subpackage (deployment,sessionjob,snapshot). - This is "core reconciler logic that is regularly executed" — flag it as such in the PR template and be conservative about behavior and performance.
- Verify: unit tests plus, where behavior is end-to-end, an
e2e-tests/script.
- Generic logic goes in
flink-autoscaler; keep it Kubernetes-free. - Operator wiring goes in the operator's
autoscaler/package; standalone wiring inflink-autoscaler-standalone. - Verify: unit tests in
flink-autoscaler; thetest_autoscaler.she2e script for behavior.
- Register through the operator's metrics subsystem (
metrics/). - Document user-facing metrics under
docs/.
- Format Java files with Spotless immediately after editing:
mvn spotless:apply(google-java-format, AOSP style). Runmvn spotless:checkbefore committing. - Checkstyle:
tools/maven/checkstyle.xml. Do not suppress rules; fix the code instead. - No Scala. This repository is Java-only.
- Apache License 2.0 header required on all new files (enforced by Apache Rat). Use an HTML comment for Markdown files.
- Logging: Use parameterized SLF4J log statements (
{}placeholders), never string concatenation. Include caught exceptions in warn/error logs. - Use
finalfor variables and fields where applicable. - Comments: Do not restate what the code does; explain "the why" where relevant.
- Reuse existing code. Search for existing utilities/abstractions before adding new ones.
- Full code style guide: https://flink.apache.org/how-to-contribute/code-style-and-quality-preamble/
- Add tests for new behavior, covering success, failure, and edge cases.
- Use JUnit 5 + AssertJ assertions in new test code. Do not use JUnit 4 or Hamcrest.
- Prefer real or fake test implementations over Mockito mocks where practical.
- Integration tests: name classes with an
ITCasesuffix. - End-to-end tests: add or extend a script under
e2e-tests/for cluster-level behavior. - Red-green verification: for bug fixes, confirm the new test fails without the fix and passes with it.
- Test location mirrors the source structure within each module.
- Testing conventions: https://flink.apache.org/how-to-contribute/code-style-and-quality-common/#7-testing
[FLINK-XXXX][component] Descriptionwhere FLINK-XXXX is the JIRA issue number.[hotfix][component] Descriptionfor typo/doc fixes without a JIRA issue.- Each commit must have a meaningful message including the JIRA ID. If you don't know the ticket number, ask.
- Separate cleanup/refactoring from functional changes into distinct commits.
- When AI tools were used: add a
Generated-by: <Tool Name and Version>trailer per the ASF generative tooling guidance.
- Title format:
[FLINK-XXXX][component] Title of the pull request. - A corresponding JIRA issue is required (except hotfixes for typos).
- Fill out the PR template (
.github/PULL_REQUEST_TEMPLATE.md) completely but concisely: purpose, change log, verification, and the impact checkboxes (dependencies, public API/CustomResourceDescriptors, core observer/reconciler logic). - Each PR should address exactly one issue.
- Ensure
mvn clean verifypasses before opening a PR. - Always push to your fork, not directly to
apache/flink-kubernetes-operator. - Rebase onto the latest target branch before submitting.
- Disclose AI usage in the PR template: check the disclosure box and uncomment the
Generated-byline with the tool name and version. - Add
Generated-by: <Tool Name and Version>to commit messages. - Never add
Co-Authored-Bywith an AI agent as co-author; agents are assistants, not authors. - You must be able to explain the design, code, and tests, debug them, and respond to review feedback substantively.
- Reviewer-ready quality bar: the author owns PR quality. Low-effort AI-generated PRs (unreviewed prose, scaffolding without behavior, tests that do not exercise the change, padded commit messages) will be closed without review.
- Adding or changing fields on the CRDs (
flink-kubernetes-operator-api) — these are user-facing API commitments with backward-compatibility implications. - Adding new dependencies.
- Changes to savepoint/checkpoint or state-upgrade behavior (affects job recovery).
- Changes to core observer/reconciler logic on the hot reconciliation path.
- Large cross-module refactors.
- Commit secrets, credentials, or tokens.
- Push directly to
apache/flink-kubernetes-operator; always work from your fork. - Mix unrelated changes into one PR.
- Hand-edit generated CRD YAML or reference docs when a generation workflow exists.
- Suppress or bypass checkstyle (no
CHECKSTYLE:OFF/CHECKSTYLE:ONcomments, notools/maven/suppressions.xmladditions, no@SuppressWarnings); fix the code instead. - Add
Co-Authored-Bywith an AI agent as co-author; useGenerated-by:instead. - Use destructive git operations unless explicitly requested.
- README.md — Project overview
- Documentation — User guides and the development guide (build, CI/CD)
- .github/PULL_REQUEST_TEMPLATE.md — PR checklist
- Code Style Guide — Detailed coding guidelines
- ASF Generative Tooling Guidance — AI tooling policy