flink原理源码分析(一) 集群与资源@k8s

1 简介

集群和资源模块提供动态资源能力,是分布式系统关键基础设施,分布式datax,分布式索引,事件引擎都需要集群和资源的弹性资源能力,提高扩展和作业处理能力。本文分析flink的集群和资源的k8s模块,深入了解其设计原理,为开发自有的集群和资源组件做技术准备, 同时涉及作业管理器,slot管理,不深入调度器。

本文分析基于flink 1.17版本,不同版本代码差异比较大

2 关键词

作业管理器

资源管理器

任务管理器

3 参考资料

flink官方网站 https://flink.apache.org/

4 flink整体架构

flink原理源码按板块逐一分析,本文分析集群和资源

API板块 Table&SQL, DataStream,DataSet将被丢弃

作业构建和转换板块

作业提交和接收 client,作业打包,提交,接收和分发

作业调度板块 执行图(Execution Graph), 调度器,作业管理器

作业执行板块 高可用,容错,状态,作业执行

5 flink运行架构

运行架构,按调用顺序展示flink集群启动,作业提交处理组件互动

总体上,集群是mater-worker架构,上图是flink的抽象架构,一个优秀架构可以抽象,第六章介绍架构”具体” k8s实现

6 flink@k8s运行架构

作业管理器得到任务管理器提供的资源(slot),启动task,资源申请完成。

7 启动集群

7.1 场景

下面详细分析各用例

7.2 启动k8s集群

k8s集群支持session和application模式,job模式将会被废弃,本文分析session模式集群

Configuration作为配置容器,几乎所有的构建需要从配置类获取配置项,这里不显示关联关系

1. 用户命令行执行kubernates-session.sh,主入口是KubernetesSessionCli main

2.ClusterClientServiceLoader SPI机制载入ClusterClientFactory,k8s环境下实现类是KubernetesClusterClientFactory

3. ClusterClientFactory是ClusterClient工厂,首先创建ClusterDescriptor集群描述,该类负责部署集群,最终返回ClusterClient,k8s环境下实现类是
KubernetesClusterDescriptor

4.KubernetesClusterDescriptor新建集群规格ClusterSpecification,该类不是针对k8s,定义了flink master和任务管理器的内存容量等技术参数,通用于容器类的集群;
KubernetesSessionClusterEntrypoint类型设置为ENTRY_POINT_CLASS参数,后面《部署集群》使用到

5.KubernetesClusterDescriptor的deploySessionCluster部署k8s集群,参看《部署集群》用例,最后返回ClusterClient,用于后续提交作业和其他集群操作

7.3 部署集群

部署集群是启动的第二步,
KubernetesClusterDescriptor的deploySessionCluster方法的一部分,构建部署规格,flink kubeclient提交到k8s集群管理器,触发flink master构建和启动

1. 首先更新配置,主要是对外端口,更新为固定的,支持对外Service通讯

2. 构建
KubernetesJobManagerParameters,该类封装Configuration和ClusterSpecification,为获取参数提供便利

3. 构建FlinkPod,首先载入pod模板构建KubernetesPod,KubernetesPod是一个包装了k8s Pod对象的Resource类;构建FlinkPod,定义了mainContainer ,podWithoutMainContainer,其中主容器固定名称,用于运行作业管理器任务管理器,其他容器运行相关的资源,如ConfigMap,Service等,详细分析参考10 flink kubeclient

4.KubernetesJobManagerFactory《构建作业管理器部署规格》构建部署规格,Fabric8FlinkKubeClient使用部署规格《新建作业管理器组件(flink master)》部署flink master组件,两用例在10 flink kubeclient分析

5. 最后客户端调用
createClusterClientProvider返回ClusterClient

8 运行时

运行时提供了Flink作业运行过程依赖的基础执行环境,包含Dispatcher、ResourceManager、JobManager和TaskManager等核心组件,本节分析资源相关运行时组件构建和启动。

flink没有使用spring,缺少ioc的构建过程相当复杂,所有依赖手动关联和置入,为了共享组件,flink使用了很多中间持有共享组件的中间对象。

8.1 场景

8.2 构建和启动flink master组件

部署集群通过flink kubeclient向k8s集群管理提交flink master的Deployment,触发flink master构建和启动

上图是构建和启动的交互图,参看《构建作业管理器部署规格》的CmdJobManagerDecorator设置了初始容器脚本和参数,集群初始入口ClusterEntryPoint

1. 容器初始执行kubernetes-jobmanager.sh

ClusterEntryPoint设置为
KubernetesSessionClusterEntrypoint

2.KubernetesSessionClusterEntrypoint继承SessionClusterEntrypoint,只重新实现createDispatcherResourceManagerComponentFactory方法,设置ResourceManagerFactory为KubernetesResourceManagerFactory,就是说集群初始化逻辑与其他session集群区别不大

