本系列文章由余凯执笔创作,联合作者:阿里云容器服务 谢石 对本文亦有奉献

近几年,企业基础设施云原生化的趋势越来越明显,从最开端的IaaS化到现在的微服务化,客户的颗粒度精细化和可观测性的需求也更加强烈。容器网络为了满意客户更高性能和更高密度的需求,也一直在高速的发展和演进中,这必定给客户对云原生网络的可观测性带来了极高的门槛和应战。为了提高云原生网络的可观测性,同时便于客户和前后线同学增加对事务链路的可读性,ACK产研和AES联合共建,合作开发了ack net-exporter和云原生网络数据面可观测性系列,帮助客户和前后线同学了解云原生网络架构系统,简化对云原生网络的可观测性的门槛,优化客户运维和售后同学处理疑难问题的体会 ,提高云原生网络的链路的稳定性。

全景剖析阿里云容器网络数据链路(六):ASM Istio

△ 服务网格示例

全景剖析阿里云容器网络数据链路(六):ASM Istio

△ Istio数据面示意图

Kubernetes的横空出现打破了底层服务器、底层网络等核算资源的界限,给事务的灵敏布置、快速康复、弹性伸缩、资源功率最大化带来了无限可能。可是事务场景的‘贪婪’是无限的,跟着微服务趋势大肆发展,事务上关于同一个service,不同版别和流量操控有着更精细化的颗粒度的需求,最好能完成Pod维度的流量操控,可观测性等等。这些在Kubernetes上是无法完成的:

  1. 从流量角度,K8s最小的操控维度是service, 其他比方金丝雀等发布,借助各种ingress controller或许其他组件完成,而且这些也无法完成Pod之间的流量和衔接状态的可观测性。

  2. K8s给服务微型化,小型化发明晰条件, 假如前后端服务存在调用关怀,他们假如运用同享通讯库,则会在开发阶段就要求一切微服务运用相同的逻辑语言和仓库,这从某种程度上又大大约束微服务的独立化,无法完成彻底的‘漠不关怀’

  3. 将原来集成在同一个ECS上的服务拆分成不同的模块,这些模块之间调用涉及跨ECS等,那么必定需求在代码开发阶段需求考虑超时,重试,衔接失败等逻辑机制,而这些与微服务最中心的服务运用其实没有太大联系,可是开发工作往往耗费大量的经历在逻辑设计上。

那么,有没有方法完成上述和微服务的事务彻底阻隔呢?Istio的出现给这个带来了相对完美的解决方案,让运用这和开发者更加重视事务本身的开发迭代。Istio运用了K8s的Pod概念,会根据运用者的装备,在每个被注入的Pod布置时,主动注入istio-proxy 容器和initial 容器。initial容器的意图是经过修正Pod单独网络命名空间的iptables规矩,让需求署理的流量进入到istio-proxy 监听的端口, istio-proxy监听收支 两个端口,根据网格装备,来完成对收支流量的署理完成和干涉。而被同一个istio注入的载体,都被视为同一个服务网格之内,他们之间的调用现已脱离了service的层面,会命中相关的istio cluster装备的endpoint,这样咱们就能够完成Pod维度的流量办理、观测性、安全性等装备。

本文是[全景剖析容器网络数据链路]第六部分,首要介绍ASM Istio形式下,数据面链路的转发链路,一是经过了解不同场景下的数据面转发链路,从而探知客户在不同的场景下拜访成果表现的原因,帮助客户进一步优化事务架构;另一方面,经过深化了解转发链路,在遇到容器网络抖动时分,客户运维以及阿里云同学能够知道在哪些链路点进行布置观测手动,从而进一步定界问题方向和原因。

系列一:全景剖析阿里云容器网络数据链路(一):Flannel

系列二:全景剖析阿里云容器网络数据链路(二):Terway ENI

系列三:全景剖析阿里云容器网络数据链路(三):Terway ENIIP

系列四:全景剖析阿里云容器网络数据链路(四):Terway IPVLAN+EBPF

系列五:全景剖析阿里云容器网络数据链路(五):Terway ENI-Trunking

ASM Istio流量署理

1.1 Pod注入

ASM默许供给了一个Webhook操控器,能够将Sidecar署理主动添加到可用的Pod中。经过下面的指令能够看到ASM注入的集群有个istio-sidecar-injector-1-15-3的mutatingwebhookconfiguration, 检查webhook内容,能够看到其间一条便是有 istio-inject:enabled 标签的namespace里的pod创立时分会主动注入。

全景剖析阿里云容器网络数据链路(六):ASM Istio

全景剖析阿里云容器网络数据链路(六):ASM Istio

全景剖析阿里云容器网络数据链路(六):ASM Istio

除了命名空间维度,还有Pod维度,其他注解方法等多种维度完成K8s集群是否被加入到Istio服务网格中。为了充分运用服务网格的一切特性,服务网格中ACK集群的运用Pod有必要包含一个Sidecar署理。除了手动注入方法外,一般主张启用主动注入的方法来简化布置,ASM现已完成了注入装备的可视化操作,具体请见**多种方法灵敏敞开主动注入 [ 1] **。

全景剖析阿里云容器网络数据链路(六):ASM Istio

1.2 Pod流量转发

经过describe被注入的Pod, 能够发现Pod中除了设置好的事务container,还多出两个容器:istio-proxy和init container:istio-init。这两个容器的镜像是一样的,仅仅运转的指令的不一样,这样的优点是只需求拉取一份镜像,节省了拉取镜像的时刻。

