ServiceMesh流量走向


在服务网格后服务与服务之间的流量走向不再是默认k8s原来的走向路径了。具体表现可以对比在后端是GRPC多副本互相调度的时候,通过传统的SVC到iptables转发后端pod会发现流量不均衡的情况。启用网格后,然后定义好DestinationRule的轮训规则后。可以达到后端负载比较均匀。

但是具体是怎么实现的呢?

Istio 实现了 service mesh 的控制平面,并整合 Envoy 开源项目作为数据平面的 sidecar,一起对流量进行控制。

pilot的业务架构图为: istio

途中讲有 统一的服务模型、标准数据面API、规则DSL语言。

统一的服务模型:

1.可以对各种不同底层平台进行对接,如图所示有kubernetes、mesos、cloudFoundry以及consul等。 2.比如k8s中的流程是pilot中用k8s适配器,通过k8s API-server获取到k8s中的SVC、pod等信息。然后翻译成pilot标准模型。

标准数据平面API

Pilot 使用了一套起源于 Envoy 项目的标准数据平面 API 来将服务信息和流量规则下发到数据平面的 sidecar 中。 Envoy V2 API,作为 Istio 控制平面和数据平面流量管理的标准接口。

pilot控制平面与数据平面 架构图 pilot

红色:控制流
黑色:数据流

流量管理组件

1.服务发现

image: gcr.io/istio-release/pilot
运行pod、svc名称:

# k get pod,svc -n istio-system|grep istio-pilot
pod/istio-pilot-78fff96ddf-bhggp   2/2  Running     4          37d
service/istio-pilot              ClusterIP   10.107.143.245   <none>        15010/....TCP

功能: 1.从k8s中获取服务信息
2.从k8s中获取流量规则(gw、vs、dstanationRule等CRD配置信息)
3.将上面获取的信息翻译为envoy能识别的配置,然后通过api下发到各个sidecar的envoy

2.K8S API-server中的CRD

Pilot 的规则 DSL在k8s上抽象为CRD实现。CRD有如下几类:

Gateway: 为网格配置网关,以允许一个服务可以被网格外部访问,可以理解为Ingress,支持TLS和http的虚拟主机以及tcp等。

Virtualservice: 用于定义路由规则,如根据来源或 Header 制定规则,或在不同服务版本之间分拆流量的一些规则定义。

DestinationRule: 定义目的服务的配置策略以及可路由子集(可以理解为后端选择svc的标签)。策略包括断路器、负载均衡以及 TLS 等。

ServiceEntry: 网格内向网格外的服务发出请求的一些服务治理定义,比如定义某些远程接口可以访问,未定义默认拒绝。

EnvoyFilter: Envoy 配置过滤器。EnvoyFilter启用Lua过滤器,动态改变Envoy的过滤链行为。

Envoy是serviceMesh的数据层传送组件,接受来自Pilot的控制配置接受和应用(热加载)。

数据平面组件

1.pilot-agent
功能:根据 K8S-API Server中的配置信息生成Envoy的配置文件,并负责启动Envoy进程。并传送pilot地址接口和zipkin地址。大部分配置信息后续根据pilot服务地址动态获取。

