# egress

访问外部服务 11分钟阅读 页面测试

由于默认情况下,来自启用Istio的Pod的所有出站流量都会重定向到其Sidecar代理,因此集群外部URL的可访问性取决于代理的配置。默认情况下,Istio将Envoy代理配置为传递对未知服务的请求。尽管这提供了一种方便的Istio入门方法,但通常最好配置更严格的控制。

此任务向您展示如何以三种不同方式访问外部服务:

允许Envoy代理将请求传递到未在网格内部配置的服务。 配置服务条目以提供对外部服务的受控访问。 对于特定范围的IP,完全绕过Envoy代理。 在你开始之前 按照安装指南中的说明安装Istio 。使用demo 配置文件或 启用Envoy的访问日志。

部署睡眠示例应用程序以用作发送请求的测试源。如果 启用了自动边车注入功能,请运行以下命令来部署示例应用程序:

$ kubectl apply -f samples/sleep/sleep.yaml

否则,请在sleep使用以下命令部署应用程序之前手动注入sidecar :

$ kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml)

您可以将curl已安装的任何Pod用作测试源。 将SOURCE\_POD环境变量设置为源容器的名称:

$ export SOURCE\_POD=$(kubectl get pod -l app=sleep -o jsonpath='{.items..metadata.name}')

envoy直通外部服务 Istio具有安装选项, meshConfig.outboundTrafficPolicy.mode用于配置外部服务(即未在Istio的内部服务registry中定义的那些服务)的边车处理。如果将此选项设置为ALLOW\_ANY,则Istio代理允许对未知服务的呼叫通过。如果该选项设置为REGISTRY\_ONLY,则Istio代理将阻止在网格中定义了HTTP服务或服务条目的任何主机.ALLOW\_ANY是默认值,使您可以快速开始评估Istio,而无需控制对外部服务的访问。然后,您可以决定以后配置对外部服务的访问。

要查看这种方法的实际效果,您需要确保将Istio安装配置为meshConfig.outboundTrafficPolicy.mode选项设置为ALLOW\_ANY。除非REGISTRY\_ONLY在安装Istio时将其明确设置为mode,否则默认情况下可能已启用它。

运行以下命令以验证meshConfig.outboundTrafficPolicy.mode选项设置为ALLOW\_ANY 或被省略:

$ kubectl get istiooperator installed-state -n istio-system -o jsonpath='{.spec.meshConfig.outboundTrafficPolicy.mode}' ALLOW\_ANY

您应该看到ALLOW\_ANY或没有输出(默认ALLOW\_ANY)。

如果已显式配置REGISTRY\_ONLY模式,则可以通过istioctl install使用更改后的设置重新运行原始命令来进行更改,例如:

$ istioctl install  --set meshConfig.outboundTrafficPolicy.mode=ALLOW\_ANY

从发出几个对外部HTTPS服务的请求,SOURCE\_POD以确认成功的200响应:

