Linkerd

在介绍Linkerd使用之前,我们要知道Linkerd是什么,Linkerd官网是这么介绍的:Linkerd 是 Kubernetes 的服务网格。它通过为您提供运行时调试、可观察性、可靠性和安全性,使运行服务更容易、更安全——所有这些都不需要对您的代码进行任何更改。

Service Mesh是什么

一言以蔽之:Service Mesh 是微服务时代的 TCP/IP 协议。

微服务 (Microservices) 是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关(Language-Independent/Language agnostic) 的 API 集相互通信。

Service Mesh的背景

Phil Calçado的文章《Pattern: Service Mesh》详细介绍了从开发者视角来看,服务开发模式和Service Mesh技术的演化过程。

《什么是 Service Mesh》这篇文章简化了《Pattern: Service Mesh》,方便了我们的理解。

       传统通信时代,因为服务器之间性能不同处理能力的不同,开发者为了确保数据一致性,以及传输的安全可靠性,需要手码通信协议来确保数据一致。为了统一便产生了TCP等协议,在TCP协议出来后,通信协议便下沉到网络层减轻了开发者对数据传输层的考虑。在TCP出现之后,服务又面临了新的问题,比如负载均衡、熔断策略等,于是服务根据业务需求来实现一部分所需的通信语义,随后衍生出一系列微服务的框架,例:Spring Boot/Go-Kit等。可是微服务框架也面临着新的问题,开发者需要对框架本身进行学习了解,以及框架并不适用于所有语言。

       因此以Linkerd,Envoy,NginxMesh为代表的代理模式(边车模式)应运而生,这就是第一代Service Mesh,它将分布式服务的通信抽象为单独一层,在这一层中实现负载均衡、服务发现、认证授权、监控追踪、流量控制等分布式系统所需要的功能,作为一个和服务对等的代理服务,和服务部署在一起,接管服务的流量,通过代理之间的通信间接完成服务之间的通信请求,这样以来微服务时代面临的问题也迎刃而解。目前Service Mesh已发展到第二代,添加了集中式控制面板,方便了所有的单机代理组件通过和控制面板交互进行网络拓扑策略的更新和单机数据的汇报。

Service Mesh架构

服务网格中分为控制平面和数据平面,当前流行的两款开源的服务网格 Istio 和 Linkerd 实际上都是这种构造,只不过 Istio 的划分更清晰,而且部署更零散,很多组件都被拆分,控制平面中包括 Mixer(Istio 1.5 之前版本)、Pilot、Citadel,数据平面默认是用 Envoy;而 Linkerd 中只分为 Linkerd 做数据平面,namerd 作为控制平面。

控制平面

控制平面的特点:

不直接解析数据包

与控制平面中的代理通信,下发策略和配置

负责网络行为的可视化

通常提供 API 或者命令行工具可用于配置版本化管理,便于持续集成和部署

数据平面

数据平面的特点:

通常是按照无状态目标设计的,但实际上为了提高流量转发性能,需要缓存一些数据,因此无状态也是有争议的

直接处理入站和出站数据包,转发、路由、健康检查、负载均衡、认证、鉴权、产生监控数据等

对应用来说透明,即可以做到无感知部署

Linkerd简介

Linkerd是Buoyant公司2016年率先开源的高性能网络代理,是业界的第一款Service Mesh框架。其主要用于解决分布式环境中服务之间通信面临的一些问题,如网络不可靠、不安全、延迟丢包等问题。

Linkerd使用Scala语言编写,运行于JVM,底层基于Twitter的Finagle库,并对其做了相应的扩展。最主要的是Linkerd具有快速、轻量级、高性能等特点,每秒以最小的延迟及负载处理万级请求,易于水平扩展。

Linkerd主要功能

继续抄:Linkerd开源精神

负载平衡:linkerd提供了多种负载均衡算法,它们使用实时性能指标来分配负载并减少整个应用程序的尾部延迟。

熔断:linkerd包含自动熔断,将停止将流量发送到被认为不健康的实例,从而使他们有机会恢复并避免连锁反应故障。

服务发现:linkerd 与各种服务发现后端集成,通过删除特定的(ad-hoc)服务发现实现来帮助您降低代码的复杂性。

