一、Istio 流量管理
Istio
是一个开源的服务网格,它为分布式微服务架构提供了网络层的抽象。它使得服务之间的通信变得更为可靠、安全,并且提供了细粒度的流量管理、监控和策略实施功能。Istio
通过在服务之间插入一个透明的代理(Envoy
)来拦截所有网络通信,从而实现这些功能。这样,开发者就可以专注于业务逻辑,而不必处理服务发现、负载均衡、故障恢复、安全性等网络问题。
Istio
和k8s
之间的关系非常紧密。它可以利用k8s
的强大功能来管理和部署服务网格。当Istio
部署在k8s
集群中时,它会自动检测到集群中的服务,并为它们提供网络层的抽象。这样,开发者就可以使用Istio
来管理服务之间的通信,同时利用k8s
来管理服务的部署和扩展。这种结合使得开发者可以更容易地构建、部署和管理复杂的微服务架构。
Istio
的流量路由规则可以让您很容易的控制服务之间的流量和 API
调用。 Istio
简化了服务级别属性的配置,比如熔断器、超时和重试,并且能轻松的设置重要的任务, 如 A/B
测试、金丝雀发布、基于流量百分比切分的分阶段发布等。它还提供了开箱即用的故障恢复特性, 有助于增强应用的健壮性,从而更好地应对被依赖的服务或网络发生故障的情况。
Istio
的流量管理是其最核心的功能之一,它能够让网络层的操作变得更加简单和灵活。以下是Istio
流量管理的核心组件和概念的详细介绍:
-
Envoy 代理:
Envoy
是一个高性能C++
分布式代理,专为单个服务和应用程序设计,以及为大型微服务"服务网格"体系结构。它作为边车(sidecar
)与服务容器一起部署,拦截所有出入流量,从而无需对服务代码进行任何更改。Envoy
支持HTTP/2
、gRPC
等协议,并提供了断路器、异常值检测、速率限制等功能,以确保网络稳定性和可靠性。 -
Pilot :
Pilot
为Istio
提供了服务发现功能,它将服务目录中的服务配置转换为Envoy
代理的配置,并确保这些配置在运行时动态地分发到所有的Envoy
代理。Pilot
抽象了各种服务发现系统,如Kubernetes
、Consul
等,允许Istio
在不同的环境中运行。 -
Mixer :
Mixer
负责在服务网格中实施访问控制和使用策略。它允许服务在执行操作之前验证请求的属性,并收集遥测数据(如日志、指标和配额)。Mixer
通过适配器与后端的各种基础设施后端进行通信,如Prometheus
、StatsD
、MySQL
等。 -
Citadel :
Citadel
负责Istio
的安全功能,包括证书管理、密钥管理以及服务之间的安全通信。它为服务网格中的工作负载提供了自动化的密钥和证书轮换,确保端到端通信的安全。 -
Virtual Service :
Virtual Service
是一个Istio
配置资源,它允许用户定义路由规则,以控制服务之间的流量路由。通过Virtual Service
,用户可以设置条件匹配(如基于路径或HTTP
头),并将流量重定向到不同的版本或服务。 -
Destination Rule :
Destination Rule
与Virtual Service
配合使用,用于定义服务版本之间的流量策略,例如负载均衡策略、连接池大小、熔断器设置等。 -
Gateway :
Gateway
是一个Istio
配置资源,用于管理进出服务网格的入口和出口流量。它允许用户为服务网格配置负载均衡器,以处理来自外部网络的流量。 -
Service Entry :
Service Entry
用于将外部服务添加到Istio
的服务目录中,使网格内的服务能够访问外部服务,同时仍然可以利用Istio的流量管理功能。
通过这些核心组件和概念,Istio
提供了一种统一的方式来管理、保护和监控微服务之间的流量,从而使开发人员可以专注于业务逻辑,而不是网络问题。
官方介绍文档如下:
https://istio.io/latest/zh/docs/concepts/traffic-management/
1.1 Istio 环境安装
下载 istioctl
客户端工具:
shell
curl -L https://istio.io/downloadIstio | sh -
将 istioctl
客户端工具添加到环境变量:
shell
cd istio-1.21.2/
export PATH=$PWD/bin:$PATH
测试环境,查看 istioctl
的版本:
shell
istioctl version
使用 istioctl
安装 istio
环境,前提当前机器中已经有了 k8s
环境。
shell
istioctl install --set profile=demo -y
其中 profile
可选项如下:
default
:根据IstioOperator API
的默认设置启动组件。 建议用于生产部署和Multicluster Mesh
中的Primary Cluster
。您可以运行istioctl profile dump
命令来查看默认设置。demo
:这一配置具有适度的资源需求,旨在展示Istio
的功能。 它适合运行Bookinfo
应用程序和相关任务。 此配置文件启用了高级别的追踪和访问日志,因此不适合进行性能测试。minimal
:与默认配置文件相同,但只安装了控制平面组件。 它允许您使用Separate
Profile
配置控制平面和数据平面组件(例如Gateway
)。remote
:配置Multicluster Mesh
的Remote Cluster
。empty
:不部署任何东西。可以作为自定义配置的基本配置文件。preview
:预览文件包含的功能都是实验性。这是为了探索Istio
的新功能。不确保稳定性、安全性和性能(使用风险需自负)。
安装成功后,查看 Istio
的 pod
:
sell
kubectl get pods -n istio-system
状态都为 Running
为正常,可以看到,安装了入口和出口网关。这两个网关实际都运行了一个 Envoy
代理实例,它们在网格的边缘作为负载均衡器运行。入口网关接收入站的连接,而出口网关接收从集群出去的连接。
创建一个命名空间,后面所有操作均在该命名空间下操作:
shell
kubectl create ns test
给该命名空间添加标签,指示在部署应用的时候,自动注入 Envoy
边车代理:
shell
kubectl label namespace test istio-injection=enabled
1.2 Istio 环境测试
在 Istio
服务网格中可以通过 VirtualService
定义流量路由规则,通过 GateWay
接入流量,下面使用一个案例测试环境是否正常。
启动一个 Nginx
作为服务的目标,并构建了/、/buy、/order 、err
接口分别用于后面不同场景的测试:
shell
vi nginx-v1.yml
yml
apiVersion: v1
kind: Service
metadata:
name: nginx-v1
namespace: test
labels:
app: nginx-v1
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
app: nginx-v1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-v1-config
namespace: test
data:
nginx.conf: |-
events {
use epoll;
worker_connections 65535;
}
http {
include mime.types;
server_tokens off;
client_max_body_size 50m;
server {
listen 80;
server_name localhost;
proxy_buffering off;
autoindex on;
add_header Access-Control-Allow-Origin '*';
proxy_connect_timeout 1800s;
proxy_send_timeout 1800s;
proxy_read_timeout 1800s;
location / {
return 200 "This is V1 Nginx.";
}
location /buy {
return 200 "This is V1 Nginx, Current Uri /buy .";
}
location /order {
return 200 "This is V1 Nginx, Current Uri /order .";
}
location /err {
return 500 "This is V1 Nginx, Current Uri /err .";
}
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-v1
namespace: test
spec:
selector:
matchLabels:
app: nginx-v1
replicas: 1
template:
metadata:
labels:
app: nginx-v1
name: nginx
version: v1
spec:
containers:
- name: nginx-v1
image: nginx:1.20.1
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: nginx-config
configMap:
name: nginx-v1-config
shell
kubectl apply -f nginx-v1.yml
查看 Pod
:
这里有两个容器是因为一个是 sidecar
一个是 nginx
目标服务。
下面创建 Gateway
和 VirtualService
测试流量转发:
shell
vi nginx-gwvs.yml
yml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: nginx-gw
namespace: test
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "*"
gateways: #绑定 gateway
- nginx-gw
http:
- route: #路由
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
shell
kubectl apply -f nginx-gwvs.yml
查看入口 gateway nodeport
的端口:
shell
kubectl get svc -n istio-system
访问: http://{node ip}:30868/
通过下面指令可以查看 ingressgateway
的日志情况:
shell
kubectl logs -f -n istio-system -l istio=ingressgateway
下面开始更详细的使用介绍。
二、VirtualService 流量管理
Istio
中的 VirtualService
是一个核心的配置资源,它允许用户通过定义一组流量路由规则来控制服务网格中的数据流。这些规则可以根据请求的属性(如路径、标头、查询参数等)将流量路由到不同的服务版本或目的地,同时支持重定向、重写、故障注入、超时、重试策略、流量镜像等功能。通过这些特性,`可以使得在复杂的微服务环境中实现细粒度的流量管理变得简单而灵活。
下面是 VirtualService
中的重要的配置项说明:
配置项 | 说明 |
---|---|
spec.hosts | 定义路由规则关联一组的 hosts ,可以是带有通配符的 DNS 名称或者 IP 地址。 |
spec.gateways | 定义应用路由规则的来源流量,可以是一个或多个网关,或网格内部的 sidecar,指定方式为 <gateway namespace>/<gateway name> |
spec.http.match | 定义路由的匹配规则列表,单个匹配规则项内所有条件是且关系,列表中多个匹配规则之间为或关系 |
spec.http.route | 定义路由转发目的地列表,一条 HTTP 路由可以是重定向或转发(默认),转发的目的地可以是一个或多个服务(服务版本)。同时也可以配置权重、header 操作等行为 |
spec.http.redirect | 定义路由重定向,一条 HTTP 路由可以是重定向或转发(默认) |
spec.http.rewrite | 定义重写,不能与重定向同时配置,重写操作会在转发前执行 |
spec.http.timeout | 定义 HTTP 请求的超时时间 |
spec.http.retries | 定义 HTTP 请求的重试策略 |
spec.http.fault | 定义 HTTP 流量的故障注入策略,开启时超时和重试策略不会开启 |
spec.http.mirror | 定义将 HTTP 流量复制到另一个指定的目的端 |
spec.http.mirrorPercent | 定义流量镜像的复制百分比,缺省时复制100% 的流量。最大值为100 |
spec.http.corsPolicy | 定义 CORS 策略 |
spec.http.headers | 定义 header 操作规则,可以更新 request 和 response 的 header ,进行增加,移除操作 |
2.1 限制请求域名
yml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: nginx-gw
namespace: test
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "www.xbc.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways: #绑定 gateway
- nginx-gw
http:
- route: #路由
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
更新配置:
shell
kubectl apply -f nginx-gwvs.yml
再次使用 http://{node ip}:30868/
访问:
此时返回 404
了,在 hosts
中添加域名映射:
shell
11.0.1.144 www.xbc.com
使用域名后,可以访问成功:
2.2 match 规则匹配
支持对 uri
、scheme
、method
、authority
类型的操作,每种类型都支持 exact
、prefix
和regex
三种模式的匹配 。
例如:
2.2.1 根据 uri 前缀路由
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /buy
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
当 uri
以 buy
为前缀时,可以正常访问:
如果访问 order
接口,此时访问不通:
2.2.2 根据 header 参数路由
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- headers:
userid:
exact: test
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
只有 header
中带有 userid=test
的请求才可以访问,如果不加 header
参数访问,会返回 404
:
带上 header
参数访问,可以正常访问:
2.2.3 同时混合使用多种规则
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- headers:
userid:
exact: test
uri:
prefix: /buy
- headers:
userid:
exact: admin
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
上面意思表示,header
中 userid
的值为 test
并且 uri
的前缀是 buy
可以访问,或者是 header
中 userid
的值为 admin
也可以访问。
当uri
以buy
为前缀,但headr
中userid
的值是其他时,访问为 404
:
当uri
以buy
为前缀,但headr
中userid
的值是test
时,正常访问 :
当 uri
以 order
为前缀, header
中的值是 test
时,访问为 404
:
当 uri
以 order
为前缀, header
中的值是 admin
时,正常访问 :
2.3 route 流量转移
上面已经简单使用 route
指定目标服务了,在 route
还有更多功能,例如实现负载均衡、灰度发布、流量转移等等,主要有三个配置:destination
(请求目标)、weight
(权重)、和 headers
,其中 destination
是必须的。
这里为了方便测试目标路由,再部署一个 nginx v2
版本:
shell
vi nginx-v2.yml
yml
apiVersion: v1
kind: Service
metadata:
name: nginx-v2
namespace: test
labels:
app: nginx-v2
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
app: nginx-v2
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-v2-config
namespace: test
data:
nginx.conf: |-
events {
use epoll;
worker_connections 65535;
}
http {
include mime.types;
server_tokens off;
client_max_body_size 50m;
server {
listen 80;
server_name localhost;
proxy_buffering off;
autoindex on;
add_header Access-Control-Allow-Origin '*';
proxy_connect_timeout 1800s;
proxy_send_timeout 1800s;
proxy_read_timeout 1800s;
location / {
return 200 "This is V2 Nginx.";
}
location /buy {
return 200 "This is V2 Nginx, Current Uri /buy .";
}
location /order {
return 200 "This is V2 Nginx, Current Uri /order .";
}
location /err {
return 500 "This is V2 Nginx, Current Uri /err .";
}
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-v2
namespace: test
spec:
selector:
matchLabels:
app: nginx-v2
replicas: 1
template:
metadata:
labels:
app: nginx-v2
name: nginx
version: v2
spec:
containers:
- name: nginx-v2
image: nginx:1.20.1
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: nginx-config
configMap:
name: nginx-v2-config
shell
kubectl apply -f nginx-v2.yml
2.3.1 基于权重的流量转移
通过配置 weight
参数,将流量按比例分配到不同的目标服务中。
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
weight: 50
- destination:
host: nginx-v2.test.svc.cluster.local
port:
number: 80
weight: 50
上面两个版本服务各分配 50%
的流量,访问应该可以感觉出负载均衡轮训的效果:
2.3.2 添加/修改 header
可以添加或修改 request
或 response
中的 header
信息:
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
headers:
response:
add:
test: xbc
set:
content-type: application/json
发起请求后,可以在返回的 header
中看到添加和修改的参数:
2.4 redirect 重定向
可以从一个uri
重定向到另一个 uri
,返回服务调用方 302
状态码,以及 header
中 location
重定向后的地址。
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /buy-v2
redirect:
uri: /buy
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
上面配置了访问 /buy-v2
的话,自动重定向到 /buy
接口 :
2.5 rewrite 重写
和重定向配置类似,但重写对用户不可见,在服务端进行。
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /buy-v2
rewrite:
uri: /buy
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
上面配置了访问 /buy-v2
的话,自动重写到 /buy
接口 ,对服务调用者无感知:
2.5 retries 请求重试
当请求失败时,可以通过重试策略,重新发起尝试,以提高服务的质量。
主要包括三个参数:attempts、perTryTimeout、retryOn
:
- 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 :服务返回
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
retries:
attempts: 3
perTryTimeout: 3s
retryOn: 5xx,connect-failure
上面定义了当目标服务返回 5xx
或 连接失败时进行重试,一共重试3
次,每次重试的超时时间 3s
。
这里可以提前查看下 nginx-v1
的日志:
shell
kubectl logs -f nginx-v1-dbf758949-bhbdr -n test
下面访问 /err
接口一次,会返回 500
错误码:
通过 nginx-v1
的日志可以看到,被访问了4
次,其中包括重试的 3
次 。
2.6 mirror 流量镜像
流量镜像可以将流量转发到目标服务的同时,也将流量给到另外一个服务,非常利于新版本环境的上线前测试,其配置的参数和 destination
相同:
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
mirror:
host: nginx-v2.test.svc.cluster.local
port:
number: 80
上面将请求同时转发到 nginx v1
的同时也向 nginx-v2
服务发送一份请求:
这里可以提前查看下 nginx-v2
的日志:
shell
kubectl logs -f nginx-v1-dbf758949-bhbdr -n test
从 nginx-v2
的日志中可以看出也被请求了:
2.7 故障注入
故障注入是一种服务网格中的测试手段,它允许在系统中引入特定的故障,以模拟网络延迟或服务中断的情况。这样做的目的是测试和提高微服务架构的弹性和稳定性,确保系统能够在遇到真实世界的各种问题时仍能正确处理请求。
注意:故障注入应该谨慎使用,尽量在测试环境中进行,以避免对生产环境造成不必要的影响。
故障注入主要包括 delay
和 abort
两种类型:
- delay:用于模拟网络延迟或服务响应延迟。通过引入延迟,可以测试服务或系统的超时处理、重试机制和整体性能。
- abort :用于模拟服务中断,通过返回特定的
HTTP
状态码来模拟服务失败。这可以用来测试服务的错误处理能力、断路器和其他故障恢复机制。
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
fault:
delay:
percentage:
value: 10
fixedDelay: 5s
abort:
percentage:
value: 10
httpStatus: 500
上面配置了 10%
的请求产生 5
秒的延时,10%
的请求直接中止返回 500
状态码:
2.8 跨域配置
VirtualService
提供了 allowOrigin、allowMethods、allowHeader、exposeHeader、maxAge、allowCredentials
参数来允许我们灵活的配置跨域。
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /
route:
- destination:
host: nginx-v1.test.svc.cluster.local
port:
number: 80
corsPolicy:
allowOrigin:
- www.xbc.com
allowMethods:
- "GET"
- "POST"
- "PUT"
- "DELETE"
maxAge: "24h"
三、 DestinationRule 流量管理策略
DestinationRule
是 Istio
服务网格中的一种配置资源,它用于定义到达特定服务时的路由规则,以及与该服务通信时的流量策略。DestinationRule
通常与 VirtualService
一起使用,当 VirtualService
和 DestinationRule
都指定了相同的主机名和子集时生效。
下面是 DestinationRule
中的重要的配置项说明:
配置项 | 说明 |
---|---|
spec.host | 关联 destination.host 服务名称 |
spec.subsets | 服务子集 |
spec.trafficPolicy | 流量策略,包括负载均衡、连接池、健康检查、TLS 策略 |
spec.trafficPolicy.loadBalancer | 负载均衡算法,支持轮训、最小连接、随机等 |
spec.trafficPolicy.connectionPool | 连接池配置 |
spec.trafficPolicy.outlierDetection | 熔断配置 |
下面我们将 Gateway
和 VirtualService
的配置保持指定为下面内容,后面主要配置DestinationRule
的信息:
yml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: nginx-gw
namespace: test
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "www.xbc.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /
route:
- destination:
host: nginx.test.svc.cluster.local
port:
number: 80
3.1 流量转移 - 负载均衡
在 k8s
中 Service
本身也提供了一种负载均衡机制,而 DestinationRule
提供了更高级的负载均衡功能和流量控制方法,允许对一个服务的多个版本进行流量的划分,比如负载均衡中的轮询算法、最少连接算法、随机等等,还可以针对不同版本转移不同权重的流量。
这里再创建一个 Service
,指向 nginx-v1
和 nginx-v2
两个版本的 Pod
:
shell
vi nginx-svc.yml
yml
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: test
labels:
app: nginx
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
name: nginx
shell
kubectl apply -f nginx-svc.yml
配置负载均衡主要有两种选择 simple
(简单负载均衡) 和 consistentHash
(一致性Hash
算法):
simple
包括:
- ROUND_ROBIN: 轮询,默认的策略。
- LEAST_CONN:最少连接,选择一个活动请求数相对少的目标服务。
- RANDOM: 随机选择一个。
- PASSTHROUGH:直接转发到目标服务,不做任何策略。
consistentHash
包括:
- httpHeaderName: 基于 Header 计算 Hash。
- httpCookie: 基于Cookie 计算 Hash。
- useSourceIp:基于IP地址计算 Hash。
- minimumRingSize: 哈希环上虚拟节点数的最小值,节点数越多则分布越均衡。
新建一个 DestinationRule
配置:
shell
vi nginx-dr.yml
yml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: nginx-dr
namespace: test
spec:
host: nginx.test.svc.cluster.local
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN #负载均衡算法
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
shell
kubectl apply -f nginx-dr.yml
通过测试可以感觉出负载均衡的效果:
3.2 流量转移 - 同一服务不同版本流量转移
上面在 VirtualService
中介绍了基于权重的流量分发,但是针对不同的 host
的,结合DestinationRule
可以针对一个 host
中多个版本更细力度的控制分发,比如控制 80%
的流量到 v1
, 20%
的流量到 v2
。
yml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: nginx-dr
namespace: test
spec:
host: nginx.test.svc.cluster.local
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: test
spec:
hosts:
- "www.xbc.com"
gateways:
- nginx-gw
http:
- match:
- uri:
prefix: /
route:
- destination:
host: nginx.test.svc.cluster.local
port:
number: 80
subset: v1
weight: 80
- destination:
host: nginx.test.svc.cluster.local
port:
number: 80
subset: v2
weight: 20
可以在控制台循环10
次请求:
shell
for /l %i in (1,1,10) do curl http://www.xbc.com:30868/
通过结果可以看出,v1
服务获得了 80%
的流量。
3.3 连接池
连接池可以用于控制发送到目标服务的连接数量,包括 TCP
连接和 HTTP
连接两种。
TCP
连接参数:
-
maxConnections : 最大连接数,默认是
1024
,也适用HTTP/1.1
,HTTP/2
会对每个主机都使用单个连接。 -
connectTimeout: 连接超时时间。
-
tcpKeepalive :
Istio1.1
后新支持的配置,定期给对目标服务发送一个keepalive
探测包,判断连接是否可用。
HTTP
连接参数:
- http1MaxPendingRequests : 最大等待请求数,默认值是
1024
,只适用于HTTP/1.1
的服务。 - http2MaxRequests : 最大请求数,默认是
1024
。只适用于HTTP/2
服务。 - maxRequestsPerConnection : 每个连接的最大请求数。
HTTP/1.1
和HTTP/2
都遵循此参数。如果没有设置,表示没有限制。设置为1
表示每个连接只处理一个请求,也就是禁用了Keep-alive
。 - maxRetries :最大重试次数,默认是
3
。 - idleTimeout: 空闲超时,在这个时间内没有活动,该请求将关闭连接。
trafficPolicy
控制可以具体到某个子集:
yml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: nginx-dr
namespace: test
spec:
host: nginx.test.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1024
connectTimeout: 30s
tcpKeepalive:
probes: 5
time: "3600"
interval: 60s
http:
http1MaxPendingRequests: 2048
http2MaxRequests: 2048
maxRequestsPerConnection: 10
maxRetries: 3
idleTimeout: 60s
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
connectionPool:
http:
http1MaxPendingRequests: 1024
http2MaxRequests: 1024
maxRequestsPerConnection: 10
maxRetries: 3
idleTimeout: 60s
- name: v2
labels:
version: v2
trafficPolicy:
connectionPool:
http:
http1MaxPendingRequests: 1024
http2MaxRequests: 1024
maxRequestsPerConnection: 10
maxRetries: 3
idleTimeout: 60s
3.2 熔断
熔断是服务网格Istio
中的一种保护机制,用于防止系统雪崩和确保服务稳定性。Istio
熔断机制通过对服务进行实时监控,当检测到某个服务出现连续失败、延迟过高或异常响应时,会自动触发熔断,阻止进一步的请求发送到该服务。这样,可以避免无效的请求占用系统资源,同时给故障服务留出恢复的时间和空间。
Istio
的熔断功能主要通过 DestinationRule
中的 outlierDetection
配置项来实现,主要包括如下配置:
- consecutiveErrors :表示在
interval
时间内,如果一个服务实例连续返回错误的次数达到或超过这个值,该实例将被认为是异常的,并触发熔断。默认值为5
。 - interval :用于定义
consecutiveErrors
的统计时间窗口。在这个时间窗口内,如果服务实例的失败次数达到consecutiveErrors
的阈值,实例将被标记为异常。默认值为10
秒。 - baseEjectionTime :表示一个异常实例被驱逐的最短时间。实例被驱逐后,即使它变得可用,也必须等待至少这个时间才能重新加入负载均衡池。默认值为
30
秒。 - maxEjectionPercent :用于限制在同一时间内可以被驱逐的最大实例比例。这个配置可以防止所有实例同时被驱逐,从而保证服务有一定的可用性。默认值为
10%
。
yml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: nginx-dr
namespace: test
spec:
host: nginx.test.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 100
http2MaxRequests: 100
outlierDetection:
consecutiveErrors: 5
interval: 1m
baseEjectionTime: 1m
maxEjectionPercent: 100
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
上面配置了当在 1
分钟内,如何发生异常出现 5
次,将进行熔断,熔断时长 1
分钟,并且允许驱逐到全部的服务。
下面使用控制台,并发访问 20
次 /err
接口:
shell
for /l %i in (1,1,20) do start curl http://www.xbc.com:30868/err
执行之后,通过 PostMan 访问 /err 接口测试:
如果此时访问其他接口,/buy
也是访问不通的,因为整个目标服务都被驱逐了:
等待 1
分钟后,再次访问,接口返回正常: