Istio Egress Gateway出口流量管理

缺省状态下,Istio服务网格内的Pod,由于其iptables将所有外发流量都透明的转发给了sidecar,所以这些集群内的服务无法访问集群之外的 URL,而只能处理集群内部的目标。

控制出口流量描述了如何通过ServiceEntry将外部服务暴露给集群内的客户端

本文则通过一个官方的用例解释如何通过Egress Gateway配置Istio的出口流量,这个例子主要适用于两种场景:

  1. 离​​开服务网格的所有流量必须流经一组专用节点,这一组节点会有特殊的监控和审查
  2. 集群中不是所有节点都有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

这一段配置中的matchgateways表示这一条路由规则是作用在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,比较简单地集成到自己项目的微服务开发中。

上一篇:Java创建数组的三种形式


下一篇:纳管集群接入Metric Adapter