Architecture Question - User Driven Resource Allocation - kubernetes

I am working on a SaaS application built on Azure AKS. Users will connect to a web frontend, and depending on their selection, will deploy containers on demand for their respective Organization. There will be a backend API layer that will connect to the Kubernetes API for the deployment of different YAML configurations.
Users will select a predefined container (NodeJs container app), and behind the scenes that container will be created from a template and a URL provided to the user to consume that REST API resource via common HTTP verbs.
I read the following blurb on the Kubernetes docs:
You'll rarely create individual Pods directly in Kubernetes—even singleton Pods. This is because Pods are designed as relatively ephemeral, disposable entities. When a Pod gets created (directly by you, or indirectly by a controller), the new Pod is scheduled to run on a Node in your cluster. The Pod remains on that node until the Pod finishes execution, the Pod object is deleted, the Pod is evicted for lack of resources, or the node fails.
I am thinking that that each "organization account" in my application should deploy containers that are allocated a shared context constrained to a Pod, with multiple containers spun up for each "resource" request. This is because, arguably, an Organization would prefer that their "services" were unique to their Organization and not shared with the scope of others. Assume that namespace, service, or pod name is not a concern as each will be named on the backend with a GUID or similar unique identifier.
Questions:
Is this an appropriate use of Pods and Services in Kubernetes?
Will scaling out mean that I add nodes to the cluster to support the
maximum constraint of 110 Pods / node?
Should I isolate these data services / pods from the front-end to its own dedicated cluster, then add a cluster when (if) maximum Node count of 15,000 is reached?

I guess you should have a look at Deployments
A container is in a pod.
A pod is in a deployment
A service exposes a deployment.

Related

Can you make a kubernetes container deployment conditional on whether a configmap variable is set?

If I have a k8s deployment file for a service with multiple containers like api and worker1, can I make it so that there is a configmap with a variable worker1_enabled, such that if my service is restarted, container worker1 only runs if worker1_enabled=true in the configmap?
The short answer is No.
According to k8s docs, Pods in a Kubernetes cluster are used in two main ways:
Pods that run a single container. The "one-container-per-Pod" model is the most common Kubernetes use case; in this case, you can think of a Pod as a wrapper around a single container; Kubernetes manages Pods rather than managing the containers directly.
Pods that run multiple containers that need to work together. A Pod can encapsulate an application composed of multiple co-located containers that are tightly coupled and need to share resources. These co-located containers form a single cohesive unit of service—for example, one container serving data stored in a shared volume to the public, while a separate sidecar container refreshes or updates those files. The Pod wraps these containers, storage resources, and an ephemeral network identity together as a single unit.
Unless your application requires it, it is better to separate the worker and api containers into their own pod. So you may have one deployment for worker and one for api.
As for deploying worker when worker1_enabled=true, that can be done with helm. You have to create a chart such that when the value of worker1_enabled=true is set, worker is deployed.
Last note, a service in kubernetes is an abstract way to expose an application running on a set of Pods as a network service.

Why headless services are not recommended in stateless applications?

I'm a kubernetes beginner and I found that headless service is generally recommended for stateful applications, so I'm wondering why it can't be used in stateless again? Is it bad that requests should be faster if they go directly to the Pod and not through the Service?
A regular Service provides you with a single, stable, IP address to access any of the replicas associated to the Service.
Given that the application is really stateless, it does not matter which replica you talk to, so the "hiding" behind a single IP.
This relieves you of the responsibility of load balancing: You can just use the very same IP every time and don't have to handle added replicas, removed replicas or repeated DNS lookups.
If you would use a headless service for a stateless application, which is of course possible, you would have to handle all that or risk that the replicas do not deliver scaling and/or high-availability as intended.
In fact a headless service shuffles the order of returned records when performing a DNS looup to help clients with the load balancing, if they can't handle it themself. But you have to perform regular DNS lookups for headless services to learn about added and/or removed instances, which is not the case for a regular service with a service IP.
First of all Headless services are vaguely used to access all the
pod replicas directly instead of using the Services.
In the case of deployment(Stateless services) the pods are
interchangeable because if the pod needs to reschedule it wont
maintain the same id as the previous pod.
Whereas the Statefulsets maintain a unique ID for each pod.
Statefulsets provide 2 unique identities for each pod. First Network
Identity which helps us to give the same DNS name to the pod
regardless of numerous restarts and second is the Storage Identity,
it will also remain the same regardless of the restarts. So,
statefulset won’t use the shared volume.
An IP address is not assigned to a headless service. Internally, it
builds the required endpoints for DNS-named pod exposure.
Conclusion: Pods having a distinct identity are required for stateful applications (hostname). To communicate one pod with other pods a StatefulSet requires a Headless Service. A service with a service IP is a headless service. As a result, it immediately returns the IPs of our related pods. This enables us to communicate with the pods directly instead of using a proxy. Whereas in stateless applications a Service is required to interact with other pods.
For more detailed information refer to this article

Is there a way of obtaining activity logs from Service objects in Kubernetes?

