在以下情况下,服务网格实际上可能会增加Kubernetes环境的管理复杂性:必须将其与Ingress控制器分开配置。分开配置不只是耗时,还会增加配置错误的概率。这些错误可能导致流量无法正确路由,甚至引发安全漏洞(例如,恶意行为者获得受限应用的访问权限)和不良体验(例如,客户无法访问其有权使用的应用)。除了分开配置所需的时间外,还需要花费更多时间排查错误。
通过将基于NGINX Plus的NGINX Ingress Controller与NGINX Service Mesh集成,以控制入站和出站mTLS流量,可以避免这些问题并节省时间。本视频演示将介绍完整步骤。
以下章节引用了支持文档:
- 先决条件
- 使用NGINX Service Mesh部署NGINX Ingress Controller
- 使用标准Kubernetes Ingress资源公开应用
- 使用NGINX VirtualServer资源公开应用
- 使用NGINX Ingress Controller配置安全的出站路由
先决条件(0:18)
在开始实际演示之前,我们完成了以下准备工作:
- 在Kubernetes集群中安装了NGINX Server Mesh control plane,并为服务网格设置了mTLS和
strict策略。 - 在Kubernetes集群中将基于NGINX Plus的NGINX Ingress Controller安装为Deployment(而非DaemonSet),并启用出站流量,然后将其公开为以下类型的服务:
LoadBalancer。注意:此演示不适用于基于NGINX Open Source的NGINX Ingress Controller。为便于阅读,本文后续将基于NGINX Plus的NGINX Ingress Controller简称为“NGINX Ingress Controller”。 - 按照我们的说明下载示例
bookinfo应用,注入NGINX Service Mesh边车,并部署该应用。
由于在步骤 1 中创建了strict策略,来自网格外部客户端、发往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 Service Mesh 部署 NGINX Ingress Controller(1:50)
公开应用流程的第一步是部署一个NGINX Ingress Controller实例。相关说明请参阅教程《使用NGINX Plus Ingress Controller for Kubernetes进行部署》。
为此,NGINX同时提供Deployment和DaemonSet清单。在本演示中,我们使用Deployment清单nginx-plus-ingress.yaml。该清单包含相关注解,用于通过同一个NGINX Ingress Controller实例路由入站和出站流量:
正在加载代码示例…
该清单支持NGINX Ingress Controller与NGINX Service Mesh的证书颁发机构(CA)Spire直接集成,无需将NGINX Service Mesh边车注入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边车。
我们还部署了一个类型为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
...使用标准Kubernetes Ingress资源公开应用(3:55)
现在,我们使用bookinfo-ingress.yaml中定义的标准Kubernetes Ingress资源,将网格中的bookinfo应用公开。相关说明请参阅教程《使用NGINX Plus Ingress Controller公开应用》。
正在加载代码示例…
该资源在第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现在,在演示中,我们使用浏览器访问位于bookinfo的应用,地址为https://bookinfo.example.com/。(我们之前已在本地/etc/hosts文件中添加了Ingress Controller服务IP地址(如上所述,演示中为35.233.133.188)与bookinfo.example.com之间的映射。有关操作说明,请参阅文档。)随着请求在Book Reviews服务的3个版本之间轮转,页面中reviews部分的信息会定期变化。这3个版本在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资源公开应用(6:45)
接下来,我们将介绍另一种公开应用的方法,即使用NGINX VirtualServer资源。这是NGINX Ingress Controller的一种自定义资源,支持更复杂的流量处理,例如流量拆分和基于内容的路由。
首先,删除标准Ingress资源:
> kubectl delete -f bookinfo-ingress.yamlingress.networking.k8s.io "bookinfo-ingress" deletedbookinfo-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配置安全出口路由(8:44)
下面介绍如何通过NGINX Ingress Controller路由出站流量。教程《使用NGINX Plus Ingress Controller配置安全出站路由》使用不同的示例应用介绍了这一过程。
我们已在bash中定义了一个简单的bash.yaml Pod,并将其部署到用于发送请求的默认命名空间中。如下方输出的READY列所示,该Pod已注入NGINX Service Mesh边车。
> 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 Service Mesh的任何实体,例如部署在以下位置的服务:
- 集群外部
- 在另一个集群上
- 位于同一集群中,但未注入NGINX Service Mesh边车
在此演示中,我们将介绍最后一种用例。我们在legacy命名空间中部署了一个应用。该命名空间不受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配置了strict 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,但由于未定义路由,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 Ingress Controller的NGINX Service Mesh
许多服务网格都提供入口和出口网关选项,但NGINX集成还带来一项额外优势:降低延迟。大多数服务网格都需要将边车注入Ingress控制器,导致流量在传输到应用的途中多经过一跳。分秒都很重要,这一额外跳转会拖慢数字体验,可能导致客户转向其他服务。NGINX Service Mesh不会向NGINX Ingress Controller注入边车,因此不会增加不必要的延迟。NGINX Ingress Controller通过直接与网格的证书颁发机构Spire集成,成为NGINX Service Mesh的一部分。NGINX Ingress Controller只需从Spire代理获取证书和密钥,即可与网格中的Pod进行mTLS证书交换。
NGINX Ingress Controller for Kubernetes有两个版本:NGINX Open Source和NGINX Plus。要按照本博客所述方式将NGINX Ingress Controller与NGINX Service Mesh结合部署,必须使用NGINX Plus版本。该版本提供30天免费试用。
NGINX Service Mesh可免费使用,并可立即下载,部署时间不到10分钟。要开始使用,请查看文档,并通过GitHub向我们反馈使用情况。
相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
