Deployments
A Deployment provides declarative update capability for Pod and ReplicaSet
You are responsible for describing the target state in the Deployment, and the Deployment Controller (Controller) changes the actual state at a controlled rate to make it the desired state. You can define a Deployment to create a new ReplicaSet, or delete an existing Deployment and adopt its resources through a new Deployment
Create a Deployment
Below is an example Deployment. Among them, a ReplicaSet is created, which is responsible for starting 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
In this example:
- Create a Deployment named nginx-deployment (indicated by the .metadata.name field). This name will become the naming basis for subsequent creation of ReplicaSet and Pod
- The Deployment creates a ReplicaSet that creates three (indicated by the .spec.replicas field) Pod replicas
- The .spec.selector field defines how the created ReplicaSet looks for Pods to manage. Here, you choose the label (app: nginx ) defined in the Pod template. However, more complex selection rules are possible, as long as the Pod template itself satisfies the given rules
- The template field contains the following subfields
- Pods are labeled app: nginx using the .metadata.labels field.
- The Pod Template Specification (ie, the .template.spec field) instructs the Pod to run an nginx container running the nginx Docker Hub image version 1.14.2.
- Create a container and name it nginx using the .spec.template.spec.containers[0].name field
Before starting, make sure your Kubernetes cluster is up and running. Follow the steps below to create the above Deployment
1. Create the Deployment by running the following command:
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
2. Run kubectl get deployments to check whether the Deployment has been created. If the Deployment is still being created, the output will be similar to:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 0/3 0 0 1s
When inspecting a Deployment in a cluster, the fields displayed are:
- NAME lists the name of the Deployment in the namespace.
- READY shows the number of available "copies" of the application. The displayed pattern is "Ready Count/Expected Count".
- UP-TO-DATE shows how many replicas have been updated to reach the desired state.
- AVAILABLE shows how many copies of the application are available to the user.
- AGE shows how long the application has been running.
Please note that the expected number of replicas is set according to the .spec.replicas field. 3.
To view the online status of the Deployment, run kubectl rollout status deployment/nginx-deployment
and the output is similar to:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out
4. Run kubectl get deployments again after a few seconds. The output is similar to:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 18s
Notice that the Deployment has created all three replicas, and all replicas are up to date (they contain the latest Pod templates) and available
5. To view the ReplicaSet(rs) created by the Deployment, run kubectl get rs. output similar to
NAME DESIRED CURRENT READY AGE
nginx-deployment-75675f5897 3 3 3 18s
The following fields are included in the ReplicaSet output:
- NAME lists the name of the ReplicaSet in the namespace;
- DESIRED shows the expected number of copies of the application, which is the value defined when creating the Deployment. This is the desired state;
- CURRENT displays the number of replicas in the current running state;
- READY shows how many copies of the application are available to serve the user;
- AGE shows how long the application has been running.
Note that the name of a ReplicaSet is always of the form [Deployment name]-[hash]. This name will be the basis for naming the Pods that are created. The hash string in it is consistent with the pod-template-hash label on the ReplicaSet
6. To view the automatically generated labels for each Pod, run kubectl get pods --show-labels. output similar to
NAME READY STATUS RESTARTS AGE LABELS
nginx-deployment-75675f5897-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=75675f5897
nginx-deployment-75675f5897-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=75675f5897
nginx-deployment-75675f5897-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=75675f5897
The created ReplicaSet ensures that there are always three nginx Pods
Update Deployments
Follow the steps below to update the Deployment:
1. First update the nginx Pod to use the nginx:1.16.1 image instead of the nginx:1.14.2 image
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
Or use the following command:
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
Here, deployment/nginx-deployment indicates the name of the Deployment, nginx indicates the container that needs to be updated, and nginx:1.16.1 indicates the new version of the image and its tag The output is similar to
:
deployment.apps/nginx-deployment image updated
Alternatively, edit the Deployment and change .spec.template.spec.containers[0].image from nginx:1.14.2 to nginx:1.16.1
kubectl edit deployment/nginx-deployment
The output is similar to:
deployment.apps/nginx-deployment edited
2. To view the online status, run:
kubectl rollout status deployment/nginx-deployment
The output is similar to:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
or
deployment "nginx-deployment" successfully rolled out
Get more information about the updated Deployment
- After successfully going online, you can view the Deployment by running kubectl get deployments: The output is similar to:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 36s
- Run kubectl get rs to see that the Deployment has finished updating the Pods by creating a new ReplicaSet and scaling it up to 3 replicas and scaling the old ReplicaSet down to 0 replicas:
kubectl get rs
The output is similar to:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 3 6s
nginx-deployment-2035384211 0 0 0 36s
Running get pods now should only show new Pods:
kubectl get pods
The output is similar to:
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-khku8 1/1 Running 0 14s
nginx-deployment-1564180365-nacti 1/1 Running 0 14s
nginx-deployment-1564180365-z9gth 1/1 Running 0 14s
The next time you want to update those Pods, just update the Deployment Pod template again.
Deployment ensures that only a certain number of Pods are shut down when updating. By default, it ensures that at least 75% of the required Pods are running (with a maximum unavailable percentage of 25%).
The Deployment also ensures that only slightly higher than expected pod counts are created. By default, it ensures that up to 125% more Pods than expected are started (maximum peak of 25%).
For example, if you look closely at the above Deployment, you will see that it first creates a new Pod, then deletes the old Pod, and creates the new Pod. It won't kill old pods until a sufficient number of new pods have come up. New pods are not created until a sufficient number of old pods are killed. It ensures that at least 3 pods are available and at most 4 total pods are available. When the Deployment is set to 4 replicas, the number of Pods will be between 3 and 5
Get more information about a Deployment
kubectl describe deployments
The output is similar to:
Name: nginx-deployment
Namespace: default
CreationTimestamp: Thu, 30 Nov 2017 10:56:25 +0000
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision=2
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.16.1
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-1564180365 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 2m deployment-controller Scaled up replica set nginx-deployment-2035384211 to 3
Normal ScalingReplicaSet 24s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 1
Normal ScalingReplicaSet 22s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 2
Normal ScalingReplicaSet 22s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 2
Normal ScalingReplicaSet 19s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 1
Normal ScalingReplicaSet 19s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 3
Normal ScalingReplicaSet 14s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 0
As you can see, when the Deployment was created for the first time, it created a ReplicaSet (nginx-deployment-2035384211) and directly expanded it to 3 replicas. When a Deployment is updated, it creates a new ReplicaSet (nginx-deployment-1564180365), scales it up to 1, waits for it to be ready; then scales down the old ReplicaSet to 2, and scales up the new ReplicaSet to 2 so that there are at least 3 Pods are available and a maximum of 4 Pods can be created. It then continues scaling up the new ReplicaSet and scaling down the old ReplicaSet using the same rolling update strategy. In the end, you will have 3 usable replicas in the new ReplicaSet, and the old ReplicaSet will shrink to 0
Rollback Deployment
Sometimes, you may want to rollback a Deployment; for example, when the Deployment is unstable (such as entering a repeatedly crashing state). By default, all live records of a Deployment are kept in the system so that they can be rolled back at any time (you can change this constraint by modifying the revision history limit
- Suppose you made a typo when updating the Deployment and set the image name to nginx:1.161 instead of nginx:1.16.1
kubectl set image deployment/nginx-deployment nginx=nginx:1.161
The output is similar to:
deployment.apps/nginx-deployment image updated
This onboarding process will stall. You can verify this by checking the live status:
kubectl rollout status deployment/nginx-deployment
The output is similar to:
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
- You can see that there are two old copies (nginx-deployment-1564180365 and nginx-deployment-2035384211), and one new copy (nginx-deployment-3066724191)
kubectl get rs
The output is similar to:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 3 25s
nginx-deployment-2035384211 0 0 0 36s
nginx-deployment-3066724191 1 1 0 6s
- Looking at the Pods created, you will notice that 1 Pod created by the new ReplicaSet is stuck in the image pull cycle
kubectl get pods
The output is similar to:
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-70iae 1/1 Running 0 25s
nginx-deployment-1564180365-jbqqo 1/1 Running 0 25s
nginx-deployment-1564180365-hysrc 1/1 Running 0 25s
nginx-deployment-3066724191-08mng 0/1 ImagePullBackOff 0 6s