跳转至

istio envoy 访问外部服务

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

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

  • 允许 Envoy 代理将请求传递到网格内未配置的服务。
  • 配置服务条目以提供对外部服务的受控访问。
  • 完全绕过特定范围 IP 的 Envoy 代理。

  ServiceEntry允许在 Istio 的内部服务注册表中添加额外条目,以便网格中自动发现的服务可以访问/路由到这些手动指定的服务。服务条目描述服务的属性(DNS 名称、VIP、端口、协议、端点)。这些服务可以是网格外部的(例如,Web API),也可以是网格内部的、不属于平台服务注册表的服务(例如,与 Kubernetes 中的服务通信的一组 VM)。此外,还可以使用字段动态选择服务条目的端点workloadSelector。这些端点可以是使用对象或 Kubernetes pod 声明的 VM 工作负载WorkloadEntry。在单个服务下同时选择 pod 和 VM 的能力允许将服务从 VM 迁移到 Kubernetes,而无需更改与服务关联的现有 DNS 名称。

1、开启envoy访问日志两种方式

1.1、使用遥测 API

apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
  name: mesh-default
  namespace: istio-system
spec:
  accessLogging:
    - providers:
      - name: envoy

1.2、使用 Mesh Config

spec:
  meshConfig:
    accessLogFile: /dev/stdout

这个是需要重启istio的组件的。

或者安装istio时配置
istioctl install <flags-you-used-to-install-Istio> --set meshConfig.accessLogFile=/dev/stdout

1.3、访问

kubectl logs -f pod/service-a-69f778dfcd-8pk8j -c istio-proxy
[2024-11-03T07:34:06.206Z] "GET /api/v1/testA/ HTTP/1.1" 200 - via_upstream - "-" 0 151 27 27 "192.168.65.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36" "627589cd-72ac-9ead-b2b3-41ee9d0e0fbb" "service-a.localserver.com" "10.1.3.49:8000" inbound|8000|| 127.0.0.6:32855 10.1.3.49:8000 192.168.65.3:0 invalid:outbound_.8000_._.service-a.default.svc.cluster.local default

2、istio外部服务处理配置

Istio 有一个安装选项, meshConfig.outboundTrafficPolicy.mode,用于配置外部服务(即未在 Istio 的内部服务注册表中定义的服务)的 sidecar 处理。

如果将此选项设置为ALLOW_ANY,Istio 代理将允许对未知服务的调用通过。

如果将选项设置为REGISTRY_ONLY,则 Istio 代理将阻止任何没有 HTTP 服务或网格内未定义服务条目的主机。

ALLOW_ANY是默认值,允许您快速开始评估 Istio,而无需控制对外部服务的访问。

meshConfig.outboundTrafficPolicy.mode除非您看到带有值的明确设置REGISTRY_ONLY,否则您可以确定该选项设置为ALLOW_ANY,这是唯一其他可能的值和默认值:

kubectl get configmap istio -n istio-system -o yaml

这种访问外部服务的简单方法的缺点是,您会失去 Istio 对外部服务流量的监控和控制。

3、ALLOW_ANY访问外部服务

kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- curl -sSI https://www.google.com | grep  "HTTP/"; kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- curl -sI https://edition.cnn.com | grep "HTTP/"

HTTP/2 200 
HTTP/2 200
envoy日志:
[2024-11-03T09:26:15.360Z] "- - -" 0 - - - "-" 892 5627 2082 - "-" "-" "-" "-" "31.13.68.169:443" PassthroughCluster 10.1.3.61:57098 31.13.68.169:443 10.1.3.61:57086 - -
[2024-11-03T09:26:17.891Z] "- - -" 0 - - - "-" 837 6188 573 - "-" "-" "-" "-" "151.101.195.5:443" PassthroughCluster 10.1.3.61:41908 151.101.195.5:443 10.1.3.61:41900 - -

3-1
无ServiceEntry

4、REGISTRY_ONLY外部访问模式

4.1、配置

将meshConfig.outboundTrafficPolicy.mode选项更改为REGISTRY_ONLY。

spec:
  meshConfig:
    outboundTrafficPolicy:
      mode: REGISTRY_ONLY
否则,请将等效设置添加到原始istioctl install命令,例如:
istioctl install <flags-you-used-to-install-Istio> \
                   --set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY
配置完了如果没有生效可能需要重启istio组件
kubectl delete pod -l istio=pilot -n istio-system
kubectl delete pod -l istio=ingressgateway -n istio-system
kubectl delete pod -l istio=egressgateway -n istio-system

4.2、验证效果

发现没有配置服务条目的无法访问。

vv@localhost istio-1.23.2 % kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- curl -sSI https://www.google.com | grep  "HTTP/"; kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- curl -sI https://edition.cnn.com | grep "HTTP/"

curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to www.google.com:443 
command terminated with exit code 35
command terminated with exit code 35

5、访问外部http服务

5.1、创建ServiceEntry

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: httpbin-ext
spec:
  hosts:
  - httpbin.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
  location: MESH_EXTERNAL
EOF

5.2、访问

kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- curl -sS http://httpbin.org/headers
5-2
有ServiceEntry

检查 sidecar 代理的日志:

