Couldn't understand availableReplicas, readyReplicas, unavailableReplicas in DeploymentStatus - kubernetes

I am creating deployments using Kubernetes API from my server. The deployment pod has two containers - one is the main and the other is a sidecar container that checks the health of the pod and calls the server when it becomes healthy.
I am using this endpoint to get the deployment. It has deployment status property with the following structure as mention here.
I couldn't understand the fields availableReplicas, readyReplicas, replicas, unavailableReplicas and updatedReplicas.
I checked docs of Kubernetes and these SO questions too - What is the difference between current and available pod replicas in kubernetes deployment? and Meaning of "available" and "unavailable" in kubectl describe deployment but could not infer the difference between of a pod being ready, running and available. Could somebody please explain the difference between these terms and states?

A different kinds of replicas in the Deployment's Status can be described as follows:
Replicas - describes how many pods this deployment should have. It is copied from the spec. This happens asynchronously, so in a very brief interval, you could read a Deployment where the spec.replicas is not equal to status.replicas.
availableReplicas - means how many pods are ready for at least some time (minReadySeconds). This prevents flapping of state.
unavailableReplicas - is the total number of pods that should be there, minus the number of pods that has to be created, or ones that are not available yet (e.g. are failing, or are not ready for minReadySeconds).
updatedReplicas - the number of pods reachable by deployment, that match the spec template.
readyReplicas - the number of pods that are reachable from deployment through all the replicas.
Let's use the official example of a Deployment that creates a ReplicaSet to bring up three nginx Pods:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
The Deployment creates three replicated Pods, indicated by the .spec.replicas field.
Create the Deployment by running the following command:
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
Run kubectl get deployments to check if the Deployment was created.
If the Deployment is still being created, the output is similar to the following:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 0/3 0 0 1s
When you inspect the Deployments in your cluster, the following fields are displayed:
NAME - lists the names of the Deployments in the namespace.
READY - displays how many replicas of the application are available to your users. It follows the pattern ready/desired.
UP-TO-DATE - displays the number of replicas that have been updated to achieve the desired state.
AVAILABLE - displays how many replicas of the application are available to your users.
AGE - displays the amount of time that the application has been running.
Run the kubectl get deployments again a few seconds later. The output is similar to this:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 18s
To see the ReplicaSet (rs) created by the Deployment, run kubectl get rs. The output is similar to this:
NAME DESIRED CURRENT READY AGE
nginx-deployment-75675f5897 3 3 3 18s
ReplicaSet output shows the following fields:
NAME - lists the names of the ReplicaSets in the namespace.
DESIRED - displays the desired number of replicas of the application, which you define when you create the Deployment. This is the desired state.
CURRENT - displays how many replicas are currently running.
READY displays how many replicas of the application are available to your users.
AGE - displays the amount of time that the application has been running.
As you can see there is no actual difference between availableReplicas and readyReplicas as both of those fields displays how many replicas of the application are available to your users.
And when it comes to the Pod Lifecycle it is important to see the difference between Pod phase, Container states and Pod conditions which all have different meanings. I strongly recommend going through the linked docs in order to get a solid understanding behind them.

Related

Kubectl get deployments, no resources

I've just started learning kubernetes, in every tutorial the writer generally uses "kubectl .... deploymenst" to control the newly created deploys. Now, with those commands (ex kubectl get deploymets) i always get the response No resources found in default namespace., and i have to use "pods" instead of "deployments" to make things work (which works fine).
Now my question is, what is causing this to happen, and what is the difference between using a deployment or a pod? ? i've set the docker driver in the first minikube, it has something to do with this?
First let's brush up some terminologies.
Pod - It's the basic building block for Kubernetes. It groups one or more containers (such as Docker containers), with shared storage/network, and a specification for how to run the containers.
Deployment - It is a controller which wraps Pod/s and manages its life cycle, which is to say actual state to desired state. There is one more layer in between Deployment and Pod which is ReplicaSet : A ReplicaSet’s 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.
Below is the visualization:
Source: I drew it!
In you case what might have happened :
Either you have created a Pod not a Deployment. Therefore, when you do kubectl get deployment you don't see any resources. Note when you create Deployments it in turn creates a ReplicaSet for you and also creates the defined pods.
Or may be you created your deployment in a different namespace, if that's the case, then type this command to find your deployments in that namespace kubectl get deploy NAME_OF_DEPLOYMENT -n NAME_OF_NAMESPACE
More information to clarify your concepts:
Source
Below the section inside spec.template is the section which is supposedly your POD manifest if you were to create it manually and not take the deployment route. Now like I said earlier in simple terms Deployments are a wrapper to your PODs, therefore anything which you see outside the path spec.template is the configuration which you will need to defined on how you want to manage (scaling,affinity, e.t.c) your POD
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Deployment is a controller providing higher level abstraction on top of pods and ReplicaSets. A Deployment provides declarative updates for Pods and ReplicaSets. Deployments internally creates ReplicaSets within which pods are created.
Use cases of deployment is documented here
One reason for No resources found in default namespace could be that you created the deployment in a specific namespace and not in default namespace.
You can see deployments in a specific namespace or in all namespaces via
kubectl get deploy -n namespacename
kubectl get deploy -A