全景剖析阿里云容器网络数据链路(六):ASM Istio

Init Container

Init container 运用的是K8s的特性,一种具有特权的特别容器,在Pod内的运用容器发动之前运转。Init容器能够包含一些运用镜像中不存在的实用东西和安装脚本。每个Pod中能够包含多个容器和多个Init容器。他与一般容器很像,可是有自己独特色:

  1. 多个init容器是串行运转的。也便是说多个init容器会依序运转,等上一个init容器运转完毕结束后,才会开端运转下一个容器。

  2. 只要等到一切的init容器悉数运转结束退出后,事务容器才开端发动,在这之前,pod不会处于ready。

  3. 假如Pod的Init容器失败,kubelet根据pod设置的restartPolicy进行相应的action。

既然现在了解了Init container的效果,那咱们来看一下istio-init在发动的过程中做了哪些事情,能够经过下面的指令:

kubectl logs -n istio-inject productpage-v1-797d845774-dndmk -c istio-init

全景剖析阿里云容器网络数据链路(六):ASM Istio

全景剖析阿里云容器网络数据链路(六):ASM Istio

能够看到istio-init在发动过程中进行了一连串的iptables规矩的生成和装备,比方出方向转发到15001端口;入方向转发到15006端口;拜访15008端口,直接return不进行流量劫持等等。那有什么方法能够自定义装备么?检查pod的信息能够看到相关装备的发动参数,也就经过相关规矩完成了收支流量重定向到设置的端口。

全景剖析阿里云容器网络数据链路(六):ASM Istio

-p: 一切出方向的流量被iptables重定向到15001端口

-z: 一切入方向的流量被iptables重定向到15006端口

-u: 用于扫除用户ID为1337,能够视为envoy运用本身运用UID 1337

-m: 流量重定向形式,“REDIRECT” 或 “TPROXY”

-i: 重定向出方向的地址规模, “*” 标明重定向一切出站流量。

-x: 指将从重定向出方向中扫除的 IP 地址规模

-b: 重定向入站端口列表

-d: 重定向入站端口中扫除的端口列表

咱们从Pod的视角去调查,将Pod视为一个整体,里边有istio-proxy容器和事务容器APP container

入方向流量转发

全景剖析阿里云容器网络数据链路(六):ASM Istio

根据上文的iptables规矩,咱们能够概括出被入方向署理转发的端口,比方80等,在Pod的网络命名空间netfilter模块经过流程是Client -> RREROUTING -> ISTIO_INBOUND -> ISTIO_IN_REDIRECT -> INPUT -> Envoy 15006(Inbound)-> OUTPUT -> ISTIO_OUTPUT -> POSTROUTING -> APP 。这样就完成了入方向流量先被转发到sidecar容器后,在转发到事务容器的监听端口。其间在过程5和6之间,流量会依照设置好的istio规矩进行处理。

出方向流量转发

全景剖析阿里云容器网络数据链路(六):ASM Istio

根据上文的iptables规矩,咱们能够概括出被入方向署理转发的端口,比方80等,在Pod的网络命名空间netfilter模块经过流程是APP > OUTPUT -> ISTIO_OUTPUT -> ISTIO_REDIRECT -> Envoy 15001(Outbound)-> OUTPUT -> ISTIO_OUTPUT -> POSTROUTING -> DST。这样就完成了出方向流量先被转发到sidecar容器后,在转发到意图监听端口。其间在过程d和e之间,流量会依照设置好的istio规矩进行处理。

入方向流量免转发

全景剖析阿里云容器网络数据链路(六):ASM Istio

关于入方向的某些端口或许自定义端口,咱们不需求它经过sidecar容器,iptables规矩会设置将符合条件的入方向流量防止转发到15006端口,直接转发到事务容器监听端口 RREROUTING -> ISTIO_INBOUND -> INPUT -> APP。

出方向流量免转发

全景剖析阿里云容器网络数据链路(六):ASM Istio

关于出方向的某些端口或许自定义端口,咱们不需求它经过sidecar容器,iptables规矩会设置将符合条件的入方向流量防止转发到15001端口,直接脱离Pod的网络命名空间 APP -> OUTPUT -> ISTIO_OUTPUT -> POSTROUTING -> DST。

Istio-proxy

全景剖析阿里云容器网络数据链路(六):ASM Istio

能够看到15001和15006被envoy运用所监听,而envoy运用便是istio-proxy容器程序。Init容器发动的时分根据所设置的参数中指定将收支站流量重定向到Envoy的形式为 “REDIRECT”或许“TPROXY”。运用REDIRECT方法,一旦Pod注入了Sidecar署理之后,一切入站流量都是从Envoy重定向,Envoy将流量发送到绑定了本地地址(127.0.0.1)的运用程序,所以运用看不到真实的原始IP。在服务网格环境下怎么保持服务拜访时的客户端源IP呢?能够运用TPROXY形式,目前ASM现已支持了TPROXY形式,具体概况请见:

help.aliyun.com/document_de…

在TPROXY形式下,Pod的网络命名空间的iptables会有mangle装备。

ADS聚合服务发现

全景剖析阿里云容器网络数据链路(六):ASM Istio

