java实现发布flink k8s application模式作业

Java发布Flink on K8s作业

一.背景

       在云原生架构全面普及的当下,Apache Flink 作为流批一体的大数据计算引擎,已成为企业处理实时日志、交易风控、实时数仓等核心业务的关键工具;Kubernetes(K8s)则凭借容器编排、弹性扩缩容、资源隔离、多租户管理等特性,成为企业云原生基础设施的标准底座。Flink K8s Application 模式作为 Flink 云原生部署的核心形态,将作业与 K8s 集群的 Pod 生命周期深度绑定,具备 “资源按需分配、隔离性强、适配云原生调度” 的优势,适配大规模、高可用、弹性化的 Flink 作业场景。但传统的 Flink K8s Application 作业发布方式(如 flink run-application -t kubernetes-application 命令行、YAML 配置文件手动提交),已难以满足企业对 “标准化、自动化、可管控、云原生适配” 的运维诉求,基于 Java 实现程序化发布该模式作业,成为解决传统痛点、适配企业级云原生落地的核心选择。

1.传统 Flink K8s Application 作业发布的核心痛点

  1. 发布流程碎片化,云原生自动化适配难传统发布依赖 flink run-application 命令行 + K8s YAML 配置文件组合操作,存在显著短板:一是参数体系复杂(需指定 K8s 命名空间、Pod 资源配额、镜像地址、ConfigMap/Secret 挂载、Flink 配置等),YAML 文件与命令行参数易出现配置不一致,导致作业提交失败;二是无法无缝集成至企业云原生 CI/CD 流水线(如 GitLab CI、ArgoCD),大量依赖人工编写 YAML、执行命令行,发布效率低且易引发人为故障;三是测试 / 生产等多环境的配置(如资源规格、镜像版本、数据源地址)需手动修改 YAML 文件,缺乏统一的配置管理机制,环境一致性难以保障。

  2. 作业全生命周期管控能力缺失flink run-application 仅能完成作业 “提交” 动作,无法程序化管控作业全生命周期:提交后无法实时获取作业在 K8s 上的运行状态(Pod 启动 / 运行 / 异常退出、JobManager/TaskManager 健康状态);作业异常时(如 Pod 被驱逐、资源不足)无法自动触发重启、扩容或告警;需人工登录 K8s Dashboard、Flink WebUI 排查问题,运维成本高,且无法快速响应核心业务作业的故障。

  3. 与云原生生态集成性不足企业级云原生场景中,作业发布需对接 K8s 权限管控(RBAC)、镜像仓库、配置中心(如 ConfigMap/Nacos)、监控告警(Prometheus/Grafana)等系统,但传统发布方式无法直接联动这些组件:例如,提交前无法校验用户是否有 K8s 命名空间的操作权限,提交后无法自动将作业监控指标接入企业监控体系,作业日志无法自动归集至 ELK 或 Loki 日志系统,难以满足云原生环境下的合规与精细化运维诉求。

  4. 多集群 / 多版本适配成本高企业往往部署多套 K8s 集群(测试 / 生产、异地容灾集群)、多个 Flink 版本,传统发布方式需为不同集群 / 版本维护不同的 YAML 文件和命令行脚本,版本兼容(如 Flink 1.17/1.19 对 K8s API 的适配差异)、集群地址切换成本高;且无法程序化识别 K8s 集群的资源余量、节点标签,易将作业提交至资源不足或不匹配的节点,导致作业启动失败。

