Kubernetes deployment/service specification app vs run label - kubernetes

I am trying to connect a k8s deployment to a (Oracle DB) deployment/service. Here is my DB deployment and service:
apiVersion: v1
kind: Service
metadata:
name: oracle-db
labels:
app: oracle-db
spec:
ports:
- name: oracle-db
port: 1521
protocol: TCP
targetPort: 1521
selector:
app: oracle-db
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: oracle-db-depl
labels:
app: oracle-db
spec:
selector:
matchLabels:
app: oracle-db
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: oracle-db
spec:
containers:
- name: oracle-db
image: oracledb:latest
imagePullPolicy: Always
ports:
- containerPort: 1521
env:
...
I'm wondering in the labels sections, what exactly is the difference between specifying 'run' vs 'app' (both of which I have seen used). I have scoured the k8s documentation and cannot find an answer.

Labels are arbitrary key value pairs. There is no special meaning of app or run. You can choose any key and value for your labels. One thing to remember though is that the service's selector needs to have a label which matches with what has been specified as label on the deployment otherwise it will not work.
So if you have app: oracle-db label in your deployment then have app: oracle-db in service's selector and if you have run: oracle-db label in your deployment then have run: oracle-db in service's selector.

Actually the only difference between run and app is the name, labels are used to identify the object in Kubernetes and you can give the name that you like, not necessarily app or run.
You probably can find a lot of run online because if you create an object via imperative command the tag run will be placed automatically for you.
Of course you can change this to a key/value pair that makes more sense to you.
According to k8s documentation:
Labels are intended to be used to specify identifying attributes of objects that are meaningful and relevant to users, but do not directly imply semantics to the core system.
Labels can be used to organize and to select subsets of objects.
Labels can be attached to objects at creation time and subsequently added and modified at any time. Each object can have a set of key/value labels defined.
Each Key must be unique for a given object

Related

How to (re-)name a pod in a K8s deployment?

I want to deploy two containers in a pod through a deployment. But I want the pod to have exactly the name yoda. But in my case, a random string is always append after yoda like that yoda-f8bcb7bf4-khml6. Is it possible to force the pod name? I try the following but I did not get what I expected.
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: yoda
name: yoda
spec:
replicas: 1
selector:
matchLabels:
app: yoda
strategy: {}
template:
metadata:
creationTimestamp: null
name: yoda
labels:
app: yoda
spec:
containers:
- image: busybox
name: anakin
resources: {}
- image: nginx
name: obiwan
resources: {}
status: {}
Regards,
Benoît
This may not be the answer you expect but with Kubernetes pods should not be seen as pets, i. e. they should not receive a lot of attention but considered as highly replaceable. The name generation is part of this consideration among others to avoid conflicts.
Almost all ways of Kubernetes involve a kind of decoupling, including container rollouts. If a pod always receives the same name it cuts itself from things like rolling deployment strategies, in which on pod terminates while another spawns. Alternatively a conflict would be the alternative.
Without a deeper discussion why the pod should be maintained by hand I am not sure you will find a proper solution.
To give some perspective:
Labels (which you already use) give a good way to select a certain pod. If you change the deployment with a different image there might be two pods be selectable with your yoda label.
So, if you want to select either the older or the newer pod (but not both), adding another label with the respective version could solve the distinguishing problem (if that is what you want). See the template metadata section below.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: yoda
name: yoda
spec:
replicas: 1
selector:
matchLabels:
app: yoda
strategy: {}
template:
metadata:
name: yoda
labels:
app: yoda
app.version: 2.0.0
spec:
containers:
- image: busybox
name: anakin
resources: {}
- image: nginx
name: obiwan
resources: {}
I hope this helps.
I am not sure if statefulset can solve your issue. But the statefulset always retain pod name.How ever it also append a numeric number(start from 0) after the pod name & goes upto no of replicas you define in the yaml definition file.
For example, if you define the replica count to 3 in statefulset definition yaml file, then pod's name will be listed below.
[podName]-0
[podName]-1
[podName]-2

How is a service connected to a pod? In yaml, what fields need to match between service and pod?

