Set environment variable for a single pod in a cluster - kubernetes

I have n instances of my micro-service running as kubernetes pods but as there's some scheduling logic in the application code, I would like only one of these pods to execute the code.
In Spring applications, a common approach is to activate scheduled profile -Dspring.profiles.active=scheduled for only instance & leave it deactivated for the remaining instances. I'd like to know how one can accomplish this in kubernetes.
Note: I am familiar with the approach where a kubernetes cron job can invoke an end point so that only one instances picked by load balancer executes the scheduled code. However, I would like to know if it's possible to configure kubernetes specification in such a way that only one pod has an environment variable set.

You can create deployment with 1 replica with the required environment variable and another deployment with as many replicas you want without that variable. You may also set the same labels on both deployments so that Service can load balance traffic between pods from both deployments if you need it.

Related

How to distribute multiple environment variables among pods in k8s?

I want to spawn multiple containers of the same type, but each pod with a different (unique) environment variable (which is a private key).
How could I achieve this without introducing an additional service?
All the Pod replicas in the deployment will have the same environment variables and no unique value to identify a particular Pod. As mentioned by #David Maze creating multiple deployments with a different Secret attached is a better workaround.
Dividing single deployment into multiple sets of deployments and services would be the simplest solution. In each deployment you can have different environment variables.
You describe a desired state in a Deployment, and the Deployment Controller changes the actual state to the desired state at a controlled rate. You can define Deployments to create new ReplicaSets, or to remove existing Deployments and adopt all their resources with new Deployments.

Run different replica count for different containers within same pod

I have a pod with 2 closely related services running as containers. I am running as a StatefulSet and have set replicas as 5. So 5 pods are created with each pod having both the containers.
Now My requirement is to have the second container run only in 1 pod. I don't want it to run in 5 pods. But my first service should still run in 5 pods.
Is there a way to define this in the deployment yaml file for Kubernetes? Please help.
a "pod" is the smallest entity that is managed by kubernetes, and one pod can contain multiple containers, but you can only specify one pod per deployment/statefulset, so there is no way to accomplish what you are asking for with only one deployment/statefulset.
however, if you want to be able to scale them independently of each other, you can create two deployments/statefulsets to accomplish this. this is imo the only way to do so.
see https://kubernetes.io/docs/concepts/workloads/pods/ for more information.
Containers are like processes,
Pods are like VMs,
and Statefulsets/Deployments are like the supervisor program controlling the VM's horizontal scaling.
The only way for your scenario is to define the second container in a new deployment's pod template, and set its replicas to 1, while keeping the old statefulset with 5 replicas.
Here are some definitions from documentations (links in the references):
Containers are technologies that allow you to package and isolate applications with their entire runtime environment—all of the files necessary to run. This makes it easy to move the contained application between environments (dev, test, production, etc.) while retaining full functionality. [1]
Pods are the smallest, most basic deployable objects in Kubernetes. A Pod represents a single instance of a running process in your cluster. Pods contain one or more containers. When a Pod runs multiple containers, the containers are managed as a single entity and share the Pod's resources. [2]
A deployment provides declarative updates for Pods and ReplicaSets. [3]
StatefulSet is the workload API object used to manage stateful applications. Manages the deployment and scaling of a set of Pods, and provides guarantees about the ordering and uniqueness of these Pods. [4]
Based on all that information - this is impossible to match your requirements using one deployment/Statefulset.
I advise you to try the idea #David Maze mentioned in a comment under your question:
If it's possible to have 4 of the main application container not having a matching same-pod support container, then they're not so "closely related" they need to run in the same pod. Run the second container in a separate Deployment/StatefulSet (also with a separate Service) and you can independently control the replica counts.
References:
Documentation about Containers
Documentation about Pods
Documentation about Deployments
Documentation about StatefulSet

Helm kubernetes. Is it possible to inject what replica number the specific replica is?

