笔记。 翻译。:服务网格无疑已成为现代基础设施中微服务架构应用程序的相关解决方案。 虽然 Istio 可能是许多 DevOps 工程师经常挂在嘴边的,但它是一个相当新的产品,虽然其提供的功能很全面,但可能需要大量时间来熟悉。 德国工程师 Rinor Maloku 在电信公司 Orange Networks 负责大客户的云计算,他编写了一系列精彩的材料,可让您快速深入地了解 Istio。 他从 Istio 一般可以做什么以及如何快速亲眼看到它开始了他的故事。
Istio — 与 Google、IBM 和 Lyft 团队合作开发的开源项目。 它解决了基于微服务的应用程序中出现的复杂性,例如:
- 交通管理:超时、重试、负载均衡;
- 安全:最终用户身份验证和授权;
- 可观测性:跟踪、监控、记录。
这些都可以在应用层面解决,但之后你的服务将不再是“微”的。 所有为解决这些问题而付出的额外努力都是对公司资源的浪费,而这些资源本来可以直接用于商业价值。 让我们看一个例子:
项目经理:添加反馈功能需要多长时间?
开发人员:两次冲刺。MP:什么?...这只是 CRUD!
R:做CRUD是比较容易的部分,但是我们仍然需要对用户和服务进行身份验证和授权。 由于网络不可靠,您将需要实现重复的请求,以及断路器模式 在客户中。 此外,为了确保整个系统不会崩溃,您将需要超时和舱壁 (有关上述两种模式的更多详细信息,请参阅本文后面的内容 - 大约翻译。),并为了发现问题、监控、追踪,[...]MP:哦,那么我们就把这个功能插入到产品服务中吧。
我认为这个想法很明确:添加一项服务所需的步骤和精力是巨大的。 在本文中,我们将了解 Istio 如何从服务中消除上述所有复杂性(并非旨在成为业务逻辑)。
注意:本文假设您具备 Kubernetes 的应用知识。 否则,我建议阅读
Istio理念
在没有 Istio 的世界中,一个服务直接向另一个服务发出请求,如果发生故障,该服务必须自行处理:进行新的尝试、提供超时、打开断路器等。
Kubernetes 中的网络流量
Istio 提供了一种专门的解决方案,与服务完全分离,并通过干扰网络通信来运行。 因此它实现了:
- 容错:根据响应中的状态码,了解请求是否失败并重新执行。
- 金丝雀推出:仅将固定百分比的请求重定向到新版本的服务。
- 监控和指标: 服务花了多长时间才回复?
- 追踪和可观察性:为每个请求添加特殊标头并在集群中跟踪它们。
- 安全:检索 JWT 令牌,对用户进行身份验证和授权。
这些只是引起您兴趣的一些可能性(实际上只是一些!)。 现在让我们深入探讨技术细节!
Istio架构
Istio 拦截所有网络流量并对其应用一组规则,以 sidecar 容器的形式将智能代理插入到每个 pod 中。 激活所有功能的代理形成 数据平面,并且可以使用动态配置它们 控制平面.
数据平面
插入 pod 中的代理可以让 Istio 轻松满足我们的需求。 例如,让我们检查一下重试和断路器功能。
Envoy 中如何实现重试和熔断
总结:
- 使者 (我们正在讨论位于 sidecar 容器中的代理,该容器分布为
单独的产品 - 大约。 译) 向服务 B 的第一个实例发送请求并失败。 - Envoy Sidecar 再次尝试 (重试). (1)
- 请求失败并返回到调用它的代理。
- 这将打开断路器并为后续请求调用下一个服务。 (2)
这意味着您不必使用另一个重试库,也不必使用编程语言 X、Y 或 Z 自行实现熔断和服务发现。所有这些以及更多功能都是开箱即用的在 Istio 中并且不需要 没有 代码的变化。
伟大的! 现在你可能想和 Istio 一起去旅行,但你仍然有一些疑虑,一些悬而未决的问题。 如果这是适用于生活中所有场合的通用解决方案,那么您自然会产生怀疑:毕竟,所有此类解决方案实际上都不适用于任何情况。
最后你问:“它可以定制吗?”
现在您已准备好进行海上航行,让我们来熟悉一下控制平面。
控制平面
它由三个部分组成: 飞行员, 密炼 и 堡垒,它们协同工作来配置 Envoy 来路由流量、执行策略和收集遥测数据。 从原理上讲,一切都是这样的:
控制平面与数据平面的交互
Envoy(即数据平面)使用以下配置
服务与 Istio 的关系
我们已经描述了 Istio 与服务的关系,但没有反过来:服务与 Istio 有何关系?
老实说,当服务问自己“水到底是什么?”时,它们就会意识到 Istio 的存在,就像鱼意识到水一样。
插图
因此,您可以使用一个工作集群,在部署 Istio 组件后,位于其中的服务将继续工作,而在删除这些组件后,一切都会恢复正常。 显然,在这种情况下您将失去 Istio 提供的功能。
理论已经足够了——让我们将这些知识付诸实践!
Istio 实践
Istio 需要一个至少具有 4 个 vCPU 和 8 GB 可用 RAM 的 Kubernetes 集群。 要快速设置集群并按照文章中的说明进行操作,我建议使用 Google Cloud Platform,它为新用户提供了
创建集群并通过控制台实用程序配置对 Kubernetes 的访问后,您可以通过 Helm 包管理器安装 Istio。
舵安装
在您的计算机上安装 Helm 客户端,如中所述
安装 Istio
从以下位置下载 Istio 资源 [istio-resources]
.
为了轻松识别 Istio 资源,请在 K8s 集群中创建命名空间 istio-system
:
$ kubectl create namespace istio-system
进入目录完成安装 [istio-resources]
并运行命令:
$ helm template install/kubernetes/helm/istio
--set global.mtls.enabled=false
--set tracing.enabled=true
--set kiali.enabled=true
--set grafana.enabled=true
--namespace istio-system > istio.yaml
该命令会将 Istio 的关键组件输出到文件中 istio.yaml
。 我们修改了标准模板以适合我们自己,指定以下参数:
-
global.mtls.enabled
安装在false
(即 mTLS 身份验证已禁用 - 大约)简化我们的约会流程; -
tracing.enabled
包括使用 Jaeger 进行请求跟踪; -
kiali.enabled
将 Kiali 安装到集群中以可视化服务和流量; -
grafana.enabled
安装 Grafana 来可视化收集的指标。
让我们通过以下命令使用生成的资源:
$ kubectl apply -f istio.yaml
集群上Istio安装完成! 等待所有 Pod 都位于命名空间中 istio-system
将能够 Running
или Completed
通过运行以下命令:
$ kubectl get pods -n istio-system
现在我们准备好继续下一部分,我们将启动并运行应用程序。
情感分析应用程序的架构
让我们使用已经提到的情感分析微服务应用程序的示例
该应用程序由四个微服务组成:
- 服务 SA-前端,它服务于 Reactjs 应用程序的前端;
- 服务 SA-Web应用程序,它提供情感分析查询;
- 服务 SA逻辑,它自己执行
情绪分析 ; - 服务 SA-反馈,它接收用户关于分析准确性的反馈。
在此图中,除了服务之外,我们还看到了入口控制器,它在 Kubernetes 中将传入请求路由到适当的服务。 Istio 在其 Ingress Gateway 中使用了类似的概念,稍后将介绍更多详细信息。
使用 Istio 代理运行应用程序
对于本文中提到的进一步操作,请克隆您的存储库
插入边车
可以进行插入操作 自动 или 手动。 要自动插入 sidecar 容器,您需要为命名空间设置标签 istio-injection=enabled
,这是通过以下命令完成的:
$ kubectl label namespace default istio-injection=enabled
namespace/default labeled
现在每个 Pod 将部署在默认命名空间中(default
)将收到其边车容器。 为了验证这一点,让我们通过转到存储库的根目录来部署测试应用程序 [istio-mastery]
并运行以下命令:
$ kubectl apply -f resource-manifests/kube
persistentvolumeclaim/sqlite-pvc created
deployment.extensions/sa-feedback created
service/sa-feedback created
deployment.extensions/sa-frontend created
service/sa-frontend created
deployment.extensions/sa-logic created
service/sa-logic created
deployment.extensions/sa-web-app created
service/sa-web-app created
部署服务后,让我们通过运行命令来检查 pod 是否有两个容器(包含服务本身及其 sidecar) kubectl get pods
并确保在该列下 READY
指定值 2/2
,表示两个容器都在运行:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
sa-feedback-55f5dc4d9c-c9wfv 2/2 Running 0 12m
sa-frontend-558f8986-hhkj9 2/2 Running 0 12m
sa-logic-568498cb4d-2sjwj 2/2 Running 0 12m
sa-logic-568498cb4d-p4f8c 2/2 Running 0 12m
sa-web-app-599cf47c7c-s7cvd 2/2 Running 0 12m
从视觉上看,它看起来像这样:
Envoy 代理位于其中一个 Pod 中
现在应用程序已启动并运行,我们需要允许传入流量进入应用程序。
入口网关
实现这一点(允许集群中的流量)的最佳实践是通过 入口网关 Istio 位于集群的“边缘”,允许您启用 Istio 功能,例如路由、负载均衡、安全性和传入流量监控。
在 Istio 安装期间,Ingress Gateway 组件以及将其转发到外部的服务已安装在集群中。 要找出该服务的外部 IP 地址,请运行:
$ kubectl get svc -n istio-system -l istio=ingressgateway
NAME TYPE CLUSTER-IP EXTERNAL-IP
istio-ingressgateway LoadBalancer 10.0.132.127 13.93.30.120
我们将继续使用此 IP(我将其称为 EXTERNAL-IP)访问应用程序,因此为了方便起见,我们将将该值写入变量中:
$ EXTERNAL_IP=$(kubectl get svc -n istio-system
-l app=istio-ingressgateway
-o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
如果您现在尝试通过浏览器访问该IP,您将收到服务不可用错误,因为 默认情况下,Istio 会阻止所有传入流量,网关尚未定义。
网关资源
网关是 Kubernetes 中的 CRD(自定义资源定义),在集群中安装 Istio 后定义,并能够指定我们希望允许传入流量的端口、协议和主机。
在我们的例子中,我们希望允许所有主机在端口 80 上进行 HTTP 流量。 该任务通过以下定义实现 (
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: http-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
除了选择器之外,此配置不需要解释 istio: ingressgateway
。 使用此选择器,我们可以指定将配置应用到哪个 Ingress Gateway。 在我们的例子中,这是 Ingress Gateway 控制器,默认安装在 Istio 中。
通过调用以下命令应用配置:
$ kubectl apply -f resource-manifests/istio/http-gateway.yaml gateway.networking.istio.io/http-gateway created
网关现在允许访问端口 80,但不知道将请求路由到哪里。 为此你需要 虚拟服务.
虚拟服务资源
VirtualService 告诉 Ingress Gateway 如何路由集群内允许的请求。
通过 http-gateway 对我们的应用程序发出的请求必须发送到 sa-frontend、sa-web-app 和 sa-feedback 服务:
需要配置VirtualServices的路由
让我们看看应该发送到 SA-Frontend 的请求:
- 一路上精确匹配
/
应发送到SA-Frontend以获取index.html; - 带前缀的路径
/static/*
必须发送到SA-Frontend以接收前端使用的静态文件,例如CSS和JavaScript; - 正则表达式匹配的路径
'^.*.(ico|png|jpg)$'
,必须发送到 SA-Frontend,因为这些是页面上显示的图片。
通过如下配置实现实现 (
kind: VirtualService
metadata:
name: sa-external-services
spec:
hosts:
- "*"
gateways:
- http-gateway # 1
http:
- match:
- uri:
exact: /
- uri:
exact: /callback
- uri:
prefix: /static
- uri:
regex: '^.*.(ico|png|jpg)$'
route:
- destination:
host: sa-frontend # 2
port:
number: 80
要点:
- 此 VirtualService 指的是通过以下方式发送的请求 http网关;
- В
destination
请求发送到的服务已确定。
注意:上面的配置保存在一个文件中 sa-virtualservice-external.yaml
,其中还包含 SA-WebApp 和 SA-Feedback 中的路由设置,但为了简洁起见,本文已对其进行了缩短。
让我们通过调用来应用 VirtualService:
$ kubectl apply -f resource-manifests/istio/sa-virtualservice-external.yaml
virtualservice.networking.istio.io/sa-external-services created
注意:当我们使用 Istio 资源时,Kubernetes API 服务器会创建一个由 Istio 控制平面接收的事件,然后将新配置应用于每个 pod 的 Envoy 代理。 Ingress Gateway 控制器似乎是控制平面中配置的另一个 Envoy。 所有这一切在图中看起来像这样:
用于请求路由的 Istio-IngressGateway 配置
情绪分析应用程序现已推出 http://{EXTERNAL-IP}/
。 如果您出现“未找到”状态,请不要担心: 有时配置生效和 Envoy 缓存更新需要更长的时间.
在继续之前,先使用该应用程序来产生流量。 (为了后续行动的清晰性,它的存在是必要的 - 大约翻译。).
Kiali:可观察性
要访问 Kiali 管理界面,请运行以下命令:
$ kubectl port-forward
$(kubectl get pod -n istio-system -l app=kiali
-o jsonpath='{.items[0].metadata.name}')
-n istio-system 20001
...然后打开
Grafana:指标可视化
在 Istio 中收集的指标进入 Prometheus 并使用 Grafana 进行可视化。 要进入 Grafana 管理界面,请运行以下命令,然后打开
$ kubectl -n istio-system port-forward
$(kubectl -n istio-system get pod -l app=grafana
-o jsonpath={.items[0].metadata.name}) 3000
单击菜单 主页 左上角并选择 Istio 服务仪表板 在左上角,从服务开始 sa-网络应用程序查看收集的指标:
这里等待我们的是一场空洞且完全无聊的表演——管理层永远不会批准这一点。 让我们使用以下命令创建一个小负载:
$ while true; do
curl -i http://$EXTERNAL_IP/sentiment
-H "Content-type: application/json"
-d '{"sentence": "I love yogobella"}';
sleep .8; done
现在我们有了更好的图表,除此之外,还有用于监控的精彩 Prometheus 工具和用于可视化指标的 Grafana,这将使我们能够了解随着时间的推移服务的性能、运行状况、改进/退化。
最后,让我们看看服务中的跟踪请求。
耶格:追踪
我们需要跟踪,因为我们拥有的服务越多,找到故障原因就越困难。 我们来看一个简单的案例,如下图所示:
随机失败请求的典型示例
请求来了,落下—— 是什么原因? 第一次服务? 还是第二个? 两者都有例外 - 让我们看看每个的日志。 您多久发现自己这样做一次? 我们的工作更像是软件侦探而不是开发人员......
这是微服务中的常见问题,可以通过分布式跟踪系统解决,其中服务相互传递唯一的标头,然后将此信息转发到跟踪系统,在跟踪系统中与请求数据进行比较。 这是一个例子:
TraceId用于标识请求
Istio 使用 Jaeger Tracer,它实现了独立于供应商的 OpenTracing API 框架。 您可以使用以下命令访问 Jaeger 用户界面:
$ kubectl port-forward -n istio-system
$(kubectl get pod -n istio-system -l app=jaeger
-o jsonpath='{.items[0].metadata.name}') 16686
现在去
该跟踪显示:
- 请求进来了 istio-ingressgateway (这是与其中一个服务的第一次交互,并为请求生成跟踪 ID),之后网关将请求发送到服务 sa-网络应用程序.
- 在职 sa-网络应用程序 请求被 Envoy sidecar 接收,在跨度中创建一个“子”(这就是我们在跟踪中看到它的原因)并重定向到容器 sa-网络应用程序. (
跨度 - Jaeger 中的逻辑工作单元,具有名称、操作的开始时间及其持续时间。 Span 可以嵌套和排序。 跨度的有向无环图形成一条迹。 — 大约。 译) - 这里的请求是通过方法处理的 情绪分析。 这些跟踪已经由应用程序生成,即他们需要更改代码。
- 从这一刻起,发起POST请求 萨逻辑。 跟踪 ID 必须转发自 sa-网络应用程序.
- ...
注意:在步骤 4 中,应用程序应该看到 Istio 生成的标头并将其传递给后续请求,如下图所示:
(A) Istio 负责转发 header; (B) 服务负责标头
Istio 完成了大部分工作,因为...... 为传入请求生成标头,在每个 sidecare 中创建新的跨度并转发它们。 但是,如果不使用服务内部的标头,完整的请求跟踪路径将会丢失。
必须考虑以下标头:
x-request-id
x-b3-traceid
x-b3-spanid
x-b3-parentspanid
x-b3-sampled
x-b3-flags
x-ot-span-context
这不是一项困难的任务,但为了简化其实现,已经有
请注意,情绪分析应用程序演示了 Flask、Spring 和 ASP.NET Core 中的实现。
现在我们已经清楚了开箱即用(或几乎开箱即用)的内容,让我们看看微调路由、网络流量管理、安全性等!
笔记。 翻译。:请阅读 Rinor Maloku 提供的 Istio 材料的下一部分来了解这一点,其翻译将在不久的将来出现在我们的博客上。 更新 (14 月 XNUMX 日):
译者PS
另请阅读我们的博客:
- “回到 Istio 的微服务”:
第 2 部分(路由、流量控制) ,第3部分(身份验证和授权) ; - «
Conduit - Kubernetes 的轻量级服务网格 “; - «
什么是服务网格,为什么我需要它 [用于具有微服务的云应用程序]? “; - «
Kubernetes 网络图解指南。 第 1 部分和第 2 部分 “; - «
这个 sidecar 容器是如何[在 Kubernetes 中]出现在这里的? “。
来源: habr.com