$ kubectl exec "$SOURCE\_POD" -c sleep -- curl -sI [https://www.google.com](https://www.google.com) | grep "HTTP/"; kubectl exec "$SOURCE\_POD" -c sleep -- curl -sI [https://edition.cnn.com](https://edition.cnn.com) | grep "HTTP/" HTTP/2 200 HTTP/2 200

恭喜你！您已成功从网格发送了出口流量。

这种访问外部服务的简单方法的缺点是,您将失去对外部服务流量的Istio监视和控制。下一节将向您展示如何监视和控制网格对外部服务的访问。

受控访问外部服务 使用IstioServiceEntry配置,您可以从Istio集群中访问任何可公开访问的服务。本部分说明如何在不丢失Istio的流量监视和控制功能的情况下配置对外部HTTP服务 httpbin.org以及外部HTTPS服务 www.google.com的访问。

更改为默认阻止策略 为了演示启用对外部服务的访问的受控方式,您需要将 meshConfig.outboundTrafficPolicy.mode选项从ALLOW\_ANY模式更改为REGISTRY\_ONLY模式。

您可以添加对已在ALLOW\_ANY模式下可访问的服务的受控访问。这样,您可以开始在某些外部服务上使用Istio功能,而不会阻止其他任何服务。配置完所有服务后,即可将模式切换REGISTRY\_ONLY为阻止任何其他无意访问。 将meshConfig.outboundTrafficPolicy.mode选项更改为REGISTRY\_ONLY。

如果使用IstioOperatorCR安装Istio,请在配置中添加以下字段:

spec: meshConfig: outboundTrafficPolicy: mode: REGISTRY\_ONLY

否则,将等效设置添加到原始istioctl install命令中,例如:

$ istioctl install   --set meshConfig.outboundTrafficPolicy.mode=REGISTRY\_ONLY

向外部HTTPS服务发出几个请求,SOURCE\_POD以确认它们现在已被阻止:

$ kubectl exec "$SOURCE\_POD" -c sleep -- curl -sI [https://www.google.com](https://www.google.com) | grep "HTTP/"; kubectl exec "$SOURCE\_POD" -c sleep -- curl -sI [https://edition.cnn.com](https://edition.cnn.com) | grep "HTTP/" command terminated with exit code 35 command terminated with exit code 35

配置更改可能要花一些时间才能传播,因此您仍然可能会获得成功的连接。等待几秒钟,然后重试最后一条命令。 访问外部HTTP服务 创建一个ServiceEntry以允许访问外部HTTP服务。

DNS解决方案在以下服务条目中用作安全措施。将分辨率设置为NONE 打开可能会造成攻击。恶意客户端可能会httpbin.org通过在HOST标头中设置它来假装正在访问,而实际上却连接到另一个IP(与不相关httpbin.org)。Istio Sidecar代理将信任HOST标头,并且即使将其传递到其他主机的IP地址,也会错误地允许该通信。该主机可以是网状安全策略禁止的恶意站点或合法站点。

通过DNS解析,Sidecar代理将忽略原始目标IP地址,并将流量定向到httpbin.org,执行DNS查询以获取IP地址httpbin.org。

$ kubectl apply -f - <\<EOF apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: httpbin-ext spec: hosts:

*   httpbin.org

    ports:
*   number: 80

    name: http

    protocol: HTTP

    resolution: DNS

    location: MESH\_EXTERNAL

    EOF

从发出对外部HTTP服务的请求SOURCE\_POD:

$ kubectl exec "$SOURCE\_POD" -c sleep -- curl -s [http://httpbin.org/headers](http://httpbin.org/headers) { "headers": { "Accept": "_/_", "Content-Length": "0", "Host": "httpbin.org", ... "X-Envoy-Decorator-Operation": "httpbin.org:80/\*", ... } }

请注意Istio sidecar代理添加的标头:X-Envoy-Decorator-Operation。

检查以下工具的日志SOURCE\_POD:

$ kubectl logs "$SOURCE\_POD" -c istio-proxy | tail \[2019-01-24T12:17:11.640Z] "GET /headers HTTP/1.1" 200 - 0 599 214 214 "-" "curl/7.60.0" "17fde8f7-fa62-9b39-8999-302324e6def2" "httpbin.org" "35.173.6.94:80" outbound|80||httpbin.org - 35.173.6.94:80 172.30.109.82:55314 -

请注意与您的HTTP请求相关的条目httpbin.org/headers。

访问外部HTTPS服务 创建一个ServiceEntry以允许访问外部HTTPS服务。

$ kubectl apply -f - <\<EOF apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: google spec: hosts:

*   www.google.com

    ports:
*   number: 443

    name: https

    protocol: HTTPS

    resolution: DNS

    location: MESH\_EXTERNAL

    EOF

向外部HTTPS服务发出请求SOURCE\_POD:

$ kubectl exec "$SOURCE\_POD" -c sleep -- curl -sI [https://www.google.com](https://www.google.com) | grep "HTTP/" HTTP/2 200

检查以下工具的日志SOURCE\_POD:

$ kubectl logs "$SOURCE\_POD" -c istio-proxy | tail \[2019-01-24T12:48:54.977Z] "- - -" 0 - 601 17766 1289 - "-" "-" "-" "-" "172.217.161.36:443" outbound|443||www.google.com 172.30.109.82:59480 172.217.161.36:443 172.30.109.82:59478 www.google.com

请注意与HTTPS请求相关的条目www.google.com。

管理到外部服务的流量 与集群间请求类似, 也可以为使用配置访问的外部服务设置Istio 路由规则ServiceEntry。在此示例中,您对httpbin.org服务的调用设置了超时规则。

从用作测试源的Pod内部,向httpbin.org外部服务的端点发出curl请求/delay:

$ kubectl exec "$SOURCE\_POD" -c sleep -- time curl -o /dev/null -s -w "%{http\_code}\n" [http://httpbin.org/delay/5](http://httpbin.org/delay/5) 200 real 0m5.024s user 0m0.003s sys 0m0.003s

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

使用kubectl设置3秒超时就调用的httpbin.org外部服务:

$ kubectl apply -f - <\<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin-ext spec: hosts:

*   httpbin.org

    http:

    *   timeout: 3s

        route:
    *   destination:

        &#x20; host: httpbin.org

        weight: 100

        EOF

等待几秒钟,然后再次发出curl请求:

$ kubectl exec "$SOURCE\_POD" -c sleep -- time curl -o /dev/null -s -w "%{http\_code}\n" [http://httpbin.org/delay/5](http://httpbin.org/delay/5) 504 real 0m3.149s user 0m0.004s sys 0m0.004s

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

清理对外部服务的受控访问 $ kubectl delete serviceentry httpbin-ext google $ kubectl delete virtualservice httpbin-ext --ignore-not-found=true

直接访问外部服务 如果要针对特定​​IP范围完全绕过Istio,则可以配置Envoy边车以防止它们 拦截 外部请求。要设置旁路,请更改global.proxy.includeIPRanges 或global.proxy.excludeIPRanges 配置选项,然后istio-sidecar-injector使用以下kubectl apply命令更新配置图。也可以通过设置相应的注释(例如) 在窗格上进行配置traffic.sidecar.istio.io/includeOutboundIPRanges。更新istio-sidecar-injector配置后,它将影响所有将来的应用程序pod部署。

与Envoy到外部服务的传递不同,Envoy使用ALLOW\_ANY流量策略来指示Istio边车代理将调用传递给未知服务,该方法完全绕过了边车,从而实质上禁用了指定IP的所有Istio功能。您不能像使用该ALLOW\_ANY方法那样为特定目标增量添加服务条目。因此,仅当出于性能或其他原因无法使用边车配置外部访问时,才建议将此配置方法作为最后的选择。 排除所有外部IP重定向到Sidecar代理的一种简单方法是将global.proxy.includeIPRanges配置选项设置为内部集群服务使用的IP范围。这些IP范围值取决于集群运行的平台。

确定平台的内部IP范围 values.global.proxy.includeIPRanges根据您的集群提供者设置值。

IBM Cloud Private service\_cluster\_ip\_range从以下位置从IBM Cloud Private配置文件获取cluster/config.yaml:

$ grep service\_cluster\_ip\_range cluster/config.yaml

以下是示例输出:

service\_cluster\_ip\_range: 10.0.0.1/24

使用 --set values.global.proxy.includeIPRanges="10.0.0.1/24"

IBM Cloud Kubernetes服务 使用 --set values.global.proxy.includeIPRanges="172.30.0.0/16\\,172.21.0.0/16\\,10.10.10.0/24"

Google容器引擎(GKE) 范围不是固定的,因此您将需要运行gcloud container clusters describe命令来确定要使用的范围。例如:

$ gcloud container clusters describe XXXXXXX --zone=XXXXXX | grep -e clusterIpv4Cidr -e servicesIpv4Cidr clusterIpv4Cidr: 10.4.0.0/14 servicesIpv4Cidr: 10.7.240.0/20

使用 --set values.global.proxy.includeIPRanges="10.4.0.0/14\\,10.7.240.0/20"

Azure容器服务(ACS) 使用 --set values.global.proxy.includeIPRanges="10.244.0.0/16\\,10.240.0.0/16

Minikube,用于桌面的Docker,裸机 默认值为10.96.0.0/12,但不是固定的。使用以下命令确定您的实际值:

$ kubectl describe pod kube-apiserver -n kube-system | grep 'service-cluster-ip-range' --service-cluster-ip-range=10.96.0.0/12

使用 --set values.global.proxy.includeIPRanges="10.96.0.0/12"

配置代理绕过 删除本指南中先前部署的服务条目和虚拟服务。 istio-sidecar-injector使用特定于平台的IP范围更新配置图。例如,如果范围是10.0.0.1/24,请使用以下命令:

$ istioctl install  --set values.global.proxy.includeIPRanges="10.0.0.1/24"

使用与安装Istio和add相同的命令--set values.global.proxy.includeIPRanges="10.0.0.1/24"。

访问外部服务 由于旁路配置仅影响新的部署,因此您需要按照开始之前部分中sleep 所述终止并重新部署应用程序。

更新配置istio-sidecar-injector映射并重新部署sleep应用程序后,Istio边车将仅拦截和管理集群中的内部请求。任何外部请求都会绕过Sidecar,并直接到达其预期的目的地。例如:

$ kubectl exec "$SOURCE\_POD" -c sleep -- curl -s [http://httpbin.org/headers](http://httpbin.org/headers) { "headers": { "Accept": "_/_", "Host": "httpbin.org", ... } }

与通过HTTP或HTTPS访问外部服务不同,您不会看到与Istio Sidecar相关的任何标头,并且发送到外部服务的请求不会出现在Sidecar的日志中。绕过Istio边车意味着您不再能够监视对外部服务的访问。

清理对外部服务的直接访问 更新配置,以停止绕过一系列IP的sidecar代理:

$ istioctl install&#x20;

了解发生了什么 在此任务中,您研究了从Istio网格调用外部服务的三种方法:

配置Envoy以允许访问任何外部服务。

使用服务条目在网格内注册可访问的外部服务。这是推荐的方法。

配置Istio边车以从其重新映射的IP表中排除外部IP。

第一种方法通过Istio边车代理来引导流量,包括对网格内未知服务的调用。使用这种方法时,您将无法监视对外部服务的访问或无法利用Istio的流量控制功能。要轻松切换到特定服务的第二种方法,只需为那些外部服务创建服务条目即可。此过程使您可以首先访问任何外部服务,然后在以后决定是否控制访问,启用流量监视以及根据需要使用流量控制功能。

第二种方法使您可以使用所有相同的Istio服务网格功能来调用集群内部或外部的服务。在此任务中,您学习了如何监视对外部服务的访问以及如何设置对外部服务的调用的超时规则。

第三种方法绕过了Istio Sidecar代理,使您的服务可以直接访问任何外部服务器。但是,以这种方式配置代理确实需要集群提供商特定的知识和配置。与第一种方法类似,您也将失去对外部服务访问的监控,并且无法将Istio功能应用于外部服务的流量。

安全说明 请注意,此任务中的配置示例未在Istio中启用安全的出口流量控制。恶意应用程序可以绕过Istio Sidecar代理,并在不受Istio控制的情况下访问任何外部服务。 为了以更安全的方式实施出口流量控制,您必须 通过出口网关引导出口流量, 并查看其他安全注意事项 部分中描述的安全问题 。

清理 关闭睡眠服务:

$ kubectl delete -f samples/sleep/sleep.yaml
