讲解

NodePort/LoadBalancer 工作在四层(TCP/端口),一个服务一个入口。真实网站往往是「一个域名 + 按路径/子域名分发到不同服务」:/api 给后端、/ 给前端、static.example.com 给静态服务——这是七层(HTTP)路由的活,Kubernetes 里由 Ingress 承担。Ingress 资源本身只是路由规则的声明(哪个主机名、哪个路径、转发给哪个 Service),真正干活的是 Ingress Controller(ingress-nginx、Traefik 等),它监听 Ingress 资源并把自己配置成反向代理。

所以装 Ingress 永远分两步:先装控制器(一个 Deployment + Service 的组合),再写 Ingress 规则。规则清单的核心字段:spec.ingressClassName 指定用哪个控制器(集群里可能装了多个);rules 里是路由表,host 按域名匹配,paths 按路径匹配,pathType 常用 Prefix(前缀匹配);backend 指向 Service 名和端口。匹配到请求的流量路径是:客户端 → 控制器 Service 暴露的入口 → 控制器按 Ingress 规则转发 → 后端 Service → Pod。

本教程的验证环境有个现实限制值得说明:安装 ingress-nginx 控制器要从 GitHub 下载官方清单,受限网络下可能失败。脚本会在验证阶段尝试安装一次:成功则真正 curl 验证七层路由;失败则只验证 Ingress 资源本身能被 API Server 接受(控制器不影响规则声明的合法性,规则会躺着等控制器来生效)。这种「资源声明与控制器解耦」的设计本身就是 Kubernetes 的通用模式——理解它,比让本地 curl 通更重要。

示例

先准备一个后端服务(复用 web 应用,ClusterIP 即可——Ingress 控制器在集群内转发,不需要 NodePort):

# wait: deploy/ohmydocs-verify-web
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ohmydocs-verify-web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ohmydocs-verify-web
  template:
    metadata:
      labels:
        app: ohmydocs-verify-web
    spec:
      containers:
        - name: nginx
          image: nginx:1.27-alpine
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: ohmydocs-verify-web
spec:
  type: ClusterIP
  selector:
    app: ohmydocs-verify-web
  ports:
    - port: 80
      targetPort: 80

Ingress 规则:把 Host 为 web.localhost 的请求全部转发给上面的 Service(这份清单会被真实 apply——规则声明不依赖控制器):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ohmydocs-verify-ing
spec:
  ingressClassName: nginx
  rules:
    - host: web.localhost
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: ohmydocs-verify-web
                port:
                  number: 80

确认 Ingress 资源已被 API Server 接受(ADDRESS 列要等控制器装好后才会填):

kubectl get ingress ohmydocs-verify-ing
kubectl describe ingress ohmydocs-verify-ing | tail -8

自己装控制器的官方命令(kind 专用清单;需要访问 GitHub Raw,受限网络可能失败——脚本已在验证阶段尝试过一次,成败见运行摘要):

# 仅示意:安装 ingress-nginx 控制器(GitHub Raw 清单,网络受限时不可用,由验证脚本统一尝试)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.1/deploy/static/provider/kind/deploy.yaml

控制器可用时的完整验证——带 Host 头访问控制器入口(验证脚本会把控制器的 Service 固定到节点端口 30081,对应建集群时的端口映射),规则命中后返回后端 nginx 首页:

# 依赖: ingress-controller
curl -sf --retry 8 --retry-delay 2 --retry-all-errors -H 'Host: web.localhost' http://localhost:30081/ | head -3

常见坑

  • 只写 Ingress 不装控制器:Ingress 是「规则声明」,没有控制器它永远不生效——ADDRESS 列一直为空就是这个原因。
  • kind 上控制器 Pod 一直 Pending:kind 版清单用 nodeSelector 要求节点带 ingress-ready=true 标签,建集群时没配(或事后忘了 kubectl label node … ingress-ready=true)就永远调度不上。
  • ingressClassName 不匹配:控制器只认领自己 class 的 Ingress;集群有多个控制器时规则必须写对 className。
  • pathType 用错:Prefix 是按路径段匹配前缀(/api 匹配 /api/v1),想要真正的前缀字符串匹配用 ImplementationSpecific;写 / 兜底时别忘了它也会吞掉没匹配到的请求。
  • 在 Ingress 上配了 TLS 但证书 Secret 没建:控制器启动正常但 443 拒绝连接;tls.secretName 指向的 Secret 必须先存在于同命名空间。

小结

Ingress = 七层路由规则的声明,Ingress Controller 才是执行者;host + path 路由到 Service;kind 上用官方 kind 清单装 ingress-nginx。至此流量入口齐了,下一章处理应用的配置:ConfigMap。