服务网格实际上使Kubernetes环境的管理变得更加复杂的原因之一是它必须与Ingress 控制器分开配置。 单独的配置不只是耗费时间。 它们增加了配置错误的概率,从而阻止正确的流量路由,甚至导致安全漏洞(如不良行为者获得受限应用程序的访问权限)和不良体验(如客户无法访问他们被授权的应用程序)。 除了执行单独配置所花费的时间之外,您还会花费更多时间来排除错误。
您可以通过将基于 NGINX Plus 的NGINX Ingress Controller与NGINX Service Mesh集成来控制入口和出口 mTLS 流量,从而避免这些问题并节省时间。 在此视频演示中,我们介绍了完整的步骤。
以下部分引用了支持文档:
在开始实际演示之前,我们执行了以下先决条件:
在 Kubernetes 集群中安装了NGINX Server Mesh 控制平面,并为服务网格设置了 mTLS 和严格
策略。
在 Kubernetes 集群中安装基于 NGINX Plus 的NGINX Ingress Controller作为 Deployment(而不是 DaemonSet),启用 egress ,并将其公开为LoadBalancer
类型的服务。
笔记: 该演示不适用于基于 NGINX 开源的 NGINX Ingress Controller。 为了方便阅读,在本博客的其余部分,我们把基于 NGINX Plus 的NGINX Ingress Controller 简称为“NGINX Ingress Controller”。
按照我们的说明下载示例bookinfo
应用程序、注入 NGINX Service Mesh sidecar 并部署该应用程序。
由于在步骤 1 中创建的严格
策略,来自网格外部的客户端对bookinfo
应用程序的请求在 sidecar 上被拒绝。 我们在演示中通过首先运行以下命令来设置端口转发来说明这一点:
> kubectl port-forward svc/product-page 9080Forwarding from 127.0.0.1:9080 -> 9080
Forwarding from [::1]:9080 -> 9080
Handling connection for 9080
当我们尝试访问应用程序时,我们会收到状态代码503
因为我们的本地机器不是服务网格的一部分:
> curl localhost:9080503
公开应用程序过程的第一阶段是部署 NGINX Ingress Controller 实例。 我们的教程《使用 NGINX Plus Ingress Controller for Kubernetes 进行部署》中提供了相应的说明。
为此,NGINX 提供了 Deployment 和 DaemonSet 清单。 在演示中,我们使用部署清单nginx-plus-ingress.yaml 。 它包括通过同一个 NGINX Ingress Controller 实例路由入口和出口流量的注释:
该清单支持将 NGINX Ingress Controller 与 NGINX Service Mesh 的证书颁发机构 (CA) Spire 直接集成,从而无需将 NGINX Service Mesh sidecar 注入 NGINX Ingress Controller。 相反,NGINX Ingress Controller 直接从 Spire CA 获取证书和密钥,以便与网格中的 pod 进行 mTLS 通信。 清单指定了 Spire 代理地址:
并将 Spire 代理 UNIX 套接字安装到 NGINX Ingress Controller pod:
关于清单,最后要注意的是-enable-internal-routes
CLI 参数,它使我们能够路由到出口服务:
在开始演示之前,我们运行kubectl
apply
-f
nginx-plus-ingress.yaml
命令来安装 NGINX Ingress Controller ,此时我们检查nginx-ingress
命名空间中的部署。 如以下输出的READY
列所示,NGINX Ingress Controller pod 只有一个容器,因为我们还没有向其注入 NGINX Service Mesh sidecar。
我们还部署了LoadBalancer
类型的服务,以在集群之外公开 NGINX Ingress Controller 的外部 IP 地址(此处为 35.233.133.188)。 我们将通过该 IP 地址访问示例bookinfo
应用。
> kubectl get pods --namespace=nginx-ingressNAME READY STATUS RESTARTS AGE
pod/nginx-ingress-867f954b8f0fzdrm 1/1 Running 0 3d3h
NAME TYPE CLUSTER-IP EXTERNAL-IP ...
service-nginx-ingress LoadBalancer 10.31.245.207 35.233.133.188 ...
... PORT(S) AGE
... 80:31469/TCP,443:32481/TCP 4d2h
...
现在,我们使用bookinfo-ingress.yaml中定义的标准 Kubernetes Ingress 资源在网格中公开bookinfo
应用程序。 我们的教程“使用 NGINX Plus Ingress Controller 公开application”中提供了相应的说明。
该资源在第 10 行引用了bookinfo
应用程序的 Kubernetes Secret,并包含一条路由规则,该规则指定将对bookinfo.example.com的请求发送到productpage
服务(第 11-18 行)。 Secret 在bookinfo-secret.yaml中定义:
我们运行此命令来加载密钥和证书,在演示中是自签名的:
> kubectl apply -f bookinfo-secret.yamlsecret/bookinfo-secret unchanged
我们激活 Ingress 资源:
> kubectl apply -f bookinfo-ingress.yamlingress.networking.k8s.io/bookinfo-ingress deleted
并验证 Ingress Controller 是否添加了资源中定义的路由,如输出末尾的事件所证实:
> kubectl describe ingress bookinfo-ingress...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedOrUpdated 5s nginx-ingress-controller Configuration for ...
...default/bookinfo-ingress was added or updated
在演示中,我们现在使用浏览器访问https://bookinfo.example.com/上的bookinfo
应用程序。 (我们之前已经在本地/etc/hosts文件中添加了 Ingress Controller 服务的 IP 地址(如上所述,演示中为 35.233.133.188)和bookinfo.example.com之间的映射。 有关说明,请参阅文档。) 随着请求在bookinfo.yaml (下载)中定义的评论
服务的三个版本之间轮换,页面上“书评”部分的信息会定期更改。
接下来我们检查进入集群的流量。 我们运行generate-traffic.sh脚本,通过NGINX Ingress Controller的公网IP地址向productpage
服务发出请求,然后运行nginx-meshctl
top
命令来监控流量:
> nginxmesh-ctl top deploy/productpage-v1Deployment Direction Resource Success Rate P99 P90 P50 ...
productpage-v1
To details-v1 100.00% 3ms 3ms 2ms
To reviews-v2 100.00% 99ms 90ms 20ms
To reviews-v3 100.00% 99ms 85ms 18ms
To reviews-v1 100.00% 20ms 17ms 9ms
From nginx-ingress 100.00% 192ms 120ms 38ms
... NumRequests
... 14
... 5
... 5
... 12
接下来我们将展示另一种公开应用程序的方法,即使用NGINX VirtualServer 资源。 它是一个自定义的 NGINX Ingress Controller 资源,支持更复杂的流量处理,例如流量分割和基于内容的路由。
首先我们删除标准 Ingress 资源:
> kubectl delete -f bookinfo-ingress.yamlingress.networking.k8s.io "bookinfo-ingress" deleted
我们的bookinfo-vs.yaml文件使用与bookinfo-ingress.yaml中相同的 Secret 配置 mTLS(第 7-8 行)。 第 9-12 行将productpage
服务定义为上游,第 13-24 行定义一条路由,将所有在bookinfo.example.com发出的GET
请求发送到该上游。 对于除GET
之外的 HTTP 方法,它返回状态代码405
。
我们应用资源:
> kubectl apply -f bookinfo-vs.yamlvirtualserver.kubernetes.nginx.org/bookinfo-vs created
然后,我们执行与 Ingress 资源相同的步骤 - 运行kubectl
describe
命令以确认正确部署并在浏览器中访问应用程序。 另一个可以确认应用程序正常运行的方法是它拒绝POST
方法:
> curl -k -X POST https://bookinfo.example.com/Method not allowed
现在我们展示如何通过 NGINX Ingress Controller 路由出口流量。 我们的教程使用 NGINX Plus Ingress Controller 配置安全出口路由介绍了使用不同示例应用程序的过程。
我们已经在bash.yaml中定义了一个简单的bash
pod,并将其部署在我们发送请求的默认命名空间中。 正如该输出的READY
列所示,它已经注入了 NGINX Service Mesh sidecar。
> kubectl get allNAME READY STATUS RESTARTS AGE
pod/bash-6ccb678958-zsgm7 2/2 Running 0 77s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.31.240.1 <none> 443/TCP 4d2h
...
在多种用例中,你可能希望启用从 pod 内部到出口服务的请求,出口服务是不属于 NGINX 服务网格的任何实体。 部署的服务示例:
在演示中,我们正在考虑最终的用例。 我们在旧
命名空间中部署了一个应用,该应用程序不受 NGINX Service Mesh 控制,并且 NGINX Service Mesh 侧车的自动注入已被禁用。 该应用程序仅运行一个 pod。
> kubectl get all --namespaces=legacyNAME READY STATUS RESTARTS AGE
pod/target-5f7bcb96c6-km9lz 1/1 Running 0 27m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/target-svc ClusterIP 10.31.245.213 <none> 80/TCP,443/TCP 27m
...
请记住,我们已经为 NGINX Service Mesh 配置了严格的
mTLS 策略;因此,我们无法直接从bash
pod 向目标服务发送请求,因为两者无法相互验证。 当我们尝试时,我们得到状态代码503
如图所示:
> kubectl exec -it bash-6ccb678958-zsgm7 -c bash -- curl target-svc.legacycurl: (56) Recv failure: connection reset by peer
503command terminated with exit code 56
解决方案是允许bash
pod 通过 NGINX Ingress Controller 发送出站流量。 我们取消注释bash.yaml第 14-15 行的注释:
然后我们应用新的配置:
> kubectl apply -f bash.yamldeployment.apps/bash configured
并验证新的bash
pod 是否已启动:
> kubectl get podsNAME READY STATUS RESTARTS AGE
bash-678c8b4579-7sfml 2/2 Running 0 6s
bash-6ccb678958-zsgm7 2/2 Terminating 0 3m28s
现在,当我们运行与之前相同的kubectl
exec
命令时,从bash
pod 向目标服务发送请求,我们会得到状态代码404
而不是503
。 这表明bash
pod 已成功将请求发送到 NGINX Ingress Controller,但由于没有定义路由,后者不知道将其转发到哪里。
我们使用legacy-route.yaml中的以下 Ingress 资源定义创建所需的路由。 第 7 行的internal-route
注释意味着目标服务不暴露给互联网,而只暴露给 NGINX Service Mesh 内的工作负载。
我们激活新的资源,并确认NGINX Ingress Controller添加了资源中定义的路由:
> kubectl apply -f legacy-route.yamlingress.networking.k8s.io/target-internal-route created
> kubectl describe ingress target-internal-route -n legacy
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedOrUpdated 6s nginx-ingress-controller Configuration for ...
...legacy/target-internal-route was added or updated
现在,当我们运行kubectl
exec
命令时,我们将到达目标服务:
{"req": {"method": "GET" "url": "/",
"host": "target-svc.legacy",
"remoteAddr": "10.28.2.76:56086"}}
通过 NGINX Ingress Controller 路由出站流量的一个优点是,您可以精确控制从集群内部可以访问哪些外部服务 - 只有您定义路由的服务。
我们在演示中展示的最后一件事是如何监控出口流量。 我们运行kubectl
exec
命令发送几个请求,然后运行此命令:
> nginxmesh-ctl top deploy/nginx-ingress -n nginx-ingressDeployment Direction Resource Success Rate P99 P90 P50 NumRequests
nginx-ingress
To target 100.00% 1ms 1ms 1ms 9
From bash 100.00% 0ms 0ms 0ms 9
许多服务网格提供入口和出口网关选项,但我们认为您会欣赏 NGINX 集成的额外好处:更低的延迟。 大多数网格都需要将sidecar注入 Ingress 控制器,这需要流量在流向应用程序的途中进行额外的跳跃。 分秒必争,而额外的一跳会减慢您的数字体验,甚至可能导致客户转向其他地方。 NGINX Service Mesh 不会增加不必要的延迟,因为它不会将 sidecar 注入 NGINX Ingress Controller。 相反,通过直接与网格的 CA Spire 集成,NGINX Ingress Controller 成为 NGINX Service Mesh 的一部分。 NGINX Ingress Controller 只是从 Spire 代理获取证书和密钥,并使用它们参与与网状 pod 的 mTLS 证书交换。
Kubernetes 的 NGINX Ingress Controller 有两个版本: NGINX 开源和 NGINX Plus。 要按照本博客所述使用 NGINX Ingress Controller 部署 NGINX Service Mesh,您必须使用 NGINX Plus 版本,该版本可免费试用 30 天。
NGINX Service Mesh 完全免费,可立即下载并可在不到 10 分钟的时间内完成部署! 首先,请查看文档并通过GitHub告诉我们进展如何。
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”