k8s进阶:Istio流量管理
基础教程
tetrate发行版有一个简单的istio入门教程,感觉还不错,视频+文字,中文字幕.
传送门,懒得在官方文档里面跳来跳去的可以直接看这个.
本文为基于该教程作的一些记录,基于istioctl+operator的部署方式,版本为1.10.3
发现选择器: Discovery selectors
Istio:1.10引入的新功能.
默认情况下,istio会watch和update集群中所有的服务,也就是所有集群中的服务都会被记录并维护在istiod的服务发现表中.
默认情况下所有envoy代理的配置方式是,他们可以到达服务网格中的每个工作负载,并接受与其相关的所有端口的流量.
例如有两个服务,foo和bar,尽管他们不需要相互通信,但是他们的端点都会被记录在对方的已发现端点列表中.
当服务数量越来越大,将不可避免地导致某程度的slow down.
discovery selectors就是为了解决这个问题存在的,配置在mesh层,可以限制被istio观察和处理的项目数量.
同样有类似功能的还有一个叫sidecar resource的解决方案.
一些命令
1 |
|
开启功能
1 |
|
1 |
|
可观测性:遥测和日志
监控: prometheus
追踪: zipkin
数据可视化: grafana
为了使grafana和kiali工作,需要先安装prometheus addon
istio会生成三种类型的遥测数据:指标度量(metric), 分布式追踪, 访问日志.
envoy代理负责收集指标.
Metric:指标
istio基于四个黄金信号生成指标:
延迟: 分为成功和失败请求的延迟
流量: 用于衡量系统需求,如每秒http请求数,并发会话,每秒检索量等
错误: 衡量失败请求的比率
饱和度: 衡量一个服务中最紧张的资源有多满.例如线程池利用率
代理级指标
可以从每个envoy代理实例的/stats
查看代理级指标
服务级指标
涵盖前面提到的四个黄金信号.这些指标可以让我们能够监控服务于服务之间的通讯.此外,istio还提供了一组仪表盘,我们可以根据这些指标监控服务行为.
默认情况下,istio的标准指标集会被导出到Prometheus.
控制平面度量
istio的控制平面也会有指标,用于监控istio的控制平面,[指标列表](Istio / pilot-discovery).
包括: 入站/出站监听器的数量,没有实例的集群数量,被拒绝或被忽略的配置等指标
Prometheus
1 |
|
然后在prometheus的dashboard中搜索istio_requests_total
就能看到刚刚的请求产生了1个请求数
Grafana
1 |
|
注意: 这里的配置不建议在生产中运行,因为它没有经过性能和安全方面的调整
默认已经在grafna配置了一些仪表盘:
istio控制平面仪表盘:control plane dashboard,展示控制平面的资源使用情况(mem,cpu,disk,go goutines),以及ilot,envoy和webhook信息.
网格仪表盘: mesh dashboard,提供网格中运行的所有服务的概览,包括全局请求数,成功率以及错误响应数.
性能仪表盘: performence,展示istio主要组件在稳定负载下的资源利用率
服务仪表盘: service,展示网格中的服务的细节,比如请求量,成功率,持续时间,以及显示按来源和响应代码,持续时间和大小的传入请求的详细图表
wash扩展: wash extension:显示于webassembly模块有关的指标,通过这个仪表盘,我们可以监控活动的和创建的wash虚拟机和获取删除wash模块和代理资源使用的数据.
istio工作负载: workload:关于工作负载的指标
分布式追踪
是一种检测微服务apps的方法.
当一个请求进入服务网格时,Envoy都会生成一个唯一的请求ID和追踪信息,并存储在http请求头中,任何apps都可以将这些header转发给它缩调用的其他服务,这样就可以在震哥哥系统中创建一个完整的追踪.
span
分布式追踪是一个跨度(span)
的集合.
每当有请求流经不同的系统组件时,每个组件都会产生一个跨度.每个跨度包含:
一个名称
一组<标签tag>:<日志log>的键值对
以及一个span context,跨度上下文
单个跨度,识别跨度,父跨度和追踪ID的上下文头一起被发送到一个叫做采集器的组件,采集器负责对数据进行验证,索引和存储.
当请求流经Envoy代理时,Envoy代理会自动生成各个跨度.但是,envoy只能在边缘收集跨度,任何如果需要的额外的跨度,由我们的app需要负责生成.
我们的app还要确保我们在调用其他服务时转发追踪header.这样,各个跨度才能正确地关联到一个单一的追踪中.
Zipkin
Zipkin是一款开源的分布式实时数据追踪系统(Distributed Tracking System),基于 Google Dapper的论文设计而来,由 Twitter 公司开发贡献。其主要功能是聚集来自各个异构系统的实时监控数据。分布式跟踪系统还有其他比较成熟的实现,例如:Naver的Pinpoint、Apache的HTrace、阿里的鹰眼Tracing、京东的Hydra、新浪的Watchman,美团点评的CAT,skywalking等。
上面说到,为了让我们的服务参与分布式追踪,我们需要在进行任何下游服务调用时传播http header.
但是尽管所有请求都经过istio sidecar,istio没有办法将出站和入站请求关联起来,而zipkin可以利用在服务之间传播的header,将这些请求拼接起来,形成完整的追踪.
istio依赖B3跟踪头(以x-b3开头的header)和envoy生成的请求id(x-request-id),通常做法是我们的应用程序需要捕获传入请求的以下header并将他们包含在所有从你的app发送出去的请求中:
x-request-id
x-b3-traceid
x-b3-spanid
x-b3-parentspanid
x-b3-sampled
x-b3-flags
b3
如果使用lightstep,还需要转发x-ot-span-context
zipkin的安装运行方式于上面的addon类似,在samples/addons/extras中有示例配置yaml文件.
Jaeger
也是一个分布式追踪平台,它与zipkin的对比可以看看这篇文章: Jaeger与Zipkin:分布式跟踪平台该选谁_Kubernetes中文社区
1 |
|
Kiali
Kiali是一个基于istio的service mesh管理控制台.提供dashboard,可视化,允许我们通过web界面配置,验证,操作网格.它通过推断流量拓扑来显示服务网格,并显示网格的健康状况.
它提供强大的验证,详细的指标,grafana访问,以及于jaeger的分布式追踪的强大集成.
安装部署与上面其他addon类似,示例配置文件在/spamles/addon/kiali.yaml
如果遇到报错:unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1"
,重新执行一次apply即可,原因是在安装CRD(自定义资源定义)和该CRD定义的资源时,会存在一个匹配条件.
流量管理
在k8s进阶:Istio - Any & Nothing 一文中我们已经根据官方文档操作了一遍流量管理的功能,这里再进行一些复习或查漏补缺.
gateway
默认安装了两个gateway: ingressgateway和engressgateway
入口网关接受入站连接,出口网关接受从集群出去的连接.网关都运行一个envoy代理,他们再网格的边缘作为负载均衡器运行.
默认使用的是loadbalance类型的svc,私有环境没有外置的负载均衡器可以通过以下方式获取它的nodeIP和nodePort:
1 |
|
有了网关,我们还需要配置网关资源(Gateway)来配置网关.
这两个东西叫法上容易叫混:
网关,ingressgateway和engressgateway部署在网格边缘,可以叫做
网关控制器
或者叫网关代理
网关资源,Gateway,是用来配置网关控制器的,也可以叫
网关配置
下面是一个例子:
1 |
|
网关控制器部署时默认有个istio=ingressgateway的标签,网关配置根据这个标签来选择它使用的网关控制器.
hosts是一个过滤器,只有以符合它配置规则为目的地的流量才能允许通过.
简单路由
virtual service
使用virtual service实现路由,通过virtual service我们可以定义流量路由规则,并在客户端连接服务时应用这些规则.例如上一篇文章配置的将流量路由到不同version的pod.下面再举一个例子:
1 |
|
在这个例子中,我们定义流量发送到customers.default.svc.cluster.local这个kubernetes的SVC,这个SVC下绑定了两个版本的pod,通过virtual service定义70%流量去到v1,30%去到v2.
http是一个包含http流量的路由规则的有序列表.
destination是指服务注册表中的一个服务,也是路由规则处理后请求将被发送的目的地.istio的服务注册表上记录的都是合法值,也包括通过serviceEntry手动添加的合法服务.
gateway字段则用来绑定对应的网关资源,有点类似ingressclass和ingress的关系
virtual service和gateway的hosts匹配关系
gateway hosts | virtualservice hosts | action |
---|---|---|
* | customers.default.svc.cluster.local | 流量会直接通过virtual service发送到目的地customers,因为gateway允许了所有 |
customers.default.svc.cluster.local | customers.default.svc.cluster.local | host匹配,流量将被发送 |
hello.com | customers.default.svc.cluster.local | hosts不匹配,无效 |
hello.com | [“hello.com”, “customers.default.svc.cluster.local”] | 只会允许hello.com,这依然是一个有效配置,因为virtual service可以连接到第二个网关,该网关的hosts包含*.default.svc.cluster.local即可 |
subset 和 destination rule
目的地指的是不同子集(subset)或服务版本.通过subset,我们可以识别应用程序的不同变体.比如version1和version2.对应于我们对应服务的两个不同版本.
每个子集都使用label去确定那些pod包含在子集中.
subset在destination rule中声明,这里前文就有例子.
另外destination rule还可以配置流量策略.
destination rule的流量策略
负载均衡策略
1 |
|
还可以基于哈希的负载均衡,并基于http头,cookies或其他请求属性实现亲和性,例如:
1 |
|
连接池配置
应用于上游服务的每个主机,用它来控制连接量:
1 |
|
异常点检测/断路器/熔断
跟踪上游
服务中每个主机(pod)的状态,如果一个主机开始返回错误,它就会在预定的时间内被负载均衡池中弹出.
对于TCP服务,envoy将连接超时或失败计算判定为错误.
1 |
|
客户端TLS设置
1 |
|
其他支持的TLS模式有:
DISABLE: 没有TLS连接
SIMPLE: 在上游端点发起TLS连接
ISTIO_MUTUAL: 类似MUTUAL但使用的istio的mTLS证书
端口流量策略
可以根据不同的端口配置不同的流量策略
1 |
|
弹性:Resiliency
弹性的目的是故障发生后将服务恢复到一个完全正常的状态.也就是failover.
服务的可用关键是在提出服务请求时使用超时(timeout)和重试(retry)策略.可以在istio的virtual service上配置这两者.下面是两个例子.
1 |
|
注意: 如果同时设置超时和重试,超时值是请求等待的最长时间,比如如果我们在上面的第二个例子中设置了超时10s,那么10s一过,即使重试策略还剩下一些尝试,也会终止直接判断服务不可用.
重试策略可以更加细化:
例如我们可以只在上游服务器返回5xx错误或者网关错误(502,503,504)时重试,或者在请求头中指定可重试的状态代码.
重试和超时都发生在客户端.
当envoy重试请求时,最初失败并导致重试的端点就不再包含在负载均衡池中,例如:
假设kubernetes有3个端点(pod),其中一个失败了,并出现了可重试的错误代码,Envoy重试请求时,将不会向原来的端点重新发送,而只发送给另外两个没有失败的端点的一个.