资讯动态

Day57-K8s核心概念速通:Pod、Deployment、Service与Ingress

发布时间:2026/8/23 18:55:57 来源:尧图企业网站定制
Pod/Deployment/Service/Ingress——后端上生产的四个分水岭容器化部署容易但很多人只照着 YAML 复制粘贴、没系统学过 K8s出故障时连应用跑在哪个 Pod、日志去哪捞、重启容器和发布新版本有什么区别都搞不清。云原生这关你不一定要成为 K8s 专家但 Pod、Deployment、Service、Ingress 这四个对象是从会写 Java到能扛住生产的分水岭——搞不懂它们出问题时你连战场在哪都不知道。本文用四个核心对象把一个 Spring Boot 应用从裸进程一步步变成生产可用先讲清声明式 API 与控制循环这一底层思维再逐个拆解 Pod最小调度单元 三探针、Deployment滚动更新与回滚、Service稳定访问入口与四种类型、Ingress七层路由最后串成完整落地链路并给出排障三板斧。读完能独立把 Java 应用部署上 K8s 并定位常见故障。一、先搞懂 K8s 的底层思维声明式 API在讲任何对象之前必须先把声明式这三个字嚼烂。这是 K8s 和传统运维最大的思维分野。传统运维是命令式你告诉系统每一步怎么走。# 命令式一步步下指令 docker run -d -p 8080:8080 my-app:v1 # 先启动一个容器 docker run -d -p 8080:8080 my-app:v1 # 再加一个容器手动扩容 # 挂了怎么办你自己写脚本监控、自己重启K8s 是声明式你只告诉系统我想要什么状态剩下交给它。# 声明式描述期望状态 kubectl apply -f deployment.yaml # deployment.yaml 里写了我要 3 个副本镜像用 my-app:v1 # K8s 会持续对账实际跑 2 个自动拉起 1 个。跑成 v2 了自动回滚到 v1。这两者的区别一句话就能说透命令式是你盯着每一步声明式是你定一个目标系统自己兜底。K8s 的核心是一个控制循环Reconciliation Loop也叫调谐循环。它的工作方式极其简单但威力巨大循环 { 观察Observe实际状态是什么 对比Diff 和期望状态差多少 行动Act 做点什么让实际状态逼近期望状态 }你提交给 K8s 的任何 YAML本质都是在声明一个期望状态。K8s 的各个控制器Controller会不停地把这个期望状态变成现实。理解了这一点你就能理解 K8s 里几乎所有让你困惑的行为——比如为什么删掉的 Pod 会自动复活为什么改了副本数不用手动操作为什么服务挂了能被拉起来。划重点kubectl apply是声明式的kubectl create是命令式的。生产环境一律用apply因为它幂等重复执行不会报错天然适合写进 CI/CD 流水线。二、Pod最小的调度单元也是容器的家先纠正一个 90% 新手都会犯的认知错误K8s 里最小的部署单位不是容器是 Pod。2.1 Pod 是什么Pod 是一个或多个容器的集合这些容器共享网络命名空间和存储卷永远被调度到同一台机器上。你可以把 Pod 理解成一组关系紧密、必须同生共死的容器。大多数情况下一个 Pod 只有一个主容器比如你的 Spring Boot 应用。什么时候会放多个容器典型场景是Sidecar 模式——主容器旁边挂一个辅助容器。比如你的应用容器旁边挂一个日志采集容器或者挂一个AI 推理的模型下载预热容器。下面是一个最简 Pod 定义# pod.yaml —— 一个最简的 Pod注意生产环境不直接裸用 Pod后面会说为什么 apiVersion: v1 kind: Pod metadata: name: my-app-pod labels: # 标签K8s 关联对象的核心手段 app: my-app spec: containers: - name: app image: my-registry/my-app:v1.0.0 # 版本号务必写死禁止用 latest ports: - containerPort: 8080 resources: # 不写资源限制是生产事故的头号元凶 requests: # 调度时的保底资源 memory: 256Mi cpu: 250m limits: # 运行时的天花板资源 memory: 512Mi cpu: 500m2.2 Pod 的生命周期Pod 从创建到销毁会经历一个明确的状态机这是你排障时必须能一眼看懂的东西四个核心状态背下来状态含义你的关注点Pending已创建但还没调度或容器没起来看是资源不足还是镜像拉不下来Running至少一个容器在运行不等于健康得配合探针判断Succeeded所有容器正常退出通常是 Job/定时任务Failed容器异常退出查容器日志和退出码这里有个大坑Running≠ 服务可用。容器进程活着不代表它已经能对外服务比如 Spring Boot 可能还在启动、数据库还没连上。这就是为什么 K8s 设计了探针Probe。2.3 三种探针健康的真正判官# deployment.yaml 的 Pod 模板片段 spec: containers: - name: app image: my-registry/my-app:v1.0.0 startupProbe: # 启动探针给慢启动的 JVM 留足时间 httpGet: path: /actuator/health port: 8080 failureThreshold: 30 # 最多等 30 * 10s 300秒 periodSeconds: 10 livenessProbe: # 存活探针进程死没死 httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 0 periodSeconds: 10 readinessProbe: # 就绪探针能不能接客 httpGet: path: /actuator/health port: 8080 periodSeconds: 5三者的分工一定要分清搞混了会引发生产事故startupProbe启动探针只判断启动完成没有。JVM 启动慢尤其是配了 AI SDK 加载模型的 Spring Boot可能几十秒才起来这时 livenessProbe 会误判死了而反复重启容器。startupProbe 就是用来给慢启动兜底的。livenessProbe存活探针判断进程是否已死。失败就重启容器——注意是重启容器不是重启 Pod。readinessProbe就绪探针判断能不能接流量。失败就从 Service 的负载均衡里摘掉但不重启容器。一句话记忆startup 管起没起来liveness 管死没死readiness 管能不能用。三、Deployment为什么不能裸用 Pod前面我留了个伏笔——生产环境不要直接裸用 Pod。原因很简单Pod 一旦挂了不会自动恢复你想扩容到 3 个副本得手动创建 3 次你想滚动升级版本得手动一个个替换。Deployment 就是来解决这三件事的。它内部管理一个 ReplicaSet副本集ReplicaSet 再管理一组 Pod形成一条控制链Deployment声明期望副本数、版本、更新策略 └── ReplicaSet保证当前版本的 Pod 数量达标 └── Pod真正干活的最小单元一个生产级 Deployment 长这样# deployment.yaml —— Spring Boot 应用的生产级部署依赖JDK 17 Spring Boot 3.x apiVersion: apps/v1 kind: Deployment metadata: name: ai-order-service labels: app: ai-order-service spec: replicas: 3 # 期望副本数改这个数字就能扩缩容 strategy: # 滚动更新策略 type: RollingUpdate rollingUpdate: maxUnavailable: 0 # 更新期间最多允许 0 个 Pod 不可用 → 零停机 maxSurge: 1 # 更新期间最多多出 1 个 Pod selector: # 用来找到属于它的 Pod matchLabels: app: ai-order-service template: # Pod 模板定义了 Pod 长什么样 metadata: labels: app: ai-order-service spec: containers: - name: app image: my-registry/ai-order-service:v2.3.0 ports: - containerPort: 8080 env: - name: SPRING_PROFILES_ACTIVE value: prod resources: requests: { memory: 512Mi, cpu: 500m } limits: { memory: 1Gi, cpu: 1000m } readinessProbe: httpGet: { path: /actuator/health, port: 8080 } periodSeconds: 5Deployment 的三个杀手级能力配合kubectl命令就是# 1. 扩缩容一条命令K8s 自己搞定 kubectl scale deployment ai-order-service --replicas5 ​ # 2. 滚动更新换镜像K8s 逐个替换旧 Pod零停机 kubectl set image deployment/ai-order-service appmy-registry/ai-order-service:v2.4.0 kubectl rollout status deployment/ai-order-service # 看更新进度 ​ # 3. 一键回滚版本出问题退回到上一个版本 kubectl rollout undo deployment/ai-order-servicemaxUnavailable: 0配合maxSurge: 1这个组合能保证更新过程中始终有 3 个 Pod 在对外服务——这就是滚动更新零停机的原理值得你记住。四、ServicePod 会死但服务地址不能变现在你有了 3 个 Pod但问题来了Pod 的 IP 是随机分配且会变的。Pod 一旦重启IP 就换了那你的前端、你的其他微服务怎么稳定地找到它Service 解决的就是稳定访问入口的问题。Service 会给一组 Pod 分配一个稳定的虚拟 IPClusterIP和 DNS 名称然后通过selector找到它要代理的 Pod把流量转发过去。Pod 死了重启IP 变了但只要labels没变Service 就永远能找到它。Service 有四种类型这是面试和实战的双料高频考点类型访问范围典型场景一句话ClusterIP集群内部微服务之间互调默认类型内部专用NodePort集群外部节点 IP:端口临时暴露、调试在 ClusterIP 基础上在每个节点开个端口LoadBalancer集群外部云厂商 LB生产对外服务在 NodePort 基础上自动创建云负载均衡器ExternalName集群外部DNS 别名访问集群外的服务就是个 CNAME不代理 Pod四种类型是层层递进的关系看这个图就明白了ClusterIP ──→ 仅集群内部可达 │ 叠加在每个节点开一个端口 ▼ NodePort ──→ 外部可通过 节点IP:端口 访问 │ 叠加云厂商自动创建负载均衡器 ▼ LoadBalancer ──→ 外部通过云 LB 的固定 IP 访问生产首选 ExternalName ──→ 独立的仅做 DNS 别名映射下面是一个 ClusterIP 型 Service配合上面的 Deployment 使用# service.yaml —— 为 ai-order-service 提供一个稳定的集群内部地址 apiVersion: v1 kind: Service metadata: name: ai-order-service spec: type: ClusterIP # 默认类型集群内部访问 selector: # 通过 label 匹配到对应的 Pod app: ai-order-service ports: - name: http port: 8080 # Service 对外暴露的端口 targetPort: 8080 # Pod 上实际监听的端口 protocol: TCP部署完成后集群内其他服务可以直接用http://ai-order-service:8080访问它不用关心背后是 3 个还是 30 个 Pod也不用关心它们的 IP 是什么。这就是 Service 的价值把访问入口和具体实例彻底解耦。实战提醒selector是 Service 找到 Pod 的唯一桥梁selector里的 label 必须和 Pod 模板里的 label 完全一致错一个字母流量就断还不会报错。五、Ingress七层路由一个入口管所有服务Service 解决了稳定访问但还差最后一公里。假设你有三个服务订单服务、用户服务、还有前几周我们做的AI 智能客服服务。如果每个服务都用 NodePort 暴露那你要记三个端口号前端还要处理一堆 IP。更重要的是NodePort 和 LoadBalancer 都是四层TCP的干不了按域名/路径路由这种七层的事。Ingress 就是来解决七层路由的。它让你用一个统一入口根据域名和路径把请求分发到不同的 Service用户请求 https://api.yourdomain.com │ ▼ Ingress Controller如 nginx-ingress │ 按规则匹配 ├── /order/** ──→ ai-order-service (Service) ├── /user/** ──→ user-service (Service) └── /ai/** ──→ ai-chat-service (Service)一个 Ingress 规则长这样# ingress.yaml —— 按路径路由到不同服务 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: api-gateway-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / # 重写规则常见坑 spec: ingressClassName: nginx # 必须指定 Ingress Controller rules: - host: api.yourdomain.com http: paths: - path: /order pathType: Prefix backend: service: name: ai-order-service port: { number: 8080 } - path: /ai pathType: Prefix backend: service: name: ai-chat-service port: { number: 8080 }一个必须记住的坑Ingress 只是一纸路由规则它本身不干活。真正转发流量的是Ingress Controller比如 nginx-ingress、Traefik这个是需要你额外部署的组件。很多新手写完 Ingress 发现不生效就是忘了装 Controller。六、串起来一个 Spring Boot 应用的完整落地把上面四件套串起来一个 Java 应用从裸进程到生产可用的完整路径就是部署顺序也很清晰照着敲就行到这里你的 Java 应用就有了自动恢复Deployment 稳定访问Service 统一入口Ingress 健康自检Probe。这就是云原生时代一个后端工程师的及格线配置。实战建议1. 先懂声明式再背命令。K8s 的命令有几百条背不完也没必要。但只要你把声明式 控制循环这个底层思维吃透所有的对象、控制器、行为都能自己推导出来。看任何 K8s 文档先问一句这是在声明什么期望状态。2. 生产环境的三条铁律写死版本号、配好资源限制、配好就绪探针。我见过太多线上事故根源就是这三条没做好镜像用了latest导致不可复现没写limits导致一个内存泄漏的 Pod 拖垮整台节点没配readinessProbe导致流量打进还没就绪的 Pod 全部报错。这三条不做到别谈上生产。3. 排障三板斧describe看事件logs看日志get events看历史。Pod 起不来别瞎猜。按顺序来kubectl describe pod pod名 # 看 Events会告诉你为什么镜像拉不下资源不足探针失败 kubectl logs pod名 -f # 看容器日志找应用层面的报错 kubectl get events --sort-by.metadata.creationTimestamp | tail -20 # 看集群最近发生了什么90% 的问题这三条命令走一遍就能定位。结尾K8s 这玩意概念多、术语绕但它骨子里就一句话你声明一个目标它负责把目标变成现实。你作为后端工程师要做的不是记住所有命令而是把 Pod、Deployment、Service、Ingress 这四个对象的职责边界刻进脑子——Pod 是干活的Deployment 是管人的Service 是开门的Ingress 是引路的。下一篇我们把上一周搭的 Spring Boot 微服务真正搬进 K8s讲ConfigMap Secret 配置管理以及基于 QPS 的弹性伸缩HPA——让你的服务不仅能跑还能自己扩容。咱们不见不散。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价