概述Deployment 基础创建 DeploymentReplicaSet滚动更新失败回滚历史版本回滚其他特性小结

概述

Deployment 是最常用的 Kubernetes 原生 Workload 资源之一,我们一开始尝试使用 Kubernetes 的时候大概率就是从运行一个 Deployment 类型的工作负载开始的。今天开始我们计划分成几讲来从 Deployment 的特性介绍、源码分析等方面深度剖析 Deployment 资源和其背后的 Deployment 控制器。

Deployment 的基础特性大家基本都熟悉,所以本文我们不计划赘述 Deployment 的所有功能细节,而是从滚动更新等不算太基础的特性入手,看下 Deployment 支持哪些玩法,为后面分析源码做准备。

Deployment 基础

我们创建一个简单的 Deployment,然后看下一些小细节。

创建 Deployment

以运行 nginx 为例,我们可以通过 Deployment 来拉起一个 3 副本的 nginx 负载:nginx-dp

  • nginx-dp.yaml
 1apiVersion: apps/v1
2kind: Deployment
3metadata:
4  name: nginx-dp
5  labels:
6    app: nginx
7spec:
8  replicas: 3
9  selector:
10    matchLabels:
11      app: nginx
12  template:
13    metadata:
14      labels:
15        app: nginx
16    spec:
17      containers:
18      - name: nginx
19        image: nginx:1.14.2
20        ports:
21        - containerPort: 80

通过 kubectl create -f nginx-dp.yaml 我们可以创建这个 Deployment 资源。

1# kubectl create -f nginx-dp.yaml
2deployment.apps/nginx-dp created
3# kubectl get deploy
4NAME       READY   UP-TO-DATE   AVAILABLE   AGE
5nginx-dp   1/3     3            1           3s
6# kubectl get deploy
7NAME       READY   UP-TO-DATE   AVAILABLE   AGE
8nginx-dp   3/3     3            3           10s

等一会,就可以通过 kubectl get deploy 命令看到所有 Pod 都起来了,这里关注下输出字段含义(NAME 和 AGE 就不用说了):

  • UP-TO-DATE:多少副本已经更新到期望状态了
  • AVAILABLE:多少副本已经可以提供服务了
  • READY:可以提供服务的副本数/期望副本数

ReplicaSet

  • 查询 ReplicaSet
1# kubectl get rs --selector=app=nginx
2NAME                  DESIRED   CURRENT   READY   AGE
3nginx-dp-66b6c48dd5   3         3         3       9m54s

前面创建了 Deployment 之后可以看到集群里多了一个 ReplicaSet 资源,也就是说 Deployment 管理的其实是 ReplicaSet 而不是直接管理 Pod,我们继续看下这个 ReplicaSet 的定义来验证下这个想法:

 1# kubectl get rs nginx-dp-66b6c48dd5 -o yaml
2apiVersion: apps/v1
3kind: ReplicaSet
4// ……
5  ownerReferences:
6  - apiVersion: apps/v1
7    blockOwnerDeletion: true
8    controller: true
9    kind: Deployment
10    name: nginx-dp
11    uid: 97736b65-0171-4916-bb18-feccc343ac14
12  resourceVersion: "1099157"
13  uid: 83ac5660-28eb-4d40-beb1-cb5ceb6928b6
14// ……

这里可以看到这个 ReplicaSet 属于 Deployment 类型的 nginx-dp 资源。同样的方法可以看到对应 Pod 是属于 ReplicaSet 管理的。

到这里,我们可以猜下 Deployment Controller 的实现原理,大概可以想到其通过管理 ReplicaSet 的生命周期,借助 ReplicaSet Controller 提供的能力间接完成了 Pod 生命周期的管理;另外可以通过创建多个 ReplicaSet 资源,控制其副本数来实现滚动更新和回滚等操作。这样 Deployment Controller 的实现逻辑就相对“高层”了。

滚动更新

  • 通过 kubectl set 命令来更新镜像:
1# kubectl set image deployment/nginx-dp nginx=nginx:1.16.1
2deployment.apps/nginx-dp image updated
  • 查看 Event
 1# kubectl describe deploy nginx-dp
