一、为什么我的Ingress总是不工作?

最近在帮朋友排查一个Kubernetes集群的问题,他的服务通过Ingress暴露后总是返回404。这让我想起刚接触Kubernetes时,自己也经常被Ingress配置搞得焦头烂额。今天我们就来聊聊这些常见的坑,以及如何优雅地避开它们。

先来看一个典型的错误配置示例(使用Nginx Ingress Controller):

# 错误示例:缺少关键注解导致路由失效
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: broken-ingress
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

这个配置看起来很正常对吧?但实际会出问题,因为它缺少了关键的nginx.ingress.kubernetes.io/rewrite-target注解。当你的服务路径和Ingress路径不一致时,这个注解必不可少。

二、Ingress控制器的核心配置要点

2.1 注解的正确使用方式

不同的Ingress控制器有不同的注解系统。以Nginx Ingress为例,这些注解就像给控制器的小纸条,告诉它该如何处理请求:

# 正确配置示例:带注解的Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: working-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /api/(.*)
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

这里有几个关键点:

  1. rewrite-target确保路径重写正确
  2. ssl-redirect强制HTTPS跳转
  3. 正则捕获组(.*)配合$1使用

2.2 多路径配置的陷阱

很多人在配置多个路径时会遇到路由冲突问题:

# 有问题的多路径配置
paths:
- path: /static
  pathType: Prefix
  backend: {...}
- path: /static/images
  pathType: Prefix
  backend: {...}

这种配置会导致/static/images的请求可能被第一个路径规则捕获。正确的做法是:

# 正确的多路径配置顺序
paths:
- path: /static/images
  pathType: Prefix
  backend: {...}
- path: /static
  pathType: Prefix
  backend: {...}

记住:更具体的路径要放在前面!

三、TLS配置的常见坑

SSL证书配置不当会导致各种奇怪的问题。来看一个完整的TLS配置示例:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-demo
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
  - hosts:
    - myapp.example.com
    secretName: myapp-tls
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 443

常见问题包括:

  1. 忘记创建对应的Secret
  2. 证书过期没有自动续期
  3. 主机名不匹配(证书是给www域名但访问的是非www)

四、调试Ingress问题的实用技巧

当Ingress不工作时,可以按照这个检查清单排查:

  1. 检查Ingress控制器Pod是否运行正常:
kubectl get pods -n ingress-nginx
  1. 查看Ingress控制器的日志:
kubectl logs -n ingress-nginx <ingress-pod-name>
  1. 检查Ingress资源状态:
kubectl describe ingress my-ingress
  1. 验证Service是否存在且Endpoints正确:
kubectl get svc,ep my-service
  1. 使用临时Pod进行网络测试:
kubectl run -it --rm debug --image=busybox -- sh
wget -O- http://my-service

五、高级配置场景解析

5.1 流量切分与金丝雀发布

通过注解可以实现精细的流量控制:

annotations:
  nginx.ingress.kubernetes.io/canary: "true"
  nginx.ingress.kubernetes.io/canary-weight: "20"

这会将20%的流量路由到该Ingress,非常适合渐进式发布。

5.2 自定义错误页面

当后端服务不可用时,可以配置友好的错误页:

annotations:
  nginx.ingress.kubernetes.io/default-backend: default-http-backend
  nginx.ingress.kubernetes.io/custom-http-errors: "503,502"

六、最佳实践总结

经过多次踩坑,我总结了这些经验:

  1. 始终检查kubectl describe ingress的输出
  2. 使用注解时要查阅对应控制器的文档
  3. 复杂的路由规则先在测试环境验证
  4. 监控Ingress控制器的指标和日志
  5. 考虑使用Service Mesh作为更高级的流量管理方案

记住,Kubernetes的配置就像做菜 - 看起来简单的食谱,细节决定成败。希望这些经验能帮你少走弯路!