pod的编排扩张和收缩(1)

K8S中有很多种控制器用于pod的水平扩展和收缩。本篇文章将介绍常用的deployment和statefulset。这两种控制器将分别对应无状态pod和有状态pod。

目录

deployment

relicas实现机制:

StatefulSet

总结


deployment

deployment对应无状态pod。 无状态pod表示:pod之间是对等的关系,相互之间没有依赖,所有pod都是一样的。这时候我们可以利用deployment控制器对pod进行拓张和收缩控制。具体地,我们可以根据deployment中字段replicas修改pod的数量,使实际pod数量符合deployment中relicas预期。

relicas实现机制:

当我们更新deployment定义的pod的模版,deployment需要遵循一种称为“滚动更新”的机制来更新现有的容器。而这个能力依赖于K8中的RelicaSet。也就是说,Deployment 控制器实际操纵的,正是这样的 ReplicaSet 对象,由ReplicaSet来更新pod的版本和数量。例如当relicas=3时ReplicaSet会为我们保持3个一样的pod。 

“滚动更新”是如何实现的呢?Deployment 的控制器,实际上控制的是 ReplicaSet 的数目,以及每个 ReplicaSet 的属性。当们对当前V1版本的pod更新为V2版本的pod我们可以进行设置比例,例如:每次删除一个旧的pod创建一个新的pod直到创建出3个新的pod为止,如下图:

 并且,我们可以通过历史ReplicaSet对pod进行回滚操作。


StatefulSet

statefulSet对应我们有状态的pod。 statefulSet解决pod之间的拓扑状态和存储状态。

拓扑状态:指的是pod之间的关系不是对等的,他们的创建有严格的前后顺序。

存储状态:指的是pod分别绑定不同的存储数据。对于这些实例来说,PodA第一次读到的数据和十分钟之后,甚至PodA被删除重创之后读到的数据是同一份的。这种情况最典型的例子,就是一个数据库应用的多个存储实例。

所以,statefulSet的核心功能就是保持pod创建的拓补状态和存储状态,基于此,statefulSet保证了pod网络标识的稳定性。

我们先来看如何保证pod网络标识的稳定性的。我们知道,假设一个Deployment有3个pod,那么我们可以定义一个Service,然后用户只需要访问到这个Service就可以访问到具体某个pod

具体的,Service有两种方式。

第一种是以Service的VIP(Virtual IP,即:虚拟IP)方式,比如:当我访问10.0.23.1这个Service的IP地址时,10.0.23.1其实就是一个VIP,它会把请求转发到该Service所代理的某一个Pod上

第二种方式,就是以Service的DNS方式。比如:这时候,只要我访问“my-svc.my-namespace.svc.cluster.local”这条DNS记录,就可以访问到名叫my-svc的Service所代理的某一个Pod。这种方式具体有两种实现方式:

第一种处理方法,是Normal Service。这种情况下,你访问“my-svc.my-namespace.svc.cluster.local”解析到的,正是my-svc这个Service的VIP,后面的流程就跟VIP方式一致了。而第二种处理方法,正是Headless Service。这种情况下,你访问“my-svc.my-namespace.svc.cluster.local”解析到的,直接就是my-svc代理的某一个Pod的IP地址。可以看到,这里的区别在于,Headless Service不需要分配一个VIP,而是可以直接以DNS记录的方式解析出被代理Pod的IP地址。


讲Service两种方式是为了接下来要讲statefulSet如何保证pod的稳定性的。

我们知道,StatefulSet是一种特殊的deployment,特殊就特殊在它对管理的pod进行编号编号规则是:<statefulset name>-<ordinal index>。并且,编号规则从0开始。例如: web-0,web-1。而我们创建pod正是根据这个编号来确定创建的顺序从而保证拓扑状态

并且这里当我们访问web-0.nginx的时候,最后解析到的,正是web-0这个Pod的IP地址;而当访问web-1.nginx的时候,解析到的则是web-1的IP地址。也就是说这里使用的是Headless Serviced方式。

可见ClusterIP 模式的 Service 为你提供的,就是一个 Pod 的稳定的 IP 地 址,即 VIP。并且,这里 Pod 和 Service 的关系是可以通过 Label 确定的。

而 Headless Service 为你提供的,则是一个 Pod 的稳定的 DNS 名字,并且,这个名字是 可以通过 Pod 名字和 Service 名字拼接出来的。