2.Java 实现发布 Flink K8s Application 作业的核心价值

       Java 作为 Flink 底层开发的核心语言,也是企业级云原生应用开发的主流语言,基于 Java 实现 Flink K8s Application 作业的程序化发布,本质是构建 “标准化、自动化、可管控、云原生原生集成” 的作业发布体系,解决传统方式的痛点:

  1. 标准化发布接口,适配云原生自动化基于 Flink 官方提供的 KubernetesApplicationClusterDescriptorKubernetesClient 等 Java API 封装统一的发布接口,将 K8s Application 作业的核心配置(主类、jar 包路径、K8s 命名空间、Pod 资源配额、镜像地址、配置挂载、并行度等)抽象为可配置参数,替代碎片化的命令行 + YAML 操作。该接口可无缝集成至企业云原生 CI/CD 流水线,实现 “代码编译 - 镜像构建 - 作业发布 - 状态校验” 的全流程自动化,契合 GitOps 运维理念,减少人工干预,降低发布错误率。

  2. 全生命周期管控,强化云原生运维能力Java 程序可通过 Flink Rest API、K8s Client API 联动作业与 K8s 集群:提交作业后实时监听 Pod 状态、Flink 作业运行状态,捕获 Pod 异常退出、JobManager 故障等事件;作业失败时自动触发 Pod 重启、重新提交作业或推送告警至企业监控平台;作业运行中可动态调整 TaskManager 数量(弹性扩缩容)、查询资源使用情况,拉取 Pod 日志并归集至统一日志系统;作业完成后自动清理闲置资源(如 ConfigMap、Pod),提升 K8s 集群资源利用率。

  3. 深度集成云原生生态,满足合规与运维诉求Java 发布程序可原生对接 K8s 生态组件:提交作业前调用 K8s RBAC 接口校验用户 / 应用对命名空间、资源的操作权限;通过 K8s Client 自动创建 / 挂载 ConfigMap/Secret,统一管理作业配置;作业发布后自动注册 Prometheus 监控指标,实现作业运行状态、资源消耗的可视化监控;提交过程中记录审计日志(提交人、时间、配置、集群信息),满足云原生环境下的合规审计要求;同时可集成镜像仓库(如 Harbor),实现镜像拉取权限校验、版本管理。

  4. 灵活适配多集群 / 多版本场景通过 Java 程序的配置化设计,将不同 K8s 集群的连接信息(APIServer 地址、认证信息)、不同 Flink 版本的适配参数(如 K8s API 版本、镜像标签)封装为配置项,发布作业时按需加载对应配置,无需修改核心代码即可适配多集群、多版本场景。例如,通过配置中心切换测试 / 生产 K8s 集群的认证信息,一键发布作业至目标集群;通过版本适配逻辑,自动兼容不同 Flink 版本对 K8s 部署的 API 差异,降低版本升级成本。

3.典型应用场景

  1. 企业级云原生流批一体平台:基于 K8s 构建统一的 Flink 云原生平台,通过 Java 实现 K8s Application 作业的标准化发布入口,支撑各业务部门提交大规模实时数仓同步、金融交易风控、物联网批流融合计算等作业,统一管控 K8s 资源配额、权限、日志,适配云原生环境下的多租户管理诉求。
  2. 核心业务弹性化作业发布:电商大促、金融行情分析等峰值型业务场景,通过 Java 程序发布 Flink K8s Application 作业,利用 K8s 的弹性扩缩容能力,根据数据流量动态调整 TaskManager 数量,保障作业在峰值期的稳定性,低谷期自动释放资源,降低成本。
  3. 多 K8s 集群作业分发与容灾:企业部署多套 K8s 集群(本地集群、公有云集群、异地容灾集群),通过 Java 程序实现作业的批量发布、状态统一监控,当主集群故障时自动将作业切换至容灾集群,保障核心业务不中断,适配混合云部署场景。
  4. 业务系统触发的云原生计算:订单系统、用户画像系统等云原生业务系统触发计算需求时,通过 Java 接口直接发布 Flink K8s Application 作业,作业完成后通过 K8s Service 或消息队列将计算结果回调至业务系统,实现 “业务 - 计算” 的云原生闭环。

       综上,Java 实现发布 Flink K8s Application 模式作业,是企业将 Flink 流批一体计算能力从 “传统集群运维” 转向 “云原生工程化管控” 的关键路径:既充分利用 Flink K8s Application 模式的云原生适配优势,又通过 Java 语言的企业级特性,解决发布碎片化、管控缺失、生态集成不足等痛点,适配企业级核心业务在云原生环境下的规模化、规范化诉求,为大规模、高弹性、高可靠的流批一体计算场景提供稳定、可管控的发布支撑。

二.具体实现

1.添加依赖

