Per-job Cluster
该模式下,一个作业一个集群,作业之间相互隔离。
在Per-Job模式下,集群管理器框架用于为每个提交的Job启动一个 Flink 集群。Job完成后,集群将关闭,所有残留的资源也将被清除。
此模式可以更好地隔离资源,因为行为异常的Job不会影响任何其他Job。另外,由于每个应用程序都有其自己的JobManager,因此它将记录的负载分散到多个实体中。
场景:Per-Job模式适合长期运行的Job,这些Job可以接受启动延迟的增加以支持弹性。
资源管理器支持:Yarn
Application
与per-job 模式相比,在Application 模式下,main() 方法在集群上而不是在客户端执行。
场景:任务启动较慢,适合于长时间运行的大型任务。
资源管理器支持:Yarn、Native kubernetes
Session
该模式下,作业共享集群资源。Session 模式提交的应用都在该集群里执行,会导致资源的竞争。
该模式优势是无需为每一个提交的任务花费精力去分解集群。但是,如果Job异常或是TaskManager 宕掉,那么该TaskManager运行的其他Job都会失败。除了影响到任务,也意味着潜在需要更多的恢复操作,重启所有的Job,会并发访问文件系统,会导致该文件系统对其他服务不可用。此外,单集群运行多个Job,意味着JobManager更大的负载。
场景:该模式适合于对启动延迟要求较高且运行时间较短的作业,例如交互式查询。任务提交速度快,适合频繁提交运行的短时间任务。
资源管理器支持:Standalone、Yarn、Native kubernetes
Flink on kubernetes
Standalone
Standalone模式需要在任务启动时就确定TaskManager的数量,不能像Yarn一样,可以在任务启动时申请动态资源。
很多时候任务需要多少个TaskManager事先并不知道,TaskManager设置少了,任务可能跑不起来,多了又会造成资源浪费,需要在任务启动时才能确定需要多少个TaskMananger。
Standalone Application kubernetes
需要先将用户代码都打到镜像里面,然后根据该镜像来部署一个flink集群运行用户代码。
每提交一个任务,单独启动一个集群运行该任务,运行结束集群被删除,资源也被释放。
Standalone Session kubernetes
在Session模式下,先启动一个Flink集群,然后向该集群提交任务,所有任务共用JobManager。
Native kubernetes
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 Kubernetes Application
native kubernetes下,application模式相当于提交任务时调k8s api自动拉起一个flink集群跑该应用,然后跑完就删除集群。
这种模式比较适合对启动时间不敏感、且长时间运行的作业。不适合对任务启动时间比较敏感的场景。
优点:隔离性比较好,任务之间资源不冲突,一个任务单独使用一个 Flink 集群;相对于 Flink session 集群而且,资源随用随建,任务执行完成后立刻销毁资源,资源利用率会高一些。
缺点:需要提前指定 TaskManager 的数量,如果 TaskManager 指定的少了会导致作业运行失败,指定的多了仍会降低资源利用率;资源是实时创建的,用户的作业在被运行前,需要先等待以下过程。
flink on native kubernetes application模式:提交任务示例 ./bin/flink run-application --target kubernetes-application -Dkubernetes.namespace=flink-native-kubernetes -Dkubernetes.cluster-id=flink-application-cluster -Dkubernetes.jobmanager.service-account=flink -Dkubernetes.container.image=flink:1.14.2 -Dkubernetes.rest-service.exposed.type=NodePort -Djobmanager.heap.size=1024m -Dkubernetes.jobmanager.cpu=1 -Dkubernetes.taskmanager.cpu=2 -Dtaskmanager.memory.process.size=1024m -Dtaskmanager.numberOfTaskSlots=2 local:///opt/flink/examples/batch/WordCount.jar
应用镜像构建方式: `FROM flink:1.14.2 RUN mkdir -p $FLINK_HOME/usrlib COPY my-flink-job.jar $FLINK_HOME/usrlib/my-flink-job.jar`
Native Kubernetes Session
native kubernetes下,session模式是提前调k8s api启动一个常驻的flink集群,然后客户端提交任务时,调k8s api自动起一个taskmanager pod 运行任务,然后等任务运行完之后,这个taskmanager的任务pod会被销毁。
flink on native kubernetes session模式: 1、kubectl create namespace flink-session-cluster 2、kubectl create serviceaccount flink -n flink-session-cluster 3、kubectl create clusterrolebinding flink-role-binding-flink --clusterrole=edit --serviceaccount=flink-session-cluster:flink 启动session集群: 4、./bin/kubernetes-session.sh -Dkubernetes.namespace=flink-session-cluster -Dkubernetes.jobmanager.service-account=flink -Dkubernetes.cluster-id=flink-session-cluster -Dkubernetes.rest-service.exposed.type=NodePort -Dkubernetes.container.image=flink:1.14.2 flink on native kubernetes session模式:提交任务示例 ./bin/flink run -d --target kubernetes-session -Dkubernetes.namespace=flink-session-cluster -Dkubernetes.cluster-id=flink-session-cluster -Dkubernetes.jobmanager.service-account=flink -Dkubernetes.rest-service.exposed.type=NodePort /opt/flink-1.14.2/examples/batch/WordCount.jar
总结
Flink on K8s :
优点:
Flink 在 K8s 上最简单的方式是以 Standalone 方式进行部署。这种方式部署的好处在于不需要对 Flink 做任何改动,同时 Flink 对 K8s 集群是无感知的,通过外部手段即可让 Flink 运行起来。
缺点:
- 无论 Operator、Helm Chart 或者是直接使用 Kubectl Yaml 的方式,Flink 都感知不到 K8s 的存在。
- 目前主要使用静态的资源分配。需要提前确认好需要多少个 TaskManager,如果 Job 的并发需要做一些调整,TaskManager 的资源情况必须相应的跟上,否则任务无法正常执行。
- 用户需要对一些 Container、Operator 或者 K8s 有一些最基本的认识,这样才能保证顺利将 Flink 运行到 K8s 之上。
- 对于批处理任务,或者想在一个 Session 里提交多个任务不太友好。无法实时申请资源和释放资源。因为 TaskManager 的资源是固定的,批处理任务可能会分多个阶段去运行,需要去实时地申请资源、释放资源,当前也无法实现。如果需要在一个 Session 里跑多个 Job 并且陆续运行结束当前也无法实现。
- 如果维持一个比较大的 Session Cluster,可能会资源浪费。但如果维持的 Session Cluster 比较小,可能会导致 Job 跑得慢或者是跑不起来。
基于这几点,社区推进了一个 Native 的集成方案。让Flink 原生的感知到下层 Cluster 的存在。Native 是相对于 Flink 而言的,借助 Flink 的命令就可以达到自治的一个状态,不需要引入外部工具就可以通过 Flink 完成任务在 K8s 上的运行。
生产环境上推荐:
Flink on YARN(pre-job、application)、Flink on Native Kubernetes Appliation;
问题
Flink on Kubernetes 需考虑的问题:
日志问题
日志需要通过k8s的pod日志排查。如果出现节点宕机,pod飘移到别的节点,日志获取困难。
应用jar包问题
flink on k8s的application模式需要将jar包以及依赖放在镜像里启动。
应用依赖问题
有依赖的任务,无法通过客户端获取信息。k8s不支持pre-job模式。