When creating a Kubernetes service, I'm trying to understand what fields in the YAML service definition need to match to a PODs definition.
For example, given the service:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx-selector
ports:
- protocol: TCP
port: 80
targetPort: 8080
What field in the Pod definition needs to say nginx-selector. I think it's the field I've labeled (metadata.labels.app = nginx-selector).
So given this Pod definition
apiVersion: v1
kind: Pod
metadata:
name: myapp
labels:
app: nginx-selector
spec:
containers:
- name: myapp
image: pats2265/myapp
labels:
app: does-this-matter
ports:
- containerPort: 8080
So many examples use names that are identical between several fields so I wanted a trivial example to spell it out.
This was a good diagram:
Taken from https://matthewpalmer.net/kubernetes-app-developer/articles/service-kubernetes-example-tutorial.html
But it didn't show the corresponding Pod definition.
Searches came up with this question:
How to communicate between pods in a service? - Which I think answers my question, so this can be marked as a duplicate but my question is more specific so I'd like to keep it to help others out.
You are right...its the label of pod which should match with selector defined in service. Check this link for more understanding- https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/

Which names should be same in this k8s yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-app
labels:
run: my-app
spec:
replicas: 3
selector:
matchLabels:
run: my-app
template:
metadata:
labels:
run: my-app
spec:
containers:
- image: gcr.io/google-samples/hello-app:1.0
name: my-app
ports:
- containerPort: 8080
This is a sample yaml from kubenetes site, there are so many my-app, do they all have to be same? what are their purpose?
This is a sample yaml from kubenetes site, there are so many my-app, do they all have to be same? what are their purpose?
No they don't have to be the same as far as the name field goes, that can be different. The my-app references seen in the metadata and selector sections
are labels that can be used to glue the different Kubernetes objects together or simply select a subset of objects when querying Kubernetes. They will sometimes be the same.
Depending on how you've created the Deployment you may have run: myapp throughout the Deployment and in the objects derived from it. Using kubectl run my-app --image=gcr.io/google-samples/hello-app:1.0 --replicas=3 would create a identical Deployment you're referring to.
Here's a picture showing how the different run: my-app labels are used, using the Deployment above as an inspiration:
The picture above shows you the Deployment and how the template box (blue) are used to create the number of specified replicas (Pods). Each Pod will get a run: my-app label in it's metadata section, from the Deployment point of view this will be used as a way of selecting the Pods it's responsible for.
A similar selection of a subset of Pods using kubectl would be:
kubectl get pods -l run=my-app
This will give you all Pods labeled run: my-app.
To sum up a bit, labels can be used to select a subset of resources when querying using e.g. kubectl or by other Kubernetes resources to do selections. You can create your own labels and they don't necessarily have to be the same throughout your specific Deployment but if they are it would be pretty easy to query for any resource with a specific label.
Personally, I think it can be helpful for checking pods grouping information.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-app <--- Deployment object name, you can change it.
labels:
run: my-app <--- It is helpful for the management, e.g.> Deleting same label one
spec:
replicas: 3
selector:
matchLabels:
run: my-app <--- What labels are controlled over by this deployment object.
template:
metadata:
labels:
run: my-app <--- Yeah, it's pod's label. It can be used of grouping with other objects
spec:
containers:
- image: gcr.io/google-samples/hello-app:1.0
name: my-app
ports:

What is the purpose of a kubernetes deployment pod selector?

