Does Kubernetes allow multiple versions of same micro service (not Kubernetes service) to be deployed in a Kubernetes cluster at any given point in time?
So, let's say I have a micro-service "MyCalculator". I create a POD to host this service.
this is v1 of the "MyCalculator".
I need that as new versions of the services are created, Kubernetes cluster allows these services to be deployed in the cluster, like so.
"MyCalculatorKubeService"/v1
"MyCalculatorKubeService"/v2
...
"MyCalculatorKubeService"/vn
The idea here is dynamically allow new versions, and allow access to these versions through a convention specified above. In the example above, I am thinking that the "MyCalculatorKubeService" is a kubernetes service.
The unused versions get decommissioned over a period of time through a manual trigger after reviewing which services are not getting any traffic for say x days.
Thanks,
For this scenario you will have to maintain a separate pod for each versions you want to keep alive. Use ingress to create separate virtual paths to each version of your application
- host: example.com
http:
paths:
- backend:
serviceName: app-v1
servicePort: 80
path: /app/v1/
- backend:
serviceName: app-v2
servicePort: 80
path: /app/v2/
Posting this as Community Wiki as its extension of #Charlie's answer.
As it was mentioned in #Charlie's answer you can do it using Ingress.
There are some Ingress Controllers, however Kubernetes officially supports only two.
Kubernetes as a project currently supports and maintains GCE and nginx controllers.
If you would like to use Nginx Ingress on GKE you need to add annotation to your Ingress manifest.
annotations:
kubernetes.io/ingress.class: nginx
You could also use Nginx Ingress Rewrite annotation.
When you are using Ingress, your services can be NodePort or ClusterIP types.
Depends on your needs you can specify which path should redirect to which service but you can also use default backend if you provide some random path like on example below:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
backend:
serviceName: hello-world
servicePort: 60000
rules:
- http:
paths:
- path: /v1
backend:
serviceName: MyCalculatorKubeService/v1
servicePort: 60000
- path: /v2
backend:
serviceName: MyCalculatorKubeService/v2
servicePort: 80
If you would provide path like MyCalculatorKubeService/vasdsadsa it would redirect to default backend which is hello-world service in this case. It might be used in some workarounds.
Related
Hi i have a question when it comes to k8s and handling branches
my namespaces have the following :
an API deployment
a NodePort service mapping the port 3000 of the deployment to port 80
a postgres instance to serve as a DB (Not important for this problem)
an Ingress exposing all
I would like to find a way that would make it able to :
When creating a new Branch, it makes my backend accessible to api.BRANCH_NAME.domain.com
I'm not able to find any documentation helping, I've tried a lot of things so far but cannot make it work
Here's a repo to see what I have so far : https://github.com/girards/tracks
Thanks in advance
You could deploy an ingress controller such as nginx and create ingress resource to expose backend services using host.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: simple-ingress-example
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: api.branchname.domain.com
http:
paths:
- path: /
backend:
serviceName: servicename
servicePort: 3000
I've 3 angular applications that are deployed on Kubernetes. I'm trying to run all 3 with just one hostname and different paths. Here is my ingress.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
name: test-ingress-deployment
namespace: my-namespace
spec:
tls:
- hosts:
- dns-name.eastus.cloudapp.azure.com
secretName: aks-ingress-tls
rules:
- host: dns-name.eastus.cloudapp.azure.com
http:
paths:
- backend:
serviceName: ui-svc
servicePort: 80
path: /(.*)
- backend:
serviceName: ui-svc-one
servicePort: 80
path: /one/?(.*)
- backend:
serviceName: ui-svc-two
servicePort: 80
path: /two/?(.*)
All these 3 services are in different namespaces. I'm getting 503 for every endpoint I'm trying to hit, after applying ingress.
Documentation around this is scarce, at least I wasn't able to find something except for Github issues shedding a little light into this issue. But as far as I know cross namespace access was intentionally avoided in K8s, it would be a prime source of privilege escalation attacks.
To my knowledge you do have two options:
You can run your ingress and ingress controller inside the kube-system namespace. But this is not recommended as kube-system is meant for K8s components only and it most likely creates security concerns.
You can have the ingress in the namespace your service resides in. But then you need an ingress controller which allows merging of rules which not all support afaik.
There are probably more solutions out there, maybe someone with more in-depth K8s knowledge can shed more light on it.
I created a service and each service is creating a new load balancer, I don't want to create a new load balancer for each service. For that, I found solution ingress controller but it's not happening.
I will try to describe the objects you need in just words.
You don't need to create a load balancer for each service. When you're using an ingress controller (like nginx), the ingress controller itself will be the type load balancer. All your other services need to be something like ClusterIP type.
Afterwards you can decide how to link your ClusterIP services with the Nginx LoadBalancer: create an ingress for each service or one ingress that exposes each service based on some rule (like paths as #harsh-manvar shows in the post above).
When you say "it's not happening", it would be good if you could provide details on your setup.
In order for Nginx ingress controller to work, it needs to be defined either as a NodePort or LoadBalancer service type. The examples provided in the nginx documentation are using LoadBalancer. However, LoadBalancer only works when your cluster supports this object (that means running in most cloud providers like AWS/GCP/Azure/DigitalOcean or newer versions of minikube). On the other hand, NodePort will expose the ingress controller on the Kubernetes node where it runs (when using minikube, that usually means a VM of sorts which then needs to be port forwarded to be accessible).
To use ingress in a local environment, you can look into minikube. All you need is to run minikube addons enable ingress and it will deploy an nginx controller for you. Afterwards, all you need to do is define an ingress and depending on your setup you may need to use kubectl port-forward to port forward port 80 on an nginx controller pod to a local port on your machine.
There are different types of services: ClusterIP, NodePort, LoadBalancer and ExternalName. You can specify it in spec.type. Actually the default one, when not specified is not LoadBalancer, but ClusterIP, so in your case, simply leave away the type: LoadBalancer definition and use your serviceName as backend in your ingress resource. Example:
spec:
rules:
- host: your.fully.qualified.host.name
http:
paths:
- backend:
serviceName: your-internal-service-name
servicePort: 80
path: /
Keep in mind that for some cloud providers there's also the possibility to use an internal LoadBalancer without a public IP. This is done by adding an annotation to the service configuration. For Azure AKS it looks like this:
metadata:
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
For Google's GKE the annotation is cloud.google.com/load-balancer-type: "Internal"
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
kubernetes.io/ingress.class: "nginx"
certmanager.k8s.io/cluster-issuer: wordpress-prod
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- test.test.com
secretName: prod
rules:
- host: test.test.com
http:
paths:
- path: /service-1
backend:
serviceName: service-1
servicePort: 80
- path: /service-2
backend:
serviceName: service-2
servicePort: 5000
Sharing here documentation for ingress to target multiple services you can redirect to multi-service.
Using this you can access services like
https://test.test.com/service-1
https://test.test.com/service-2
Following documentation you should do the following.
More information: kubernetes.github.com
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something(/|$)(.*)
For example, the ingress definition above will result in the following rewrites:
rewrite.bar.com/something rewrites to rewrite.bar.com/
rewrite.bar.com/something/ rewrites to rewrite.bar.com/
rewrite.bar.com/something/new rewrites to rewrite.bar.com/new
So I have two clusters at the moment (soon to be a few more, once I get this working), ClusterA and ClusterB.
Is it possible for one ingress to interface with services from both clusters?
ClusterA hosts the front end and the ingress, while ClusterB hosts the back end.
The excerpted ingress is below. Everything bar the back end works.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:{...}
selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/test-frontend-ingress
uid: //
spec:
backend:
serviceName: idu-frontend-XYZ
servicePort: 80
rules:
- http:
paths:
- backend:
serviceName: test-backend-app-service
servicePort: 8080
path: /api/v2/
- backend:
serviceName: idu-frontend-XYZ
servicePort: 80
path: /
tls:
- secretName: tls-cert-name
status:
loadBalancer:
ingress:
- ip: 123.456.789.012
Back end service URL:
https://console.cloud.google.com/kubernetes/service/asia-southeast1-b/test-backend/default/test-backend-app-service...
URL the ingress tries to point to:
https://console.cloud.google.com/kubernetes/service/asia-southeast1-b/standard-cluster-1/default/test-backend-app-service...
So what I've gathered is the ingress can only interface with things in the same cluster as them? test-backend and standard-cluster-1 are the cluster names, and they are both on the default namespace. Isn't that kind of pointless, as you can only deploy one thing to each cluster? Unless your images contain multiple apps, in which case it isn't really microservices anymore.
Connecting two clusters with Kubernetes is hard I guess.
Instead you can deploy both the services on the same cluster. You can create two deployments and expose them as services. And then ingress can redirect traffic between them.
Why do you need a cluster per service though ?
If there is no other alternative you will have to do something like this:
https://appscode.com/products/voyager/7.1.1/guides/ingress/http/external-svc/
I have multiple MSA on k8s on GKE. Each is on separate subdomain like:
msa1.example.com
msa2.example.com
I have it in single ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: main-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: lalala-ip-1
kubernetes.io/ingress.allow-http: "false"
spec:
tls:
- hosts:
- msa1.example.com
secretName: msa1-tls
backend:
serviceName: sink
servicePort: 80
rules:
- host: msa1.example.com
http:
paths:
- path: /.well-known/*
backend:
serviceName: letsencrypt
servicePort: 80
- path: /*
backend:
serviceName: lalala
servicePort: 80
- host: msa2.example.com
http:
paths:
- path: /*
backend:
serviceName: lalala2
servicePort: 80
... and all is nice.
The thing is, that I want to have each MSA in separate file.
Problem is this kubernetes.io/ingress.global-static-ip-name: lalala-ip-1 line. If I have it in two ingresses only first started is bounded to IP, but other ones no.
Is there a way, to share IP on GKE ingress controller between two ingresses?
A way around it could be to run your own nginx-ingress controller in your cluster and expose it via LoadBalancer service type. Then you would have 1 IP for your ingress and be able to serve all ingresses via nginx controller by adding annotation kubernetes.io/ingress.class: "nginx"
Reference: https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/
Confirmed my comment:
Only one resource at a time can use a static external IP address.
https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address
GKE has recently added support for the new Kubernetes Gateway API. Both the GKE Gateway implementation as well as the Kubernetes Gateway API specification are still in alpha at this point.
The Kubernetes Gateway-API, is intended to support use cases, where you have a central Gateway (with a single IP), but want different Routes (with different hostnames or paths), managed in separate objects or even namespaces.
References:
https://gateway-api.sigs.k8s.io/
https://cloud.google.com/kubernetes-engine/docs/concepts/gateway-api