一.背景
在云原生架构全面普及的当下,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 作业发布的核心痛点
-
发布流程碎片化,云原生自动化适配难传统发布依赖
flink run-application命令行 + K8s YAML 配置文件组合操作,存在显著短板:一是参数体系复杂(需指定 K8s 命名空间、Pod 资源配额、镜像地址、ConfigMap/Secret 挂载、Flink 配置等),YAML 文件与命令行参数易出现配置不一致,导致作业提交失败;二是无法无缝集成至企业云原生 CI/CD 流水线(如 GitLab CI、ArgoCD),大量依赖人工编写 YAML、执行命令行,发布效率低且易引发人为故障;三是测试 / 生产等多环境的配置(如资源规格、镜像版本、数据源地址)需手动修改 YAML 文件,缺乏统一的配置管理机制,环境一致性难以保障。 -
作业全生命周期管控能力缺失
flink run-application仅能完成作业 “提交” 动作,无法程序化管控作业全生命周期:提交后无法实时获取作业在 K8s 上的运行状态(Pod 启动 / 运行 / 异常退出、JobManager/TaskManager 健康状态);作业异常时(如 Pod 被驱逐、资源不足)无法自动触发重启、扩容或告警;需人工登录 K8s Dashboard、Flink WebUI 排查问题,运维成本高,且无法快速响应核心业务作业的故障。 -
与云原生生态集成性不足企业级云原生场景中,作业发布需对接 K8s 权限管控(RBAC)、镜像仓库、配置中心(如 ConfigMap/Nacos)、监控告警(Prometheus/Grafana)等系统,但传统发布方式无法直接联动这些组件:例如,提交前无法校验用户是否有 K8s 命名空间的操作权限,提交后无法自动将作业监控指标接入企业监控体系,作业日志无法自动归集至 ELK 或 Loki 日志系统,难以满足云原生环境下的合规与精细化运维诉求。
-
多集群 / 多版本适配成本高企业往往部署多套 K8s 集群(测试 / 生产、异地容灾集群)、多个 Flink 版本,传统发布方式需为不同集群 / 版本维护不同的 YAML 文件和命令行脚本,版本兼容(如 Flink 1.17/1.19 对 K8s API 的适配差异)、集群地址切换成本高;且无法程序化识别 K8s 集群的资源余量、节点标签,易将作业提交至资源不足或不匹配的节点,导致作业启动失败。
2.Java 实现发布 Flink K8s Application 作业的核心价值
Java 作为 Flink 底层开发的核心语言,也是企业级云原生应用开发的主流语言,基于 Java 实现 Flink K8s Application 作业的程序化发布,本质是构建 “标准化、自动化、可管控、云原生原生集成” 的作业发布体系,解决传统方式的痛点:
-
标准化发布接口,适配云原生自动化基于 Flink 官方提供的
KubernetesApplicationClusterDescriptor、KubernetesClient等 Java API 封装统一的发布接口,将 K8s Application 作业的核心配置(主类、jar 包路径、K8s 命名空间、Pod 资源配额、镜像地址、配置挂载、并行度等)抽象为可配置参数,替代碎片化的命令行 + YAML 操作。该接口可无缝集成至企业云原生 CI/CD 流水线,实现 “代码编译 - 镜像构建 - 作业发布 - 状态校验” 的全流程自动化,契合 GitOps 运维理念,减少人工干预,降低发布错误率。 -
全生命周期管控,强化云原生运维能力Java 程序可通过 Flink Rest API、K8s Client API 联动作业与 K8s 集群:提交作业后实时监听 Pod 状态、Flink 作业运行状态,捕获 Pod 异常退出、JobManager 故障等事件;作业失败时自动触发 Pod 重启、重新提交作业或推送告警至企业监控平台;作业运行中可动态调整 TaskManager 数量(弹性扩缩容)、查询资源使用情况,拉取 Pod 日志并归集至统一日志系统;作业完成后自动清理闲置资源(如 ConfigMap、Pod),提升 K8s 集群资源利用率。
-
深度集成云原生生态,满足合规与运维诉求Java 发布程序可原生对接 K8s 生态组件:提交作业前调用 K8s RBAC 接口校验用户 / 应用对命名空间、资源的操作权限;通过 K8s Client 自动创建 / 挂载 ConfigMap/Secret,统一管理作业配置;作业发布后自动注册 Prometheus 监控指标,实现作业运行状态、资源消耗的可视化监控;提交过程中记录审计日志(提交人、时间、配置、集群信息),满足云原生环境下的合规审计要求;同时可集成镜像仓库(如 Harbor),实现镜像拉取权限校验、版本管理。
-
灵活适配多集群 / 多版本场景通过 Java 程序的配置化设计,将不同 K8s 集群的连接信息(APIServer 地址、认证信息)、不同 Flink 版本的适配参数(如 K8s API 版本、镜像标签)封装为配置项,发布作业时按需加载对应配置,无需修改核心代码即可适配多集群、多版本场景。例如,通过配置中心切换测试 / 生产 K8s 集群的认证信息,一键发布作业至目标集群;通过版本适配逻辑,自动兼容不同 Flink 版本对 K8s 部署的 API 差异,降低版本升级成本。
3.典型应用场景
- 企业级云原生流批一体平台:基于 K8s 构建统一的 Flink 云原生平台,通过 Java 实现 K8s Application 作业的标准化发布入口,支撑各业务部门提交大规模实时数仓同步、金融交易风控、物联网批流融合计算等作业,统一管控 K8s 资源配额、权限、日志,适配云原生环境下的多租户管理诉求。
- 核心业务弹性化作业发布:电商大促、金融行情分析等峰值型业务场景,通过 Java 程序发布 Flink K8s Application 作业,利用 K8s 的弹性扩缩容能力,根据数据流量动态调整 TaskManager 数量,保障作业在峰值期的稳定性,低谷期自动释放资源,降低成本。
- 多 K8s 集群作业分发与容灾:企业部署多套 K8s 集群(本地集群、公有云集群、异地容灾集群),通过 Java 程序实现作业的批量发布、状态统一监控,当主集群故障时自动将作业切换至容灾集群,保障核心业务不中断,适配混合云部署场景。
- 业务系统触发的云原生计算:订单系统、用户画像系统等云原生业务系统触发计算需求时,通过 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();
Java发布Flink on K8s作业
30

被折叠的 条评论
为什么被折叠?



