首页
  • 监控

    • grafana
    • prometheus
  • 学习笔记

    • 《核心系统命令实战》
    • 《MySQL 是怎样运行的:从根儿上理解 MySQL》
    • 《Ansible权威指南》
  • 博客搭建
  • git
  • python
  • 友情链接
  • 文档编写规范
  • 我用过的电脑
  • 喷涂相关
  • 每日一溜
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

小刘说

砥砺前行
首页
  • 监控

    • grafana
    • prometheus
  • 学习笔记

    • 《核心系统命令实战》
    • 《MySQL 是怎样运行的:从根儿上理解 MySQL》
    • 《Ansible权威指南》
  • 博客搭建
  • git
  • python
  • 友情链接
  • 文档编写规范
  • 我用过的电脑
  • 喷涂相关
  • 每日一溜
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • zabbix

  • docker

  • kubernetes

    • 二进制安装高可用k8s集群(v1.25.0)
    • 二进制安装高可用k8s集群(v1.27.2)
    • kubernetes架构解析
    • kubernetes基础概念-Pod
    • kubernetes调度基础
    • kubernetes控制器-Deployment
      • 1. Deployment的工作原理
        • 1.1. 水平扩缩
        • 1.2. 滚动更新
      • 2. Deployment的更新
      • 3. Deployment的回滚
        • 3.1. 查看历史版本
        • 3.2. 回滚历史版本
        • 3.3. 修改历史版本数量限制
      • 4. Deployment的扩缩容&暂停和恢复
        • 4.1. Deployment的扩缩容
        • 4.2. Deployment的暂停和恢复
      • 5. 控制滚动更新速率
      • 6. 阻止错误版本的滚动更新
    • kubernetes控制器-Service
    • Kubernetes(k8s) YAML文件详解
  • harbor

  • mysql

  • nexus

  • jenkins

  • elasticsearch

  • 学习笔记

  • apache2.2升级2.4
  • heredoc(cat EOF)
  • Rocky linux 9 初始化
  • 运维
  • kubernetes
小刘
2023-08-08
目录

kubernetes控制器-Deployment

# kubernetes控制器-Deployment

学习Deployment之前,首先要清楚两个概念:

  • 无状态应用:任意一个Web请求端提出请求时,请求本身包含了响应端为响应这一请求所需的全部信息(认证信息等)。
  • 有状态应用:Web请求端的请求必须被提交到保存有其相关状态信息(比如session)的服务器上,否则这些请求可能无法被理解,这也就意味着在此模式下服务器端无法对用户请求进行自由调度。

分辨有无状态应用的关键点就在数据的存储位置,存储在客户端的就是无状态应用,存储在服务端的就是有状态应用。

而Deployment管理的就是无状态应用。kubernetes中也有针对有状态应用的控制器Statefulset,但本篇文章不进行讲解。

# 1. Deployment的工作原理

# 1.1. 水平扩缩

了解Deployment的工作原理之前,我们先新建一个Deployment,新建 Deployment.yml 如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx-deployment
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx-deployment
    spec:
      containers:
      - name: nginx-deployment
        image: nginx:latest
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

下面我们画一张图分析一下Deployment的结构:

Deployment

而从这个Deployment,我们能看出来,控制器的结构如图所示,由上半部分的控制器定义(包括期望状态),加上下半部分的被控制对象的模板(template)组成的。

创建这个Deployment,并查看Deployment的状态:

kubectl apply -f Deployment.yml
kubectl get deployments.apps
1
2

  • READY:当前已经可用的Pod的个数/用户期望的Pod副本个数(spec.replicas的值)。
  • UP-TO-DATE:当前处于最新版本的Pod的个数,所谓最新版本指的是Pod的Spec部分与Deployment里Pod模板里定义的完全一致。
  • AVAILABLE:当前已经可用的Pod的个数,即:既是Running状态,又是最新版本,并且已经处于Ready(健康检查正确)状态的Pod的个数。

而在所有API对象的Metadata里,都有一个字段叫作ownerReference,用于保存当前这个API对象的拥有者(Owner)的信息。

而Deployment实际操纵的是ReplicaSet。在创建完Deployment之后,Namespace中多出了一个ReplicaSet,这时,我们查看ReplicaSet的yaml中的ownerReference,就能找到依据:

kubectl get replicasets.apps -o yaml | grep ownerReference -A 10
1

Pod的的拥有者(Owner)是ReplicaSet,而ReplicaSet的拥有者(Owner)是Deployment。而三者之间的关系,实际上是一种“层层控制”的关系。

releations

而实现水平扩缩就简单了,Deployment通过控制ReplicaSet的副本数就能实现。

# 1.2. 滚动更新

我们也是先执行一次滚动更新,需要注意的是只有spec.template(Pod模板)更新时才会触发Deployment的更新。如更改CPU,镜像等等。

执行滚动更新有两种方式,可以更改yaml文件后使用 kubectl apply -f 进行更新,也可以使用 kubectl edit 进行编辑Deployment来更新。我们这里把nginx的版本号由 latest 改为 1.25.1:

    spec:
      containers:
      - name: nginx-deployment
        image: nginx:1.25.1
1
2
3
4

使用 kubectl apply -f 进行更新:

kubectl apply -f Deployment.yml
1

查看Deployment的Events来观察滚动更新的过程:

