1

I have a service "A" deployed in "X" namespace. "Z" service from "P" namespace, calls it on
svc-a.x.svc.cluster.local
I have to deploy staging of service "A" in Y namespace as well and I want to register these IPs under
svc-a.x.svc.cluster.local
Is there any way to do it? I want to the main service to select pods from different namespaces.

xyphan
  • 95
  • 2
  • 9
  • Are you trying to load balance across the pods from both namespaces? – Gari Singh Jan 12 '23 at 09:42
  • No. I simply want that if any service is calling `svc-a.x.svc.cluster.local`, that should land on pods of both namespace "X" and "Y" – xyphan Jan 12 '23 at 12:03
  • Maybe a poor choice of words as a Service is either going to load balance across pods or for a headless service return the addresses of the pods. But you really do want a single service which can route to backends in both namespaces. – Gari Singh Jan 12 '23 at 18:23
  • In our use case, yes. – xyphan Jan 13 '23 at 07:47
  • Service meshes (e.g. Istio, Linkerd) work well in these cases. – Gari Singh Jan 13 '23 at 08:21
  • I totally agree, we are trying to adopt that but it has high latency cost over http1.1 – xyphan Jan 16 '23 at 08:27
  • feel free to update the status of question, mark as accepted if any of below resolves your issue, or do upvote if found any one helpful. you can also write your own answer if found solution. – Harsh Manvar Feb 03 '23 at 04:33

3 Answers3

2

You can try using a Service without selectors with an EndPointSlice which refers to a Service from each namespace.

Create svc-a in namespace X which selects / points to pods in namespace X. The Service will be available at svc-a.x.svc.cluster.local.

Create svc-a in namespace Y which selects / points to pods in namespace Y. The Service will be available at svc-a.y.svc.cluster.local.

Create a svc-a in namespace Z without selectors.

apiVersion: v1
kind: Service
metadata:
  name: svc-a
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

The Service will be available at svc-a.z.svc.cluster.local.

Create an EndpointSlice in namespace Z with svc-a.x.svc.cluster.local and svc-a.y.svc.cluster.local as endpoints and attach it to svc-a:

apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
  name: svc-a
  labels:
    kubernetes.io/service-name: svc-a
addressType: FQDN
ports:
  - name: http
    protocol: TCP
    port: 80
endpoints:
  - addresses:
      - "svc-a.x.svc.cluster.local"
      - "svc-a.y.svc.cluster.local"

So now you'll have svc-a.z.svc.cluster.local available in any namespace pointing to backends in both the X and Y namespaces.

Gari Singh
  • 11,418
  • 2
  • 18
  • 41
  • That will get the job done, but will there be any added latency cost with this? as it's double mapping. – xyphan Jan 14 '23 at 09:09
  • Probably a bit of latency, although it should be negligible given it's low-level within the cluster. – Gari Singh Jan 14 '23 at 10:17
  • I tested this config, but the headless service is not listing any endpoints even though the endpoint slice is present and pointing to desired service endpoints. – xyphan Jan 19 '23 at 10:55
  • i think fqdn is not supported by kube-proxy internal service IP or loopback maybe i read somewhere. – Harsh Manvar Jan 20 '23 at 19:41
  • 1
    https://kubernetes.io/docs/concepts/services-networking/service/#custom-endpointslices – Harsh Manvar Jan 21 '23 at 08:30
0

You can use the ExternalName service type for this purpose. You can create new service which selects the pods from 'Y' namespace and use that service in 'A' by using the externalName.

Example: Assume new service name is 'svc-b' which is in Y namespace you can modify your 'A' service something like this

apiVersion: v1
kind: Service
metadata:
  name: svc-a
  namespace: X
spec:
  type: ExternalName
  externalName: svc-b.y.svc.cluster.local
  ports:
  - port: 80

Refer to this SO which helped in solving a similar issue.

  • How will it pick pods from it's own namespace? afaik ExternalName just routes to provided fqdn. – xyphan Jan 12 '23 at 12:02
0

As per Gari's suggestion i tried using the Endpoint slice but didn't work, looks like kube-proxy having an issue with internal virtual IP.

Note: The endpoint IPs must not be: loopback (127.0.0.0/8 for IPv4, ::1/128 for IPv6), or link-local (169.254.0.0/16 and 224.0.0.0/24 for IPv4, fe80::/64 for IPv6).

The endpoint IP addresses cannot be the cluster IPs of other Kubernetes Services, because kube-proxy doesn't support virtual IPs as a destination.

Created 3 namespace test-1, test-2, test-main

You can go with Endpoints instead. Sharing the YAML example below

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
  namespace: test-1
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 1
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  namespace: test-1
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-app
  namespace: test-2
spec:
  selector:
    matchLabels:
      run: hello-app
  replicas: 1
  template:
    metadata:
      labels:
        run: hello-app
    spec:
      containers:
      - name: hello-app
        image: gcr.io/google-samples/hello-app:1.0
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: hello-app
  namespace: test-2
  labels:
    run: hello-app
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
  selector:
    run: hello-app
---
apiVersion: v1
kind: Service
metadata:
  name: slice-svc
  namespace: test-main
spec:
  ports:
  - port: 80
    name: http
    targetPort: 80
  clusterIP: None
---
kind: Endpoints
apiVersion: v1
metadata:
  name: slice-svc
  namespace: test-main
subsets:
  - addresses:
      - ip: 10.102.24.29 #CluserIP of service nginx from namespace-1
      - ip: 10.99.216.222 #CluserIP of service my-app from namespace-2
    ports:
      - port: 80

Note : ClusterIP get change when you delete and re-create the service else it's stable to use when you don't have a better way to resolve the IP in DNS.

Harsh Manvar
  • 27,020
  • 6
  • 48
  • 102