2// ……
3
4Events:
5  Type    Reason             Age   From                   Message
6  ----    ------             ----  ----                   -------
7  Normal  ScalingReplicaSet  26m   deployment-controller  Scaled up replica set nginx-dp-66b6c48dd5 to 3
8  Normal  ScalingReplicaSet  88s   deployment-controller  Scaled up replica set nginx-dp-559d658b74 to 1
9  Normal  ScalingReplicaSet  87s   deployment-controller  Scaled down replica set nginx-dp-66b6c48dd5 to 2
10  Normal  ScalingReplicaSet  87s   deployment-controller  Scaled up replica set nginx-dp-559d658b74 to 2
11  Normal  ScalingReplicaSet  86s   deployment-controller  Scaled down replica set nginx-dp-66b6c48dd5 to 1
12  Normal  ScalingReplicaSet  86s   deployment-controller  Scaled up replica set nginx-dp-559d658b74 to 3
13  Normal  ScalingReplicaSet  84s   deployment-controller  Scaled down replica set nginx-dp-66b6c48dd5 to 0

从 Event 里可以看到 deployment-controller 通过调整 ReplicaSet 资源 nginx-dp-66b6c48dd5 和 nginx-dp-559d658b74 的副本数完成了这次滚动更新,先看下这两个 ReplicaSet:

1# kubectl get rs --selector=app=nginx
2NAME                  DESIRED   CURRENT   READY   AGE
3nginx-dp-559d658b74   3         3         3       134m
4nginx-dp-66b6c48dd5   0         0         0       159m

可以看到这时候新增了一个 nginx-dp-559d658b74,副本数是 3,同时老的 nginx-dp-66b6c48dd5 变成了 0 副本。这个过程大概是这样:

  1. nginx-dp-66b6c48dd5 to 3 / replica set nginx-dp-559d658b74 to 1 -> 新 rs 增加一个副本到 1;合计 4 副本
  2. Scaled down replica set nginx-dp-66b6c48dd5 to 2 -> 老 rs 减少一个副本到 2;合计 3 副本
  3. Scaled up replica set nginx-dp-559d658b74 to 2 -> 新 rs 增加一个副本到 2;合计 4 副本
  4. Scaled down replica set nginx-dp-66b6c48dd5 to 1 -> 老 rs 减少一个副本到 1;合计 3 副本
  5. Scaled up replica set nginx-dp-559d658b74 to 3 -> 新 rs 增加一个副本到 3;合计 4 副本
  6. Scaled down replica set nginx-dp-66b6c48dd5 to 0 -> 老 rs 减少一个副本到 0;合计 3 副本

失败回滚

历史版本

先看下怎么查询更新历史:

1# kubectl rollout history deployments/nginx-dp
2deployment.apps/nginx-dp
3REVISION  CHANGE-CAUSE
41         <none>
52         <none>

这里可以看到一个细节,CHANGE-CAUSE 是空的,这个字段其实是从 kubernetes.io/change-cause 注解中拿的,我们加个注解试一下:

1kubectl annotate deployment/nginx-dp kubernetes.io/change-cause="image updated to 1.16.1"

再查一次:

1# kubectl rollout history deployments/nginx-dp
2deployment.apps/nginx-dp
3REVISION  CHANGE-CAUSE
41         <none>
52         image updated to 1.16.1

第一个版本怎么办呢?这里大概可以猜到要存储多个版本的 CHANGE-CAUSE 信息,这个注解应该是用的 ReplicaSet 里的,所以我们尝试这样补充第一个版本的注解:

1kubectl annotate rs/nginx-dp-66b6c48dd5 kubernetes.io/change-cause="nginx deployment created"

再查一次:

1# kubectl rollout history deployments/nginx-dp
2deployment.apps/nginx-dp
3REVISION  CHANGE-CAUSE
41         nginx deployment created
52         image updated to 1.16.1

现在就比较和谐了,需要指定版本回滚的时候不迷路。

回滚

  • 设置一个不存在的镜像版本来模拟更新失败场景:
 1# kubectl set image deployment/nginx-dp nginx=nginx:1.161
2deployment.apps/nginx-dp image updated
3# kubectl get rs --selector=app=nginx
4NAME                  DESIRED   CURRENT   READY   AGE
5nginx-dp-559d658b74   3         3         3       168m
6nginx-dp-66b6c48dd5   0         0         0       3h13m
7nginx-dp-66bc5d6c8    1         1         0       6s
8# kubectl get pod --selector=app=nginx
9NAME                        READY   STATUS             RESTARTS   AGE
10nginx-dp-559d658b74-l4bq7   1/1     Running            0          170m
11nginx-dp-559d658b74-qhh8m   1/1     Running            0          170m
12nginx-dp-559d658b74-vbtl5   1/1     Running            0          170m
13nginx-dp-66bc5d6c8-tl848    0/1     ImagePullBackOff   0          2m2s
  • 设置个注解:
