• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

linkerd服务网格调研笔记

武飞扬头像
Sindweller5530
帮助1

简介

Linkerd是一个k8s的服务网格,通过提供运行时调试、可观察性、可靠性和安全性来保证更简单安全地运行服务。这些功能都不需要对你的代码进行修改。

什么是服务网格?

服务网格是一个专注于处理服务间通信的基础设施层,是应用开发和交付问题的解决方案。

从架构上来看,它就是一束用户空间代理,位置卡在了服务的"next",额外的会有一组管理进程。

学新通

那些用户空间代理被称为服务网格的data plane,那些管理进程成为了服务网格的control plane。
数据层拦截服务之间的调用并且使用这些调用来做一些事,控制层协调代理之间的行为并提供API,operator负责操作和测量整个网格。

  • 数据层/代理是什么? 它们是第7层感知TCP代理,就像是haproxy或NGINX。不同服务网格选择的代理不同,Linkerd使用的Linkerd-proxy是用Rust写的微代理,专门给Linkerd使用。其他的服务网格会使用不同的代理——Envoy是一种普遍的选择。但选择代理已经是实现方面的细节。
  • 数据层/代理做什么? 代理在服务之间被调用,更准确地说,它们的行为包括“代理”和“反向代理”,会处理传入传出的调用。并且它们实现了一个功能集,关注于服务之间的调用。这些对服务间流量的关注重点是区分服务网格代理和api网关或ingress代理的重点,后者关注于来自外界对集群的调用。
  • 控制层是什么? 控制层是一组组件,提供那些数据面以协调方式运行所需的任何机制,包括服务发现,TLS证书颁发,指标聚合等。数据层调用控制层来通知其行为,控制面反过来提供一个API来允许用户去修改并检查数据面的行为。
    以Linkerd控制层&数据层为例,控制层的组件包括小型Prometheus实例(聚合代理的指标数据),服务发现组件destination,证书授权identity,web和cli终端public-api。数据层则只是一个简单的linkerd-proxy,位于一个服务应用的"next"。(这只是一个逻辑图,实际部署可能会得到每个控制面组件的三个副本,成百上千个数据面代理)
    在逻辑图中的蓝色盒子是k8s pod的边界。linkerd-proxy跟应用的容器跑在一个pod里,称sidecar容器。

Sidecar,微服务中“用于端对端通信的、被单独分离出来的“组件

学新通

服务网格的更进一步解释

上文中所说的sidecar容器是一个代理实例,这个代理实例最终实现了服务网格。它会包含在每一个service中(app proxy=pod)。这个sidecar负责处理服务之间的通信、监控以及一些安全方面(这些安全内容可以从服务本体中抽象出来)。这样服务间通信变成了sidecar proxy之间通信。

服务网格的一些功能举例:
关于proxy可以实现的服务发现功能:当一个实例需要与其他服务进行通讯时,它需要“寻找并发现”另一个健康、可用的服务实例。对应这件事,k8s维护着一个时刻准备接受请求的实例列表。
关于服务网格可以实现的安全内容:服务网格可以加密和解密服务间的请求与响应,而且这一步操作是独立于服务之外的,这样每个服务内部无需去处理这个加解密步骤了。尽管服务网格在发起请求的时候要创建新的TCP连接(详见下文中的附:什么是Layer 7 proxy),但它可以优先再利用已存在的持续连接来提高性能。除加解密之外,服务网格对于服务间请求也可以进行授权和认证,只发送那些有效的请求给服务。
熔断器模式:隔离不健康的实例,或将实例再次添加进健康实例池。
控制面的工作内容:创建新实例,终止不健康或不需要的实例,服务监控,集成监控与管理,实施应用范围的策略,或将整个应用优雅结束掉。控制面一半被设计成用于连接api、命令行工具或者一个用于管理整个应用的可视化用户界面。

为什么要用到服务网格?研发人员在专注于开发服务,运维人员负责维护服务网格,运行app即可。

附:什么是Layer 7 proxy

