Apache Flink on Kubernetes:四种运行模式,我该选择哪一种?

2021年09月15日 阅读数:3
这篇文章主要向大家介绍Apache Flink on Kubernetes:四种运行模式,我该选择哪一种?,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

前言php

Apache Flink 是一个分布式流处理引擎,它提供了丰富且易用的API来处理有状态的流处理应用,而且在支持容错的前提下,高效、大规模的运行此类应用。经过支持事件时间(event-time)、计算状态(state)以及刚好一次(exactly-once)的容错保证,Flink迅速被不少公司采纳,成为了新一代的流计算处理引擎。设计模式

2020 年 2 月 11 日,社区发布了 Flink 1.10.0 版本,该版本对性能和稳定性作了很大的提高,同时引入了 native Kubernetes 的特性。对于 Flink 的下一个稳定版本,社区在 2020 年 4 月底冻结新特性的合入,预计在 2020 年 5 月中旬会推出 Flink 1.11,在新版本中将重点引入新特性,以扩容 Flink 的使用场景。api

Flink 为何选择 Kubernetes安全

Kubernetes 项目源自 Google 内部 Borg 项目,基于 Borg 多年来的优秀实践和其超前的设计理念,并凭借众多豪门、大厂的背书,时至今日,Kubernetes 已经成长为容器管理领域的事实标准。在大数据及相关领域,包括 Spark,Hive,Airflow,Kafka 等众多知名产品正在迁往 Kubernetes,Apache Flink 也是其中一员。网络

Flink 选择 Kubernetes 做为其底层资源管理平台,缘由包括两个方面:session

  • Flink 特性:流式服务通常是常驻进程,常常用于电信网质量监控、商业数据即席分析、实时风控和实时推荐等对稳定性要求比较高的场景;架构

  • Kubernetes 优点:为在线业务提供了更好的发布、管理机制,并保证其稳定运行,同时 Kubernetes 具备很好的生态优点,能很方便的和各类运维工具集成,如 prometheus 监控,主流的日志采集工具等;同时 Kubernetes 在资源弹性方面提供了很好的扩缩容机制,很大程度上提升了资源利用率。并发

Flink on Kubernetes 的发展历史app

在 Flink 的早期发行版 1.2 中,已经引入了 Flink Session 集群模式,用户得以将 Flink 集群部署在 Kubernetes 集群之上。运维

随着 Flink 的逐渐普及,愈来愈多的 Flink 任务被提交在用户的集群中,用户发如今 session 模式下,任务之间会互相影响,隔离性比较差,所以在 Flink 1.6 版本中,推出了 Per Job 模式,单个任务独占一个 Flink 集群,很大的程度上提升了任务的稳定性。

在知足了稳定性以后,用户以为这两种模式,没有作到资源按需建立,每每须要凭用户经验来事先指定 Flink 集群的规格,在这样的背景之下,native session 模式应用而生,在 Flink 1.10 版本进入 Beta 阶段,咱们增长了 native per job 模式,在资源按需申请的基础上,提升了应用之间的隔离性。

本文根据 Flink 在 Kubernetes 集群上的运行模式的趋势,依次分析了这些模式的特色,并在最后介绍了 Flink operator 方案及其优点。

Flink 运行模式

本文首先分析了 Apache Flink 1.10 在 Kubernetes 集群上已经GA(生产可用)的两种部署模式,而后分析了处于 Beta 版本的 native session 部署模式和即将在 Flink 1.11 发布的 native per-job 部署模式,最后根据这些部署模式的利弊,介绍了当前比较 native kubernetes 的部署方式,flink-operator。

咱们正在使用的 Flink 版本已经很好的支持了 native session 和 native per-job 两种模式,在 flink-operator 中,咱们也对这两种模式也作了支持。

接下来将按照如下顺序分析了 Flink 的运行模式,读者能够结合自身的业务场景,考量适合的 Flink 运行模式。

  • Flink session 模式

  • Flink per-job 模式

  • Flink native session 模式

  • Flink native per-job 模式

这四种部署模式的优缺点对比,能够用以下表格来归纳,更多的内容,请参考接下来的详细描述。

Session Cluster 模式

原理简介

Session 模式下,Flink 集群处于长期运行状态,当集群的Master组件接收到客户端提交的任务后,对任务进行分析并处理。用户将Flink集群的资源描述文件提交到 Kubernetes 以后,Flink 集群的 FlinkMaster 和 TaskManager 会被建立出来,以下图所示,TaskManager 启动后会向 ResourceManager 模块注册,这时 Flink Session 集群已经准备就绪。当用户经过 Flink Clint 端提交了 Job 任务时,Dispatcher 收到该任务请求,将请求转发给 JobMaster,由 JobMaster 将任务分配给具体的 TaskManager。

