Is it possible to "unify" the endpoints of single services running in kubernetes? For example I've two services:
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
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.
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.