1# kubectl annotate deployment/nginx-dp kubernetes.io/change-cause="image updated to 1.161"
2deployment.apps/nginx-dp annotated
3# kubectl rollout history deployments/nginx-dp
4deployment.apps/nginx-dp
5REVISION  CHANGE-CAUSE
61         nginx deployment created
72         image updated to 1.16.1
83         image updated to 1.161
  • 回滚到 revision 2:
1# kubectl rollout undo deployment/nginx-dp
2deployment.apps/nginx-dp rolled back
3# kubectl rollout history deployments/nginx-dp
4deployment.apps/nginx-dp
5REVISION  CHANGE-CAUSE
61         nginx deployment created
73         image updated to 1.161
84         image updated to 1.16.1

这时候版本 2 变成了最新的版本:4

  • 查看某个版本的详细配置:
 1# kubectl rollout history deployments/nginx-dp --revision=1
2deployment.apps/nginx-dp with revision #1
3Pod Template:
4  Labels:    app=nginx
5    pod-template-hash=66b6c48dd5
6  Annotations:    kubernetes.io/change-cause: nginx deployment created
7  Containers:
8   nginx:
9    Image:    nginx:1.14.2
10    Port:    80/TCP
11    Host Port:    0/TCP
12    Environment:    <none>
13    Mounts:    <none>
14  Volumes:    <none>
  • 指定版本回滚:
1# kubectl rollout undo deployment/nginx-dp --to-revision=1
2deployment.apps/nginx-dp rolled back
3# kubectl rollout history deployments/nginx-dp
4deployment.apps/nginx-dp
5REVISION  CHANGE-CAUSE
63         image updated to 1.161
74         image updated to 1.16.1
85         nginx deployment created

其他特性

最后我们看下 Deployment 类型 spec 的全部属性:

  • minReadySeconds:默认值为 0,表示一个 pod reday 之后多长时间可以提供服务;换句话说配置成1就是 pod ready 之后 1s 才对外提供服务;
  • paused:挂起;
  • progressDeadlineSeconds:默认 600,表示处理一个 Deployment 任务的超时时间,比如 10 分钟到了还没有升级成功,则标记为 failed 状态;
  • replicas:副本数;
  • revisionHistoryLimit:默认是 10,表示保留的历史版本数量;
  • selector:标签选择器;
  • strategy:表示 Deployment 更新 pod 时的替换策略;
  • template:Pod 模板;

这里的 strategy 有两个属性,分别是:typerollingUpdate。type 可选值是:"Recreate" 和 "RollingUpdate",默认为 "RollingUpdate"。strategy.rollingUpdate 有两个属性:

  • maxSurge: 表示滚动更新的时候最多可以比期望副本数多几个,数字或者百分比配置都行;比如 1 表示更新过程中最多同时新增 1 个副本,然后等一个老副本删掉之后才能继续增加 1 个新副本;百分比计算的时候向上取整;
  • maxUnavailable:表示滚动更新的时候可以有多少副本不可用,同样是数字或者百分比配置;比如期望副本数是 3,1 则表示最多删除副本到剩下 2,然后要等新副本创建才能继续删除;百分比计算的时候向下取整;

小结

本文我们的目的是知道 Deployment 的全部特性,进而为后面的源码分析做准备。在这个过程中我们没有赘述 Deployment 的基础特性,而是主要介绍“滚动更新”和“回滚”等主要功能,另外简单过一下 Deployment 的 spec 包含的全量配置项,从而心中有个概念,知道 Deployment 的能力边界在那里,从而后面看源码时更有针对性。

