控制器类型

控制器类型

ReplicationController 和 ReplicaSet

deployment

daemonset

statefulset

job/Cronjob

Horizontal pod Autoscaling

每一种控制器都有它们各自的优点,我们要掌握它们的优点以后才能够合理的在不同情况下去选择对应的控制器。接下来就给大家讲解一下它们每一种的特点,以及使用在那种环境之下

6.2.1 ReplicationController 和 ReplicaSet

首先就是我们的 RC 和 RS 它们写在一起就是 RS 是我们的现在进行时,RC 是我们的过去时

replicationcontroller(RC)最基本的控制器类型就是用来维持 pod 的副本数目的:用来确保容器应用的副本数目始终维持在用户定义的副本数目,即如果有容器异常退出,也会创建新的 pod 来取代,也就是意味着始终维持我们的 pod 数目;而如果异常多出来的容器也会自动回收,不管是多还是少都不行,必须得是我们的期望值上。

在新版本中得 kubernetes 建议使用 replicaset(RS)来取代 RC 。RS 和 RC 最大得不同点就是replicaset 支持了集合式得 selector(选择器);这里得选择是通过了标签进行选择即控制的。对于我们的 RS 来说它支持大量的一些算法来进行标签得匹配。而且 RC 是没有的,所以 RC 被淘汰了。

6.2.2 deployment

deployment 为我们的 pod 和 replicaset(RS) 提供了一个声明式定义方法,这需要给大家解释一下声明式定义方法,我给大家看一个说明。

对于我们的声明式定义来说它也有一个队立面,叫做命令式编程,这是两类完全不同的思想。

命令式编程:侧重于如何实现程序,就像我们刚接触编程的时候,我们需要把程序实现的结果按照逻辑结果一步一步写下来。

声明式编程:侧重于定义想要什么,然后告诉计算机引擎,让计算机去帮我们实现。

这两种其实我们已经看到了特点一个我需要一步一步的把想要得到的结果按照它的顺序和执行关系定义出来以后,它帮我们去实现。另一个是只要告诉他结果就帮我们去实现。从我们客户端这里来说那肯定是声明式编程更友好的,但是我们也看到了一个问题,声明式编程对开发人员不太友好。其实还是前端定义了一些语法结构,去理解以后帮我们实现的。并且声明式还有一个最大的特点就是,它还是一个可重复执行或叫它是一个幂等的。

声明式使用命令(deployment): apply(优) create

命令式使用命令(RS) :create(优) apply

用来替代以前的 replicationController(RC) 来方便的管理应用。典型的应用场景包括:

定义 deployment 用来创建 pod 和 Replicaset(RC)

如下图,当我们去创建一个 deployment 的时候比如这个 deployment 叫做 nginx ,这时候它呢回去创建一个叫做 nginx-deployment-xxxxx 的 RS。那这个就是一个典型的 RS 、或叫 deployment 创建的 RS ,也就是我们的 deployment 会去创建出来对应的 RS ,而 RS 再去创建出来我们对应的 Pod ,这个逻辑关系很重要,deployment 不是直接去管理这些 pod 的而是由 RS 去管理这些 pod 的。

在这里插入图片描述

滚动升级和回滚应用

滚动升级:控制 RS 这么一个版本进行我们所谓的滚动更新,回滚或者是我们所谓的暂停或继续,如果想进行滚动更新的话,它会创建出来一个新副本的 RS ,旧的这个 RS 会被删除并不是真的删除,而是将他的 pod 副本数目降低,然后将多的那个副本数目已移至新的 RS 中,直到旧的 RS 这边一个 pod 副本数都没有了,全部都移动至新的 RS 中。至此完成整个流程的滚动更新。

回滚应用:如果有一天我们觉得这个新的 RS 中的 pod 并不是我想要的结果,然后就会将旧的 RS 中的 pod 副本数目启动,并且同时将新的 RS 中的 pod 副本数往旧的 RS 中移动,直到新的 RS 移动完。就实现了我们的回滚

这就是 deployment 滚动和回滚操作底层的原理了

扩容和缩容

扩容缩容是在我们 RS 上面就已经实现了,那既然 deployment 是通过我们的 RS 去进行所谓的 pod 管理的,所以我们想都不用想了 deployment 肯定是支持的

暂停和继续 deployment

在我们的 pod 还是有对应的挂起操作,进行所谓的暂停操作。

总结:

也就意味着其实对于我们大部分应用程序来说,通过 RC 和 deployment 都可以实现了,如果两个都可以选的话建议大家选择我们的 deployment ,因为它的功能更多。

6.2.3 daemonset

