目录
一、Deployment 控制器:概念、原理解读
1.1 Deployment 概述
1.2 Deployment 工作原理:如何管理 rs 和 Pod?
补充:什么叫做更新节奏和更新逻辑呢?
二、Deployment 资源清单文件编写技巧
三、Deployment 使用案例:创建一个 web 站点
三、Deployment 实现 pod 扩缩容
3.1 通过 deployment 管理应用,实现扩容,把副本数变成 3
3.2 通过 deployment 管理应用,实现缩容,把副本数变成 2
四、通过 k8s 实现滚动更新
4.1 滚动更新简介
4.2 在 k8s 中实现金滚动更新
测试滚动更新
一、Deployment 控制器:概念、原理解读
1.1 Deployment 概述
Deployment 是 kubernetes 中最常用的资源对象,为 ReplicaSet 和 Pod 的创建提供了一种声明式的定义方法,在 Deployment 对象中描述一个期望的状态,Deployment 控制器就会按照一定的控制速率把实际状态改成期望状态,通过定义一个 Deployment 控制器会创建一个新的ReplicaSet 控制器,通过 ReplicaSet 创建 pod,删除 Deployment 控制器,也会删除 Deployment控制器下对应的 ReplicaSet 控制器和 pod 资源。
使用 Deployment 而不直接创建 ReplicaSet 是因为 Deployment 对象拥有许多 ReplicaSet 没有的特性,例如滚动升级、金丝雀发布、蓝绿部署和回滚。
扩展:声明式定义是指直接修改资源清单 yaml 文件,然后通过 kubectl apply -f 资源清单yaml 文件,就可以更改资源。
Deployment 控制器是建立在 rs 之上的一个控制器,可以管理多个 rs,每次更新镜像版本,都会生成一个新的 rs,把旧的 rs 替换掉,多个 rs 同时存在,但是只有一个 rs 运行。
rs v1 控制三个 pod,删除一个 pod,在 rs v2 上重新建立一个,依次类推,直到全部都是由rs v2 控制,如果rs v2有问题,还可以回滚,Deployment 是建构在rs之上的,多个 rs 组成一个Deployment,但是只有一个 rs 处于活跃状态.。
1.2 Deployment 工作原理:如何管理 rs 和 Pod?
Deployment 可以使用声明式定义,直接在命令行通过纯命令的方式完成对应资源版本的内容的修改,也就是通过打补丁的方式进行修改;Deployment 能提供滚动式自定义自控制的更新;对Deployment 来讲,我们在实现更新时还可以实现控制更新节奏和更新逻辑。
补充:什么叫做更新节奏和更新逻辑呢?
比如说 Deployment 控制 5 个 pod 副本,pod 的期望值是 5个,但是升级的时候需要额外多几个 pod,那我们控制器可以控制在 5个 pod 副本之外还能再增加几个 pod 副本;比方说能多一个,但是不能少,那么升级的时候就是先增加一个,再删除一个,增加一个删除一个,始终保持pod 副本数是 5个;还有一种情况,最多允许多一个,最少允许少一个,也就是最多 6个,最少 4个,第一次加一个,删除两个,第二次加两个,删除两个,依次类推,可以自己控制更新方式,这种滚动更新需要加 readinessProbe 和 livenessProbe 探测,确保 pod 中容器里的应用都正常启动了才删除之前的 pod。
启动第一步,刚更新第一批就暂停了也可以;假如目标是 5个,允许一个也不能少,允许最多可以 10个,那一次加 5个即可;这就是我们可以自己控制节奏来控制更新的方法。
通过 Deployment 对象,你可以轻松的做到以下事情:
- 创建 ReplicaSet 和 Pod
- 滚动升级(不停止旧服务的状态下升级)和回滚应用(将应用回滚到之前的版本)
- 平滑地扩容和缩容
- 暂停和继续 Deployment
二、Deployment 资源清单文件编写技巧
# 查看 Deployment 资源对象由哪几部分组成
[root@k8s-master01 ~]# kubectl explain deployment
KIND: Deployment
VERSION: apps/v1
DESCRIPTION:
Deployment enables declarative updates for Pods and ReplicaSets.
FIELDS:
apiVersion <string> # 该资源使用的 api 版本
kind <string> # 创建的资源是什么
metadata <Object> # 元数据,包括资源的名字和名称空间
spec <Object> # 定义容器的
status <Object> # 状态,不可以修改
# 查看 Deployment 下的 spec 字段
[root@k8s-master01 ~]# kubectl explain deployment.spec
KIND: Deployment
VERSION: apps/v1
RESOURCE: spec <Object>
DESCRIPTION:
Specification of the desired behavior of the Deployment.
DeploymentSpec is the specification of the desired behavior of the
Deployment.
FIELDS:
minReadySeconds <integer> # Kubernetes 在等待设置的时间后才进行升级;如果没有设置该值,Kubernetes 会假设该容器启动起来后就提供服务了
paused <boolean> # 暂停,当我们更新的时候创建 pod 先暂停,不是立即更新
Indicates that the deployment is paused.
progressDeadlineSeconds <integer>
# k8s 在升级过程中有可能由于各种原因升级卡住(这个时候还没有明确的升级失败),比如在拉取被墙的镜像,权限不够等错误。那么这个时候就需要有个 deadline ,在 deadline 之内如果还卡着,那么就上报这个情况,这个时候这个 Deployment 状态就被标记为 False,并且注明原因。但是它并不会阻止 Deployment 继续进行卡住后面的操作。完全由用户进行控制。
replicas <integer> # 副本数
revisionHistoryLimit <integer># 保留的历史版本,默认是10
selector <Object> -required- # 标签选择器,选择它关联的 pod
strategy <Object> # 更新策略
The deployment strategy to use to replace existing pods with new ones.
template <Object> -required- # 定义的 pod 模板
Template describes the pods that will be created.
# 查看 Deployment 下的 spec.strategy 字段
[root@k8s-master01 ~]# kubectl explain deployment.spec.strategy
KIND: Deployment
VERSION: apps/v1
RESOURCE: strategy <Object>
DESCRIPTION:
The deployment strategy to use to replace existing pods with new ones.
DeploymentStrategy describes how to replace existing pods with new ones.
FIELDS:
rollingUpdate <Object>
type <string>
Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
RollingUpdate.
Possible enum values:
- `"Recreate"` Kill all existing pods before creating new ones.
- `"RollingUpdate"` Replace the old ReplicaSets by new one using rolling
update i.e gradually scale down the old ReplicaSets and scale up the new
one.
# 支持两种更新,Recreate 和 RollingUpdate
# Recreate 是重建式更新,删除一个更新一个
# RollingUpdate 滚动更新,定义滚动更新方式,也就是 pod 能多几个,少几个
# 查看 Deployment 下的 spec.strategy.rollingUpdate 字段
[root@k8s-master01 ~]# kubectl explain deployment.spec.strategy.rollingUpdate
KIND: Deployment
VERSION: apps/v1
RESOURCE: rollingUpdate <Object>
DESCRIPTION:
Rolling update config params. Present only if DeploymentStrategyType =
RollingUpdate.
Spec to control the desired behavior of rolling update.
FIELDS:
maxSurge <string>
# 我们更新的过程当中最多允许超出的指定的目标副本数有几个;它有两种取值方式,第一种直接给定数量,第二种根据百分比,百分比表示原本是5个,最多可以超出20%,那就允许多一个,最多可以超过40%,那就允许多两个。
maxUnavailable <string>
# 最多允许几个不可用
# 假设有5个副本,最多一个不可用,就表示最少有4个可用
replicas: 5
maxSurge: 25% # 5*25%=1.25 -> 5+2=7;多的不管小数是多少,都加一
maxUnavailable: 25% # 5%25%=1.25 -> 5-1=4;少的不管小数是多少,都是整数位
# 查看 Deployment 下的 spec.template 字段
# template 为定义 Pod 的模板,Deployment 通过模板创建 Pod
[root@k8s-master01 ~]# kubectl explain deployment.spec.template
KIND: Deployment
VERSION: apps/v1
RESOURCE: template <Object>
DESCRIPTION:
Template describes the pods that will be created.
PodTemplateSpec describes the data a pod should have when created from a
template
FIELDS:
metadata <Object> # 定义模板的名字
spec <Object>
# deployment.spec.template 为 Pod 定义的模板,和 Pod 定义不太一样,template 中不包含apiVersion 和Kind 属性,要求必须有 metadata。deployment.spec.template.spec 为容器的属性信息,其他定义内容和 Pod 一致。
参考官方文档:Deployment | Kubernetes
三、Deployment 使用案例:创建一个 web 站点
deployment 是一个三级结构,deployment 管理 replicaset,replicaset 管理 pod。把 myapp-blue-v1.tar.gz 和 myapp-blue-v2.tar.gz 上传到 node1 和 node2 上,手动解压:
[root@k8s-node1 ~]# ctr -n=k8s.io images import myapp-blue-v1.tar.gz
[root@k8s-node1 ~]# ctr -n=k8s.io images import myapp-blue-v1.tar.gz
[root@k8s-node2 ~]# ctr -n=k8s.io images import myapp-blue-v1.tar.gz
[root@k8s-node2 ~]# ctr -n=k8s.io images import myapp-blue-v1.tar.gz
# 用 deployment 创建一个 pod
[root@k8s-master01 ~]# vim deploy-demo.yaml
apiVersion: apps/v1 # deployment对应的api版本
kind: Deployment # 创建的资源是 deployment
metadata:
name: myapp-v1 # deployment 的名字
spec:
replicas: 2 # deployment 管理的 pod 副本数
selector: # 标签选择器
matchLabels: # matchLabels下定义的标签需要跟 template.metadata.labels 定义的标签一致
app: myapp
version: v1
template:
metadata:
labels:
app: myapp
version: v1
spec: # 定义容器的属性
containers:
- name: myapp
image: janakiramm/myapp:v1 # 容器使用的镜像
imagePullPolicy: IfNotPresent # 镜像拉取策略
ports:
- containerPort: 80 # 容器里的应用的端口
startupProbe:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
livenessProbe:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
readinessProbe:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
# 更新资源清单文件:
[root@k8s-master01 ~]# kubectl apply -f deploy-demo.yaml
# 在 Deployment 中 kubectl apply:表示声明式的定义,既可以创建资源,也可以动态更新资源
# 查看 deploy 状态:
[root@k8s-master01 ~]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
myapp-v1 2/2 2 2 101s
# 查看 rs 状态:
# 创建的控制器名字是 myapp-v1-6bd64fd79
[root@k8s-master01 ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
myapp-v1-6bd64fd79 2 2 2 84s
# 创建 deploy 的时候也会创建一个 rs(replicaset),6bd64fd79 这个随机数字是我们引用 pod 的模板 template 的名字的 hash 值。
# 请注意,ReplicaSet 的名称始终设置为 [DEPLOYMENT-NAME]-[RANDOM-STRING]。RANDOM-STRING 是随机生成的。
[root@k8s-master01 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-v1-6bd64fd79-9mbg4 1/1 Running 0 84m 10.244.169.184 k8s-node2 <none> <none>
myapp-v1-6bd64fd79-qm469 1/1 Running 0 84m 10.244.36.106 k8s-node1 <none> <none>
- NAME :列出名称空间中 deployment 的名称。
- READY:显示 deployment 有多少副本数。它遵循 ready/desired 的模式。
- UP-TO-DATE: 显示已更新到所需状态的副本数。
- AVAILABLE: 显示你的可以使用多少个应用程序副本。
- AGE :显示应用程序已运行的时间。
- NAME: 列出名称空间中 ReplicaSet 资源名称
- DESIRED:显示应用程序的所需副本数,这些副本数是在创建时定义的。这是所需的状态。
- CURRENT: 显示当前正在运行多少个副本。
- READY: 显示你的用户可以使用多少个应用程序副本。
- AGE :显示应用程序已运行的时间。
# 请求刚才创建的pod资源,访问的服务内容都是一样的
[root@k8s-master01 ~]# curl 10.244.169.184
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sample Deployment</title>
<style>
body {
color: #ffffff;
background-color: blue;
font-family: Arial, sans-serif;
font-size: 14px;
}
······
[root@k8s-master01 ~]# curl 10.244.36.106
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sample Deployment</title>
<style>
body {
color: #ffffff;
background-color: blue;
font-family: Arial, sans-serif;
font-size: 14px;
}
·····
三、Deployment 实现 pod 扩缩容
3.1 通过 deployment 管理应用,实现扩容,把副本数变成 3
# 直接修改 replicas 数量,如下,变成 3
[root@k8s-master01 ~]# vim deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
spec:
replicas: 3
# 注意:apply 不同于 create,apply 可以执行多次;create 执行一次,再执行就会报错复。
[root@k8s-master01 ~]# kubectl apply -f deploy-demo.yaml
deployment.apps/myapp-v1 configured
# 可以看到 pod 副本数变成了 3 个
[root@k8s-master01 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-v1-6bd64fd79-7g96q 1/1 Running 0 55s 10.244.169.185 k8s-node2 <none> <none>
myapp-v1-6bd64fd79-9mbg4 1/1 Running 0 98m 10.244.169.184 k8s-node2 <none> <none>
myapp-v1-6bd64fd79-qm469 1/1 Running 0 98m 10.244.36.106 k8s-node1 <none> <none>
3.2 通过 deployment 管理应用,实现缩容,把副本数变成 2
# 直接修改 replicas 数量,如下,变成 2
[root@k8s-master01 ~]# vim deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
spec:
replicas: 2
······
[root@k8s-master01 ~]# kubectl apply -f deploy-demo.yaml
deployment.apps/myapp-v1 configured
[root@k8s-master01 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-v1-6bd64fd79-9mbg4 1/1 Running 0 106m 10.244.169.184 k8s-node2 <none> <none>
myapp-v1-6bd64fd79-qm469 1/1 Running 0 106m 10.244.36.106 k8s-node1 <none> <none>
四、通过 k8s 实现滚动更新
4.1 滚动更新简介
滚动更新是一种自动化程度较高的发布方式,用户体验比较平滑,是目前成熟型技术组织所采用的主流发布方式,一次滚动发布一般由若干个发布批次组成,每批的数量一般是可以配置的(可以通过发布模板定义),例如第一批1台,第二批10%,第三批50%,第四批100%。每个批次之间留观察间隔,通过手工验证或监控反馈确保没有问题再发下一批次,所以总体上滚动式发布过程是比较缓慢的。
4.2 在 k8s 中实现金滚动更新
# 首先看下 Deployment 资源对象的组成:
[root@k8s-master01 ~]# kubectl explain deployment.spec
KIND: Deployment
VERSION: apps/v1
RESOURCE: spec <Object>
DESCRIPTION:
Specification of the desired behavior of the Deployment.
DeploymentSpec is the specification of the desired behavior of the
Deployment.
FIELDS:
minReadySeconds <integer>
paused <boolean> # 暂停,当我们更新的时候创建 pod 是先暂停,不是立即更新
Indicates that the deployment is paused.
progressDeadlineSeconds <integer>
replicas <integer>
revisionHistoryLimit <integer> # 保留的历史版本数,默认是10个
The number of old ReplicaSets to retain to allow rollback. This is a
pointer to distinguish between explicit zero and not specified. Defaults to
10.
selector <Object> -required-
strategy <Object> # 更新策略,支持的滚动更新策略
The deployment strategy to use to replace existing pods with new ones.
template <Object> -required-
Template describes the pods that will be created.
[root@k8s-master01 ~]# kubectl explain deployment.spec.strategy
KIND: Deployment
VERSION: apps/v1
RESOURCE: strategy <Object>
DESCRIPTION:
The deployment strategy to use to replace existing pods with new ones.
DeploymentStrategy describes how to replace existing pods with new ones.
FIELDS:
rollingUpdate <Object>
Rolling update config params. Present only if DeploymentStrategyType =
RollingUpdate.
type <string>
Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
RollingUpdate.
Possible enum values:
- `"Recreate"` Kill all existing pods before creating new ones.
- `"RollingUpdate"` Replace the old ReplicaSets by new one using rolling
update i.e gradually scale down the old ReplicaSets and scale up the new
one.
# 支持两种更新,Recreate 和 RollingUpdate
# Recreate 是重建式更新,删除一个更新一个
# RollingUpdate 滚动更新,定义滚动更新的更新方式的,也就是 pod 能多几个,少几个,控制更新力度的
[root@k8s-master01 ~]# kubectl explain deployment.spec.strategy.rollingUpdate
KIND: Deployment
VERSION: apps/v1
RESOURCE: rollingUpdate <Object>
DESCRIPTION:
Rolling update config params. Present only if DeploymentStrategyType =
RollingUpdate.
Spec to control the desired behavior of rolling update.
FIELDS:
maxSurge <string>
#我们更新的过程当中最多允许超出的指定的目标副本数有几个。它有两种取值方式,第一种直接给定数量,第二种根据百分比,百分比表示原本是5个,最多可以超出20%,那就允许多一个,最多可以超过40%,那就允许多两个
maxUnavailable <string>
# 最多允许几个 pod 不可用。假设有5个副本,最多一个不可用,就表示最少有4个可用。
deployment 是一个三级结构,deployment 控制 replicaset,replicaset 控制 pod。
# 直接修改 replicas 数量,如下,变成 3
[root@k8s-master01 ~]# vim deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
spec:
replicas: 3
······
[root@k8s-master01 ~]# kubectl apply -f deploy-demo.yaml
# 可以看到 pod 副本数变成了 3 个
[root@k8s-master01 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-v1-6bd64fd79-9mbg4 1/1 Running 1 (29m ago) 20h
myapp-v1-6bd64fd79-qm469 1/1 Running 1 (29m ago) 20h
myapp-v1-6bd64fd79-s84p6 1/1 Running 0 43s
# 查看 myapp-v1 这个控制器的详细信息
[root@k8s-master01 ~]# kubectl describe deployment myapp-v1
Name: myapp-v1
Namespace: default
CreationTimestamp: Sat, 10 Dec 2022 18:09:22 +0800
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=myapp,version=v1
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
# 默认的更新策略rollingUpdate
StrategyType: RollingUpdate
MinReadySeconds: 0
# 最多允许多25%个 pod,25%表示不足一个,可以补一个
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=myapp
version=v1
······
测试滚动更新
# 更改镜像版本,按如下操作:
把 image: janakiramm/myapp:v1 变成 image: janakiramm/myapp:v2
spec:
containers:
- name: myapp
image: janakiramm/myapp:v2
imagePullPolicy: IfNotPresent
[root@k8s-master01 ~]# kubectl apply -f deploy-demo.yaml
deployment.apps/myapp-v1 configured
pending 表示正在进行调度,ContainerCreating 表示正在创建一个 pod,running 表示运行一个 pod,running 起来一个pod之后再 Terminating(停掉)一个 pod,以此类推,直到所有 pod完成滚动升级:
# 在另外一个窗口执行
[root@k8s-master01 ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
myapp-v1-59c458cb84 3 3 3 2m
myapp-v1-6bd64fd79 0 0 0 20h
# 上面可以看到 rs 有两个,下面那个是升级之前的,已经被停掉,但是可以随时回滚
# 查看 myapp-v1 这个控制器的滚动历史,显示如下
[root@k8s-master01 ~]# kubectl rollout history deployment myapp-v1
deployment.apps/myapp-v1
REVISION CHANGE-CAUSE
1 <none>
2 <none>
# 回滚到指定版本:
[root@k8s-master01 ~]# kubectl rollout undo deployment/myapp-v1 --to-revision=1 -n default
deployment.apps/myapp-v1 rolled back
版本回滚成功:
参考官方文档:Deployments | Kubernetes
上一篇文章:【云原生 | Kubernetes 实战】09、K8s 控制器 Replicaset 入门到企业实战应用_Stars.Sky的博客-CSDN博客
下一篇文章:【云原生 | Kubernetes 实战】10、K8s 控制器 Deployment 入门到企业实战应用(下)_Stars.Sky的博客-CSDN博客