So I have a spring boot app which runs with two replicas. I want to be able to inject whether the app is replica 1 or 2. I want to this as i want my application to run a proccess on startup, however I only want one of the replicas to run the start up proccess
My test.values.yaml.template
spring-boot:
application:
spring:
datasource:
url: url
username: username
password: password
profiles:
active: prod, agent
In general if for any reason you need to make your application replicas distinguishable from each other, then you should use StatefulSet instead of Deployment. Then you can inject the POD name into your container as env variable and use it in your application.
TL;DR:
No, you cannot inject job operations directly on a ReplicaSet.
It's not a helm issue, it's a core Kubernetes concept:
From ReplicaSet’s Documentation:
A ReplicaSet purpose is to maintain a stable set of replica Pods running at any given time. As such, it is often used to guarantee the availability of a specified number of identical Pods.
This actually means that you may never need to manipulate ReplicaSet objects: use a Deployment instead, and define your application in the spec section.
The purpose of a ReplicaSet is to replicate the pods (usually described in a deployment) and ensure the desired number of replicas is always available.
I want to be able to inject whether the app is replica 1 or 2. I want to this as i want my application to run a proccess on startup, however I only want one of the replicas to run the start up proccess
Pods are separate hosts, It's not like two instances of a app running inside the same computer, hence if you need a startup job to make them work, this job needs to be run in each one of them.
A Pod represents a unit of deployment: a single instance of an application in Kubernetes, which might consist of either a single container or a small number of containers that are tightly coupled and that share resources.
For that you can use a InitContainer:
Init containers are exactly like regular containers, except:
Init containers always run to completion.
Each init container must complete successfully before the next one starts
I'll leave you some examples of how to use InitContainers:
Kubernetes.io InitContainer Examples
A Spring-boot Use Case with Kubernetes
Kubernetes.io Configure a Pod Initialization
The InitContainer Pattern
If you have any question let me know in the comments.
If you have any startup process, one of the best option is to make use of init container. Please see more details here

Specify scheduling order of a Kubernetes DaemonSet

I have Consul running in my cluster and each node runs a consul-agent as a DaemonSet. I also have other DaemonSets that interact with Consul and therefore require a consul-agent to be running in order to communicate with the Consul servers.
My problem is, if my DaemonSet is started before the consul-agent, the application will error as it cannot connect to Consul and subsequently get restarted.
I also notice the same problem with other DaemonSets, e.g Weave, as it requires kube-proxy and kube-dns. If Weave is started first, it will constantly restart until the kube services are ready.
I know I could add retry logic to my application, but I was wondering if it was possible to specify the order in which DaemonSets are scheduled?
Kubernetes itself does not provide a way to specific dependencies between pods / deployments / services (e.g. "start pod A only if service B is available" or "start pod A after pod B").
The currect approach (based on what I found while researching this) seems to be retry logic or an init container. To quote the docs:
They run to completion before any app Containers start, whereas app Containers run in parallel, so Init Containers provide an easy way to block or delay the startup of app Containers until some set of preconditions are met.
This means you can either add retry logic to your application (which I would recommend as it might help you in different situations such as a short service outage) our you can use an init container that polls a health endpoint via the Kubernetes service name until it gets a satisfying response.
retry logic is preferred over startup dependency ordering, since it handles both the initial bringup case and recovery from post-start outages

Kubernetes job that consists of two pods (that must run on different nodes and communicate with each other)

I am trying to create a Kubernetes job that consists of two pods that have to be scheduled on separate nodes in our Hybrid cluster. Our requirement is that one of the pods runs on a Windows Server node and the other pod is running on a Linux node (thus we cannot just run two Docker containers from the same pod, which I know is possible, but would not work in our scenario). The Linux pod (which you can imagine as a client) will communicate over the network with the Windows pod (which you can imagine as a stateful server) exchanging data while the job runs. When the Linux pod terminates, we want to also terminate the Windows pod. However, if one of the pods fail, then we want to fail both pods (as they are designed to be a single job)
Our current design is to write a K8S service that handles the communication between the pods, and then apply the service and the two pods to the cluster to "emulate" a job. However, this is not ideal since the two pods are not tightly coupled as a single job and adds quite a bit of overhead to manually manage this setup (e.g. when failures or the job, we probably need to manually kill the service and deployment of the Windows pod). Plus we would need to deploy a new service for each "job", as we require the Linux pod to always communicate with the same Windows pod for the duration of the job due to underlying state (thus cannot use a single service for all Windows pods).
Any thoughts on how this could be best achieved on Kubernetes would be much appreciated! Hopefully this scenario is supported natively, and I would not need to resort in this kind of pod-service-pod setup that I described above.
Many thanks
I am trying to distinguish your distaste for creating and wiring the Pods from your distaste at having to do so manually. Because, in theory, a Job that creates Pods is very similar to what you are describing, and would be able to have almost infinite customization for those kinds of rules. With a custom controller like that, one need not create a Service for the client(s) to speak to their server, as the Job could create the server Pod first, obtain its Pod-specific-IP, and feed that to the subsequently created client Pods.
I would expect one could create a Job controller using only bash and either curl or kubectl: generate the json or yaml that describes the situation you wish to have, feed it to the kubernetes API (since the Job would have a service account - just like any other in-cluster container), and use normal traps to cleanup after itself. Without more of the specific edge cases loaded in my head it's hard to say if that's a good idea or not, but I believe it's possible.