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

时间:2016-05-14 01:22:28

标签: kubernetes

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

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

这表明我应该:

  1. serviceX中定义namespaceA服务,没有选择器(因为我要选择的POD不在namespaceA中)。
  2. serviceX中定义服务(我也称为namespaceB),然后
  3. namespaceA中定义端点对象,使其指向serviceX中的namespaceB
  4. 这是我无法完成的第三步。

    首先,我尝试用这种方式定义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字段是强制性的。因此,我的下一次尝试是将固定的ClusterIP地址分配给serviceX中的namespaceB,并将其放入IP字段中(请注意service_cluster_ip_range配置为192.168.0.0/16,并192.168.1.1已将serviceX分配为namespaceBserviceX的ClusterIP; namespaceA中的192.168.0.0/16已在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 子网上自动分配了不同的ClusterIP :

    serviceX

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

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

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

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

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

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

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

4 个答案:

答案 0 :(得分:120)

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

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

您可以使用该DNS名称在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

答案 1 :(得分:2)

要访问两个不同名称空间中的服务,可以使用如下网址:

HTTP://<your-service-name>.<namespace-with-that-service>.svc.cluster.local

要列出所有名称空间,可以使用:

kubectl get namespace

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

kubectl get services -n <namespace-name>

这将为您提供帮助。

答案 2 :(得分:1)

您可以通过在比命名空间服务更高的层(例如服务负载均衡器https://github.com/kubernetes/contrib/tree/master/service-loadbalancer)上部署某些内容来实现此目的。如果要将其限制为单个命名空间,请使用“--namespace = ns”参数(默认为所有命名空间:https://github.com/kubernetes/contrib/blob/master/service-loadbalancer/service_loadbalancer.go#L715)。这适用于L7,但对于L4来说有点乱。

答案 3 :(得分:1)

这很简单

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

它将类似于:servicename.namespacename.svc.cluster.local

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

对于

kind: Service
apiVersion: v1
metadata:
  name: service
spec:
  type: ExternalName
  externalName: <servicename>.<namespace>.svc.cluster.local

在这里用适当的值替换<servicename><namespace>

在kubernetes中,名称空间用于创建虚拟环境,但它们彼此连接。