Ping api in kubernetes environment which is running in other namespaces - kubernetes

How do I ping my api which is running in kubernetes environment in other namespace rather than default. Lets say I have pods running in 3 namespaces - default, dev, prod. I have ingress load balancer installed and configured the routing. I have no problem in accessing default namespace - https://localhost/myendpoint.... But how do I access the apis that are running different image versions in other namespaces eg dev or prod? Do I need to add additional configuration in service or ingress-service files?
EDIT: my pods are restful apis that communicates over http requests. All I’m asking how to access my pod which runs in other namespace rather than default. The deployments communicate between each other with no problem. Let’s say I have a front end application running and want to access it from the browser, how is it done? I can access if the pods are in the default namespace by hitting http://localhost/path... but if I delete all the pods from default namespace and move all the services and deoloyments into dev namespace, I cannot access it anymore from the browser with the same url. Does it have a specific path for different namespaces like http://localhost/dev/path? Do I need to cinfigure it
Hopefully it's clear enough. Thank you

Route traffic with Ingress to Service
When you want to route request from external clients, via Ingress to a Service, you should put the Ingress and Service object in the same namespace. I recommend to use different domains in your Ingress for the environments.
Route traffic from Service to Service
When you want to route traffic from a pod in your cluster to a Service, possible in another namespace, it is easiest to use Service Discovery with DNS, e.g. send request to:
<service-name>.<namespace>.svc.<configured-cluster-name>.<configured-name>
this is most likely
<service-name>.<namespace>.svc.cluster.local

Related

Connecting to many kubernetes services from local machine

From my local machine I would like to be able to port forward to many services in a cluster.
For example I have services of name serviceA-type1, serviceA-type2, serviceA-type3... etc. None of these services are accessible externally but can be accessed using the kubectl port-forward command. However there are so many services, that port forwarding to each is unfeasible.
Is it possible to create some kind of proxy service in kubernetes that would allow me to connect to any of the serviceA-typeN services by specifying the them in a URL? I would like to be able to port-forward to the proxy service from my local machine and it would then forward the requests to the serviceA-typeN services.
So for example, if I have set up a port forward on 8080 to this proxy, then the URL to access the serviceA-type1 service might look like:
http://localhost:8080/serviceA-type1/path/to/endpoint?a=1
I could maybe create a small application that would do this but does kubernetes provide this functionality already?
kubectl proxy command provides this functionality.
Read more here: https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-services/#manually-constructing-apiserver-proxy-urls
Good option is to use Ingrees to achieve it.
Read more about what Ingress is.
Main concepts are:
Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource.
An Ingress may be configured to give Services externally-reachable URLs, load balance traffic, terminate SSL / TLS, and offer name-based virtual hosting.
An Ingress controller is responsible for fulfilling the Ingress, usually with a load balancer, though it may also configure your edge router or additional frontends to help handle the traffic.
An Ingress does not expose arbitrary ports or protocols. Exposing services other than HTTP and HTTPS to the internet typically uses a service of type Service.Type=NodePort or Service.Type=LoadBalancer.
In Kubernetes we have 4 types of Services and the default service type is Cluster IP which means the service is only reachable within the cluster.Ingress exposes your service outside the cluster so ingress acts as the entry point into your cluster.
If you plan to move to cloud (I assume you will, because all applications are going to work in cloud in future) with Ingress, it will be compatible with cloud services and eventually will save time and will be easier to migrate from local environment.
To start with ingress you need to install an Ingress controller first.
There are different ingress controllers which you can use.
You can start with most common ingress-nginx which is supported by kubernetes community.
If you're using a minikube than it can be enabled as an addon - see here
Once you have installed ingress in your cluster, you need to create a rule to have it work. Simple fanout is an example with two services and path based routing to it.

Microservice structure using helm and kubernetes

We have several microservices(NodeJS based applications) which needs to communicate each other and two of them uses Redis and PostgreSQL. Below are the name of of my microservices. Each of them has their own SCM repository and Helm Chart.Helm version is 3.0.1. We have two environments and we have two values.yaml per environments.We have also three nodes per cluster.
First of all, after end user's action, UI service triggers than it goes to Backend. According to the end user request Backend services needs to communicate any of services such as Market, Auth and API.Some cases API and market microservice needs to communicate with Auth microservice as well.
UI -->
Backend
Market --> use postgreSQL
Auth --> use Redis
API
So my questions are,
What should we take care to communicate microservices among each other? Is this my-svc-namespace.svc.cluster.local enough to provide developers or should we specify ENV in each pod as well?
Our microservices is NodeJS application. How developers. will handle this in application source code? Did they use this service name if first question's answer is yes?
We'd like to expose our application via ingress using host per environments? I guess ingress should be only enabled for UI microservice, am I correct?
What is the best way to test each service can communicate each other?
kubectl get svc --all-namespaces
NAMESPACE NAME TYPE
database my-postgres-postgresql-helm ClusterIP
dev my-ui-dev ClusterIP
dev my-backend-dev ClusterIP
dev my-auth-dev ClusterIP
dev my-api-dev ClusterIP
dev my-market-dev ClusterIP
dev redis-master ClusterIP
ingress ingress-traefik NodePort
Two ways to perform Service Discovery in K8S
There are two ways to perform communication (service discovery) within a Kubernetes cluster.
Environment variable
DNS
DNS is the simplest way to achieve service discovery within the cluster.
And it does not require any additional ENV variable setting for each pod.
As its simplest, a service within the same namespace is accessible over its service name. e.g http://my-api-dev:PORT is accessible for all the pods within the namespace, dev.
Standard Application Name and K8s Service Name
As a practice, you can give each application a standard name, eg. my-ui, my-backend, my-api, etc. And use the same name to connect to the application.
That practice can be even applied testing locally from developer environment, with entry in the /etc/host as
127.0.0.1 my-ui my-backend my-api
(Above is nothing to do with k8s, just a practice for the communication of applications with their names in local environments)
Also, on k8s, you may assign service name as the same application name (Try to avoid, suffix like -dev for service name, which reflect the environments (dev, test, prod, etc), instead use namespace or separate cluster for that). So that, target application endpoints can be configured with their service name on each application's configuration file.
Ingress is for services with external access
Ingress should only be enabled for services which required external accesses.
Custom Health Check Endpoints
Also, it is a good practice to have some custom health check that verify all the depended applications are running fine, which will also verify the communications of application are working fine.

