什么是服务网格,云原生应用程序(为云设计的应用程序)如何使用它?在本文中,我们将向您展示如何使用Linkerd作为 Kubernetes 上的服务网格,以及它如何捕获和报告顶级服务指标,例如成功率、请求量和延迟,而无需更改应用程序代码。
我们看到的关于 Linkerd 的最常见问题之一是,服务网格到底是什么?当 Kubernetes 等环境提供服务对象和负载均衡器等原语时,为什么服务网格是云原生应用程序的关键组件?
简而言之,服务网格是管理应用程序之间(或同一应用程序的各个部分之间的通信,例如微服务)的层。在传统应用程序中,此逻辑直接内置于应用程序本身:重试和超时、监控/可见性、跟踪、服务发现等都被硬编码到每个应用程序中。
然而,随着应用程序架构越来越多地细分为服务,将通信逻辑从应用程序中移出并移入底层基础设施变得越来越重要。正如应用程序不应该编写自己的 TCP 堆栈一样,它们也不应该管理自己的负载平衡逻辑、服务发现管理或重试和超时逻辑。(例如,请参阅Oliver Gould 的 MesosCon 演讲,了解更多关于跨多个服务协调重试和超时的困难。)
像 Linkerd 这样的服务网格为大规模运行的多服务应用程序提供了关键功能:
基线弹性:重试预算、截止日期、熔断。
顶级服务指标:成功率、请求量和延迟。
延迟和容错:故障和延迟感知负载平衡,可以绕过缓慢或损坏的服务实例。
分布式跟踪 la Zipkin和OpenTracing。
服务发现:定位目标实例。
协议升级:将跨网络通信封装在 TLS 中,或者将 HTTP/1.1 转换为 HTTP/2.0。
路由:不同版本服务之间的路由请求,集群之间的故障转移等。
在 Kubernetes 中使用 Linkerd 进行服务监控
在请求层运行的优势之一是服务网格可以访问成功和失败的协议级语义。例如,如果您正在运行 HTTP 服务,Linkerd 可以理解 200 与 400 与 500 响应的语义,并可以自动计算成功率等指标(当我们谈论重试时,在这一层操作变得更加重要)。
让我们通过一个快速示例来了解如何在 Kubernetes 上安装 Linkerd 以自动捕获聚合的顶级服务成功率,而无需更改应用程序。
第 1 步:安装 Linkerd
使用此 Kubernetes 配置安装 Linkerd 。这会将 Linkerd 安装为在默认 Kubernetes 命名空间中运行的 DaemonSet(即每个主机一个实例):
1个
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd.yml
2个
的
您可以通过查看 linkerd 的管理页面来确认安装是否成功:
1个
INGRESS_LB = $(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}")
2个
打开 http:// $INGRESS_LB :9990
3个
的
第 2 步:安装示例应用程序
使用这个 hello-world 配置安装两个服务,“hello”和“world” 。这会将服务安装到默认命名空间中:
1个
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world.yml
2个
的
这两个服务共同构成一个高度可扩展的“hello world”微服务(hello 服务自然会调用 world 服务来完成其请求)。
您可以通过 Linkerd 的外部 IP 发送流量来查看实际效果:
1个
http_proxy = $INGRESS_LB :4140 curl -s http://hello
2个
的
您应该会看到字符串“Hello world”。
第 3 步:安装 Linkerd-viz
让我们通过安装linkerd-viz看看我们的服务在做什么。Linkerd-viz 是一个补充包,包括简单的 Prometheus 和 Grafana 设置,并配置为自动查找 Linkerd 实例。
使用此 linkerd-viz 配置安装 Linkerd-viz 。这会将 Linkerd-viz 安装到默认命名空间中:
1个
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-viz/master/k8s/linkerd-viz.yml
2个
的
打开Linkerd-viz的外网IP查看dashboard:
1个
VIZ_INGRESS_LB = $(kubectl get svc linkerd-viz -o jsonpath="{.status.loadBalancer.ingress[0].*}")
2个
打开 http:// $VIZ_INGRESS_LB
3个
的
您应该会看到一个仪表板,包括按服务和实例分类的选择器。Linkerd-viz 仪表板包括三个部分:
第一行:集群范围内的成功率和请求量。
服务指标:每个部署的应用程序的一个部分。包括成功率、请求量和延迟。
每实例指标:集群中每个节点的成功率、请求量和延迟。
只需三个简单的命令,我们就能够在我们的 Kubernetes 集群上安装 Linkerd,安装一个应用程序,并使用 Linkerd 来了解应用程序服务的健康状况。当然,Linkerd 提供的不仅仅是可见性:在引擎盖下,我们已经启用了延迟感知负载平衡、自动重试和熔断、分布式跟踪等。
作为服务网格,Linkerd 旨在与应用程序代码一起运行,管理和监控服务间通信,包括执行服务发现、重试、负载平衡和协议升级。
乍一看,这听起来非常适合 Kubernetes 中的边车部署。毕竟,Kubernetes 的定义特征之一是它的 pod 模型。作为 sidecar 进行部署在概念上很简单,具有清晰的故障语义,并且我们花费了大量时间针对此用例优化 Linkerd。
然而,sidecar 模型也有一个缺点:按 pod 部署意味着每个 pod 的资源成本会增加。如果您的服务是轻量级的,并且您运行许多实例,例如 Monzo(他在 Linkerd 和 Kubernetes 之上构建了整个银行),那么使用边车的成本可能会非常高。
我们可以通过为每个主机而不是每个 pod 部署 Linkerd 来降低这种资源成本。这允许按主机扩展资源消耗,这通常是一个比 Pod 数量增长慢得多的指标。幸运的是,Kubernetes正是为此目的提供了DaemonSet 。
不幸的是,对于 Linkerd,为每个主机部署比仅使用 DaemonSets 要复杂一些。我们可以通过在 Kubernetes 中按主机部署来解决服务网格问题。
Kubernetes 中的每主机部署
服务网格的定义特征之一是它能够将应用程序通信与传输通信分离。例如,如果服务 A 和 B 使用 HTTP,服务网格可能会在应用程序不知情的情况下通过线路将其转换为 HTTPS。服务网格还可以执行连接池、准入控制或其他传输层功能,同样以对应用程序透明的方式进行。
为了完全实现这一点,Linkerd 必须在每个请求的发送端和接收端,代理本地实例。例如,对于 HTTP 到 HTTPS 的升级,Linkerd 必须能够启动和终止 TLS。
从主机 1 上的 Pod A 开始并发往主机 2 上的 Pod J 的请求必须经过 Pod A 的主机本地 Linkerd 实例,然后到主机 2 的 Linkerd 实例,最后到 Pod J。这个路径引入了 Linkerd 的三个问题必须解决:
应用程序如何识别其主机本地 Linkerd?
Linkerd 如何将传出请求路由到目的地的 Linkerd?
Linkerd 如何将传入请求路由到目标应用程序?