daemonset 确保全部(或一些)node 上运行一个 pod 的副本上。当有 node 加入集群时,也会为它们新增一个 pod 。当有 node 从集群移除时,这些 pod 也会被收回,并不是我们的命令下达一瞬间,有哪些 node 那些 node 上就会去运行 pod 而后面新加的这些 node 以后,这些 node 并不会运行这些 pod 而是一个动态持续的过程,只要这个 daemonset 它在持续运行,没有被删除那在这个整个周期之类对应的 node 上都会去运行我想运行的 pod ,并且需要注意一下只有一个 pod 副本,也就是 daemonset 并不可以去定义超过一个以上的 pod 副本,因为它的默认值只有一个,也只能定义为一个,如果有多个 pod 需要运行在我们对应的 node 上的话,就可以通过定义多个 daemonset 的方案去实现。删除 daemonset 将会删除它创建的所有 pod,还是那句话 daemonset 引导起来的 pod 都是被我们的 daemonset 所管理的,你的管理者都已经没有了那 pod 自然也不应该存在。

全部或一些这是一个非常关键的概念:也就意味着其实在我们的 K8s 里,它的调度选择是可以被我们管理员所控制的并不是只有 K8S 自己去决定,这在后面的调度策略里会教大家怎么去把对应的 pod 放在对应的 node 上去运行,那些 node 不想运行 pod 也是可以被定义的,主要是通过我们的标签选择或者说是所谓的污点去决定的

使用 Daemonset 的一些典型用法:

运行集群存储 daemon , 例如在每个 node 上运行 glusterd、ceph

在每个 node 上运行日志收集 daemon,例如fluentd、logstash

在每个 node 上运行监控 daemon ,比如 zabbix,也可以通过 daemonset 去部署更便于我们去实现,因为他可以去确保每个 node 节点有且只有一个,哪怕 zabbix 死了以后也会被启动。

6.2.4 statefulset

我们之前也说过,对于我们的 docker 来说更适合的是运行我们的无状态服务。哪有状态服务怎么办呢,docker 给我们的解决方案是一个以存储卷的方案去加载对应的数据,但是在 K8S 里它不仅有存储卷,还给了我们一个特殊的控制器叫 statefulset ,去完成我们的有状态服务的解决。其实现在还是有很多有状态的应用程序不方便去部署进我们的 statefulset ,或是不方便部署进我们的 k8s。比如我们的 mysql ,其实至今没有一个太好的解决方案可以把 mysql 这么一个有状态服务部署进我们的 K8s。

statefulset 作为 controller 为 pod 提供唯一的表示。它可以保证部署和 scale 的顺序

statefulset 是为了解决有状态服务的问题 (对应 Deployments 和 ReplicaSets 是为无状态服务而设计),其应用场景包括:

稳定的持久化存储:即 pod 重新调度后还是能够访问到相同的持久化数据,基于 PVC 来实现。假设现在我有几个我们的容器,是被我们的 statefulset 去部署的,部署完成以后呢可能都用到了我们同一个存储卷,假如有一天这个 pod 死亡了,但我们的 statefulset 为了维持这个副本数就会重新创建对应的 pod ,这时候新创建的 pod 也会继续使用上一个 pod 退出时使用到的存储卷。也就这里的持久化数据并不会丢失,这就是我们所谓的稳定的持久化存储方案。

稳定的网络标识:即 pod 重新调度以后其 pod name 和 host name 不变(这个很重要,在我们的很多服务里我们去创建对应的一些服务的链接方案的时候,都会以我们的 pod name 为链接对象,或者 host name 为链接对象,如果我们的 pod 死亡被重新创建以后它的名称发生改变了这个对于我们后面的自动化流程来说时非常不友好的。但是对于我们的 statefulset 来说它可以确保每一个 pod 它的 pod name 和 host name 在 statefulset 生命周期里完全不变),基于 headless service 无头服务实现(也就是没有 cluster IP 的 service,可以理解为没有 IP 地址和端口 )来实现

有序部署,有序扩展:即 pod 是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(即从 0 到 N1,在下一个 pod 运行之前所有的 pod 必须是 running 和 ready 状态),基于 init containers 来实现。好这里需要注意以下为啥是基于 init containers 而不是基于我们所谓的 start 或 stop ,原因是不管是 start 、stop 他都需要去更改我们 pod 内部的容器镜像,但是对于init containers 初始化容器来说是不需要更改的,只需要在statefulset 的 pod 里面的容器运行之前加一个 init C ,并不会对我们的原有 pod 结构发生改变。所以这是他的解决方案怎么去实现这里的 running 和 ready。

有序收缩,有序删除(即从 N1 到 0):会发现在扩展部署的时候是 0 到 N1 的,在删除的时候 N1 到 0 的,这是一个倒序关系。我们可以观察下图:

在这里插入图片描述