<dependency>
	<groupId>org.apache.flink</groupId>
	<artifactId>flink-kubernetes</artifactId>
	<version>1.18.1</version>
</dependency>
<dependency>
	<groupId>org.apache.flink</groupId>
	<artifactId>flink-clients</artifactId>
	<version>1.18.1</version>
</dependency>

2.初始化flink参数

  Configuration flinkConfig = new Configuration();

        flinkConfig.setString(JobManagerOptions.TOTAL_FLINK_MEMORY.key(), "1024m");
        flinkConfig.setString(TaskManagerOptions.TOTAL_FLINK_MEMORY.key(), "1024m");
        flinkConfig.setInteger(TaskManagerOptions.NUM_TASK_SLOTS, 4);
        flinkConfig.setString(CoreOptions.FLINK_HADOOP_CONF_DIR, "/xxx/xxx");
        flinkConfig.setString(YarnConfigOptions.APPLICATION_TYPE, "Flink");

        // add flink pipeline.jars configuration
        flinkConfig.set(PipelineOptions.JARS, new ArrayList<>());


        // add flink container image tag to flink configuration
        flinkConfig.set(KubernetesConfigOptions.CONTAINER_IMAGE,"");

        // retrieve k8s cluster and submit flink job on application mode
        KubernetesClusterDescriptor clusterDescriptor = null;
        ClusterClient<String> clusterClient = null;


        flinkConfig.setString(KubernetesConfigOptions.KUBE_CONFIG_FILE,"");

        flinkConfig.setString(KubernetesConfigOptions.KUBERNETES_SERVICE_ACCOUNT,"");

3.初始化客户端

KubernetesClusterClientFactory clientFactory = new KubernetesClusterClientFactory();
        clusterDescriptor = clientFactory.createClusterDescriptor(flinkConfig);
        ClusterSpecification clusterSpecification = clientFactory.getClusterSpecification(flinkConfig);

        ApplicationConfiguration applicationConfig = ApplicationConfiguration.fromConfiguration(flinkConfig);

4.发布作业

clusterClient = clusterDescriptor
                .deployApplicationCluster(clusterSpecification, applicationConfig)
                .getClusterClient();

        String clusterId = clusterClient.getClusterId();
        String web = clusterClient.getWebInterfaceURL();

