本文介绍了服务位于另一个名称空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试找到一种方法来在一个名称空间中定义服务,该服务链接到在另一个名称空间中运行的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
 

这似乎是合乎逻辑的方法,并且显然 targetRef的作用是什么.但是,这导致一个错误,指出addresses数组中的ip字段是强制性的.因此,我的下一个尝试是为namespaceB中的serviceX分配一个固定的ClusterIP地址,并将其放在IP字段中(请注意,将service_cluster_ip_range配置为192.168.0.0/16,并且将192.168.1.1分配为在192.168.0.0/16子网中为namespaceB中的serviceX; namespaceA中的serviceX自动分配了另一个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
 

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

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

因此,有没有一种方法可以满足文档中的承诺,即我可以将一个命名空间中的服务指向在另一个命名空间中运行的 service ?

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

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

每个租户的Pod在各自的命名空间中运行,但是每个租户的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-x.namespace-b.svc.cluster.local
  ports:
  - port: 80
 

I have been trying to find a way to define a service in one namespace that links to a Pod running in another namespace. I know that containers in a Pod running in namespaceA can access serviceX defined in namespaceB by referencing it in the cluster DNS as serviceX.namespaceB.svc.cluster.local, but I would rather not have the code inside the container need to know about the location of serviceX. That is, I want the code to just lookup serviceX and then be able to access it.

The Kubernetes documentation suggests that this is possible. It says that one of the reasons that you would define a service without a selector is that You want to point your service to a service in another Namespace or on another cluster.

That suggests to me that I should:

  1. Define a serviceX service in namespaceA, without a selector (since the POD I want to select isn't in namespaceA).
  2. Define a service (which I also called serviceX) in namespaceB, and then
  3. Define an Endpoints object in namespaceA to point to serviceX in namespaceB.

It is this third step that I have not been able to accomplish.

First, I tried defining the Endpoints object this way:

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

That seemed the logical approach, and obviously what the targetRef was for. But, this led to an error saying that the ip field in the addresses array was mandatory. So, my next try was to assign a fixed ClusterIP address to serviceX in namespaceB, and put that in the IP field (note that the service_cluster_ip_range is configured as 192.168.0.0/16, and 192.168.1.1 was assigned as the ClusterIP for serviceX in namespaceB; serviceX in namespaceA was auto assigned a different ClusterIP on the 192.168.0.0/16 subnet):

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

That was accepted, but accesses to serviceX in namespaceA did not get forwarded to the Pod in namespaceB - they timed out. Looking at the iptables setup, it looks like it would have had to do NAT pre-routing twice to accomplish that.

The only thing I did find that worked - but is not a satisfactory solution - is to lookup the actual IP address of the Pod providing serviceX in namespaceB and put that address in the Endpoints object in namespaceA. That isn't satisfactory, of course, because the Pod IP address may change over time. That's the problem service IPs are there to solve.

So, is there a way to meet what seems to be the promise of the documentation that I can point a service in one namespace to a service running in a different namespace?

A commenter questioned why you would want to do this - here is a use case that makes sense to me, at least:

Say you have a multi-tenant system, which also includes a common data-access function that can be shared between tenants. Now imagine that there are different flavors of this data-access function with common APIs, but different performance characteristics. Some tenants get access to one of them, other tenants have access to another one.

Each tenant's pods run in their own namespaces, but each one needs to access one of these common data-access services, which will necessarily be in another namespace (since it is accessed by multiple tenants). But, you wouldn't want the tenant to have to change their code if their subscription changes to access the higher-performing service.

A potential solution (the cleanest one I can think of, if only it worked) is to include a service definition in each tenant's namespace for the data-access service, with each one configured for the appropriate endpoint. This service definition would be configured to point to the proper data-access service each tenant is entitled to use.

解决方案

I stumbled over the same issue and found a nice solution which does not need any static ip configuration:

You can access a service via it's DNS name (as mentioned by you): servicename.namespace.svc.cluster.local

You can use that DNS name to reference it in another namespace via a local service:

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

这篇关于服务位于另一个名称空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 22:35