当我们把这两个有状态pod删除,Kubernetes会按照原先编号的顺序,重新创建出了两个新的Pod。并且,Kubernetes根据它们的编号(还是0和1)给它们分配了与原来相同的“网络身份”:web-0.nginx和web-1.nginx。通过这种严格的对应规则,StatefulSet就保证了Pod网络标识的稳定性。这时你访问web-0.nginx则自动访问pod0的新IP。

所以,如果web-0是一个需要先启动的主节点,web-1是一个后启动的从节点,那么只要这个StatefulSet不被删除,你访问web-0.nginx时始终都会落在主节点上,访问web-1.nginx时,则始终都会落在从节点上,这个关系绝对不会发生任何变化。所以通过Headless Service的方式,StatefulSet为每个Pod创建了一个固定并且稳定的DNS记录,来作为它的访问入口。实际上,在部署“有状态应用”的时候,应用的每个实例拥有唯一并且稳定的“网络标识”。


基于这个编号的性质,我们实现了存储状态的保证。具体如何实现,我们需要先了解Persistent Volume Claim(PVC)和Persistent Volume(PV)的API对象。

这里PV是一个具体实现对象,里面有一些volume的属性,例如:10HB内存,只能读写。并且PV是在远端服务器的。

而PVC只是一个声明,我们只需要在Pod中写一个PVC用来描述我们需要什么属性的存储卷,K8就会自动给我们分配实现好了的符合PVC要求的PV。

具体地,我们为这个StatefulSet额外添加了一个volumeClaimTemplates字段。从名字就可以看出来,它跟Deployment里Pod模板(PodTemplate)的作用类似。也就是说,凡是被这个StatefulSet管理的Pod,都会声明一个对应的PVC;而这个PVC的定义,就来自于volumeClaimTemplates这个模板字段。更重要的是,这个PVC的名字,会被分配一个与这个Pod完全一致的编号。这个自动创建的PVC,与PV绑定成功后,就会进入Bound状态,这就意味着这个Pod可以挂载并使用这个PV了。因此,PVC,都以“<PVC名字>-<StatefulSet名字>-<编号>”的方式命名。

那我们如何做到存储状态的保证的呢?当你把一个Pod,比如web-0,删除之后,这个Pod对应的PVC和PV,并不会被删除,而这个Volume里已经写入的数据,也依然会保存在远程存储服务里(比如,我们在这个例子里用到的Ceph服务器)。而当StatefulSet发现0号pod消失了就会重新创建一个0号pod,由于是0号pod声明还是0号PVC ,于是自动绑定到0号PVC,而0号PVC则是绑定在原来的PV上的。所以,这时候新0号pod读取的数据还是和之前一样。

总结

看到这里,你是不是已经大致理解了StatefulSet的工作原理呢?现在,我再为你详细梳理一下吧。

首先,StatefulSet的控制器直接管理的是Pod。这是因为,StatefulSet里的不同Pod实例,不再像ReplicaSet中那样都是完全一样的,而是有了细微区别的。比如,每个Pod的hostname、名字等都是不同的、携带了编号的。而StatefulSet区分这些实例的方式,就是通过在Pod的名字里加上事先约定好的编号。

其次,Kubernetes通过Headless Service,为这些有编号的Pod,在DNS服务器中生成带有同样编号的DNS记录。只要StatefulSet能够保证这些Pod名字里的编号不变,那么Service里类似于web-0.nginx.default.svc.cluster.local这样的DNS记录也就不会变,而这条记录解析出来的Pod的IP地址,则会随着后端Pod的删除和再创建而自动更新。这当然是Service机制本身的能力,不需要StatefulSet操心。

最后,StatefulSet还为每一个Pod分配并创建一个同样编号的PVC。这样,Kubernetes就可以通过Persistent Volume机制为这个PVC绑定上对应的PV,从而保证了每一个Pod都拥有一个独立的Volume。

在这种情况下,即使Pod被删除,它所对应的PVC和PV依然会保留下来。所以当这个Pod被重新创建出来之后,Kubernetes会为它找到同样编号的PVC,挂载这个PVC对应的Volume,从而获取到以前保存在Volume里的数据。

因此,StatefulSet其实是一种特殊的Deployment,只不过这个“Deployment”的每个Pod实例的名字里,都携带了一个唯一并且固定的编号。这个编号的顺序,固定了Pod的拓扑关系;这个编号对应的DNS记录,固定了Pod的访问方式;这个编号对应的PV,绑定了Pod与持久化存储的关系。所以,当Pod被删除重建时,这些“状态”都会保持不变。

而一旦你的应用没办法通过上述方式进行状态的管理,那就代表了StatefulSet已经不能解决它的部署问题了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值