使用 Istio 实现应用迁移

背景:当前环境中有 Cluster A 和 Cluster B,各自部署了相同的应用,且该应用有两个域名用于处理不同的请求。目前,这两个域名的请求都由 Cluster A 中的应用处理。为进行应用迁移,现希望将域名 A 的请求继续由 Cluster A 处理,而域名 B 的请求则切换至由 Cluster B 中的应用来处理。

由于目前的流量处理都是由 Istio 负责,所以可以通过 ServiceEntry 来实现此需求。

创建一个 ServiceEntry:

将 b.nginx.com 的流量转发到 Cluster B 的 Istio Ingress Gateway,然后再通过 Cluster B 的 VirtualService 将流量转发到 Cluster B 中的应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-nginx
namespace: default
spec:
addresses: {}
endpoints:
# 此处为 Cluster B 的 Istio Ingress Gateway 的地址和端口
- address: 172.16.0.104
ports:
http: 80
hosts:
- b.nginx.com
location: MESH_EXTERNAL
ports:
- name: http
number: 80
protocol: HTTP
resolution: DNS

修改原有的 VirtualService 中处理域名 B 流量的部份:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: nginx-virtualservice
namespace: default
spec:
gateways:
- http-gateway.istio-system.svc.cluster.local
hosts:
- a.nginx.com
- b.nginx.com
http:
- match:
- headers:
host:
exact: a.nginx.com
route:
- destination:
host: nginx.default.svc.cluster.local
port:
number: 80
- match:
- headers:
host:
exact: b.nginx.com
route:
- destination:
# 此处原本为 nginx.default.svc.cluster.local,如果要做迁移将其修改为 b.nginx.com 即可
host: b.nginx.com
port:
number: 80

尝试请求查看效果:

Istio 使用随记

Istio 是一种开源服务网格,使用代理拦截所有网络流量,可根据配置提供广泛的应用程序感知功能。

常见的 CRD:

  1. VirtualService:定义服务间或服务至外部流量的路由规则,支持请求匹配、路由选择、流量分割、重试、超时等策略。
  2. DestinationRule:定义目标服务的流量策略,比如负载均衡、连接池、TLS 配置等。每个目标服务的流量策略通过 DestinationRule 配置后,对所有请求生效。
  3. Gateway:配置边缘网关的入口流量规则,例如定义外部流量如何进入服务网格。它可以用于 HTTP、HTTPS、TLS 和 TCP 流量。
  4. ServiceEntry:将外部服务引入到 Istio 网格中,允许 Istio 管理和监控这些服务的流量。例如,可以使用 ServiceEntry 来引入外部 API,使网格中的服务可以透明地与外部服务交互。

创建一个 Nginx,用于测试:

1
2
kubectl create deployment nginx --image=nginx:mainline
kubectl expose deployment nginx --port=80

创建 Gateway:

selector 匹配 istio-ingressgateway 部署的 Pod,通过该网关来接收外部流量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: http-gateway
namespace: istio-system
spec:
selector:
# select the istio ingressgateway
istio: ingressgateway
servers:
- hosts:
- test.nginx.com
port:
name: http
number: 80
protocol: HTTP

创建 VirtualService:

hosts 字段指定了可以通过 test.nginx.com 主机名访问该服务的外部请求,流量通过定义的 Gateway 进入。VirtualService 的 route 字段将流量路由到 nginx.default.svc.cluster.local。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: nginx-virtualservice
namespace: default
spec:
gateways:
# select the gateway created above
- http-gateway.istio-system.svc.cluster.local
hosts:
- test.nginx.com
http:
- route:
- destination:
host: nginx.default.svc.cluster.local
port:
number: 80

创建 DestinationRule:

trafficPolicy 中定义了负载均衡策略为 LEAST_CONN,即最小连接数策略。DestinationRule 的 host 必须匹配 VirtualService 中的 destination。

1
2
3
4
5
6
7
8
9
10
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: nginx-destination-rule
namespace: default
spec:
host: nginx.default.svc.cluster.local
trafficPolicy:
loadBalancer:
simple: LEAST_CONN

通过 Istio Ingress Gateway 访问 Nginx:

1
curl -H "Host: test.nginx.com" http://<istio-ingressgateway-cluster-ip>/