【4】 Deployment深入简出&实战演练

发布于:2025-07-03 ⋅ 阅读:(13) ⋅ 点赞:(0)

文章目录

    • 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也发现正在更新。


网站公告

今日签到

点亮在社区的每一天
去签到