3. 经过容错日志,插件文件系统初始化,进入ClusterEntrypoint的runCluster,该方法主要做两个事,initializeServices
DispatcherResourceManagerComponent

4. initializeServices构建基础服务,Rpc服务,Jmx服务,ha服务,blob服务,metics等

5.DispatcherResourceManagerComponent运行时组件,高可用组件的初始化/启动;同时也是持有者,用于后面关闭和清理

8.3 构建和启动任务管理器

构建和启动任务管理器是申请资源的一部分,按请求新worker的延申,类型分属于运行时一部分。

1. createTaskManagerPod与10.2 新建作业管理组件类似,CmdTaskManagerDecorator,装饰器实现了pod装饰,装饰主容器,设置shell执行命令

设置执行脚本
KUBERNETES_TASK_MANAGER_SCRIPT_PATH= "kubernetes-jobmanager.sh"

主入口
KubernetesTaskExecutorRunner main方法

2. 任务管理器启动比较简单,主要启动rpc服务和高可用组件,高可用触发9.5 注册任务管理器/报告资源

9 资源

本章分析资源管理的场景,服务级实现;核心数据流,资源槽从新增,报告,匹配,分配,到释放的完整生命周,详细了解每个场景下资源槽的状态型态型态指资源类结构,类直接转换,状态属性,存储。

9.1 场景

资源处理有声明式处理资源细粒度处理资源 是两个实现,两者不是并行的两种实现策略,声明式是资源申请和分配方式,粒度是指资源分割方式,细粒度按需可变的资源,粗粒度是固定的资源,本文只分析声明式粗粒度处理资源

9.2 申请和分配资源(simple allocator)

用户提交作业,分发器接收并分发作业到作业管理器调度器确定所需资源,申请资源,检查当前可用资源是否足够,如果不足,请求新资源,动态增加资源;若足够,分配资源给任务。

分配还有另一个实现,slot sharing,有比较复杂的资源分配策略,分配策略跟本文主题无关,因此选了比较简单simple allocator

9.2.1 服务分析

DeclarativeSlotPoolBridge桥接DeclarativeSlotPool,声明式资源池,真正处理资源,用声明式SlotPool实现SlotPool,为了简化描述,描述不区分DeclarativeSlotPoolBridge和DeclarativeSlotPool

1. 调度器调用PhysicalSlotProvider的allocatePhysicalSlot分配资源

2. allocatePhysicalSlot首先tryAllocateFromAvailable,从当前可用资源分配;若当前可用资源不够9.3 请求新资源

3. tryAllocateFromAvailable调用DeclarativeSlotPoolBridge的
getAvailableSlotsInformation获取资源池的可用资源,其实际最终调用AllocatedSlotPool的getFreeSlotsInformation并组装为SlotInfoAndResources,该类组合了SlotInfo,分配信息;ResourceProfile,资源信息

4. SlotSelectionStrategy选择策略在可用资源选择一个最合适的,目前基于位置策略

5. 选出最合适的资源后,PhysicalSlotProvider调用DeclarativeSlotPoolBridge的allocateAvailableSlot分配资源

6. DeclarativeSlotPoolBridge的allocateAvailableSlot分配资源,该方法调用DeclarativeSlotPool的
increaseResourceRequirementsBy增加资源请求(声明),该方法触发异步处理资源请求,9.2.21深入分析

7. 最后保留资源,真正的分配在处理资源请求,保留资源AllocatedSlotPool的reserveFreeSlot登记未已分配资源AllocatedSlot

8. 最后调整资源,保留不一定是最终分配,最终分配后调整实际资源情况

9.2.1.1 notifyNewResourceRequirements

最后分析一下
notifyNewResourceRequirements
notifyNewResourceRequirements类型Consumer,函数方法

图1

上图是
notifyNewResourceRequirements设置和调用的方法,函数是怎么设置?

图2

图1是图2的 connect调用,设置Service

设置方法是哪里调起?

1.
ResourceManagerLeaderListener监听资源管理器选主,获取新主节点的地址

2.
ResourceManagerLeaderListener通知JobMaster,调用JobMaster的


notifyOfNewResourceManagerLeader方法

3.
notifyOfNewResourceManagerLeader启动rpc(重新)连接

4. rpc连接后,触发onRegistrationSuccess事件方法,然后
DeclarativeSlotPoolService的

connectToResourceManager方法,而后者即图1,设置Conumer

总结,请求新资源主要是调用资源管理器的declareRequiredResources方法,该方法用

