乐趣区

关于阿里云:你的-Sleep-服务会梦到服务网格外的-bookinfo-吗

作者:尹航

作为业内首个全托管 Istio 兼容的阿里云服务网格产品 ASM,一开始从架构上就放弃了与社区、业界趋势的一致性,管制立体的组件托管在阿里云侧,与数据面侧的用户集群独立。ASM 产品是基于社区 Istio 定制实现的,在托管的管制面侧提供了用于撑持精细化的流量治理和平安治理的组件能力。通过托管模式,解耦了 Istio 组件与所治理的 K8s 集群的生命周期治理,使得架构更加灵便,晋升了零碎的可伸缩性。从 2022 年 4 月 1 日起,阿里云服务网格 ASM 正式推出商业化版本, 提供了更丰盛的能力、更大的规模反对及更欠缺的技术保障,更好地满足客户的不同需要场景,详情可点击原文链接查看。

前言

服务网格是一个通过“Sidecar”模式进行服务治理简化的平台。整个服务网格能够划分为包含外围组件 Istiod 的“管制面”以及包含了每个服务的 Sidecar 的“数据面”。如果各位应用过服务网格,置信对下面的概念也算是略有理解了。

在服务网格 Istio 中,咱们晓得每个 Sidecar 都是一个 envoy 利用,外部有着蕴含着 listener、route、cluster、secret 等局部的残缺配置;envoy 就是依据这些配置来扭转本身行为,实现不同的流量管制伎俩的。而管制面组件的次要工作,就是将网格中的 VirtualService、DestinationRule 等资源“翻译”成 envoy 的具体配置,并将配置发送给数据面的每个 envoy,咱们简称这个过程为“配置推送”。

在 envoy 中,cluster 配置对应着 envoy 外部的“集群”这个概念,一个 cluster 是指“Envoy 连贯的一组逻辑雷同的上游主机”,其实大多数时候也就是对应着一个具体的服务。

如果咱们理论查看 envoy 的残缺配置会发现,咱们在什么都没做的时候,envoy 外部就曾经蕴含着一些动静下发的 cluster 了,也就是说,Sidecar 主动发现并蕴含了集群中的服务信息。这里就引出一个外围问题:服务网格的“服务发现”是如何实现的呢?咱们通常会用“网格内服务”来称说对应 Pod 注入了 Sidecar 的服务;那么,是不是说服务网格会将注入了 Sidecar 的“网格内服务”主动的退出每个 Sidecar 的 cluster 配置呢?

明天这篇文章就来次要聊一聊服务网格的“服务发现”和“配置推送”。

服务网格的“服务发现”

一个简略的小试验就能够解答下面的这些问题。咱们在 Kubernetes 集群中装置服务网格平台(能够应用 aliyun ASM + ACK 来疾速搭建服务网格平台),而后在 default 默认命名空间之外,再建设一个 test 命名空间。

而后,咱们为 default 命名空间开启 Sidecar 主动注入,也就是说,default 命名空间内的服务将主动成为“网格内”的服务,而 test 命名空间内的服务将不会注入 Sidecar,也就是“网分外”的服务。

在服务网格 ASM 中,咱们能够在控制台的“全局命名空间”治理中来不便地开启和敞开主动注入(开启 / 敞开后别忘了同步一下主动注入哦):

咱们能够随便在这两个命名空间内部署一些中意的服务,我在这里向 default 命名空间部署了一个 sleep 服务。这个服务就如字面意思,外面是一个 curl 容器,并且一进去就始终在睡大觉 (~o~).zZ,能够进入这个服务的 Pod 不便地 curl 其它服务。

在 Istio 的社区官网 github 仓库中,能够找到 sleep 这个示例服务的 YAML 文件:istio/samples/sleep/sleep.yaml,咱们能够拷贝这个文件后执行:

kubectl apply -f sleep.yaml

同理,在 test 命名空间下,咱们轻易部署点啥服务,我这里部署了一个 Istio 使用者的老朋友 bookinfo,咱们同样能够在 Istio 的官网 github 中找到它的 YAML 文件:istio/samples/bookinfo/platform/kube/bookinfo.yaml,将其拷贝后执行:

kubectl apply -f bookinfo.yaml -n test

顺带一提,为了不让 sleep 太寂寞,我还在 default 命名空间部署了一个 httpbin 利用陪他,不过不部署也无所谓┐(゚~゚)┌。