四层负载均衡和七层负载均衡的区别:
L4 工作于传输层,负责处理消息的传递,不管消息内容。TCP就是HTTP传输方式的四层协议(Layer 4 Protocol)。L4的负载均衡只针对由上游服务发送和接收的网络报,而不检查包内的具体内容是什么。L4可以通过检查TCP流中的前几个包来决定是否限制路由。
L7工作于应用层(顶层),也就是将负载均衡部署在应用层上,处理每条消息中的真正内容(L4不检查具体内容)。L7适合HTTP这种基于TCP传输的方式。一个L7负载均衡会终止网络传输并读取消息中的内容,基于其中的内容(比如URL和cookie)来作出负载均衡的决策。之后,L7负载均衡会建立一个新的TCP连接(或选择一个已存在的TCP连接通过keepalives方式)来选择上游服务并对服务发出请求.
L7的优势:运用缓存的方式来卸载上游服务较慢的连接,显著提高性能。使用L7的设备经常被用于反向代理。
L7举例:L7让均衡器根据请求的具体信息来进行路由,比如针对图片或视频的静态内容请求被路由到多媒体内容服务器,事物型信息路由到应用服务器。利用L7可以建立一个高速调整、高度优化、针对需求可靠且可扩展的服务基础架构或应用传递网络。

服务网格架构的含义

  • 代理功能集是出于被服务间调用而设计的,只有你的应用构建为服务时,服务网格才具有意义。你可以将它与单体应用程序一起食用,但运行单个代理将是一大堆机器,并且功能集不太适用。另一个后果是服务网格将需要大量代理。 事实上,Linkerd 为每个服务的每个实例添加了一个链接器代理(Linkerd-proxy)。其他的一些服务网格的实现是为每个node/host/vm添加一个代理,也很多。大量代理的使用本身有几个含义:
    • 无论这些数据面的代理是什么,它们都最好非常快。你正在为每个调用添加两个代理跃点,一个在client一个在server。
    • 代理需要小而轻量,每一个代理都会消耗内存和cpu,这种消耗会与你的应用线性相关。
    • 你需要一个系统来部署和更新代理,你不会想手动操作它。
  • 至少在10,000ft级别,这些就是服务网格的全部了:你部署大量userspace代理来向内部和“服务到服务”流量“做一些事”,并且你使用控制面来更改它们的行为并查询它们生成的数据。

回到Linkerd

linkerd具有三个组件:

  • 一个UI
  • 一个数据面
  • 一个控制面

运行linkerd可以通过:

  1. 在本地环境中安装cli
  2. 在集群中安装控制面
  3. 将你的服务添加进linkerd的数据面

当一个服务带着linkerd一同运行,你可以使用linkerd的ui来检查并操纵这个服务。

linkerd是如何工作的?(监控与操纵出入服务的流量)

linkerd在每个服务实例“旁边”安装一个轻量级同名代理(app与proxy在同一个pod中,proxy代理了所有出入流量)。这些代理自动处理服务的所有出入流量。因为它们是透明的,这些代理充当高度仪表化的进程外网络堆栈,发送遥测给控制面并从控制面接收信号。这种设计允许Linkerd来测量和操纵流量出入你的服务,并不会引入过多的延迟。
为了尽可能地小而轻量且安全,linkerd的代理由Rust编写(rust容易写出轻量的组件)并为linkerd特制。(同时控制层是用go写的)

  1. 安装cli
    curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | sh
    结果:
Linkerd stable-2.11.1 was successfully installed 🎉


Add the linkerd CLI to your path with:

  export PATH=$PATH:/Users/sindweller/.linkerd2/bin

Now run:

  linkerd check --pre                     # validate that Linkerd can be installed
  linkerd install | kubectl apply -f -    # install the control plane into the 'linkerd' namespace
  linkerd check                           # validate everything worked!
  linkerd dashboard                       # launch the dashboard
  1. 验证linkerd
    linkerd check --pre
    结果:
Status check results are √
  1. 向你的k8s cluster里安装控制面
    linkerd install | kubectl apply -f -
    linkerd install 命令会生成一个k8s的manifest,包含所有核心控制面资源,将此manifest导入 kubectl apply 然后指示 Kubernetes 将这些资源添加到您的集群中。
  2. 验证控制面
    linkerd check
    这一步用了相当长的时间。遇到一个报错:
