Service 的 NodePort 方式需要记住端口号,且无法做基于域名的路由。Ingress 解决了这个问题 — 它充当集群的七层入口,根据域名和路径将流量转发到不同的 Service。

1. Ingress 工作原理

Ingress 由两部分组成:

  • Ingress Controller — 实际执行反向代理的 Pod(如 Ingress-Nginx)
  • Ingress 资源 — 定义路由规则的 K8s 对象(域名→路径→Service 的映射)

简言之:外部请求 → Ingress Controller(根据 Ingress 规则匹配)→ 内部 Service → Pod

2. 安装 Ingress-Nginx 控制器

2.1 通过 Helm 安装(推荐)

# 添加 ingress-nginx 仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# 安装
helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --create-namespace \
  --set controller.service.type=NodePort \
  --set controller.service.nodePorts.http=30080 \
  --set controller.service.nodePorts.https=30443

2.2 验证安装

kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

# 输出类似:
# NAME                                 TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)
# ingress-nginx-controller             NodePort   10.96.x.x              80:30080/TCP,443:30443/TCP

3. 第一个 Ingress 规则

3.1 准备后端服务

# 部署两个示例应用
kubectl create deployment web1 --image=nginx:1.25 --replicas=2
kubectl create deployment web2 --image=httpd:2.4 --replicas=2

kubectl expose deployment web1 --port=80
kubectl expose deployment web2 --port=80

3.2 编写 Ingress 规则

创建 ingress-demo.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-demo
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: web1.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web1
            port:
              number: 80
  - host: web2.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web2
            port:
              number: 80
kubectl apply -f ingress-demo.yaml

3.3 测试访问

# 本地修改 /etc/hosts 将域名指向节点 IP
# 192.168.1.102 web1.example.com web2.example.com

curl -H "Host: web1.example.com" http://192.168.1.102:30080
# 返回 Nginx 欢迎页

curl -H "Host: web2.example.com" http://192.168.1.102:30080
# 返回 Apache 欢迎页

4. 路径路由与正则匹配

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-routing
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /api(/|$)(.*)          # /api → backend-api
        pathType: ImplementationSpecific
        backend:
          service:
            name: backend-api
            port:
              number: 8080
      - path: /                      # / → frontend
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 80

5. HTTPS 配置

5.1 生成TLS证书(自签名示例)

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=myapp.example.com"

# 创建 Secret
kubectl create secret tls myapp-tls --key tls.key --cert tls.crt

5.2 添加 TLS 配置到 Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - myapp.example.com
    secretName: myapp-tls
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp
            port:
              number: 80
生产环境建议使用 cert-manager 自动签发 Let's Encrypt 免费证书,后文会单独介绍。

6. 常用 Annotations

Annotation作用示例
rewrite-target重写 URL 路径/
ssl-redirect强制 HTTP→HTTPS 跳转"true"
proxy-body-size请求体大小限制"50m"
proxy-read-timeout后端响应超时"60"
rate-limit限制请求速率"100"
cors-allow-originCORS 跨域配置"https://example.com"

7. Ingress vs Gateway API

Ingress 是当前最广泛使用的方案,Kubernetes 社区正在推进 Gateway API(前身为 Istio/Mesh 中的 Gateway):

特性IngressGateway API
角色分离不支持✅ 基础设施管理者 vs 应用开发者
TLS 管理基础支持更灵活的策略绑定
流量切分需 annotation✅ 原生支持权重路由
成熟度GAbeta → 逐步 GA

8. 完整部署流程总结

# 1. 安装 Ingress Controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx --create-namespace \
  --set controller.service.type=NodePort

# 2. 部署后端应用并暴露 Service
kubectl create deployment myapp --image=nginx --replicas=2
kubectl expose deployment myapp --port=80

# 3. 创建 TLS Secret
kubectl create secret tls myapp-tls --key=tls.key --cert=tls.crt

# 4. 编写并应用 Ingress 规则
kubectl apply -f ingress-demo.yaml

# 5. 验证
kubectl get ingress
kubectl describe ingress ingress-demo

# 6. 访问测试
curl -k https://myapp.example.com:30443

9. 排错指南

现象排查方向
503 Service Unavailable后端 Service 名称拼写错误或 Endpoints 为空
404 Not_foundIngress 规则中 host/path 不匹配
证书错误Secret 不在同一命名空间或 tls 配置有误
Ingress 规则不生效检查 ingressClassName 和控制器的 watch 命名空间