前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >istio服务网格进阶最佳实践

istio服务网格进阶最佳实践

作者头像
QQ音乐技术团队
发布2023-10-31 14:38:32
3080
发布2023-10-31 14:38:32
举报

❝作者:delphisfang,目前就职于腾讯音乐/社区产品部/公共框架团队,从事微服务、服务网格等云原生架构的开发与落地。 本文约6000字,预计阅读完毕需要15分钟。

1. 前言

本文从 Service Mesh 开发者的角度,阐述 istio 进阶的个人最佳实践,希望帮助正在入门 istio 的同学节省一点时间,少走一点弯路。

1.1 本文出发点

学会 istio[1] 或 envoy[2] 需要多久?是一周、两周,还是一个月?笔者无法给出准确的答案,那取决于每个人对“学会” 这个标准的定义。网上有不少介绍 istio 的入门文章,如果只是想快速地完成一篇「Service Mesh 综述」的话,看看过往的文章应该已经足够。不过按照笔者的经验,看完之后大概会达到一种浅尝辄止的状态:能说上那么两句,但是仅此而已,不能立即投入线上开发,也无法调试定位具体的问题。如果想要更深入一步,则需要去啃那些「大部头书籍」,花费的时间会成倍增长。

因此,笔者撰写本文的出发点是,尝试找到入门文章与大部头书籍之间的一个平衡,以一篇文章的篇幅,帮助初学者达到「玩转istio」的阶段。也可以说是完成对istio的祛魅,为 istio 的初学者提供一把打开 Service Mesh 进阶之路的钥匙。希望它既不是一篇「入门介绍」,也不是一本巨细靡遗、主次不分的「参考手册」,而是一篇只讲重点、只讲笔者自身经验的最佳实践。

1.2 何为「最佳实践」?

“最佳实践” 这个名词起源于管理领域,但是已经有一些被滥用了。我们可以在网上搜到各式各样的「某某最佳实践」。然而事实上,“最佳实践” 无疑是一个伪命题。这个世界上永远不可能有什么工程实践是最佳的,除非你是 Jeff Dean(冷笑话)。实事求是地说,本文介绍的只是一种还算不错的、可以快速上手的实践。

1.3 何为「进阶」?

我们经常看到有人在简历里写 “熟练掌握某某技术”、“精通某某技术”。那么,到底什么程度才能算精通?精通的那根标准线在哪里?「进阶开发」的英文是 Advanced Programming。Advanced 既有高级的意思,也有先进的含义。高级是指,掌握了这个事物的一些不为初学者所知的、精微的技术细节,能让你完成别人完成不了的工作,或者比别人更快地完成。先进则是指,这个事物本身带来了一些更新颖的、更现代化的想法或理念,比如:Google 在2006年发布的三驾马车论文、Docker 带来的容器思想、Kubernetes 引入的声明式API。

2. 最佳实践的一点方法论

在厘清本文的定位以及标题关键词的含义之后,就可以开始正文部分了。

在面对一个庞大的系统时,我们该如何去掌握它?像 Kubernetes[3] 这种活跃度超级高的开源项目,其代码行数通常是以百万计的,没有人能够清楚地记得所有的细节,也没有这个必要。本文并不会 case by case 地去讲解 istio/envoy 的每一个功能或特性,而是尝试介绍一种通用的工程实践方法,让开发者在需要研究某一项特性时,知道如何快速切入、纵向深挖与横向发散,并快速得出结论、验证原型,最终应用于生产环境。

2.1 三重证据学习法

历史学领域有一个著名的研究方法:三重证据法,即:「传世文献 · 出土文字 · 出土文物」三方相互印证,构成严密的证据链,从而推断出某个历史的真相。在这里我们提出:可以使用类似的思路学习和掌握复杂的技术系统,即:「官方文档 · 源码 · 原型实验」 三位一体,构成一个完整的学习闭环。

2.2 去除不必要的流程或组件

该说法出自Elon Musk 的视频采访 Five Step Improvement Process[4] 中的第2步:Remove unnecessary process,它更广为人知的名字是:奥卡姆剃刀原则。早在2012年,微信之父张小龙在《微信背后的产品观》的讲座中,就不断提到类似的理念:保持简单。我们也认为,在学习乃至设计一个东西的过程中,需要不断地追问:

  • 哪些东西是必不可少的,哪些只是锦上添花?
  • 哪些东西是新颖的,哪些是业界已有的套路?