(转载请保留本文原始链接 https://www.danielhu.cn)

Kubernetes Deployment 源码分析(一)的更多相关文章

  1. Kubernetes Deployment 源码分析(二)

    概述startDeploymentController 入口逻辑DeploymentController 对象DeploymentController 类型定义DeploymentController ...

  2. Kubernetes client-go 源码分析 - Reflector

    概述入口 - Reflector.Run()核心 - Reflector.ListAndWatch()Reflector.watchHandler()NewReflector()小结 概述 源码版本: ...

  3. client-go客户端自定义开发Kubernetes及源码分析

    介绍 client-go 是一种能够与 Kubernetes 集群通信的客户端,通过它可以对 Kubernetes 集群中各资源类型进行 CRUD 操作,它有三大 client 类,分别为:Clien ...

  4. Kubernetes client-go 源码分析 - ListWatcher

    概述ListWatch 对象的创建GetterListWatchList() & Watch() 概述 源码版本信息 Project: kubernetes Branch: master La ...

  5. Kubernetes client-go Informer 源码分析

    概述ControllerController 的初始化Controller 的启动processLoopHandleDeltas()SharedIndexInformersharedIndexerIn ...

  6. Kubernetes client-go workqueue 源码分析

    概述Queue接口和结构体setAdd()Get()Done()DelayingQueue接口和结构体waitForNewDelayingQueuewaitingLoop()AddAfter()Rat ...

  7. Kubernetes client-go DeltaFIFO 源码分析

    概述Queue 接口DeltaFIFO元素增删改 - queueActionLocked()Pop()Replace() 概述 源码版本信息 Project: kubernetes Branch: m ...

  8. kubernetes垃圾回收器GarbageCollector Controller源码分析(二)

    kubernetes版本:1.13.2 接上一节:kubernetes垃圾回收器GarbageCollector Controller源码分析(一) 主要步骤 GarbageCollector Con ...

  9. Kubernetes client-go Indexer / ThreadSafeStore 源码分析

    Kubernetes client-go Indexer / ThreadSafeStore 源码分析   请阅读原文:原文地址   Contents 概述 Indexer 接口 ThreadSafe ...

随机推荐

  1. minix3使用轻快入门

    minix3是一款迷你的unix作业系统,但又不在at&t代码的基础上构建.当年开发这款作业系统的作者仅仅是拿来自用,给学生上课使用的. 如果你已经安装了minix3,你还需要安装openss ...

  2. openldap集成ssh 登录

    一 安装nslcd服务 yum install nss-pam-ldapd 二.修改vi /etc/nslcd.conf这个配置文件 修改uri 和base的值 改为你的ldap的地址和用户名 三.  ...

  3. JScript.net

    参考网址一.JScript帮助指南 http://doc.51windows.net/jscript5/?url=/jscript5/dir.htm 参考网址二.以下网址列出的类,可以尝试一下,会有意 ...

  4. 用Python基本库实现进度条

    用Python基本库实现进度条效果几个要点:1. \r,重置光标2. time.perf_counter,计算运行时间3. 用format控制输出格式 1 #progress bar2 2 #The ...

  5. 鸿蒙内核源码分析(定时器篇) | 哪个任务的优先级最高 | 百篇博客分析OpenHarmony源码 | v31.02

    百篇博客系列篇.本篇为: v31.xx 鸿蒙内核源码分析(定时器篇) | 哪个任务的优先级最高 | 51.c.h .o 本篇说清楚定时器的实现 读本篇之前建议先读鸿蒙内核源码分析(总目录)其余篇. 运 ...

  6. UVa/数组与字符串习题集

    UVa-272. Description: TEX is a typesetting language developed by Donald Knuth. It takes source text ...

  7. 实验2:Open vSwitch虚拟交换机实践

    作业链接:实验2:Open vSwitch虚拟交换机实践 一.实验目的 能够对Open vSwitch进行基本操作: 能够通过命令行终端使用OVS命令操作Open vSwitch交换机,管理流表: 能 ...

  8. WebXml文件与SpringMVC的联系

    WebXml文件与SpringMVC的联系 无论采用何种框架来进行Java Web的开发,只要是Web项目必须在WEB-INF下有web.xml,这是java规范. 当然,我们最早接触到Java We ...

  9. 无服务计算应用场景探讨及 FaaS 应用实战

    作者 | 宋文龙(闻可)  阿里云全球技术服务部高级交付专家 什么是无服务计算 无服务器计算(Serverless Computing)在构建和运行应用时无需管理服务器等基础设施.它描述了一个细粒度的 ...

  10. ShardingSphere 知识库更新 | 官方样例集助你快速上手

    Apache ShardingSphere 作为 Apache 顶级项目,是数据库领域最受欢迎的开源项目之一.经过 5 年多的发展,ShardingSphere 已获得超 14K Stars 的关注, ...