你是不是也遇到过写了个 ServiceNodePort 怎么都连不上curl 一直超时配了 Ingress后端日志里看到的客户端 IP 全是 127.0.0.1多个服务想共用一个公网入口结果一个 Ingress 里塞了几十条规则还听说 Ingress NGINX 2026 年 3 月要停了这篇文档不跟你绕弯子。读完你能搞定分清 ClusterIP / NodePort / LoadBalancer / Ingress 到底什么场景用哪个顺手抄走 8 份能直接跑的 YAML 配置躲开 5 个生产环境最常见的坑源 IP 丢失、端口范围、externalTrafficPolicy、Ingress 规则冲突搞懂 2026 年 Ingress NGINX 退役后该怎么优雅“跳槽”前置条件已有一个 K8s 集群kubectl配置好能创建 Service/Deployment/Ingress。我用 Kubernetes v1.31 在云上测的裸机或自建集群也基本一样。一、先搞懂 Service 到底解决了什么3 分钟K8s 里 Pod 是“短命鬼”——换个节点 IP 就变了随时可能被删掉重建。Service 提供的是虚拟 IP DNS 名永远指向符合标签条件的 Pod。一句话Service 固定的 IP 域名背后 Pod IP 怎么变都无所谓。彩蛋*你甚至可以用 Service 指向集群外部的服务。YAML 里不写selector手动配 EndpointSlices就能优雅地把外部数据库“伪装”成集群内的 Service。二、四种 Service 类型附可直接复用的 YAML1. ClusterIP——打底用的“内部直通车”没指定type时默认就是它。只能在集群内部访问最适合微服务间的调用。apiVersion: v1 kind: Service metadata: name: backend-service spec: type: ClusterIP # 可以省略默认就是 selector: app: backend # 和 Pod 的 label 保持一致 ports: - port: 8080 # Service 对外端口 targetPort: 80 # Pod 容器实际监听的端口验证在集群里任意一个 Pod 里curl http://backend-service:8080生产场景前端 Pod → 后端 Service完全不用暴露到集群外面。简单直接。2. NodePort——“凑合用”的外部入口在每个节点 IP 上开一个静态端口默认 30000-32767流量推给后端 Pod。apiVersion: v1 kind: Service metadata: name: myapp-nodeport spec: type: NodePort selector: app: myapp ports: - port: 80 targetPort: 8080 nodePort: 30080 # 不写的话系统自动分配访问方式curl http://任意节点IP:30080⚠️我踩过的坑NodePort 默认端口范围就 30000-32767。想用 80、443 之类的端口得在 kube-apiserver 启动参数里加--service-node-port-range80-32767。生产环境劝你别这么干——改起来麻烦还可能跟节点上的其他进程冲突。真需要 80/443 的请直接上 IngressLoadBalancer。3. LoadBalancer——生产环境真神器云厂商自带的负载均衡器直接给你一个公网 IP或主机名。在 AKS/EKS/GKE 这类托管集群里用得最多。apiVersion: v1 kind: Service metadata: name: myapp-lb spec: type: LoadBalancer selector: app: myapp ports: - port: 80 targetPort: 8080创建后kubectl get svc的EXTERNAL-IP那一列会显示分配的 IP。等着就是云平台分配需要点时间。生产优先级多租户、每天上万请求直接上 LoadBalancer少折腾。4. externalTrafficPolicy 的坑这个藏得很深但我必须说默认externalTrafficPolicy: Cluster会让请求在节点间二次转发。结果就是你后端 Pod 收到的客户端 IP全变成了 Node IP。改成Local就能保留真实客户端 IPapiVersion: v1 kind: Service metadata: name: myapp-lb spec: type: LoadBalancer externalTrafficPolicy: Local # ← 关键就这一行 selector: app: myapp ports: - port: 80⚠️致命 trade-offLocal模式下每个节点只把流量分给自己节点上的 Pod。没有 Pod 的节点LB 会把该节点摘掉。Pod 分布不均匀时可能出现“某几个节点根本不接流量”的情况。所以配了 Local 之后尽量用 Pod 反亲和podAntiAffinity把 Pod 均匀散到各节点。三、Ingress——“一个入口万种路由”和 Service 什么关系Service 只管把请求定向到 Pod。Ingress 接管更上层的事情路径判断、域名分流、TLS 加解密。二者不是替代关系Ingress 背后一定是某个 Service。架构示意外部请求 → LB ServiceType: LoadBalancer→ Ingress Controller Pod → 根据 host/path 分发 → 各个 Service → 对应的 Pod或是云厂商自家的 Ingress Controller 直接对接云 LB中间少一跳。1. 最简 Ingress——路径路由apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: simple-ingress spec: ingressClassName: nginx # 指定用哪个 Ingress Controller rules: - host: app.example.com http: paths: - path: /api pathType: Prefix backend: service: name: api-service port: number: 8080 - path: / pathType: Prefix backend: service: name: web-service port: number: 80验证curl -H Host: app.example.com http://Ingress IP/api2. Ingress TLS证书apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: tls-ingress spec: ingressClassName: nginx tls: - hosts: - secure.example.com secretName: tls-secret # 证书存在这个 Secret 里 rules: - host: secure.example.com http: paths: - path: / pathType: Prefix backend: service: name: secure-app port: number: 443证书可以用cert-manager Let‘s Encrypt全自动管理metadata: annotations: cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - secure.example.com secretName: secure-example-tls干了啥Ingress 一创建cert-manager 检测到 annotation自动申请证书、写入 Secret。过期前自动续期不用你操心。3. annotations 的七七八八不同 Ingress Controller 有自己的“独门绝技”基本通过 annotations 实现。用 NGINX Ingress 的时候这几个最常用metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: / # 重写路径 nginx.ingress.kubernetes.io/ssl-redirect: true # HTTP→HTTPS nginx.ingress.kubernetes.io/backend-protocol: HTTPS # 后端走了 HTTPS nginx.ingress.kubernetes.io/limit-rps: 100 # 限速⚠️注意backend-protocol: HTTPS这个我吃过苦头——后端 Pod 只认 HTTPSIngress 默认发 HTTP报错The plain HTTP request was sent to HTTPS port。加上这个 annotation 立马解决。四、Ingress Controller 选型指南 2026 年大消息Ingress 定义跑到集群里是不会自己动的——得有个Ingress Controller把规则加载到真正的反向代理Nginx、Envoy、Traefik 等里。⚠️ 2026 年 3 月Ingress NGINX 正式退役Kubernetes SIG Network 已明确Ingress NGINX 仓库进入只读模式不再有 bug 修复、安全补丁和新特性发布。影响范围很大——它是目前部署最广的 Ingress Controller。K8s 项目官方也不计划移除 Ingress API 本身networking.k8s.io/v1。所以你只是不能用ingress-nginx了可以换别的 Controller。替代方案推荐短期过渡继续用 Ingress APITraefik—— 部署简单自带 dashboard同时支持 Ingress 和 Gateway APIannotation 兼容性不错HAProxy Ingress—— 性能极其猛企业级 L7 路由ContourEnvoy 底座—— 性能好是迈向 Gateway API 的桥梁长期方案我建议直接走这条路Gateway API—— Ingress 的官方替代品角色分离更清晰平台团队管 Gateway应用团队只管 HTTPRoute。支持 HTTPRoute 权重分割、TCP/UDP 等原生能力。建议从现在的新项目就直接上免得到时候集中迁。执行建议成立一个“出 Ingress NGINX”专项把集群清单摸清楚从负载小的非核心服务开始练手。挨到 2026 年 3 月后再被动式手忙脚乱换那就真的来不及了。顺便提一嘴Gateway API 里HTTPRoute弄金丝雀发布很方便weight: 80和weight: 20一配20% 流量切到新版本Flagger 还能自动化。五、生产环境最容易翻车的 5 件事问题 1Service 访问不通——“端口写错了还是 selector 没对上”先 kubectl describe svc 看看 Endpoints 列有没有东西。Endpoints 为空 selector 标签没匹配到任何 Pod。问题 2Ingress 不生效——Ingress Controller 没装没有 ControllerIngress 就是一纸空文。跑kubectl get pods -n ingress-nginx确认 pod 在运行。问题 3客户端 IP 丢了上面已经讲过 externalTrafficPolicy: Local。用之后确认 Pod 均匀分布免得部分节点被 LB 踢掉。问题 4NodePort 被别人占了加了nodePort: 30080后发现端口被别的 Service 占着K8s API Server 会自动排错报错信息会告诉你冲突。解决办法删掉冲突 Service或换个端口。问题 5Ingress 太大reload 越来越慢把单体几十条规则的大 Ingress 拆成多个小规模的分 service 分 path 各自管理。改一个规则只影响小范围重载快得多。最后的检查清单上线前务必走一遍Service 的 Endpoints 有值NodePort 在默认端口范围内30000-32767Ingress 有对应的 Controller 在跑externalTrafficPolicy 按需要设置证书没到期六、总结一张表让你心里有底场景用哪个一句话理由Pod A 调 Pod B集群内部ClusterIP虚拟 IP 稳定测试/临时暴露服务NodePort最快上手云上生产环境对外LoadBalancer Ingress专有 IP 高级路由集群内部就一个服务简单暴露LoadBalancer不配 Ingress省事多域名/多路径/TLSIngress Controller就是为这种场景设计的你还有什么实际踩过的坑想补充或者正在纠结用哪个 Ingress Controller评论区见一起把坑填平。