K8s Ingress实战:从零配置Nginx Ingress Controller,实现基于路径和域名的灵活路由
K8s Ingress实战:从零配置Nginx Ingress Controller,实现基于路径和域名的灵活路由
当你的Kubernetes集群需要对外暴露多个Web服务时,直接使用LoadBalancer或NodePort会面临端口管理混乱、SSL终止繁琐等问题。这时,Ingress就像一位智能交通指挥员,它能根据HTTP请求的路径或域名,将流量精准路由到不同的后端服务。本文将带你从零开始,手把手搭建Nginx Ingress Controller,并通过实际案例演示如何实现灵活的路由规则。
1. 理解Ingress的核心组件
在Kubernetes中,Ingress并不是一个独立的服务,而是一套由多个组件协作的解决方案。要正确使用Ingress,首先需要理清三个核心概念:
- Ingress资源:定义路由规则的K8s对象,相当于"交通规则手册"
- Ingress Controller:实际执行路由的代理服务,相当于"交通警察"
- 后端服务(Service):最终处理请求的应用,相当于"目的地"
常见误区:很多初学者会混淆Ingress资源与Ingress Controller。前者只是声明式的规则定义,后者才是真正处理流量的实体。这就好比交通规则手册本身不会指挥交通,需要交警来具体执行。
目前主流的Ingress Controller实现包括:
- Nginx Ingress Controller(官方维护)
- Traefik
- HAProxy Ingress
- Istio Ingress Gateway
我们选择Nginx版本,因为它:
- 由Kubernetes社区官方维护
- 功能全面且稳定
- 有丰富的注解(Annotation)支持高级配置
2. 部署Nginx Ingress Controller
2.1 快速安装方案
对于大多数生产环境,推荐使用Helm进行安装:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm install ingress-nginx ingress-nginx/ingress-nginx \ --namespace ingress-nginx \ --create-namespace \ --set controller.service.type=LoadBalancer如果集群没有LoadBalancer支持(如本地测试环境),可以改用NodePort:
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=304432.2 验证安装
检查Pod状态:
kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx预期输出应显示READY状态为1/1。
获取外部访问地址:
kubectl get svc -n ingress-nginx如果是云环境,EXTERNAL-IP列会显示负载均衡器的地址;本地环境则使用任意节点IP加NodePort端口。
2.3 重要配置参数
安装时可通过--set调整的关键参数:
| 参数 | 说明 | 示例值 |
|---|---|---|
| controller.service.type | 服务暴露类型 | LoadBalancer/NodePort |
| controller.service.annotations | 云厂商特定注解 | 见各云厂商文档 |
| controller.config.* | Nginx全局配置 | 如proxy-body-size |
| controller.extraArgs | 控制器额外参数 | --enable-ssl-passthrough |
提示:生产环境建议配置资源请求/限制,如--set controller.resources.requests.cpu=500m
3. 配置Ingress路由规则
3.1 基础路径路由
假设我们有两个服务:
- frontend:处理/web路径的流量
- backend:处理/api路径的流量
对应的Ingress配置如下:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress spec: rules: - http: paths: - path: /web pathType: Prefix backend: service: name: frontend port: number: 80 - path: /api pathType: Prefix backend: service: name: backend port: number: 80关键字段说明:
pathType:支持Exact(精确匹配)、Prefix(前缀匹配)和ImplementationSpecificbackend:指定目标Service及其端口
3.2 基于域名的虚拟主机
如果需要支持多个域名,可以这样配置:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: multi-host-ingress spec: rules: - host: shop.example.com http: paths: - path: / pathType: Prefix backend: service: name: shop port: number: 80 - host: blog.example.com http: paths: - path: / pathType: Prefix backend: service: name: blog port: number: 803.3 路径重写实战案例
当后端服务的URL路径与Ingress路径不一致时,需要使用重写功能。例如,将/app请求转发到后端的/路径:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rewrite-example annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - http: paths: - path: /app(/|$)(.*) pathType: Prefix backend: service: name: my-app port: number: 80这个配置会:
- 匹配以/app开头的请求
- 将请求路径中的/app替换为/
- $2表示捕获的第二个分组(.*)
4. 高级配置与优化
4.1 常用注解(Annotations)
Nginx Ingress提供了丰富的注解来实现高级功能:
| 注解 | 功能 | 示例值 |
|---|---|---|
| nginx.ingress.kubernetes.io/affinity | 启用会话保持 | cookie |
| nginx.ingress.kubernetes.io/proxy-body-size | 请求体大小限制 | 20m |
| nginx.ingress.kubernetes.io/ssl-redirect | 强制HTTPS跳转 | "true" |
| nginx.ingress.kubernetes.io/configuration-snippet | 自定义Nginx配置 | 见下文 |
配置片段示例:
annotations: nginx.ingress.kubernetes.io/configuration-snippet: | if ($host = 'example.com') { return 301 https://www.example.com$request_uri; }4.2 流量切分与金丝雀发布
通过注解可以实现按权重的流量分配:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: canary-demo annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "30" spec: rules: - http: paths: - path: / pathType: Prefix backend: service: name: new-version port: number: 80这会将30%的流量路由到new-version服务,剩余70%走默认Ingress规则。
4.3 性能优化实践
对于高流量场景,建议调整以下参数:
controller: config: # 每个worker进程保持的最大连接数 worker-connections: "10000" # 启用长连接 keep-alive: "75" # 缓冲区大小 proxy-buffer-size: "16k" # 最大请求体大小 proxy-body-size: "20m" resources: limits: cpu: "2" memory: "2Gi" requests: cpu: "1" memory: "1Gi"5. 常见问题排查指南
5.1 诊断工具与命令
查看Ingress事件:
kubectl describe ingress <ingress-name>检查Nginx配置:
kubectl exec -n ingress-nginx <ingress-pod> -- cat /etc/nginx/nginx.conf实时日志监控:
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100 -f5.2 典型问题解决方案
问题1:404错误但后端服务正常
- 检查Ingress的pathType是否匹配预期
- 验证后端服务的健康检查路径是否正确
问题2:SSL证书不生效
- 确保证书Secret与Ingress在同一命名空间
- 检查证书是否过期
- 验证Ingress的tls字段配置正确
问题3:上传大文件失败
- 增加proxy-body-size注解值
- 调整client_max_body_size配置
问题4:WebSocket连接断开
- 添加以下注解:
annotations: nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" nginx.ingress.kubernetes.io/websocket-services: "my-websocket-svc"
5.3 监控与告警配置
建议为Ingress Controller配置以下监控指标:
- 请求率(nginx_ingress_controller_requests)
- 响应时间(nginx_ingress_controller_response_duration_seconds)
- 错误率(nginx_ingress_controller_requests)
示例Prometheus告警规则:
- alert: HighErrorRate expr: rate(nginx_ingress_controller_requests{status=~"5.."}[1m]) / rate(nginx_ingress_controller_requests[1m]) > 0.05 for: 5m labels: severity: critical annotations: summary: "High error rate on {{ $labels.ingress }}" description: "5xx error rate is {{ printf \"%.2f\" $value }}%"在实际项目中,我发现最常遇到的问题往往是路径匹配规则配置不当。例如,忘记设置pathType导致路径匹配不符合预期,或者重写规则写错导致后端收到错误的URL。建议在测试环境充分验证路由规则后再部署到生产环境。
