<blockquote>
原文链接:从 Ingress-NGINX Controller 迁移至 NGINX Ingress Controller
转载来源:NGINX 开源社区
NGINX 唯一中文官方社区 ,尽在 nginx.org.cn
本文介绍如何从社区维护的 Ingress-NGINX Controller 迁移到 F5 提供的 NGINX Ingress Controller。
概述
本页将介绍两种从社区维护的 Ingress-NGINX Controller 项目迁移到 NGINX Ingress Controller 的方法:使用 NGINX 的 Ingress 资源,或使用 Kubernetes 内置的 Ingress 资源。这样做通常是因为两者在实现上存在差异,并且可以利用例如 NGINX Plus 集成等功能。之所以提供两条路径,是因为两者在实现方式上不同,同时也为了让你能使用更多高级功能(例如 NGINX Plus 集成)。
本指南中的内容摘自免费电子书《Kubernetes Ingress Controller Deployment and Security with NGINX》,可在 NGINX Library 下载。
开始之前
要完成本指南中的步骤,你需要具备以下条件:
• 了解 Ingress Controller 的基本工作原理。
• 在与现有 Ingress-NGINX Controller 相同的主机上已安装 NGINX Ingress Controller。
从社区版 Ingress-NGINX 迁移到 NGINX Ingress Controller,主要有两种方式:
• 使用 NGINX Ingress Resources
• 使用 Kubernetes Ingress Resources
使用 NGINX Ingress Resources 进行迁移
采用这种迁移方式,会先用 Kubernetes Ingress Resources来设置root权限,再通过 NGINX 的自定义资源(CRDs)完成配置,包括:
• VirtualServer and VirtualServerRoute
• TransportServer
• GlobalConfiguration
• Policy
配置 SSL 终止和基于 HTTP 路径的路由
下面展示的两个示例,分别对应 Kubernetes Ingress Resource和 NGINX VirtualServer Resource。虽然写法和结构不同,但实现的都是相同的基本 Ingress 功能,用于配置 SSL 终止与七层路径路由。
Kubernetes Ingress Resource:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-test
spec:
tls:
- hosts:
- foo.bar.com
secretName: tls-secret
rules:
- host: foo.bar.com
http:
paths:
- path: /login
backend:
serviceName: login-svc
servicePort: 80
- path: /billing
serviceName: billing-svc
servicePort: 80
NGINX VirtualServer Resource:
apiVersion: networking.k8s.io/v1
kind: VirtualServer
metadata:
name: nginx-test
spec:
host: foo.bar.com
tls:
secret: tls-secret
upstreams:
- name: login
service: login-svc
port: 80
- name: billing
service: billing-svc
port: 80
routes:
- path: /login
action:
pass: login
- path: /billing
action:
pass: billing
配置 TCP/UDP 负载均衡与 TLS 透传
NGINX Ingress Controller 使用 TransportServer 和 GlobalConfiguration 资源来暴露 TCP 和 UDP 服务。这些资源为 TCP/UDP 和 TLS 透传负载均衡提供了丰富的配置选项。相比之下,社区版 Ingress-NGINX Controller 则通过 Kubernetes 的 ConfigMap 对象来暴露 TCP/UDP 服务。
将 Ingress-NGINX Controller 的注解转换为 NGINX Ingress 资源
Kubernetes 部署中,经常需要在基本的 Ingress 规则上扩展高级用例,例如金丝雀发布、蓝绿部署、流量限速,以及进出流量管控。社区版 Ingress-NGINX Controller 主要通过 Kubernetes 注解和自定义 Lua 扩展来实现这些功能。
这些自定义 Lua 扩展针对特定的 NGINX Ingress 资源定义,但在处理高级用例时可能无法提供足够的细粒度。下面的示例展示了如何将这些注解转换为 NGINX Ingress Controller Resources。
金丝雀部署
金丝雀部署和蓝绿部署可以在不影响现有用户的前提下,将代码更新到生产环境。NGINX Ingress Controller 在数据平面上运行这些部署;要从社区版 Ingress-NGINX Controller 迁移,必须将其注解映射到 VirtualServer 和 VirtualServerRoute 资源上。
Ingress-NGINX Controller 按以下顺序解析金丝雀注解:
1. nginx.ingress.kubernetes.io/canary-by-header
2. nginx.ingress.kubernetes.io/canary-by-cookie
3. nginx.ingress.kubernetes.io/canary-by-weight
为了让 NGINX Ingress Controller 以相同方式处理它们,这些注解在 VirtualServer 或 VirtualServerRoute 清单中必须按相同顺序出现。
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "httpHeader"
NGINX Ingress Controller:
matches:
- conditions:
- header: httpHeader
value: never
action:
pass: echo
- header: httpHeader
value: always
action:
pass: echo-canary
action:
pass: echo
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "httpHeader"
nginx.ingress.kubernetes.io/canary-by-header-value: "my-value"
NGINX Ingress Controller:
matches:
- conditions:
- header: httpHeader
value: my-value
action:
pass: echo-canary
action:
pass: echo
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "cookieName"
NGINX Ingress Controller:
matches:
- conditions:
- cookie: cookieName
value: never
action:
pass: echo
- cookie: cookieName
value: always
action:
pass: echo-canary
action:
pass: echo
流量控制
使用微服务的环境通常会采用广泛的流量控制策略,通过断路器、限流和连接限制来管理临时性应用,以防止由于不健康状态或异常行为引起的错误情况。
下面的示例展示了如何将 Ingress-NGINX Controller 的注解映射到 NGINX VirtualServer 和 VirtualServerRoute 资源,以实现限流、自定义 HTTP 错误、自定义默认后端以及 URI 重写。
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/custom-http-errors: "code"
nginx.ingress.kubernetes.io/default-backend: "default-svc"
NGINX Ingress Controller:
errorPages:
- codes: [code]
redirect:
code: 301
url: default-svc
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/limit-connections: "number"
NGINX Ingress Controller:
http-snippets: |
limit_conn_zone $binary_remote_addr zone=zone_name:size;
routes:
- path: /path
location-snippets: |
limit_conn zone_name number;
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/limit-rate: "number"
nginx.ingress.kubernetes.io/limit-rate-after: "number"
NGINX Ingress Controller:
location-snippets: |
limit_rate number;
limit_rate_after number;
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/limit-rpm: "number"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "multiplier"
NGINX Ingress Controller:
rateLimit:
rate: number/m
burst: number * multiplier
key: ${binary_remote_addr}
zoneSize: size
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/limit-rps: "number"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "multiplier"
NGINX Ingress Controller:
rateLimit:
rate: number/s
burst: number * multiplier
key: ${binary_remote_addr}
zoneSize: size
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/limit-whitelist: "CIDR"
NGINX Ingress Controller:
http-snippets: |
server-snippets: |
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/rewrite-target: "URI"
NGINX Ingress Controller:
rewritePath: "URI"
有四个 Ingress-NGINX Controller 注解尚未对应到 NGINX Ingress 资源字段:必须通过 snippets 来处理。
• nginx.ingress.kubernetes.io/limit-connections
• nginx.ingress.kubernetes.io/limit-rate
• nginx.ingress.kubernetes.io/limit-rate-after
• nginx.ingress.kubernetes.io/limit-whitelist
请求头操作
操作 HTTP Header 在很多场景下都很有用,因为它们包含了参与 HTTP 事务系统所需的重要信息。社区版 Ingress-NGINX Controller 支持启用和配置跨域资源共享(CORS)相关的请求头,常用于 AJAX 应用程序,其中前端 JavaScript 代码与后端应用或 Web 服务器交互。
下方代码示例展示了如何将 Ingress-NGINX 注解对应到 NGINX Ingress Controller 的 VirtualServer 和 VirtualServerRoute 资源。
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-allow-headers: "X-Forwarded-For"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-max-age: "seconds"
NGINX Ingress Controller:
responseHeaders:
add:
- name: Access-Control-Allow-Credentials
value: "true"
- name: Access-Control-Allow-Headers
value: "X-Forwarded-For"
- name: Access-Control-Allow-Methods
value: "PUT, GET, POST, OPTIONS"
- name: Access-Control-Allow-Origin
value: "*"
- name: Access-Control-Max-Age
value: "seconds"
代理与负载均衡
NGINX Ingress Controller 提供多种代理和负载均衡功能,可根据具体使用场景进行配置,例如选择负载均衡算法,以及代理连接的超时和缓冲设置。
下表展示了 Ingress-NGINX Controller 注解如何映射到 VirtualServer 和 VirtualServerRoute 资源中的 upstream 字段,这些字段涵盖负载均衡、代理超时、代理缓冲以及服务 ClusterIP 地址和端口的连接路由。
接路由。
| Ingress-NGINX Controller | NGINX Ingress Controller |
| nginx.ingress.kubernetes.io/load-balance | b-method |
| nginx.ingress.kubernetes.io/proxy-buffering | buffering |
| nginx.ingress.kubernetes.io/proxy-buffers-number | buffers |
| nginx.ingress.kubernetes.io/proxy-buffer-size | buffers |
| nginx.ingress.kubernetes.io/proxy-connect-timeout | connect-timeout |
| nginx.ingress.kubernetes.io/proxy-next-upstream | next-upstream |
| nginx.ingress.kubernetes.io/proxy-next-upstream-timeout | next-upstream-timeout |
| nginx.ingress.kubernetes.io/proxy-read-timeout | read-timeout |
| nginx.ingress.kubernetes.io/proxy-send-timeout | send-timeout |
| nginx.ingress.kubernetes.io/service-upstream | use-cluster-ip |
mTLS 认证
mTLS 认证是一种对进出集群的流量(南北向流量)执行双向身份验证的方法。这种安全的通信方式在服务网格中很常见,尤其用于严格的零信任环境。
NGINX Ingress Controller 层能够通过为外部连接提供有效证书来实现终端系统的 mTLS 认证。它通过 Policy 资源完成配置,这些资源对应于 Ingress-NGINX Controller 中的客户端证书认证和后端证书认证注解。
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/auth-tls-secret: secretName
nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
NGINX Ingress Controller:
ingressMTLS:
clientCertSecret: secretName
verifyClient: "on"
verifyDepth: 1
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/proxy-ssl-secret: "secretName"
nginx.ingress.kubernetes.io/proxy-ssl-verify: "on|off"
nginx.ingress.kubernetes.io/proxy-ssl-verify-depth: "1"
nginx.ingress.kubernetes.io/proxy-ssl-protocols: "TLSv1.2"
nginx.ingress.kubernetes.io/proxy-ssl-ciphers: "DEFAULT"
nginx.ingress.kubernetes.io/proxy-ssl-name: "server-name"
nginx.ingress.kubernetes.io/proxy-ssl-server-name: "on|off"
NGINX Ingress Controller:
egressMTLS:
tlsSecret: secretName
verifyServer: true|false
verifyDepth: 1
protocols: TLSv1.2
ciphers: DEFAULT
sslName: server-name
serverName: true|false
使用 NGINX Plus 的会话保持
使用 NGINX Plus,你可以通过 Policy 资源实现会话保持(session persistence),这与社区版 Ingress-NGINX Controller 使用的注解相对应。
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "cookieName"
nginx.ingress.kubernetes.io/session-cookie-expires: "x"
nginx.ingress.kubernetes.io/session-cookie-path: "/route"
nginx.ingress.kubernetes.io/session-cookie-secure: "true"
NGINX Ingress Controller:
sessionCookie:
enable: true
name: cookieName
expires: xh
path: /route
secure: true
使用 Kubernetes Ingress 资源进行迁移
从社区版 Ingress-NGINX Controller 迁移到 NGINX Ingress Controller 的另一种方式是仅使用标准 Kubernetes 资源中的注解和 ConfigMap,可能还会依赖可合并的 Ingress 类型。
这种方式可以确保所有配置都保存在 Ingress 对象中。
警告
如果采用这种迁移方式,应避免修改 Ingress 资源的 spec 字段。Ingress-NGINX Controller 与 NGINX Ingress Controller 的实现略有不同:修改 Kubernetes Ingress 可能会导致兼容性问题。
使用注解的高级配置
下表将 Ingress-NGINX Controller 的注解映射到 NGINX Ingress Controller 的等效注解,以及对应的 NGINX 指令。
| Ingress-NGINX Controller | NGINX Ingress Controller | NGINX 指令 |
| nginx.ingress.kubernetes.io/configuration-snippet | nginx.org/location-snippets | N/A |
| nginx.ingress.kubernetes.io/load-balance (1) | nginx.org/lb-method | random two least_conn |
| nginx.ingress.kubernetes.io/proxy-buffering | nginx.org/proxy-buffering | proxy_buffering |
| nginx.ingress.kubernetes.io/proxy-buffers-number | nginx.org/proxy-buffers | proxy_buffers |
| nginx.ingress.kubernetes.io/proxy-buffer-size | nginx.org/proxy-buffer-size | proxy_buffer_size |
| nginx.ingress.kubernetes.io/proxy-busy-buffers-size | nginx.org/proxy-busy-buffers-size | proxy_busy_buffers_size |
| nginx.ingress.kubernetes.io/proxy-connect-timeout | nginx.org/proxy-connect-timeout | proxy_connect_timeout |
| nginx.ingress.kubernetes.io/proxy-read-timeout | nginx.org/proxy-read-timeout | proxy_read_timeout |
| nginx.ingress.kubernetes.io/proxy-send-timeout | nginx.org/proxy-send-timeout | proxy_send_timeout |
| nginx.ingress.kubernetes.io/rewrite-target | nginx.org/rewrites | rewrite |
| nginx.ingress.kubernetes.io/server-snippet | nginx.org/server-snippets |
N/A |
| nginx.ingress.kubernetes.io/ssl-redirect | ingress.kubernetes.io/ssl-redirect | N/A (2) |
1. Ingress-NGINX Controller 使用 Lua 实现部分负载均衡算法,而这些算法在 NGINX Ingress Controller 中可能没有对应实现。
2. 要将 HTTP(80)流量重定向到 HTTPS(443),NGINX Ingress Controller 使用内置的 NGINX if 条件,而 Ingress-NGINX Controller 则使用 Lua。
以下两个代码片段展示了 Ingress-NGINX Controller 注解,及其在 NGINX Ingress Controller(使用 NGINX Plus 时)的对应注解。
Ingress-NGINX Controller:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "cookie_name"
nginx.ingress.kubernetes.io/session-cookie-expires: "seconds"
nginx.ingress.kubernetes.io/session-cookie-path: "/route"
NGINX Ingress Controller (with NGINX Plus):
nginx.com/sticky-cookie-services: "serviceName=example-svc cookie_name expires=time path=/route"
NGINX Ingress Controller 对使用 NGINX Plus 的功能提供了额外的注解,这些功能在 Ingress-NGINX Controller 中没有对应实现,例如主动健康检查和基于 JSON Web Token (JWT) 的认证。
下表展示了启用后端(上游)服务的 TLS 和 gRPC 协议时,注解的对应转换方法。
| Ingress-NGINX Controller | NGINX Ingress Controller |
| nginx.ingress.kubernetes.io/backend-protocol: “HTTPS” | nginx.org/ssl-services: “ssl_service_name” |
| nginx.ingress.kubernetes.io/backend-protocol: “GRPC” | nginx.org/grpc-services: “grpc_service_name” |
| nginx.ingress.kubernetes.io/backend-protocol: “GRPCS” | nginx.org/ssl-services: “grpc_service_name” nginx.org/grpc-services: “grpc_service_name” |
重要提示:
GRPC 服务必须使用启用 TLS 终止和 HTTP/2 的 Ingress(详见http2 ConfigMap Key)。
使用 ConfigMap 的全局配置
下表展示了 Ingress-NGINX Controller 的 ConfigMap 键与 NGINX Ingress Controller 对应键的映射关系。

</div>