默认情况下,来自启用Istio的Pod的所有出站流量都会重定向到其Sidecar代理,因此集群外部URL的可访问性取决于代理的配置。网格中的工作负载想要访问网格外的服务时,有以下三种方法:

  1. 允许Envoy代理将请求透传到未在网格内部配置的服务。
  2. 配置 ServiceEntries 以提供对外部服务的受控访问。
  3. 对于特定范围的IP,完全绕过Envoy代理。

默认Istio将Envoy代理配置为透传对未知服务的请求,这简化了应用程序开发以及现有应用程序到网格的迁移。

第2种方法,使用Istio ServiceEntry配置,您可以从Istio集群中访问任何可公开访问的服务。而且不丢失Istio的流量监视和控制功能。该方法也是本文主要讲述的方法。

对于第三种方法,通过global.proxy.includeIPRanges配置。对于一些对性能要求比较高的应用可以选择使用,但是需要保证IP范围在一个可信的环境下。

代理出站流量策略模式

Istio有一个安装选项meshConfig.outboundTrafficPolicy.mode,用于配置对外部服务(即Istio内部服务注册表中未定义的那些服务)的处理方式。如果此选项设置为ALLOW_ANY,则Istio代理将允许对未知服务的调用。如果该选项设置为REGISTRY_ONLY,则Istio代理将阻止在网格中未定义HTTP服务或ServiceEntry的任何主机。

默认情况下,ALLOW_ANY为该配置项的默认值。

ServiceEntry

ServiceEntry是扩展Istio服务注册表的一种方式,以便现有的自动发现的服务可以访问其他服务,无论它们是未发现的内部服务还是完全在网格外部的服务(例如,Web API)。

通过配置ServiceEntry,您可以管理在网格外部运行的服务的流量,包括以下功能:

  • 重定向和转发用于外部目标的流量,例如从网络使用的API或到旧基础结构中服务的流量。
  • 为外部目标定义重试,超时和故障注入策略。
  • 通过将虚拟机添加到网格中,在虚拟机(VM)中运行网格服务。
  • 在逻辑上将来自其他集群的服务添加到网格,以在Kubernetes上配置多集群Istio网格。

以下示例描述了内部应用程序使用DNS通过主机名解析通过HTTP访问的外部API。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin.org
  namespace: foo
spec:
  hosts:
  - httpbin.org
  - www.httpbin.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
  exportTo:
  - "."
  resolution: DNS
  location: MESH_EXTERNAL

我们对该配置逐一字段解析:

  • hosts:DNS名称。可以具有通配符前缀。
  • ports:关联的端口。
  • ports.protocol: 以下之一:HTTP,HTTPS,HTTP2,GRPC,MONGO,TCP或TLS。
  • exportTo:默认情况下使用“*”,这意味着该ServiceEntry公开给每个命名空间。 “.”仅将其限制为当前命名空间。目前,exportTo值仅限于这两个。
  • resolution:主机的服务发现模式
  • location:从网格的角度来看,应将此服务视为内部或外部服务。

这里的字段并不是ServiceEntry支持的所有字段,更多请查看官方文档

Demo

该demo我们不仅仅是演示如何通过ServiceEntry访问外部服务,而且是演示如何对外部服务定义注入超时等策略。

1: 部署之前先部署我们的sleep pod,作为网格内的工作负载。由于我们在之前的文章中已经部署完成,所以这里略过。

kubectl get pods -n foo
NAME                       READY   STATUS    RESTARTS   AGE
httpbin-779c54bf49-dqmgm   2/2     Running   0          27h
sleep-d6b58ff57-jl8pq      2/2     Running   0          27h

2: 将上面示例ServiceEntry应用到集群中。

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin.org
  namespace: foo
spec:
  hosts:
  - httpbin.org
  - www.httpbin.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
  exportTo:
  - "."
  resolution: DNS
  location: MESH_EXTERNAL
EOF

3:从sleep的Pod内部,向http://httpbin.org外部服务的/delay端点发出curl请求:

$ kubectl exec sleep-d6b58ff57-jl8pq -c sleep -n foo -- time curl -o /dev/null -s -w "%{http_code}n" http://httpbin.org/delay/5
200
real    0m 5.70s
user    0m 0.00s
sys    0m 0.00s

该请求应在大约5秒钟内返回200(OK)。

4: 对外部服务httpbin.org增加超时设置,我们需要创建一个VirtualService如下:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin.org
  namespace: foo
spec:
  hosts:
    - httpbin.org
    - www.httpbin.org
  http:
  - timeout: 3s
    route:
      - destination:
          host: httpbin.org
        weight: 100
EOF

5: 再次从sleep的Pod内部,向http://httpbin.org外部服务的/delay端点发出curl请求:

kubectl exec sleep-d6b58ff57-jl8pq -c sleep -n foo -- time curl -o /dev/null -s -w "%{http_code}n" http://httpbin.org/delay/5
504
real    0m 3.01s
user    0m 0.00s
sys    0m 0.00s

这次3秒后出现504(网关超时)。尽管http://httpbin.org等待5秒,但Istio却在3秒时截断了请求。

总结

现实的世界中,并不能做到所有的业务都容器化,Istio也意识到了这个问题,所以正在支持非容器部署的业务。除了ServiceEntry,又增加了WorkloadEntry,从而支持将vm部署的业务纳入mesh中。


iyacontrol
1.4k 声望2.7k 粉丝

专注kubernetes,devops,aiops,service mesh。


« 上一篇
详解Istio mTLS
下一篇 »
Istio流量管理