背景

近期我接入了一个K8s系统, 系统对Ingress的支持不完善, 缩减了许多功能, 不过它支持完整功能的Istio, 因此我调研使用了下Istio, 试用其功能, 看看能不能满足我们的需求. 我在接入系统时, 并没有特别深入Istio的底层, 仅仅是为了实现特定功能, 可能按照自己的想法来理解和使用, 有不对的地方也欢迎指出.

Istio的简单介绍

Istio是一个开放的, 与平台无关的服务网格, 提供了流量管理, 策略下发, 和远程收集能力.

直接从图中来看, Istio的功能就是集群中的流量管理功能, 附带了可视化界面. 因此如果Istio提供了对外出口, 也就可以像Ingress那样, 流量从一个入口进入, 再转发至不同pod中.

Istio安装后的简单使用

我测试使用的是minikube(1.2.0), 也用它来安装Istio的(1.6.8)

Istio装好后

1
2
3
4
5
6
7
8
9
kubectl -n istio-system get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
grafana 1/1 1 1 13d
istio-ingressgateway 1/1 1 1 14d
istiod 1/1 1 1 14d
jaeger 1/1 1 1 13d
kiali 1/1 1 1 10d
kiali-operator 1/1 1 1 13d
prometheus 1/1 1 1 14d

Istio自带的Ingress, 在istio安装好之后, kubectl -n istio-system get deploy istio-ingressgateway有一个自带的ingress, 该ingress用于处理istio的入流量, 它可以当一个普通的Ingress服务, 也可以作为istio的gateway使用.

使用Ingress方式创建对外服务

这个方案是官方实例中给出的(samples/bookinfo/platform/kube/bookinfo-ingress.yaml), 不过所有文件中, 只有这一个是kind: Ingress的例子.

使用Ingress资源暴露接口

与之前我们用Nginx或是OpenResty创建的ingress服务是不太一样的, 因为他的gateway服务使用了Envoy(使用C++编写的服务代理工具, 类似Nginx), 但是到了istio中, ingress的配置做一些改变:

20210624114132

配置中中增加了/*来匹配路径, 而不能像Nginx中通过前缀来分流 我没有做进一步的测试, 不过既然从Nginx换成了Envoy, 一些配置理论上是不通用的.

使用gateway+vs, ds的方式创建对外服务

这个方案官方实例中给出较多, 还包括怎么分流以及服务间互相调用. 对外服务创建时, 我们也需要指定域名, 路径规则以及后端服务, 因此, 最精简的配置如下:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 指定要接收流量的gateway
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: arya-gateway
namespace: xxx-group-2
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "arya-python3.istio.xxx.com"

# virtual-service用于说明gateway的流量如何处理
# 可以看到, 这里是允许使用前缀路径来做转发的, 这种方案可以不需要DestinationRule
# 完全用kubernetes的service来做
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: arya-virtual-service
namespace: xxx-group-2
spec:
hosts:
- "arya-python3.istio.xxx.com"
gateways:
- arya-gateway
http:
- match:
- uri:
prefix: /static
route:
- destination:
host: prod-arya-python3-static
- match:
- uri:
prefix: /
route:
- destination:
host: prod-arya-python3

按比例分配流量

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
# 依赖的是service中区分prod-arya-python3以及stage-arya-python3
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: arya-virtual-service
namespace: xxx-group-2
spec:
hosts:
- "arya-python3.istio.xxx.com"
gateways:
- arya-gateway
http:
- match:
- uri:
prefix: /static
route:
- destination:
host: prod-arya-python3-static
- match:
- uri:
prefix: /
route:
- destination:
host: prod-arya-python3
weight: 50
- destination:
host: stage-arya-python3
weight: 50

使用VirtualService与DestinationRule配合使用

使用DestinationRule相比于使用原生的Service拓展了一些功能, 而且能够根据服务的实例进行分组, 我们目前基于版本的发布方式也比较容易的配合DestinationRule.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# service中仅选择应用名称, 不再区分版本号
---
apiVersion: v1
kind: Service
metadata:
name: prod-arya-python3
namespace: xxx-group-2
spec:
selector:
app_name: "arya-python3"
# app: "arya-python3-v2361" # 不再需要选择版本号
ports:
- protocol: TCP
port: 80
targetPort: 6000
name: http

---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: arya-virtual-service
namespace: xxx-group-2
spec:
hosts:
- "arya-python3.istio.xxx.com"
gateways:
- arya-gateway
http:
- match:
- uri:
prefix: /static
route:
- destination:
host: prod-arya-python3-static
- match:
- uri:
prefix: /
route:
- destination:
host: prod-arya-python3
subset: v2361
weight: 50
- destination:
host: prod-arya-python3
subset: v2418
weight: 50

# Service中不再区分版本号, 而是将其放在DestinationRule中
# 使用不同的subset来确定流量走向
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: arya-destination
namespace: xxx-group-2
spec:
host: prod-arya-python3
subsets:
- name: v2361
labels:
version: "2361"
- name: v2418
labels:
version: "2418"

由于我们使用了istio, 为了以后能用到DestinationRule的一些特性, 应该要按照后面的这种方式, 由DestinationRule的subset来进行分流.

kiali的界面

20210624114851

总结

从当前的调研使用来看, Istio的IngressGateway与普通的Ingress有一些区别, 不过很多功能可以用其替换. 如果项目从一开始就打算使用Istio的话, 建议不要再去使用Ingress了, 可以直接采用Gateway+VirtualService的形式. 我之后应该也会分享下用VirtualService以及DestinationRule可以实现的一些规则.