× control plane pods are ready
    No running pods for "linkerd-destination"

根据报错来检查一下control面的pod: kubectl -n linkerd get po

sindweller@xindeweiladeMacBook-Pro ~ % kubectl -n linkerd get po
NAME                                     READY   STATUS                  RESTARTS   AGE
linkerd-destination-7848d79549-6fdpl     0/4     Init:0/1                0          9m55s
linkerd-heartbeat-27406998-7wn72         0/1     ContainerCreating       0          32s
linkerd-identity-6b78ff444f-nj6vr        0/2     Init:ImagePullBackOff   0          9m55s
linkerd-proxy-injector-6469747db-bhq4s   0/2     Init:0/1                0          9m55s

发现是img没有pull下来

Warning  Failed     2m14s               kubelet            Error: ImagePullBackOff
Normal   Pulling    2m1s (x2 over 14m)  kubelet            Pulling image "cr.l5d.io/linkerd/proxy-init:v1.4.0"

自己用docker pull 了一下这个img cr.l5d.io/linkerd/proxy-init:v1.4.0 成功pull下来了。
由于用的kind创建的k8s集群,所以需要把本地的镜像加载进kind里:

sindweller@xindeweiladeMacBook-Pro ~ % kind load docker-image cr.l5d.io/linkerd/proxy-init:v1.4.0
Image: "cr.l5d.io/linkerd/proxy-init:v1.4.0" with ID "sha256:a69eedfa2d4e8f04c60e7420ad0b32d28cc4cb6404350bf39d1a253915bcc7cf" not yet present on node "kind-control-plane", loading...

这样的话删除ns后再次安装

kubectl delete ns linkerd
linkerd install | kubectl apply -f -

然后使用kubectl -n linkerd describe po linkerd-destination-d86c59855-rpccx查看一下pod内事件,发现

 Normal  Pulled     19s   kubelet            Container image "cr.l5d.io/linkerd/proxy-init:v1.4.0" already present on machine

说明本地pull的镜像已经加载进kind节点里了
在pull了一堆kind无法直接pull的镜像后,check通过

Status check results are √
  1. 安装demo app
  • demo app 介绍: 这是一个包含gRPC和HTTP调用来允许用户给他们最喜欢的emojis投票的app。在emojivoto的ns中安装这个app:
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/emojivoto.yml \
  | kubectl apply -f -

但linkerd还并没有起作用,我们需要把这个app“网格化”。但在此之前,先看一下emojivoto的自然状态。我们通过将流量转发到他的web-svc服务来做到这一点,这样我们可以将浏览器指向他。运行以下命令来在本地将web-svc转发到8080端口
kubectl -n emojivoto port-forward svc/web-svc 8080:80
这个时候去访问http://localhost:8080就可以看到emojivoto。(点击巧克力圈会导致一个404 err,这是故意的,为了之后用linkerd来验证这个问题)
6. 通过添加linkerd数据面代理来网格化这个app

kubectl get -n emojivoto deploy -o yaml \
  | linkerd inject - \
  | kubectl apply -f -

这个命令检索所有在emojivoto命名空间内运行的deploys,通过linkerd inject运行它们的manifests。随后,重新apply至cluster。(linkerd inject命令只是在向pod的spec里添加一些annotations,这些注解指示linkerd在创建pod时将porxy注入到pod中。)
现在已经将linkerd添加进了一个app中。
7. 检查数据面 linkerd -n emojivoto check --proxy
8. 访问8080

继续探索linkerd

emojivoto看起来在加上linkerd之后并无变化,为了展示linkerd实际上做了什么,需要安装一个扩展。linkerd的核心控制面非常迷你,所以linkerd附带扩展,扩展会给linkerd添加一些非关键但非常好用的功能,包括一些dashboard。
于是我们添加一些内容(二选一):

  1. viz扩展,会安装一个在cluster上的指标堆栈 linkerd viz install | kubectl apply -f -
  2. 或者buoyant-cloud扩展,它连接了一个托管的指标堆栈
