1. Ingress-nginx动态路由配置实战

第一次接触Ingress-nginx时,我完全被它复杂的配置搞懵了。直到在实际项目中踩过几次坑后,才发现它的动态路由配置其实比传统Nginx方便得多。想象一下,你有个电商平台需要根据不同商品类别做路由分发:/electronics该走A服务,/clothing该走B服务。传统方式得手动改Nginx配置然后reload,而在Kubernetes里,只需要一个YAML文件就能自动生效。

动态路由的核心在于Ingress资源的rules配置。举个实际案例,这是我上周给物流系统做的路由规则:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: logistics-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: logistics.example.com
    http:
      paths:
      - path: /tracking/(.*)
        pathType: Prefix
        backend:
          service:
            name: tracking-service
            port: 
              number: 8080
      - path: /warehouse/(.*)
        pathType: Prefix
        backend:
          service:
            name: warehouse-service
            port: 
              number: 8081

这个配置实现了:

  • 访问logistics.example.com/tracking/xxx 自动路由到tracking-service
  • 访问logistics.example.com/warehouse/xxx 自动路由到warehouse-service

关键点在于pathType的三种类型:

  • Prefix:前缀匹配(最常用)
  • Exact:精确匹配
  • ImplementationSpecific:依赖具体实现

实测发现个坑:当同时存在多条规则时,匹配顺序是从长到短。有次配置了/api/api/v2两条规则,结果短的先匹配了,调了半天才发现是顺序问题。

2. 外部访问的完整链路解析

很多新手会困惑:为什么配了Ingress还是无法外部访问?这得从整个请求链路说起。上周帮同事排查问题时,我画了张链路图:

外部用户 -> 节点IP:NodePort -> Ingress Controller Service -> Ingress Controller Pod -> 目标Service -> 目标Pod

关键组件协作流程:

  1. NodePort Service:在集群所有节点开放端口(默认30000-32767)
  2. Ingress Controller:持续监听Ingress资源变更
  3. 目标Service:需要确保selector能匹配到后端Pod

常见问题排查步骤:

  1. 检查NodePort是否生效:
    kubectl get svc -n ingress-nginx
    curl <节点IP>:<NodePort>
    
  2. 验证Ingress配置是否注入:
    kubectl exec -n ingress-nginx <ingress-controller-pod> -- cat /etc/nginx/nginx.conf
    
  3. 测试后端服务是否可达:
    kubectl port-forward svc/<target-service> 8080:80
    curl localhost:8080
    

遇到过最头疼的问题是浏览器访问一直504,最后发现是后端Pod的readinessProbe配置错误,导致流量无法到达。建议新手一定要学会用kubectl describe ingress查看事件日志。

3. 生产环境最佳实践

经过多个项目的锤炼,我总结出这些实战经验:

高可用配置方案:

  • 至少部署2个Ingress Controller副本
  • 使用PodAntiAffinity避免副本集中在同一节点
  • 资源限制建议:
    resources:
      limits:
        cpu: "2"
        memory: 2Gi
      requests:
        cpu: "1"
        memory: 1Gi
    

性能调优参数:

annotations:
  nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
  nginx.ingress.kubernetes.io/proxy-read-timeout: "1800"
  nginx.ingress.kubernetes.io/proxy-body-size: "20m"
  nginx.ingress.kubernetes.io/upstream-keepalive-connections: "100"

SSL证书配置:

  1. 创建TLS secret:
    kubectl create secret tls my-tls \
      --cert=path/to/cert.pem \
      --key=path/to/key.pem
    
  2. 在Ingress中引用:
    spec:
      tls:
      - hosts:
        - mydomain.com
        secretName: my-tls
    

曾有个项目因为没加HSTS头导致安全评分不合格,后来通过这个annotation解决:

nginx.ingress.kubernetes.io/hsts: "max-age=63072000; includeSubdomains; preload"

4. 常见故障排查指南

遇到问题别慌,按这个checklist逐步排查:

问题1:访问返回502 Bad Gateway

  • 检查后端服务是否正常运行
  • 查看Ingress Controller日志:
    kubectl logs -n ingress-nginx <pod-name>
    
  • 验证Service的selector是否匹配Pod标签

问题2:修改Ingress后配置不生效

  • 检查Ingress Controller是否监听了正确namespace
  • 查看Ingress资源事件:
    kubectl describe ingress <ingress-name>
    
  • 手动删除Ingress Controller Pod触发重建

问题3:端口冲突无法绑定 修改kube-apiserver配置:

spec:
  containers:
  - command:
    - kube-apiserver
    - --service-node-port-range=1-65535

然后重启kubelet:

systemctl daemon-reload
systemctl restart kubelet

有个记忆深刻的案例:客户坚持要用80端口,但修改后仍然报错。后来发现是安全组没放行,白白折腾了半天。建议新手一定要先检查网络基础配置。

5. 进阶技巧:金丝雀发布配置

通过Ingress实现灰度发布简直不要太方便。这是我常用的金丝雀配置:

annotations:
  nginx.ingress.kubernetes.io/canary: "true"
  nginx.ingress.kubernetes.io/canary-weight: "30"
  nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
  nginx.ingress.kubernetes.io/canary-by-cookie: "canary"

这个配置表示:

  • 30%流量走金丝雀版本
  • 带X-Canary头的请求走金丝雀
  • 有canary cookie的走金丝雀

配合Helm可以实现更复杂的发布策略。有次上线新功能时,我们先给内部员工开启cookie,测试无误后再逐步放量,整个过程用户完全无感知。

6. 监控与日志收集方案

生产环境必须做好监控,推荐配置:

Prometheus监控:

annotations:
  prometheus.io/scrape: "true"
  prometheus.io/port: "10254"

关键监控指标:

  • nginx_connections_total
  • nginx_requests_total
  • upstream_response_latency

日志收集建议:

  • 将访问日志输出到stdout
  • 使用Fluentd或Filebeat收集
  • 重要字段:
    $remote_addr - $http_host - $request - $status
    $body_bytes_sent - $http_referer
    $http_user_agent - $request_time
    

曾经因为没监控,直到用户投诉才发现某个路由的延迟飙升。现在我们的告警规则是这样的:

  • 5分钟内5xx错误率>1%
  • 平均延迟>500ms
  • 带宽使用>80%阈值

更多推荐