由于 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 服务的调用?的主要内容,如果未能解决你的问题,请参考以下文章