The meaning of the key field

I have a deployment, that looks as follows:
The question is, what is the difference between the red border label and the violet one?
blue border labels are applied to pod spec where as red border labels are part of deployment spec.
Notice that replicaSet selector uses same key:value pair to identify the related pods.
You can query deployment object using below command
kubectl get deploy -l app=nginx
same way, you can query pod using
kubectl get po -l app=nginx
You can add labels to any k8s object. Pod are one of the objects that take most advantage of it as services target them through labels, but again, any object can have labels.
About deployments, a deployment creates a replicaSet, that in turn creates the pods. The red square is the deployment labels, while the violet is the labels that will have the pods that the replicaSet will create. Note that it is under template section (Pod template).
Now, and this is the important thing with deployments, these two labels must match, in order for a deployment to recognize its "children", otherwise the pods will be orphan. So, if you would change any of these labels, the deployment will create new pods with its labels, and the pods that do not match will run without any controller to back them up.
These key fields are refereed as Labels on Kubernetes. These labels are used in Kubernetes in order to organize our cluster.
Labels are key/value pairs that are attached to objects that can be used to identify or group resources in Kubernetes. They can be used to select resources from a list.
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.
Going deeper on it, lets suppose you have this Pod in your cluster:
apiVersion: v1
kind: Pod
metadata:
name: sample-pod
namespace: default
labels:
env: development
spec:
containers:
- name: busybox
image: busybox
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
restartPolicy: Always
As you can see we are setting one label: env: development
If you deploy this pod you can run the following command to list all lables set to this pod:
kubectl get pod sample-pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
sample-pod 1/1 Running 0 28s env=development
You can also list all pods with development label:
$ kubectl get pods -l env=development
NAME READY STATUS RESTARTS AGE
sample-pod 1/1 Running 0 106s
You can also delete a pod using the label selection:
pod "sample-pod" deleted
Matching objects must satisfy all of the specified label constraints, though they may have additional labels as well. Three kinds of operators are admitted =,==,!=. The first two represent equality (and are simply synonyms), while the latter represents inequality. For example:
environment = production
tier != frontend
You can read more about labels on Kubernetes Documentation.

What is the difference between kubectl autoscale vs kubectl scale

I am new to kubernetes and trying to understand when to use kubectl autoscale and kubectl scale commands
Scale in deployment tells how many pods should be always running to ensure proper working of the application. You have to specify it manually.
In YAMLs you have to define it in spec.replicas like in example below:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Second way to specify scale (replicas) of deployment is use command.
$ kubectl run nginx --image=nginx --replicas=3
deployment.apps/nginx created
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 3 3 3 3 11s
It means that deployment will have 3 pods running and Kubernetes will always try to maintain this number of pods (If any of the pods will crush, K8s will recreate it). You can always change it with in spec.replicas and use kubectl apply -f <name-of-deployment> or via command
$ kubectl scale deployment nginx --replicas=10
deployment.extensions/nginx scaled
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 10 10 10 10 4m48s
Please read in documentation about scaling and replicasets.
Horizontal Pod Autoscaling (HPA) was invented to scale deployment based on metrics produced by pods. For example, if your application have about 300 HTTP request per minute and each your pod allows to 100 HTTP requests for minute it will be ok. However if you will receive a huge amount of HTTP request ~ 1000, 3 pods will not be enough and 70% of request will fail. When you will use HPA, deployment will autoscale to run 10 pods to handle all requests. After some time, when number of request will drop to 500/minute it will scale down to 5 pods. Later depends on request number it might go up or down depends on your HPA configuration.
Easiest way to apply autoscale is:
$ kubectl autoscale deployment <your-deployment> --<metrics>=value --min=3 --max=10
It means that autoscale will automatically scale based on metrics to maximum 10 pods and later it will downscale minimum to 3.
Very good example is shown at HPA documentation with CPU usage.
Please keep in mind that Kubernetes can use many types of metrics based on API (HTTP/HTTP request, CPU/Memory load, number of threads, etc.)
Hope it help you to understand difference between Scale and Autoscaling.