咱们现已知道了服务网格会在每个注入的Pod内注入两个容器:istio-init和istio-proxy。一旦在网格操控面进行相关装备的修正,会经过pilot下发到每个istio-proxy容器去收效。而istio是经过xDS服务接口去完成相关装备的动态下发的,其间xDS包含了LDS(Listener Discover Service)、CDS(Cluster Discover Service)、EDS(Endpoint Discovery Service)和RDS(Route Discover Service)。一般状况下,在更新装备过程中应该先更新Cluster-> 之后CLuster的Endpoint 开端更新-> 开端更新Cluster和Endpoint相对应的Listener -> Route开端更新新装备的Listener信息 -> 最后删去不在运用 Cluster 和Endpoint 以确保更新过程中流量无损。可是这些xDS接口是相互独立,所以在装备下发的时分,存在某些依赖联系的DS因装备收效前后联系造成了部分流量被丢弃,这在某些生产环境中是无法承受的。

为了确保数据面装备的一致性,服务网格运用gRPC流来进行ADS聚合发现服务,经过一个gRPC流来确保各个xDS接口的调用次序,防止各个接口独立性造成数据装备的不匹配。具体信息能够参阅:
www.envoyproxy.io/docs/envoy/…

envoy-rev.json

全景剖析阿里云容器网络数据链路(六):ASM Istio

能够看到istio-proxy发动了pilot-agent程序,pilot-agent作为父进程发动了子进程/usr/local/bin/envoy。其间/etc/istio/proxy/envoy-rev.json是envoy初始化的装备文件。

Node
包含了istio-proxy地点节点,当时Pod,istio版别、ACK集群ID、ASM版别、必要端口等相关信息。

全景剖析阿里云容器网络数据链路(六):ASM Istio

admin

istio-proxy相关日志,办理端口等信息

全景剖析阿里云容器网络数据链路(六):ASM Istio

dynamic_resources

ADS相关装备信息,比方api协议,版别,超时时刻等

全景剖析阿里云容器网络数据链路(六):ASM Istio

static_resources

包含了prometheus_stats、agent、sds-grpc、xds-grpc和zipkin五个cluster和一个在15090上监听的listener,xds-grpc cluster对应前面dynamic_resources中ADS装备。prometheus_stats cluster和15090用于对外供给prometheus采集端口。zipkin cluster是外部的zipkin服务器调用地址。

全景剖析阿里云容器网络数据链路(六):ASM Istio

tracing

分布式链路跟踪,这儿的collector_cluster是前面static_resources里边定义的zipkin cluster。

全景剖析阿里云容器网络数据链路(六):ASM Istio

拜访日志剖析

经过前文,咱们现已知道两个相互被注入的pod拜访,流量会被各自的istio-proxy所劫持并处理,那么只要剖析客户端和服务端的istio-proxy日志并进行加工,就能够对流量进行可观测性解读。咱们在这儿仍是以官方例子来举例。拜访http:///productpage , productpage运用会主动调用details服务,reviews服务。咱们以productpage和details之间链路来进行举例剖析。

全景剖析阿里云容器网络数据链路(六):ASM Istio

productpage-v1-797d845774-dndmk IP是10.0.1.130,details运用的svc的名称是details,svc地址是192.168.1.125,svc端口是9080

全景剖析阿里云容器网络数据链路(六):ASM Istio

恳求发送方productpage-v1-797d845774-dndmk的istio-proxy日志

{"upstream_host":"10.0.1.127:9080","downstream_remote_address":"10.0.1.130:49586","downstream_local_address":"192.168.1.125:9080","duration":6,"upstream_cluster":"outbound|9080||details.istio-inject.svc.cluster.local","path":"/details/0","protocol":"HTTP/1.1","upstream_local_address":"10.0.1.130:50026","method":"GET","user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36","route_name":"default","request_id":"834147c2-435f-94a7-af11-8491df9ab4f8","start_time":"2023-01-31T14:23:20.603Z","upstream_transport_failure_reason":null,"upstream_service_time":"5","response_flags":"-","bytes_received":0,"authority_for":"details:9080","authority":"details:9080","requested_server_name":null,"istio_policy_status":null,"trace_id":"9712c9f3da936a8c927f227bfe536c16","response_code":200,"x_forwarded_for":null,"bytes_sent":178}

恳求承受方details-v1-6758dd9d8d-dtbdc 的istio-proxy日志

{"x_forwarded_for":null,"start_time":"2023-01-31T14:23:20.608Z","method":"GET","response_flags":"-","route_name":"default","istio_policy_status":null,"requested_server_name":"outbound_.9080_._.details.istio-inject.svc.cluster.local","bytes_received":0,"request_id":"834147c2-435f-94a7-af11-8491df9ab4f8","response_code":200,"upstream_host":"10.0.1.127:9080","trace_id":"9712c9f3da936a8c927f227bfe536c16","downstream_remote_address":"10.0.1.130:50026","protocol":"HTTP/1.1","bytes_sent":178,"upstream_transport_failure_reason":null,"downstream_local_address":"10.0.1.127:9080","upstream_local_address":"127.0.0.6:46225","authority":"details:9080","authority_for":"details:9080","upstream_service_time":"0","upstream_cluster":"inbound|9080||","duration":1,"path":"/details/0","user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"}

日志内容解读

“upstream_host”:”10.0.1.127:9080″,————关于outbound,此是上游某个Endpoint的地址和端口

