文章目录
-
- Deployment是什么
- ReplicaSet
- Deployment实战
-
- Deployment清单文件
- 重点解释(!!!重点!!!)
- 部署第一个**Deployment**
- 测试滚动更新
- 测试回滚
-
- `!!!重要提示!!!`
Deployment是什么
✅也许你的期望状态是10个Pod副本,但是只有8个在运行——这时Kubernetes会发出红色警告,然后命令控制层进入“应急状态”,并再启动两个副本。最棒的一点在于——它会默默完成这一切,而不是在凌晨4:20叫醒你!这就是Deployment帮你做的事。
看起来很不错
所以,k8s引入了Deployment这个组件,它可以自动实现pod的
自愈
,扩缩容
,滚动更新
,升级回滚
等诸多操作,所以,Deployment绝对是k8s的大杀器。
自愈:某pod出现故障,Deployment会将其直接替换掉
扩缩容:可以丝滑的改变pod的数量
滚动更新:0停机小批量多次的滚动式更新pod,无感更新(多pod时)
升级回滚:回滚到历史版本,就这么简单(在更新版本时旧版本信息其实是保存了,用于回滚)
关于滚动更新的详细解读: 假设现在有10个pod,现在你发现pod中运行的服务有bug,于是你提交了修复版容器镜像,这时候你只需要在Deployment的yaml清单文件(和pod清单文件一样,用来创建Deployment资源的文件)中修改镜像名称与版本就行,这时候底层就会减少一部分pod,然后新建等量新版本pod,重复几次所有pod才会全部更新最新版本,这就是滚动更新。这样就不会因为一次性更新服务带来服务空窗期。
ReplicaSet
说到Deployment就不得不说ReplicaSet了,他们的关系更像是上下级的关系,Deployment是ReplicaSet的上级,总体来说,Deployment使用ReplicaSet来提供自愈和扩缩容能力,虽然并不建议直接操作ReplicaSet,不过了解其关系是比较重要的。
需要说明的是,虽然某些功能是由ReplicaSet在底层完成的,但是我们要想完成这些操作还是只需要与Deployment打交道即可,它会自动调用ReplicaSet的
Deployment实战
Deployment清单文件
apiVersion: apps/v1 # 部署对象的版本
kind: Deployment # 声明这个资源类型为Pod类型
metadata:
name: hello-deploy111 # Deployment对象名字
spec:
replicas: 10 # Deployment要保持10个pod数量存在
selector:
matchLabels: # 要管理的Pod所必须具备的标签
app: hello-zxnbmk # 具备标签的具体键值对
minReadySeconds: 10 # 每个Pod的在更新时需要间隔10s(避免一次性更新太快失误来不及挽救)
strategy:
type: RollingUpdate # 一种更新策略(默认即可)
rollingUpdate:
maxUnavailable: 1 #不允许出现比期望状态指定的Pod数量少超过一个的情况(下面重点解释)
maxSurge: 1 #不允许出现比期望状态指定的Pod数量多超过一个的情况(下面重点解释)
template:
metadata: # 好了,这里就又到了定义Pod末班的时候了
labels:
app: hello-zxnbmk # Pod的标签,只要和上面matchLabels的标签一样,创建的Pod就能被这个Deployment管理了
spec: #ok,下面就是Pod中容器的详情了
containers:
- name: hello-pod #容器名字
image: nigelpoulton/k8sbook:latest # 使用的Docker镜像名字与版本
ports:
- containerPort: 8080 # 声明这个容器的服务在8080端口(需要与容器中服务实际监听端口一致)
重点解释(!!!重点!!!)
关于清单文件: 首先我们看见Deployment的清单文件不仅说明了自己,还列出了Pod,容器的具体期望状态,这是因为Deployment就是用来管理Pod的,而Pod就是运行我们容器来提供服务的,所以一般我们创建Deployment的时候就会包含Pod和容器的期望状态。而有了这些期望状态,k8s就知道应该创建一些什么样的Pod,用什么容器镜像等等。
关于rollingUpdate: 这个元素下面有maxUnavailable和maxSurge,看上面的解释似乎很迷,我来举个例子,加入你现在有10个Pod,现在maxUnavailable和maxSurg都是1,那么意思就是你在更新的时候,Pod总数最多11个,最少9个,(因为我们在更新的时候需要删除旧Pod,新建新Pod)也就是10个旧Pod,你只能先删除一个旧Pod(现在总数9),然后新建2个新Pod(现在总数11个)这样更新,依据规则重复即可。
关于containerPort: 这里我一直强调需要与容器中服务实际监听端口一致,也就是说,这个端口并不影响容器自己里面服务的端口,你要是写错了,容器端口依然监听容器镜像设计者设计的端口,长话短说这个值就是让Deployment创建Pod的时候让Pod能够告诉别人他里面的容器监听的端口是多少。所以,containerPort的值原则上是你进容器查看里面服务监听端口情况得到的。
部署第一个Deployment
上面我们已经获得了一个清单文件,我将它命名为deployment.yml
下面使用kubectl apply -f deployment.yml
来将这个清单文件POST到API-server。
接下来我们使用下面的命令查看清单文件里面出现的deployment是否已经成功创建
kubectl get deployments.apps -o wide
命令解释:
get
不用解释,我们在集群中无论查看那种资源(Pod,svc,deployment……),都是使用get命令(英文翻译为获得获取,顾名思义),后面紧跟你要查看的资源类型,比如pod,deployments(deployments.apps也是可以的),-o
是指输出格式控制,wide
指的是输出格式(它是一种扩展输出格式旨在展示更多数据,你也可以替换为yaml则展示为yaml格式,当然还有json格式)话好像有点密,不说了🤔
这里可以看见名叫hello-deploy111的deployment已经被创建,总共10个Pod,READY了10个Pod,里面的容器叫hello-pod,使用的镜像是nigelpoulton/k8sbook:latest
继续查看Pod详情
kubectl get pods -o wide
这里可以看见确实是10个Pod,已经全部Running了,在NODE列我们可以发现,已经自动分配到不同节点上了,仔细的你可能还会发现刚好是五五分,稍稍解释一下,其实是k8s中kube-scheduler
负责将新创建的 Pod 调度到合适的工作节点上,依据就是每个Pod的资源和负载情况。这里两台node是我复制的,他们的情况应该是基本一致,所以才会五五分,如果两台机器的状况不太一样,可能分配的数量也会有差距。
测试滚动更新
我们说过,使用deployment创建的Pod可以支持滚动更新,只需要修改yaml文件就可以了,那么我们把容器镜像修改一下,再使用kubectl apply命令POST一下。
可以看见,我们将原来的镜像注释了,换成nginx:1.22.1的镜像,退出并保存后继续使用
kubectl apply -f deployment.yml
更新Pod
可以看到,这时候我们查看deployment时,IMAGES已经变成nginx:1.22.1了,说明已经成功切换了镜像。但是你发现了吗,READY变成11/10了,这就是新旧Pod正在滚动更新了,我们可以脑补一下,旧Pod原来是10个,现在删除一个旧的(保持不少于9个,不懂的话可以看Deployment清单文件
下面的重点解释
,早说过是重点了👀),然后添加两个新Pod(保证不多于11个,不懂回去看重点解释👀),所以这就是11/10的由来。
继续查看Pod验证:
首先解释一下
Terminating
意为终结,意思就是这个Pod已经终结了,只是还没清理出去,除去两个终结Pod,可以看见刚好11个。ContainerCreating
翻译过来为“创建容器”,没错这个状态就代表这个容器正在创建,不难看出这就是其中一个新容器。😎偷偷告诉你,其实看AGE列就能看出来谁是新创建的了,有两个2s的,这就是Pod的生存时间,2s肯定是最新的,上面我们推测一个旧Pod被删除,两个新Pod被建立,果然是这样的吧。
等待一段时间继续查看,可以发现已经完全更新好了:
- 那么这里自愈扩缩容等旧不再演示了,更改yaml中的Pod数量与杀死一定数量的Pod即可(最简单的方法是将node1节点直接关机)
测试回滚
要想回滚,那旧必须要有历史版本,我们现在使用的是nginx:1.22.1的镜像,现在将nginx:1.22.1的镜像注释,放出nigelpoulton/k8sbook:latest镜像。如下图:
现在重新加载yaml并创建一个历史版本
kubectl apply -f deployment.yml --record
注意,其实我们使用kubectl apply -f 更新的时候也会被记录版本,但是–record会将当时更新的命令也记录了,否则你可能在多个版本中"迷路"。可以看下图区别
!!!重要提示!!!
上图可以使用了
kubectl rollout history deployment/hello-deploy111 -n default
命令查看了历史版本,其中4就是刚刚更新开启–record的版本,可以看见已经记录了命令,3是之前的版本,没有任何记录,4就是现在运行的版本
,由于我们在生产环境如果要更新yaml,坑定是新建yaml文件,保留下旧yaml留档备用,所以文件名不一样,–record记录的命令就不一样了,这样就能快速区分版本区别。命令解释:
deployment/hello-deploy111这个参数就是为了更精确找到
hello-deploy111
这个资源,如果你创建了很多Deployment的时候很好用,-n即选择namespace 这里选择的是default(默认空间)。由于我们yaml没有定义任何namespace ,所以创建资源会默认放在default,(😀前面的kubectl get,kubectl apply,kubectl rollout等命令都应该加上-n 因为我们的资源放在默认命名空间,所以不加也可以查询到,如果在其他空间,不加-n 指定命名空间的话,很可能会出现找不到资源的情况)
kubectl rollout undo deployment hello-deploy111 --to-revision=3
上面就是回滚命令,可以看见回滚到版本3,也就是我们注释nginx:1.22.1的镜像之前的版本,下面展示实操:
可以看见回滚之前的镜像还是nigelpoulton/k8sbook:latest,回滚后成功回到nginx:1.22.1,查看Pod也发现正在更新。