我一直在尝试找到一种方法来定义一个名称空间中的服务,该服务链接到在另一个名称空间中运行的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/16
,192.168.1.1
被分配为namespaceB
中serviceX
的集群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在其自己的名称空间中运行,但是每个租户都需要访问这些公共数据访问服务之一,该服务必须位于另一个名称空间中(因为它被多个租户访问)。但是,如果租户为了访问性能更高的服务而更改了订阅,您不会希望租户必须更改代码。
一个潜在的解决方案(我能想到的最干净的解决方案,如果它能工作的话)是在数据访问服务的每个租户的命名空间中包含一个服务定义,每个服务定义都为适当的端点进行配置。该服务定义将被配置为指向每个租户有权使用的适当数据访问服务。
6条答案
按热度按时间vbkedwbf1#
我偶然发现了同样的问题,并找到了一个不需要任何静态IP配置的很好的解决方案:
您可以通过DNS name访问服务(如您所说):servicename.nampace.svc.cluster.local
您可以使用该DNS名称通过本地服务在另一个命名空间中引用它:
w1jd8yoj2#
做这件事太简单了。
如果您想要将其用作主机并希望解析它,
如果您使用大使到位于另一个命名空间中的任何其他API网关进行服务,则始终建议您使用:
例如,
servicename.namespacename.svc.cluster.local
这将向您提到的命名空间内的特定服务发送请求。
服务示例:
在这里,用适当的值替换
<servicename>
和<namespace>
。在Kubernetes中,命名空间用于创建虚拟环境,但所有命名空间都通过特定的DNS约定相互连接。
ncgqoxb03#
要访问两个不同名称空间中的服务,您可以使用如下url:
要列出可以使用的所有命名空间,请执行以下操作:
对于该命名空间中的服务,您只需使用:
这会对你有帮助。
voase2hg4#
使用无头服务跨多个命名空间访问服务
实际上,我发现
headless service
可以从多个名称空间访问,而不需要做太多的工作。如果你想走无头服务之路,那么就按如下方式转换你的服务:现在,您可以ssh到任何名称空间中的任何容器,并ping
<service.name>.<namespace>
、<service.name>.<namespace>.svc
或<service.name>.<namespace>.svc.cluster.local
。他们都下定决心。示例:Nfs-server-svc-svc.nfs-server.svc.cluster.local
注:我使用的是带有默认设置的法兰绒网络插件,K8S v1.24.4版,并确保您的容器安装了ping。
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有点混乱。
0ejtzxu16#
在花了一些时间尝试在EKS中实现这一点后,我发现了一个可能对未来其他人有用的解决方案。
作为EKS doesnt support External names,解决方案是在您拥有服务的每个命名空间中创建入口,并通过向IngressGroups的每个入口添加注解来使所有入口使用相同的负载均衡器,如下所示:
Alb.ingress.kubernetes.io/group.name:my-group
有关更多详细信息,请访问this link并搜索:使用IngressGroups跨多个入口资源共享应用程序负载均衡器