这个步骤可以大幅降低系统的复杂度和理解成本,为我们节省出大量的时间。拨开表面的那些枝叶,我们才能看清一个东西的骨架,即 “原型”。

2.3 关键词定位

Talk is cheap, Dive into the code. 与启发式的AI神经网络算法相比,大多数工程类的项目都有一个优点:它们的一切奥秘都在源码之中,其行为以及背后驱动的代码都是确定无疑、可以被解释的。这意味着:你一定能在源码中定位到它、读懂它,乃至修改它。如果某个项目的源码在可读性方面做得还还不赖的话,你就可以用关键词定位法快速地锁定代码段,大大节省你的时间。

以 istio 和 envoy 为例,两者均已发展成为数十万行代码的项目。但是得益于高度模块化、可扩展的设计,两者的代码在 可读性 与 内聚度 两方面都达到了很高的水平,这使得关键词检索法能够发挥最大的威力。你甚至不需要一个解析代码的IDE,仅靠grep大法也可以锁定某个特性背后的核心代码。

综合上述几点方法论,可以总结出一套进阶最佳实践

1. 预设问题:带着问题出发,逐个寻找答案,在有限时间内收敛闭环,避免无限发散。

2. 文档调研:了解目标对象是什么、不是什么、边界在哪里、竞品有哪些,它在更大的Landscape中的位置。

3. 原型搭建:搭建目标系统的架构原型,设计实验,验证其行为是否符合自己预期。

4. 深入源码:修改它、重编它、运行它、调试它,让它按照你所指挥的那样去工作。

为了避免本文演变成虚无的、形而上的坐而论道,方法论部分点到为止。

3. istio进阶最佳实践案例

下面以「istio 就近地域路由」这个特性为例,展示这套最佳实践的具体操作过程。「就近地域路由」是一个粒度适中的特性,既不大也不小,很适合用于展示 istio进阶 的最佳实践。

3.1 预设问题

下面的问题是逐层递进的。有些只需要做文档调研就能回答;有些则需要深入源码,甚至运行实验才能得出确切的结论。尽管不同人提出的问题可能会非常不同,但是笔者认为问题列表应该存在一个最低标准,即:将这些问题紧密串联起来,应该要能回答整个架构的每一环是如何工作的,即:每一个环节的输入是什么、输出是什么。

Q1:何为Locality?

Q2:希望就近地域路由如何表现?

Q3:如何驱动envoy的就近地域路由?需要如何配置?

Q4:如何驱动istio的就近地域路由?需要如何配置?

Q5:istio如何获知某个envoy的locality?

Q6:就近地域路由的核心算法是怎么样的?在istio层还是envoy层实现?

3.2 文档调研

3.2.1 何为Locality?

在云计算领域,Locality 通常指二元组 <Region, Availability Zone>,即:<地域, 可用区>。此概念起源于云计算大厂 Amazon[5]。【地域】的划分,是为了尽量靠近当地的用户,使用户获得较低的接入时延;不同地域之间只能通过公网互通。【可用区】的划分,是为了冗余和容灾;可用区之间的网络是互通的,距离在100KM以内,且采用高速光纤相连。这意味着,用户连到A区 或 连到B区,在时延上的差别几乎可以忽略。通常一个可用区就是一个数据中心(即一个机房),规模较大的可用区也可以由多个距离靠近的数据中心组成,形成庞大的服务器集群。

Kubernetes 沿袭了云厂商的提法,支持 Region、AZ 两个级别[6]。而在 istio 中,Locality 则是一个三元组:<Region, Zone, Sub-zone>,即:<地域,可用区,子区>。按照 Istio 官方 [6] 的说法,Sub-zone是为了做更精细的划分,比如:划分到 “机架” 的粒度。

3.2.2 istio就近地域路由策略:Locality failover