2.Envoy
功能: Envoy由Pilot-agent进程启动。 启动后,Envoy 读取 Pilot-agent 为它生成的配置文件,然后根据该文件的配置获取到 Pilot 的地址,通过数据平面标准 API 的 xDS 接口从 pilot 拉取动态配置信息,包括路由(route),监听器(listener),服务集群(cluster)和服务端点(endpoint。
Envoy 初始化完成后,就根据这些配置信息对微服务间的通信进行寻址和路由。

示范以及问题:

1.在服务C的pod中,通过查看Envoy的管理接口(istio-proxy的15000服务)config_dump所有静态配置,思考是否完整?

2.通过Envoy-config配置,找到grpc-P服务目标路由。

3.通过在第一步中获取到的动态集群列表中,查找到目标服务集群grpc-P的OutbondCluster。

4.通过在第3步中找到的service_name获取到详细后端路径。

示范及答案:

1.通过执行访问15000的config_dump接口获取路由信息。

#消费者GO的服务是frontend pod
kubectl exec frontend-76d7c7cf44-6xjnr -c istio-proxy curl http://127.0.0.1:15000/config_dump > dump.jsion
2.获取到P的Envoy路由配置信息
➜  ~ grep 8000 dump.json|grep cluster
      "name": "outbound|8000||backend.default.svc.cluster.local",
           "stat_prefix": "outbound|8000||backend.default.svc.cluster.local",
           "cluster": "outbound|8000||backend.default.svc.cluster.local"

可以看见 生产者的服务cluster,但是没有详细后端信息。所以信息不完整,这里并不是走的k8s的svc!

"cluster": "outbound|8000||backend.default.svc.cluster.local"

3.因为每个envoy的配置信息不全,都是通过动态获取pilot服务的而来,所以去pilot服务去获取完整信息。所以获取信息方法为:

~# k get pod,svc -n istio-system|grep istio-pilot
pod/istio-pilot-78fff96ddf-bhggp    2/2 Running 4   37d
service/istio-pilot ClusterIP   10.107.143.245   <none> 15010/TCP,15011/TCP,8080/TCP,15014/TCP 

4.获取详细后端路径

kubectl port-forward svc/istio-pilot 15014:15014 -n istio-system
curl http://127.0.0.1:15014/debug/endpointz > endpoint.json

cat endpoint.json|grep backend.default.svc.cluster.local
{"svc": "backend.default.svc.cluster.local:grpc", "ep": [
{
    "endpoint": {
      "Family": 0,
      "Address": "10.80.128.195",
      "Port": 8000,
      "ServicePort": {
        "name": "grpc",
        "port": 8000,
        "protocol": "GRPC"
      },
...
    "service": {
      "hostname": "backend.default.svc.cluster.local",
      "address": "10.97.159.224",
      "Mutex": {},
      "cluster-vips": {
        "Kubernetes": "10.97.159.224"
      },
      "ports": [
        {
          "name": "grpc",
          "port": 8000,
          "protocol": "GRPC"
        }
      ],
...
{
    "endpoint": {
      "Family": 0,
      "Address": "10.80.153.151",
      "Port": 8000,
      "ServicePort": {
        "name": "grpc",
        "port": 8000,
        "protocol": "GRPC"
      },
...
    },
    "service": {
      "hostname": "backend.default.svc.cluster.local",
      "address": "10.97.159.224",
      "Mutex": {},
      "cluster-vips": {
        "Kubernetes": "10.97.159.224"
      },
      "ports": [
        {
          "name": "grpc",
          "port": 8000,
          "protocol": "GRPC"
        }
...
{
    "endpoint": {
      "Family": 0,
      "Address": "10.80.167.213",
      "Port": 8000,
      "ServicePort": {
        "name": "grpc",
        "port": 8000,
        "protocol": "GRPC"
      },
...
    },
    "service": {
      "hostname": "backend.default.svc.cluster.local",
      "address": "10.97.159.224",
      "Mutex": {},
      "cluster-vips": {
        "Kubernetes": "10.97.159.224"
      },
      "ports": [
        {
          "name": "grpc",
          "port": 8000,
          "protocol": "GRPC"
        }
...

5.Pilot内部的配置信息获取方法

kubectl port-forward svc/istio-pilot 15014:15014 -n istio-system  

服务注册表信息
curl http://127.0.0.1:15014/debug/registryz

所有的endpoint
curl http://127.0.0.1:9093/debug/endpointz[?brief=1]

所有的配置信息
curl http://127.0.0.1:15014/debug/configz

Pilot自身的一些性能数据
curl http://127.0.0.1:15014/metrics
Devops  k8s