特色分析

这种类型的 Flink 集群,FlinkMaster 和 TaskManager 是以Kubernetes deployment的形式长期运行在 Kubernetes 集群中。在提交做业以前,必须先建立好 Flink session 集群。多个任务能够同时运行在同一个集群内,任务之间共享 K8sResourceManager 和 Dispatcher,可是 JobMaster 是单独的。这种方式比较适合运行短时做业、即席查询、任务提交频繁、或者对任务启动时长比较敏感的场景。

优势:做业提交的时候,FlinkMaster 和 TaskManager已经准备好了,当资源充足时,做业可以当即被分配到 TaskManager 执行,无需等待 FlinkMaster,TaskManager,Service 等资源的建立。

缺点:

  • 须要在提交 Job 任务以前先建立 Flink 集群,须要提早指定 TaskManager 的数量,可是在提交任务前,是难以精准把握具体资源需求的,指定的多了,会有大量 TaskManager 处于闲置状态,资源利用率就比较低,指定的少了,则会有任务分配不到资源,只能等集群中其余做业执行完成后,释放了资源,下一个做业才会被正常执行。

  • 隔离性比较差,多个 Job 任务之间存在资源竞争,互相影响;若是一个 Job 异常致使 TaskManager crash 了,那么全部运行在这个 TaskManager 上的 Job 任务都会被重启;进而,更坏的状况是,多个 Jobs 任务的重启,大量并发的访问文件系统,会致使其余服务的不可用;最后一点是,在 Rest interface 上是能够看到同一个 session 集群里其余人的 Job 任务。

Per Job Cluster 模式

顾名思义,这种方式会专门为每一个 Job 任务建立一个单独的 Flink 集群,当资源描述文件被提交到 Kubernetes 集群,Kubernetes 会依次建立 FlinkMaster Deployment、TaskManagerDeployment 并运行任务,任务完成后,这些 Deployment 会被自动清理。

特色分析

优势:隔离性比较好,任务之间资源不冲突,一个任务单独使用一个 Flink 集群;相对于 Flink session 集群并且,资源随用随建,任务执行完成后马上销毁资源,资源利用率会高一些。

缺点:须要提早指定 TaskManager 的数量,若是 TaskManager 指定的少了会致使做业运行失败,指定的多了仍会下降资源利用率;资源是实时建立的,用户的做业在被运行前,须要先等待如下过程:

  • Kubernetes scheduler为FlinkMaster和 TaskManager 申请资源并调度到宿主机上进行建立;

  • Kubernetes kubelet拉取FlinkMaster、TaskManager 镜像,并建立出FlinkMaster、TaskManager容器;

  • TaskManager启动后,向Flink ResourceManager 注册。

这种模式比较适合对启动时间不敏感、且长时间运行的做业。不适合对任务启动时间比较敏感的场景。

Native Session Cluster 模式

原理分析

  1. Flink提供了 Kubernetes 模式的入口脚本 kubernetes-session.sh,当用户执行了该脚本以后,Flink 客户端会生成 Kubernets 资源描述文件,包括 FlinkMaster Service,FlinkMasterDeloyment,Configmap,Service并设置了owner reference,在 Flink 1.10 版本中,是将 FlinkMaster Service 做为其余资源的 Owner,也就意味着在删除 Flink 集群的时候,只须要删除 FlinkMaster service,其余资源则会被以及联的方式自动删除;

  2. Kubernetes 收到来自 Flink 的资源描述请求后,开始建立FlinkMaster Service,FlinkMaster Deloyment,以及 Configmap 资源,从图中能够看到,伴随着 FlinkMaster 的建立,Dispatch 和 K8sResMngr 组件也同时被建立了,这里的 K8sResMngr 就是 Native 方式的核心组件,正是这个组件去和 Kubernetes API server 进行通讯,申请 TaskManager 资源;当前,用户已经能够向 Flink 集群提交任务请求了;

  3. 用户经过 Flink client 向 Flink 集群提交任务,flink client 会生成 Job graph,而后和 jar 包一块儿上传;当任务提交成功后,JobSubmitHandler 收到了请求并提交给 Dispatcher并生成 JobMaster,JobMaster 用于向 KubernetesResourceManager 申请 task 资源;

  4. Kubernetes-Resource-Manager 会为 taskmanager 生成一个新的配置文件,包含了 service 的地址,这样当 Flink Master 异常重建后,能保证 taskmanager 经过 Service 仍然能链接到新的 Flink Master;

    TaskManager 建立成功后注册到 slotManager,这时 slotManager向TaskManager 申请 slots,TaskManager 提供本身的空闲 slots,任务被部署并运行。

