Unify service endpoints in kubernetes

9/15/2019

Is it possible to "unify" the endpoints of single services running in kubernetes? For example I've two services:

  1. User
  2. Post

Both services are exposed using it's own port. E.g.: http://localhost:30888/api/user and http://localhost:30884/api/post.

Now I want a single interface like this:

http://localhost:8080/api/user and http://localhost:8080/api/post. How can I configure this?

The services are exposed using this:

apiVersion: v1
kind: Service
metadata:
  name: post-service
  labels:
    app: post-service
spec:
  type: NodePort
  ports:
    - port: 44884
      nodePort: 30884
  selector:
    app: post
-- BendEg
kubernetes
routing
service

2 Answers

9/15/2019

It sounds like you're looking to add an Ingress on top of your Services. Ingresses can do a bunch of things including send traffic to different Services based on paths.

An Ingress to get you started might look something like:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  rules:
  - http:
      paths:
      - path: /api/user
        backend:
          serviceName: post-service
          servicePort: 44884
      - path: /api/post
        backend:
          serviceName: user-service
          servicePort: 33883 # Or whatever port your user-service is using

Behind the scenes, what makes an Ingress work varies depending on how you're running your Kubernetes cluster. For example, if you're using GKE, an Ingress is actually implemented as an HTTP load balancer. If you're using EKS, it's implemented as an Application load balancer. Each load balancer has lots of features and options, but the big one you should know about before starting anything is they will cost additional money on top of running your cluster.

Edit:

As prometherion mentioned in the comments, Ingresses allow traffic from outside of your cluster. If you're running a publicly-exposed website of some type, this is probably what you want. However, if these are internal endpoints that should not be exposed to the outside world, you might want to investigate service meshes from prometherion's answer instead.

-- supersam654
Source: StackOverflow

9/15/2019

Actually, using Kubernetes default resources, it's not possible: you have to use an available Service Mesh like Istio, Maesh or Linkerd or using a simple proxy according to your preferred flavor (NGINX, HAproxy or a simple GoLang application using http/net standard library).

I'm not a big expert of Istio (that's actually one of most used Service Mesh aroud available) but probably the VirtualService could do the trick, along with DestinationRule resources.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews-route
spec:
  hosts:
  - you-service.your-namespace.svc.cluster.local
  http:
  - name: user-v1-routes
    match:
    - uri:
        prefix: "/api/user"
    route:
    - destination:
        host: user-service.your-namespace.svc.cluster.local
        subset: v1
  - name: post-v1-route
    route:
    - destination:
        host: post-service.your-namespace.svc.cluster.local
        subset: v1
    match:
    - uri:
        prefix: "/api/post"
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: user-destination
spec:
  host: user-service.yout-namespace.svc.cluster.local
  subsets:
  - name: v1
    labels:
      version: v1
      app: user
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: post-destination
spec:
  host: post-service.yout-namespace.svc.cluster.local
  subsets:
  - name: v1
    labels:
      version: v1
      app: post

YMMV and the YAMLs are just explanatory.

-- prometherion
Source: StackOverflow