咱们当初筹备好了,大家可能猜到接下来要干啥了。咱们就来看看——这个 Sidecar 里都有哪些 cluster 配置。

如果你应用 Istio,能够用 istioctl 命令行工具不便地查看 Sidecar 中的各项配置的总结信息;在服务网格 ASM 中这招可能行不通,不过 ASM 也有一个可能局部兼容的命令行工具 asmctl,咱们能够进入阿里云帮忙核心,搜寻 asmctl,找到“装置和应用诊断工具 asmctl”,依照文档提醒下载安装此工具。

以 asmctl 为例,能够用这个姿态来查看 Sidecar 外部的 cluster 配置(须要提前配置好数据面集群的 Kubeconfig):

$ asmctl proxy-config cluster sleep-557747455f-g4lcs 
SERVICE FQDN                                                      PORT      SUBSET     DIRECTION     TYPE             DESTINATION RULE
                                                                  80        -          inbound       ORIGINAL_DST     
BlackHoleCluster                                                  -         -          -             STATIC           
InboundPassthroughClusterIpv4                                     -         -          -             ORIGINAL_DST     
InboundPassthroughClusterIpv6                                     -         -          -             ORIGINAL_DST     
PassthroughCluster                                                -         -          -             ORIGINAL_DST     
agent                                                             -         -          -             STATIC           
asm-validation.istio-system.svc.cluster.local                     443       -          outbound      EDS              
controlplane-metrics-aggregator.kube-system.svc.cluster.local     443       -          outbound      ORIGINAL_DST     
details.test.svc.cluster.local                                    9080      -          outbound      EDS              
envoy_accesslog_service                                           -         -          -             STRICT_DNS       
heapster.kube-system.svc.cluster.local                            80        -          outbound      EDS              
httpbin.default.svc.cluster.local                                 8000      -          outbound      EDS              
istio-ingressgateway.istio-system.svc.cluster.local               80        -          outbound      EDS              
istio-ingressgateway.istio-system.svc.cluster.local               443       -          outbound      EDS              
istio-sidecar-injector.istio-system.svc.cluster.local             443       -          outbound      EDS              
istio-sidecar-injector.istio-system.svc.cluster.local             15014     -          outbound      EDS              
istiod.istio-system.svc.cluster.local                             15012     -          outbound      ORIGINAL_DST     
kiali.istio-system.svc.cluster.local                              20001     -          outbound      EDS              
kube-dns.kube-system.svc.cluster.local                            53        -          outbound      EDS              
kube-dns.kube-system.svc.cluster.local                            9153      -          outbound      EDS              
kubernetes.default.svc.cluster.local                              443       -          outbound      EDS              
metrics-server.kube-system.svc.cluster.local                      443       -          outbound      EDS              
productpage.test.svc.cluster.local                                9080      -          outbound      EDS              
prometheus_stats                                                  -         -          -             STATIC           
ratings.test.svc.cluster.local                                    9080      -          outbound      EDS              
reviews.test.svc.cluster.local                                    9080      -          outbound      EDS              
sds-grpc                                                          -         -          -             STATIC           
sleep.default.svc.cluster.local                                   80        -          outbound      EDS              
storage-crd-validate-service.kube-system.svc.cluster.local        443       -          outbound      EDS              
storage-monitor-service.kube-system.svc.cluster.local             11280     -          outbound      EDS              
xds-grpc                                                          -         -          -             STATIC           
zipkin

这里就有一个有意思的事件了,尽管整套 bookinfo 利用都没有注入 Sidecar,但咱们还是能在 sleep 的 Sidecar 中找到 productpage、reviews、ratings 等 bookinfo 利用的服务信息。

这所有是怎么实现的呢?实际上 Istio 官网在社区文章《Traffic Management》中,有对这一过程进行解释:

In order to direct traffic within your mesh, Istio needs to know where all your endpoints are, and which services they belong to. To populate its own service registry, Istio connects to a service discovery system. For example, if you’ve installed Istio on a Kubernetes cluster, then Istio automatically detects the services and endpoints in that cluster.

简要地说,服务网格 Istio 并不进行服务发现。所有的服务都经由服务网格底层平台的服务发现(Kubernetes、Consul 等,大多数状况下都是 Kubernetes),通过管制面适配后传入网格本人的服务注册核心(也就是 Sidecar 的那一堆 cluster 配置了)。

