我一直在尝试找到一种方法来在一个命名空间中定义一个服务,该服务链接到在另一个命名空间中运行的 Pod。我知道 Pod 中运行的容器可以通过在集群 DNS 中引用它namespaceA来访问serviceX定义的. 也就是说,我希望代码只是查找然后能够访问它。namespaceB``serviceX.namespaceB.svc.cluster.local``serviceX``serviceX
namespaceA
serviceX
namespaceB``serviceX.namespaceB.svc.cluster.local``serviceX``serviceX
Kubernetes文档表明这是可能的。它说您定义没有选择器的服务的原因之一是 您希望将您的服务指向另一个命名空间或另一个集群中的服务 。
这表明我应该:
namespaceB
这是我无法完成的第三步。
首先,我尝试以这种方式定义 Endpoints 对象:
kind: Endpoints apiVersion: v1 metadata: name: serviceX namespace: namespaceA subsets: - addresses: - targetRef: kind: Service namespace: namespaceB name: serviceX apiVersion: v1 ports: - name: http port: 3000
这似乎是合乎逻辑的方法, 显然 是为了什么targetRef。但是,这导致了一个错误,指出数组中的ip字段addresses是强制性的。所以,我的下一个尝试是为 in 分配一个固定的 ClusterIP 地址serviceX,namespaceB并将其放在 IP 字段中(请注意,service_cluster_ip_range配置为192.168.0.0/16,192.168.1.1并被分配为serviceXin的 ClusterIP namespaceB;serviceX在子网上namespaceA自动分配了一个不同的 ClusterIP 192.168.0.0/16) :
targetRef
ip
addresses
service_cluster_ip_range
192.168.0.0/16
192.168.1.1
kind: Endpoints apiVersion: v1 metadata: name: serviceX namespace: namespaceA subsets: - addresses: - ip: 192.168.1.1 targetRef: kind: Service namespace: namespaceB name: serviceX apiVersion: v1 ports: - name: http port: 3000
serviceX这被接受了,但是对in 的访问namespaceA没有被转发到 Pod in namespaceB- 他们超时了。查看 iptables 设置,看起来它必须执行两次 NAT 预路由才能完成此操作。
我发现唯一可行但不是一个令人满意的解决方案的唯一方法是查找提供的 Pod 的实际 IP 地址,serviceX并将namespaceB该地址放在 Endpoints 对象中namespaceA。当然,这并不令人满意,因为 Pod IP 地址可能会随着时间而改变。这就是服务 IP 要解决的问题。
那么,有没有一种方法可以满足文档的承诺,即我可以将一个命名空间中的 服务 指向在不同命名空间中运行的服务?
一位评论者质疑您为什么要这样做 - 这是一个对我来说有意义的用例,至少:
假设您有一个多租户系统,其中还包括一个可以在租户之间共享的通用数据访问功能。现在想象一下,这个数据访问函数有不同风格的通用 API,但性能特征不同。一些租户可以访问其中一个,其他租户可以访问另一个。
每个租户的 pod 都在自己的命名空间中运行,但每个人都需要访问这些常见的数据访问服务之一,这些服务必然位于另一个命名空间中(因为它由多个租户访问)。但是,如果他们的订阅发生更改以访问性能更高的服务,您不希望租户必须更改他们的代码。
一个潜在的解决方案(我能想到的最简洁的解决方案,如果它有效的话)是在每个租户的数据访问服务的命名空间中包含一个服务定义,每个服务定义都针对适当的端点进行配置。该服务定义将被配置为指向每个租户有权使用的正确数据访问服务。
我偶然发现了同样的问题,并找到了一个不需要任何静态 ip 配置的好解决方案:
您可以通过它的DNS 名称(如您所提到的)访问服务: servicename.namespace.svc.cluster.local
您可以使用该 DNS 名称通过本地服务在另一个命名空间中引用它:
kind: Service apiVersion: v1 metadata: name: service-y namespace: namespace-a spec: type: ExternalName externalName: service-y.namespace-b.svc.cluster.local ports: - port: 80