默认情况下,来自启用Istio的Pod的所有出站流量都会重定向到其Sidecar代理,因此集群外部URL的可访问性取决于代理的配置。网格中的工作负载想要访问网格外的服务时,有以下三种方法:
- 允许Envoy代理将请求透传到未在网格内部配置的服务。
- 配置 ServiceEntries 以提供对外部服务的受控访问。
- 对于特定范围的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中。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。