kubectl logs -f pod/sleep-5577c64d7c-8zln9 -c istio-proxy
[2024-11-03T15:30:47.911Z] "GET /headers HTTP/1.1" 200 - via_upstream - "-" 0 980 707 706 "-" "curl/8.10.1" "fe4df2bc-cf84-990c-a870-8e68b1380541" "httpbin.org" "52.6.108.150:80" outbound|80||httpbin.org 10.1.3.61:47086 52.6.108.150:80 10.1.3.61:47084 - default

6、访问外部https服务

6.1、创建ServiceEntry

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: google
spec:
  hosts:
  - www.google.com
  ports:
  - number: 443
    name: https
    protocol: HTTPS
  resolution: DNS
  location: MESH_EXTERNAL
EOF

6.2、访问

kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- curl -sSI https://www.google.com | grep  "HTTP/"
HTTP/2 200

sidecar代理日志

[2024-11-04T02:55:43.908Z] "- - -" 0 - - - "-" 892 5630 562 - "-" "-" "-" "-" "31.13.112.9:443" outbound|443||www.google.com 10.1.3.73:42256 31.13.112.9:443 10.1.3.73:42240 www.google.com -

6-2
有ServiceEntry https

7、管理外部服务流量

与集群间请求类似,也可以为使用ServiceEntry配置访问的外部服务配置路由规则。

访问:

 kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- time curl -o /dev/null -sS -w "%{http_code}\n" http://httpbin.org/delay/5

200
real    0m 5.74s
user    0m 0.00s
sys     0m 0.00s

通过vs配置对外部服务的调用3秒超时:

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

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

kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- time curl -o /dev/null -sS -w "%{http_code}\n" http://httpbin.org/delay/5

504
real    0m 3.02s
user    0m 0.00s
sys     0m 0.00s

8、出口tls发起-sidecar发起

原始流量为 HTTP,而 Istio 将打开到外部服务的 HTTPS 连接。

8.1、配置对外部服务的访问

8.1.1、创建ServiceEntry

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: edition-cnn-com
spec:
  hosts:
  - edition.cnn.com
  ports:
  - number: 80
    name: http-port
    protocol: HTTP
  - number: 443
    name: https-port
    protocol: HTTPS
  resolution: DNS
EOF

8.1.2、访问

kubectl exec pod/sleep-5577c64d7c-8zln9 -c sleep -- curl -sSL -o /dev/null -D - http://edition.cnn.com/politics|grep "HTTP"
HTTP/1.1 301 Moved Permanently
HTTP/2 200 

sidecar代理日志:

http

[2024-11-04T04:25:18.079Z] "GET /politics HTTP/1.1" 301 - via_upstream - "-" 0 0 341 341 "-" "curl/8.10.1" "76d4fe81-18ea-9c99-92d4-f574bf10530f" "edition.cnn.com" "151.101.195.5:80" outbound|80||edition.cnn.com 10.1.3.73:47300 151.101.195.5:80 10.1.3.73:47288 - default
[2024-11-04T04:25:18.429Z] "- - -" 0 - - - "-" 874 2924478 976 - "-" "-" "-" "-" "151.101.131.5:443" outbound|443||edition.cnn.com 10.1.3.73:38346 151.101.195.5:443 10.1.3.73:38656 edition.cnn.com -

https

[2024-11-04T04:27:14.255Z] "- - -" 0 - - - "-" 874 2925623 1330 - "-" "-" "-" "-" "151.101.3.5:443" outbound|443||edition.cnn.com 10.1.3.73:34780 151.101.67.5:443 10.1.3.73:41362 edition.cnn.com -
http发生了两次请求,如果改成https则是一次。

尽管curl命令透明地处理了重定向,但这里存在两个问题:

  • 第一个问题是冗余请求,这会使获取 内容的延迟加倍http://edition.cnn.com/politics。
  • 第二个问题是 URL 的路径(在本例中为politics)以明文形式发送。

8.2、出口流量tls发起

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: edition-cnn-com
spec:
  hosts:
  - edition.cnn.com
  ports:
  - number: 80
    name: http-port
    protocol: HTTP
    targetPort: 443
  - number: 443
    name: https-port
    protocol: HTTPS
  resolution: DNS
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: edition-cnn-com
spec:
  host: edition.cnn.com
  trafficPolicy:
    portLevelSettings:
    - port:
        number: 80
      tls:
        mode: SIMPLE # initiates HTTPS when accessing edition.cnn.com
EOF

9、通配符主机-sidecar发起

请求直接从sidecar调用服务,不通过出口网关。

这种方式容易被绕过,使用出口网关引导流量更安全。

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: wikipedia
spec:
  hosts:
  - "*.wikipedia.org"
  ports:
  - number: 443
    name: https
    protocol: HTTPS
EOF
kubectl exec sleep-5577c64d7c-8zln9 -c sleep -- sh -c 'curl -s https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"; curl -s https://de.wikipedia.org/wiki/Wikipedia:Hauptseite | grep -o "<title>.*</title>"'

<title>Wikipedia, the free encyclopedia</title>
<title>Wikipedia  Die freie Enzyklopädie</title>

10、典型应用

forecast服务对外部www服务的访问被本地的sidecar拦截。 通过serviceEntry访问网格外的服务

对外部服务的访问必须经过一个对外的egress代理的场景,因为只有这个节点有对外的ip或者这个节点是统一的安全出口等。 经过统一的出口


本文阅读量  次

评论