The deployment of Apache Flink on Kubernetes represents a critical intersection of stream processing and container orchestration. Kubernetes serves as a primary deployment platform for Flink, enabling the execution of complex data pipelines with the benefit of cloud-native scalability. The integration is primarily facilitated through the operator pattern, which transitions the deployment process from manual imperative commands to a declarative state. In this model, users define the desired state of their jobs within a declarative resource, and a Kubernetes operator—a specialized control loop—handles the provisioning, scaling, and updating of all required infrastructure. This automation is essential for production environments, as it drastically reduces the manual overhead associated with managing the lifecycle of distributed stream processing jobs.
Historically, several operators have emerged to support this ecosystem. These include the flinkk8soperator developed by Lyft, the flink-on-k8s-operator from Spotify (which originated as a Google-developed project), and the flink-controller created by Andrea Medeghini. However, the industry has largely coalesced around the upstream Flink Kubernetes Operator, which is developed directly under the Apache Flink project umbrella. This official operator provides the standardized mechanism for installing Flink and executing jobs, though it serves as a foundation that organizations must build upon to create a fully realized, enterprise-grade data platform.
Flink Deployment Modes on Kubernetes
The architecture of Flink on Kubernetes is bifurcated into two primary deployment strategies: Session Mode and Application Mode. These modes dictate how the JobManager and TaskManagers are provisioned and how the job artifacts are delivered to the cluster.
Application Mode
Application Mode is designed for scenarios where a dedicated cluster is required for a single application. In this mode, the application is provided at the time of deployment, and the cluster is tailored to run that specific job. This ensures that the job is the sole consumer of the cluster's resources, eliminating interference from other applications.
A basic Flink Application cluster deployment consists of three core architectural components:
- An Application: This component runs the JobManager, which coordinates the execution of the job.
- A Deployment: This provides a pool of TaskManagers that execute the actual data processing tasks.
- A Service: This component exposes the JobManager's REST and UI ports to allow for monitoring and management.
For an Application Mode deployment to function, the args attribute within the jobmanager-application-non-ha.yaml configuration must specify the main class of the user job. This ensures the JobManager knows exactly which entry point to execute upon startup. Job artifacts can be provided via a job-artifacts-volume in the resource definition, which maps the actual binary code to the container.
Session Mode
Session Mode allows for a long-running cluster that can accept multiple job submissions over time. This is useful for development or shared environments where users want to submit various jobs without recreating the entire cluster infrastructure.
In Session Mode, the JobManager is started as a deployment, and TaskManagers are added as needed. The JobManager remains active, acting as a coordinator for any number of submitted jobs. Users can submit jobs to a session cluster using the Flink CLI via the command:
./bin/flink run -m localhost:8081 ./examples/streaming/TopSpeedWindowing.jar
Technical Resource Configurations
Deploying Flink on Kubernetes requires the precise configuration of several Kubernetes resource types, including ConfigMaps, Services, and Deployments.
Configuration via ConfigMaps
ConfigMaps are used to inject Flink-specific configurations and logging properties into the pods. A typical flink-configuration-configmap.yaml includes critical parameters that govern the performance and networking of the cluster.
| Parameter | Value (Example) | Description |
|---|---|---|
jobmanager.rpc.address |
flink-jobmanager |
The address used for RPC communication. |
taskmanager.numberOfTaskSlots |
2 |
The number of concurrent tasks a TaskManager can execute. |
blob.server.port |
6124 |
The port used by the Blob Server for transferring artifacts. |
jobmanager.rpc.port |
6123 |
The port used for JobManager RPC communication. |
taskmanager.rpc.port |
6122 |
The port used for TaskManager RPC communication. |
jobmanager.memory.process.size |
1600m |
Total process memory allocated to the JobManager. |
taskmanager.memory.process.size |
1728m |
Total process memory allocated to the TaskManager. |
parallelism.default |
2 |
The default parallelism for jobs submitted to the cluster. |
Logging is also handled via ConfigMaps using log4j-console.properties. This allows operators to set the rootLogger.level to INFO and define appenders such as ConsoleAppender and RollingFileAppender.
Service Definitions
Services are used to expose the Flink components to the network. A common configuration is the flink-jobmanager-rest service, which exposes the JobManager's REST port.
- Service Name:
flink-jobmanager-rest - Service Type:
NodePort - Port:
8081 - Target Port:
8081 - Node Port:
30081
When kubernetes.rest-service.exposed.type is set to ClusterIP, certain operations such as cancel, list, and stop will not work from outside the Kubernetes cluster. To access the Flink UI locally in such cases, users must employ port-forwarding:
kubectl port-forward service/flink-application-cluster-rest 8081 -n <namespace>
TaskManager Infrastructure and State Management
The TaskManager is the worker component of Flink. Depending on the requirements for state recovery and persistence, TaskManagers can be deployed using different Kubernetes controllers.
Deployment-based TaskManagers
For simple deployments, TaskManagers are run as a standard Kubernetes Deployment. In the taskmanager-job-deployment.yaml, the container uses the apache/flink:2.2.0-scala_2.12 image. Key configuration aspects include:
- Container Port:
6122(namedrpc). - Liveness Probe: A TCP socket probe on port
6122with aninitialDelaySecondsof 30 and aperiodSecondsof 60. - Security Context: The
runAsUseris set to9999, which corresponds to the_flink_user in the official image. - Volume Mounts: The
flink-config-volumeis mounted to/opt/flink/conf/, and thejob-artifacts-volumeis mounted to/opt/flink/usrlib.
StatefulSet and Local Recovery
For high-performance state recovery, Kubernetes StatefulSets are utilized. This allows Flink to map a pod to a persistent volume, which is critical for minimizing the time it takes for a TaskManager to recover its state after a failure.
To implement local recovery, the following configurations are required:
- Volume Claim Templates: Used to mount persistent volumes to TaskManagers.
- Deterministic Resource ID: A
taskmanager.resource-idmust be configured, with a suitable value being the pod name exposed through environment variables. - ConfigMap Updates: The
state.backend.local-recoverymust be set totrue, and theprocess.taskmanager.working-dirshould be set to a persistent path, such as/pv.
High Availability (HA) Architecture
High Availability is crucial for production-grade Flink deployments to ensure that the failure of a single JobManager does not result in the failure of the entire data pipeline.
Kubernetes HA Services
Flink leverages native Kubernetes services to achieve HA. The configuration is managed via a ConfigMap where the following parameters are defined:
kubernetes.cluster-id: A unique identifier for the cluster.high-availability.type: Set tokubernetes.high-availability.storageDir: The path for recovery data, for example,hdfs:///flink/recovery.restart-strategy.type: Set tofixed-delay.restart-strategy.fixed-delay.attempts: Set to10.
To support this architecture, JobManager and TaskManager pods must be started with a service account that possesses the necessary RBAC permissions to create, edit, and delete ConfigMaps within the namespace.
JobManager Redundancy
In HA configurations, the jobmanager-session-deployment-ha.yaml allows for the specification of multiple replicas. Setting the replicas to a value greater than 1 enables the deployment of standby JobManagers. These standby instances can take over the role of the leader if the primary JobManager fails, ensuring continuous operation of the streaming application.
Operational Management and Troubleshooting
Managing a Flink cluster on Kubernetes involves interacting with both the Flink Web UI and the Kubernetes CLI.
Log Analysis
Logs are the primary tool for troubleshooting Flink applications. There are two primary methods for accessing logs:
- Flink Web UI: If access to the Web UI is available, logs for both JobManagers and TaskManagers can be viewed directly.
- Kubernetes CLI: When the UI is unavailable or the cluster is failing to start,
kubectlis used.
To view all running pods, use:
kubectl get pods
Once the pod names are identified (e.g., flink-jobmanager-589967dcfc-m49xv), the logs can be retrieved using:
kubectl logs flink-jobmanager-589967dcfc-m49xv
Resource Lifecycle Management
The lifecycle of a Flink deployment involves the creation and deletion of several resources. For a session cluster, the following commands are used to tear down the infrastructure:
- Delete JobManager Service:
kubectl delete -f jobmanager-service.yaml - Delete Configuration ConfigMap:
kubectl delete -f flink-configuration-configmap.yaml - Delete TaskManager Deployment:
kubectl delete -f taskmanager-session-deployment.yaml - Delete JobManager Deployment:
kubectl delete -f jobmanager-session-deployment-non-ha.yaml
For application clusters, the deletion is simpler:
kubectl delete deployment.apps/flink-application-cluster -n <namespace>
Analysis of Kubernetes as a Flink Execution Environment
The transition of Apache Flink to Kubernetes reflects a broader industry shift toward the decoupling of application logic from underlying infrastructure. By utilizing the operator pattern, Flink transforms from a complex distributed system requiring manual tuning into a manageable Kubernetes resource.
The impact of using StatefulSets for TaskManagers cannot be overstated; by providing deterministic identities and persistent volume mapping, Flink overcomes the ephemeral nature of Kubernetes pods. This allows for local recovery, which significantly reduces the recovery time objective (RTO) for stateful streaming applications. Without this, every failure would necessitate a full state reload from a remote checkpoint, introducing significant latency and potential data processing gaps.
Furthermore, the distinction between Application Mode and Session Mode allows organizations to optimize for either resource efficiency or developer velocity. Application Mode is the gold standard for production because it ensures total isolation and eliminates the risk of a single rogue job consuming all cluster resources. Session Mode, while less isolated, provides the flexibility required for iterative development.
The integration of Kubernetes-native HA services further simplifies the architecture. By offloading the leader election and metadata storage to Kubernetes ConfigMaps and external storage like HDFS, Flink removes the need for external coordination services like ZooKeeper in many scenarios. This reduces the operational footprint and the number of failure points in the system.
In conclusion, the synergy between Apache Flink and Kubernetes creates a robust framework for real-time data processing. The ability to declaratively manage complex stream processing jobs through an operator, combined with the power of StatefulSets for local recovery and native HA services for resilience, makes Kubernetes the most compelling deployment target for Flink.