通常情况下,在服务部署的时候,使用 pod 来管理一组相关的服务(一个 pod 中要么部署一个服务,要么部署一组有关系的服务)。如下图是部署了一组有关系的服务的结构图,其中 C 表示容器(container),下面的 pod 里就有很多个容器。
如何理解一组相关的服务?
如下图:有一个请求是访问 Nginx,然后部署了 Nginx 的容器就把请求转发给部署了 web 服务的容器,web 再访问数据库,然后请求会依次返回来数据,最后再返回给用户。
因此在 链式调用的调用链路上的服务 叫做一组相关的服务。
只需要复制多个 pod 的副本即可,这也是 k8s 管理的先进之处。k8s 如果要进行扩容或缩容,只需要控制 pod 的数量即可。比如上面那个部署模式,服务集群就是复制多个这样的 pod。
前面说过 pod 内部的容器也是一个独立的沙箱环境,因此也有自己的 ip 和 端口。如果内部容器还是通过 ip:port 来通信,相当于还是远程访问,这样的话性能会受到一定的影响。如何提高内部容器之间访问的性能呢?
pod 底层
作用:管理控制 pod 副本(服务集群)的数量,以使其永远与预期设定的数量保持一致。
例如:replicas = 3 (创建 3 个副本,这是提前设置好的)
当副本设置为 3 时,副本控制器将会永远保证副本数量为 3。因此当有 pod 服务宕机时(如上面第 3 个 pod),那副本控制器会立马重新创建一个新的 pod,就能够保证副本数量一直为预先设定好的 3 个。
ReplicaSet 和 ReplicationController 都是副本控制器,其中:
什么意思呢?
假设下面有下面两个不同机器上的 Node 结点,如何知道它们的 pod 其实都是相同的呢?答案是通过标签。
给每个 pod 打上标签 ( key=value 格式,如下图中的 app=web, release=stable,这有两个选项,相同的pod副本的标签是一样的),于是副本控制器可以通过标签选择器 seletor 去选择一组相关的服务。
一旦 selector 和 pod 的标签匹配上了,就表明这个 pod 是当前这个副本控制器控制的,表明了副本控制器和 pod 的所属关系。如下图中 seletor 指定了 app = web 和 release=stable 是复合选择,要用 ReplicaSet 才能实现若用 ReplicationController 的话只能选择一个,如只选择匹配app=web标签。这样下面的 3 个 pod 就归这个副本控制器管。
可见 ReplicaSet 功能更齐全,所以在新版的 k8s 中,建议使用 ReplicaSet 作为副本控制器,不再使用 ReplicationController。
ReplicaSet 副本控制器可以永久保持 pod 副本的数量。但是项目的需求在不断的迭代、更新,项目在不断发版。那如何做到服务更新?难道把服务停掉再把新版本部署上去吗?当然不是,答案是用滚动更新。就是重新创建一个 pod (v2版本) 来代替 之前的 pod (v1版本)。
那是如何滚动更新的呢?涉及到下面要讲到的部署模型。
单独的 ReplicaSet 是不支持滚动更新的,Deployment 对象支持滚动更新,通常和 ReplicaSet 一起使用。
需要滚动更新时的步骤:
所以它们之间是有层次关系的,Deployment 管 Replicaset,Replicaset 维护 pod。在更新时删除的是旧的 pod,老版本的 ReplicaSet 是不会删除的,所以在需要时还可以回退以前的状态。
思考:如果 MySQL(有状态服务) 使用容器化部署,会存在什么问题?
因此对 k8s 来说,不能使用 Deployment 部署有状态的服务。通常情况下,Deployment 被用来部署无状态服务。
然后 StatefulSet 就是为了解决有状态服务使用容器化部署的一个问题。
StatefulSet 的部署模型和 Deployment 的很相似。
比如下图,借助 PVC(与存储有关) 文件系统来存储的实时数据,因此下图就是一个有状态服务的部署。
在 pod 宕机之后重新建立 pod 时,StatefulSet 通过保证 hostname 不发生变化来保证数据不丢失。因此 pod 就可以通过 hostname 来关联(找到) 之前存储的数据。
原文链接: https://blog.csdn.net/qq_43280818/article/details/106910187
本文分享自 kubernetes中文社区 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!