ResourceManagerLeaderListener和DeclareResourceRequirementServiceConnectionManager绕一下,是为了适应分布式环境下资源管理器上线下线,主节点选举后获取新主的地址,重新连接,每次连接完成重新设置ResourceManagerGateway

9.3 请求新资源(request new slots)

请求新资源是9.1 分配资源的延申,当前没有足够的可用资源,调度器请求新的资源

9.3.1 服务分析

类图跟9.2 申请和分配资源基本相同,场景实现由相同的类实现

1. 调度器在9.11 分配资源没有获得足够可用资源,调用SlotPool的requestNewAllocatedSlot,请求新的资源;这里的SlotPool是DeclarativeSlotPoolBridge桥接 DeclarativeSlotPool实现的SlotPool,实现声明式管理的资源池,下面不区分两者

2. DeclarativeSlotPoolBridge调用
increaseResourceRequirementsBy增加资源请求,触发检查资源请求,参看9.2.2.1深入分析

9.4 请求新worker(require new worker)

请求新worker是请求新资源的一部分,检查资源声明判断需要新增资源,向集群管理请求部署新worker,触发任务管理器部署,任务管理器启动后报告新的资源。

1. 检查资源声明是9.2请求新资源的延申,判断需要增加资源时调用requestNewWorker

2. requestNewWorker调用ResourceManagerDriver的requestResource方法,k8s环境下,ResourceManagerDriver的实现
KubernetesResourceManagerDriver,requestResource使用kubeclient向k8s集群管理发起《构建和启动任务管理器》,任务管理器启动后,9.5 注册任务管理器/报告资源

9.5 注册任务管理器/报告资源

任务管理器启动后注册到资源管理器,报告自身资源,资源通过这个方式新增的

9.5.1 服务分析

1. 任务管理器启动,同时启动高可用组件,触发
ResourceManagerLeaderListener监听机制,注意,ResourceManagerLeaderListener有两个,一个是作业管理器,一个是任务管理器,这里毫无疑问用任务管理器相关的那个

2.
ResourceManagerLeaderListener调用TaskExecutor的notifyOfNewResourceManagerLeader方法

3.
notifyOfNewResourceManagerLeader方法使用RegisteredRpcConnection连接到资源管理器

4. RegisteredRpcConnection连接完成后,触发事件onRegistrationSuccess,onRegistrationSuccess调用资源管理器的sendSlotReport(rpc)方法报告资源

5. ResourceManager的sendSlotReport方法,调用SlotManager注册任务管理器和登记资源

6. 最后采用延时异步方式执行《检查资源请求》,登记新资源,触发处理资源请求

9.6 请求使用资源(request slots)/提供资源(offer slots)

调度器申请和分配资源,匹配了合适的空闲资源,资源管理器请求资源所属的任务管理器使用资源,任务管理器确认提供资源

资源请求使用和提供两步操作,资源管理器不直接使用资源,主要让资源使用情况放在任务管理器资源管理器下线, 选出新资源管理器master,任务管理器重新注册,恢复资源使用情况

9.6.1 服务分析

1. 调度器分配资源完成,向资源所在的任务管理器TaskExecutor发出使用请求requestSlot

2. TaskExecutor调用allocateSlotForJob,登记资源使用jobId, slotId, allocationId, resourceProfile, targetAddress

3. TaskExecutor rpc-offerSlots通知JobMaster,确认提供资源

4. JobMaster转交SlotPool的offerSlots处理,同样,最终处理是DeclarativeSlotPool

5. DeclarativeSlotPool的
matchOfferWithOutstandingRequirements匹配offerSlot与未完成的资源请求,构建AllocatedSlot

6. 最后AllocatedSlot放入资源slot分配池AllocatedSlotPool,返回接收的offerSlots给TaskExecutor处理,一部分没有匹配不接收

关于
matchOfferWithOutstandingRequirements(TBD)

9.7 检查资源需求/检查资源声明

检查资源请求/检查资源声明是flink声明式资源管理的关键方法,上面的资源场景分为两类,提出资源需求提供资源, 检查资源请求/检查资源声明是交汇点,处理资源请求,该分配的分配,该请求新的请求新的资源;检查资源声明,哪些资源可以释放,需要新资源请求新worker。

本章深入分析两方法,上游提出资源需求和下游提供资源的串联,资源状态演变,存储型态

9.7.1 检查资源请求(checkResourceRequirements)

检查资源请求是真正的分配资源,上面说的分配实际只是请求分配,增加请求

1) 获取作业的未完成资源请求

2) 尝试分配可用资源到作业

之所以尝试,资源变更触发调用检查资源请求,但不一定是增加,可能是无效分配

slotTracker获取所有可用资源,与请求匹配,合适的分配allocateSlot,该方法对应场景9.6 请求使用资源/提供资源

3) 尝试使用待定的资源

