一文吃透 K8s Deployment:资源创建、扩缩容与节点自愈实战 📅 2026/7/15 6:28:17 前言Kubernetes简称 K8s作为当前容器编排领域的事实标准其核心能力之一就是通过多种控制器Controller来管理应用的生命周期。在实际生产环境中我们很少直接操作 Pod —— 因为 Pod 本身不具备自愈、扩缩容、滚动更新等能力。为此Kubernetes 提供了 Deployment、ReplicaSet、DaemonSet、StatefulSet、Job 等一系列更高层次的对象其中Deployment是最常用、也最基础的工作负载控制器。无论是部署一个简单的 Web 服务还是维护一个复杂的微服务集群Deployment 都能帮助我们轻松实现声明式管理你只需要告诉 Kubernetes “我想要运行 3 个实例使用 httpd 镜像”它就会自动创建所需的 ReplicaSet 和 Pod并确保实际状态始终与期望状态一致。此外Deployment 还天然支持滚动更新、版本回滚、副本扩缩容、节点故障自动迁移等高级功能。本文将从 Deployment 的基本概念出发结合实际的命令行输出和 YAML 配置文件逐步分析 Deployment 的执行流程、创建资源的方式、配置文件编写方法、在线扩缩容操作、节点故障时的自动切换以及如何通过 Label 控制 Pod 的调度位置。文章内容基于 Kubernetes v1.18.6 环境所有示例均来自真实操作记录。希望通过这篇详解能帮助读者从原理到实践全面掌握 Deployment 的使用。一、Deployment介绍1. Deployment的概念为了满足不同业务场景Kubernetes 开发了 Deployment、ReplicaSet、DaemonSet、StatefulSet、Job 等多种 Controller。其中Deployment是最常用的一种。Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义declarative方法用来替代以前的 Replication Controller从而更方便地管理应用。作为最常用的 Kubernetes 对象Deployment 经常被用来创建 ReplicaSet 和 Pod。我们通常不会直接在集群中使用 ReplicaSet 部署微服务因为 ReplicaSet 功能不够强大缺乏更新、扩缩容等常见运维操作。Deployment 的引入正是为了支持这些复杂操作。2. Deployment执行状态分析查看 Deployment 的状态可以使用以下命令[rootmaster k8s]# kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE http-deployment 3/3 3 3 160m可以看到集群中有一个名为http-deployment的 Deployment它有三个副本且全部正常运行。要查看某个 Deployment 的详细信息可以执行[rootmaster k8s]# kubectl describe deployment http-deployment从输出中发现存在一个 ReplicaSethttp-deployment-749876cdf4这说明 Deployment 是通过 ReplicaSet 来管理 Pod 的。接着查看 ReplicaSet 的状态[rootmaster k8s]# kubectl get replicaset http-deployment-749876cdf4使用kubectl describe replicaset可以查看更详细的信息[rootmaster ~]# kubectl describe replicaset Name: http-deployment-749876cdf4 Namespace: default Selector: apphttp_server, pod-template-hash749876cdf4 Labels: apphttp_server pod-template-hash749876cdf4 Annotations: deployment.kubernetes.io/desired-replicas: 3 deployment.kubernetes.io/max-replicas: 4 deployment.kubernetes.io/revision: 1 Controlled By: Deployment/http-deployment Replicas: 3 current / 3 desired Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed Pod Template: Labels: apphttp_server pod-template-hash749876cdf4 Containers: http-web: Image: httpd Port: none Host Port: none Environment: none Mounts: none Volumes: none Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulCreate 51m replicaset-controller Created pod: http-deployment-749876cdf4-vlfrp Normal SuccessfulCreate 51m replicaset-controller Created pod: http-deployment-749876cdf4-k2xSt Normal SuccessfulCreate 51m replicaset-controller Created pod: http-deployment-749876cdf4-kq9dt输出中的Controlled By指明该 ReplicaSet 是由 Deploymenthttp-deployment创建的。Events 部分记录了三个副本 Pod 的创建过程。然后查看 Pod 的状态[rootmaster k8s]# kubectl get pod NAME READY STATUS RESTARTS AGE http-deployment-749876cdf4-k2x5t 1/1 Running 0 101s http-deployment-749876cdf4-kq9dt 1/1 Running 0 101s http-deployment-749876cdf4-vlfrp 1/1 Running 0 101s可以看到三个副本 Pod 都处于 Running 状态。使用kubectl describe pod查看更详细的信息Controlled By: ReplicaSet/http-deployment-749876cdf4 Containers: http-web: Container ID: docker://3043f79fa114... Image: httpd Image ID: docker-pullable://httpdsha256:2a9ae199b5... State: Running Started: Fri, 24 Jul 2020 16:53:17 0800 Ready: True Restart Count: 0 Environment: none ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled unknown default-scheduler Successfully assigned default/http-deployment-749876cdf4-89c29 to node2 Normal Pulling 67s kubelet, node2 Pulling image httpd Normal Pulled 52s kubelet, node2 Successfully pulled image httpd Normal Created 52s kubelet, node2 Created container http-web Normal Started 52s kubelet, node2 Started container http-web输出中Controlled By指明此 Pod 是由 ReplicaSethttp-deployment-749876cdf4创建。最后的 Events 记录了 Pod 的启动过程。如果操作失败比如镜像不存在也可以从这里查看到失败原因。3. Deployment执行流程总结Deployment 的实现过程可以总结为以下几步用户通过kubectl创建 Deployment。Deployment 创建 ReplicaSet。ReplicaSet 创建 Pod。Pod 在每个节点上通过 kubelet 调用容器运行时如 docker完成容器创建。对象的命名方式为子对象的名字 父对象名字 随机字符串或数字。二、K8s中创建资源的方式1. 基于命令的方式优点简单直观快捷上手快。适用场景适合临时测试或实验。2. 基于配置文件的方式优点资源的属性写在 YAML 配置文件中描述了最终要达到的状态。配置文件提供了创建资源的模板能够重复部署可以像管理代码一样管理部署。适用场景适合正式的、跨环境、规模化部署。注意这种方式要求熟悉配置文件的语法有一定难度。后续我们主要采用这种方式需要尽快熟悉和掌握。3. 用 kubectl 命令直接创建资源已部分废弃[rootmaster k8s]# kubectl run nginx-deployment --imagenginx --port80 [rootmaster k8s]# kubectl get pod nginx-deployment 1/1 Running 0 31s从 Kubernetes 1.18 版本开始已经不支持在命令行中通过参数指定资源的属性例如--replicas参数已弃用推荐使用 Deployment 配置文件方式创建 Pod。4. 通过配置文件和kubectl apply创建资源[rootmaster k8s]# more http.yml apiVersion: apps/v1 kind: Deployment metadata: name: http-deployment spec: replicas: 3 selector: matchLabels: app: http_server template: metadata: labels: app: http_server spec: containers: - name: http-web image: httpdkubectl apply不仅可以创建 Kubernetes 资源还能对资源进行更新非常方便。虽然 Kubernetes 还提供了kubectl create、kubectl replace、kubectl edit和kubectl patch等命令但kubectl apply已经能够应对超过 90% 的场景。三、通过 YAML 文件编写 Deployment 配置Deployment 的配置格式详解以http.yml为例进行说明字段说明apiVersion当前配置格式的版本。可以通过kubectl api-resources找到所有资源再用kubectl explain deploy获取版本和类型信息。kind要创建的资源类型这里是Deployment。metadata该资源的元数据name是必需的可任意指定。spec第一层Deployment 的规格说明。replicas副本数量默认为 1这里指定为 3。selector选择器matchLabels用于匹配标签。发布 Service 时selector需要与此处对应。template定义 Pod 的模板是配置文件的重点部分。template.metadata定义 Pod 的元数据至少要定义一个labelkey/value 可任意指定。template.spec描述 Pod 的规格定义 Pod 中每个容器的属性name和image是必需的。注意containers后面是一个列表所以每项前面需要加一个短横线-。四、在线增加或减少 Pod 的副本数1. 增加 Pod 副本数修改http.yml文件将replicas从 3 增加到 5然后重新应用配置[rootmaster k8s]# kubectl apply -f http.yml deployment.apps/http-deployment configured [rootmaster k8s]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE http-deployment-749876cd4f-89c29 1/1 Running 0 76m 10.244.2.5 node2 http-deployment-749876cd4f-bj7v9 1/1 Running 0 76m 10.244.1.7 node1 http-deployment-749876cd4f-gv8cw 1/1 Running 0 22s 10.244.1.8 node1 http-deployment-749876cd4f-hxkks 1/1 Running 0 76m 10.244.1.6 node1 http-deployment-749876cd4f-ldq8q 1/1 Running 0 22s 10.244.2.8 node2可以看到 Pod 数量由 3 个增加到了 5 个。2. 减少 Pod 副本数修改http.yml文件将replicas从 5 减少到 3或 2重新应用即可。Kubernetes 会自动终止多余的 Pod。五、Node 节点故障时的 Pod 切换假设当前有 3 个 httpd 副本分别运行在 node1 和 node2 上[rootmaster k8s]# kubectl get nodes NAME STATUS ROLES AGE VERSION master Ready master 8h v1.18.6 node1 Ready none 8h v1.18.6 node2 Ready none 8h v1.18.6 [rootmaster k8s]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE http-deployment-749876cdf4-brmt7 1/1 Running 0 16s 10.244.1.12 node1 http-deployment-749876cdf4-jt4bd 1/1 Running 0 16s 10.244.1.11 node1 http-deployment-749876cdf4-p56tb 1/1 Running 0 16s 10.244.2.9 node2现在模拟 node1 故障关闭该节点然后查看状态[rootmaster k8s]# kubectl get nodes NAME STATUS ROLES AGE VERSION master Ready master 8h v1.18.6 node1 NotReady none 8h v1.18.6 node2 Ready none 8h v1.18.6 [rootmaster k8s]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE http-deployment-749876cd4-rmt7 1/1 Terminating 0 7m56s 10.244.1.12 node1 http-deployment-749876cd4-jt4bd 1/1 Terminating 0 7m56s 10.244.1.11 node1 http-deployment-749876cd4-17jkd 1/1 Running 0 83s 10.244.2.11 node2 http-deployment-749876cd4-ndb9g 1/1 Running 0 83s 10.244.2.10 node2 http-deployment-749876cd4-p56tb 1/1 Running 0 7m56s 10.244.2.9 node2可以看到node1 状态变为NotReady。等待一段时间Kubernetes 会检测到 node1 不可用将 node1 上的 Pod 标记为Terminating状态并在 node2 上新建两个 Pod使总副本数维持在 3 个。当 node1 恢复后Terminating的 Pod 会被删除但已经在 node2 上运行的 Pod 不会重新调度回 node1。六、通过 Label 控制 Pod 的位置默认配置下Scheduler 会将 Pod 调度到所有可用的 Node。但有时我们希望将 Pod 部署到指定的 Node例如将大量磁盘 I/O 的 Pod 部署到配置了 SSD 的节点或需要 GPU 的 Pod 部署到 GPU 节点。Kubernetes 通过Label实现这个功能。Label 是 key-value 对各种资源都可以设置 Label灵活添加自定义属性。1. 给 Node 添加 Label执行如下命令标注 node1 是配置了 SSD 磁盘的节点[rootmaster k8s]# kubectl label node node1 diskssd [rootmaster k8s]# kubectl get node --show-labels注意diskssd中disk是 keyssd是 value都是自定义的。除了自定义 labelNode 上还有几个 Kubernetes 自己维护的 label。2. 编写带 nodeSelector 的 Deployment编写一个nginx.yml文件内容如下apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx_server template: metadata: labels: app: nginx_server spec: containers: - name: nginx-web image: nginx nodeSelector: disk: ssd在 Pod 模板的spec中通过nodeSelector指定将此 Pod 部署到具有 labeldiskssd的 Node 上。注意nodeSelector需要与containers保持同级且其中的S必须大写。3. 删除 Label要删除 label执行[rootmaster k8s]# kubectl label node node1 disk-删除之后已存在的 Pod 并不会重新部署依然会在原节点上运行。要改变 Pod 运行的节点需要修改nodeSelector设置然后通过kubectl apply重新部署。结语通过本文的详细介绍我们系统性地学习了 Kubernetes Deployment 的方方面面从它作为 ReplicaSet 和 Pod 上层控制器的基本定位到实际的创建、查看、更新操作从 YAML 配置文件的逐字段解析到在线扩缩容、节点故障自愈等强大特性最后还掌握了如何通过 Label 和 nodeSelector 精准控制 Pod 的调度位置。Deployment 的设计思想体现了 Kubernetes 声明式 API 的精髓 —— 用户只需要描述“想要什么”系统会持续不断地将实际状态调整为期望状态。这种模式极大地降低了运维复杂度也为自动化运维和 GitOps 实践奠定了坚实基础。在实际生产环境中Deployment 通常还会结合 Service、Ingress、ConfigMap、Secret 等对象共同工作形成一个完整的应用部署方案。作为 Kubernetes 学习的起点深入理解 Deployment 的使用方法和原理将帮助你更轻松地掌握 StatefulSet有状态应用、DaemonSet守护进程、Job/CronJob任务型应用等其它控制器从而从容应对各种复杂业务场景。希望本文能成为你 Kubernetes 学习之路上的一块坚实垫脚石。如果你有任何疑问或建议欢迎在评论区留言交流。