特色分析

以前咱们提到的两种部署模式,在 Kubernetes 上运行 Flink 任务是须要事先指定好 TaskManager 的数量,可是大部分状况下,用户在任务启动前是没法准确的预知该任务所需的 TaskManager 数量和规格。

指定的多了会资源浪费,指定的少了会致使任务的执行失败。最根本的缘由,就是没有 Native 的使用 Kubernetes 资源,这里的 Native,能够理解为 Flink 直接与 Kuberneter 通讯来申请资源。

这种类型的集群,也是在提交任务以前就建立好了,不过只包含了 FlinkMaster 及其 Entrypoint(Service),当任务提交的时候,Flink client 会根据任务计算出并行度,进而肯定出所需 TaskManager 的数量,而后 Flink 内核会直接向 Kubernetes API server 申请 taskmanager,达到资源动态建立的目的。

优势:相对于前两种集群而言,taskManager 的资源是实时的、按需进行的建立,对资源的利用率更高,所需资源更精准。

缺点:taskManager 是实时建立的,用户的做业真正运行前,与 Per Job集群同样,仍须要先等待 taskManager 的建立,所以对任务启动时间比较敏感的用户,须要进行必定的权衡。

Native Per Job 模式

在当前的 Apache Flink 1.10 版本里,Flink native per-job 特性还没有发布,预计在后续的 Flink 1.11 版本中提供,咱们能够提早一览 native per job 的特性。

原理分析

当任务被提交后,一样由 Flink 来向 Kubernetes 申请资源,其过程与以前提到的 native session 模式类似,不一样之处在于:

  1. Flink Master是随着任务的提交而动态建立的;

  2. 用户能够将 Flink、做业 Jar 包和 classpath 依赖打包到本身的镜像里;

  3. 做业运行图由 Flink Master 生成,因此无需经过 RestClient 上传 Jar 包(图 2 步骤 3)。

特色分析

native per-job cluster 也是任务提交的时候才建立 Flink 集群,不一样的是,无需用户指定 TaskManager 资源的数量,由于一样借助了 Native 的特性,Flink 直接与 Kubernetes 进行通讯并按需申请资源。

优势:资源按需申请,适合一次性任务,任务执行后当即释放资源,保证了资源的利用率。

缺点:资源是在任务提交后开始建立,一样意味着对于提交任务后对延时比较敏感的场景,须要必定的权衡。

Flink-operator

简介

分析以上四种部署模式,咱们发现,对于 Flink 集群的使用,每每须要用户自行维护部署脚本,向 Kubernetes 提交各类所需的底层资源描述文件(Flink Master,TaskManager,配置文件,Service)。

在 session cluster 下,若是集群再也不使用,还须要用户自行删除这些的资源,由于这类集群的资源使用了 Kubernetes 的垃圾回收机制 owner reference,在删除 Flink 集群的时候,须要经过删除资源的 Owner 来进行及联删除,这对于不熟悉 Kubernetes 的 Flink 用户来讲,就显得不是很友好了。

而经过 Flink-operator,咱们能够把 Flink 集群描述成 yaml 文件,这样,借助 Kubernetes 的声明式特性和协调控制器,咱们能够直接管理 Flink 集群及其做业,而无需关注底层资源如 Deployment,Service,ConfigMap 的建立及维护。

当前 Flink 官方还未给出 flink-operator 方案,不过 GoogleCloudPlatform 提供了一种基于 kubebuilder 构建的 flink-operator方案。接下来,将介绍 flink-operator 的安装方式和对 Flink 集群的管理示例。

Flink-operator 原理及优点

当 Fink operator 部署至 Kubernetes 集群后, FlinkCluster 资源和 Flink Controller 被建立。其中 FlinkCluster 用于描述 Flink 集群,如 JobMaster 规格、TaskManager 和 TaskSlot 数量等;Flink Controller 实时处理针对 FlinkCluster 资源的 CRUD 操做,用户能够像管理内置 Kubernetes 资源同样管理 Flink 集群。

