虚拟服务提供流量路由功能,它基于 Istio 和平台提供的基本的连通性和服务发现能力,让您配置如何在服务网格内将请求路由到服务
示例:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts: # 向服务发送请求时使用的地址,不必是 Istio 服务注册的一部分,它只是虚拟的目标地址
- reviews
http: # 包含路由规则,描述匹配条件和路由行为
- match: # 匹配来自jason用户的所有请求
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews # 实际目的地址,必须是存在于 Istio 服务注册中心的实际目标地址
subset: v2
- route: # 默认目标,其他路由不满足时,使用该目标
- destination:
host: reviews
subset: v3
目标规则提供流量路由功能,虚拟服务是将流量如何路由到给定目标地址,目标规则用来配置该目标的流量
可以使用目标规则来指定命名的服务子集,例如按版本为所有给定服务的实例分组。然后可以在虚拟服务的路由规则中使用这些服务子集来控制到服务不同实例的流量。
示例:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: my-destination-rule
spec:
host: my-svc
trafficPolicy:
loadBalancer:
simple: RANDOM # 随机
subsets:
- name: v1
labels: # pod上label
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN # 轮询,覆盖顶层的trafficPolicy
- name: v3
labels:
version: v3
使用网关为网格来管理入站和出站流量,能够指定要进入或离开网格的流量。网关配置被用于运行在网格边界的独立 Envoy 代理,而不是服务工作负载的 sidecar 代理。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: ext-host-gwy
spec:
selector:
app: my-gateway-controller
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- ext-host.example.com
tls:
mode: SIMPLE
serverCertificate: /tmp/tls.crt
privateKey: /tmp/tls.key
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: virtual-svc
spec:
hosts:
- ext-host.example.com
gateways:
- ext-host-gwy
Istio 服务网格从逻辑上分为数据平面和控制平面
由一组智能代理(Envoy)组成,被部署为 Sidecar。这些代理负责协调和控制微服务之间的所有网络通信,同时还收集和报告所有网格流量的遥测数据。
管理并配置代理来进行流量路由
架构图如下:
Envoy 是用 C++ 开发的高性能代理,用于协调服务网格中所有服务的入站和出站流量。
Envoy 代理被部署为服务的 Sidecar,在逻辑上为服务增加了 Envoy 的许多内置特性,例如:
Istio envoy sidecar proxy 配置中包含以下四个部分:
每个部分中都包含静态配置与动态配置,其中 bootstrap 配置又是在集群启动的时候通过 sidecar 启动参数注入的,配置文件在 /etc/istio/proxy/envoy-rev0.json
Envoy 提供了如下的 API:
CDS(Cluster Discovery Service):集群发现服务
EDS(Endpoint Discovery Service):端点发现服务
HDS(Health Discovery Service):健康发现服务
LDS(Listener Discovery Service):监听器发现服务
MS(Metric Service):将 metric 推送到远端服务器
RLS(Rate Limit Service):速率限制服务
RDS(Route Discovery Service):路由发现服务
SDS(Secret Discovery Service):秘钥发现服务
所有名称以 DS 结尾的服务统称为 xDS
Istiod 提供服务发现、配置和证书管理。
Istiod 将控制流量行为的高级路由规则转换为 Envoy 特定的配置,并在运行时将其传播给 Sidecar。
Pilot 提取了特定平台的服务发现机制,并将其综合为一种标准格式,任何符合 Envoy API 的 Sidecar 都可以使用。
Istiod 安全通过内置的身份和凭证管理,实现了强大的服务对服务和终端用户认证。您可以使用 Istio 来升级服务网格中未加密的流量。
Istiod 充当证书授权(CA),并生成证书以允许在数据平面中进行安全的 mTLS 通信。
Istiod做了进一步的细分,分成了 Pilot、Mixer 和 Citadel,它们的各自功能如下:
Pilot: 为 Envoy 提供了服务发现,流量管理和智能路由(AB 测试、金丝雀发布等),以及错误处理(超时、重试、熔断)功能。 用户通过 Pilot 的 API 管理网络相关的资源对象,Pilot 会根据用户的配置和服务的信息把网络流量管理变成 Envoy 能识别的格式分发到各个 Sidecar 代理中。
Mixer: 为整个集群执行访问控制(哪些用户可以访问哪些服务)和 Policy 管理(Rate Limit,Quota 等),并且收集代理观察到的服务之间的流量统计数据。
Citadel: 为服务之间提供认证和证书管理,可以让服务自动升级成 TLS 协议。
Istio 负载测试网格包含了 1000 个服务和 2000 个 sidecar,全网格范围内,QPS 为 70,000。 在使用 Istio 1.10.3 运行测试后,我们得到了如下结果:
控制平面支持数千个服务,分布在数千个 pod 上,所需的用户自有虚拟服务和其它配置对象的数量级与之类似。Pilot 的 CPU 和内存资源需求量与系统配置和可能状态的量级成正比。CPU 消耗的变化取决于以下因素:
一个单一的 Pilot 实例仅用 1 vCPU 和 1.5 GB 的内存就可以支持 1000 个服务和 2000 个 sidecar,可以增加 Pilot 实例的数量来降低它花在推送配置到所有代理的耗时。
数据平面的性能受很多因素影响,例如:
代理的内存消耗取决于它的总体配置状态。大量的监听器、集群和路由会增加内存使用量。Istio 1.1 引入了命名空间隔离来限制配置被下发到代理的范围。在一个比较大的命名空间中,代理将消耗大约 50 MB 的内存。
因为 Istio 在数据路径上注入了一个 sidecar 代理,所以延迟是重要的考量因素。Istio 向代理添加了身份验证和 Mixer 过滤器。每一个额外的过滤器都会增加代理内的路径长度并影响延迟。
在网格内部,一个请求会先遍历客户端代理,然后遍历服务端代理。在 90% 的情况下,数据路径上的这两个代理每 1000 QPS 会产生 6.3 ms 的延迟。90% 的情况下仅服务端代理会增加 1.7 ms 的延迟。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
- headers:
end-user:
exact: jason
fault:
delay:
percentage:
value: 100.0
fixedDelay: 7s
route:
- destination:
host: ratings
subset: v1
- route:
- destination:
host: ratings
subset: v1
将流量从微服务的一个版本的逐渐迁移到另一个版本,在 Istio 中,通过配置一系列规则来实现此目标,这些规则将一定比例的流量路由到一个或另一个服务。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 50
- destination:
host: reviews
subset: v3
weight: 50
我们使用 Istio 的权重路由功能将 reviews 服务的流量迁移到新版本,这和使用容器编排平台的部署功能来进行版本迁移完全不同,后者使用了实例扩容来对流量进行管理。
使用 Istio,两个版本的 reviews 服务可以独立地进行扩容和缩容,而不会影响这两个服务版本之间的流量分发。
DestinationRule配置
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1 # 并发连接数最大为1
http:
http1MaxPendingRequests: 1 # 最大并发请求数
maxRequestsPerConnection: 1 #每个连接最大请求数
outlierDetection:
consecutive5xxErrors: 1
interval: 1s
baseEjectionTime: 3m
maxEjectionPercent: 100
当流量被镜像时,请求将发送到镜像服务中,并在 headers 中的 Host/Authority 属性值上追加 -shadow。例如 cluster-1 变为 cluster-1-shadow,可以使用 mirror_percent 属性来设置镜像流量的百分比。
被镜像的流量是即发即弃的,就是说镜像请求的响应会被丢弃
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin
http:
- route:
- destination:
host: httpbin
subset: v1
weight: 100
mirror: # 将流量100% 镜像到v2服务
host: httpbin
subset: v2
mirrorPercent: 100
除了支持Kubernetes Ingress,Istio还提供了另一种配置模式,Istio Gateway。与 Ingress 相比,Istio Gateway 提供了更广泛的自定义和灵活性,并允许将 Istio 功能(例如监控和路由规则)应用于进入集群的流量。
# Gateway
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "httpbin.example.com"
# VirtualService
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "httpbin.example.com"
gateways:
- httpbin-gateway
http:
- match:
- uri:
prefix: /status
- uri:
prefix: /delay
route:
- destination:
port:
number: 8000
host: httpbin
# 请求
curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/status/200"
使用Ingress Resource入口资源将Istio配置为在服务网格集群之外公开服务。
Ingress资源如下所示,使用 kubernetes.io/ingress.class 注解来告知 Istio 网关控制器它应该处理此 Ingress,在 Kubernetes 1.18 中,添加了新资源 IngressClass ,以替换 Ingress 资源上的 kubernetes.io/ingress.class 注解。
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: istio
name: ingress
spec:
rules:
- host: httpbin.example.com
http:
paths:
- path: /status/*
backend:
serviceName: httpbin
servicePort: 8000
由于默认情况下,来自 Istio-enable Pod 的所有出站流量都会重定向到其 Sidecar 代理,集群外部 URL 的可访问性取决于代理的配置。默认情况下,Istio 将 Envoy 代理配置为允许传递未知服务的请求。
三种访问外部服务的方法:
允许 Envoy 代理将请求传递到未在网格内配置过的服务。
配置 service entries 以提供对外部服务的受控访问。
对于特定范围的 IP,完全绕过 Envoy 代理。
通过 global.outboundTrafficPolicy.mode,配置 sidecar 对外部服务(那些没有在 Istio 的内部服务注册中定义的服务)的处理方式
从 Istio 网格调用外部服务的三种方法:
kubectl create namespace istio-system
# 部署token、sa
helm install istio-base manifests/charts/base -n istio-system
# 部署 istiod
helm upgrade --install istiod istio-control/istio-discovery \
--set global.hub="docker.io/istio" \
--set global.tag="1.10.5" \
--set global.jwtPolicy=first-party-jwt \
--set meshConfig.accessLogFile=/dev/stdout \
-n istio-system