kubectl describe deployments.apps nginx-deployment
1

  1. Deployment创建一个新ReplicaSet、这个ReplicaSet叫 nginx-deployment-cb699c677,并且这个新ReplicaSet的初始Pod副本数是0。
  2. Deployment将旧ReplicaSet nginx-deployment-7c864f7c 由三个收缩为2个。并把新ReplicaSet nginx-deployment-cb699c677 扩展为1个。
  3. 新ReplicaSet和旧ReplicaSet分别进行水平扩容和水平收缩,直到新ReplicaSet的副本数为3,旧ReplicaSet的副本数为0,就完成了这次滚动更新。

查看集群内ReplicaSet的最终状态,也正如我们预想的那样,旧ReplicaSet已经水平收缩为0:

像这样,将一个集群中正在运行的多个Pod版本,交替地逐一升级的过程,就是“滚动更新”。

# 2. Deployment的更新

可以使用 edit 命令直接编辑Deployment进行更新:

kubectl edit deployments.apps/nginx-deployment
1

使用 rollout status 查看更新过程:

kubectl rollout status deployments.apps/nginx-deployment
1

当进行Deployment新建或者更新后,Deployment都会把 pod-template-hash 标签添加到 每个由Deployment控制的ReplicaSet上,确保每个ReplicaSet的唯一性。不要更改此标签

# 3. Deployment的回滚

当更新了版本不稳定或配置不合理时,可以对其进行回滚操作。默认情况下,Deployment 的所有上线记录都保留在系统中,以便可以随时回滚。

# 3.1. 查看历史版本

使用 rollout history 查看更新历史:

kubectl rollout history deployment/nginx-deployment
1

其中,CHANGE-CAUSE 的内容是从 Deployment 的 kubernetes.io/change-cause 注解复制过来的,可以通过以下方式设置:

  • 使用 kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to latest" 为 Deployment 添加注解。
  • 手动编辑Deployment文件进行更新。

查看更新历史的详细信息:

kubectl rollout history deployment/nginx-deployment --revision=2
1

# 3.2. 回滚历史版本

使用 rollout undo 从 revision 2 回滚到 revision 1 :

kubectl rollout undo deployment/nginx-deployment
1

也可以手动指定 revision :

kubectl rollout undo deployment/nginx-deployment --to-revision=2
1

# 3.3. 修改历史版本数量限制

默认情况下,revision 保留10个旧的ReplicaSet,其余的将在后台进行垃圾回收,可以在 .spec.revisionHistoryLimit 设置保留 ReplicaSet 的个数。当设置为0时,不保留历史记录,也就意味着无法进行历史版本回滚了。

# 4. Deployment的扩缩容&暂停和恢复

# 4.1. Deployment的扩缩容

使用 scale 进行Deployment的扩容,副本数为5:

kubectl scale deployment/nginx-deployment --replicas=5
1

# 4.2. Deployment的暂停和恢复

每次我们使用 edit 或者 set image 指令等等进行Deployment更新时,都会生成一个新的ReplicaSet对象,而通过暂停可以使我们对Deployment的多次更新操作的最终结果只生成一个ReplicaSet:

kubectl rollout pause deployment/nginx-deployment
1

暂停后可以任意修改,最后恢复Deployment:

kubectl rollout resume deployment/nginx-deployment
1

发现只有一个新的ReplicaSet生成,也就是通过暂停和恢复Deployment,只触发了一次“滚动更新”。

# 5. 控制滚动更新速率

在Deployment的滚动升级期间,有两个属性会决定一次替换多少个pod。可以通过Deployment的 strategy 字段下 rollingUpdate 的子属性来配置:

spec:
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
1
2
3
4
5
6
种类 说明
maxSurge 决定了Deployment在滚动更新的过程中最多允许超出的Pod实例的数量。默认值为25%,所以Pod实例最多可以比replicas数量多25%。如果replicas被设置为4,那么在滚动升级期间,不会运行超过5个Pod。值也可以设置为数字。
maxUnavailable 决定了Deployment在滚动更新的过程中最多允许有多少Pod处于不可用状态。默认值也是25%,所以可用 pod 实例的数量不能低于期望副本数的75%,百分数转换成绝对值时这个数字会四舍五入。如果replicas被设置为4,那么在滚动升级期间,只能有一个 pod 处于不可用状态。值也可以设置为数字。

# 6. 阻止错误版本的滚动更新

.spec.minReadySeconds 属性指定新创建的pod至少要成功运行多久之后,才能将其视为可用Pod(在容器的健康检查通过之后开始计算),默认值为0。

minReadySeconds 的主要功能是避免部署出错版本的应用,如果一个新的pod运行出错,并且在 minReadySeconds 时间内它的就绪探针出现了失败,那么新版本的滚动更新将被阻止。

参考文章及书籍:

  • Deployments (opens new window)

  • Kubernetes in Action (opens new window)

  • 深入剖析Kubernetes (opens new window)

  • 云原生Kubernetes全栈架构师实战 (opens new window)

上次更新: 2024/05/11, 03:55:33

← kubernetes调度基础 kubernetes控制器-Service→

最近更新
01
kubernetes控制器-Service
08-18
02
kubernetes调度基础
07-27
03
kubernetes基础概念-Pod
07-25
更多文章>
Theme by Vdoing | Copyright © 2023-2024 本站支持IPv6访问 本站支持SSL安全访问
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式