curl --proto '=https' --tlsv1.2 -sSfL https://buoyant.cloud/install | sh # get the installer
linkerd buoyant install | kubectl apply -f -

无论安装了哪一个扩展,之后再次检查一下:
linkerd check

然后就可以使用viz的dashboard,linkerd viz dashboard & 会看到一个界面:
学新通

debug模式

使用linkerd来诊断一些不至于让整个服务崩溃的小问题。

通过将ns选取为emojivoto来查看关于这个app的deploy的状态信息。包含:成功率、每秒请求数、延迟分位数

学新通

这里会发现web的成功率低于100%,点击web

学新通

查看web deploy的页面,可以看到这个web deploy会从vote-bot接收流量(vote-bot持续生成低水平的实时流量),web deploy有两个传出依赖——emoji和voting。

  • emoji deploy处理来自web的请求,并且全都成功
  • voting deploy会有一些处理失败的请求

deploy依赖(emoji&voting)中的失败可能是导致web返回错误的原因。

继续查看页面的后续部分,会看到一个关于所有出入web的流量的实时列表。
在tools-top里选择ns为emojivoto之后点击start,可以获取出入流量

学新通

按照教程中的点击web之后下拉也会看到一些api调用

学新通

从deployments的tcp metrics点击web进入会看到教程中所说的两个失败

学新通

因为/api/vote是一个传入调用而VoteDoughnut是一个传出调用,因此这是一个很好的线索,表明这个端点是导致问题的原因!

更深入探索一下原因,可以点击列表右侧的tap图标,就可以看到仅匹配此端点的请求的实时列表。可以看到GRPC status是Unknown,这是因为请求失败返回了GRPC status code 2。

学新通

Linkerd 无需任何其他配置即可知道 gRPC 的响应分类!

点击下拉按钮可以获取更多请求细节~

学新通

至此,我们拥有修复端点和恢复应用程序整体健康所需的一切

遇到的一些报错

  1.  
Error running port-forward: unable to listen on any of the requested ports: [{50750 8084}] for linkerd-viz/web-db97ff489-rl28g
Check for `linkerd dashboard` running in other terminal sessions, or use the `--port` flag.

这里是重复启动了,ps axu |grep linkerd一下,杀掉之前的linkerd dashboard进程就好了。
2.

 linkerd viz top deploy/web -n emojivoto
Error: no pods to tap for deployment/web
1 pods found with tap not enabled:
	* web-5f86686c4d-q5wlt
restart these pods to enable tap and make them valid tap targets

没有启用tap,按照报错提示的重新启动这个pod就好了:
kubectl -n emojivoto delete po web-5f86686c4d-q5wlt
然后再次使用viz的top命令
linkerd viz top deploy/web -n emojivoto
就可以看到出入流量

Source                     Destination             Method      Path                                                    Count    Best   Worst    Last  Success Rate
web-5f86686c4d-vqrrg       emoji-696d9d8f95-stw4f  POST        /emojivoto.v1.EmojiService/ListAll                         90     2ms     5ms     3ms       100.00%
vote-bot-6d7677bb68-7qmxx  web-5f86686c4d-vqrrg    GET         /api/list                                                  90     4ms    11ms     7ms       100.00%
web-5f86686c4d-vqrrg       emoji-696d9d8f95-stw4f  POST        /emojivoto.v1.EmojiService/FindByShortcode                 90     1ms     6ms     2ms       100.00%
vote-bot-6d7677bb68-7qmxx  web-5f86686c4d-vqrrg    GET         /api/vote                                                  90     6ms    16ms    13ms        74.44%
web-5f86686c4d-vqrrg       voting-ff4c54b8d-vhqwn  POST        /emojivoto.v1.VotingService/VoteDoughnut                   23     2ms     4ms     3ms         0.00%
web-5f86686c4d-vqrrg       voting-ff4c54b8d-vhqwn  POST        /emojivoto.v1.VotingService/VotePointUp2                    3     2ms     3ms     3ms       100.00%
web-5f86686c4d-vqrrg       voting-ff4c54b8d-vhqwn  POST        /emojivoto.v1.VotingService/VoteTaco                        3     2ms     3ms     3ms       100.00%
  1. 正在运行着的viz dashboard报错:
