istio访问外部的服务

发布时间 2023-06-06 15:27:55作者: FLOWERS_WAN

部署 sleep 这个示例应用,用作发送请求的测试源。 如果你启用了自动注入 sidecar,使用以下的命令来部署示例应用:

kubectl apply -f samples/sleep/sleep.yaml

设置环境变量 SOURCE_POD,值为你的源 pod 的名称:

$ export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
 
Istio 有一个安装选项global.outboundTrafficPolicy.mode,它配置 sidecar 对外部服务(那些没有在 Istio 的内部服务注册中定义的服务)的处理方式。如果这个选项设置为 ALLOW_ANY
Istio 代理允许调用未知的服务。如果这个选项设置为 REGISTRY_ONLY,那么 Istio 代理会阻止任何没有在网格中定义的 HTTP 服务或 service entry 的主机。ALLOW_ANY 是默认值,
不控制对外部服务的访问,方便你快速地评估 Istio。你可以稍后再配置对外部服务的访问
 
kubectl get istiooperator installed-state -n istio-system -o jsonpath='{.spec.meshConfig.outboundTrafficPolicy.mode}'
您应该看到ALLOW_ANY或没有任何输出(默认为ALLOW_ANY
 

SOURCE_POD 向外部 HTTPS 服务发出两个请求,确保能够得到状态码为 200 的响应:

$ kubectl exec "$SOURCE_POD" -c sleep -- curl -sSI https://www.google.com | grep "HTTP/"; kubectl exec "$SOURCE_POD" -c sleep -- curl -sI https://edition.cnn.com | grep "HTTP/"
HTTP/2 200 HTTP/2 200
 

恭喜!你已经成功地从网格中发送了 egress 流量。

这种访问外部服务的简单方法有一个缺点,即丢失了对外部服务流量的 Istio 监控和控制;比如,外部服务的调用没有记录到 Mixer 的日志中。下一节将介绍如何监控和控制网格对外部服务的访问。

 

控制对外部服务的访问

使用 Istio ServiceEntry 配置,你可以从 Istio 集群中访问任何公开的服务。本节将向你展示如何在不丢失 Istio 的流量监控和控制特性的情况下,配置对外部 HTTP 服务(httpbin.org) 和外部 HTTPS 服务(www.google.com) 的访问。

 

更改为默认的封锁策略

为了演示如何控制对外部服务的访问,你需要将 global.outboundTrafficPolicy.mode 选项,从 ALLOW_ANY模式 改为 REGISTRY_ONLY 模式。

执行以下命令来将 global.outboundTrafficPolicy.mode 选项改为 REGISTRY_ONLY

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

spec:
  meshConfig:
    outboundTrafficPolicy:
      mode: REGISTRY_ONLY

修改这里才有效果
[root@k8s-master01 ~]# kubectl edit cm -n istio-system istio
configmap/istio edited

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

$ istioctl install <flags-you-used-to-install-Istio> \ --set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY

SOURCE_POD 向外部 HTTPS 服务发出几个请求,验证它们现在是否被阻止:

$ kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://www.google.com | grep "HTTP/"; kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://edition.cnn.com | grep "HTTP/"
command terminated with exit code 35 command terminated with exit code 35
 
配置更改后肯需要一小段时间才能生效,所以你可能仍然可以得到成功地响应。等待若干秒后再重新执行上面的命令。

 

 

访问一个外部的 HTTP 服务

创建一个 ServiceEntry,以允许访问一个外部的 HTTP 服务:

 

DNS 解析在下面的服务条目中用作安全措。将解析设置为 NONE会开启了攻击的可能。恶意客户端在真正连接到其他IP时,可能会伪装设置 HOST 头信息为 httpbin.org(与 httpbin.org 不相关)。Istio sidecar 代理将信任 HOST 头信息,并错误地允许通信,甚至将其传递到其他主机的 IP 地址。 该主机可能是恶意的站点,或者网格安全策略禁止的站点。

使用 DNS 解析,Sidecar 代理将忽略原始目标 IP 地址并引导流量到 httpbin.org,并执行 DNS 查询以获取 httpbin.org 的IP地址。

 

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
SOURCE_POD 向外部的 HTTP 服务发出一个请求:

 kubectl exec -it $SOURCE_POD -c sleep -- curl http://httpbin.org/headers
检查 SOURCE_POD 的 sidecar 代理的日志:

 kubectl logs $SOURCE_POD -c istio-proxy | tail

 kubectl logs $SOURCE_POD -c istio-proxy | tail
与集群内的请求相似,也可以为使用 ServiceEntry 配置访问的外部服务设置 Istio 路由规则。在本示例中,你将设置对 httpbin.org 服务访问的超时规则。

 

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

kubectl exec "$SOURCE_POD" -c sleep -- time curl -o /dev/null -sS -w "%{http_code}\n" http://httpbin.org/delay/5

退出测试源 pod,使用 kubectl 设置调用外部服务 httpbin.org 的超时时间为 3 秒

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

几秒后,重新发出 curl 请求:

kubectl exec -it $SOURCE_POD -c sleep sh
time curl -o /dev/null -s -w "%{http_code}\n" http://httpbin.org/delay/5

清理对外部服务的受控访问

$ kubectl delete serviceentry httpbin-ext google
$ kubectl delete virtualservice httpbin-ext --ignore-not-found=true

 

直接访问外部服务

如果要让特定范围的 ​​IP 完全绕过 Istio,则可以配置 Envoy sidecars 以防止它们拦截外部请求。要设置绕过 Istio,请更改 global.proxy.includeIPRangesglobal.proxy.excludeIPRanges configuration option,并使用 kubectl apply 命令更新 istio-sidecar-injector 配置。也可以通过设置相应的注解)在pod上进行配置,例如traffic.sidecar.istio.io / includeOutboundIPRangesistio-sidecar-injector 配置的更新,影响的是新部署应用的 pod。

 

