Flink On K8s部署方式
部署在k8s里主要有以下几个优势:
- 容器环境容易部署、清理和重建:不像是虚拟环境以镜像进行分发部署起来对底层系统环境依赖小,所需要的包都可以集成到镜像中,重复使用。
- 更好的隔离性与安全性,应用部署以pod启动,pod之间相互独立,资源环境隔离后更安全。
- k8s集群能够利用好资源,机器学习、在线服务等许多任务都可以混合部署。
- 云原生的趋势,丰富的k8s生态,以及大数据计算上云原生的趋势
# Standalone Cluster on K8S
需要配合 kubectl + yaml 部署,Flink 无法感知 K8s 集群的存在,资源被动
流程:
1、通过yaml文件预先定义Flink Master deployment、taskmanager deployment、configmap等。
2、通过yaml文件部署Flink JobManager的service将jobmanager服务暴露出去。
3、通过Flink client和JobManager service将任务提交到集群。
总结:
优点:Flink任务通过多个yaml文件在K8S部署standalone集群,Flink无需做任何源码修改,流程简单易操作。
缺点:Flink感知不到K8S的存在,任务资源无法自动调整;没有任务的生命周期管理,任务管理成本较高;目前主要使用静态的资源分配,需要提前确认好需要多少个 TaskManager,如果 Job 的并发需要做一些调整,TaskManager 的资源情况必须相应的跟上,否则任务无法正常执行。无法实时申请资源和释放资源。如果维持一个比较大的 Session Cluster,可能会资源浪费。但如果维持的 Session Cluster 比较小,可能会导致 Job 跑得慢或者是跑不起来。
# Native Flink on K8S
为了降低Flink on K8S的使用门槛,同时解决Flink on K8S资源无法自动调整的问题,Flink官方推出了Native Flink on K8S。
流程:
1、Flink client通过内置的K8S client与K8S API Server直接进行通信,之后部署master deployment、jobmanager service、configmap等。
2、JobMaster 通过 K8SResourceManager 向 K8S Master 动态申请资源去创建运行 TaskManager 的 pod,然后 TaskManager再向JobMaster 进行注册。
总结:
优点:native的特点是任务提交的时候才创建 Flink 集群,并且资源可以按需申请;对不熟悉K8S的开发人员比较友好,不涉及太多的K8S概念,部署成本较低。
缺点:缺乏任务生命周期管理能力;K8S集群权限不好管理;不同的用户jar包需要分别构建镜像,需要管理任务镜像;关于K8S相关资源的配置不够灵活,很多自定义配置无法使用,导致Flink Web UI、任务日志等不好管理;没有被大规模生产环境验证。
仅使用 flink 客户端 kubernetes-session.sh or flink run 部署,Flink 主动与 K8s 申请资源
- 资源申请方式:Flink 的 Client 内置了一个 K8s Client,可以借助 K8s Client 去创建 JobManager,当 Job 提交之后,如果对资源有需求,JobManager 会向 Flink 自己的 ResourceManager 去申请资源。这个时候 Flink 的 ResourceManager 会直接跟 K8s 的 API Server 通信,将这些请求资源直接下发给 K8s Cluster,告诉它需要多少个 TaskManger,每个 TaskManager 多大。当任务运行完之后,它也会告诉 K8s Cluster 释放没有使用的资源。相当于 Flink 用很原生的方式了解到 K8s Cluster 的存在,并知晓何时申请资源,何时释放资源。
- Native 是相对于 Flink 而言的,借助 Flink 的命令就可以达到自治的一个状态,不需要引入外部工具就可以通过 Flink 完成任务在 K8s 上的运行。
# Flink K8S Operator
Operator的核心思想是“自动化”,将某一特定场景下的专家人工运维流程通过编码实现自动化,降低运维成本。Operator包含两个核心概念。
- 自定义资源CRD: 根据具体的业务场景实现自定义资源,CRD可以在不修改K8S源码的基础上方便的扩展K8S的功能。
- 控制器Controller: 控制器通过内部循环不停地追踪至少一种资源和该资源的期望状态,并且负责确保其当前状态接近期望状态。
Operator通过将CRD和Controller相结合实现了声明式API,声明式API是K8S容器编排的核心,通过API对象来声明期望的状态,并且支持多client以 PATCH 的方式对 API 对象进行修改,K8S可以方便地对API对象进行管理,完成对“实际状态”和“期望状态”的调谐(Reconcile)过程。
流程:
1、在K8S集群中部署Flink Operator,包括FlinkCluster CRD和controller。
2、通过声明式API将FlinkCluster提交给K8S API Server。
3、API Server验证CRD信息并生成FlinkCluster CR存储在ETCD。
4、K8S触发FlinkCluster add事件然后分发到Flink Controller。
5、Flink Controller解析FlinkCluster CR,调用API Server创建底层资源(jobmanager deployment、jobmanager service、ingress、taskmanager deployment)。
6、Flink Controller开始调协循环(reconciliation loop),监控FlinkCluster底层资源的变化并更新相应的状态,不断的采取行动来使得期望状态和观察到的状态无限接近。
7、Job Submitter通过Rest API获取Flinkcluster状态,当Flinkcluster正常启动后,提交Flink任务,提交完成后结束job。
总结:
- 优点:能够提供生命周期管理能力;通过声明式API管理任务和Operator管理任务,可以方便的自定义K8S资源并进行扩展,如支持远程jar、initContainers、sidecars、volumes、podAnnotations、securityContext等丰富能力;降低运维成本,如自动生成savepoint并重启任务,在任务配置变更或集群升级情况下比较方便;方案比较成熟,业内有通过Operator进行管理Flink任务的案例。
- 缺点:非native方式,无法根据用户代码并行度自动调整资源;需要对K8S比较了解,有一定门槛。