downstream_remote_address”:”10.0.1.130:49586″,” ————关于outbound,此为本pod-ip:随机端口1

downstream_local_address”:”192.168.1.125:9080″,”————关于outbound,此为意图svc-ip:svc-port

duration”:6,” ———— 整个恳求时刻,单位ms

upstream_cluster”:”outbound|9080||details.istio-inject.svc.cluster.local”,———— cluster信息

“path”:”/details/0″,

“protocol”:”HTTP/1.1″,

“upstream_local_address”:”10.0.1.130:50026″, ————关于outbound,此为本pod-ip:随机端口2

“method”:”GET”,

“user_agent”:”Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36″,

“route_name”:”default”,———— 路由名称

“request_id”:”834147c2-435f-94a7-af11-8491df9ab4f8″,

“start_time”:”2023-01-31T14:23:20.603Z”,

“upstream_transport_failure_reason”:null,

“upstream_service_time”:”5″,———— 上游回来恳求时刻,单位ms

“response_flags”:”-“,———— 回来标志,关于衔接或回来的具体信息

“bytes_received”:0,

“authority_for”:”details:9080″,

“authority”:”details:9080″,

“requested_server_name”:null,

“istio_policy_status”:null,

“trace_id”:”9712c9f3da936a8c927f227bfe536c16″,———— 此ID为唯一值,能够在上游istio-proxy对应

“response_code”:200,———— 回来状态码

“x_forwarded_for”:null

,”bytes_sent”:178

日志解读能够具体见官方衔接:
www.envoyproxy.io/docs/envoy/…

全景剖析阿里云容器网络数据链路(六):ASM Istio

UPSTREAM_HOST

上游主机的host,标明从envoy宣布的恳求的意图端

一般来说,关于outbound cluster,此值是「上游pod-ip : pod-port」 ,而关于 inbound cluster,此值是「本pod-ip : pod-port」

UPSTREAM_LOCAL_ADDRESS

上游衔接中,当时envoy的本地地址

一般来说,关于outbound cluster,此值是「本pod-ip : 随机端口2」 ,而关于inbound cluster,此值是「127.0.0.6: 随机端口3」,此处的127.0.0.6对应了 【1.2 Pod流量转发-Init Container】 中的iptables会将来自127.0.0.6的流量免于istio署理,因为这个流量是从sidecar本身宣布的

DONSTREAM_LOCAL_ADDRESS

下流衔接中,当时envoy的本地地址

一般来说,关于outbound cluster,此值是「意图service-ip : service-port 」,而关于 inbound cluster,此值是「当时pod-ip : pod-port,此处和下流的upstream_host应该相对应。

DOWNSTREAM_REMOTE_ADDRESS

一般来说,关于outbound cluster,此值是「当时pod-ip : 随机端口 」,而关于 inbound cluster,此值是「下流pod-ip : 随机端口2」,此处和下流的upstream_local_address相对应

1.3 Envoy装备简读(数据链路)

布景

全景剖析阿里云容器网络数据链路(六):ASM Istio

仍是用官方的示例, 以productpage拜访reviews服务来举例。

全景剖析阿里云容器网络数据链路(六):ASM Istio

全景剖析阿里云容器网络数据链路(六):ASM Istio

全景剖析阿里云容器网络数据链路(六):ASM Istio

全景剖析阿里云容器网络数据链路(六):ASM Istio

经过Kubernetes集群资源,咱们可一看到reviews有三个版别分别为v1,v2,v3, pod数量各一个。SVC reviews是ClusterIP形式,svc端口是9080, targetport是pod的9080端口,v1,v2,v3 都被加到了reviews SVC的endpointslice。在未被istio注入的状况下, 集群内productpage pod拜访reviews.istio-inject服务, 会被netfilter以round-robin的方法平均转发到v1,v2,v3三个pod上, 每个pod应该承受1/3的流量。

在传统的K8s集群中,是无法经过K8s的resource操控不同版别的流量分配的。可是实际的生产环境,咱们是有这方面的需求的。比方v1版别是线上事务版别,承载了首要事务流量, v2版别是开发完毕预上线版别, 本质上是不期望影响线上流量的,可能需求引流线上流量的5%到预发版别进行一段时刻的调查,来判别新版别是否有问题,之后再进一步扩展引流份额至100%之后,v1版别才下线,从而完成事务角度的滑润搬迁。或许比方v3是测验版别,咱们期望调查流量在网络波动超时状况下,事务的自我容灾和康复状况的行为是否符合预期,以前这种需求需求经过在事务代码中写好熔断代码,不同熔断环境都需求重新发版,那么像这种流量操控在ASM Istio就能够很容易的完成。

下面便是一个ASM Istio中的vs和dr的装备。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  creationTimestamp: '2023-01-30T06:25:21Z'
  generation: 1
  name: reviews
  namespace: istio-inject
  resourceVersion: '651722274'
  uid: 63f715c9-b253-4fbb-8351-5313371df14e
spec:
  hosts:
    - reviews.istio-inject.svc.cluster.local
  http:
    - name: route
      route:
        - destination:
            host: reviews
            subset: v1
          weight: 10
        - destination:
            host: reviews
            subset: v2
          weight: 40
        - destination:
            host: reviews
            subset: v3
          weight: 50

