为满足公司日常业务场景中数据分析、数据同步、实时风控、实时推荐、营销自动化、数仓建设等实时数据分析计算场景的需求,建设提供了一个管理 Flink 实时计算任务的整个生命周期,集开发、部署、监控流程为一体的基础工具平台系统。体系分层结构分别为:管理调度层、计算资源层、存储服务层;而我们将 Flink 任务部署到计算资源层,就需要横贯这三层进行打通,其中涉及到权限认证、状态存储、环境初始化、任务监控、任务日志等一系列相关问题。如上图系统建设主要分为三个方面:任务开发、任务部署、任务监控;上述三方相辅相成,从任务编码、配置、发布到部署,对任务实施监控各项指标、日志采集分析等反馈出任务的健康状态、性能等方面的数据,对任务的异常指标告警触达,推进任务更加合理化配置运行资源,促进任务健康平稳地运行。为解决当前 Flink on Yarn 部署模式的一些痛点问题:EMR 成本攀高、资源利用率低、资源碎片化、资源隔离性差、环境部署成本等。因此从资源隔离、运维成本和成本收益角度、快速扩缩、资源利用率等方面出发,我们开始调研 Flink on K8s 模式,希望解决当前 Yarn 环境的以上痛点;本文将侧重介绍部署 K8s 环境,在任务开发、任务部署以及任务监控方面的一些实践总结。Flink on K8s 相比 Flink on Yarn 的优势:- 更好的资源与网络的隔离性、安全性,更适合多租户场景。
- 更容易实现与 online service 的混合部署,提升集群利用率。
- 容器环境容易部署、清理和重建,更加快捷的部署,运维友好。
- 云原生的趋势,可以受益 K8s 丰富的生态系统,以及大数据计算上云原生的趋势。
对于 Flink on K8s 部署方式,官网以及社区推荐的部署模式:Native Kubernetes,社区提供的 Native Kubernetes 模式部署流程如下:研究 Flink on K8s 部署模式的实施,通过分析对比各种部署模式和优缺点和社区趋势,得出如下图结论。结合,当前平台中各个 Flink 版本的占比情况,计划 Flink on K8s 的部署模式的支持从 Flink 1.12 版本开始,使用 Native Kubernetes 模式,以 Application 运行方式提交部署 Flink 任务,应用 Kubernetes 生态能力保障 Flink 任务 HA 和资源自动伸缩、调度管理能力。- 使用 Native Kubernetes 模式,相较于 standalone 方式(Flink 管理资源调度),对资源调度管理使用 Kubernetes 的原生能力。
- 对于任务的 HA 保障,从Flink1.12版本开始支持使用 Kubernetes 的原生能力,而不再依赖 Zookeeper 的能力来实现HA。
- Flink 生态社区逐渐废除 Per Job 模式,替代为 Application 模式提交启动任务。
- 当前平台各个 Flink 版本占比分布情况,Flink1.12.5 及以上版本是主力分布。
- 第一期,支持从 Flink1.12 版本及以上支持部署 Kubernetes,尽量推进实时平台中Flink1.12 以下任务升级到 Flink 高版本;
- 第二期,后续如果 Flink1.12 以下版本有需要部署 Kubernetes 的强烈诉求,再考虑 Standalone 部署模式支持相对较低的版本。
2.3 部署思路
- 由 Flink 任务管理平台控制提交任务到指定业务线对应的资源空间。
- 由于不同租户相关的资源、权限认证、配置等不同,因此存在 Flink 提交机的隔离性,通过临时的 POD 容器来作为 Flink Client 来实现动态加载、差役隔离性,避免在 Flink 任务管理平台中维护多个开发组(租户)的资源隔离。
- 在提交机中加载指定版本的待部署镜像,动态加载不同任务的不同资源启动任务。
2.4 部署实现
- 定义 Dockerfile 以及启动脚本,构建模板镜像。
- 数据开发者在平台中资源管理模块上传任务 jar 资源。
- 数据开发者在平台中数据开发模块开发并启动 Flink 实时任务。
- Flink 任务在管理平台中提交 Flink 任务到 K8s 集群环境,拉取镜像。
- 在 K8S 环境中按照 Dockerfile 镜像以及启动脚本进行 Flink 任务环境初始化。
- Flink 任务启动运行,由 job manager 拉起 task manager。
为了快速试验得到初步的思路验证和部署体验问题总结,我们先尝试本地环境进行 Demo 验证部署。为此,我们本地环境搭建虚拟机、Docker、K8s 环境,准备 Flink运行环境、构建 Docker 镜像,向 K8s 容器提交部署 Flink 任务,命令如下:./bin/Flink run-application \
--target kubernetes-application \
-c com.weimob.flink.client.DemoClient -Denv=QA \
-Dkubernetes.namespace=Flink-K8S-demo \
-Dkubernetes.container.image=Flink-deploy-demo:1.15.2 \
-Dkubernetes.cluster-id=Flink-thor-2926-9365 \
local:///opt/Flink/usrlib/root.jar
3.2 动态数据
以基础镜像动态加载任务运行所需资源的思路,将任务运行所需环境初始化- 当前平台维护的众多实时任务,不希望一个任务一个镜像,甚至是一次部署一个镜像,这对于 tcr 镜像存储成本是一种损耗
- 因此,我们考虑通过基础镜像结合动态资源加载脚本来实现任务运行环境的资源差异化加载的能力,而不是通过提前将运行时环境构建好,一次运行一个镜像的方式。
3.3 动态界面
Flink 官网文档研究分析,通过 clusterIP、nodePort 的方式都不适用于 K8s 容器环境,并且公司生产级 K8s 集群体系本身已经有成熟的服务暴露方案,本质上是通过 Load Balance 方式,参考如下:- 由于 K8s 环境的网络访问结构决定,外部网络无法直接访问,因此,想要访问到 Flink 任务的 WebUI 服务,需要将任务的 Service 暴露。
- 在完善的 K8s 体系下,我们需要将 ingress 路由规则和任务的 Service 绑定,就能实现通过指定的域名透过 K8s 环境的路由到内部 Service 对应的 POD 服务。
3.4 状态存储
任务运行的数据存储,包含Checkpoint、日志等上传腾讯COS。- 对于 Flink on K8s 模式,我们需要支持 HDFS on COS 的能力,以方便任务的Checkpoint 上传和存储,具体配置做法,可以参考腾讯官方文档
3.5 日志采集
对于 K8s 容器环境日志采集方式,大概分3类模式,参考业内实践总结如下:初期,为了快速实施部署实现效果,在 Demo 实践中采用 Sidecar 模式部署在同一个 POD 中的不同 Container 的方式来实现对容器日志采集,写入 ElasticSearch 集群中,在数据平台中对应页面搜索展示时使用。后期,通过对比现有容器集群的日志采集体系,考虑依托当前运维体系的日志数据采集来实施对 Flink 任务的日志采集,同时,和容器集群的其他业务日志进行隔离采集,由数据平台相关服务对采集的日志进行分析处理并写入 ElasticXearch集群中。相对于 Sidecar 模式来说,Daemonset 模式部署在资源成本上和统一管理,部署资源成本更加低,资源利用率更加高,K8s 全体系日志数据采集方案和实施逻辑更加统一和管理,对于开发者和租户更友好,无需感知任务日志的采集体系。3.6 监控指标
对于任务的指标数据采集和告警监控体系,我们接入目前整体基础体系的监控采集体系中,依托 K8s 环境体系自动发现 POD,经过 VM Agent 采集到相关 POD 的指标数据存储,设置对应的 VM Rule 来实现触发告警推送到 AlertManager,经过 Flink 任务管理平台识别是否发送告警到用户端。对于部署效果和任务提交运行的直接呈现,我们需要能访问任务 Flink Web UI 界面,在测试环境以及生产环境中,对应的网络体系和服务暴露需要找运维小伙伴支持,最终我们可以通过任务对应的专属域名访问 Flink Web UI 界面。4.2 任务日志
我们对任务日志搜索提供了平台集成性页面展示,方便用户检索查看任务运行日志。 4.3 任务监控
任务指标监控数据展示,配置对应的 Grafana 大盘,展示 Flink on K8s 环境的任务指标数据。目前已经完成任务的部署、监控&告警的一套完整基础流程,还遗留部分问题及优化,包括:- POD 资源CPU、Memory的实际使用率统计分析,确定弹性比例,以及适合的机器资源型号。
- 磁盘存储方面,对于任务 Checkpoint 状态存储,后续需要研究挂载 PVC 来实现。
- 数据清理,对于 K8s 容器环境,倾向于是无状态应用,本质上不希望产生日志文件,任务运行结束,收尾处理,清理资源等操作。
- 镜像优化,以及同一个镜像融合 Yarn 部署模式和 K8s 模式,目前是拆分镜像。
5.2 日志&监控
当前数据平台体系中,对于任务运行的日志采集、搜索体系,还分散在各个业务子系统中,后续规划,可以独立数据平台的日志服务中心,独立服务来为整体数据中心所有子系统服务。日常开发者所需的任务监控展示和告警体系,也需要独立一个数据中心的独立模块来收口聚集统一的服务实现,方便整体数据中心的统一操作行为和用户习惯。因此,对于日志和告警其实是倾向于构建独立的模块服务于整体数据中心平台,这可以使得平台更加体系化、健壮以及用户友好。Flink Native Kubernetes Deploy(https://nightlies.apache.org/flink/flink-docs-release-1.13/zh/docs/deployment/resource-providers/native_kubernetes/)
Native Kubernetes Integration (Beta)(https://flink.apache.org/2020/02/11/apache-flink-1.10.0-release-announcement/#native-kubernetes-integration-beta)
Kubernetes publishing-services-service-types(https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types)
HDFS TO COS 工具(https://cloud.tencent.com/document/product/436/7212)
Integeration of Tencent COS in Hadoop(https://hadoop.apache.org/docs/stable/hadoop-cos/cloud-storage/index.html)
K8s 中的sidecar 和daemonset的理解和实践(https://blog.csdn.net/knight_zhou/article/details/126241319)
分布式计算引擎 Flink/Spark on K8S 的实现对比以及实践(https://developer.aliyun.com/article/788288)