AWS 中 HTTPS 的 Kubernetes nginx ingress 基于路径的路由
Kubernetes nginx ingress path-based routing of HTTPS in AWS
问题:在 Kubernetes 中,当它被定义为 TCP 时,如何配置 nginx 入口以将来自弹性负载均衡器的流量视为 HTTPS?
我正在 AWS 环境中使用 Kubernetes 集群。我想使用 nginx 入口对 HTTPS 流量进行基于路径的路由;但是,我不想在 AWS 弹性负载均衡器上进行 SSL 终止或重新加密。
所需的设置是:
客户端 -> 弹性负载均衡器 -> nginx ingress -> pod
要求:
1.流量端到端加密
2.必须使用AWS ELB(流量不能从外界直接进入Kubernetes)。
我遇到的问题是要在 ELB 上进行 SSL 直通,我必须将 ELB 配置为 TCP 流量。但是,当ELB定义为TCP时,所有流量都会绕过nginx。
据我所知,我可以设置一个 TCP passthrough via a ConfigMap,但这只是另一个通道;它不允许我在 nginx 中进行基于路径的路由。
我正在寻找一种方法将 ELB 定义为 TCP(用于直通),同时仍然让入口将流量视为 HTTPS。
我可以将 ELB 定义为 HTTPS,但是过程中还有第二个不必要的 negotiate/break/reencrypt 步骤,我想尽可能避免。
为了更清楚,我将从 OSI model, which tells us that TCP is level 4 protocol and HTTP/HTTPS is level 7 protocol. So, frankly speaking HTTP/HTTP
data is encapsulated 到 TCP
数据开始,然后再进行其余级别封装以将数据包传输到另一个网络设备。
如果你设置Classic (TCP) LoadBalancer它在读取TCP部分后停止读取数据包数据,这足以决定(根据LB配置)哪个IP address
和哪个IP port
这个应该传送数据包。之后,LB 获取 TCP 有效载荷数据并将其与另一个 TCP 层数据包裹起来并将其发送到目标点(这反过来会导致应用所有其他 OSI 层)。
为了使您的配置按预期工作,需要公开 nginx-ingress-controller Pod using NodePort service。然后,可以将经典 ELB 配置为将流量传送到任何集群节点到为该 NodePort 服务选择的端口。通常它在 30000
和 32767
之间。所以您的 LB 池将如下所示:
假设集群节点的 IP 地址为 10.132.10.1...10
,NodePort 端口为 30276
。
ELB Endpoint 1: 10.132.10.1:30276
ELB Endpoint 2: 10.132.10.2:30276
...
ELB Endpoint 10: 10.132.10.10:30276
注意:在 AWS ELB 的情况下,我猜,应该使用节点 DNS 名称而不是 IP 地址。
因此它应该导致从客户端到 Kubernetes 应用程序 Pod 的流量分配顺序如下:
- 客户端发送带有HTTP/HTTPS请求的TCP数据包到ELB_IP:ELB_port (
a.b.c.d:80
).
- ELB 接收 IP 数据包,分析其 TCP 数据,从后端池(整个 Kubernetes 集群节点列表)中找到合适的端点,并创建另一个包含相同 HTTP/HTTPS 数据的 TCP 数据包,并替换目标IP和目标TCP端口到集群节点IP和Service NodePort TCP端口(
l.m.n.k:30xxx
)然后发送到选择的目标.
- Kubernetes 节点收到TCP 数据包,使用iptables 规则再次更改TCP 数据包的目的IP 和目的端口,并将数据包(根据Nodeport 服务配置)转发到目的pod。在这种情况下,它将是 nginx-ingress-controller pod。
- Nginx-ingress-controller pod收到TCP数据包,因为根据TCP数据它必须在本地传递,从中提取HTTP/HTTP数据并发送数据(HTTP/HTTPS请求) 到 Pod 中 Nginx 容器内的 Nginx 进程,
- 容器中的 Nginx 进程接收 HTTP/HTTPS 请求,对其进行解密(在 HTTPS 的情况下)并分析所有 HTTP header。
- 根据
nginx.conf
设置,Nginx处理改变HTTP请求并将其传递给集群服务,指定为配置的主机和URL路径。
- Nginx 进程将更改后的 HTTP 请求发送到后端应用程序。
- 然后在HTTP请求中加入TCPheader发送给后端服务
IP_address:TCP_port
.
- 为后端服务定义的 iptables 规则,将数据包传送到服务端点之一(应用程序 Pods)。
注意:要在入口控制器上终止 SSL,您必须在 SAN 部分创建包含 ELB IP 和 ELB FQDN 的 SSL 证书。
注意:如果您想在应用程序Pod 上终止SSL 以进行端到端SSL 加密,您可能需要配置nginx 以绕过SSL 流量。
底线:配置为向 Kubernetes 集群传送 TCP 流量的 ELB 如果您以正确的方式配置它,可以与 nginx-ingress 控制器完美配合。
在 GKE(Google Kubernetes Engine)中,如果您使用 type:LoadBalancer 创建一个服务,它会准确地为您创建 TCP LB,它将流量转发到服务节点端口,然后 Kubernetes 负责将其传送到荚。 AWS 的 EKS(弹性 Kubernetes 服务)的工作方式非常相似。
问题:在 Kubernetes 中,当它被定义为 TCP 时,如何配置 nginx 入口以将来自弹性负载均衡器的流量视为 HTTPS?
我正在 AWS 环境中使用 Kubernetes 集群。我想使用 nginx 入口对 HTTPS 流量进行基于路径的路由;但是,我不想在 AWS 弹性负载均衡器上进行 SSL 终止或重新加密。
所需的设置是:
客户端 -> 弹性负载均衡器 -> nginx ingress -> pod
要求:
1.流量端到端加密
2.必须使用AWS ELB(流量不能从外界直接进入Kubernetes)。
我遇到的问题是要在 ELB 上进行 SSL 直通,我必须将 ELB 配置为 TCP 流量。但是,当ELB定义为TCP时,所有流量都会绕过nginx。
据我所知,我可以设置一个 TCP passthrough via a ConfigMap,但这只是另一个通道;它不允许我在 nginx 中进行基于路径的路由。
我正在寻找一种方法将 ELB 定义为 TCP(用于直通),同时仍然让入口将流量视为 HTTPS。
我可以将 ELB 定义为 HTTPS,但是过程中还有第二个不必要的 negotiate/break/reencrypt 步骤,我想尽可能避免。
为了更清楚,我将从 OSI model, which tells us that TCP is level 4 protocol and HTTP/HTTPS is level 7 protocol. So, frankly speaking HTTP/HTTP
data is encapsulated 到 TCP
数据开始,然后再进行其余级别封装以将数据包传输到另一个网络设备。
如果你设置Classic (TCP) LoadBalancer它在读取TCP部分后停止读取数据包数据,这足以决定(根据LB配置)哪个IP address
和哪个IP port
这个应该传送数据包。之后,LB 获取 TCP 有效载荷数据并将其与另一个 TCP 层数据包裹起来并将其发送到目标点(这反过来会导致应用所有其他 OSI 层)。
为了使您的配置按预期工作,需要公开 nginx-ingress-controller Pod using NodePort service。然后,可以将经典 ELB 配置为将流量传送到任何集群节点到为该 NodePort 服务选择的端口。通常它在 30000
和 32767
之间。所以您的 LB 池将如下所示:
假设集群节点的 IP 地址为 10.132.10.1...10
,NodePort 端口为 30276
。
ELB Endpoint 1: 10.132.10.1:30276
ELB Endpoint 2: 10.132.10.2:30276
...
ELB Endpoint 10: 10.132.10.10:30276
注意:在 AWS ELB 的情况下,我猜,应该使用节点 DNS 名称而不是 IP 地址。
因此它应该导致从客户端到 Kubernetes 应用程序 Pod 的流量分配顺序如下:
- 客户端发送带有HTTP/HTTPS请求的TCP数据包到ELB_IP:ELB_port (
a.b.c.d:80
). - ELB 接收 IP 数据包,分析其 TCP 数据,从后端池(整个 Kubernetes 集群节点列表)中找到合适的端点,并创建另一个包含相同 HTTP/HTTPS 数据的 TCP 数据包,并替换目标IP和目标TCP端口到集群节点IP和Service NodePort TCP端口(
l.m.n.k:30xxx
)然后发送到选择的目标. - Kubernetes 节点收到TCP 数据包,使用iptables 规则再次更改TCP 数据包的目的IP 和目的端口,并将数据包(根据Nodeport 服务配置)转发到目的pod。在这种情况下,它将是 nginx-ingress-controller pod。
- Nginx-ingress-controller pod收到TCP数据包,因为根据TCP数据它必须在本地传递,从中提取HTTP/HTTP数据并发送数据(HTTP/HTTPS请求) 到 Pod 中 Nginx 容器内的 Nginx 进程,
- 容器中的 Nginx 进程接收 HTTP/HTTPS 请求,对其进行解密(在 HTTPS 的情况下)并分析所有 HTTP header。
- 根据
nginx.conf
设置,Nginx处理改变HTTP请求并将其传递给集群服务,指定为配置的主机和URL路径。 - Nginx 进程将更改后的 HTTP 请求发送到后端应用程序。
- 然后在HTTP请求中加入TCPheader发送给后端服务
IP_address:TCP_port
. - 为后端服务定义的 iptables 规则,将数据包传送到服务端点之一(应用程序 Pods)。
注意:要在入口控制器上终止 SSL,您必须在 SAN 部分创建包含 ELB IP 和 ELB FQDN 的 SSL 证书。
注意:如果您想在应用程序Pod 上终止SSL 以进行端到端SSL 加密,您可能需要配置nginx 以绕过SSL 流量。
底线:配置为向 Kubernetes 集群传送 TCP 流量的 ELB 如果您以正确的方式配置它,可以与 nginx-ingress 控制器完美配合。
在 GKE(Google Kubernetes Engine)中,如果您使用 type:LoadBalancer 创建一个服务,它会准确地为您创建 TCP LB,它将流量转发到服务节点端口,然后 Kubernetes 负责将其传送到荚。 AWS 的 EKS(弹性 Kubernetes 服务)的工作方式非常相似。