文章目录一、实验背景二、实验环境三、直接使用 YAML 创建 Pod3.1 编写 Pod 配置3.2 创建并检查 Pod3.3 验证 Nginx 服务3.4 为什么直接创建的 Pod 不会自动恢复四、使用 Deployment 管理 Pod 副本4.1 编写 Deployment YAML4.2 创建 Deployment 并查看资源关系4.3 Deployment 和 ReplicaSet 的职责五、通过删除实验验证 Pod 自愈5.1 记录删除前的 Pod5.2 删除一个 Pod5.3 Pod 自愈的准确含义六、使用 Service 提供稳定的访问入口6.1 为什么不能依赖 Pod IP6.2 编写 Service YAML6.3 创建 Service6.4 使用 EndpointSlice 验证后端七、验证 Service 的访问能力7.1 从集群内部访问 ClusterIP7.2 删除后端 Pod再观察 EndpointSlice八、总结这次实验真正理解了什么九、后续学习方向一、实验背景以YAML 创建 Nginx Pod为例子在 Kubernetes 学习过程中如果只是通过kubectl create deployment等命令创建应用很容易停留在“会使用命令”的阶段却不一定真正理解 Kubernetes 是如何管理应用的。因此本次实验从 YAML 配置文件出发在一台安装了 K3s 的 Ubuntu 服务器上部署 Nginx依次验证以下核心机制Pod 的创建与生命周期Deployment、ReplicaSet 与 Pod 之间的管理关系ReplicaSet 如何维持期望副本数量Service 如何通过标签选择后端 PodEndpointSlice 如何反映后端地址变化Pod 被替换后Service 如何继续提供稳定的访问入口本次实验使用独立命名空间nginx-yaml-lab避免与服务器上已有的应用资源混淆。二、实验环境项目配置操作系统Ubuntu ServerKubernetes 发行版K3s应用Nginx资源管理方式Kubernetes YAML实验命名空间nginx-yaml-labPod 网络10.42.0.0/16Service 网络10.43.0.0/16创建实验命名空间kubectl create namespace nginx-yaml-lab验证命名空间kubectl get namespace nginx-yaml-lab通过命名空间隔离实验资源可以降低误操作影响其他工作负载的风险。三、直接使用 YAML 创建 Pod3.1 编写 Pod 配置创建文件nginx-pod.yamlapiVersion:v1kind:Podmetadata:name:nginx-podnamespace:nginx-yaml-lablabels:app:nginxspec:containers:-name:nginximage:m.daocloud.io/docker.io/library/nginx:stableports:-containerPort:80这里有几个重要字段apiVersion: v1指定 Pod 使用的 Kubernetes API 版本。kind: Pod声明要创建的资源类型。metadata定义资源名称、命名空间和标签。spec.containers声明容器名称、镜像和端口。containerPort: 80描述容器使用的端口并不会自动将宿主机的 80 端口映射给容器。3.2 创建并检查 Pod执行kubectl apply-fnginx-pod.yaml查询运行状态kubectl get pod nginx-pod-nnginx-yaml-lab-owide实验结果NAME READY STATUS RESTARTS AGE IP nginx-pod 1/1 Running 0 ... 10.42.0.191Pod 成功运行容器就绪状态为1/1。但是Running并不等同于应用一定能正常处理请求因此还需要验证实际的 HTTP 响应。3.3 验证 Nginx 服务执行kubectlexec-nnginx-yaml-lab nginx-pod --\curl-I--max-time5http://127.0.0.1/返回HTTP/1.1 200 OK Server: nginx/1.30.5 Content-Type: text/html这证明 Nginx 已经能够正常响应 HTTP 请求。需要注意此时访问的是容器内部的127.0.0.1还没有验证其他 Pod 是否可以通过网络访问该应用。3.4 为什么直接创建的 Pod 不会自动恢复通过以下命令检查 Pod 的上级所有者引用kubectl get pod nginx-pod\-nnginx-yaml-lab\-ojsonpath{.metadata.ownerReferences}{\n}实验中输出为空。这表明该 Pod 没有声明所属的 Kubernetes 上级对象例如 ReplicaSet。如果直接创建的 Pod 被删除Kubernetes 不会因为本地 YAML 文件还存在就自动重新创建它。YAML 文件只是配置文件并不是一个持续运行的控制器。因此直接创建 Pod 适合学习基础资源和进行简单测试但不适合单独承担需要自动恢复的生产应用。四、使用 Deployment 管理 Pod 副本4.1 编写 Deployment YAML创建nginx-deployment.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:nginx-deploymentnamespace:nginx-yaml-labspec:replicas:2selector:matchLabels:app:nginx-deploymenttemplate:metadata:labels:app:nginx-deploymentspec:containers:-name:nginximage:m.daocloud.io/docker.io/library/nginx:stableports:-containerPort:80与直接创建 Pod 相比这份 YAML 增加了几个关键配置。replicas: 2声明期望运行两个 Pod 副本。它描述的是期望状态而不是保证任意时刻都绝对有两个可用 Pod。selector.matchLabels指定 Deployment 用什么标签识别其管理的 Pod 副本集合。template定义新 Pod 的模板包括标签、容器镜像、端口等信息。其中selector.matchLabels必须与template.metadata.labels匹配否则 Deployment 无法按照预期识别自己的副本。4.2 创建 Deployment 并查看资源关系先验证配置kubectl apply --dry-runserver-fnginx-deployment.yaml服务端试运行通过后再正式创建kubectl apply-fnginx-deployment.yaml查询 Deployment、ReplicaSet 和 Podkubectl get deployment,replicaset,pod-nnginx-yaml-lab实验中观察到的资源关系如下Deployment └── ReplicaSet ├── Pod └── PodDeployment 的状态为2/2ReplicaSet 的期望副本数为 2两个 Pod 均为Running。此时实验命名空间中还保留着之前直接创建的nginx-pod所以一共有三个 Pod一个独立 Pod以及两个由 Deployment 管理的 Pod。这说明 Kubernetes 并不会因为两个 Pod 使用了相似的 Nginx 镜像就自动将它们归为同一个应用。资源的管理关系取决于控制器、标签和所有者引用等信息。4.3 Deployment 和 ReplicaSet 的职责Deployment 与 ReplicaSet 并不是重复的两层资源它们承担不同职责。Deployment管理应用发布过程包括滚动更新、版本回滚以及对 ReplicaSet 的管理。ReplicaSet维持符合条件的 Pod 副本数量使实际状态尽量符合期望状态。Pod承载实际运行的容器。当 Deployment 声明replicas: 2时ReplicaSet 会持续观察实际副本数量。如果发现副本不足就尝试创建新的 Pod如果副本过多就尝试缩减副本数量。这一过程体现了 Kubernetes 的声明式管理思想用户声明期望状态控制器持续观察实际状态并尝试协调两者之间的差异。五、通过删除实验验证 Pod 自愈理论理解之后通过实际操作验证控制器的行为。5.1 记录删除前的 Pod使用标签选择器查询 Deployment 管理的副本kubectl get pods\-nnginx-yaml-lab\-lappnginx-deployment-owide实验中两个 Pod 的 IP 分别为10.42.0.192 10.42.0.193两个 Pod 都处于Running状态。5.2 删除一个 Pod执行kubectl delete pod\nginx-deployment-784659cff6-cfgxd\-nnginx-yaml-lab然后再次查询kubectl get pods\-nnginx-yaml-lab\-lappnginx-deployment-owide实验结果显示原 Pod 被删除后Kubernetes 创建了一个新 Pod原 Pod IP10.42.0.192 新 Pod IP10.42.0.194副本数量恢复为两个另一个 Pod 保持运行。这证明 ReplicaSet 会尝试维持期望副本数量。它并不是恢复原来的 Pod 对象而是根据 Pod 模板创建一个新的 Pod。5.3 Pod 自愈的准确含义这里所说的“自愈”并不意味着 Kubernetes 能够修复原 Pod 内部的所有故障。更准确地说ReplicaSet 发现 Pod 副本数量不足时可以创建新的 Pod。如果容器进程退出Kubelet 可能根据 Pod 的重启策略重新启动容器。如果节点发生故障工作负载能否恢复以及恢复需要多久还取决于节点状态检测、调度条件、存储、网络和其他因素。因此Pod 重建、容器重启和节点故障恢复是不同层次的机制不能简单地视为同一种行为。六、使用 Service 提供稳定的访问入口6.1 为什么不能依赖 Pod IP在前面的实验中Pod 被删除后新 Pod 获得了不同的 IP。如果客户端把某个 Pod 的 IP 直接写入配置那么 Pod 替换后客户端可能仍然访问旧地址需要额外修改配置。对于多个副本的应用更合理的方式是提供统一的访问入口让客户端不必关心具体请求最终到达哪个后端。这就是 Service 的主要作用之一。6.2 编写 Service YAML创建nginx-service.yamlapiVersion:v1kind:Servicemetadata:name:nginx-servicenamespace:nginx-yaml-labspec:type:ClusterIPselector:app:nginx-deploymentports:-port:80targetPort:80几个核心字段的含义如下字段含义type: ClusterIP创建供集群内部访问的 Serviceselector根据标签选择后端 Podport: 80Service 提供的端口targetPort: 80后端容器接收流量的端口port和targetPort并不一定相同。例如Service 可以对外提供 8080 端口再将流量转发到容器的 80 端口。6.3 创建 Service执行kubectl apply-fnginx-service.yaml查询 Servicekubectl getservicenginx-service-nnginx-yaml-lab实验中获得的 ClusterIP 为10.43.131.88这个地址是 Service 的集群内部虚拟 IP不是某个 Nginx 容器的 IP。创建 Service 后还需要确认它是否成功发现了后端 Pod。6.4 使用 EndpointSlice 验证后端执行kubectl get endpointslice\-nnginx-yaml-lab\-lkubernetes.io/service-namenginx-service实验中观察到ADDRESSTYPE PORTS ENDPOINTS IPv4 80 10.42.0.194,10.42.0.193这说明 Service 对应的 EndpointSlice 已经记录了两个后端地址。其工作关系可以概括为Service 的 selector 匹配 Pod 标签。EndpointSlice 记录对应的后端端点。集群网络组件根据 Service 规则转发流量。需要注意EndpointSlice 不负责转发请求它主要用于记录端点信息实际流量转发由 Kubernetes 的网络实现完成。七、验证 Service 的访问能力7.1 从集群内部访问 ClusterIP使用之前直接创建的独立 Pod 作为客户端执行kubectlexec-nnginx-yaml-lab nginx-pod --\curl-I--max-time5http://10.43.131.88/实验结果HTTP/1.1 200 OK Server: nginx/1.30.5 Content-Type: text/html这证明客户端 Pod 能够通过 Service 的 ClusterIP 访问 Nginx。与之前直接访问127.0.0.1不同这次请求经过了 Service 的访问路径验证了集群内服务访问能力。7.2 删除后端 Pod再观察 EndpointSlice为了进一步验证服务发现机制删除一个由 Deployment 管理的 Podkubectl delete pod\nginx-deployment-784659cff6-6c7fx\-nnginx-yaml-lab重新查看 EndpointSlicekubectl get endpointslice\-nnginx-yaml-lab\-lkubernetes.io/service-namenginx-service实验结果中后端地址从10.42.0.193 10.42.0.194更新为10.42.0.193 10.42.0.195与此同时查询 Pod 发现新的 Pod 已经创建并运行副本数量仍然是两个。这一过程验证了两个不同但相互配合的机制ReplicaSet 负责补足 Pod 副本。EndpointSlice 控制器根据符合条件的 Pod 状态更新端点信息。因此Service 不需要把某个固定 Pod 的 IP 写入 YAML。后端 Pod 被替换后符合选择条件的新 Pod 可以被纳入服务的后端端点集合。八、总结这次实验真正理解了什么通过从 YAML 创建 Pod、Deployment 和 Service并实际删除 Pod 观察资源变化可以总结出以下几点。第一Kubernetes 使用声明式配置管理资源。YAML 描述期望状态Kubernetes 根据配置创建资源并持续协调实际状态。配置文件本身不会自动执行资源的持续管理依赖控制器等组件。第二Pod 不是应用高可用的全部。直接创建的 Pod 不会因为被删除就自动重建。Deployment 通过管理 ReplicaSet间接实现应用副本管理与发布能力。第三副本自愈与应用健康检查不是同一回事。ReplicaSet 主要维持副本数量。容器重启、Readiness Probe、Liveness Probe 和节点故障恢复分别解决不同层次的问题。第四Service 解耦了客户端和 Pod。客户端使用稳定的 Service 地址不需要追踪每个 Pod 的动态 IP。Service 通过标签选择后端EndpointSlice 反映当前端点信息网络组件负责实际转发。第五Kubernetes 的核心是控制器持续协调期望状态和实际状态。理解这一点比记住某一条kubectl命令更重要。它也是后续学习扩缩容、滚动更新、回滚、健康检查和故障排查的基础。九、后续学习方向完成本次实验后可以继续学习NodePort 与外部访问理解集群外部客户端如何访问应用以及端口规划和网络边界。Readiness Probe 与 Liveness Probe理解如何判断应用是否可以接收流量以及何时需要重启容器。Deployment 滚动更新与回滚观察镜像或 Pod 模板变化如何创建新的 ReplicaSet。资源限制与调度学习 requests、limits、节点资源和 Pod 调度之间的关系。结合 CI/CD 实践将构建出的应用镜像部署到 Kubernetes进一步串联 Jenkins、镜像仓库、发布和回滚流程。从实际运维角度看理解这些机制不仅能帮助我们编写 Kubernetes YAML也能在应用不可访问、Pod 不断重建或服务后端异常时沿着资源状态和控制器关系逐层定位问题。