默认值为 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 global.proxy.includeIPRanges="10.96.0.0/12"

[root@k8s-master01 istio-1.17.1]# istioctl manifest apply --set profile=demo --set values.global.proxy.includeIPRanges="10.96.0.0/12"
This will install the Istio 1.17.1 demo profile with ["Istio core" "Istiod" "Ingress gateways" "Egress gateways"] components into the cluster. Proceed? (y/N) y
✔ Istio core installed                                                                                                                                                                                                                      
✔ Istiod installed                                                                                                                                                                                                                          
✔ Ingress gateways installed                                                                                                                                                                                                                
✔ Egress gateways installed                                                                                                                                                                                                                 
✔ Installation complete                                                                                                                                                                                                                     
Making this installation the default for injection and validation.

安装 Istio 命令的基础上增加 --set values.global.proxy.includeIPRanges="10.0.0.1/24"

访问外部服务

由于绕行配置仅影响新的部署,因此您需要按照开始之前部分中的说明重新部署 sleep 程序。

在更新 istio-sidecar-injector configmap 和重新部署 sleep 程序后,Istio sidecar 将仅拦截和管理集群中的内部请求。 任何外部请求都会绕过 Sidecar,并直接到达其预期的目的地。举个例子:

kubectl exec "$SOURCE_POD" -c sleep -- curl -sS http://httpbin.org/headers

 


[root@k8s-master01 istio-1.17.1]# kubectl exec -it $SOURCE_POD -c sleep -- curl -I https://www.126.com | grep  "HTTP/"
HTTP/2 20

与通过 HTTP 和 HTTPS 访问外部服务不同,你不会看到任何与 Istio sidecar 有关的请求头, 并且发送到外部服务的请求既不会出现在 Sidecar 的日志中,也不会出现在 Mixer 日志中。 绕过 Istio sidecar 意味着你不能再监视对外部服务的访问。

清除对外部服务的直接访问

更新配置,以针对各种 IP 停止绕过 sidecar 代理:

[root@k8s-master01 istio-1.17.1]# istioctl manifest apply --set profile=demo
This will install the Istio 1.17.1 demo profile with ["Istio core" "Istiod" "Ingress gateways" "Egress gateways"] components into the cluster. Proceed? (y/N) y
✔ Istio core installed                                                                                                                                                                                                                      
✔ Istiod installed                                                                                                                                                                                                                          
✔ Egress gateways installed                                                                                                                                                                                                                 
✔ Ingress gateways installed                                                                                                                                                                                                                
✔ Installation complete                                                                                                                                                                                                                     
Making this installation the default for injection and validation.