由于 Istio VirtualService,有没有办法代理对 ExternalName 服务的调用?

Posted

技术标签:

【中文标题】由于 Istio VirtualService,有没有办法代理对 ExternalName 服务的调用?【英文标题】:Is there a way to proxy calls to an ExternalName service thanks to an Istio VirtualService? 【发布时间】:2020-10-08 09:47:47 【问题描述】:

在我目前正在进行的一个项目中,我想为位于另一个命名空间中的 Kubernetes 服务创建一个 DNS 别名。为此,我创建了一个 ExternalName 服务,如下所示:

kind: Service
apiVersion: v1
metadata:
  name: connector
  namespace: test
spec:
  type: ExternalName
  externalName: gateway.eventing.svc.cluster.local

到目前为止,一切都很好。当我请求“连接器”DNS 时,我成功点击了外部名称,即 gateway.eventing.svc.cluster.local。

现在,我想为发送到连接器 ExternalName 服务的所有 http 请求添加标头,因此我创建了一个 Istio VirtualService 来执行此操作:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: connector
  namespace: test
spec:
  hosts:
    - connector
    - connector.test.svc.cluster.local
 http:
   - match:
      - uri:
          prefix: /
      route:
        - destination:
            host: connector
            port:
              number: 80
#headers config ignored for brevity

问题是永远不会调用 VirtualService。似乎它不会拦截对连接器 DNS 或其完全限定名称(即 connector.test.svc.cluster.local)发出的请求。

阅读文档后,我认为这是因为 Istio VirtualService 检查服务注册表,而 ExternalName 服务不是其中的一部分,它只是某种 DNS 别名。

因此,我尝试创建一个 Istio ServiceEntry,如下所示:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: connector
  namespace: test
spec:
  hosts:
  - connector
  endpoints:
  - address: gateway.eventing.svc.cluster.local
  ports:
  - number: 80
    name: http
    protocol: HTTP
  location: MESH_INTERNAL
  resolution: DNS

它可以工作,我可以在 Kiali 中看到,在请求连接器时,它不是调用 PassthroughCluster,而是调用连接器 ServiceEntry,据我了解应该发生什么。

但是,我的连接器 VirtualService 仍然没有被调用。这是为什么?有办法实现吗?

如果没有,我可以做些什么来给给定命名空间中的别名(即测试)位于另一个(即事件)和代理 http 请求的服务,这要归功于 Istio VirtualService?

提前感谢您的帮助!

编辑:

在命名空间范围内启用 Sidecar 注入(即测试)

【问题讨论】:

【参考方案1】:

因此,事实证明,要使其正常工作,所缺少的只是在 ExternalName 服务上指定和命名端口。

这是更新后的 yaml:

kind: Service
apiVersion: v1
metadata:
  name: connector
  namespace: test
spec:
  type: ExternalName
  externalName: gateway.eventing.svc.cluster.local
  ports:
    - name: http
      port: 80

---

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: connector
  namespace: test
spec:
  hosts:
    - connector
    - connector.test.svc.cluster.local
 http:
   - match:
      - uri:
          prefix: /
      route:
        - destination:
            host: connector
            port:
              number: 80
#headers config ignored for brevity

命名端口是绝对需要,因为它让 Istio 知道要使用的应用程序协议,由 VirtualService 定义。

无需添加ServiceEntry,它会与VirtualService中指定的BYON主机一起工作。

请注意,@Christoph Raab 提供的答案也适用,但遗憾的是过于冗长,无法标记为我的首选答案。

【讨论】:

【参考方案2】:

更新

我没有看到缺少端口列表,并且不确定如何应用 yml,因为应该需要该列表。

无论如何,我留下我的答案。也许它会进一步帮助其他人。

原帖(稍作修改)

文档不清楚,但我认为标题操作可以由接收侧车完成。据我了解您的设置,ServiceEntry 背后的资源没有边车,所以如果这是真的,那么操作将不起作用。

要添加自定义标头,您可以使用 lua 类型的 EnvoyFilter,它应用于发送者的 sidecar,并且可以动态操纵流量。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: add-custom-header-filter
  namespace: test
spec:
  configPatches:
  - applyTo: CLUSTER
    match:
      context: SIDECAR_OUTBOUND
      cluster: 
        service: connector
    patch:
      operation: INSERT_BEFORE
      value: 
        name: envoy.lua
        typed_config:
          "@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
          inlineCode: |
            function envoy_on_request(request_handle)
              response_handle:logInfo("adding custom headers...""); 
              response_handle:headers():add("X-User-Header", "worked");
            end

此过滤器在出站时由命名空间test 中的每个sidecar 应用于服务入口连接器的每个请求,并在执行任何其他操作之前添加自定义标头。

【讨论】:

我明天上班时检查一下,同时感谢您的回答。但是,我想知道您对我的代码所说的内容... VirtualService 具有标头转换配置(路由->标头)...不能代替使用吗?在我的情况下,端口 80 上的流量甚至没有到达连接器 VirtualService(据我了解,它应该可以工作,即使在网格模式下,不是吗?),我可以通过故障注入来验证这一事实。此外,在文档中,他们确实说我应该能够使用 BYON 别名作为主机,但它似乎不起作用。 这是一个描述 BYON 别名的链接,即使没有 ServiceEntry,它也应该在网格模式下固有地在我的 VirtualService(仅在端口 80 上)上工作。就我而言,由于某种原因,如果我没有设置 ExternalName 服务或 ServiceEntry,我唯一的 VS 上的 Http 请求会给我一个 DNS 未解析异常。 github.com/istio/istio/issues/15567#issuecomment-517081181 对不起,我误会了。我以为您有标题匹配规则,而不是标题转换配置。是的,这也可以工作。您能否将其添加到问题中的代码中以进行澄清。问题可能是服务条目资源没有边车,因此您需要使用描述的特使过滤器。我用一些关于特使如何在你的情况下过滤的发现更新了我的答案。 您的建议似乎有效。然而,正如我的回答所说,我找到了一种让它以更简单的方式工作的方法。再次感谢您的时间。

以上是关于由于 Istio VirtualService,有没有办法代理对 ExternalName 服务的调用?的主要内容,如果未能解决你的问题,请参考以下文章

Istio系列学习----Istio的路由规则配置:VirtualService

Istio实战-路由规则配置:VirtualService

基于Istio版本的路由导致404

istio流量管理

Istio DestinationRule 目标规则

istio 0.8 TLS 简单测试