Istio 学习笔记
作者:王珂
邮箱:49186456@qq.com
文章目录
前言
本文主要讲解在使用Istio开发微服务过程中涉及到的一些基本概念,Istio环境安装,Istio组件作用和使用方法。最后再通过实战讲解来结束Istio的学习。
我的Kubernetes信息
节点名称 | IP | 说明 |
---|---|---|
node21 | 192.168.1.21 | 主节点名称为node21 |
node26 | 192.168.1.26 | 工作节点名称为node26 |
node27 | 192.168.1.27 | 工作节点名称为node27 |
node28 | 192.168.1.28 | 工作节点名称为node28 |
一、基本概念
服务网格
服务网格 Service Mesh
Kubernetes Ingress, Gateway和Istio Gateway的区别
2022年5月份Kubernetes Gateway API才发布了 Beta 版本,当前大多数组织应该还在使用稳定的 Ingress API。
Kubernetes Ingress
Kubernetes Ingress 是一个资源对象,用于控制进入 Kubernetes 集群的流量。
它可以配置外部 IP 地址、端口、域名、以及路径等信息,将流量路由到不同的服务。
Ingress 通常使用 Nginx 或 HAProxy 等代理服务器来实现。Kubernetes Gateway
Kubernetes Gateway 是一个 API 对象,用于定义网络流量的入口点。
它可以配置服务、端口、协议等信息,以及如何将流量路由到不同的服务。
Gateway 旨在替代 Ingress 成为 Kubernetes 中流量管理的标准 API。Gateway API 在 Ingress API 的基础上增加了更多特性,例如 HTTP 头匹配、加权流量分割、多协议支持(如 HTTP、gRpc)以及其他各种后端功能(如桶、函数)。
Gateway API 比 Ingress API 更好的分离了关注点。使用 Ingress,集群运维人员和应用开发人员在同一个 Ingress 对象上操作,却不知道彼此的角色,可能会导致设置错误。
Route 和 Gateway 对象是由 Gateway API 独立于配置创建的,从而为集群运维人员和应用开发人员提供了自主权。
Istio Gateway
Istio Gateway 是 Istio 服务网格中的一个组件,用于控制进入服务网格的流量。
它可以配置虚拟服务、端口、协议等信息,以及如何将流量路由到不同的服务。
Istio Gateway 使用 Envoy 代理来实现,并支持更丰富的流量管理功能,例如服务发现、负载均衡、熔断、超时、重试等。
简而言之:
Kubernetes Ingress 和 Gateway 都是用于控制进入 Kubernetes 集群的流量的资源对象。
Gateway 是 Ingress 的下一代 API,旨在提供更强大的功能和灵活性。
Istio Gateway 是 Istio 服务网格中用于控制进入服务网格的流量的组件,并支持更丰富的流量管理功能。
三个对象对比
特性 Kubernetes Ingress Kubernetes Gateway Istio Gateway
API 对象 Ingress Gateway Gateway
代理服务器 Nginx, HAProxy Envoy Envoy
支持的流量管理功能 基本 增强 丰富
服务发现 不支持 支持 支持
负载均衡 支持 支持 支持
熔断 不支持 支持 支持
超时 不支持 支持 支持
重试 不支持 支持 支持
使用场景:
如果您只需要基本的流量管理功能,可以使用 Kubernetes Ingress。
如果您需要更强大的流量管理功能,可以使用 Kubernetes Gateway 或 Istio Gateway。
如果您使用 Istio 服务网格,则建议使用 Istio Gateway。
1.1 Istio定义
官网(英文):
https://istio.io/latest/
官网(中文):
https://istio.io/latest/zh/
Istio是一个开源的服务网格。
特性
- 自动负载均衡HTTP, gRPC, WebSocket和TCP流量
架构
Istio服务网格从逻辑上分为数据平面和控制平面
数据平面
由一组被部署为 Sidecar 的智能代理(Envoy) 组成。这些代理负责协调和控制微服务之间的所有网络通信。 它们还收集和报告所有网格流量的遥测数据。
控制平面
管理并配置代理来进行流量路由。
二、Istio的安装
2.1 通过Istioctl安装
Kubernetes与Istio对应关系
https://istio.io/latest/docs/releases/supported-releases/#support-status-of-istio-releases
下载
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.16.6 sh -
目录说明
./istio-1.16.6 ├── bin # 存放istioctl二进制文件 ├── LICENSE ├── manifests # istio内置的chart目录,默认使用这些内置的chart生成安装清单,安装过程也可以自行设置 ├── manifest.yaml # 指定外部chart ├── README.md ├── samples # 提供一些示例应用程序 └── tools # 一些工具,如certs用于生成证书
1)配置环境变量
cat <<EOF > /etc/profile.d/custom.sh #! /bin/bash export ISTIO_HOME=/opt/istio/istio-1.16.6 export PATH=$ISTIO_HOME/bin:$PATH EOF
查看istio的profile
istioctl profile list
Istio configuration profiles:
ambient
default
demo
empty
external
minimal
openshift
preview
remote
① default: 根据 lstioOperator AP!的默认设置启动组件。建议用于生产部署和 Multicluster Mesh 中的 Primary Cluster。您可以运行 istioct profile dump 命令来查看默认设置,
② demo: 这一配置具有适度的资源需求,旨在展示lstio 的功能。它适合运行 Bookinfo 应用程序和相关任务。 此配置文件启用了高级别的追踪和访问日志,因此不适合进行性能测试。
③ minimal: 与默认配置文件相同,但只安装了控制平面组件。它允许您使用 Separate Profile 配置控制平面和数据平面组件(例如 Gateway)。
④ remote: 配置Multicluster Mesh 的 Remote Cluster.
⑤ empty: 不部署任何东西。可以作为自定义配置的基本配置文件。
⑥ preview: 预览文件包含的功能都是实验性。这是为了探索 lstio 的新功能。不确保稳定性、安全性和性能(使用风险需自负)。
组件 | default | demo | minimal | remote | empty | preview |
---|---|---|---|---|---|---|
核心组件 | ||||||
istio-ingressgateway | √ | √ | √ | |||
istio-egressgateway | √ | |||||
istiod | √ | √ | √ | √ |
2)执行安装
istioctl install --set profile=demo
3)给命名空间添加标签
创建ns-istio命名空间
kubectl create namespace ns-istio
给命ns-istio名空间添加标签,指示istio在部署应用的时候,自动注入Envoy边车代理
kubectl label namespace ns-istio istio-injection=enabled
查看安装结果
kubectl get svc,pod -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/istio-egressgateway ClusterIP 10.102.75.82 80/TCP,443/TCP 14h
service/istio-ingressgateway LoadBalancer 10.108.158.227 15021:31495/TCP,80:30645/TCP,443:30754/TCP,31400:31434/TCP,15443:31846/TCP 14h
service/istiod ClusterIP 10.105.204.23 15010/TCP,15012/TCP,443/TCP,15014/TCP 14hNAME READY STATUS RESTARTS AGE
pod/istio-egressgateway-66d96985c-2xc4x 1/1 Running 2 (10h ago) 14h
pod/istio-ingressgateway-c5fd879b5-f4wkh 1/1 Running 2 (10h ago) 14h
pod/istiod-98988c6b6-8qvr8 1/1 Running 2 (10h ago) 14h
4)卸载
istioctl uninstall --purge
删除istio-system命名空间
kubectl delete namespace istio-system
2.2 通过Helm安装
TODO
三、Istio组件
3.1 Gateway
在安装Istio的时候,安装了入口网关和出口网关。这两个网关实际都运行了一个Envoy代理实例,他们在网格的边缘做为负载均衡器运行。入口网关接收入站连接,而出口网关接收从集群出去的连接。
有一个指向入口网关单一的外部IP地址,并根据Header将流量路由到集团内的不同的服务。通过入口网关,可以对进入集群的流量应用路由规则。
使用Gateway配置网关资源
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: gateway-hello namespace: ns-istio spec: selector: istio: ingressgateway # 通过这个标签选中了istio=ingressgateway的service servers: - port: number: 80 name: http protocol: HTTP hosts: - hello.alisls.com
上述配置解释:
配置了一个代理,做为负载均衡器
为入口暴露80端口
配置应用于istio入口网关代理
hosts字段做为一个过滤器,只有以hello.alisls.com为目的地的流量才被允许通过
网关资源描述了负载均衡器的暴露端口、协议、SNI配置等
Gateway字段名称 | 字段含义 |
---|---|
metadata.name | Gateway名称 |
metadata.namespace | |
spec.selector | Gateway使用填写的标签键值对匹配配置下发的边缘代理网关实例 |
spec.servers.port.number | 端口 |
spec.servers.hosts | 域名,支持通配符* |
spec.servers.tls.httpsRedirect | 值为true时,边缘代理网关会对所有http请求返回301重定向,要求客户端发起https请求 |
spec.servers.tls.mode | 配置当前端口的 TLS 安全认证模式,如需要开启当前端口的安全认证则需要填写。支持PASSTHROUGH, SIMPLE, MUTUALAUTO PASSTHROUGH, ISTIO MUTUAL |
spec.servers.tls.credentialName | 配置发现 TLS 证书密钥的 secret 的名称 |
spec.servers.tls.serverCertificate | 设置端口的 TLS 证书密钥通过 file mount 形式(不推荐,推荐采用填写 credentialName 字段加载证书私钥)挂载时需要填写的证书路径字段Istio 默认使用网关所在命名空间下 istio-ingressgateway-certssecret加载证书至路径/etc/istio/ingressgateway-certs |
spec.servers.tls.privateKey | 设置端口的 TLS 证书密钥通过 file mount 形式(不推荐,推荐采用填写 credentialName 字段加载证书私钥)挂载时需要填写的私钥路径字段Istio 默认使用网关所在命名空间下 istio.ingressgateway-certs secret 加载私钥至路径/etc/istio/ingressgateway-certs |
spec.servers.tls.caCertificates | 设置端口的 TLS 证书密钥通过 file mount 形式(不推荐,推荐采用填写 credentialName 字段加载证书私钥)挂载时需要填写的跟证书路径字段Istio 默认使用网关所在命名空间下 istio-ingressgateway-ca-certs 加载根证书至路径/etc/istio/ingressgateway-ca-certs,双向认证时需要配置根证书 |
SNI, 服务器名称指示,是TLS协议的扩展。它指示在”握手“过程开始时浏览器正在联系哪个主机名;允许服务器为多个站点安全地托管多个SSL证书,多个网站存在于同一IP地址上。
为了控制和转发流量到集群内部运行实例的Kubernetes服务,我们必须用特定的主机名(例如:hello.alisls.com)配置一个VirtualService,让后将网关连接到它。
3.2 VirtulService
使用VirtualService资源在Istio服务网格中进行流量路由。通过VirtualService定义流量路由规则。
VirtualService字段名称 | 字段说明 |
---|---|
spec.hosts | 定义路由规则关联一组的 hosts,可以是带有通配符的 DNS 名称或者IP 地址(IP 地址仅能应用于来源流量为边缘代理网关)。该字段能应用于HTTP 和 TCP 流量。在 Kubernetes 环境中,可以使用 service 的名称作为缩写,lstio 会按照VirtualService所在 namespace 补齐缩写,例如在default namespace 的VirtualService 包含host 缩写 reviews 会被补齐为reviews.default.svc.cluster.local。为避免误配置,推荐填写 host 全称 |
spec.gateways | 定义应用路由规则的来源流量,可以是一个或多个网关,或网格内部的 sidecar,指定方式为/,保留字段 mesh 表示网格内部所有的 sidecar,当该参数缺省时,会默认填写 mesh,即该路由规则的来源流量为网格内部所有 sidecar |
spec.http | 定义一组有序的(优先匹配靠前的路由规则)应用于 HTTP 流量的路由规则,HTTP 路由规则会应用于网格内部的 service 端口命名为 http-,http2-,grpc-开头的流量以及来自 gateway 的协议为HTTP HTTP2,GRPC, TLS-Terminated-HTTPS 的流量 |
spec.http.match | 定义路由的匹配规则列表,单个匹配规则项内所有条件是且关系,列表中多个匹配规则之间为或关系 |
spec.http.route | 定义路由转发目的地列表,一条 HTTP 路由可以是重定向或转发(默认),转发的目的地可以是一个或多个服务(服务版本)。同时也可以配置权重、header 操作等行为 |
spec.http.redirect | 定义路由重定向,一条 HTTP 路由可以是重定向或转发(默认),如规则中指定了 passthrough 选项,route、redirect 均会被忽略。可将 HTTP301 重定向到另外的 URL 或 Authority |
spec.http.rewrite | 定义重写 HTTP URL或 Authority headers,不能与重定向同时配置,重写操作会在转发前执行 |
spec.http.timeout | 定义HTTP请求的超时时间 |
spec.http.retries | 定义HTTP请求的重试策略 |
spec.http.fault | 定义HTTP流量的故障注入策略,开启时超时和重试策略不会开启 |
spec.http.mirror | 定义将 HTTP 流量复制到另一个指定的目的端,被复制的流量按照“best effort”原则,sidecar/网关不会等待复制流量的响应结果就会从源目的端返回响应。镜像流量的目的服务端会产生监控指标。 |
spec.http.mirrorPercent | 定义流量镜像的复制百分比,缺省时复制100%的流量。最大值为100 |
spec.http.corsPolicy | 定义 CORS 策略(跨域资源共享,Cross-OriginResource Sharing, CORS) |
spec.http.headers | 定义 header 操作规则,包括 request 和response header 的更新,增加,移除操作 |
spec.tcp | 定义一组有序的(优先匹配靠前的路由规则)应用于 TCP 流量的路由规则,该路由规则会应用于任何非 HTTP 和 TLS 的端口 |
spec.tcp.match | 定义 TCP 流量路由的匹配规则列表,单个匹配规则项内所有条件是且关系,列表中多个匹配规则之间为或关系 |
spec.tcp.route | 定义 TCP 连接转发的目的端 |
spec.tls | 定义一组有序的(优先匹配靠前的路由规则)应用于未终止的 TLS 或 HTTPS 流量的路由规则,该路由规则会应用于网格内部的 service 端口命名为https-,tls-开头的流量,来自 gateway 的端口协议为 HTTPS, TLS 的未终止加密流量,ServiceEntry 使用 HTTPS, TLS 协议的端口。当 https-,tls-端口未关联 VirtualService 规则时将会被视为TCP 流量 |
spec.tls.match | 定义 TLS 流量路由的匹配规则列表,单个匹配规则项内所有条件是且关系,列表中多个匹配规则之间为或关系 |
spec.tls.route | 定义连接转发的目的端 |
3.2.1 route详解
HTTPRoute规则的功能是:满足HTTPMatchRequest条件的流量都被路由到HTTPRouteDestination,执行重定向(HTTPRedirect)、重写(HTTPRewrite)、重试(HTTPRetry)、故障注入(HTTPFaultlnjection)、跨站(CorsPolicy)策略等。HTTPRoute不仅可以做路由匹配,还可以做一些写操作来修改请求本身。
3.2.2 match详解
match定义路由的匹配条件。
支持以下字段的定义:
uri, schema, method, authority: 这四个字段都是StringMatch类型,匹配请求时都支持exact, prefix和regex三种模式的匹配
- match: - uri: prefix: /hello
headers: 匹配请求中的Header,是一个map类型。map的key是字符串类型,value是StringMatch类型。即对每一个Header的值,都可以使用精确、前缀和正则三种方式进行匹配。
- match: - headers: source: exact: north
port: 表示请求服务的端口,大多数服务只开放一个端口,这也是在微服务中推荐的做法,在这种场景下可以不指定port;
sourceLabels: 是一个map类型的键值对,表示请求来源负载匹配标签。这在很多情况有用,可以对一组服务都打一个相同的标签,然后使用sourceLabels字段对这些服务实施相同的流量规则。在Kubernetes平台上,这里的Label就是Pod上的标签。
http: - match: - sourceLabels: app: testA version: v2
gateway: 表示规则应用的Gateway名称,语义同VirtualService 上面的gateway定义,是一个更细的Match条件,会覆盖在VirtualService上配置的gateway。
在VirtualServite中match字段都是数组类型。HTTPMatchRequest中的诸多属性如uri、header、method等都是“与”逻辑,而数组中几个元素间关系是“或”逻辑。
- match: - headers: source: exact: north uri: prefix: "/hello" - uri: prefix: "/hello2"
match包含两个HTTPMatchRequest元素,其条件的语义是:headers中的source取值为“north”,且uri以“/hello”开头的请求,或者uri以“/hello2”开头的请求。
3.2.3 路由目标
路由目标,RouteDestination
route字段是一个HTTPRouteDestination类型的数组,表示满足条件的流量目标。
destination 请求目标,包含host, subset, port三个属性
1)host 在istio中注册的服务名
2)subset 表示在host上定义的一个子集
3)port
spec: hosts: - hello.alisls.com http: - route: - destination: host: hello.alisls.com subset: v2 - destination: host: hello.alisls.com subset: v1
weight 权重
weight表示流量分配的比例,在一个route下多个destination的weight总和要求是100。默认也是100,必填字段。
示例:从原有的v1版本中切分20%的流量到v2版本,这也是灰度发布常用的一个流量策略,即不区分内容,平等的从总流量中切出一部分给新版本。
spec: hosts: - hello.alisls.com http: - route: - destination: host: hello.alisls.com subset: v2 weight: 20 - destination: host: hello.alisls.com subset: v1 weight: 80
headers
提供了对HTTP header的一种操作机制,可以修改一次HTTP请求中的Request或Response的值。包含request和response两个字段。
request
表示发请求给目标地址时修改request的header
response
表示返回应答时修改response的header
对应的类型都是HeaderOperation类型,使用set, add, remove字段来定义对Header的操作。
set: 使用map上的key和value覆盖request和response中对应的header
add: 追加map上的key和value到原有的header
remove: 删除在列表中指定的header
3.2.4 HTTP重定向
HTTPRedirect包括两个重要的字段来表示重定向的目标
uri 替换URL中的uri部分
authority 替换URL中的Authority部分
1)用户请求老地址
http://hello.alisls.com/hello
2)服务端返回301重定向新地址
http://welcom.alisls.com/welcome
3)用户请求新地址
http://welcom.alisls.com/welcome
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: gateway-hello namespace: ns-istio spec: hosts: - hello.alisls.com http: - match: - uri: prefix: /hello redirect: uri: /welcome authority: welcome.alisls.com
对hello.alisls.com服务所有前缀是/hello的请求都会被重定向到welcome.alisls.com的/welcome地址。
3.2.5 HTTP重写
通过HTTP重写可以在将请求转发给目标服务前修改HTTP请求中指定部分的内容,不同于重定向,用户是可见的(HTTP重写对用户实不可见的,因为在服务端进行的)。
重写HTTP也包括uri和authority两个字段
uri 重写URL中的Path部分
authority 重写URL中的Authority
和HTTPRedirect规则稍有不同的是,HTTPRedirect替换全部的Path;HTTPRewrite的uri是可以重写前缀的,即如果原来匹配条件是前缀匹配,则修改后只修改匹配到的前缀。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hello namespace: ns-istio spec: hosts: - hello.alisls.com http: - match: - uri: prefix: /hello rewrite: uri: /welcome route: - destination: host: hello
前缀匹配/hello的请求,其请求uri中的这部分前缀会被/welcome替换。
3.2.6 HTTP重试
HTTP重试是解决很多请求异常最直接、简单的方法。尤其是在工作环境比较复杂的场景下,可提高总体服务质量。
但重试使用不当也会有问题,最糟糕的情况是重试一直不成功,反而增加延迟和性能开销。所以根据系统运行环境、服务自身特点,配置适当的重试规则显得尤为重要。
HTTPRetry可以定义请求失败时的重试策略,重试策略包括重试次数,超时,重试条件等,这里分别描述相应的三个字段:
attempts
必选字段,定义重试次数
perTryTimeout
每次重试超时的时间,单位可以是ms, s, m和h
retryOn
进行重试的条件,可以是多个条件,以逗号分隔。
取值包括以下几种:
5xx: 在上游服务返回5xx应答码,或者在没有返回时重试
gateway-error: 类似5xx异常,只对502,503和504应答码进行重试
connect-failure: 在链接上游服务失败时重试
retriable-4xx: 在上游服务返回可重试的4xx应答码时执行重试
refused-stream: 在上游服务使用REFUSED_STREAM错误码重置时执行重试
cancelled: gRPC应答的Header中状态码是cancelled时执行重试
deadline-exceeded: 在gRPC应答的Header中状态码是deadline-exceeded时执行重试
internal: 在gRPC应答的header中状态码是internal时执行重试
resource-exhausted: 在gRPC应答的Header中状态码是resource-exhausted时执行重试
unavailable: 在gRPC应答的Header中状态码是unavailable时执行重试
示例:
配置一个重试策略,在5xx, connect-failure条件下进行最多5次重试,每次重试超时为3秒
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hello namespace: ns-istio spec: hosts: - hello.alisls.com http: - route: - destination: host: hello retries: attempts: 3 perTryTimeout: 3s retryOn: 5xx, connect-failure
3.2.7 HTTP流量镜像
HTTP流量镜像是指将流量转发到原目标地址的同时,将流量给另外一个目标地址镜像一份。把生产环境中的实际流量镜像一份到另一个系统上,完全不会对生产系统产生影响。这里只镜像了一份流量,数据面代理只需要关注原来转发的流量就可以,不用等待原镜像目标地址的返回。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hello namespace: ns-istio spec: hosts: - hello.alisls.com http: - route: - destination: host: hello subset: v1 mirror: host: hello subset: v2
3.2.8 HTTP故障注入
延时故障注入HTTPFaultInjection通过delay和abort两个字段设置延时和中止两种故障,分别表示Proxy延时转发HTTP请求和中止HTTP请求。
延时故障注入
使用HTTPFaultInjection.Delay类型描述延时故障。表示发送请求前进行一段延时,模拟网络、远端服务负载均衡等各种原因导致的失败,主要有以下两个字段:
fixedDelay
必选字段,表示延时时间,单位可也是毫秒、秒、分钟和小时。至少大于1毫秒。
percentage
配置的延迟故障作用在多少比例的请求上,通过这种方式可以只让部分请求发生故障。
示例:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hello namespace: ns-istio spec: hosts: - hello.alisls.com http: - route: - destination: host: hello subset: v1 fault: delay: percentage: value: 1.5 fixedDelay: 10s
请求中止故障注入
使用HTTPFaultInjection.Abort描述中止故障,模拟服务端异常,给调用的客户端返回预先预先定义的错误状态码,主要有以下两个字段:
httpStatus 是一个必选字段,表示中止的HTTP状态码
percentage 配置中止故障作用在多少比例的请求上,通过这种方式可以只能让部分请求发生故障,用法同延时故障
示例:让hello的v1版本的服务1.5%的请求返回500
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hello namespace: ns-istio spec: hosts: - hello.alisls.com http: - route: - destination: host: hello subset: v1 fault: abort: percentage: value: 1.5 httpStatus: 500
3.2.9 HTTP跨域资源共享
HTTP跨域资源共享 CORS(Cross Origin Resource Sharing)
当一个资源向该资源所在服务器的不同领域发起请求时,就会产生一个跨域的HTTP请求。出于安全考虑,浏览器会限制从脚本发起的跨域HTTP请求。通过跨域资源共享CORS机制可以允许Web应用服务器进行跨域访问控制,使跨域数据传递安全进行。在实现上是在HTTP Header中追加一些额外的信息来通知浏览器准许以上访问。
在VirtualService中可以对满足条件的请求配置跨域资源共享。有allowOrigin, allowMethods, allowHeader, exposeHeader, maxAge, allowCredentials, 其实都是被转化成Access-Control-*的Header。
示例:允许来在news.com的GET方法的请求的访问:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: vs-hello namespace: ns-istio spec: hosts: - hello.alisls.com http: - route: - destination: host: hello corsPolicy: allowOrigin: - news.com allowMethods: - GET maxAge: "2d"
3.3 DestinationRule
VirtualService中的destination中会包含Service子集的subset字段,这个服务子集就是通过DestinationRule定义的。
字段名称 | 字段含义 |
---|---|
spec.host | 关联 DestinationRule 配置的服务名称,可以是自动发现的服务(例如 Kubernetes servicename),或通过ServiceEntry声明的 hosts。如填写的服务名无法在上述源中找到,则该DestinationRule 中定义的规则无效 |
spec.subsets | 定义服务的版本(subsets),版本可通过标签键值对匹配匹配服务中的endpoints。可以在subsets 级覆盖流量策略配置 |
spec.trafficPolicy | 定义流量策略,包括负载均衡、连接池、健康检查、TLS 策略 |
spec.trafficPolicy.loadBalancer | 配置负载均衡算法,可配置:简单负载均衡算法(round robin, least conn, random…),一致性哈希(会话保持,支持按 headername,cookie,IP,query parameter 哈希),地域感知负载均衡算法 |
spec.trafficPolicy.connectionPool | 配置与上游服务的连接量,可设置 TCP/HTTP 的连接池 |
spec.trafficPolicy.outlierDetection | 配置从负载均衡池中驱逐不健康的 hosts |
spec.trafficPolicy.tls | 连接上游服务的 client 端 TLS 相关配置,与PeerAuthentication 策略(server 端 TLS 模式配置)配合使用 |
spec.trafficPolicy.portLevelSettings | 配置端口级别的流量策略,端口级别的流量策略会覆盖服务/subsets 级别的流量策略配置 |
通过DestinationRule,我们可以定义设置,如负载均衡配置,连接池大小,局部异常检测,在路由发生后应用于流量。我们可以在trafficPolicy字段下设置流量策略。
负载均衡器设置
连接池设置
局部异常点检测
客户端TLS设置
端口流量策略
示例:
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: dr-hello namespace: ns-istio spec: host: hello.ns-istio.svc.cluster.local subsets: - name: v1 labels: version: v1 - name: v1 labels: version: v2
3.3.1 负载均衡器设置
通过负载均衡器设置,我们可以控制目的地使用哪种负载均衡算法。
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: dr-hello namespace: ns-istio spec: host: hello.ns-istio.svc.cluster.local trafficPolicy: loadBalancer: simple: ROUND_ROBIN # 轮询算法 subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2
simple字段指定负载均衡算法
1)ROUND_ROBIN 轮询算法,默认
2)LEAST_CONN 最少连接算法
3)RANDOM 随机
4)PASSTHROUGH 直接转发连接到客户端连接的目标地址,即没有做负载均衡
consistentHash字段
一致性hash,并根据HTTP头,cookies或其他请求属性提供会话亲和性。
httpHeaderName: 基于Header
httpCookie: 基于Cookie
useSourceIP: 基于源IP计算哈希值
minimumRingSize: 哈希环上虚拟节点数的最小值,节点数越多则负载均衡越精细
... trafficPolicy: loadBalancer: consistentHash: httpCookie: name: location ttl: 4s
3.3.2 连接池配置
可以在TCP和HTTP层面应用于上游服务的每个主机,可用用来控制连接数量。
TCP连接池配置
1)maxConnections
上游服务的所有实例建立的最大连接数,默认是1024,属于TCP层面的配置,对于HTTP,只用于HTTP/1.1,因为HTTP/2对每个主机都使用单个连接。
2)connectTimeout: TCP连接超时,表示主机网络连接超时,可以改善因调用服务变慢导致整个链路变慢的情况。
3)tcpKeepalive: 设置TCP keepalives,属于istio1.1新支持的配置,定期给端发送一个keepalive的探测包,判断连接是否可用。
spec: host: hello.ns-istio.svc.cluter.local trafficPolicy: connectionPool: tcp: maxConnections: 50 connectTimeout: 25ms tcpKeepalive: probes: 5 time: 3600 interval: 60s
Http连接池配置
1)http1MaxPendingRequests: 最大等待 HTTP 请求数,默认值是 1024,只适用于HTTP/1.1 的服务,因为 HTTP/2 协议的请求在到来时会立即复用连接,不会在连接池等待。
2)http2MaxRequests: 最大请求数,默认是1024。只适用于HTTP/2服务,因为HTTP/1.1使用最大连接数maxConnections即可,表示上游服务的所有实例处理的最大请求数。
3)maxRetries: 最大重试次数,默认是3,表示服务可以执行的最大重试次数。如果调用端因为偶尔抖动导致请求直接失败,则可能会带来业务损失,一般建议配置重试,若重试成功则可正常返回数据,只不过比原来响应得慢一点,但重试次数太多会影响性能,要谨使用。
4)idleTimeout: 空闲超时,定义在多长时间内没有活动请求则关闭连接。
http可用和tcp配合使用,示例:
spec: host: hello.ns-istio.svc.cluter.local trafficPolicy: connectionPool: tcp: maxConnections: 80 connectTimeout: 25ms http: http2MaxRequests: 800 maxRequestsPerConnection: 10
配置最大80个连接,只允许最多800个并发请求,每个连接的请求数不超过10个,连接超时是25毫秒。
3.3.3 异常点检查
异常点检测是一个断路器的实现,它跟踪上游服务中每个主机(Pod)的状态。如果一个主机开始返回5xx HTTP错误,它就会在预定的时间内被从负载均衡池中弹出。对于TCP服务,Envoy将连接超时或失败计算为错误。
两种健康检测:
主动性
定期探测目标服务实例,根据应答来判断服务实例的健康状态。如负载均衡器中的健康检查。
被动性
通过实际的访问情况来找出不健康的实例,如istio中的异常检查点。
异常实例检查相关配置:
consecutiveErrors:
实例被驱逐前的连续错误次数,默认是5。
对于HTTP服务,返回502,503和504的请求会被认为异常;
对于TCP服务,连接超时或者连接错误事件会被认为异常;
interval
驱逐的时间间隔,默认值为10s, 要求大于1ms,单位可以是时、分、毫秒;
baseEjectionTime
最小驱逐时间。一个实例被驱逐的时间等于这个最小驱逐时间*驱逐次数。这样一个因多次异常被驱逐的实例,被驱逐的时间会越来越长。默认为30s,要求大于1ms,单位可以是时、分、毫秒。
maxEjectionPercent
负载均衡池中可以被驱逐的故障实例的最大比例,默认为10%,设置这个值是为了避免太多的服务实例被驱逐导致服务整体能力下降。
minHealthPercent
最小健康实例比例,是lstio 1.1新增的配置。当负载均衡池中的健康实例数的 例大于这个比例时,异常点检查机制可用;当可用实例数的比例小于这个比例时,异常点检查功能将被禁用,所有服务实例不管被认定为健康还是不健康,都可以接收请求。参数的默认值为50%。
trafficPolicy: connectionPool: http: http2MaxRequests: 500 maxRequestsPerConnection: 10 outlierDetection: consecutiveErrors: 10 interval: 5m baseEjectionTime: 10m
3.3.4 TLS设置
包含任何与上游服务连接的 TLS 相关设置。下面是一个使用提供的证书配置 mTLS 的例子:
... trafficPolicy: tls: mode: MUTUAL clientCertificate: /etc/certs/cert.pem privateKey: /etc/certs/key.pem caCertificates: /etc/certs/ca.pem
mtls: 双向认证,客户机和服务器都通过证书颁发机构彼此验证身份。
由同一个 root ca 生成两套证书,即客户端证书和服务端证书。客户端使用 https 访问服务端时,双方会交换证书,并进行认证,认证通过方可通信。
其他支持的 TLS 模式有 DISABLE(没有 TLS 连接),SIMPLE(在上游端点发起 TLS 连接),以及ISTIO MUTUAL(与MUTUAL类似,使用Istio的mTLS 证书)。
3.3.5 端口流量策略
在端口上配置流量策略,且端口上流量策略会覆盖全局的流量策略。
trafficPolicy: connectionPool: tcp: maxConnections: 80 portLevelSettings: - port: number: 80 loadBalancer: simple: LEAST_CONN connectionPool: tcp: maxConnections: 100 - port: number: 8000 loadBalancer: simple: ROUND_ROBIN
3.3.6 服务子集
subset,定义服务子集
name 服务子集的名字
labels subset上的标签,通过一组标签定义了属于这个subset的服务实例。比如最常用的标识服务版本version标签
trafficPolicy 应用到这个subset上的流量策略
示例:
...... spec: hosts: hello subsets: - name: v2 labels: version: v2 trafficPolicy: connectionPool: tcp: maxConnections: 80 # 给一个特定的subset配置最大连接数
四、Kiali组件
kiali组件位于:安装包/samples/addons,将这个目录下的所有插件都安装
执行安装
kubectl apply -f ./addons/
注意:如果在安装插件时出错,再运行一次命令。有一些和时间相关的问题,再次运行就能解决。
查看安装结果
kubectl get svc,pod -n istio-system
[root@node21 samples]# kubectl get svc,pod -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/grafana ClusterIP 10.99.8.238 <none> 3000/TCP 6m50s service/istio-egressgateway ClusterIP 10.102.75.82 <none> 80/TCP,443/TCP 16h service/istio-ingressgateway LoadBalancer 10.108.158.227 <pending> 15021:31495/TCP,80:30645/TCP,443:30754/TCP,31400:31434/TCP,15443:31846/TCP 16h service/istiod ClusterIP 10.105.204.23 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 16h service/jaeger-collector ClusterIP 10.96.79.13 <none> 14268/TCP,14250/TCP,9411/TCP 6m49s service/kiali NodePort 10.96.12.6 <none> 20001:30418/TCP,9090:30171/TCP 17m service/prometheus ClusterIP 10.99.107.205 <none> 9090/TCP 6m49s service/tracing ClusterIP 10.111.187.36 <none> 80/TCP,16685/TCP 6m49s service/zipkin ClusterIP 10.98.207.250 <none> 9411/TCP 6m49s NAME READY STATUS RESTARTS AGE pod/grafana-b854c6c8-ts8c5 1/1 Running 0 6m50s pod/istio-egressgateway-66d96985c-2xc4x 1/1 Running 2 (12h ago) 16h pod/istio-ingressgateway-c5fd879b5-f4wkh 1/1 Running 2 (12h ago) 16h pod/istiod-98988c6b6-8qvr8 1/1 Running 2 (12h ago) 16h pod/jaeger-54b7b57547-k5jxh 1/1 Running 0 6m49s pod/kiali-5ff88f8595-7m4qb 1/1 Running 0 17m pod/prometheus-7b8b9dd44c-smvnn 2/2 Running 0 6m49s
修改kiali的Service类型为NodePort,方便外部可以访问
kubectl edit service kiali -n istio-system
访问
http://node21:30418/
五、实战
5.1 Hello服务实战
1)开发一个SpringBoot服务
2)发布Docker镜像
3)部署服务到Kubernetes
hello.yaml
apiVersion: v1 kind: Service metadata: name: hello namespace: ns-istio spec: type: ClusterIP # Service的类型:ClusterIP, NodePort, LoadBalancer, ExternalName ports: # 端口信息 - port: 8080 # service端口 targetPort: 8080 # pod端口 selector: # 标签选择器,用于确定当前service代理哪些pod app: hello --- apiVersion: apps/v1 kind: Deployment metadata: name: hello namespace: ns-istio spec: replicas: 1 # 副本数量 selector: # 选择器,通过它指定该控制器管理哪些pod matchLabels: app: hello template: metadata: labels: app: hello spec: containers: - name: hello image: com.alisls/hello:1.0 ports: - containerPort: 8080 protocol: TCP nodeName: node26 # 为了调试方便,只发布到node26节点
4)部署Gateway和VirtualService
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: gateway-hello namespace: ns-istio spec: selector: istio: ingressgateway # use istio default controller servers: - port: protocol: HTTP name: http number: 80 hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: hello namespace: ns-istio spec: hosts: - "*" gateways: - gateway-hello http: - match: - uri: prefix: /hello route: - destination: host: hello # service name port: number: 8080 # service port