很明显,对于【就近路由】这个特性,最直接的诉求就是:istio应该总是尝试将流量转发给距离主调方最近的目标服务实例。这是一个不断做降级 (Failover) 的过程

  1. 如果有与主调方处在同一个 region/zone/sub-zone 的被调实例,则 istio 优先路由给这些实例;否则转到第 2 步。
  2. 如果有与主调方处在同一个 region/zone 的被调实例,则 istio 优先路由给这些实例;否则转到第 3 步。
  3. 如果有与主调方处在同一个 region 的被调实例,则 istio 优先路由给这些实例;否则转到第 4 步。
  4. 将流量路由给其他实例。

在 istio 中,该策略被称为 Locality failover,具体的例子可以参考文献[8]。

3.3 istio原型搭建

3.3.1 理解 istio 架构原型

本节将向读者展示 istio架构[9] 真正必不可少的部件(即原型)是什么,以及在自助学习进阶istio的阶段,我们可以暂时不去关注哪些内容,只聚焦在最核心的部件上。本质上,只有 envoy 与 pilot 两个组件是必不可少的。当然,如果您有充足的时间,建议您还是部署一套 Kubernetes 集群,并在其上部署一套完整的istio系统。

一个完整的 istio service mesh 架构[10] 如上图所示,包含几个要点:

  • 整套 istio 必须部署运行于 Kubernetes 之上。
  • 主调方与被调方均需部署 istio proxy,分别接管 outbound流量 和 inbound流量。
  • istio 的控制面 istiod 包含 Pilot、Citadel、Galley 三个主要的子模块,分别用于下发xDS配置给envoy、管理证书、为其他控制面组件生成配置。

简化理解istio架构:

  • 如今minikube、kind等工具已经使得部署一个 Kubernetes 集群变得非常简单,然而要想在K8s上调试一个istio 集群,您仍然需要具备操纵 K8s Deployment、Pod、ConfigMap 等资源的前置能力。当您需要验证某个 istio 特性时,K8s 这一层的存在,将使你所花费的时间成倍地增长。
  • istio 默认要求在主、被调双方都部署 proxy (即envoy),以接管一切出、入流量。然而如果仔细分析,除了全局限流 (global ratelimit)、服务间调用鉴权 (service authentication) 等几个特性之外,大多数流量治理能力都可以只由 主调方proxy 承担。即是说,架构可以简化为只部署主调方的 proxy。
  • 在istio控制面的三个组件中,pilot是必不可少的,我们需要利用它给数据面的envoy下发xDS配置,驱动envoy按照我们指挥的那样去工作。
  • 综上三点,我们可以得出一套 简化的istio service mesh架构,便于学习-调试-验证阶段的快速切入,如下图所示。

3.3.2 理解envoy层的地域配置:locality endpoint

由第2节的调研结果可知:envoy并不会直接去计算每个目标实例与自己的距离远近,而是由 istio 告知 envoy 每个实例的优先级 (priority);envoy只需要将流量优先转发给 priority值最小的那些实例。

在 envoy 层面,使用 locality endpoint 表示一批拥有相同locality的实例;而locality 和 priority 都是 locality endpoint 的属性,分别用于指明这批实例的 地理位置 和 优先级。

Envoy locality endpoint 配置示例如下:

代码语言:javascript
复制
- name: helloworld
  connect_timeout: 0.1s
  type: static
  lb_policy: ROUND_ROBIN
  load_assignment:
    cluster_name: helloworld
    endpoints:
    - priority: // 第1个实例,位于华南-深圳-01,优先级为0 (最高)
      locality:
        region: south-china
        zone: shenzhen
        sub_zone: 01
      lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: 1.1.1.1
              port_value: 12345
    - priority: // 第2个实例,位于华南-深圳-02,优先级为1
      locality:
        region: south-china
        zone: shenzhen
        sub_zone: 02
      lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: 2.2.2.2
              port_value: 12345
    - priority: // 第3个实例,位于华南-广州-01,优先级为2
      locality:
        region: south-china
        zone: guangzhou
        sub_zone: 
      lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: 3.3.3.3
              port_value: 
    - priority:  // 第4个实例,位于华东-上海-01,优先级为3 (最低)
      locality:
        region: east-china
        zone: shanghai
        sub_zone: 
      lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: 4.4.4.4
              port_value: 

3.3.3 理解istio层的地域配置:DestinationRule