How do I make Kubernetes scale my deployment based on the "ready"/ "not ready" status of my Pods?

I have a deployment with a defined number of replicas. I use readiness probe to communicate if my Pod is ready/ not ready to handle new connections – my Pods toggle between ready/ not ready state during their lifetime.
I want Kubernetes to scale the deployment up/ down to ensure that there is always the desired number of pods in a ready state.
Example:
If replicas is 4 and there are 4 Pods in ready state, then Kubernetes should keep the current replica count.
If replicas is 4 and there are 2 ready pods and 2 not ready pods, then Kubernetes should add 2 more pods.
How do I make Kubernetes scale my deployment based on the "ready"/ "not ready" status of my Pods?
I don't think this is possible. If pod is not ready, k8 will not make it ready as It is something which releated to your application.Even if it create new pod, how readiness will be guaranted. So you have to resolve the reasons behind non ready status and then k8. Only thing k8 does it keep them away from taking world load to avoid request failure
Ensuring you always have 4 pods running can be done by specifying the replicas property in your deployment definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 4 #here we define a requirement for 4 replicas
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Kubernetes will ensure that if any pods crash, replacement pods will be created so that a total of 4 are always available.
You cannot schedule deployments on unhealthy nodes in the cluster. The master api will only create pods on nodes which are healthy and meet the quota criteria to create any additional pods on the nodes which are schedulable.
Moreover, what you define is called an auto-heal concept of k8s which in basic terms will be taken care of.

Does updating a Deployment (rolling update) keep both new and old coexisting replicas receiving traffic at the same time?

I just want to find out if I understood the documentation right:
Suppose I have an nginx server configured with a Deployment, version 1.7.9 with 4 replicas.
apiVersion: apps/v1beta1 # for versions before 1.6.0 use extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 4
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Now I update the image to version 1.9.1:
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
Withkubectl get pods I see the following:
> kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-2100875782-c4fwg 1/1 Running 0 3s
nginx-2100875782-vp23q 1/1 Running 0 3s
nginx-390780338-bl97b 1/1 Terminating 0 17s
nginx-390780338-kq4fl 1/1 Running 0 17s
nginx-390780338-rx7sz 1/1 Running 0 17s
nginx-390780338-wx0sf 1/1 Running 0 17s
2 new instances (c4fwg, vp23q) of 1.9.1 have been started coexising for a while with 3 instances of the 1.7.9 version.
What happens to the request made to the service at this moment? Do all request go to the old pods until all the new ones are available? Or are the requests load balanced between the new and the old pods?
In the last case, is there a way to modify this behaviour and ensure that all traffic goes to the old versions until all new pods are started?
The answer to "what happens to the request" is that they will be round-robin-ed across all Pods that match the selector within the Service, so yes, they will all receive traffic. I believe kubernetes considers this to be a feature, not a bug.
The answer about the traffic going to the old Pods can be answered in two ways: perhaps Deployments are not suitable for your style of rolling out new Pods, since that is the way they operate. The other answer is that you can update the Pod selector inside the Service to more accurately describe "this Service is for Pods 1.7.9", which will pin that Service to the "old" pods, and then after even just one of the 1.9.1 Pods has been started and is Ready, you can update the selector to say "this Service is for Pods 1.9.1"
If you find all this to be too much manual labor, there are a whole bunch of intermediary traffic managers that have more fine-grained control than just using pod selectors, or you can consider a formal rollout product such as Spinnaker that will automate what I just described (presuming, of course, you can get Spinnaker to work; I wish you luck with it)