例如,用户经过 yaml 文件描述指望的 Flink 集群并向 Kubernetes 提交,Flink controller 分析用户的 yaml,获得 FlinkCluster CR,而后调用 API server 建立底层资源,如JobMaster Service,JobMaster Deployment,TaskManager Deployment。

经过使用 Flink Operator,有以下优点:

管理 Flink 集群更加便捷

flink-operator 更便于咱们管理 Flink 集群,咱们不须要针对不一样的 Flink 集群维护 Kubenretes 底层各类资源的部署脚本,惟一须要的,就是 FlinkCluster 的一个自定义资源的描述文件。建立一个 Flink session 集群,只须要一条 kubectl apply 命令便可,下图是 Flink Session集群的 yaml 文件,用户只须要在该文件中声明指望的 Flink 集群配置,flink-operator 会自动完成 Flink 集群的建立和维护工做。若是建立 Per Job 集群,也只须要在该 yaml 中声明 Job 的属性,如 Job 名称,Jar 包路径便可。经过 flink-operator,上文提到的四种 Flink 运行模式,分别对应一个 yaml 文件便可,很是方便。

apiVersion: flinkoperator.k8s.io/v1beta1
kind: FlinkCluster
metadata:
  name: flinksessioncluster-sample
spec:
  image:
    name: flink:1.10.0
    pullPolicy: IfNotPresent
  jobManager:
    accessScope: Cluster
    ports:
      ui: 8081
    resources:
      limits:
        memory: "1024Mi"
        cpu: "200m"
  taskManager:
    replicas: 1
    resources:
      limits:
        memory: "2024Mi"
        cpu: "200m"
    volumes:
      - name: cache-volume
        emptyDir: {}
    volumeMounts:
      - mountPath: /cache
        name: cache-volume
  envVars:
    - name: FOO
      value: bar
  flinkProperties:
    taskmanager.numberOfTaskSlots: "1"

声明式

经过执行脚本命令式的建立 Flink 集群各个底层资源,须要用户保证资源是否依次建立成功,每每伴随着辅助的检查脚本。借助 flink operator 的控制器模式,用户只需声明所指望的 Flink 集群的状态,剩下的工做所有由 Flink operator 来保证。在 Flink 集群运行的过程当中,若是出现资源异常,如 JobMaster 意外中止甚至被删除,Flink operator 都会重建这些资源,自动的修复 Flink 集群。

自定义保存点

用户能够指定 autoSavePointSeconds 和保存路径,Flink operator 会自动为用户按期保存快照。

自动恢复

流式任务每每是长期运行的,甚至 2-3 年不中止都是常见的。在任务执行的过程当中,可能会有各类各样的缘由致使任务失败。用户能够指定任务重启策略,当指定为 FromSavePointOnFailure,Flink operator 自动从最近的保存点从新执行任务。

sidecar containers

sidecar 容器也是 Kubernetes 提供的一种设计模式,用户能够在 TaskManager Pod 里运行 sidecar 容器,为 Job 提供辅助的自定义服务或者代理服务。

Ingress 集成

用户能够定义 Ingress 资源,flink operator 将会自动建立 Ingress 资源。云厂商托管的 Kubernetes 集群通常都有 Ingress 控制器,不然须要用户自行实现 Ingress controller。

Prometheus 集成

经过在 Flink 集群的 yaml 文件里指定 metric exporter 和 metric port,能够与 Kubernetes 集群中的 Prometheus 进行集成。

最后

经过本文,咱们了解了 Flink 在 Kubernetes 上运行的不一样模式,其中 Native 模式在资源按需申请方面比较突出,借助 Kubernetes Operator,咱们能够将 Flink 集群当成Kubernetes原生的资源同样进行 CRUD 操做。限于篇幅,本文主要分析了 Flink 在 Kubernetes 上的运行模式的区别,后续将会有更多的文章来对 Flink 在 Kubernetes 上的最佳实践进行描述,敬请期待。

文章来源:腾讯云原生,点击查看原文

Kubernetes实战培训

Kubernetes实战培训将于2020年12月25日在深圳开课,3天时间带你系统掌握Kubernetes,学习效果很差能够继续学习。本次培训包括:云原生介绍、微服务;Docker基础、Docker工做原理、镜像、网络、存储、数据卷、安全;Kubernetes架构、核心组件、经常使用对象、网络、存储、认证、服务发现、调度和服务质量保证、日志、监控、告警、Helm、实践案例等,点击下方图片或者阅读原文连接查看详情。