其间在reviews vs的定义了集群内拜访reviews.istio-inject.svc.cluster.local是的http协议的规矩。其间指明晰v1版别权重10%,v2版别权重40%,v3版别权重 50%

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  creationTimestamp: '2023-01-30T06:28:46Z'
  generation: 2
  name: reviews
  namespace: istio-inject
  resourceVersion: '654863578'
  uid: fdbdfcea-1fcd-453e-96fb-ce41c91ded9b
spec:
  host: reviews
  subsets:
    - labels:
        version: v1
      name: v1
    - labels:
        version: v2
      name: v2
    - labels:
        version: v3
      name: v3
  trafficPolicy:
    connectionPool:
      http:
        http2MaxRequests: 1000
        maxRequestsPerConnection: 10
      tcp:
        maxConnections: 100
    outlierDetection:
      baseEjectionTime: 15m
      consecutive5xxErrors: 7
      interval: 5m

reviews dr的定义了集群内reviews的几个版别,并定义了相关流量战略。其间http2MaxRequests标明http最大的恳求数。maxRequestsPerConnection标明每个衔接最大的恳求数。tcp最大衔接数是100。在熔断装备中,每隔5min中检测一次,接连7次5xx,把后端移除endpoint 15min。

经过前文咱们知道pilot经过xDS接口将服务网格的装备下发到每个被注入的pod中的istio-proxy中。那么关于每个pod中的istio-proxy,咱们是否有方法去检查相关的加载的装备信息呢?istio-proxy经过15000端口对外露出办理端口,咱们能够经过如图所示的指令获取到相关的装备信息。

其间能够经过curl 127.0.0.1:15000/config_dump能够获取到完整的装备信息,由于此装备信息超过1万多行,咱们就不在这儿做悉数的展现,感兴趣的同学能够自行研讨下,下文会针对此config_dump信息中的cluster,Listener,endpoint,route等要害信息做个相关展现和扼要阐明,同时也和前文的xDS做个照应。

kubectl exec -n istio-inject productpage-v1-797d845774-dndmk -c istio-proxy  -it -- curl 127.0.0.1:15000/config_dump

全景剖析阿里云容器网络数据链路(六):ASM Istio

Bootstrap

Envoy的初始化装备,与前文中的envoy-rev0.json是一致的。其间drainDuration —— 热重启期间Envoy封闭衔接的时刻(以秒为单位),默许是45s。

parentShutdownDuration —— 热重启期间,在彻底封闭父进程之前,等到的最大时刻,默许60s。此数值应该大于drainDuration。

terminationDrainDuration —— 默许5s。proxy在封闭之前,允许衔接封闭时刻。经过前文,咱们知道pod流量先过istio再被转发到事务容器。当运用发版时分,假如确保现有衔接高雅封闭,确保istio-proxy容器在事务容器彻底封闭现有衔接后,再退出是发版更新时分需求考虑的问题,此值是完成事务滑润更新需求考虑的。

全景剖析阿里云容器网络数据链路(六):ASM Istio

static_resources

config_dump中静态资源,是来自envoy-rev0.json, 里边包含了prometheus_stats、agent、sds-grpc、xds-grpc和zipkin等装备

全景剖析阿里云容器网络数据链路(六):ASM Istio

dynamic_resources

动态资源,是经过xDS接口下发到每个istio-proxy容器收效的ASM Istio的装备。也是上述reviews dr,vs装备后经过ASM管控侧下发的。咱们接下来重视动态资源装备

Listeners

Envoy选用的listener来承受到达Envoy的流量恳求。Listener和IP Sock、Unix Domain Socket绑定,也能够不绑定到具体的端口,而是接收从其他listener转发来的流量。ASM Istio便是运用了Envoy listener的这一特性来完成转发给不同的服务恳求交给不同的Listeners来处理。

仍是以productpage拜访reviews来举例, productpage拜访的是reviews的9080端口,根据上文咱们知道productpage container拜访外部的9080端口会被先转发到15001端口,所以咱们先看下15001的端口listeners。

VirtualOutbound

Envoy在15001端口创立了Listeners,一切被iptables转发的对外恳求都会被转到envoy的15001端口。能够从装备看到,envoy承受到了流量后,并不会做相关的事务动作,而是根据 “use_original_dst”: true, 这个装备,根据恳求的意图端口转发到相应的listeners 进行处理。

全景剖析阿里云容器网络数据链路(六):ASM Istio

那么肯定有个疑问了,假如恳求的意图端口并没有装备相关的listeners设置,流量该怎么进行处理呢?这个取决于outboundTrafficPolicy的装备,概况请见:
istio.io/latest/docs…

全景剖析阿里云容器网络数据链路(六):ASM Istio

Outbound

outbound监听命名是0.0.0.0_9080, 标明发向任何IP地址的9080端口都被此监听涵盖。”bind_to_port”: false此值标明监听没有绑定到tcp端口,流量是有virtualOutbound转发而来的。那么首先咱们需求差异这个监听是为了入方向仍是出方向呢?关于入方向,流量会经过15006端口的virtualInbound 的listeners,是不会进入0.0.0.0_9080的listeners。

全景剖析阿里云容器网络数据链路(六):ASM Istio

从装备上能够看到filter中并没有特别的志敏挑选条件,阐明承受任何流量,其间config_source 为ads,标明这个是来主动态发现。

