位于另一个命名空间中的服务

g6ll5ycj  于 2022-09-20  发布在  Kubernetes
关注(0)|答案(6)|浏览(215)

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

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

在我看来,我应该:

1.在namespaceA中定义一个serviceX服务,不带选择器(因为我要选择的POD不在namespaceA中)。
1.在namespaceB中定义一个服务(我也叫serviceX),然后
1.在namespaceA中定义终结点对象,以指向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分配一个固定的集群IP地址,并将其放入IP字段(请注意,service_cluster_ip_range被配置为192.168.0.0/16192.168.1.1被分配为namespaceBserviceX的集群IP;namespaceA中的serviceX被自动分配了192.168.0.0/16子网上的不同集群IP):

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要解决的问题。

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

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

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

每个租户的Pod在其自己的名称空间中运行,但是每个租户都需要访问这些公共数据访问服务之一,该服务必须位于另一个名称空间中(因为它被多个租户访问)。但是,如果租户为了访问性能更高的服务而更改了订阅,您不会希望租户必须更改代码。

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

vbkedwbf

vbkedwbf1#

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

您可以通过DNS name访问服务(如您所说):servicename.nampace.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
w1jd8yoj

w1jd8yoj2#

做这件事太简单了。

如果您想要将其用作主机并希望解析它,

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

Use : <service name>
            Use : <service.name>.<namespace name>
            Not : <service.name>.<namespace name>.svc.cluster.local

例如,servicename.namespacename.svc.cluster.local

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

服务示例:

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

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

在Kubernetes中,命名空间用于创建虚拟环境,但所有命名空间都通过特定的DNS约定相互连接。

ncgqoxb0

ncgqoxb03#

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

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

要列出可以使用的所有命名空间,请执行以下操作:

kubectl get namespace

对于该命名空间中的服务,您只需使用:

kubectl get services -n <namespace-name>

这会对你有帮助。

voase2hg

voase2hg4#

使用无头服务跨多个命名空间访问服务

实际上,我发现headless service可以从多个名称空间访问,而不需要做太多的工作。如果你想走无头服务之路,那么就按如下方式转换你的服务:

apiVersion: v1
kind: Service
metadata:
  name: nfs-server-svc
  namespace: nfs-server
spec:
  clusterIP: None
  ports:
  - name: nfs
    port: 2049
    targetPort: nfs
    protocol: TCP
  - name: rpcbind
    port: 111
    targetPort: rpcbind
  - name: mountd
    port: 20048
    targetPort: mountd
  selector:
    app: nfs-server-app
  type: ClusterIP

现在,您可以ssh到任何名称空间中的任何容器,并ping <service.name>.<namespace><service.name>.<namespace>.svc<service.name>.<namespace>.svc.cluster.local。他们都下定决心。示例:

kubectl -n nfs-server exec -it my-web-deployment-68976cb578-f9v8t -- bash
bash-5.1# ping nfs-server-svc-svc.nfs-server.svc.cluster.local
PING uoe-api-v6-nfs-svc.uoe-api-v6.svc (10.244.2.176): 56 data bytes
64 bytes from 10.244.2.176: seq=0 ttl=62 time=0.877 ms
64 bytes from 10.244.2.176: seq=1 ttl=62 time=0.983 ms
64 bytes from 10.244.2.176: seq=2 ttl=62 time=0.956 ms
^C
--- nfs-server-svc-svc.nfs-server.svc.cluster.local ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.877/0.938/0.983 ms
bash-5.1#

Nfs-server-svc-svc.nfs-server.svc.cluster.local

注:我使用的是带有默认设置的法兰绒网络插件,K8S v1.24.4版,并确保您的容器安装了ping。

gt0wga4j

gt0wga4j5#

您可以通过在名称空间服务之外的更高层部署一些东西来实现这一点,比如服务负载均衡器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有点混乱。

0ejtzxu1

0ejtzxu16#

在花了一些时间尝试在EKS中实现这一点后,我发现了一个可能对未来其他人有用的解决方案。

作为EKS doesnt support External names,解决方案是在您拥有服务的每个命名空间中创建入口,并通过向IngressGroups的每个入口添加注解来使所有入口使用相同的负载均衡器,如下所示:
Alb.ingress.kubernetes.io/group.name:my-group

有关更多详细信息,请访问this link并搜索:使用IngressGroups跨多个入口资源共享应用程序负载均衡器

相关问题