istio 层面的【地域路由】称作 Locality failover,需要使用 DestinationRule [19] 进行配置才能启用。如下面的yaml配置所示,该 DestinationRule 描述了 helloworld 服务的3个核心策略,分别是:connectionPool (连接参数)、loadBalancer (负载均衡策略)、outlierDetection(熔断踢除策略)。其中与【就近地域路由】相关的配置就是第2项:localityLbSetting。需要注意的是:必须同时有 outlierDetection 配置项,locality failover 才能生效。

istio DestinationRule locality failover 配置示例如下:

代码语言:javascript
复制
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: helloworld
  namespace: demo-namespace
spec:
  host: helloworld.svc.cluster.local
  trafficPolicy:
    connectionPool:
      http:
        maxRequestsPerConnection: 100
    loadBalancer:
      simple: ROUND_ROUBIN
      localityLbSetting: // 启用 locality failover 策略
        enabled: true
        failover: []
    outlierDetection: // 必须有该配置项,locality策略才能生效
      consecutive5xxErrors: 
      interval: 5s
      baseEjectionTime: 1m

3.4 深入istio源码

3.4.1 读懂istio地域路由的核心算法

源码路径:https://github.com/istio/istio/blob/master/pilot/pkg/networking/core/v1alpha3/loadbalancer/loadbalancer.go#L158

在 istio 源码中,尝试检索关键词 Locality 和 Failover,可以看到:确实有一个名为 applyLocalityFailover 的函数(如上述源码所示)。阅读该函数的注释,不难发现:该函数正是 Locality Failover 的核心算法实现。该函数通过计算 endpoint locality 与 envoy locality 的匹配程度,得出 endpoint 的 priority。当然,这个priority值仅仅只是针对该envoy来说的。换成另一个envoy,计算出来的endpoint priority就可能完全不同。

核心算法如下:

  1. 若 region/zone/sub-zone 三层均匹配,则将实例的priority设置为0。
  2. 若仅 region/zone 两层匹配,则将实例的priority设置为1。
  3. 若仅 region 匹配,则将实例的priority设置为2。
  4. 若均不匹配,则将实例的priority设置为3。

3.4.2 istio 如何获知每个服务实例的 Locality?

我们知道,每一个 istio Service Entry [17] 都用于唯一表示一个服务,包括隶属于该服务的所有实例 (endpoint)。而 Locality 又是 endpoint 的一个属性。因此,实例的Locality一定存在于 ServiceEntry 对象中,如下面的yaml配置所示。istio 通过解析 ServiceEntry 对象,即可获知每个实例的Locality。

Service Entry locality 配置示例如下:

代码语言:javascript
复制
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: helloworld
  namespace: demo-namespace
spec:
  hosts: 
  - helloworld.svc.cluster.local
  ports:
  - number: 
    name: helloworld
    protocol: HTTP
  resolution: static
  endpoints:
  - address: 1.1.1.1
    locality: south-china/shenzhen/01
  - address: 2.2.2.2
    locality: south-china/shenzhen/02
  - address: 3.3.3.3
    locality: south-china/guangzhou/01
  - address: 4.4.4.4
    locality: east-china/shanghai/01

3.4.3 istio 如何获知每个 envoy 的 Locality?

源码路径:https://github.com/istio/istio/blob/master/pilot/pkg/model/context.go

如上面的 istio 源码所示:在 istio 中,每一个连接到它的 envoy 实例都由一个Proxy对象唯一表示,其中就包含Locality属性。而 Locality 的取值就存放在该envoy实例的 bootstrap 启动配置文件中。

4. istio进阶知识点

1. envoy 并不依赖 容器 与 Kubernetes,可以部署在虚拟机、物理机乃至裸金属环境上。

2. envoy 也不依赖 istio,而是反过来,istio 选择了 envoy 作为数据面组件。

3. 在 envoy 层面,服务、实例、路由配置、监听器 等所有资源都被定义为 xDS API [14],可以动态获取。当然,这些资源也可以静态配置在 envoy bootstrap 配置文件 [15] 中。在调试验证阶段,采用静态配置的方式显然会方便很多。