E0210 16:10:15.826094   48128 portforward.go:400] an error occurred forwarding 50750 -> 8084: error forwarding port 8084 to pod 1a64581654541315cbc6e5dc95e098c668ce871a00a1700c60369959e9cb4930, uid : failed to find sandbox "1a64581654541315cbc6e5dc95e098c668ce871a00a1700c60369959e9cb4930" in store: not found
E0210 16:10:26.563891   48128 portforward.go:400] an error occurred forwarding 50750 -> 8084: error forwarding port 8084 to pod 1a64581654541315cbc6e5dc95e098c668ce871a00a1700c60369959e9cb4930, uid : failed to find sandbox "1a64581654541315cbc6e5dc95e098c668ce871a00a1700c60369959e9cb4930" in store: not found

还是一样,杀掉重启

linkerd和istio的优劣

Istio也是一个非常流行的服务网格。主要列出以下几点linkerd的优势

  • 适配相对较容易,有内置和开箱即用的配置,不需要去进行过多的配置。从这个角度来说,配置灵活性可能导致运维团队的负担。
  • ingress controller: inkerd本身不提供ingress功能,可以接入任何ingress controller
  • 设计轻巧,比Istio快。

代理功能

  • HTTP、HTTP/2 和任意 TCP 协议的透明、零配置代理。
  • 自动为 HTTP 和 TCP 流量导出 Prometheus 指标。
  • 透明的零配置 WebSocket 代理。
  • 自动的、可感知延迟的 7 层负载均衡。
  • 非 HTTP 流量的自动的 4 层负载均衡。
  • 按需诊断 tap API。

为什么微服务需要服务网格?

目前的微服务开发模式中,对于每个服务有一些重复性的基础工作,例如:

  • 服务注册
  • 服务发现
  • 得到服务实例后,负载均衡
  • 熔断机制

这些基础工作需要开发人员在项目中用代码解决并实现,即使用库或框架也十分麻烦。
那么是否可以把这些重复性的基础工作从服务中抽离出来?

首先要考虑的是这些工作所处的位置,解决的是什么问题:这些工作集中在处理各个服务之间的通信。

那么我们可以专注于服务间通信,形成单独的组件运行在微服务中。这种组件称为sidecar。这样做的好处是:微服务中的业务逻辑与服务通信解耦,分离成两个独立运行的组件。

以组件作为服务间通信的解决方案,还存在一个可以优化的地方,即每个微服务的sidecar无法通用,如果能将组件拆出来分配给任意微服务使用的话,将构成一个更加通用且简单的解决方案。

因此,在sidecar上更进一步,构建一个专注于处理服务间通信的基础设施层——服务网格。app无需考虑微服务中的通讯部分。在服务网格中,每个微服务至少拥有两个组件:1. 用于处理业务功能的app 2. 专门处理服务间通信的proxy/sidecar。

因此,在开发微服务时,研发人员无需考虑服务通信,服务通信由每个微服务的sidecar组件完成,而这些sidecar组件有专门的项目来接管。例如Envory HaProxy和Nginx(还有linkerd-proxy)都可以当作sidecar来使用。

服务网格使开发人员和运维人员的职责范围更清晰且避免重叠,开发人员关注业务开发,运维团队关注微服务中的sidecar就可以了解到微服务的健康情况和各种指标。

总之,服务网格实际上就是处于TCP/IP上的一个抽象层,它有点类似TCP/IP,具备处理网络故障的能力。对于TCP来说,是对网络端点间传输字节的机制进行了抽象,而服务网格是对服务节点间请求的路由机制进行了抽象。(服务网格不关心消息体也不关心如何编码)。服务网格的目标是配合app的“将某些东西从a传送到b”目标,实现这个目标并处理传送过程中的任何故障。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgchjgc
系列文章
更多 icon
同类精品
更多 icon
继续加载