根据前文能够可看到revirews,ratings,details几个service都是9080端口,这些运用都被同一个服务网格注入,那么productpage拜访的意图地址的9080,Envoy怎么刚知道是哪个service?是怎么判别假如意图端口未9080的地址不是网格内,该怎么处理呢?经过上图”route_config_name”: “9080” 能够看到存在一个‘9080’的路由规矩,在这个路由规矩中规定不同的恳求意图地的不同的处理成果,下一末节咱们将讨论。

Route

前文咱们现已知道productpage运用拜访reviews的9080端口会被listeners outbound 0.0.0.0_9080路由规矩到9080的路由。以下是‘9080’ 路由的悉数信息。咱们能够看到一共有5个virtual_hosts, 分别是allow_any、details、productpage、ratings、和reviews。其间后面4个对应4个不同outbound的cluster, allow_any对应的是PassthroughCluster,当出方向恳求找到相应的Cluster规矩时分,会选用默许直接经过。

可能有小伙伴很古怪productpage为什么不直接调用ratings服务,为什么productpage envoy装备会包含ratings的信息。这是因为ASM Istio操控面是无法感知到数据面各个服务之间是怎么调用的,因此会将一切的装备信息都下发到被注入的envoy里边,这样确保了网格装备的一致性,可是跟着网格服务装备的增多,每个envoy承受和本envoy不相关的装备信息就会变多,这样对envoy资源运用会有一定影响,假如小伙伴有很好的envoy开发能力,而且对事务之间调用非常了解,想去除去本pod中envoy无关的规矩,能够经过sidecar规矩自定义装备对egress和ingress进行调整,概况请见:

