Kubernetes Nginx Ingress:从入门到精通
在云原生应用日益普及的今天,如何在Kubernetes集群中高效、安全地管理外部流量至关重要。Kubernetes Ingress作为一项关键的API对象,为进入集群的HTTP和HTTPS流量提供了路由规则。在众多Ingress控制器中,Nginx Ingress Controller凭借其卓越的性能、灵活性和丰富的功能集脱颖而出,成为社区中最受欢迎的选择之一。本文将带领您从基础概念出发,逐步深入到高级配置和最佳实践,全面掌握Kubernetes Nginx Ingress Controller。
I. 引言
A. 什么是Kubernetes Ingress?
Kubernetes Ingress是Kubernetes集群中用于定义外部流量如何路由到集群内部服务的API对象。它充当统一的入口点,允许您在单个外部IP地址下暴露多个服务,并根据主机名、URL路径或其他规则来管理流量。
B. 为何选择Nginx Ingress Controller?
Nginx Ingress Controller是Kubernetes Ingress规范的一个实现,它以高性能的Nginx Web服务器作为反向代理和负载均衡器。Nginx以其高效和稳定性而闻名,使其Ingress Controller成为管理微服务流量的可靠选择。其核心功能包括负载均衡、SSL终止、基于URL路径的路由以及通过自定义注解实现扩展功能。
C. Ingress、LoadBalancer与NodePort的对比
Kubernetes提供了多种暴露服务的方式,如NodePort和LoadBalancer服务类型。然而,Ingress为HTTP(S)路由提供了更复杂的解决方案:
* NodePort: 在每个节点的IP地址上通过静态端口暴露服务。它简单易用,但灵活性较低,且占用每个节点上的一个端口。
* LoadBalancer: 为服务提供一个外部云负载均衡器。通常,每个服务可能都需要自己的负载均衡器,这会带来较高的成本。
* Ingress: 提供第7层(HTTP/HTTPS)解决方案,允许单个外部IP地址根据规则(如基于主机的路由、基于路径的路由、TLS终止)管理流向多个服务的流量,这些功能是NodePort或LoadBalancer服务本身不具备的。
II. 入门指南:理解基础
A. 核心概念:Ingress Resource与Ingress Controller
Kubernetes Ingress系统由两个主要组件构成:
* Ingress Resource: 这是一个Kubernetes API对象,您在此定义路由规则。它指定了如何根据主机、路径和协议将传入请求定向到您的服务。
* Ingress Controller: 这是一个运行在Kubernetes集群内部的专用反向代理。它持续监听Ingress资源的变化,并更新其配置(例如,Nginx配置)以实施定义的路由规则。
B. Nginx Ingress Controller的工作原理
Nginx Ingress Controller作为一个控制循环运行。它监视Kubernetes API资源,如Ingress、Service和Secret。当发生变化时,它将这些Kubernetes对象转换为Nginx原生配置文件。为了应用这些更改,Nginx通常需要重新加载其配置。然而,Nginx Ingress Controller旨在通过使用Lua处理器来更新上游配置,从而最大限度地减少停机时间,而无需为端点更改进行完整的Nginx重新加载。
C. 安装
Nginx Ingress Controller可以通过多种方式安装,其中Helm是推荐的流行方法,因其可配置性和生命周期管理能力。
使用Helm安装示例:
1. 添加Nginx Ingress Helm仓库:
bash
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
2. 安装Nginx Ingress Controller:
bash
helm install nginx-ingress ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace
此命令会部署控制器,创建必要的Deployment、Service、ConfigMap以及其他资源。
D. 基本Ingress配置(基于主机和基于路径的路由)
控制器运行后,您可以定义Ingress资源来路由流量。
示例:基于主机的路由
此Ingress将app1.example.com的流量路由到app1-service,将app2.example.com的流量路由到app2-service。
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
spec:
ingressClassName: nginx
rules:
- host: app1.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80
- host: app2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 80
示例:基于路径的路由
此Ingress将example.com/app1的流量路由到app1-service,将example.com/app2的流量路由到app2-service。
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-based-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2 # 对路径路由非常重要
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /app1(/|$)(.*)
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80
- path: /app2(/|$)(.*)
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 80
E. 示例:暴露一个简单的Web应用程序
为了测试,您通常会部署一个简单的Web应用程序(例如,“Hello World”应用)作为一个Deployment,并通过一个Service(例如ClusterIP)暴露它。然后,创建一个指向此Service的Ingress资源。
III. 进阶篇:高级特性与配置
A. TLS终止(SSL/HTTPS)
TLS终止是Ingress Controller解密传入的HTTPS流量,并将未加密的HTTP流量转发到后端服务的D。这集中了证书管理,并减轻了应用程序Pod的加密/解密负担。
- 工作原理: Ingress Controller使用存储在Kubernetes Secrets中的TLS证书来处理HTTPS连接。
-
Secrets和注解配置:
- 创建一个包含您的TLS证书和私钥的Kubernetes Secret。
- 在Ingress资源的
tls部分引用此Secret。 - 使用
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"注解将HTTP重定向到HTTPS。
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- secure.example.com
secretName: example-tls-secret # 包含TLS证书和密钥的Kubernetes Secret
rules:
- host: secure.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-secure-app-service
port:
number: 443 # 如果TLS在Ingress处终止,则为443或80
3. Cert-Manager集成: 对于自动化证书管理(例如Let’s Encrypt),cert-manager通常与Nginx Ingress集成,以自动供应和续订TLS证书。
B. 重写规则
重写规则在将请求URI转发到后端服务之前对其进行修改。当应用程序期望的路径与外部暴露的路径不同时,这特别有用。
nginx.ingress.kubernetes.io/rewrite-target注解: 此注解指定了流量必须重定向到的目标URI。-
路径中的正则表达式: 您可以在Ingress规则的
path字段中使用正则表达式,并结合nginx.ingress.kubernetes.io/use-regex: "true",来捕获URI的一部分并在rewrite-target中使用。捕获组被引用为$1、$2等。yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite-example
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1 # 将$1改为$2,因为(/|$)是第一个捕获组
nginx.ingress.kubernetes.io/use-regex: "true" # 启用路径匹配的正则表达式
spec:
ingressClassName: nginx
rules:
- host: rewrite.example.com
http:
paths:
- path: /app/(.*) # 捕获/app/之后的所有内容到$1
pathType: Prefix
backend:
service:
name: my-backend-service
port:
number: 80
在此示例中,对rewrite.example.com/app/users的请求将在发送到my-backend-service之前被重写为/users。
C. 流量管理
Nginx Ingress Controller提供了多种流量管理功能:
- 负载均衡算法: Nginx支持轮询(默认)、最少连接和IP哈希等算法,以在后端Pod之间分配流量。
- 速率限制: 控制客户端在一段时间内可以发出的请求或连接数量,以保护您的服务免受过载。这可以通过
nginx.ingress.kubernetes.io/limit-conn和nginx.ingress.kubernetes.io/limit-rate等注解进行配置。 - 会话持久性: 确保来自特定客户端的请求始终路由到相同的后端Pod,这对于有状态应用程序非常有用。
D. 自定义Nginx配置
您可以通过多种方式微调Ingress Controller生成的Nginx配置:
- 用于全局设置的ConfigMaps: Nginx Ingress Controller从ConfigMap(通常是其命名空间中的
nginx-configuration)读取适用于所有Ingress的全局Nginx设置。 - 用于特定Ingress规则的注解: 为了实现更细粒度的控制,可以在单个Ingress资源上使用注解来应用特定的Nginx指令。注解的优先级高于ConfigMap设置。例如,
nginx.ingress.kubernetes.io/proxy-read-timeout用于自定义超时,nginx.ingress.kubernetes.io/client-max-body-size用于最大请求体大小。 - 自定义模板: 对于无法通过ConfigMaps或注解实现的特定或复杂配置,您可以向控制器提供自定义Nginx模板。
IV. 精通篇:生产级部署与最佳实践
A. 高可用性与扩缩容
在生产环境中,确保Nginx Ingress Controller具备高可用性和可扩展性至关重要。
- 多个控制器Pod: 部署多个Nginx Ingress Controller副本可确保冗余并防止单点故障。
- 水平Pod自动扩缩(HPA): 配置HPA以根据CPU利用率或其他指标自动扩缩Ingress Controller Pod的数量,使其能够有效处理流量高峰。
- 资源限制: 为Ingress Controller Pod定义适当的CPU和内存请求及限制,以确保稳定的性能并防止资源耗尽。
B. 安全考量
保护您的Ingress对于保护您的应用程序至关重要。
- 外部认证(OAuth、API Keys): Nginx Ingress Controller可以与外部身份验证提供商集成。可以使用
nginx.ingress.kubernetes.io/auth-url和nginx.ingress.kubernetes.io/auth-signin等注解将身份验证委托给外部服务(例如OAuth2 Proxy、Vouch Proxy)。 - IP白名单/黑名单: 使用
nginx.ingress.kubernetes.io/whitelist-source-range等注解限制特定IP地址或CIDR范围对服务的访问。 - 安全的TLS/SSL实践:
- 始终将HTTP重定向到HTTPS。
- 启用HTTP严格传输安全(HSTS)。
- 使用现代密码套件,禁用过时的协议,如SSLv3/TLS 1.0/1.1。
- 使用
cert-manager等工具自动化证书管理。
C. 监控与故障排除
有效的监控和故障排除对于维护健康的Ingress设置至关重要。
- 检查控制器和Ingress日志:
- 控制器日志(
kubectl logs <nginx-controller-pod-name>)显示Ingress规则如何转换为Nginx配置。 - 访问日志显示控制器处理的HTTP请求。
- 控制器日志(
- 描述资源(
kubectl describe): 使用kubectl describe ingress <ingress-name>获取有关Ingress资源的详细信息,包括事件和潜在的错误配置。 - 调试模式(
--v=5): 通过向控制器的参数添加--v=5来增加控制器日志的详细程度,以获取更详细的调试信息。 - 检查生成的Nginx配置: 您可以检查控制器Pod内部的实际Nginx配置文件(
kubectl exec -it <nginx-controller-pod-name> -- cat /etc/nginx/nginx.conf),以验证您的Ingress规则是否正确转换。 - 常见问题:
- 502/504错误: 通常表示后端服务或Nginx耗尽的问题。检查HPA行为和资源限制。
loadBalancer状态为空: 表示Ingress没有分配外部IP或负载均衡器,表明底层云提供商的负载均衡器或Ingress Controller本身存在配置问题。- 网络策略/防火墙: 确保必要的端口已打开,并且网络策略允许Ingress Controller和后端服务之间的流量。
D. Nginx Ingress Controller与Nginx Inc. Ingress Controller
区分社区维护的Nginx Ingress Controller(kubernetes/ingress-nginx)和Nginx Inc. Ingress Controller(nginxinc/kubernetes-ingress)很重要。
* 社区版本: 基于Nginx开源版本,由Kubernetes社区维护。它被广泛使用并拥有强大的社区支持。
* Nginx Inc.版本: 由F5 Nginx开发和维护,提供基于Nginx开源(免费)和基于Nginx Plus(商业)的版本。Nginx Plus版本提供高级功能,如动态重新配置和主动健康检查。
E. Ingress的未来:Gateway API
Kubernetes项目已宣布Ingress API不再积极开发,并且不会对其进行进一步的更改或更新,社区Nginx Ingress Controller计划于2026年3月退役。推荐的现代替代方案是Gateway API,它提供更具表达性和灵活性的流量管理功能。鼓励用户考虑迁移到Gateway API以处理新的或长期的生产工作负载。
V. 结论
Kubernetes Nginx Ingress Controller是管理Kubernetes集群中应用程序外部访问的强大而多功能的工具。通过理解其核心概念,利用TLS终止和重写规则等高级功能,并遵循生产部署和安全的最佳实践,您可以为微服务构建一个健壮、可伸缩和安全的流量管理层。尽管Ingress API正在向Gateway API演进,但Nginx Ingress Controller仍然是许多Kubernetes环境中广泛部署且有价值的组件,为控制入站流量提供了坚实的基础。
希望这篇详细的文章能够帮助您从入门到精通Nginx Ingress!