此外,如果你查看 Sidecar 中记录的 endpoint,你会发现无论是否注入 Sidecar,Kubernetes 集群内所有 Pod 的 ip 地址都会记录在内。

尝试在 test 命名空间内部署上面这么个 VirtualService:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  namespace: test
  name: test-vs
spec:
  hosts:
    - productpage.test.svc.cluster.local
  http:
    - match:
        - uri:
            prefix: /test/
      rewrite:
        uri: /
      route:
        - destination:
            host: productpage.test.svc.cluster.local
            port:
              number: 9080

这个 VirtualService 实现了一个 uri 的重写,但指标 host 是一个“网分外”的服务 productpage。

尝试一下,curl 一个会被重写的门路 /test/productpage

kubectl exec -it sleep-557747455f-g4lcs -c sleep -- curl productpage.test:9080/test/productpage

会发现重写失效了,申请失常有返回。

上述行为能够阐明,所谓“网格内外”只是以是否注入 Sidecar 确定的一个辨别伎俩,并不是说网格自身和网分外的服务有着严格的隔离边界。在下面的例子中,VirtualService 实际上失效于申请发送方 Sidecar 的 route 配置之中,而 productpage 服务即便没有 Sidecar,也是会被服务网格管制面发现、并退出 cluster 配置之中的,有对应的 cluster。因而,网格当然能够设定针对此 cluster 的路由规定,只有申请发送方的 Pod 是注入 Sidecar 的,VirtualService 的性能就能失常工作。

当然,理论应用中,服务网格的其它资源可能失效于入站流量配置之中,此时申请接管方也必须注入 Sidecar 才行。但 Sidecar 注入并不对网格的服务发现起到决定作用,这一点是能够必定的。

服务网格的“配置推送”

下面咱们摸索了服务网格的“服务发现”机制,能够说还是非常奇妙,这套机制既让服务网格免于再去实现一套冗余的服务发现机制,也不便网格自身与不同的底层平台进行对接。然而,认真思考就会发现这其中存在的问题与暗藏的反直觉现实情况。

就以下面测试中咱们在 Kubernetes 集群中部署的利用为例。Sleep 利用与 bookinfo 利用是两个独立的利用,彼此之间其实没有太大关系(只不过想拜访的话彼此还是拜访的通而已)。在理论的生产环境中,置信很多用户都会有这样的实际:利用 Kubernetes 命名空间的隔离机制,在同一个集群中部署多个利用对外提供服务,每个利用蕴含几个微服务,而利用之间彼此的关系则比拟独立。而其中又只有局部的利用须要应用服务网格的治理能力(多语言服务互通、蓝绿公布等),因而注入了 Sidecar。