<think>由于问题涉及Kubernetes集群中部署Flink并配置PV和PVC,同时另一个Pod需要调用Flink,我将详细说明如何在Kubernetes上部署Flink(包括JobManager和TaskManager),并配置持久化存储(PV和PVC)。此外,还会涉及如何让其他Pod访问Flink服务。 部署FlinkKubernetes通常有两种模式:Session集群和Application集群。这里我们以Session集群为例,因为它允许多个作业共享集群。 步骤: 1. 创建命名空间(可选) 2. 创建持久卷(PV)和持久卷声明(PVC)用于Flink的检查点和保存点数据。 3. 部署Flink JobManager(包括Service)。 4. 部署Flink TaskManager。 注意:我们假设使用Flink官方提供的Docker镜像,并配置Kubernetes资源。 首先,创建一个命名空间(如flink-namespace),但也可以使用默认命名空间。 然后,创建PV和PVC。这里我们创建一个PV,使用本地存储(也可以使用其他存储系统,如NFS、云存储等)。例如,我们创建一个名为flink-checkpoint-pv的PV,并创建一个PVC绑定到这个PV。 接着,部署JobManager: - 创建一个Deployment(或StatefulSet)来运行JobManager。 - 创建一个Service暴露JobManager的REST端口(8081)和内部通信端口(6123)。 最后,部署TaskManager,它也是一个Deployment,通过服务发现自动连接到JobManager。 下面我们给出具体的YAML配置文件。 1. 创建命名空间(可选): ```yaml apiVersion: v1 kind: Namespace metadata: name: flink ``` 2. 创建PV和PVC。假设我们使用hostPath(仅适用于单节点集群,生产环境建议使用网络存储): ```yaml apiVersion: v1 kind: PersistentVolume metadata: name: flink-checkpoint-pv namespace: flink spec: storageClassName: manual capacity: storage: 5Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data/flink" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: flink-checkpoint-pvc namespace: flink spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 5Gi ``` 3. 部署JobManager: 创建JobManager的Deployment,并挂载PVC到容器内的某个路径(如/opt/flink/checkpoints)。 ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: flink-jobmanager namespace: flink spec: replicas: 1 selector: matchLabels: app: flink component: jobmanager template: metadata: labels: app: flink component: jobmanager spec: containers: - name: jobmanager image: flink:latest args: ["jobmanager"] ports: - containerPort: 6123 name: rpc - containerPort: 6124 name: blob - containerPort: 6125 name: query - containerPort: 8081 name: ui env: - name: JOB_MANAGER_RPC_ADDRESS value: flink-jobmanager volumeMounts: - name: checkpoint-volume mountPath: /opt/flink/checkpoints volumes: - name: checkpoint-volume persistentVolumeClaim: claimName: flink-checkpoint-pvc ``` 创建JobManager的Service: ```yaml apiVersion: v1 kind: Service metadata: name: flink-jobmanager namespace: flink spec: selector: app: flink component: jobmanager ports: - name: rpc port: 6123 - name: blob port: 6124 - name: query port: 6125 - name: ui port: 8081 targetPort: 8081 ``` 4. 部署TaskManager: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: flink-taskmanager namespace: flink spec: replicas: 2 # 根据需求调整 selector: matchLabels: app: flink component: taskmanager template: metadata: labels: app: flink component: taskmanager spec: containers: - name: taskmanager image: flink:latest args: ["taskmanager"] ports: - containerPort: 6121 name: data - containerPort: 6122 name: rpc env: - name: JOB_MANAGER_RPC_ADDRESS value: flink-jobmanager volumeMounts: - name: checkpoint-volume mountPath: /opt/flink/checkpoints volumes: - name: checkpoint-volume persistentVolumeClaim: claimName: flink-checkpoint-pvc ``` 这样,Flink集群就部署完成了。其他Pod可以通过Service名称`flink-jobmanager.flink.svc.cluster.local`(如果调用方Pod在同一个命名空间,则可以直接用`flink-jobmanager`)和端口8081(REST端口)来提交作业或与Flink交互。 注意:上述YAML文件中的镜像`flink:latest`建议替换为特定版本,如`flink:1.14.4-scala_2.12`。 另外,关于Flink配置,我们通过环境变量`JOB_MANAGER_RPC_ADDRESS`指定了JobManager的地址(即Service名称)。Flink容器启动时会读取这个环境变量。 检查点和保存点的存储路径在容器内是`/opt/flink/checkpoints`,该路径挂载了PVC,因此数据会持久化。 调用Flink的Pod可以通过Flink的REST API(http://flink-jobmanager.flink:8081)来提交作业或监控作业状态。 相关注意事项: - 存储类(storageClassName)根据集群环境配置,上述例子中使用了manual。 - 生产环境中,PV的存储应该使用网络存储,以便多个节点可以访问(但注意accessModes,Flink的检查点通常只需要ReadWriteOnce)。 - 如果使用高可用模式,还需要配置ZooKeeper和将检查点存储配置为可共享的文件系统(如HDFS或S3)。 现在,假设有一个Pod需要调用Flink,它可以通过Flink REST API提交作业。例如,使用curl提交作业: ```bash curl -X POST -H "Content-Type: application/json" -d '{"programArgs":"..."}' http://flink-jobmanager.flink:8081/jars/<jar-id>/run ``` 其中`<jar-id>`是通过REST API上传作业jar后返回的id。 以上就是在同一个Kubernetes集群中部署Flink并配置PV/PVC的基本步骤。 注意:实际部署时,可能需要根据Flink版本和Kubernetes集群环境调整配置。 下面提出相关问题。</think>### 在 Kubernetes 集群中部署 Flink 并配置 PV/PVC 在 Kubernetes 上部署 Flink 需要为 **检查点(Checkpoints)** 和 **保存点(Savepoints)** 配置持久化存储。以下是完整部署方案: --- #### 1. **创建 PV 和 PVC** 为 Flink 的检查点数据创建持久化存储: ```yaml # flink-pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: flink-checkpoint-pv spec: storageClassName: manual capacity: storage: 20Gi accessModes: - ReadWriteMany hostPath: path: "/mnt/data/flink" # 生产环境应使用云存储(如 AWS EBS) --- # flink-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: flink-checkpoint-pvc spec: storageClassName: manual accessModes: - ReadWriteMany resources: requests: storage: 10Gi ``` **关键配置说明**: - `accessModes: ReadWriteMany`:允许多个 TaskManager 并发写入 - `hostPath`:仅用于测试,生产环境需替换为云存储(如 `awsElasticBlockStore` 或 `nfs`) - 存储大小:根据业务数据量调整(建议 >= 10GiB) --- #### 2. **部署 Flink Session 集群** ##### JobManager 部署(含 Service): ```yaml # jobmanager-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: flink-jobmanager spec: replicas: 1 selector: matchLabels: app: flink component: jobmanager template: metadata: labels: app: flink component: jobmanager spec: containers: - name: jobmanager image: flink:1.17.1 args: ["jobmanager"] ports: - containerPort: 6123 # RPC - containerPort: 8081 # Web UI env: - name: JOB_MANAGER_RPC_ADDRESS value: flink-jobmanager volumeMounts: - name: checkpoint-volume mountPath: /opt/flink/checkpoints volumes: - name: checkpoint-volume persistentVolumeClaim: claimName: flink-checkpoint-pvc --- # jobmanager-service.yaml apiVersion: v1 kind: Service metadata: name: flink-jobmanager spec: selector: app: flink component: jobmanager ports: - name: rpc port: 6123 - name: ui port: 8081 ``` ##### TaskManager 部署: ```yaml # taskmanager-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: flink-taskmanager spec: replicas: 3 # 按需调整并行度 selector: matchLabels: app: flink component: taskmanager template: metadata: labels: app: flink component: taskmanager spec: containers: - name: taskmanager image: flink:1.17.1 args: ["taskmanager"] env: - name: JOB_MANAGER_RPC_ADDRESS value: flink-jobmanager # 通过Service访问JobManager volumeMounts: - name: checkpoint-volume mountPath: /opt/flink/checkpoints volumes: - name: checkpoint-volume persistentVolumeClaim: claimName: flink-checkpoint-pvc ``` --- #### 3. **Flink 配置持久化路径** 在 Flink 配置中指定 PVC 挂载路径: ```yaml # flink-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: flink-config data: flink-conf.yaml: | # 关键持久化配置 state.savepoints.dir: file:///opt/flink/checkpoints/savepoints state.checkpoints.dir: file:///opt/flink/checkpoints/checkpoints # 高可用配置(可选) high-availability: zookeeper high-availability.storageDir: file:///opt/flink/checkpoints/ha ``` **挂载到容器**: ```yaml # 在JobManager/TaskManager的Deployment中添加 volumeMounts: - name: flink-config-volume mountPath: /opt/flink/conf/flink-conf.yaml subPath: flink-conf.yaml volumes: - name: flink-config-volume configMap: name: flink-config ``` --- #### 4. **其他 Pod 调用 Flink** 通过 Kubernetes Service 访问: ```java // Java 示例:从其他Pod提交Flink作业 StreamExecutionEnvironment env = StreamExecutionEnvironment .createRemoteEnvironment( "flink-jobmanager", // Service名称 8081, // REST端口 "/path/to/your.jar" ); env.execute("My Flink Job"); ``` **访问方式**: 1. **REST API**:`http://flink-jobmanager:8081/jobs` 2. **RPC**:`flink-jobmanager:6123` (JobManager 地址) 3. **日志**:通过 Flink Web UI 或 Kubernetes 日志命令查看 --- ### 关键注意事项 1. **存储选择**: - 生产环境使用云存储(如 AWS EBS、GCP PD) - 避免 `hostPath`(单节点风险) 2. **高可用**: - 启用 ZooKeeper + 持久化存储 - 配置 `high-availability.storageDir` 3. **资源隔离**: - 为 JobManager/TaskManager 设置 CPU/Memory Limits 4. **版本对齐**: - Flink 客户端版本需与集群一致 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路边草随风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值