istio.io/latest/docs…


    {
     "version_info": "2023-01-30T06:25:21Z/19",
     "route_config": {
      "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
      "name": "9080",
      "virtual_hosts": [
       {
        "name": "allow_any",
        "domains": [
         "*"
        ],
        "routes": [
         {
          "match": {
           "prefix": "/"
          },
          "route": {
           "cluster": "PassthroughCluster",
           "timeout": "0s",
           "max_grpc_timeout": "0s"
          },
          "name": "allow_any"
         }
        ],
        "include_request_attempt_count": true
       },
       {
        "name": "details.istio-inject.svc.cluster.local:9080",
        "domains": [
         "details.istio-inject.svc.cluster.local",
         "details.istio-inject.svc.cluster.local:9080",
         "details",
         "details:9080",
         "details.istio-inject.svc",
         "details.istio-inject.svc:9080",
         "details.istio-inject",
         "details.istio-inject:9080",
         "192.168.1.125",
         "192.168.1.125:9080"
        ],
        "routes": [
         {
          "match": {
           "prefix": "/"
          },
          "route": {
           "cluster": "outbound|9080||details.istio-inject.svc.cluster.local",
           "timeout": "0s",
           "retry_policy": {
            "retry_on": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
            "num_retries": 2,
            "retry_host_predicate": [
             {
              "name": "envoy.retry_host_predicates.previous_hosts",
              "typed_config": {
               "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
              }
             }
            ],
            "host_selection_retry_max_attempts": "5",
            "retriable_status_codes": [
             503
            ]
           },
           "max_stream_duration": {
            "max_stream_duration": "0s",
            "grpc_timeout_header_max": "0s"
           }
          },
          "decorator": {
           "operation": "details.istio-inject.svc.cluster.local:9080/*"
          },
          "name": "default"
         }
        ],
        "include_request_attempt_count": true
       },
       {
        "name": "istio-ingressgateway.istio-system.svc.cluster.local:9080",
        "domains": [
         "istio-ingressgateway.istio-system.svc.cluster.local",
         "istio-ingressgateway.istio-system.svc.cluster.local:9080",
         "istio-ingressgateway.istio-system",
         "istio-ingressgateway.istio-system:9080",
         "istio-ingressgateway.istio-system.svc",
         "istio-ingressgateway.istio-system.svc:9080",
         "192.168.1.250",
         "192.168.1.250:9080"
        ],
        "routes": [
         {
          "match": {
           "prefix": "/"
          },
          "route": {
           "cluster": "outbound|9080||istio-ingressgateway.istio-system.svc.cluster.local",
           "timeout": "0s",
           "retry_policy": {
            "retry_on": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
            "num_retries": 2,
            "retry_host_predicate": [
             {
              "name": "envoy.retry_host_predicates.previous_hosts",
              "typed_config": {
               "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
              }
             }
            ],
            "host_selection_retry_max_attempts": "5",
            "retriable_status_codes": [
             503
            ]
           },
           "max_stream_duration": {
            "max_stream_duration": "0s",
            "grpc_timeout_header_max": "0s"
           }
          },
          "decorator": {
           "operation": "istio-ingressgateway.istio-system.svc.cluster.local:9080/*"
          "name": "default"
         }
        ],
        "include_request_attempt_count": true
       },
       },     
       {
        "name": "productpage.istio-inject.svc.cluster.local:9080",
        "domains": [
         "productpage.istio-inject.svc.cluster.local",
         "productpage.istio-inject.svc.cluster.local:9080",
         "productpage",
         "productpage:9080",
         "productpage.istio-inject.svc",
         "productpage.istio-inject.svc:9080",
         "productpage.istio-inject",
         "productpage.istio-inject:9080",
         "192.168.6.226",
         "192.168.6.226:9080"
        ],
        "routes": [
         {
          "match": {
           "prefix": "/"
          },
          "route": {
           "cluster": "outbound|9080||productpage.istio-inject.svc.cluster.local",
           "timeout": "0s",
           "retry_policy": {
            "retry_on": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
            "num_retries": 2,
            "retry_host_predicate": [
             {
              "name": "envoy.retry_host_predicates.previous_hosts",
              "typed_config": {
               "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
              }
             }
            ],
            "host_selection_retry_max_attempts": "5",
            "retriable_status_codes": [
             503
            ]
           },
           "max_stream_duration": {
            "max_stream_duration": "0s",
            "grpc_timeout_header_max": "0s"
           }
          },
          "decorator": {
           "operation": "productpage.istio-inject.svc.cluster.local:9080/*"
          },
          "name": "default"
         }
        ],
        "include_request_attempt_count": true
       },
       {
        "name": "ratings.istio-inject.svc.cluster.local:9080",
        "domains": [
         "ratings.istio-inject.svc.cluster.local",
         "ratings.istio-inject.svc.cluster.local:9080",
         "ratings",
         "ratings:9080",
         "ratings.istio-inject.svc",
         "ratings.istio-inject.svc:9080",
         "ratings.istio-inject",
         "ratings.istio-inject:9080",
         "192.168.1.172",
         "192.168.1.172:9080"
        ],
        "routes": [
         {
          "match": {
           "prefix": "/"
          },
          "route": {
           "cluster": "outbound|9080||ratings.istio-inject.svc.cluster.local",
           "timeout": "0s",
           "retry_policy": {
            "retry_on": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
            "num_retries": 2,
            "retry_host_predicate": [
             {
              "name": "envoy.retry_host_predicates.previous_hosts",
              "typed_config": {
               "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
              }
             }
            ],
            "host_selection_retry_max_attempts": "5",
            "retriable_status_codes": [
             503
            ]
           },
           "max_stream_duration": {
            "max_stream_duration": "0s",
            "grpc_timeout_header_max": "0s"
           }
          },
          "decorator": {
           "operation": "ratings.istio-inject.svc.cluster.local:9080/*"
          },
          "name": "default"
         }
        ],
        "include_request_attempt_count": true
       },
       {
        "name": "reviews.istio-inject.svc.cluster.local:9080",
        "domains": [
         "reviews.istio-inject.svc.cluster.local",
         "reviews.istio-inject.svc.cluster.local:9080",
         "reviews",
         "reviews:9080",
         "reviews.istio-inject.svc",
         "reviews.istio-inject.svc:9080",
         "reviews.istio-inject",
         "reviews.istio-inject:9080",
         "192.168.4.113",
         "192.168.4.113:9080"
        ],
        "routes": [
         {
          "match": {
           "prefix": "/"
          },
          "route": {
           "weighted_clusters": {
            "clusters": [
             {
              "name": "outbound|9080|v1|reviews.istio-inject.svc.cluster.local",
              "weight": 10
             },
             {
              "name": "outbound|9080|v2|reviews.istio-inject.svc.cluster.local",
              "weight": 40
             },
             {
              "name": "outbound|9080|v3|reviews.istio-inject.svc.cluster.local",
              "weight": 50
             }
            ],
            "total_weight": 100
           },
           "timeout": "0s",
           "retry_policy": {
            "retry_on": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
            "num_retries": 2,
            "retry_host_predicate": [
             {
              "name": "envoy.retry_host_predicates.previous_hosts",
              "typed_config": {
               "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
              }
             }
            ],
            "host_selection_retry_max_attempts": "5",
            "retriable_status_codes": [
             503
            ]
           },
           "max_stream_duration": {
            "max_stream_duration": "0s",
            "grpc_timeout_header_max": "0s"
           }
          },
          "metadata": {
           "filter_metadata": {
            "istio": {
             "config": "/apis/networking.istio.io/v1alpha3/namespaces/istio-inject/virtual-service/reviews"
            }
           }
          },
          "decorator": {
           "operation": "reviews:9080/*"
          },
          "name": "route"
         }
        ],
        "include_request_attempt_count": true
       }
      ],
      "validate_clusters": false
     },
     "last_updated": "2023-01-30T06:25:21.804Z"
    },

咱们仍是以productpage调用reviews来举例, Envoy会根据 HTTP header 中domains 来匹配VirtualHost中domain,所以能够看到domains中列举了reviews的集群内的长短域名,和svc的地址。match “/” 会路由到三个cluster “outbound|9080|v1|reviews.istio-inject.svc.cluster.local”、”outbound|9080|v2|reviews.istio-inject.svc.cluster.local”和”outbound|9080|v3|reviews.istio-inject.svc.cluster.local”,权重分别为10,40,50,名称是‘route’,看到这儿是不是有点了解?对的,这和前文 [1.3 Envoy装备简读-布景]中reviews的VS中的设置,故咱们在vs中的相关装备信息,终究envoy会转为route的装备加载后收效。

全景剖析阿里云容器网络数据链路(六):ASM Istio

全景剖析阿里云容器网络数据链路(六):ASM Istio

经过前面咱们还能够看到默许超时是0s,默许重试次数是2次,重试条件是”connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes”。

Cluster

outbound cluster

根据上一下末节,productpage拜访reviews,会被productpage中的istio-proxy匹配到‘9080’路由-> 根据vs装备的相关信息,进入三个cluster( “outbound|9080|v1|reviews.istio-inject.svc.cluster.local”、”outbound|9080|v2|reviews.istio-inject.svc.cluster.local”和”outbound|9080|v3|reviews.istio-inject.svc.cluster.local”)中一个。这儿咱们就以”outbound|9080|v1|reviews.istio-inject.svc.cluster.local”cluster 为例

