缺省状态下,Istio服务网格内的Pod,由于其iptables将所有外发流量都透明的转发给了sidecar,所以这些集群内的服务无法访问集群之外的 URL,而只能处理集群内部的目标。
控制出口流量描述了如何通过ServiceEntry将外部服务暴露给集群内的客户端
本文则通过一个官方的用例解释如何通过Egress Gateway
配置Istio的出口流量,这个例子主要适用于两种场景:
- 离开服务网格的所有流量必须流经一组专用节点,这一组节点会有特殊的监控和审查
- 集群中不是所有节点都有public IP,定义egress网关,通过它引导所有出口流量并将public IP分配给egress网关节点,允许应用节点以受控方式访问外部服务
环境准备
创建Kubernetes集群
阿里云容器服务Kubernetes 1.11.2目前已经上线,可以通过容器服务管理控制台非常方便地快速创建 Kubernetes 集群。具体过程可以参考这里
部署istio
阿里云容器服务在应用目录
目前支持istio快速部署,具体过程可以参考这里
部署用例
kubectl apply -f <(istioctl kube-inject -f https://raw.githubusercontent.com/istio/istio/release-1.0/samples/sleep/sleep.yaml)
定义需要向外发送请求的pod
export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
创建ServiceEntry
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: cnn
spec:
hosts:
- edition.cnn.com
ports:
- number: 80
name: http-port
protocol: HTTP
- number: 443
name: https
protocol: HTTPS
resolution: DNS
EOF
验证配置生效
kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
如下返回表示配置生效
HTTP/1.1 301 Moved Permanently
...
location: https://edition.cnn.com/politics
...
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
Content-Length: 151654
...
创建Gateway
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: egressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- edition.cnn.com
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: egressgateway-for-cnn
spec:
host: istio-egressgateway.istio-system.svc.cluster.local
subsets:
- name: cnn
EOF
创建VirtualService
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: direct-cnn-through-egress-gateway
spec:
hosts:
- edition.cnn.com
gateways:
- istio-egressgateway
- mesh
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: cnn
port:
number: 80
weight: 100
- match:
- gateways:
- istio-egressgateway
port: 80
route:
- destination:
host: edition.cnn.com
port:
number: 80
weight: 100
EOF
再次发送请求
kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
此时返回应该仍然是成功的,但是我们查看istio-egressgateway
的日志
kubectl logs $(kubectl get pod -l istio=egressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}') egressgateway -n istio-system | tail
应该会有一条类似这样的记录
[2018-06-14T11:46:23.596Z] "GET /politics HTTP/2" 301 - 0 0 3 1 "172.30.146.87" "curl/7.35.0" "ab7be694-e367-94c5-83d1-086eca996dae" "edition.cnn.com" "151.101.193.67:80"
说明出口流量已经汇入egress gateway
,然后由他引导至集群外部
配置解释
在本例中创建了四种资源,真正定义将出口流量转发给egress gateway
的是VirtualService
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: cnn
port:
number: 80
weight: 100
这一段配置中的match
的gateways
表示这一条路由规则是作用在mesh
上的,也就是整个网格中所有的sidecar上,port
表示所有访问80端口的流量才会应用这条规则,因为本例中只提供了80端口的服务,所以这一项是可以省略掉的
destination
表示会把所有路由后的流量导入istio-egressgateway.istio-system.svc.cluster.local
service的cnn
sbuset下的80端口,这里需要注意的是,istio-egressgateway
是在Istio部署时定义的service,已经开放了80,443端口,在真实使用中如果要用到别的端口,需要在istio-egressgateway
的定义中做对应的修改
同理,VirtualService
中的另一部分规则作用在istio-egressgateway
上,会把出口流量引导至集群外部
总结
本文通过示例演示了Istio如何对网格内的出口流量做统一的引导。
欢迎大家使用阿里云上的容器服务,快速搭建微服务的开放治理平台Istio,比较简单地集成到自己项目的微服务开发中。
欢迎大家使用阿里云上的容器服务,快速搭建微服务的开放治理平台Istio,比较简单地集成到自己项目的微服务开发中。