1.1 什么是istio?有什么用?

1
istio:之前业务出错我们需要重试,后来出了断路器等组件,但是是冗余到业务系统代码里的,istio就是要将这些断路器、重试、鉴权等东西抽离出来下沉成单独服务,让业务系统不在关心。也就是说在create pod的时候被人拦截下来,然后在pod里部署一个sidecar的容器,这步骤是无需业务代码感知的,是自动的。业务只需要关心业务就行,这些重试鉴权等东西自动沉淀下去。

1.2 istio的两大组件是什么

1
2
3
4
5
6
7
8
数据平面:由一组代理组成,这些代理微服务所有网络通信,并接收和实施来自Mixer的策略。
• Proxy:负责高效转发与策略实现。

控制平面:管理和配置代理来路由流量。此外,通过mixer实施策略与收集来自边车代理的数据。
• Mixer:适配组件,数据平面与控制平面通过它交互,为Proxy提供策略和数据上报。
• Pilot:策略配置组件,为Proxy提供服务发现、智能路由、错误处理等。
• Citadel:安全组件,提供证书生成下发、加密通信、访问控制。
• Galley:配置管理、验证、分发

istio组件

1.3 说说istio的注入?

1
2
3
4
5
6
7
8
9
10
11
12
将原来的pod停止,在新启动两个pod:原pod+istio proxy,准确的说启动三个pod,还有一个是istio-init,这个pod负责搭建网络环境,搭建完就消亡了,所以他是雷锋,铺好通信的道路就走了,所以到最后就两个pod,一个原来的pod,还一个是istio proxy代理。这些过程全自动。

部署httpbin Web示例:
cd istio-1.4.2/samples/httpbin
# 手动注入
kubectl apply -f <(istioctl kube-inject -f httpbin-nodeport.yaml)
或者
istioctl kube-inject -f httpbin-nodeport.yaml |kubectl apply -f -
# 自动注入
kubectl label namespace default istio-injection=enabled
kubectl apply -f httpbin-gateway.yaml
NodePort访问地址:http://192.168.31.62:31928

1.4 istio 有4 个配置资源

1
2
3
4
5
istio 有 4 个配置资源,落地所有流量管理需求:
• VirtualService:实现服务请求路由规则的功能。
• DestinationRule:实现目标服务的负载均衡、服务发现、故障处理和故障注入的功能。
• Gateway:让服务网格内的服务,可以被全世界看到。
• ServiceEntry :让服务网格内的服务,可以看到外面的世界。

1.5 istio概述 Service Mesh

1
2
3
4
5
6
7
8
9
通常serviceA去调用serviceB,是走的service名,然后通过dns解析cluster ip,再通过iptable和ipvs的规则转到serviceB,可以理解为直连。

所谓的Service Mesh,不让你直连,不希望你业务到业务的调用是直接走的,我希望做什么呢?我希望在每个业务的pod容器旁插一个Sidecar,就被转换成一几段,A服务的实例到他自己的边车这一段的调用,A的sidecar到B的sidecar的调用,B的sidecar到B服务的实例调用。为什么要做这些事情,平白无故的多了一些开销吗?他存在的原因:我们要委托他一些事情,
1.服务发现的能力
2.认证鉴权能力
3.协议升级TLS
4.熔断的能力(降级,比如广告微服务出现问题,让他不显示而已,不影响业务)
5.负载均衡的能力
所谓的服务风格,可以理解为传统意义上来讲的微服务平台加上Sidecar,以Sidecar的形式来实现的微服务的治理就是服务风格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Service Mesh 的中文译为 “服务网格” ,是一个用于处理服务和服务之间通信的基础设施层,它负责为构建复杂的云原生应用传递可靠的网络请求,并为服务通信实现了微服务所需的基本组件功能,例如服务发现、负载均衡、监控、流量管理、访问控制等。在实践中,服务网格通常实现为一组和应用程序部署在一起的轻量级的网络代理,但对应用程序来说是透明的。

服务网格:主要接管业务程序进出流量,管理这些流量

• 治理能力独立(Sidecar)
• 应用程序无感知
• 服务通信的基础设施层
• 解耦应用程序的重试/超时、监控、追踪和服务发现

• 连接(Connect)
- 流量管理
- 负载均衡
- 灰度发布
• 安全(Secure)
- 认证
- 鉴权
• 控制(Control)
- 限流
- ACL
• 观察(Observe)
- 监控
- 调用链

1.6 服务网关 gateway

1
2
3
4
5
6
7
8
9
10
Gateway为网格内服务提供负载均衡器,提供以下功能:
• L4-L7的负载均衡
• 对外的mTLS
Gateway根据流入流出方向分为:
• IngressGateway:接收外部访问,并将流量转发到网格内的服务。
• EgressGateway:网格内服务访问外部应用。

ingress gateway:envory
gateway # 绑定端口
virtualservice # 具体规则

