从零构建生产级Kubernetes Ingress网关:Nginx Controller实战与选型指南
当你第一次在Kubernetes集群中部署服务时,最令人困惑的问题之一就是:"外部用户如何访问我的应用?" 三年前我刚接触K8s时,曾天真地以为只需创建一个Deployment,世界就能自动访问我的服务。直到面对NodePort的随机端口、LoadBalancer的天价账单,以及各种Ingress方案的术语轰炸,才明白服务暴露原来是个技术活。本文将带你绕过我踩过的坑,用最实用的方式掌握Ingress的核心玩法。
1. 为什么需要Ingress Controller?
想象你正在运营一个电商平台,前端、订单、支付等服务都部署在Kubernetes集群中。如果直接用NodePort暴露服务,用户需要记住:
- 商品服务:node1:30001
- 支付服务:node2:30002
- 推荐服务:node3:30003
这显然不现实。而LoadBalancer方案虽然能提供固定IP,但当你有20个微服务时,云厂商的账单会让你心跳加速。这就是Ingress Controller的价值所在——它像一位智能门卫,通过域名和路径区分流量,只需一个入口IP就能路由所有服务。
主流Ingress方案对比:
| 方案 | 协议层 | 典型实现 | 适用场景 | 性能损耗 |
|---|---|---|---|---|
| NodePort | L4 | Kube-proxy | 开发测试环境 | 15-20% |
| LoadBalancer | L4 | 云厂商SLB | 生产环境独立服务 | 10-15% |
| Ingress | L7 | Nginx/Traefik | 生产环境多服务路由 | 5-8% |
提示:L4负载均衡基于IP+端口,L7则能识别HTTP/HTTPS协议内容,实现基于域名、URL路径的路由
2. 部署Nginx Ingress Controller
2.1 Helm安装方案(推荐)
对于大多数生产环境,Helm是最便捷的部署方式。以下命令将创建一个专属命名空间并安装最新稳定版:
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.replicaCount=3 \ --set controller.nodeSelector."kubernetes\.io/os"=linux \ --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux关键参数说明:
replicaCount=3:确保高可用,至少部署3个副本nodeSelector:限定节点调度范围- 默认会创建LoadBalancer类型的Service(云环境自动分配公网IP)
2.2 裸金属环境部署
如果没有云厂商的LoadBalancer,可以使用HostNetwork模式直接绑定节点网络:
# nginx-ingress-daemonset.yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: ingress-nginx-controller spec: template: spec: hostNetwork: true containers: - name: controller ports: - containerPort: 80 hostPort: 80 - containerPort: 443 hostPort: 443部署后,直接访问节点IP的80/443端口即可,但要注意:
- 需要确保节点有固定IP
- 同一节点只能运行一个Ingress Pod
- 建议配合nodeSelector定向调度
3. 配置Ingress路由规则
3.1 基础域名路由
假设我们有两个服务需要暴露:
- 前端服务:frontend-svc(端口8080)
- API服务:api-svc(端口3000)
对应的Ingress配置如下:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: main-ingress spec: rules: - host: "shop.example.com" http: paths: - path: / pathType: Prefix backend: service: name: frontend-svc port: number: 8080 - host: "api.example.com" http: paths: - path: / pathType: Prefix backend: service: name: api-svc port: number: 30003.2 高级路径重写
某些前端框架可能需要路径重写:
annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 rules: - http: paths: - path: /api(/|$)(.*) backend: service: name: api-svc port: number: 3000这会将/api/users重写为/users转发到后端服务
4. TLS证书配置
4.1 自动证书签发(Let's Encrypt)
使用cert-manager实现自动化HTTPS:
# 安装cert-manager helm install cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1.8.0 \ --set installCRDs=true # 创建ClusterIssuer apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: email: admin@example.com server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx然后在Ingress中添加注解:
metadata: annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: tls: - hosts: - shop.example.com secretName: shop-tls4.2 自定义证书
如果有自购证书,可直接创建Secret:
kubectl create secret tls custom-tls \ --cert=fullchain.pem \ --key=privkey.pem \ --namespace=default在Ingress中引用:
spec: tls: - hosts: - shop.example.com secretName: custom-tls5. 性能优化实战技巧
5.1 调优参数示例
在Helm values.yaml中配置:
controller: config: # 保持长连接 keep-alive: "75" keep-alive-requests: "100" # 缓冲区优化 proxy-buffer-size: "16k" proxy-buffers-number: "4" # 超时设置 proxy-read-timeout: "60" proxy-send-timeout: "60"5.2 监控与日志
启用Prometheus监控:
controller: metrics: enabled: true serviceMonitor: enabled: true查看实时日志:
kubectl logs -n ingress-nginx \ -l app.kubernetes.io/name=ingress-nginx \ --tail=100 -f6. 多Ingress Controller选型
当Nginx不能满足需求时,可以考虑:
Traefik优势:
- 自动服务发现
- 内置Dashboard
- 更轻量级
Contour特点:
- 基于Envoy构建
- 支持gRPC原生路由
- 更精细的流量策略
部署Traefik示例:
helm install traefik traefik/traefik \ --namespace traefik \ --create-namespace \ --set ports.websecure.http.tls.enabled=true \ --set dashboard.enabled=true选择建议:
- 需要丰富功能选Nginx
- 追求易用性选Traefik
- 处理gRPC流量选Contour
7. 常见故障排查
问题1:Ingress规则不生效
- 检查Controller日志是否有错误
- 确认Ingress Class配置正确
- 验证后端服务Endpoints是否健康
问题2:HTTPS证书异常
- 检查cert-manager Pod状态
- 查看Certificate资源事件
- 验证DNS解析是否正确
诊断命令:
# 查看Ingress状态 kubectl get ingress -o wide # 检查后端服务 kubectl describe svc my-service # 测试端口连通性 kubectl run -it --rm debug \ --image=nicolaka/netshoot -- bash curl -v http://service:port记得第一次配置Ingress时,我因为忘记在DNS解析中添加记录,花了三小时排查"为什么访问返回404"。现在每次部署新服务,都会先确认:
- DNS解析是否生效
- Service端口是否匹配
- Ingress注解是否正确
这些经验让我再也没犯过同样的错误。