Linkerd 2.10 系列
- 快速上手 Linkerd v2.10 Service Mesh(服务网格)
- 腾讯云 K8S 集群实战 Service Mesh—Linkerd2 & Traefik2 部署 emojivoto 应用
- 详细了解 Linkerd 2.10 基础功能,一起步入 Service Mesh 微服务架构时代
- Linkerd 2.10—将您的服务添加到 Linkerd
- Linkerd 2.10—自动化的金丝雀发布
- Linkerd 2.10—自动轮换控制平面 TLS 与 Webhook TLS 凭证
- Linkerd 2.10—如何配置外部 Prometheus 实例
- Linkerd 2.10—配置代理并发
- Linkerd 2.10—配置重试
- Linkerd 2.10—配置超时
- Linkerd 2.10—控制平面调试端点
- Linkerd 2.10—使用 Kustomize 自定义 Linkerd 的配置
Linkerd 2.10 中文手册持续修正更新中:
这个演示是一个Ruby应用程序,可以帮助您管理书架。
它由多个微服务组成,并通过 HTTP 使用 JSON 与其他服务通信。有三种服务:
出于演示目的,该应用程序带有一个简单的流量生成器。整体拓扑如下所示:
先决条件
要使用本指南,您需要在集群上安装 Linkerd 及其 Viz 扩展。
如果您还没有这样做,请按照安装 Linkerd 指南进行操作。
安装应用
首先,让我们将 books app 安装到您的集群上。在本地终端中,运行:
kubectl create ns booksapp && \
curl -sL https://run.linkerd.io/booksapp.yml \
| kubectl -n booksapp apply -f -
复制代码
此命令为 demo 创建一个命名空间,下载其 Kubernetes 资源清单
并使用 kubectl
将其应用到您的集群。
该应用程序包含在 booksapp
命名空间中
运行的 Kubernetes deployments 和 services。
第一次下载一堆容器需要一点时间。Kubernetes 可以告诉您所有服务何
时都在运行并准备好进行通信。通过运行以下命令等待它发生:
kubectl -n booksapp rollout status deploy webapp
复制代码
您还可以通过运行以下命令快速查看添加到集群中的所有组件:
kubectl -n booksapp get all
复制代码
部署成功完成后,您可以通过本地端口转发 webapp
访问应用程序本身:
kubectl -n booksapp port-forward svc/webapp 7000 &
复制代码
在浏览器中打开 http://localhost:7000/ 以查看前端。
不幸的是,应用程序中有一个错误:如果您单击 Add Book,它有 50% 的时间会失败。
这是一个典型的不明显、间歇性故障的案例——这种故障让服务所有者抓狂,因为它很难调试。
Kubernetes 本身无法检测或显示此错误。从 Kubernetes 的角度来看,
看起来一切都很好,但您知道应用程序正在返回错误。
将 Linkerd 添加到服务中
现在我们需要将 Linkerd 数据平面代理添加到服务中。最简单的选择是做这样的事情:
kubectl get -n booksapp deploy -o yaml \
| linkerd inject - \
| kubectl apply -f -
复制代码
此命令检索 booksapp
命名空间中所有部署的清单,
通过 linkerd inject
运行它们,然后使用 kubectl apply
重新应用。
linkerd inject
命令对每个资源进行注释,
以指定它们应该添加 Linkerd 数据平面代理,
当清单重新应用于集群时,Kubernetes 会执行此操作。
最重要的是,由于 Kubernetes 进行滚动部署,因此应用程序始终保持运行。
调试
让我们使用 Linkerd 来发现此应用程序失败的根本原因。 要查看 Linkerd 仪表板,请运行:
linkerd viz dashboard &
复制代码
从命名空间下拉列表中选择 booksapp
并单击
Deployments 工作负载。
您应该会看到 booksapp
命名空间中的所有部署都显示出来了。
会有成功率、每秒请求数和延迟百分位数。
这很酷,但你会注意到 webapp
的成功率不是 100%。
这是因为流量生成器正在提交新书。
你可以自己做同样的事情,把成功率推得更低。
单击 Linkerd 仪表板中的 webapp
以进行实时调试会话。
您现在应该查看 webapp
服务的详细信息视图。
您会看到 webapp
正在从 traffic
(负载生成器)中获取流量,
并且它有两个传出依赖项:authors
和 book
。
一个是作者信息拉取服务,一个是图书信息拉取服务。
依赖服务中的故障可能正是导致 webapp
返回错误的原因(以及您作为用户在单击时可以看到的错误)。
我们可以看到 books
服务也失败了。让我们进一步向下滚动页面,
我们将看到 webapp
正在接收的所有流量端点的实时列表。这是有趣的:
啊哈!我们可以看到,从 webapp
服务到 books
服务的入站流量在很大一部分时间都失败了。
这可以解释为什么 webapp
会引发间歇性故障。让我们点击 tap (?) 图标,
然后点击开始按钮来查看实际的请求和响应流。
事实上,许多这些请求都返回 500。
诊断仅影响单一路线的间歇性问题非常容易。
您现在拥有了打开详细错误报告所需的一切,该报告准确地解释了根本原因是什么。
如果 books
服务是您自己的,您就知道在代码中的确切位置。
Service Profiles
为了了解根本原因,我们使用了实时流量。
对于某些问题,这很好,但是如果问题是间歇性的并且发生在半夜会怎样?
Service profiles 为 Linkerd 提供了有关您的服务的一些附加信息。
这些定义了您正在服务的路由,除其他外,还允许在每个路由的基础上收集指标。
通过 Prometheus 存储这些指标,您将能够睡个好觉并在早上查找间歇性问题。
获取 service profiles 设置的最简单方法之一是使用现有的
OpenAPI (Swagger) 规范。
此 demo 已发布其每项服务的规范。您可以通过运行以下命令为 webapp
创建 service profile:
curl -sL https://run.linkerd.io/booksapp/webapp.swagger \
| linkerd -n booksapp profile --open-api - webapp \
| kubectl -n booksapp apply -f -
复制代码
这个命令会做三件事:
- 获取
webapp
的 swagger 规范。 - 获取规范并使用
profile
命令将其转换为服务配置文件。 - 将此配置应用于集群。
除了 install
和 inject
,profile
也是一个纯文本操作。查看生成的配置文件:
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
creationTimestamp: null
name: webapp.booksapp.svc.cluster.local
namespace: booksapp
spec:
routes:
- condition:
method: GET
pathRegex: /
name: GET /
- condition:
method: POST
pathRegex: /authors
name: POST /authors
- condition:
method: GET
pathRegex: /authors/[^/]*
name: GET /authors/{id}
- condition:
method: POST
pathRegex: /authors/[^/]*/delete
name: POST /authors/{id}/delete
- condition:
method: POST
pathRegex: /authors/[^/]*/edit
name: POST /authors/{id}/edit
- condition:
method: POST
pathRegex: /books
name: POST /books
- condition:
method: GET
pathRegex: /books/[^/]*
name: GET /books/{id}
- condition:
method: POST
pathRegex: /books/[^/]*/delete
name: POST /books/{id}/delete
- condition:
method: POST
pathRegex: /books/[^/]*/edit
name: POST /books/{id}/edit
复制代码
name
指的是你的 Kubernetes 服务的 FQDN,
在这个实例中 webapp.booksapp.svc.cluster.local
。
Linkerd 使用请求的 Host
头将服务配置文件与请求相关联。
当代理看到 webapp.booksapp.svc.cluster.local
的 Host
头时,
它将使用它来查找服务配置文件的配置。
路由是包含方法(例如 GET
)和匹配路径的正则表达式的简单条件。
这允许您将 REST 风格的资源组合在一起,而不是看到一个巨大的列表。
路由的名称可以是您喜欢的任何名称。对于此 demo,该方法附加到路由正则表达式。
要获取 authors
和 books
的配置文件,您可以运行:
curl -sL https://run.linkerd.io/booksapp/authors.swagger \
| linkerd -n booksapp profile --open-api - authors \
| kubectl -n booksapp apply -f -
curl -sL https://run.linkerd.io/booksapp/books.swagger \
| linkerd -n booksapp profile --open-api - books \
| kubectl -n booksapp apply -f -
复制代码
当您使用 linkerd viz tap
时,很容易验证这一切是否有效。
每个实时请求都会显示正在看到的 :authority
或 Host
标头以及正在使用的 :path
和 rt_route
。
运行:
linkerd viz tap -n booksapp deploy/webapp -o wide | grep req
复制代码
这将观察流经 webapp
的所有实时请求,看起来像:
req id=0:1 proxy=in src=10.1.3.76:57152 dst=10.1.3.74:7000 tls=true :method=POST :authority=webapp.default:7000 :path=/books/2878/edit src_res=deploy/traffic src_ns=booksapp dst_res=deploy/webapp dst_ns=booksapp rt_route=POST /books/{id}/edit
复制代码
As you can see:
:authority
是正确的 host:path
正确匹配rt_route
包含 route 名称
这些指标是 linkerd viz routes
命令的一部分,
而不是 linkerd viz stat
。
要查看到目前为止累积的指标,请运行:
linkerd viz -n booksapp routes svc/webapp
复制代码
这将输出所有观察到的路由及其黄金指标的表。
[DEFAULT]
路由是所有与服务配置文件不匹配的所有内容。
配置文件可用于观察传出(outgoing)请求以及传入(incoming)请求。 为此,请运行:
linkerd viz -n booksapp routes deploy/webapp --to svc/books
复制代码
这将显示源自 webapp
deployment 并发往 books
服务的所有请求和路由。
与在调试部分使用 tap
和 top
视图类似,此 demo 中错误的根本原因很明显:
ROUTE SERVICE SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
DELETE /books/{id}.json books 100.00% 0.5rps 18ms 29ms 30ms
GET /books.json books 100.00% 1.1rps 7ms 12ms 18ms
GET /books/{id}.json books 100.00% 2.5rps 6ms 10ms 10ms
POST /books.json books 52.24% 2.2rps 23ms 34ms 39ms
PUT /books/{id}.json books 41.98% 1.4rps 73ms 97ms 99ms
[DEFAULT] books - - - - -
复制代码
重试
由于更新代码和推出新版本可能需要一段时间,让我们告诉 Linkerd 它可以重试对失败端点的请求。这会
增加请求延迟,因为请求将被多次重试,并不需要推出新版本。
在这个应用中,从 books
deployment 到 authors
service 的请求成功率很低。
要查看这些指标,请运行:
linkerd viz -n booksapp routes deploy/books --to svc/authors
复制代码
输出应如下所示:
ROUTE SERVICE SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
DELETE /authors/{id}.json authors - - - - -
GET /authors.json authors - - - - -
GET /authors/{id}.json authors - - - - -
HEAD /authors/{id}.json authors 50.85% 3.9rps 5ms 10ms 17ms
POST /authors.json authors - - - - -
[DEFAULT] authors - - - - -
复制代码
有一点很清楚,从书籍到作者的所有请求都发送到 HEAD /authors/{id}.json
路由,
并且这些请求在大约 50% 的时间内失败。
为了更正这个问题,让我们编辑 authors 服务配置文件并使那些请求可重试,运行以下命令:
kubectl -n booksapp edit sp/authors.booksapp.svc.cluster.local
复制代码
您需要将 isRetryable
添加到特定路由。它应该看起来像:
spec:
routes:
- condition:
method: HEAD
pathRegex: /authors/[^/]*\.json
name: HEAD /authors/{id}.json
isRetryable: true ### ADD THIS LINE ###
复制代码
编辑服务配置文件后,Linkerd 将开始自动重试对该路由的请求。我们可以看到通过运行以下命令:
linkerd viz -n booksapp routes deploy/books --to svc/authors -o wide
复制代码
这应该是这样的:
ROUTE SERVICE EFFECTIVE_SUCCESS EFFECTIVE_RPS ACTUAL_SUCCESS ACTUAL_RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
DELETE /authors/{id}.json authors - - - - - 0ms
GET /authors.json authors - - - - - 0ms
GET /authors/{id}.json authors - - - - - 0ms
HEAD /authors/{id}.json authors 100.00% 2.8rps 58.45% 4.7rps 7ms 25ms 37ms
POST /authors.json authors - - - - - 0ms
[DEFAULT] authors - - - - - 0ms
复制代码
你会注意到 -o wide
标志在 routes
视图中添加了一些列。
这些显示了 EFFECTIVE_SUCCESS
和 ACTUAL_SUCCESS
之间的区别。
这两者之间的差异表明重试的效果如何。
EFFECTIVE_RPS
和 ACTUAL_RPS
显示有多少请求被发送到目标服务,
以及有多少请求被客户端的 Linkerd 代理接收。
现在自动重试,成功率看起来不错,但 p95 和 p99 延迟增加了。这是可以预料的,因为重试需要时间。
超时
Linkerd 可以限制在传出请求到另一个服务失败之前等待的时间。
这些超时通过向服务配置文件的路由配置添加另一个 key 来工作。
首先,让我们看一下从 webapp
到 books
服务的请求的当前延迟:
linkerd viz -n booksapp routes deploy/webapp --to svc/books
复制代码
这应该类似于:
ROUTE SERVICE SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
DELETE /books/{id}.json books 100.00% 0.7rps 10ms 27ms 29ms
GET /books.json books 100.00% 1.3rps 9ms 34ms 39ms
GET /books/{id}.json books 100.00% 2.0rps 9ms 52ms 91ms
POST /books.json books 100.00% 1.3rps 45ms 140ms 188ms
PUT /books/{id}.json books 100.00% 0.7rps 80ms 170ms 194ms
[DEFAULT] books - - - - -
复制代码
对 books
服务的 PUT /books/{id}.json
路由的请求包括当该服务调用 authors
服务
作为服务这些请求的一部分时的重试,如上一节所述。这以额外的延迟为代价提高了成功率。
出于本 demo 的目的,让我们为对该路由的调用设置 25 毫秒超时。
您的延迟数字将根据集群的特征而有所不同。
要编辑 books
服务配置文件,请运行:
kubectl -n booksapp edit sp/books.booksapp.svc.cluster.local
复制代码
更新 PUT /books/{id}.json
路由以设置超时:
spec:
routes:
- condition:
method: PUT
pathRegex: /books/[^/]*\.json
name: PUT /books/{id}.json
timeout: 25ms ### ADD THIS LINE ###
复制代码
Linkerd 现在将在达到超时时将错误返回给 webapp
REST 客户端。
此超时包括重试请求,并且是 REST 客户端等待响应的最长时间。
运行 routes
以查看发生了什么变化:
linkerd viz -n booksapp routes deploy/webapp --to svc/books -o wide
复制代码
现在发生超时,指标将发生变化:
ROUTE SERVICE EFFECTIVE_SUCCESS EFFECTIVE_RPS ACTUAL_SUCCESS ACTUAL_RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
DELETE /books/{id}.json books 100.00% 0.7rps 100.00% 0.7rps 8ms 46ms 49ms
GET /books.json books 100.00% 1.3rps 100.00% 1.3rps 9ms 33ms 39ms
GET /books/{id}.json books 100.00% 2.2rps 100.00% 2.2rps 8ms 19ms 28ms
POST /books.json books 100.00% 1.3rps 100.00% 1.3rps 27ms 81ms 96ms
PUT /books/{id}.json books 86.96% 0.8rps 100.00% 0.7rps 75ms 98ms 100ms
[DEFAULT] books - - - - -
复制代码
延迟数字包括在 webapp
应用程序本身中花费的时间,
因此预计它们会超过我们为从 webapp
到 books
的请求设置的 25 毫秒超时。
我们可以通过观察路由的有效成功率下降到 100% 以下来看到超时正在起作用。
清理
要从集群中删除 books 应用程序和 booksapp 命名空间,请运行:
curl -sL https://run.linkerd.io/booksapp.yml \
| kubectl -n booksapp delete -f - \
&& kubectl delete ns booksapp
复制代码
我是为少
微信:uuhells123
公众号:黑客下午茶
加我微信(互相学习交流),关注公众号(获取更多学习资料~)
复制代码