istio-gateway

1.7 Istio 实现灰度发布

1
2
3
4
5
主流发布方案:
• 蓝绿发布
• 滚动发布
• 灰度发布(金丝雀发布)
• A/B Test

1.7.1 蓝绿发布

1
2
3
4
5
6
7
8
9
项目逻辑上分为AB组,在项目升级时,首先把A组从负载均衡中摘除,进行新版本的部署。B组仍然继续提供服务。A组升级完成上线,B组从负载均衡中摘除。
特点:
• 策略简单
• 升级/回滚速度快
• 用户无感知,平滑过渡
缺点:
• 需要两倍以上服务器资源
• 短时间内浪费一定资源成本
• 有问题影响范围大

1.7.2 滚动发布

1
2
3
4
5
6
7
8
每次只升级一个或多个服务,升级完成后加入生产环境,不断执行这个过程,直到集群中的全部旧版升级新版本。Kubernetes的默认发布策略。
特点:
• 用户无感知,平滑过渡
缺点:
• 部署周期长
• 发布策略较复杂
• 不易回滚
• 有影响范围较大

1.7.3 灰度发布(金丝雀发布)

1
2
3
4
5
6
7
8
9
只升级部分服务,即让一部分用户继续用老版本,一部分用户开始用新版本,如果用户对新版本没有什么意见,那么逐步扩大范围,把所有用户都迁移到新版本上面来。
特点:
• 保证整体系统稳定性
• 用户无感知,平滑过渡
缺点:
• 自动化要求高

基于权重的路由(金丝雀发布)
weight: 90

1.7.4 灰度发布(A/B Test)

1
2
3
灰度发布的一种方式,主要对特定用户采样后,对收集到的反馈数据做相关对比,然后根据比对结果作出决策。用来测试应用功能表现的方法,侧重应用的可用性,受欢迎程度等,最后决定是否升级。

基于请求内容的路由(A/B Test)

istio-灰度发布

1.8 可视化监控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
grafana:
1、请求成功率
2、http时延,百分位计算方式

Jaeger:
1、响应时间
2、链路追踪(关联的其他服务、HTTP请求详细信息)

kiali:
1、微服务链路拓扑图
2、单个微服务RPS、成功率、错误率
3、流量最小/最大(请求数据包和响应数据包)
4、查看工作负载(应用)
5、查看容器日志
6、数据包请求/响应大小
7、查看istio资源配置文件

istio解决什么问题?
1、故障排查
2、应用容错性
3、应用升级发布
4、系统安全性

1.9 一个项目使用istio做灰度发布:

1
2
3
4
5
6
7
8
9
1、使用deployment部署这项目,并增加一个独立用于区分版本的标签:version: v1
2、添加istio灰度发布规则(virtualservice、destinationrule)
3、灰度发布准备先将新的版本部署k8s中

service名称 端口
1、全部到v1
virtualservice -> subset -> destinationrule定义的subset名称 -> 根据标签匹配pod
2、90%v1 10%v2 增加两个版本权重 virtualservice -> subset
3、50%v2 50%v3 调整权重值

1.10 接入了istio后,mycaller服务请求myresponser服务时,http接口可以通,grpc服务不通

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
分析:
1.使用sleep容器对mycaller服务进行请求:
# kubectl exec -it -c sleep $(kubectl get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}') -- curl "mycaller.default:59130/testCaller/GetHello?type=1&orgcode=private&port=53605"
{"code":10000000,"error":"内部错误","detail":"grpc: error while marshaling: proto: Marshal called with nil"}
2.返回错误,于是查看mycaller服务容器的日志:
看日志http get请求返回了正常的数据,但是grpc调用Hello方法时报错:rpc error: code = Unimplemented desc = Not Found: HTTP status code 404; transport: received the unexpected content-type “text/plain; charset=utf-8”
3.于是再查看mycaller pod中的envoy日志:
发现是HTTP/2协议报的404,于是查看svc,是配置的grpc协议,不是http2
4.于是修改svc,将name从grpc-53606修改为http2-53606
5.再次请求mycaller服务,发现还是报一样的错误。搞了半天,索性把http部分去掉,只保留http2的port
参考文档:https://blog.csdn.net/scun_cg/article/details/104625863

例2:
我有一个服务在两个端口上监听;一个是http,另一个是grpc。 我想建立一个可以通过同一主机路由到这两个端口的入口。 如果使用http / 1.1,则负载均衡器将重定向到http端口,如果使用h2,负载均衡器将重定向到grpc端口。 有没有办法用istio做到这一点?
如果将grpc-server和http-server容器移动到具有唯一标签的不同容器(即,服务的不同版本,可以这么说),然后在Ingress后面使用Istio路由规则,则可以执行类似的操作。 标题Upgrade: h2匹配的规则可以将流量发送到grpc版本,默认规则会将其余流量发送到http 1