istio 1.10学习笔记12: Istio Egress Gateway及其使用场景
2021-07-29
上一节学习了istio服务网格内部访问外部服务的三种方法,推荐使用ServiceEntry将一个外部服务注册到服务网格中的方式,这样服务网格内部的到外部服务的访问流量都是受到istio管理的,但这种方法下访问外部服务的流量都是从内部服务实例所在节点的sidecar代理发出的,这在某些场景下会有一些限制。 例如,一个对安全有严格要求的组织,要求服务网格所有的出站流量必须经过一组专用节点。专用节点运行在专门的机器上,与集群中运行应用程序的其他节点隔离,这些专用节点将专门实施针对出站流量的策略,并且受到比其余节点更严密地监控。另外一个场景是在集群中不是所有节点都可以访问公网(或某个外部IP的),如集群中只有一个节点可以访问公网,所以服务网格内其他节点上的服务实例也就无法访问公网上的外部服务了。在这两个场景中都是因为服务网格内的一部分节点在网络上无法访问外部服务,因此需要有一个在网络上可以访问外部服务的节点作为egress gateway节点,用来引导所有的出站流量,这样也能实现该节点以受控的方式访问外部服务。
前面第7节我们学习Istio Ingress Gateway用来将集群外部流量接入到服务网格内,与之对应的还有一个Istio Egress Gateway定义了服务网格的统一出口。 Ingress and Egress Gateways可以被理解为配置运行在服务网格边缘的负载均衡,Ingress gateway允许我们定义网格所有入站流量的入口,Egress gateway允许我们定义网格的出口。
下面来具体实际操作一下。以demo profile部署的isito已经随之安装了engress gateway,可以使用下面的命令查看一下:
1kubectl get all -n istio-system -l app=istio-egressgateway
2NAME READY STATUS RESTARTS AGE
3pod/istio-egressgateway-7d4f75956-mq6d9 1/1 Running 0 8d
4
5NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
6service/istio-egressgateway ClusterIP 10.105.21.145 <none> 80/TCP,443/TCP 25d
7
8NAME READY UP-TO-DATE AVAILABLE AGE
9deployment.apps/istio-egressgateway 1/1 1 1 25d
在真实的使用场景中我们应该将istio-egressgateway
调度到服务网格内专门用作egress gateway的节点上。
下面测试使用istio-egressgateway
引导服务网格内访问外部服务httpbin.org
的流量。
与上节内容一下,要访问外部服务,需要先创建一个ServiceEntry将外部服务注册到服务网格内:
1kubectl apply -f - <<EOF
2apiVersion: networking.istio.io/v1alpha3
3kind: ServiceEntry
4metadata:
5 name: httpbin-ext
6spec:
7 hosts:
8 - httpbin.org
9 ports:
10 - number: 443
11 name: https
12 protocol: HTTPS
13 resolution: DNS
14EOF
因为default命名空间在前面部署bookinfo应用时已经开启了istio sidecar的自动注入功能,这里我们在default命令空间中手动启动一个radial/busyboxplus:curl
pod用来测试,启动的这个pod将被自动注入istio sidecar代理:
1kubectl run curl --image=radial/busyboxplus:curl -it
在curl容器内部测试可以正常访问httpbin.org
,说明ServiceEntry已经配置。
1curl -sSI https://httpbin.org/headers | grep "HTTP/"
2HTTP/1.1 200 OK
为httpbin.org
的443端口创建Egress Gateway。并为指向Egress Gateway的流量创建一个目标规则DestinationRule。
1kubectl apply -f - <<EOF
2apiVersion: networking.istio.io/v1alpha3
3kind: Gateway
4metadata:
5 name: istio-egressgateway
6spec:
7 selector:
8 istio: egressgateway
9 servers:
10 - port:
11 number: 443
12 name: tls
13 protocol: TLS
14 hosts:
15 - httpbin.org
16 tls:
17 mode: PASSTHROUGH
18---
19apiVersion: networking.istio.io/v1alpha3
20kind: DestinationRule
21metadata:
22 name: egressgateway-for-httpbin-ext
23spec:
24 host: istio-egressgateway.istio-system.svc.cluster.local
25 subsets:
26 - name: httpbin-ext
27EOF
创建一个虚拟服务VirtualService,将流量从 sidecar 引导至 egress gateway,再从 egress gateway 引导至外部服务:
1kubectl apply -f - <<EOF
2apiVersion: networking.istio.io/v1alpha3
3kind: VirtualService
4metadata:
5 name: direct-httpbin-ext-through-egress-gateway
6spec:
7 hosts:
8 - httpbin.org
9 gateways:
10 - mesh
11 - istio-egressgateway
12 tls:
13 - match:
14 - gateways:
15 - mesh
16 port: 443
17 sniHosts:
18 - httpbin.org
19 route:
20 - destination:
21 host: istio-egressgateway.istio-system.svc.cluster.local
22 subset: httpbin-ext
23 port:
24 number: 443
25 - match:
26 - gateways:
27 - istio-egressgateway
28 port: 443
29 sniHosts:
30 - httpbin.org
31 route:
32 - destination:
33 host: httpbin.org
34 port:
35 number: 443
36 weight: 100
37EOF
在curl容器内向https://httpbin.org/headers
发送请求,确认正常可以访问:
1curl -sSI https://httpbin.org/headers | grep "HTTP/"
2HTTP/1.1 200 OK
检查istio-egressgateway
代理的日志:
1kubectl logs -l istio=egressgateway -n istio-system
2
3[2021-07-29T12:13:02.120Z] "- - -" 0 - - - "-" 574 5590 1946 - "-" "-" "-" "-" "18.235.124.214:443" outbound|443||httpbin.org 10.244.166.182:42106 10.244.166.182:8443 10.244.104.48:41278 httpbin.org -
说明到httpbin.org
的请求是由istio-egressgateway
代理作为出口发出的。
需要注意,Istio中定义的egress Gateway本身并没有为其所在的节点提供任何特殊处理。集群管理员或云提供商可以在专用节点上部署egress gateway,并引入额外的安全措施,从而使这些节点比网格中的其他节点更安全。 另外要注意的是,Istio 无法强制让所有出站流量都经过egress gateway,Istio 只是通过sidecar代理实现了这种流向。攻击者只要绕过sidecar代理,就可以不经egress gateway直接与网格外的服务进行通信,从而避开了Istio的控制和监控。 出于安全考虑,集群管理员或云供应商必须确保网格所有的出站流量都要经过egress gateway。这需要通过Istio之外的机制来满足这一要求。例如,集群管理员可以配置防火墙,拒绝egress gateway以外的所有流量。Kubernetes网络策略也能禁止所有不是从egress gateway发起的出站流量。