4. 在 istio 层面,沿袭了 K8s 的设计,使用 CRD (Custom Resource Definition [16]) 表示各种资源。其中,最核心的CRD有3个:

  • istio Service Entry [17] 用于定义一个服务及其下的实例列表。
  • istio Virtual Service [18] 用于定义一个服务的流量路由策略 (traffic routing)。
  • istio Destination Rule [19] 用于定义一个服务的关键参数,包括:连接参数、负载均衡策略、故障踢除策略。

5. 虽然 istio 控制面包含有若干个子模块:pilot、citadel、galley,但在大多数应用场景下,只有 pilot 是必不可少的。一套最简单的 Istio Service Mesh 可以只部署 pilot 和 envoy,让 envoy 连接到 pilot 动态拉取资源。更极致地,你可以只部署 envoy,将实验所需的资源都写在 envoy bootstrap config 中。

6. 虽然 envoy 的代码量已经超过了 70w 行,istio 的代码量超过了 30w 行,但是不必担心,也不要企图搞清楚每一处细节。你甚至不需要一款全功能的IDE,有需要时可以直接搜索关键词。

7. 虽然本文的标题是「istio进阶最佳实践」,不过本实践路径并不局限于学习 istio,也适用于其他开源技术 (尤其是云原生技术) 的学习与进阶。

5. istio 进阶技术文档

[1] The istio service mesh.

https://istio.io/latest/about/service-mesh/

[2] Envoy proxy.

https://www.envoyproxy.io/

[3] Kubernetes Github.

https://github.com/kubernetes/kubernetes

[4] Elon Musk Five Step Improvement Process.

https://www.youtube.com/watch?v=Jgw-_hlFQk4

[5] AWS Regions & Zones.

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html

[6] K8s Topology Aware Routing.

https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/

[7] Istio Locality Load Balancing.

https://istio.io/latest/docs/tasks/traffic-management/locality-load-balancing/

[8] Istio Locality failover.

https://istio.io/latest/docs/tasks/traffic-management/locality-load-balancing/failover/

[9] Istio architecture.

https://istio.io/latest/zh/docs/ops/deployment/architecture/

[10] Istio Locality weighted distribution.

https://istio.io/latest/docs/tasks/traffic-management/locality-load-balancing/distribute/

[11] Envoy Locality weighted load balancing.

https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/locality_weight

[12] Envoy Priority Levels.

https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/priority#arch-overview-load-balancing-priority-levels

[13] Envoy Advanced.

https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/advanced

[14] Envoy xDS API.

https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/operations/dynamic_configuration

[15] Envoy bootstrap config example.

https://www.envoyproxy.io/docs/envoy/latest/configuration/overview/examples

[16] Kubernetes CRD.

https://kubernetes.io/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/

[17] Istio Service Entry.

https://istio.io/latest/docs/reference/config/networking/service-entry/

[18] Istio Virtual Service.

https://istio.io/latest/docs/reference/config/networking/virtual-service/

[19] Istio Destination Rule.

https://istio.io/latest/docs/reference/config/networking/destination-rule/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-10-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯音乐技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1 本文出发点
  • 1.2 何为「最佳实践」?
  • 1.3 何为「进阶」?
  • 2. 最佳实践的一点方法论
  • 2.1 三重证据学习法
  • 2.2 去除不必要的流程或组件
  • 2.3 关键词定位
  • 3. istio进阶最佳实践案例
  • 3.1 预设问题
  • 3.2 文档调研
    • 3.2.2 istio就近地域路由策略:Locality failover
    • 3.3 istio原型搭建
      • 3.3.1 理解 istio 架构原型
      • 3.4 深入istio源码
      • 3.4.1 读懂istio地域路由的核心算法
        • 3.4.2 istio 如何获知每个服务实例的 Locality?
        • 4. istio进阶知识点
        • 5. istio 进阶技术文档
        相关产品与服务
        服务网格
        服务网格(Tencent Cloud Mesh, TCM),一致、可靠、透明的云原生应用通信网络管控基础平台。全面兼容 Istio,集成腾讯云基础设施,提供全托管服务化的支撑能力保障网格生命周期管理。IaaS 组网与监控组件开箱即用,跨集群、异构应用一致发现管理加速云原生迁移。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档