全景剖析阿里云容器网络数据链路(六):ASM Istio

全景剖析阿里云容器网络数据链路(六):ASM Istio

outbound|9080|v1|reviews.istio-inject.svc.cluster.local cluster装备中能够看到,其类型为EDS,即标明该Cluster的endpoint来自于动态发现,动态发现中eds_config则标明是由ads下发的。相同能够看到与前文[1.3 Envoy装备简读-布景]中reviews的dr中的设置了解的装备,比方connectionpool,outlierDetection等这些相关装备信息,终究envoy会转为cluster的装备加载后收效。

接下来咱们略微讨论下其他几个特别的cluster。

BlackHoleCluster

Envoy关于找不到后端处理恳求的会默许丢弃,所以会有一致的一个blackholecluster,没有任何指明的后端svc,任何无匹配后端的流量会被转发到这个cluster。

全景剖析阿里云容器网络数据链路(六):ASM Istio

PassthroughCluster

和BlackHoleCluter正好相反,发向PassthroughCluster的恳求会被直接发送到器恳求衔接中的原始目地的,type类型是”type”: “ORIGINAL_DST”,标明其发到原始的意图地址:端口

全景剖析阿里云容器网络数据链路(六):ASM Istio

Inbound Cluster

inbound Cluster是为了pod上的入方向的恳求,关于reviews来说,其对应的Inbound Cluster只要一个inbound|9080。

全景剖析阿里云容器网络数据链路(六):ASM Istio

Endpoint

从endpoint文件内容能够看到,reviews cluster “outbound|9080|v1|reviews.istio-inject.svc.cluster.local”只要1个endpoint地址,是reviews-v1-74fb8fdbd8-qwsjq的pod ip 10.0.3.29。

全景剖析阿里云容器网络数据链路(六):ASM Istio

全景剖析阿里云容器网络数据链路(六):ASM Istio

至此,咱们大概整理完毕服务网格内两个服务之间拜访,istio-proxy日志解读和装备对应联系。

Tips

前文的config_dump文件太长,解读起来其实比较费力,服务网格供给了asmctl东西能够很方便的去解读listeners,route,cluster,endpoint等,具体信息请见:
help.aliyun.com/document_de…

[root@shycmain ~]# asmctl --asmconfig asmconfig pc  listeners  productpage-v1-797d845774-dndmk.istio-inject --port 9080
ADDRESS PORT MATCH                        DESTINATION
0.0.0.0 9080 Trans: raw_buffer; App: HTTP Route: 9080
0.0.0.0 9080 ALL                          PassthroughCluster
[root@shycmain ~]# asmctl --asmconfig asmconfig pc  routes  productpage-v1-797d845774-dndmk.istio-inject  --name 9080
NOTE: This output only contains routes loaded via RDS.
NAME     DOMAINS                               MATCH     VIRTUAL SERVICE
9080     details                               /*
9080     istio-ingressgateway.istio-system     /*
9080     productpage                           /*
9080     ratings                               /*
9080     reviews                               /*        reviews.istio-inject
[root@shycmain ~]# asmctl --asmconfig asmconfig pc  cluster  productpage-v1-797d845774-dndmk.istio-inject --fqdn reviews.istio-inject.svc.cluster.local
SERVICE FQDN                               PORT     SUBSET     DIRECTION     TYPE     DESTINATION RULE
reviews.istio-inject.svc.cluster.local     9080     -          outbound      EDS      reviews.istio-inject
reviews.istio-inject.svc.cluster.local     9080     v1         outbound      EDS      reviews.istio-inject
reviews.istio-inject.svc.cluster.local     9080     v2         outbound      EDS      reviews.istio-inject
reviews.istio-inject.svc.cluster.local     9080     v3         outbound      EDS      reviews.istio-inject
[root@shycmain ~]# asmctl --asmconfig asmconfig pc  endpoint  productpage-v1-797d845774-dndmk.istio-inject  --cluster "outbound|9080|v1|reviews.istio-inject.svc.cluster.local"
ENDPOINT           STATUS      OUTLIER CHECK     CLUSTER
10.0.3.29:9080     HEALTHY     OK                outbound|9080|v1|reviews.istio-inject.svc.cluster.local

企业拥抱容器化总结

本篇文章首要聚焦在ASM Istio服务网格形式下,被注入pod的数据面流量转发链路状况。istio灵敏注入完成了在Pod维度对流量的定制化装备和观测性,带来了事务链路角度完成的更多种的可能。在服务网格中装备gateway,virtualservice,destinationrule等规矩在经过xDS下发到envoy后,会经过listeners, route、cluster、endpoint等一个环节一个环节终究体现在流量转发规矩上。那么在运用ASM遇到不符合预期状况时,这些环节都是需求考虑的方向。ASM除了流量办理,还有安全,鉴权,可观测方面的快捷运用,这些方面的装备,终究也会体现在相关的网格服务资源装备上,感兴趣的小伙伴能够参阅**ASM官方文档 [ 2] **。

参阅链接

istio.io/latest/docs…

www.envoyproxy.io/docs/envoy/…

[1]多种方法灵敏敞开主动注入

help.aliyun.com/document_de…

[2] 官方文档

help.aliyun.com/product/147…