I have the following situation (this is my motivation to ask the question, not the question itself):
I've got a web application that accepts uploads from users.
The users access the application through an Ingress,
then a Service,
Then a Deployment with two Pods.
Application contained in each Pod.
Sometimes the upload fails:
I can see in the logs from the Pod that the upload went all right.
I can even see the data uploaded by the user.
There are nothing but normal logs in the Pod.
But the ingress reports a HTTP 500 error.
And the users sees a HTTP 500 error - connection reset by peer.
If the Pod seems all right, but ingress complains, then I should check the middle man, the Service. Then I realized that there is no easy way to obtain logs from the service.
So this is my question:
How can I read logs from the Service object ? I mean activity logs, not the deployment events.
Do they exist?
The only resources in K8s that produce logs are Pods! Pods lead to the creation of containers, which for their part lead to the creation of Linux processes on the K8s nodes. Those processes write logs that are "reaped" by the container runtime and made available to K8s, e.g. when you run kubectl logs.
Consequently, only K8s resources that are backed by Pods produce logs, e.g. Deployment, Daemonsets, StatefulSets and Jobs.
Services are merely logical resources that configures how network traffic can be routed to Pods. So, in a way they have underlying Pods, but do not produce any additional log output. The only tangible outcome of a Service resource are iptables rules on the K8s nodes, that define how traffic has to be routed from the Service IP to the IPs of the underlying Pods.
To resolve Ingress related problems, you might get further insights from the logs of your ingress controller which is typically deployed as a deployment and therefore backed by Pods.

What is the difference between having multiple namespace and multiple cluster in Kubernetes

I am a beginner and learning about Kubernetes.
As per my understanding, namespace is a virtual cluster backed by the same physical cluster.
In which usecases do we go for separate physical Kubernetes cluster?
What are the main resources that can be saved by opting for namespace instead of physical Kubernetes cluster? (Kubernetes objects present in one namespace of the physical cluster can be shared by all other namespaces, like the ones in kube-system? And are the nodes in the physical Kubernetes cluster shared by all the namespaces but it is not possible to share nodes between multiple physical Kubernetes clusters?)
A namespace isn't a "virtual cluster" in any meaningful way; it's just a way to group together resources. For instance, these Services are different because they're in different namespaces:
kubectl describe service --namespace n1 foo
kubectl describe service --namespace n2 foo
But a service in n1 can make a call to foo.n2.svc.cluster.local without doing any special setup.
A namespace is a natural boundary for Kubernetes RBAC settings. If one object directly references another (e.g., a pod mounts a persistent volume claim or gets environment variables from a config map) they generally must be in the same namespace.
In an actual cluster, the nodes are shared. A given node can run any pod from any namespace (unless that's specifically configured at the pod level); kubectl describe node will show this. If a pod makes very heavy use of some resource (CPU, memory, disk I/O) this can impact other pods running on the same node. That completely ignores namespace boundaries.
You want different clusters when you want things to actually be separated: when a service in one environment shouldn't be able to call a service in a different environment, when cluster-level resources like NodePort services need to be separated, if you have different policies around things like PersistentVolume allocation.
Sharing a cluster means that you need fewer copies of some cluster-global processes (the Kubernetes core, service meshes like Istio) and you can share nodes. That could result in better utilization of large nodes.
You might, for example, separate your test and production environments into separate clusters. These would have different external-DNS settings, separate ingress controllers, and separate node pools. You couldn't accidentally send requests into the test environment from outside, and a load test on the test environment wouldn't impact the production environment.
Generally a separate physical cluster is necessary
To meet compliance and security standards such as PCI DSS, HIPPA etc.
To provide dedicated physical resources to critical workloads.
To separate different environments such as DEV, TEST, PROD
A multi tenant cluster shared by many tenants using their own namespace is useful for saving cost. Namespace separation is logical where the resources of all namespaces still reside in same ETCD storage but with different keys. This is not a problem in separate dedicated physical cluster because in that case the cluster will have separate ETCD as well.
Access to resources across namespaces is controlled by RBAC via kubernetes API Server. But you can access everything from all namespaces if you get access to ETCD directly bypassing the API Server.
You need to put lot of best practices and protection in a multi tenant cluster so that tenants from different namespaces do not step on each other toes. This not that much necessary in a separate dedicated physical cluster.

What exactly Kubernetes Services are and how they are different from Deployments

After reading thru Kubernetes documents like this, deployment , service and this I still do not have a clear idea what the purpose of service is.
It seems that the service is used for 2 purposes:
expose the deployment to the outside world (e.g using LoadBalancer),
expose one deployment to another deployment (e.g. using ClusterIP services).
Is this the case? And what about the Ingress?
------ update ------
Connect a Front End to a Back End Using a Service is a good example of the service working with the deployment.
Service
A deployment consists of one or more pods and replicas of pods. Let's say, we have 3 replicas of pods running in a deployment. Now let's assume there is no service. How does other pods in the cluster access these pods? Through IP addresses of these pods. What happens if we say one of the pods goes down. Kunernetes bring up another pod. Now the IP address list of these pods changes and all the other pods need to keep track of the same. The same is the case when there is auto scaling enabled. The number of the pods increases or decreases based on demand. To avoid this problem services come into play. Thus services are basically programs that manages the list of the pods ip for a deployment.
And yes, also regarding the uses that you posted in the question.
Ingress
Ingress is something that is used for providing a single point of entry for the various services in your cluster. Let's take a simple scenario. In your cluster there are two services. One for the web app and another for documentation service. If you are using services alone and not ingress, you need to maintain two load balancers. This might cost more as well. To avoid this, ingress when defined, sits on top of services and routes to services based on the rules and path defined in the ingress.