服务网格实际上使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 9080从 127.0.0.1:9080 转发 -> 9080 从 [::1]:9080 转发 -> 9080 处理 9080 的连接
当我们尝试访问应用程序时,我们会收到状态代码503
因为我们的本地机器不是服务网格的一部分:
>卷曲本地主机: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-ingress NAME 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...... 港口年龄... 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.yaml secret/bookinfo-secret 不变
我们激活 Ingress 资源:
> kubectl apply -f bookinfo-ingress.yaml ingress.networking.k8s.io/bookinfo-ingress 已删除
并验证 Ingress Controller 是否添加了资源中定义的路由,如输出末尾的事件所证实:
> kubectl 描述入口 bookinfo-ingress …
事件:
类型 原因 年龄 来自 消息 ---- ------ ---- ---- ------- 正常 已添加或更新 5s nginx-ingress-controller 配置... ...default/bookinfo-ingress 已添加或更新
在演示中,我们现在使用浏览器访问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-v1部署方向 资源 成功率 P99 P90 P50 ... productpage-v1 到 details-v1 100.00% 3ms 3ms 2ms 到 reviews-v2 100.00% 99ms 90ms 20ms 到 reviews-v3 100.00% 99ms 85ms 18ms 到 reviews-v1 100.00% 20ms 17ms 9ms 来自 nginx-ingress 100.00% 192ms 120ms 38ms ... 请求数... 14 ... 5 ... 5 ... 12
接下来我们将展示另一种公开应用程序的方法,即使用NGINX VirtualServer 资源。 它是一个自定义的 NGINX Ingress Controller 资源,支持更复杂的流量处理,例如流量分割和基于内容的路由。
首先我们删除标准 Ingress 资源:
> kubectl delete -f bookinfo-ingress.yaml ingress.networking.k8s.io “bookinfo-ingress”已删除
我们的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.yaml virtualserver.kubernetes.nginx.org/bookinfo-vs 创建
然后,我们执行与 Ingress 资源相同的步骤 - 运行kubectl
describe
命令以确认正确部署并在浏览器中访问应用程序。 另一个可以确认应用程序正常运行的方法是它拒绝POST
方法:
> curl -k -X POST https://bookinfo.example.com/方法不允许
现在我们展示如何通过 NGINX Ingress Controller 路由出口流量。 我们的教程使用 NGINX Plus Ingress Controller 配置安全出口路由介绍了使用不同示例应用程序的过程。
我们已经在bash.yaml中定义了一个简单的bash
pod,并将其部署在我们发送请求的默认命名空间中。 正如该输出的READY
列所示,它已经注入了 NGINX Service Mesh sidecar。
> kubectl 获取全部名称 就绪状态 重新启动 年龄
pod/bash-6ccb678958-zsgm7 2/2 运行 0 77 秒
名称 类型 集群 IP 外部 IP 端口 年龄
service/kubernetes ClusterIP 10.31.240.1 <无> 443/TCP 4d2h
...
在多种用例中,你可能希望启用从 pod 内部到出口服务的请求,出口服务是不属于 NGINX 服务网格的任何实体。 部署的服务示例:
在演示中,我们正在考虑最终的用例。 我们在旧
命名空间中部署了一个应用,该应用程序不受 NGINX Service Mesh 控制,并且 NGINX Service Mesh 侧车的自动注入已被禁用。 该应用程序仅运行一个 pod。
> kubectl 获取所有 --namespaces=legacy名称 就绪状态 重新启动 年龄
pod/target-5f7bcb96c6-km9lz 1/1 正在运行 0 27m
名称 类型 集群 IP 外部 IP 端口 年龄
service/target-svc 集群 IP 10.31.245.213 <无> 80/TCP,443/TCP 27m
...
请记住,我们已经为 NGINX Service Mesh 配置了严格的
mTLS 策略;因此,我们无法直接从bash
pod 向目标服务发送请求,因为两者无法相互验证。 当我们尝试时,我们得到状态代码503
如图所示:
> kubectl exec -it bash-6ccb678958-zsgm7 -c bash --curl target-svc.legacy curl: (56)接收失败:对端重置连接 503 命令终止,退出代码为 56
解决方案是允许bash
pod 通过 NGINX Ingress Controller 发送出站流量。 我们取消注释bash.yaml第 14-15 行的注释:
然后我们应用新的配置:
> kubectl apply -f bash.yaml deploy.apps/bash 已配置
并验证新的bash
pod 是否已启动:
> kubectl get pods名称就绪状态重新启动年龄bash-678c8b4579-7sfml 2/2 正在运行 0 6s bash-6ccb678958-zsgm7 2/2 正在终止 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.yaml ingress.networking.k8s.io/target-internal-route created > kubectl describe ingress target-internal-route -n legacy ...
事件:
类型 原因 期限 来自 消息 ---- ------ ---- ---- ------- 正常 已添加或更新 6s nginx-ingress-controller 配置... ...legacy/target-internal-route 已添加或更新
现在,当我们运行kubectl
exec
命令时,我们将到达目标服务:
{"请求": {"方法": “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-ingress部署方向 资源 成功率 P99 P90 P50 NumRequests nginx-ingress 到目标 100.00% 1ms 1ms 1ms 9 从 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 内容。”