I fail to see why kubernetes need a pod selector in a deployment statement that can only contain one pod template? Feel free to educate me why kubernetes engineers introduced a selector statement inside a deployment definition instead of automatically select the pod from the template?
---
apiVersion: v1
kind: Service
metadata:
name: grpc-service
spec:
type: LoadBalancer
ports:
- name: grpc
port: 8080
targetPort: 8080
protocol: TCP
selector:
app: grpc-test
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: grpc-deployment
spec:
replicas: 1
revisionHistoryLimit: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
selector:
matchLabels:
app: grpc-test
template:
metadata:
labels:
app: grpc-test
spec:
containers:
...
Why not simply define something like this?
---
apiVersion: v1
kind: Service
metadata:
name: grpc-service
spec:
type: LoadBalancer
ports:
- name: grpc
port: 8080
targetPort: 8080
protocol: TCP
selector:
app: grpc-test
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: grpc-deployment
spec:
replicas: 1
revisionHistoryLimit: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
app: grpc-test
spec:
containers:
...
Ah! Funny enough, I have once tried wrapping my head around the concept of label selectors as well before. So, here it goes...
First of all, what the hell are these labels used for? Labels within Kubernetes are the core means of identifying objects. A controller controls pods based on their label instead of their name. In this particular case they are meant to identify the pods belonging to the deployment’s replica set.
You actually didn’t have to implicitly define .spec.selector when using the v1beta1 extensions. It would in that case default from .spec.template.labels. However, if you don’t, you can run into problems with kubectl apply once one or more of the labels that are used for selecting change because kubeclt apply will look at kubectl.kubernetes.io/last-applied-configuration when comparing changes and that annotation will only contain the user input when he created the resource and none of the defaulted fields. You’ll get an error because it cannot calculate the diff like:
spec.template.metadata.labels: Invalid value: {"app":"nginx"}: `selector` does not match template `labels`
As you can see, this is a pretty big shortcoming since it means you can not change any of the labels that are being used as a selector label or it would completely break your deployment flow. It was “fixed” in apps/v1beta2 by requiring selectors to be explicitly defined, disallowing mutation on those fields.
So in your example, you actually don’t have to define them! The creation will work and will use your .spec.template.labels by default. But yeah, in the near future when you have to use v1beta2, the field will be mandatory. I hope this kind of answers your question and I didn’t make it any more confusing ;)
However, if you don’t, you can run into problems with kubectl apply once one or more of the labels that are used for selecting change because kubeclt apply will look at kubectl.kubernetes.io/last-applied-configuration when comparing changes and that annotation will only contain the user input when he created the resource and none of the defaulted fields.
Quoting from Toon's answer.
My interpretation is it's not logically necessary at all. It's only due to the limitation of the current implementation of Kubernetes, that it has some weird "behavior" in that the functionality it uses to "compare" two deployments / objects does not take into account "default values".
It is a method to decouple a replicaset type from a pod type. There are many similar answers here, but the crux of it is that a deployment/replicaset may be changed at a future point in time, but it won't know what the previous selector was for the last revision. It would have to look at the last revision's template.metadata.labels and then recursively apply those pod labels as the current revision selector. But wait! What if the template.metadata.labels in the current revision changes? Now how do you account for two template.metadata.labels label sets if the new spec doesn't include the same label(s) in the prior revision where the matchLabels was inferred?
Consider inferred matchLabels:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: grpc-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: grpc-test
spec:
containers:
...
Now if I were to go and revise this deployment, my client-side doesn't have awareness of the inferred matchLabels, so my changes would need to account for existing pods. Server-side could do some magic to assume the context in a diff, but what if I changed my template.metadata.labels:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: grpc-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: grpc-test-new
spec:
containers:
...
Now my deployment would need to both infer the new template.metadata.labels as well as munged with the existing server-side, else you end up orphaning a bunch of pods.
I hope this helps illustrate a scenario where explicitly defining the selector allows you to be more flexible in your template updates while still retaining the revision history of previous selectors.
As far as I know, the selector in the deployment is an optional property.
The template is the only required field of spec.
So, you don't need the use the label selector in the deployment, and in you're example I don't see why you couldn't use the latter part?
Deployments are dynamic objects, for example, when your system need a scale up and add more Pods. The template section only defines the Pods that this Deployment would create when you do kubectl apply, while the selector section ensures that the newly created Pods by scaling up are still managed by the already existing Deployment.
Generally speaking, Deployment continuously watches all the Pods and see if there are any Pods it should control, via the selector section.

Re Scheduling pods from one node to another

So, I am writing a custom auto-rescheduler for my clusters and I am using Python Client library to do so. As the rescheduler is still in proposal and nothing has been done for it, the only known way is to delete the pod from overused node and let the replication controller and scheduler take care of the rest (make a new pod and assign it to an appropriate node). What I want to know is can I use the client library to move the pods from one node to another without deleting the pod. Basically, I want to create a pod in an appropriate node first and then delete the pod in the over-used node. Is that possible?
Using node label you can start the container in matching nodes. for this first you need set the node label and update the deployment file and apply it.
Here is the sample yml file I used for blue green deployment, see this help.
web server running on node labeled web
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: webserver-blue
spec:
replicas: 2
template:
metadata:
labels:
type: webserver
color: blue
spec:
containers:
- image: nginx:1.12.0
name: webserver-container
ports:
- containerPort: 80
name: http-server
nodeSelector:
svrtype: web
set another node label as newweb and update and deployment with different name and node label the config.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: webserver-green
spec:
replicas: 2
template:
metadata:
labels:
type: webserver
color: green
spec:
containers:
- image: nginx:1.13.0
name: webserver-container
ports:
- containerPort: 80
name: http-server
nodeSelector:
svrtype: newweb
After testing you can remove the old one. the issue here is you can direct the traffic to only one deployment at a time.