问题是,服务网格的管制面也不能假如用户服务之间的关系,因而还是须要厚此薄彼地 watch 集群内所有的服务与端点:-(

更好受的是,管制面还须要向及时向数据面的每一位 Sidecar 同步集群内最新的服务信息,这就导致了以下的“费劲不讨好”场面:

1、一开始大家相安无事,岁月静好

2、Service2 扩容了!

3、Istiod 下发新的配置

4、难堪的事件产生了,Service1 和 Service2 其实是两个独立的利用,网格内的 Sidecar 不须要记录 Service2 的任何信息。

如果网格内的服务不多,这倒也不能造成什么微小的问题,无非就是网格的管制面组件多做点无用功罢了。可是正所谓质变引起量变,无用功堆积起来就会成为不可漠视的大问题。如果您的集群中部署着成千上百个服务,而其中只有大量的服务退出了网格,网格的管制面就会吞没在大量的有效信息中,管制面组件的负载居高不下,并且一直向所有 Sidecar 推送他们并不需要的信息。

因为管制面组件不比网关,只是负责向 Sidecar 推送配置,管制面的负载过高可能很难引起服务网格用户的留神。然而一旦负载过高导致 Pilot SLB 超限 / 管制面组件重启等情况,用户就会轻则面临新的路由配置推送过慢、重则面临注入 Sidecar 的 Pod 起不来的困境。因而,在享受服务网格为咱们带来的便当的流量治理能力的同时,适度地关怀服务网格管制面的身心健康,对管制面进行配置推送的优化,也是十分有必要的。

配置推送优化 - 之选择性服务发现

针对下面所述的情况,咱们能够手动地去配置服务网格,让网格的管制面只去“发现”特定命名空间内的服务,而对其它的命名空间束之高阁。在社区中,Istio 于 1.10 版本后提供了“discovery selector”的能力。而服务网格 ASM 也对应提供了“选择性服务发现”的能力,二者的失效机制是完全相同的。

咱们以服务网格 ASM 的“选择性服务发现”为例。首先给网格内利用所在的命名空间打一个特定的标签,用来辨别网格内与网分外利用所在的命名空间(留神是给数据面的命名空间打标签):

# 在这里,default 命名空间开启了主动注入,属于“网格内”命名空间
kubectl label namespace default in-mesh=yes
# 其实咱们也能够间接用 istio-injection:enabled 标签,不必再打一个 

进入咱们的 ASM 实例治理页面,在左侧菜单中选择“配置推送优化 -> 选择性服务发现”。

在“选择性服务发现”页面中,抉择“增加标签选择器”->“增加标签准确匹配规定”,输出咱们方才打好的标签。

而后点击“确定”就好了,真是十分中央便。这之后网格会通过一个短暂的更新阶段,更新咱们方才写下的这个配置,而后从新进入“运行中”状态。

再来运行一遍咱们最开始的指令,查看一下 sleep 服务的 Sidecar 中的 cluster 配置:

$ asmctl proxy-config cluster sleep-557747455f-g4lcs   
SERVICE FQDN                             PORT     SUBSET     DIRECTION     TYPE             DESTINATION RULE
                                         80       -          inbound       ORIGINAL_DST     
BlackHoleCluster                         -        -          -             STATIC           
InboundPassthroughClusterIpv4            -        -          -             ORIGINAL_DST     
InboundPassthroughClusterIpv6            -        -          -             ORIGINAL_DST     
PassthroughCluster                       -        -          -             ORIGINAL_DST     
agent                                    -        -          -             STATIC           
envoy_accesslog_service                  -        -          -             STRICT_DNS       
httpbin.default.svc.cluster.local        8000     -          outbound      EDS              
kubernetes.default.svc.cluster.local     443      -          outbound      EDS              
prometheus_stats                         -        -          -             STATIC           
sds-grpc                                 -        -          -             STATIC           
sleep.default.svc.cluster.local          80       -          outbound      EDS              
xds-grpc                                 -        -          -             STATIC           
zipkin                                   -        -          -             STRICT_DNS

能够看到 sleep 服务的 Sidecar 中曾经没有任何一个 bookinfo 利用中服务的信息了,当初 Sidecar 中的配置看起来精简多了。可喜可贺可喜可贺 (^o^)/

当然,咱们做的不只是缩小 Sidecar 中的配置数量而已。如上文所说,应用“选择性服务发现后”,管制面将不会 watch 除 default 命名空间外的任何服务,也因而管制面的工作累赘失去了大幅削减,服务网格重回高效运行状态~ 咱们也能够没有后顾之忧地向集群中部署其它服务了。

总结

服务网格的服务发现机制其实说起来是一个非常简略的货色,毕竟服务网格基本就没有服务发现机制呢!

不过不去理论理解的话,想必很少有人可能间接确定每个 Sidecar 里记录的那些林林总总的服务到底是如何发现的。同时,Istiod 作为服务网格中负责配置推送的外围组件,做的却是批改翻译和批改配置这样的后盾工作,也导致网格的用户通常很难意识到管制面组件到底在进行什么工作,以及现有的实际是否给管制面组件造成了过大的多余累赘。

心愿这篇文章能让更多的服务网格用户意识到,配置推送的优化也是网格平台保护的重要一环。应用“选择性服务发现”的话,仅用 1 分钟的工夫就可能大幅度优化网格的配置优化,缩小应用网格时无谓的隐患,岂不美哉?

对于大多数用户来说,“选择性服务发现”就曾经足够对配置推送进行优化了。不过如果您想做的更“绝”,还能够间接应用服务网格的 Sidecar 资源来对 Sidecar 的配置进行最大限度地优化。服务网格 ASM 针对 Sidecar 资源这一机制,也提供了基于拜访日志剖析主动举荐的 Sidecar 资源来帮忙客户进行应用上的深度简化。欢送应用服务网格 ASM,即刻让您领有简化的无侵入式服务治理能力!

从 2022 年 4 月 1 日起,阿里云服务网格 ASM 正式推出商业化版本, 提供了更丰盛的能力、更大的规模反对及更欠缺的技术保障,更好地满足客户的不同需要场景。

退出移动版