介绍
Pod 用于运行容器,但在 Kubernetes 中,直接使用 Pod 并不是运行应用程序的常规方式。Deployment 描述了应用程序的期望状态,并创建一个 ReplicaSet,进而由 ReplicaSet 来创建和维护 Pod。
在本实验中,你将创建第一个 Deployment,等待其变为可用状态,检查它所创建的 Deployment、ReplicaSet 和 Pod,然后观察 Deployment 如何在 Pod 被删除后恢复它们。这是后续学习 CKAD 主题(如扩缩容、滚动更新、回滚和应用暴露)的基础。
准备 Deployment 命名空间
在此步骤中,你将准备一个干净的命名空间用于 Deployment 练习,并将其设置为命令的默认命名空间。
从 /home/labex/project 开始。虽然本实验不需要编写清单文件,但使用相同的工作区可以保持课程的一致性。
mkdir -p /home/labex/project
cd /home/labex/project
检查 Kubernetes API 服务器是否可访问。如果虚拟机刚启动且此命令失败,请等待几秒钟并再次运行,直到节点状态为 Ready。
kubectl get nodes --request-timeout=5s
预期输出包括:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Pod 需要集群网络插件才能变为 Ready 状态。在创建应用程序工作负载之前,请等待 Calico 节点 Pod 就绪。
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
预期输出:
pod/calico-node-... condition met
创建一个名为 ckad-prep-deployments 的命名空间:
kubectl create namespace ckad-prep-deployments
该命令应确认创建成功:
namespace/ckad-prep-deployments created
将此命名空间设置为当前上下文的命名空间:
kubectl config set-context --current --namespace=ckad-prep-deployments
确认当前命名空间:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
预期输出:
ckad-prep-deployments
创建 Deployment
在此步骤中,你将创建一个名为 web-demo 且包含两个副本的 Deployment。
kubectl create deployment 命令会请求 Kubernetes 创建一个 Deployment 对象。--image 选项设置 Pod 模板中的容器镜像,而 --replicas=2 则要求 Deployment 保持两个匹配的 Pod 处于运行状态。
kubectl create deployment web-demo --image=registry.k8s.io/pause:3.10.1 --replicas=2
预期输出:
deployment.apps/web-demo created
等待 Deployment 滚动更新完成。对于一个新的 Deployment,滚动更新状态意味着 Kubernetes 已经创建了 ReplicaSet,并且所请求的 Pod 已变为可用状态。
kubectl rollout status deployment/web-demo --timeout=90s
在 Pod 变为可用期间,输出可能会包含简短的等待信息。最终应显示:
deployment "web-demo" successfully rolled out
现在检查 Deployment 的摘要信息:
kubectl get deployment web-demo
预期输出包括:
NAME READY UP-TO-DATE AVAILABLE AGE
web-demo 2/2 2 2 ...
检查 ReplicaSet 和 Pod
在此步骤中,你将检查 Deployment 下方创建的对象。
Deployment 不会直接运行容器。它会创建一个 ReplicaSet,然后由 ReplicaSet 创建 Pod。Deployment 的选择器(selector)和 Pod 模板标签将这些对象连接在一起。
首先,检查 Deployment 上的选择器标签和模板标签。JSONPath 仅打印选定的字段,使输出更加清晰。
kubectl get deployment web-demo -o 'jsonpath={.spec.selector.matchLabels.app}{" "}{.spec.template.metadata.labels.app}{"\n"}'
预期输出:
web-demo web-demo
第一个值是 Deployment 的选择器标签,第二个值是放置在模板中 Pod 上的标签。它们匹配,因此 Deployment 可以管理这些 Pod。
列出由该 Deployment 创建的 ReplicaSet:
kubectl get replicasets -l app=web-demo
预期输出包括:
NAME DESIRED CURRENT READY AGE
web-demo-... 2 2 2 ...
现在列出由相同标签选择的 Pod:
kubectl get pods -l app=web-demo --show-labels
预期输出包括两个正在运行的 Pod:
NAME READY STATUS RESTARTS AGE LABELS
web-demo-... 1/1 Running 0 ... app=web-demo,pod-template-hash=...
web-demo-... 1/1 Running 0 ... app=web-demo,pod-template-hash=...
最后,显示每个 Pod 的所有者类型。每个 Pod 都由 ReplicaSet 拥有,而不是直接由 Deployment 拥有。
kubectl get pods -l app=web-demo -o 'custom-columns=NAME:.metadata.name,OWNER:.metadata.ownerReferences[0].kind,PHASE:.status.phase'
预期输出:
NAME OWNER PHASE
web-demo-... ReplicaSet Running
web-demo-... ReplicaSet Running
观察期望状态的恢复
在此步骤中,你将删除当前的 Pod,并观察 Deployment 如何恢复期望状态。
这是单个 Pod 和 Deployment 之间的关键区别。如果你删除独立的 Pod,它们就会消失。如果你删除由 Deployment 管理的 Pod,Deployment 会注意到实际状态不再匹配期望状态,并创建新的 Pod 来替换它们。
删除由 app=web-demo 选择的 Pod。--wait=false 选项会在发送删除请求后立即返回,这样你就可以在不等待旧 Pod 完全消失的情况下观察恢复过程。
kubectl delete pods -l app=web-demo --wait=false
预期输出包括:
pod "web-demo-..." deleted from ckad-prep-deployments namespace
pod "web-demo-..." deleted from ckad-prep-deployments namespace
等待 Deployment 再次变为可用状态:
kubectl wait --for=condition=Available deployment/web-demo --timeout=90s
预期输出:
deployment.apps/web-demo condition met
再次列出 Pod:
kubectl get pods -l app=web-demo
预期输出包括两个正在运行的 Pod。由于 ReplicaSet 创建了替换的 Pod,名称可能会有所不同。
NAME READY STATUS RESTARTS AGE
web-demo-... 1/1 Running 0 ...
web-demo-... 1/1 Running 0 ...
再次检查 Deployment 摘要:
kubectl get deployment web-demo
预期输出包括:
NAME READY UP-TO-DATE AVAILABLE AGE
web-demo 2/2 2 2 ...
总结
你创建了一个 Deployment,等待其滚动更新完成,检查了它的选择器和 Pod 模板标签,找到了它创建的 ReplicaSet 和 Pod,并观察了删除 Pod 后期望状态的恢复过程。这些概念为你接下来的 Deployment 实验打下了基础,在后续实验中,你将学习如何更改副本数量、更新应用程序以及管理滚动更新行为。