现在我有这么一个结构,底下是我们一个数据库 mysql ,上面运行了我们一些 php-fpm,在上面运行了我们的一个 nginx 实现了我们的一个反向代理,这样的一个结构我们会发现在部署的时候应该从底往上部署。也就意味着他是先部署我们的 mysql –> php-fpm –> nginx ,这我们的部署顺序。那如果我们想把这个服务停止的话它的顺序正好是相反的,我们应该先停我们的 nginx –> php-fpm –> mysql ,这时候有可能有的朋友就会想为什么不是先停我们的 mysql , 假如我们先把 mysql 停了,那这里的 php-fpm 和 nginx 还是在运行状态。用户的请求有可能是会到我们的 nginx 那就有可能到我们的 php-fpm 就有可能报错。所以它的部署顺序和它的启动顺序恰好是相反的。

6.2.5 job

job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 pod 成功结束。这是什么盖脸呢,举例:我现在有这么一个脚本,这个脚本如果正常退出的话是以 0 状态码退出的,这时候 job 就会记录它的正常退出次数为 1 ,那我是可以定义 job 能够正常退出的次数。比如我们定义为 4 ,它正常退出一次我们的次数加 1 ,有运行一遍我们就加 1 变为 2 直到正常退出次数为 4 。变成4 达到我们的要求以后这个 job 成功退出。这个成功退出的含义就是这个 job 执行完成了就不需要运行了。

job 的生命周期也就等于我们的 pod 运行至成功数目以后结束,那我们想要一个根据时间去循环的 job 的话,这时就需要借助到 cronjob 的这么一个控制器。

那如果我们有一些类似于脚本的方案需要去执行的话,我就需要引入两个新的管理器,一个是 job 一个是我们的 Cronjob

job 会有自己的纠错能力,也就意味着如果在里面运行的这么一个脚本没有以 0 的状态码退出的话,他会重新执行这个程序,也就意味着以 job 去实现的这么一个管理控制器,它更倾向于去以这种所谓的脚本的运行方案机制的这么一个 pod 的管理。也就意味着以 job 这么一个资源管理控制器里面去部署对应的脚本,以确保它能够正常运行。

6.2.6 Cronjob 在特定的时间循环创建 job

cron job 管理基于时间的 job,即:

在给定的时间内只允许一次

周期性地在给定时间点运行

类似于 Linux 中的 crontab 定时计划任务。

并且 cronjob 也是通过创建在特定时间创定 job 去实现的

配置方案和 crontab 一摸一样 * * * * * 分、时、日、月、周

但是运行 cronjob 有前提条件:当前使用的 K8S 集群,版本必须大于 1.8 。启动 API server 时,通过传递选项 --runtime-config=batch/v2alpha1=true可以开启 batch/v2alpha1 API**

典型的使用方法如下所示:

在给定的时间点调度 job 运行

周期性的创建运行的 job,例如:数据库备份、发送邮件

总结:

当遇到批处理的任务,job、cronjob 是我们最好的处理方案。

6.2.7 Horizontal pod Autoscaling (HPA 水平扩展)

应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让 service 中的 pod 个数自动调整呢?这就有赖于 HPA 了,顾名思义使 Pod 水平自动缩放。

自动扩展,我们可以理解为它并不是一个控制器,而是一个控制器的附属品,比如我先部署了一个 RS 这时候我再去确定 HPA ,去运行管理这个 RS ,比如我先部署了一个 deployment ,我再去创建一个 HPA 去管理这个deployment。 HPA 并不是一个直接的控制器,HPA 是控制这些控制器为模板的。

那我们为什么需要这个 HPA 控制器呢,这个 HPA 给我们实现的就是一个自动扩容缩容方案;可以居于我们的一些指标去实现,比如一些 CPU 大于百分之 80 的时候给我们扩容到 10 个节点,那 CPU 小于百分之 60 的时候就给我们恢复到 4 个节点。这里的过程就可以以 HPA 来实现,当然我们 K8s 集群本身是不支持这个功能的,他需要加一个资源收集的方案,给我们 HPA 提供一个资源性能的指标,才能帮我去做调整。

6.2.8 总结:

有状态服务部署至我们的 RS 、deployment 需要与我们 node 为节点部署至 daemonset ,是一些批处理任务的话部署在 job 和 cronjob,有状态服务 statefulset,以上就是我们控制器的一些类型,包括他的一些意义,以及每种控制器适合在那种情况下去运行。

※部分文章来源于网络,如有侵权请联系删除;更多文章和资料|点击后方文字直达 ↓↓↓ 100GPython自学资料包 阿里云K8s实战手册 [阿里云CDN排坑指南]CDN ECS运维指南 DevOps实践手册 Hadoop大数据实战手册 Knative云原生应用开发指南 OSS 运维实战手册 云原生架构白皮书 Zabbix企业级分布式监控系统源码文档 10G大厂面试题戳领

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值