在服务网格后服务与服务之间的流量走向不再是默认k8s原来的走向路径了。具体表现可以对比在后端是GRPC多副本互相调度的时候,通过传统的SVC到iptables转发后端pod会发现流量不均衡的情况。启用网格后,然后定义好DestinationRule的轮训规则后。可以达到后端负载比较均匀。
但是具体是怎么实现的呢?
Istio 实现了 service mesh 的控制平面,并整合 Envoy 开源项目作为数据平面的 sidecar,一起对流量进行控制。
pilot的业务架构图为:
途中讲有 统一的服务模型、标准数据面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控制平面与数据平面 架构图
红色:控制流
黑色:数据流
流量管理组件
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