kubernetes高可用(kubernetes高可用架构)
大家好!今天让创意岭的小编来大家介绍下关于kubernetes高可用的问题,以下是小编对此问题的归纳整理,让我们一起来看看吧。
开始之前先推荐一个非常厉害的Ai人工智能工具,一键生成原创文章、方案、文案、工作计划、工作报告、论文、代码、作文、做题和对话答疑等等
只需要输入关键词,就能返回你想要的内容,越精准,写出的就越详细,有微信小程序端、在线网页版、PC客户端
创意岭作为行业内优秀的企业,服务客户遍布全球各地,如需了解SEO相关业务请拨打电话175-8598-2043,或添加微信:1454722008
本文目录:
一、【Flink on k8s】高可用的关键机制及configmap数据详解
源码详解:DefaultCompletedCheckpointStore.addCheckpoint/tryRemoveCompletedCheckpoint
步骤 1 :根据checkpointID获取checkpoint path
步骤 2 :在s3 path写state数据,接着修改configmap的中checkpoint信息即flink-161511ce1fe78368bc659597e472fb7d-jobmanager-leader的checkpointID-0000000000000102688
步骤 3 :把checkpoint信息放到队列里面,然后根据需要保留的completecheckpoint数量(集群配置state.checkpoints.num-retained),删除多余的completecheckpoint
设置 s3 协议的文件路径作为状态后端即 s3://bucket01/flink/savepoints 、 s3://bucket01/flink/checkpoints ,设置支持 s3 协议的集群即 s3.endpoint 、 s3.access-key 和 s3.secret-key 。
high-availability 设置为 org.apache.flink.kubernetes.highavailability.KubernetesHaServicesFactory ,
kubernetes.namespace 是指 kubernetes 的 namespace,kubernetes.service-account 是指 kubernetes 的serviceaccount, high-availability.storageDir 采用 s3 地址,最后 kubernetes.cluster-id 是设置了高可用 configmap 的前缀,例如 flink-dispatcher-leader、flink-161511ce1fe78368bc659597e472fb7d-jobmanager-leader 等
dispatcher 是管理作业的主节点,高可用数据主要有 dispatcher 主节点的地址 、 非完成状态的作业状态和流图保存地址 ,其中流图保存地址是 Base64 编码的。如下所示,dispatcher 主节点是 akka.tcp://flink@10.244.0.246:8123/user/rpc/dispatcher_1 ,作业 161511ce1fe78368bc659597e472fb7d 的状态是 Running ,其流图 jobGraph-161511ce1fe78368bc659597e472fb7d 保存在 s3://bucket01/flink/ha/default/submittedJobGraph407e2d6a5be8
作业的高可用数据主要有 作业管理节点的地址 、 当前作业的checkpoint 最新数据的保存地址 ,其中checkpoint 保存地址是 Base64 编码的。如下所示,作业管理节点是 akka.tcp://flink@10.244.0.246:8123/user/rpc/jobmanager_2 ,该作业最新的 checkpoint 是 checkpointID-0000000000000102688 ,其保存地址是 s3://bucket01/flink/ha/default/completedCheckpointf07724c0946a
二、kubernetes架构-组件交互篇
Kubernetes的节点包含两种角色:Master节点和Node节点。Master节点部署apiserver 、scheduler、controller manager (replication controller、node controller等),Node节点上部署kubelet和proxy。当然可以把Master和Node节点部署到一起,只是生产环境通常不建议这样做。
以下涉及各个组件实现了什么,有什么处理逻辑,部分组件涉及该组件的高可用,并以deployment创建为例串了下流程。整个下来,对kunernetes各个组件有一定的了解。
Apiserver 是Kubernetes最核心的组件,是整个集群API的入口,每个组件都需要和它交互。Kubernetes所有资源数据都是通过Apiserver保存到后端Etcd的,它本身还提供了对资源的缓存。因为Apiserver是无状态的,所以在集群的高可用部署可以为多活。
Apiserver启动 后会将每个版本的接口注册到一个 核心的路由分发器(Mux) 。Kubernetes API接口主要分为组、版本和资源三层。举例:“/apis/batch/v1/jobs”接口,batch是组,v1是版本,jobs是资源。Kubernetes的核心资源都放在“/api”接口下,扩展的接口放在“/apis”下。
Apiserver请求处理流程拆分如下:
1) 当客户端请求到达Apiserver后,首先经过Authentication认证和Authorization授权。认证支持Basic、Token及证书认证等。授权目前默认使用的是RBAC。
2) 认证成功后,请求到达路由分发器(Mux),然后路由分发到指定接口。
3) 经过路由分发后,为了兼容多个接口版本,将请求中不同版本的资源类型统一转化为一个内部资源类型。
4) 转换为内部模型后, 进入Admission准入控制 ,在准入控制采用插件机制,用户可以定义自己的注入控制器验证,并更改资源配置。
5) 准入控制通过后,进入 Validation资源校验 。资源校验主要是验证参数是否合法,必传参数是否齐备等。
6) 最后转化到用户最初的资源版本,并保存到 Etcd 中。
Controller manager是负责资源管理的组件,它主要负责容器的副本数管理、节点状态维护、节点网段分配等,是Kubernetes负责实现生命式API和控制器模式的核心。
以ReplicaSet为例,Controller manager会周期地检测理想的“目标容器数”和真实的“当前容器数”是否相同。如果不相等,则会将实际的容器数调整到目标容器数。当设置一个ReplicaSet的副本数为10的时候,如果实际的容器数小于10,则会执行调用Apiserver创建Pod。如果当前容器数大于10,则会执行删除Pod操作。
Scheduler负责容器调度组件。每个Pod会在一台node节点上启动,通过 Scheduler 调度组件的筛选、打分,选择出Pod启动的最佳节点。当Pod创建后,Pod的NodeName属性为空,Scheduler会查询所有NodeName为空的Pod,并执行调度策略。选择最优的部署节点后,调用 Apiserver 绑定Pod对应的主机(设置Pod NodeName属性)。绑定成功后,对应节点的 Kubelet 便可以启动容器。
Scheduler的调度过程分为两个步骤:
第一步是筛选(Predicate),筛选满足需要的节点。筛选的条件主要包括(1)Pod所需的资源(CPU、内存、GPU等);(2)端口是否冲突(针对Pod HostPort端口和主机上面已有端口,我认为这个应该是容器的网络模式为host);(3)nodeSelector及亲和性(Pod亲和性和Node亲和性);(4)如果使用本地存储,那么Pod在调度时,将只会调度存储绑定的节点;(5)节点的驱赶策略,节点可以通过taint(污点)设置驱赶Pod策略,对应的Pod也可以设置Toleration(容忍)。
第二步是根据资源分配算法排序打分(Priorities),选择得分最高的节点作为最终的调度节点,主要调度策略包括LeastRequestedPriority(最少资源请求)、BalancedResourceAllocation(均衡资源使用)、ImageLocalityPriority(镜像本地优先)和NodeAffinityPriority(主机亲和算法)等。为了归一化每种算法的权重,每种算法取值范围都是0~10,累加所有算法的总和,取得分最大的主机作为Pod的运行主机。
Scheduler组件本地维护了一个调度队列和本地缓存, 调度队列 暂存了需要被调度的Pod,调度的先后顺序可以调整。 本地缓存 主要是缓存Pod和Node信息,可以避免每次调度时都从Apiserver获取主机信息。
为了提高调度效率,Scheduler采用了乐观锁,即Predicate和Priorities是并行操作的,那么有可能会出现数据的不一致,即Pod调度时主机上面资源是符合要求的。当容器启动时,由于其他容器也调度到该节点导致资源又不满足要求了。所以在Kubelet启动容器之前首先执行一遍审计(在Kubelet上重新执行一遍Predicate)操作,确认资源充足才会启动容器,否则将更新Pod状态为Failed。
Scheduler是典型的单体调度。为了 支持高可用 ,可以部署多个Scheduler,但只有一个Scheduler处于Active状态,其他都为Standby状态。当处于Active的Scheduler宕机后,由于无法续约,会从Etcd中摘除,其他Scheduler节点便可以通过争抢注册Etcd的方式获得调度权限。
Kubelet 接收 Apiserver 分配的启动容器的任务,然后拉起容器。当然,如果收到销毁指令,同样会执行删除容器的操作。
本地镜像也是由Kubelet负责维护,配合GC机制,删除无用的镜像和容器。
除此之外,Kubelet还需定时向 Apiserver 上报自己的状态,一方面告知Apiserver自身还存活着,另一方面将本节点的Pod状态、存储使用等信息上报到Apiserver。
Kubelet启动一个主线程,用于保持和Apiserver的通信,主线程不能被阻塞,否则将无法定时完成上报,导致Apiserver将该节点设置为NotReady状态。所以Kubelet会启动很多协程用于检测节点状态,回收废旧资源,驱赶低优先级Pod,探测Pod健康状态等。 syncLoop 是Kubelet的核心,它通过一个死循环不断接收来自Pod的变化信息,并通过各种Manger执行对应的操作,如下图。
Kube-proxy 是代理服务,为Kubernetes的Service提供负载均衡,本质上是iptables或ipvs实现的。Kubernetes将服务和Pod通过标签的方式关联到一起,通过服务的标签筛选找到后端的Pod,但服务的后端通过Endpoint(端点)关联Pod,Endpoint可以理解为“Pod地址:Pod端口”的组合。
举例:kube-proxy如何生成iptables规则的?当创建一个服务后,Kubernetes默认会为每个服务生成一个虚拟IP( VIP )。通过访问VIP即以负载均衡的方式访问后端Pod的服务。举例一个服务:对内提供服务的端口8080,对外提供服务的端口31341,并通过paas.io/serviceName选择后端容器。这会在每台机器上生产如下iptables规则。
1)将进和出的流量都转到KUBE-SERVICES链上。
2)目标是VIP(10.0.0.41)或访问NodePort的流量都转发到某个链上(KUBE-SVC-HDARFCJAQENGWQ37)。
3)KUBE-SVC-HDARFCJAQENGWQ37链通过iptables的随机模块分发流量,第一个是50%,第二个是100%。如果后端有3个Pod,那么比例将会是33%、50%、100%,以此类推。
4)最终通过DNAT进入容器。
通过kubectl run(eg:kubectl run nginx--image=nginx--replicas=5)命令去创建一个Deployment。
这个请求先到达 Apiserver ,Apiserver负责保存到 Etcd , Controller manager 中的Deployment控制器会监测到有一个Deployment被创建,此时会创建相应的ReplicaSet,ReplicaSet的控制器也会监测到有新的ReplicaSet创建,会根据相应的副本数调用Apiserver创建Pod。
此时Pod的主机字段是空的,因为还不知道将要在哪台机器上面启动,然后 Scheduler 开始介入,调度没有分配主机的Pod,通过预先设定的调度规则,包括节点标签匹配、资源使用量等选择出最合适的一台机器,在通过apiserver的bind请求将Pod的主机字段设置完成。
Kubelet 监测到属于自己的节点有新容器创建的事件,于是便拉起一个容器,并上报给apiserver容器的状态。
三、Kubernetes存储
在 Docker的设计 实现中, 容器中的数据是临时性的,当容器销毁或重新启动时存储在容器内部的数据将会全部丢失 ,但实际上很多容器化应用是需要持久化保存的数据,这就需要使用Docker数据卷挂载宿主机上的文件或者目录到容器中以保证数据的持久化存储。在 Kubernetes中Pod重建如同Docker销毁一样,数据就会丢失 ,Kubernetes也通过挂载数据卷方式为Pod数据提供持久化能力,这些数据卷以Pod为最小单位进行存储,通过共享存储或分布式存储在各个Pod之间实现共享。
Kubernetes是由Master节点及Node节点组成的,在Master节点中通过etcd存储了Kubernetes集群的节点信息、Pod信息、容器信息、配置信息。Node节点主要对外提供容器服务,着重描述Node节点与存储相关的内容。
Kubernetes以Pod为单位对外提供容器服务,真正的服务是通过Service进行访问的。 Kubernetes中的服务按类型分成三种:无状态服务(stateless)、普通有状态服务、有状态集群服务 。
无状态服务:不需要持久化存储的,即使Pod重建也不会受影响,只要确保服务的可靠性便可,Kubernetes通过ReplicationSet来保证某个服务的实例数量。
普通有状态服务:这类服务需要保留服务的状态,通常通过Kubernetes提供的Volume及Persistent Volume、Persistent Volume Claim来保存状态。
有状态的集群服务:这类服务除了保存服务状态的同时还需要提供集群管理的功能,集群管理过程中也涉及临时数据的保存、集群内数据共享等。
Kubernetes中涉及存储的主要使用场景 :
1) 容器集群相关配置信息及运行时信息保存,这类信息存储在etcd中。
2) 服务的基本配置文件及证书文件。
3) 服务的状态存储、数据存储信息。
4) 集群内不同服务交换共享的数据信息。
1) 临时文件形式 :同一个Pod内不同容器间通过共享内存方式访问,会创建一个空目录,交换完信息后会删除这个空目录。
2) HostPath方式 :同一个Node内不同的Pod间进行信息共享使用HostPath方式(比如时区timezone)。如果Pod配置了EmptyDir数据卷,则它在Pod的生命周期内都会存在。当Pod被分配到Node上的时候,会在Node上创建EmptyDir数据卷,并挂载到Pod的容器中。
3) PV及PVC: Kubernetes的持久化存储机制的核心是PV(Persistent Volume)、PVC (Persistent Volume Claim)。PV是Volume插件,关联到真正的后端存储系统,PVC是从PV中申请资源,而不需要关心存储的提供方。PVC和PV的关系就如同Pod和Node一样,Pod是消费Node提供的资源,PVC是消费PV提供的存储资源。PVC和PV通过匹配完成绑定关系,PVC可以被Pod里的容器挂载。
4) 网络方式 :不同Node节点之间的数据共享通过网络方式使用,通常采用分布式存储方式。开源的分布式文件系统比较流行的选择有GlusterFS和Ceph,还有一些其他的分布式文件系统(NFS)选择。
5) 自定义插件方式 :Kubernetes提供了丰富的Volume的插件来进行存储管理。如果存储管理接口不够用,用户可以通过CSI或Flex Volume进行扩展。
存储管理组件(存储组件)主要是接收北向API收到的Rest请求,维护持久卷的生命周期管理。如创建、删除卷, 存储组件负责与后端存储软件交互完成实际的创建、删除卷等操作;并负责调用Kubernetes原生接口创建对应的PVC和PV 。
存储后端系统提供数据文件的实际持久化能力,不仅需要实现数据文件的读写、副本复制等存储操作,通常还需具备多节点高可用的能力。
当需要为自己的微服务应用挂载持久卷时,只需要通过存储组件创建持久卷,存储组件会在Kubernetes业务集群创建PVC/PV,并到后端存储系统(如GlusterFS)上创建真正的物理Volume,同时维护好PVC/PV/Volume之间的一一映射对应关系。这样,用户部署容器时就可以选择挂载相应的持久卷,部署后相应的卷就可以挂载到对应的容器。应用挂载持久卷后,进行读写时就类似于本地目录的读写操作。
在Pod进行重建或者迁移到其他节点时,Pod可以自动挂回原来对应的持久卷,继续使用原先的数据。多个Pod可以共享一个持久卷,从而达到容器间文件共享的目的。
摘抄自陆平的《基于Kubernetes的容器云平台实战》一书的第11章Kubernetes存储
四、Kubernetes对象之ReplicaSet
说到ReplicaSet对象,得先说说ReplicationController(简称为RC)。在旧版本的Kubernetes中,只有ReplicationController对象。它的主要作用是 确保Pod以你指定的副本数运行 ,即如果有容器异常退出,会自动创建新的 Pod 来替代;而异常多出来的容器也会自动回收。可以说,通过ReplicationController,Kubernetes实现了集群的高可用性。
在新版本的 Kubernetes 中建议使用 ReplicaSet(简称为RS )来取代 ReplicationController。ReplicaSet 跟 ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector(ReplicationController 仅支持等式)。
ReplicationController和Pod一样,都是Kubernetes中的对象,因此创建方式类似。通过yaml或json描述文件来定义一个ReplicationController对象。一个最简单的ReplicationController的定义如下:
下面简要解释一下上述ReplicationController描述文件中的关键点:
上面的RC通过 kubectl apply 命令创建成功后,Kubernetes会在所有可用的Node上,新建三个Pod。每个Pod都有一个app: nginx的label,并且每个Pod中都运行一个nginx容器。一旦其中某个Pod发生故障停止运行了,Controller Manager都能够及时发现,然后根据当前RC定义,创建出一个新的Pod,从而使包含label:app: nginx的Pod的运行副本数始终为3。
由于ReplicaSet是ReplicationController的代替物,因此用法基本相同,唯一的区别在于ReplicaSet支持集合式的selector。一个典型的RS描述文件如下:
以上RS描述文件中,selector除了可以使用matchLabels,还支持集合式的操作:
使用 kubectl delete 命令会删除此RS以及它管理的Pod。在Kubernetes删除RS前,会将RS的replica调整为0,等待所有的Pod被删除后,在执行RS对象的删除。
如果希望仅仅删除RS对象(保留Pod),请使用 kubectl delete 命令时添加 --cascade=false 选项。
通过修改 .spec.replicas 的值可以实时修改RS运行的Pod数量。
RS可以通过HPA来根据一些运行时指标实现自动伸缩,下面是一个简单的例子:
上面的描述文件会创建一个名为frontend-scaler的HorizontalPodAutoscaler,它会根据CPU的运行参数来对名为frontend的RS进行自动伸缩。
更过关于HPA的信息请参考:
以上就是关于kubernetes高可用相关问题的回答。希望能帮到你,如有更多相关问题,您也可以联系我们的客服进行咨询,客服也会为您讲解更多精彩的知识和内容。
推荐阅读: