❝作者:delphisfang,目前就职于腾讯音乐/社区产品部/公共框架团队,从事微服务、服务网格等云原生架构的开发与落地。
本文约6000字,预计阅读完毕需要15分钟。
1. 前言
本文从 Service Mesh 开发者的角度,阐述 istio 进阶的个人最佳实践,希望帮助正在入门 istio 的同学节省一点时间,少走一点弯路。
学会 istio[1] 或 envoy[2] 需要多久?是一周、两周,还是一个月?笔者无法给出准确的答案,那取决于每个人对“学会” 这个标准的定义。网上有不少介绍 istio 的入门文章,如果只是想快速地完成一篇「Service Mesh 综述」的话,看看过往的文章应该已经足够。不过按照笔者的经验,看完之后大概会达到一种浅尝辄止的状态:能说上那么两句,但是仅此而已,不能立即投入线上开发,也无法调试定位具体的问题。如果想要更深入一步,则需要去啃那些「大部头书籍」,花费的时间会成倍增长。
因此,笔者撰写本文的出发点是,尝试找到入门文章与大部头书籍之间的一个平衡,以一篇文章的篇幅,帮助初学者达到「玩转istio」的阶段。也可以说是完成对istio的祛魅,为 istio 的初学者提供一把打开 Service Mesh 进阶之路的钥匙。希望它既不是一篇「入门介绍」,也不是一本巨细靡遗、主次不分的「参考手册」,而是一篇只讲重点、只讲笔者自身经验的最佳实践。
“最佳实践” 这个名词起源于管理领域,但是已经有一些被滥用了。我们可以在网上搜到各式各样的「某某最佳实践」。然而事实上,“最佳实践” 无疑是一个伪命题。这个世界上永远不可能有什么工程实践是最佳的,除非你是 Jeff Dean(冷笑话)。实事求是地说,本文介绍的只是一种还算不错的、可以快速上手的实践。
我们经常看到有人在简历里写 “熟练掌握某某技术”、“精通某某技术”。那么,到底什么程度才能算精通?精通的那根标准线在哪里?「进阶开发」的英文是 Advanced Programming。Advanced 既有高级的意思,也有先进的含义。高级是指,掌握了这个事物的一些不为初学者所知的、精微的技术细节,能让你完成别人完成不了的工作,或者比别人更快地完成。先进则是指,这个事物本身带来了一些更新颖的、更现代化的想法或理念,比如:Google 在2006年发布的三驾马车论文、Docker 带来的容器思想、Kubernetes 引入的声明式API。
历史学领域有一个著名的研究方法:三重证据法,即:「传世文献 · 出土文字 · 出土文物」三方相互印证,构成严密的证据链,从而推断出某个历史的真相。在这里我们提出:可以使用类似的思路学习和掌握复杂的技术系统,即:「官方文档 · 源码 · 原型实验」 三位一体,构成一个完整的学习闭环。
综合上述几点方法论,可以总结出一套进阶最佳实践:
为了避免本文演变成虚无的、形而上的坐而论道,方法论部分点到为止。
下面以「istio 就近地域路由」这个特性为例,展示这套最佳实践的具体操作过程。「就近地域路由」是一个粒度适中的特性,既不大也不小,很适合用于展示 istio进阶 的最佳实践。
Q1:何为Locality?
Q2:希望就近地域路由如何表现?
Q3:如何驱动envoy的就近地域路由?需要如何配置?
Q4:如何驱动istio的就近地域路由?需要如何配置?
Q5:istio如何获知某个envoy的locality?
Q6:就近地域路由的核心算法是怎么样的?在istio层还是envoy层实现?
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是为了做更精细的划分,比如:划分到 “机架” 的粒度。
在 istio 中,该策略被称为 Locality failover,具体的例子可以参考文献[8]。
本节将向读者展示 istio架构[9] 真正必不可少的部件(即原型)是什么,以及在自助学习进阶istio的阶段,我们可以暂时不去关注哪些内容,只聚焦在最核心的部件上。本质上,只有 envoy 与 pilot 两个组件是必不可少的。当然,如果您有充足的时间,建议您还是部署一套 Kubernetes 集群,并在其上部署一套完整的istio系统。
简化理解istio架构:
- name: helloworld
connect_timeout: 0.1s
type: static
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: helloworld
endpoints:
- priority: 0 // 第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: 1 // 第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: 2 // 第3个实例,位于华南-广州-01,优先级为2
locality:
region: south-china
zone: guangzhou
sub_zone: 01
lb_endpoints:
- endpoint:
address:
socket_address:
address: 3.3.3.3
port_value: 12345
- priority: 3 // 第4个实例,位于华东-上海-01,优先级为3 (最低)
locality:
region: east-china
zone: shanghai
sub_zone: 01
lb_endpoints:
- endpoint:
address:
socket_address:
address: 4.4.4.4
port_value: 12345
istio 层面的【地域路由】称作 Locality failover,需要使用 DestinationRule [19] 进行配置才能启用。如下面的yaml配置所示,该 DestinationRule 描述了 helloworld 服务的3个核心策略,分别是:connectionPool (连接参数)、loadBalancer (负载均衡策略)、outlierDetection(熔断踢除策略)。其中与【就近地域路由】相关的配置就是第2项:localityLbSetting。需要注意的是:必须同时有 outlierDetection 配置项,locality failover 才能生效。
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: 10
interval: 5s
baseEjectionTime: 1m
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: helloworld
namespace: demo-namespace
spec:
hosts:
- helloworld.svc.cluster.local
ports:
- number: 12345
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 启动配置文件中。
[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
[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/