动态请求路由:linkerd 启用动态请求路由和重新路由,允许您使用最少量的配置来设置分段服务(staging service),金丝雀(canaries),蓝绿部署(blue-green deploy),跨DC故障切换和黑暗流量(dark traffic)。

重试次数和截止日期:linkerd可以在某些故障时自动重试请求,并且可以在指定的时间段之后让请求超时。

TLS:linkerd 可以配置为使用 TLS 发送和接收请求,您可以使用它来加密跨主机边界的通信,而不用修改现有的应用程序代码。

HTTP代理集成:linkerd 可以作为 HTTP 代理,几乎所有现代 HTTP 客户端都广泛支持,使其易于集成到现有应用程序中。

透明代理:您可以在主机上使用 iptables 规则,设置通过 linkerd 的透明代理

gRPC:linkerd 支持 HTTP/2 和 TLS,允许它路由 gRPC 请求,支持高级 RPC 机制,如双向流,流程控制和结构化数据负载。

分布式跟踪:linkerd 支持分布式跟踪和度量仪器,可以提供跨越所有服务的统一的可观察性。

仪器仪表: linkerd 支持分布式跟踪和度量仪器,可以提供跨越所有服务的统一的可观察性。

Linkerd 架构

这里引用Linkerd中文文档里的介绍。

Linkerd 由一个 控制平面(control plane) 和一个 数据平面(data plane) 组成。

控制平面是一组服务,提供对 Linkerd整体的控制。

数据平面由在每个服务实例“旁边”运行的透明微代理(micro-proxies)组成,作为 Pod中的sidecar。这些代理会自动处理进出服务的所有 TCP流量,并与控制平面进行通信以进行配置。

Linkerd 还提供了一个 CLI,可用于与控制平面和数据平面进行交互。

架构图:

CLI

Linkerd CLI 通常在集群外部运行(例如在您的本地机器上),用于与 Linkerd 交互。

控制平面(control plane)

Linkerd 控制平面是一组在专用 Kubernetes 命名空间(默认为 linkerd)中运行的服务。控制平面有几个组件,列举如下。

目标服务(destination)

数据平面代理使用 destination 服务来确定其行为的各个方面。它用于获取服务发现信息(即发送特定请求的位置和另一端预期的 TLS 身份);获取有关允许哪些类型的请求的策略信息;获取用于通知每条路由指标、重试和超时的服务配置文件信息;和更多其它有用信息。

身份服务(identity)

identity 服务充当 TLS 证书颁发机构, 接受来自代理的 CSR 并返回签名证书。这些证书在代理初始化时颁发,用于代理到代理连接以实现 mTLS。

代理注入器(proxy injector)

proxy injector 是一个 Kubernetes admission controller,它在每次创建 pod 时接收一个 webhook 请求。此 injector 检查特定于 Linkerd 的 annotation(linkerd.io/inject: enabled)的资源。当该 annotation 存在时,injector 会改变 pod 的规范, 并将 proxy-init 和 linkerd-proxy 容器以及相关的启动时间配置添加到 pod 中。

数据平面(data plane)

Linkerd 数据平面包含超轻型微代理,这些微代理部署为应用程序 Pod 内的 sidecar 容器。由于由 linkerd-init(或者,由 Linkerd 的 CNI 插件)制定的 iptables 规则, 这些代理透明地拦截进出每个 pod 的 TCP 连接。

代理(Linkerd2-proxy)

Linkerd2-proxy 是一个用 Rust 编写的超轻、透明的微代理。Linkerd2-proxy 专为 service mesh 用例而设计,并非设计为通用代理。

代理的功能包括:

HTTP、HTTP/2 和任意 TCP 协议的透明、零配置代理。

HTTP 和 TCP 流量的自动 Prometheus 指标导出。

透明、零配置的 WebSocket 代理。

自动、延迟感知、第 7 层负载平衡。

非 HTTP 流量的自动第 4 层负载平衡。

自动 TLS。

按需诊断 Tap API。

还有更多。

代理支持通过 DNS 和目标 gRPC API 进行服务发现。

Linkerd init 容器