待定资源是指申请了新的worker或者将要申请新worker所产生的资源,目前没有物理上的对应资源,通俗说就是先占个“坑”,等申请的资源下来填回去

同样,首先匹配现有的待定资源,若还有未分配打开新的待定资源


tryAllocateWorkerAndReserveSlot调用TaskExecutorManager的allocateWorker,预先挖好”坑”


declareNeededResourcesWithDelay方法下节介绍,按需要申请新的worker,增加物理资源

到此还有一个问题,物理资源到位后怎样填”坑”

首先,自然想到9.5 注册任务管理器/报告资源,使用新增资源抵消待定

TaskExecutorManager的registerTaskManager方法

9.7.2 检查资源声明(checkResourceDeclarations)

声明资源,要申请多少资源,可释放多少资源,上一节检查资源请求打开新待定资源,最终调用checkResourceDeclarations,实际申请新worker获得物理资源,为了支持动态/静态资源申请,中间ResourceAllocator转接了一下,这里不详细分析

现有的worker数量-需要的worker数量,大于0,worker多了可以释放;反之,worker少了,需要打开新worker

requestNewWorker参看9.4 请求新worker

ResourceDeclaration怎么来?

主要是计算totalWorkerNum,目前worker总数量

totalWorkerNum = pendingWorkerNum + neededRegisteredWorkers

pendingWorkerNum 待定的slots除以每个worker的slots,向上修正,只多不少

neededRegisteredWorkers是已经注册的worker减去待释放的worker

10 flink kubeclient

flink kubeclient是面向flink应用的fabric8 kubeclient的封装,本节分析flink如何封装kubeclient,核心组件是装饰器,资源和ServiceType,下面通过分析业务创建作业管理器组件(createJobManagerComponent)了解flink kubeclient

10.1 场景

10.2 新建作业管理器组件

1.
KubernetesJobManagerFactory构建KubernetesJobManagerSpecification

2.
KubernetesJobManagerSpecification有两属性Deployment和accompanyingResources,前者Deployment是k8s资源对象,后者是类型是List<HasMetadata>,用来管理发布的控制器,详情可参考k8s文档;accompanyingResources定义k8s资源对象,如 ConfigMap,Service等

3. KubernetesStepDecorator装饰器,装饰器列表实现责任链模式,装饰用模板构建的FlinkPod,包括主容器和其他容器,增加其特性,用户使用此机制定制pod,后面几章分析几个典型的装饰器

4. Fabric8FlinkKubeClient的createJobManagerComponent,请求k8s集群构建和启动flink master组件,输入参数是
KubernetesJobManagerSpecification,其Deployment属性直接用于Fabric8 kubeclient创建Deployment对象

下面分析几个作业管理组件重要的容器装饰器

10.2.1InitJobManagerDecorator

读入配置属性,设置pod的容器

10.2.2CmdJobManagerDecorator

装饰器只实现了pod装饰,装饰主容器,设置shell执行命令

设置执行脚本
KUBERNETES_JOB_MANAGER_SCRIPT_PATH = "kubernetes-jobmanager.sh"

deploymentTarget kubernetes-session或kubernetes-application

10.2.3ExternalServiceDecorator

装饰器构建k8s Service对象

读入ServiceType,flink对应k8s Service的抽象类,实现
buildUpExternalRestService方法,构建k8s Service

10.2.4FlinkConfMountDecorator/PodTemplateMountDecorator

两个装饰器功能相同,构建ConfigMap,非主容器作为存储卷,主容器挂载存储卷

10.3 总结

flink kubeclient要点

1. 模板构建初始的FlinkPod,拥有初始的完整的特性和属性

2. 可配置的/可扩展的装饰器增加FlinkPod的特性和属性,以及相应的资源,ConfigMap,Service等

3. Resource是k8s资源的简单封装;ServiceType是 k8s Service对象的构建器基类

11回顾

最后,本章以运行架构图串联起分析场景

1 7.2 启动k8s集群,7.3 部署集群,10.2 新建作业管理器组件

2 8.2 构建和启动flink mater组件

3 提交作业,N/A

4 分发作业,N/A

5 9.2 申请和分配资源

6 9.3 请求新资源

7 9.4 请求新worker,8.3 构建和启动任务管理器

8 9.5 注册任务管理器/报告资源

9 /10 9.6 请求使用资源/提供资源

12 附录

flink分析系列

Ø 系列(二) 作业提交,接收和分发

Ø 系列(三) 作业执行,高可用,状态,容错

Ø 系列(四) 作业调度

Ø 系列(五) 作业构建和转换

Ø 系列(六) 作业API-DataStream

Ø 系列(七) 作业API-Table&SQL

Ø 其他,内存管理,rpc

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中间件XL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值