kubernetes:服务位于另一个名称空间中

Dav*_*ley 75 kubernetes

我一直在尝试找到一种方法来在一个命名空间中定义一个服务,该命名空间链接到另一个命名空间中运行的Pod.我知道在"namespaceA"中运行的Pod中的容器可以通过在集群DNS中将其引用为"serviceX.namespaceB.svc.cluster.local"来访问"namespaceB"中定义的"serviceX",但我宁愿没有代码容器内部需要知道"serviceX"的位置.也就是说,我希望代码只是查找"serviceX"然后才能访问它.

Kubernetes文档表明这是可能的.它表示您在没有选择器的情况下定义服务的原因之一是" 您希望将服务指向另一个名称空间或另一个集群中的服务".

这告诉我,我应该:

  1. 在"namespaceA"中定义"serviceX"服务,没有选择器(因为我想要选择的POD不在"namespaceA"中).
  2. 在"namespaceB"中定义一个服务(我也称之为"serviceX"),然后
  3. 在"namespaceA"中定义一个Endpoints对象,指向"namespaceB"中的"serviceX".

这是我无法完成的第三步.

首先,我尝试以这种方式定义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
Run Code Online (Sandbox Code Playgroud)

这似乎是合乎逻辑的方法,"显然"是"targetRef"的用途.但是,这导致了一个错误,即"地址"数组中的"ip"字段是强制性的.因此,我的下一个尝试是将"固定的ClusterIP地址"分配给"namespaceB"中的"serviceX",并将其放在IP字段中(请注意,service_cluster_ip_range配置为192.168.0.0/16,并且192.168.1.1被指定为ClusterIP用于"namespaceB"中的"serviceX";"namespaceA"中的"serviceX"在192.168.0.0/16子网上自动分配了不同的ClusterIP:

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
Run Code Online (Sandbox Code Playgroud)

这已被接受,但是对"namespaceA"中的"serviceX"的访问没有被转发到"namespaceB"中的Pod - 它们超时了.看看iptables设置,看起来它必须做两次NAT预路由才能完成.

我找到的唯一有用 - 但不是一个令人满意的解决方案 - 是查找在"namespaceB"中提供"serviceX"的Pod的实际IP地址,并将该地址放在"namespaceA"中的Endpoints对象中.当然,这并不令人满意,因为Pod IP地址可能会随着时间而改变.这就是服务IP需要解决的问题.

那么,有没有办法满足文档的承诺,我可以将一个命名空间中的服务指向运行在不同命名空间中的服务

一位评论者质疑你为什么要这样做 - 这是一个对我有意义的用例,至少:

假设您有一个多租户系统,该系统还包括可在租户之间共享的通用数据访问功能.现在想象一下,这种数据访问功能与常见的API有不同的风格,但性能特征不同.有些租户可以访问其中一个,其他租户可以访问另一个.

每个租户的pod都在自己的命名空间中运行,但每个人都需要访问其中一个常见的数据访问服务,这些服务必然位于另一个命名空间中(因为它可以被多个租户访问).但是,如果他们的订阅更改为访问性能更高的服务,您不希望租户必须更改其代码.

一个潜在的解决方案(我能想到的最干净的解决方案,如果它只能工作)是在每个租户的数据访问服务的命名空间中包含一个服务定义,每个服务定义都配置用于适当的端点.此服务定义将配置为指向每个租户有权使用的正确数据访问服务.

Pau*_*aul 159

我偶然发现了同样的问题并找到了一个不需要任何静态ip配置的好解决方案:

您可以通过它的DNS名称(如您所述)访问服务:servicename.namespace.svc.cluster.local

您可以使用该DNS名称通过本地服务另一个名称空间中引用它:

kind: Service
apiVersion: v1
metadata:
  name: service-y
  namespace: namespace-a
spec:
  type: ExternalName
  externalName: service-x.namespace-b.svc.cluster.local
  ports:
  - port: 80
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的解决方案!当我最初提出问题时,我不确定“ExternalName”类型是否可用于服务,但现在支持它,并且巧妙地解决了问题。谢谢,保罗。 (2认同)
  • 是的,它确实。它适用于一个Pod与另一个命名空间中的服务进行通信,但不适用于入口负载平衡器。 (2认同)

Har*_*var 26

做起来很简单

如果您想将其用作主机并想解决它

如果您使用大使到位于另一个命名空间中的服务的任何其他 API 网关,则始终建议使用:

            Use : <service name>
            Use : <service.name>.<namespace name>
            Not : <service.name>.<namespace name>.svc.cluster.local
Run Code Online (Sandbox Code Playgroud)

它会像: servicename.namespacename.svc.cluster.local

这将向您提到的命名空间内的特定服务发送请求。

例子:

kind: Service
apiVersion: v1
metadata:
  name: service
spec:
  type: ExternalName
  externalName: <servicename>.<namespace>.svc.cluster.local
Run Code Online (Sandbox Code Playgroud)

此处将<servicename>和替换为<namespace>适当的值。

在 Kubernetes 中,命名空间用于创建虚拟环境,但所有命名空间都相互连接。

  • SO 的一个方便技巧是在答案中添加评论并进行必要的澄清。 (12认同)
  • 您能否解释一下这个答案与保罗两年前提供的答案有何不同? (7认同)
  • 我将其称为最佳解决方案,因为默认情况下支持“.svc.cluster.local”用于内部解析服务。 (4认同)
  • 我不明白你的第一个代码块在说什么。似乎是说您“不应该”使用完全限定的“&lt;service.name&gt;.&lt;namespace.name&gt;.svc.cluster.local”,但应该使用“&lt;service.name&gt;”或“&lt;service.name” &gt;.&lt;namespace.name&gt;` 代替?但接着又说你“应该”使用完全合格的吗? (3认同)
  • @Oliver 没有区别,但我只是指定了在特定位置替换服务名称和命名空间的内容。虽然他使用了命名空间-a,所以我看起来很困惑。 (2认同)

Dev*_*esh 13

要访问两个不同命名空间中的服务,您可以像这样使用 url:

HTTP://<your-service-name>.<namespace-with-that-service>.svc.cluster.local
Run Code Online (Sandbox Code Playgroud)

要列出您可以使用的所有命名空间:

kubectl get namespace
Run Code Online (Sandbox Code Playgroud)

对于该命名空间中的服务,您可以简单地使用:

kubectl get services -n <namespace-name>
Run Code Online (Sandbox Code Playgroud)

这会帮助你。