linkerd-init 容器作为 Kubernetes init 容器 添加到每个网格 pod 中,该容器在任何其他容器启动之前运行。它使用iptables 通过代理将所有 TCP 流量,路由到 Pod 和从 Pod 发出。

Linkerd 工作原理

这里引用的GitBook里的k8s文档

Linkerd 路由将请求处理分解为多个步骤

(1) IDENTIFICATION:为实际请求设置逻辑名字(即请求的目的服务),如默认将 HTTP 请求 GET 赋值名字 /svc/example

(2) BINDING:dtabs 负责将逻辑名与客户端名字绑定起来,客户端名字总是以 /# 或 /$ 开头,比如

# 假设 dtab 为/env => /#/io.l5d.serversets/discovery/svc => /env/prod# 那么服务名 / svc/users 将会绑定为/svc/users/env/prod/users/#/io.l5d.serversets/discovery/prod/users

(3) RESOLUTION:namer 负责解析客户端名,并得到真实的服务地址(IP + 端口)

(4) LOAD BALANCING:根据负载均衡算法选择如何发送请求

Linkerd部署

这里借鉴的Linkerd中文文档

第一步:检查

在我们做任何操作之前,我们需要确保您可以访问 Kubernetes 集群并在 本地机器上运行 kubectl 命令。(如果您还没有 Kubernetes 集群, 一个简单的选择是在您的本地机器上运行一个。有很多方法可以做到这一点, 包括 kind、k3d、 Docker for Desktop 等更多。)

通过运行以下命令验证您的 Kubernetes 设置:

# kubectl version --short

应该看到包含 Client Version 和 Server Version 组件的输出。

第二步:安装CLI

可以通过以下命令检查Linkerd是否安装过

# env|grep linkerd

将 linkerd 命令行界面 (CLI) 下载到本地机器上。CLI 将允许您与 Linkerd deployment 进行交互。

要手动安装 CLI,请运行:

# curl -fsL| sh

可能会遇到的问题:

这是因为你缺少校验和二进制,安装个openssl

# yum install openssl -y

安装完后我们配置一下环境变量

默认安装到/root/.linkerd2/bin/ 这个目录下# cp /root/.linkerd2/bin/linkerd /usr/bin/

然后,使用以下命令验证 CLI 是否正常运行:

# linkerd version

您会看到 CLI 版本以及 Server version: unavailable。这是因为您尚未在集群上安装 控制平面。是正常情况。

第三步:验证 Kubernetes 集群

在安装 Linkerd 控制平面之前,需要检查并验证所有配置是否正确。要检查你的集群是否符合安装 Linkerd的条件。

# linkerd check --pre

第四步:安装控制平面

# linkerd install | kubectl apply -f -

在此命令中,linkerd install 命令生成一个 Kubernetes manifest, 其中包含所有必要的 控制平面 资源

安装过程中可以通过运行以下命令等待控制面板准备就绪并验证安装是否完成。

# linkerd check

随着几十行✅的打印,我们的Linkerd就可以宣告安装成功了。

附加:探索Linkerd

Linkerd就这样悄无声息的安装完了,因为Linkerd的核心控制平面非常的小,如果我们想仔细看看Linkerd实际上做了什么,那么就需要安装一些扩展,扩展为 Linkerd 添加了非关键但通常有用的功能,包括各种仪表板。

viz 扩展,将安装集群上的指标堆栈(metrics stack)

buoyant-cloud 扩展,将连接到托管的指标堆栈。

这里我们以viz安装为例,请执行:

# linkerd viz install | kubectl apply -f -

最后一次检查校验

# linkerd check

启动viz

# linkerd viz dashboard --address 0.0.0.0 --port 12345

浏览器中访问  ip:port    不出意外的我们报错了。

接下来我们修改Linkerd-viz命名空间下的的Deployment控制器下的web。

# kubectl get deploy -n linkerd-viz

执行以上命令可以看到如下图:

修改web的deploy

# kubectl edit deploy -n linkerd-viz web

将红框框起来的部分=前的内容按照如图修改为.*然后重新运行。然后你就能看到如下界面了。

# linkerd viz dashboard --address 0.0.0.0 --port 12345