OpenShift access service in other namespace without network join

I'm new to OpenShift. I have two projects|namespaces. In each I have a rest service. What I want is service from NS1 access service from NS2 without joining projects networks. Also SDN with multi tenant plugin.
I found example on how to add external services to cluster as native. In NS1 I created an Endpoint for external IP of Service form NS2, but when I tried to create a Service in NS1 for this Endpoint, it failed cause there was no type tag (which wasn't in example also).
I also tried ExternalName. For externalName key my value was URL of router to service in NS2. But it doesn't work pretty well, cause it always returns me a page with Application is not available. But app\service works.
Services in different namespaces are not external, but local to the cluster. So you simply access the services using DNS:
for example: servicename.svc.cluster.local or simply servicename.svc
see also https://docs.openshift.com/enterprise/3.0/architecture/additional_concepts/networking.html
Your question is not very clear and lacks information regarding your network setup and what you mean by joining projects network. What does the SDN multi-tenancy do for example?
By default, the network within the cluster is routable within the whole cluster. If you expose a service in a namespace NS_A, it can access a services in namespace NS_B like so:
Pod in namespace A : curl NS_B.servicename:port
vice versa:
Pod in namespace B : curl NS_A.servicename:port
If your SDN setup makes that impossible, you can expose both service with an Ingress / route and address is from the network where you expose those ( public or not ).
Read the docs on those, for example:
https://kubernetes.io/docs/concepts/services-networking/ingress/
That website is a great resource for all things Kubernetes (like OpenShift).
In OpenShift a slightly different take on it is with routes :
https://docs.openshift.com/container-platform/4.11/networking/routes/route-configuration.html
Basically, try to understand how the networks are set up and how these principles work.
If this does not answer your question, please make it more clear and specific.

Frontend communication with API in Kubernetes cluster

Inside of a Kubernetes Cluster I am running 1 node with 2 deployments. React front-end and a .NET Core app. I also have a Load Balancer service for the front end app. (All working: I can port-forward to see the backend deployment working.)
Question: I'm trying to get the front end and API to communicate. I know I can do that with an external facing load balancer but is there a way to do that using the clusterIPs and not have an external IP for the back end?
The reason we are interested in this, it simply adds one more layer of security. Keeping the API to vnet only, we are removing one more entry point.
If it helps, we are deploying in Azure with AKS. I know they have some weird deployment things sometimes.
Pods running on the cluster can talk to each other using a ClusterIP service, which is the default service type. You don't need a LoadBalancer service to make two pods talk to each other. According to the docs on this topic
ClusterIP exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster. This is the default ServiceType.
As explained in the Discovery documentation, if both Pods (frontend and API) are running on the same namespace, the frontend just needs to send requests to the name of the backend service.
If they are running on different namespaces, the frontend API needs to use a fully qualified domain name to be able to talk with the backend.
For example, if you have a Service called "my-service" in Kubernetes Namespace "my-ns" a DNS record for "my-service.my-ns" is created. Pods which exist in the "my-ns" Namespace should be able to find it by simply doing a name lookup for "my-service". Pods which exist in other Namespaces must qualify the name as "my-service.my-ns". The result of these name lookups is the cluster IP.
You can find more info about how DNS works on kubernetes in the docs.
The problem with this configuration is the idea that the Frontend app will be trying to reach out to the API via the internal cluster. But it will not. My app, on the client's browser can not reach services and pods in my Kluster.
My cluster will need something like nginx or another external Load Balancer to allow my client side api calls to reach my API.
You can alternatively used your front end app, as your proxy, but that is highly not advised!
I'm trying to get the front end and api to communicate
By api, if you mean the Kubernetes API server, first setup a service account and token for the front-end pod to communicate with the Kubernetes API server by following the steps here, here and here.
is there a way to do that using the clusterIPs and not have an external IP for the back end
Yes, this is possible and more secure if external access is not needed for the service. Service type ClusterIP will not have an ExternalIP and the pods can talk to each other using ClusterIP:Port within the cluster.

How to prevent inter-namesapce communication in Kubernetes

In our K8s cluster, micro-services for one application are hosted within one namespace. There is a plan for multiple applications, thus multiple namespaces.
We want communication between micro-services in a namespace through the cluster-ip service, but that between different namespaces to come through the API gateway, with some authentication, with some exceptions. How can we achieve this?
From what I see, K8s network policy is used for controlling pod to pod communication only. "namespaceSelector" works for limiting communication between namespaces, but disables NodePort access as well.
To access a service that is deployed in a different namespace than the one you’re accessing it from, use a FQDN in the form
$SVC.$NAMESPACE.svc.cluster.local
For reference: http://kubernetesbyexample.com/sd/