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

Is there a way to proxy calls to an ExternalName service thanks to an Istio VirtualService?

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

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

到目前为止,还不错。当我请求 'connector' DNS 时,我成功命中了外部名称,即 gateway.eventing.svc.cluster.local.

现在,我想将 headers 添加到发送到连接器 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 仍然没有被调用。这是为什么?有办法实现吗?

如果没有,我能做些什么来在给定的命名空间中别名(即测试)位于另一个(即事件)中的服务并通过 Istio VirtualService 代理 http 请求?

在此先感谢您的帮助!

编辑:

Sidecar 注入已启用namespace-wide(即测试)

更新

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

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

原文Post(略有修改)

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

为了添加自定义 header,您可以使用类型为 luaEnvoyFilter,它应用于发件人的 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 对服务入口连接器的每个请求,并在完成任何其他操作之前添加自定义 header。

因此,事实证明,使它正常工作所缺少的只是在 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 提供的答案也有效,但不幸的是过于冗长,无法标记为我的首选答案。