Z.S.K.'s Records

Istio学习(Gateway)

Gateway在istio中是一个比较重要的对象, 一般用于管理南北流量,即集群外向集群内的访问及集群内需要访问集群外的这部分流量.

同样, 还是以官方的示例: book-info做为例子

Gateway

从ingressgateway容器的启动命令中可以看到,启动跟envoy的启动命令很像

同样 pilot-agent为1号启动进程, 负责envoy的启动及托管, 还负责envoy的配置更新

envoy启动的proxy 后面是sidecar,而ingressgateway启动的proxy后面是router

启动命令

Pilot-agent启动命令:

1
/usr/local/bin/pilot-agent proxy router --domain istio-system.svc.cluster.local --proxyLogLevel=warning --proxyComponentLogLevel=misc:error --log_output_level=default:info --drainDuration 45s --parentShutdownDuration 1m0s --connectTimeout 10s --serviceCluster istio-egressgateway --zipkinAddress zipkin.istio-system:9411 --proxyAdminPort 15000 --statusPort 15020 --controlPlaneAuthPolicy NONE --discoveryAddress istio-pilot.istio-system:15010 --trust-domain=cluster.local

envoy的启动命令:

1
/usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev1.json --restart-epoch 1 --drain-time-s 45 --parent-shutdown-time-s 60 --service-cluster istio-ingressgateway --service-node router~10.244.0.4~istio-ingressgateway-6d759478d8-pxbn9.istio-system~istio-system.svc.cluster.local --max-obj-name-len 189 --local-address-ip-version v4 --log-format [Envoy (Epoch 1)] [%Y-%m-%d %T.%e][%t][%l][%n] %v -l warning --component-log-level misc:error

gateway

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"

上面指定了istio: ingressgateway,即所有从80端口的任一域名的http协议都由ingressgateway进入, 这样就保证了所有外部流量的统一治理。

gateway一般与virtualService一起共用.

和 Kubernetes Ingress 不同,Istio Gateway 只配置四层到六层的功能(例如开放端口或者 TLS 配置)。绑定一个 VirtualService到 Gateway 上,就可以使用标准的 Istio 规则来控制进入的 HTTP 和 TCP 流量

为上面的gateway定义virtualservice:

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
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway #绑定gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080

这样,就可以在集群外部访问productpage服务了

engressgateway跟Ingressgateway其实一样,只不过一个管理出口流量,一个管理进口流量,engressgateway的作用完全可以由ingressgateway替代, 不过为了区分,让两者独立管理罢了.

engressgateway还有一个好外是将所有的对外网访问控制engressgateway这一个范围, 而不必对每个需要访问外网的应用开启外网权限,起到一个安全的作用

ServiceEntry

上面gateway用于集群外需要访问集群内的服务, 而serviceEntry则是用于要访问的服务不在集群内部, 使用serviceEntry同样可以把这部分的请求流量治理起来.

serivceEntry通常搭配engress 一起使用, 当然 , serviceEntry没有engress也可以,只不过为了统一管理/治理外出流量,因此将所有定义的serviceEntry的请求都统一转到engress向外转发

serviceEntry跟Kubernetes在Servicesubset的subset中指定endpoint作用相同

典型的serviceEntry的例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: googleapis
spec:
hosts:
- www.googleapis.com
ports:
- number: 80
name: http
protocol: HTTP
- number: 443
name: https
protocol: HTTPS
resolution: DNS

通过host字段来指定外部目标, 通过80/443就能够在meseh内部访问www.googleapis.com了

当然,还可以通过virtualservice来对这次访问进行控制, 比如给上面的访问加上个10s超时

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: timeout-for-googleapis
spec:
hosts:
- www.googleapis.com
http:
- route:
- destination:
host: www.googleapis.com
timeout: 10

流量的重定向和转发、定义重试和超时以及错误注入策略都支持外部目标。然而由于外部服务没有多版本的概念,因此权重(基于版本)路由就无法实现了

问题

假如在kubernetes中已经存在了一个service访问外部ip, yaml文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
clusterIP: None
ports:
- protocol: TCP
port: 3306
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-db
subsets:
- addresses:
- ip: 190.64.31.232
ports:
- port: 3306

190.64.31.232这个是外部mysql的地址,在kubernetes中, 即可直接通过external-db直接访问数据库

如果这时,需要通过istio统一管理外向流量,则可通过以下方式:

保存上面的Headless service不变

创建一个serviceEntry:

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: external-db
spec:
hosts:
- external-db
ports:
- number: 3306
name: tcp
protocol: TCP
location: MESH_EXTERNAL
resolution: STATIC

注意, 这里的resolution为STATIC, 因为kubernetes中已经存在了有external-db的域名(上面headless的定义),不需要再进行解析就可以直接转到endpoint(190.64.31.232)

当然 如果mysql本身存在域名且在网格之外可以解析, 那就无需在kubernetes定义svc, 直接创建一个serviceEntry即可

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: external-db
spec:
hosts:
- external-db.xxx.yyy
ports:
- number: 3306
name: tcp
protocol: TCP
location: MESH_EXTERNAL
resolution: DNS #DNS, 需要保证hosts对应的域名可以解析

参考文章:

转载请注明出处https://izsk.me

Z.S.K. wechat
Scan Me To Read on Phone
I know you won't do this,but what if you did?