Kubernetes Deployment Resource Analysis
Deployment Overview
Deployment is one of the most commonly used Kubernetes native Workload resources. When first exploring Kubernetes, developers typically begin by running a Deployment workload. This analysis examines Deployment characteristics and controller behavior.
Rather than covering basic Deployment functionality, this article focuses on advanced features like rolling updates to understand Deployment capabilities before diving into implementation details.
Deployment Fundamentals
Let's create a simple Deployment and examine some implementation details.
Creating a Deployment
To run nginx with 3 replicas using a Deployment named web-server:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
labels:
app: webapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Create the Deployment using kubectl create -f web-server.yaml:
$ kubectl create -f web-server.yaml
deployment.apps/web-server created
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
web-server 1/3 3 1 3s
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
web-server 3/3 3 3 10s
After a brief period, all Pods become available. Key output fields include:
- UP-TO-DATE: Number of replicas updated to desired state
- AVAILABLE: Number of replicas ready to serve traffic
- READY: Available replicas / desired replicas
ReplicaSet Relationship
Query the associated ReplicaSet:
$ kubectl get rs --selector=app=webapp
NAME DESIRED CURRENT READY AGE
web-server-66b6c48dd5 3 3 3 9m54s
After creating the Deployment, a ReplicaSet resource appears in the cluster. This indicates that Deployments manage ReplicaSets rather than directly managing Pods. Examining the ReplicaSet definition confirms this relationship:
$ kubectl get rs web-server-66b6c48dd5 -o yaml
apiVersion: apps/v1
kind: ReplicaSet
...
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: Deployment
name: web-server
uid: 97736b65-0171-4916-bb18-feccc343ac14
resourceVersion: "1099157"
uid: 83ac5660-28eb-4d40-beb1-cb5ceb6928b6
...
The ReplicaSet belongs to the Deployment resource named web-server. Similarly, Pods are owned by the ReplicaSet.
This suggests the Deployment Controller implementation manages ReplicaSet lifecycles, leveraging ReplicaSet Controller capabilities to indirectly handle Pod lifecycle management. By creating multiple ReplicaSet resources and controlling their replica counts, the Deployment enables rolling updates and rollback operations.
Rolling Updates
Update the container image using kubectl set:
$ kubectl set image deployment/web-server nginx=nginx:1.16.1
deployment.apps/web-server image updated
Examine the events:
$ kubectl describe deploy web-server
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 26m deployment-controller Scaled up replica set web-server-66b6c48dd5 to 3
Normal ScalingReplicaSet 88s deployment-controller Scaled up replica set web-server-559d658b74 to 1
Normal ScalingReplicaSet 87s deployment-controller Scaled down replica set web-server-66b6c48dd5 to 2
Normal ScalingReplicaSet 87s deployment-controller Scaled up replica set web-server-559d658b74 to 2
Normal ScalingReplicaSet 86s deployment-controller Scaled down replica set web-server-66b6c48dd5 to 1
Normal ScalingReplicaSet 86s deployment-controller Scaled up replica set web-server-559d658b74 to 3
Normal ScalingReplicaSet 84s deployment-controller Scaled down replica set web-server-66b6c48dd5 to 0
The deployment-controller performs the rolling update by adjusting replica counts for ReplicaSet resources web-server-66b6c48dd5 and web-server-559d658b74. Check the current ReplicaSets:
$ kubectl get rs --selector=app=webapp
NAME DESIRED CURRENT READY AGE
web-server-559d658b74 3 3 3 134m
web-server-66b6c48dd5 0 0 0 159m
A new ReplicaSet web-server-559d658b74 appears with 3 replicas, while the old web-server-66b6c48dd5 drops to 0 replicas. The update process follows this pattern:
- Scale up new ReplicaSet to 1 replica (total: 4 replicas)
- Scale down old ReplicaSet to 2 replicas (total: 3 replicas)
- Scale up new ReplicaSet to 2 replicas (total: 4 replicas)
- Scale down old ReplicaSet to 1 replica (total: 3 replicas)
- Scale up new ReplicaSet to 3 replicas (total: 4 replicas)
- Scale down old ReplicaSet to 0 replicas (total: 3 replicas)
Rollback Operations
Revision History
Check update history:
$ kubectl rollout history deployments/web-server
deployment.apps/web-server
REVISION CHANGE-CAUSE
1 <none>
2 <none>
</none></none>
The CHANGE-CAUSE field is empty by default. This field comes from the kubernetes.io/change-cause annotation. Add an annotation:
kubectl annotate deployment/web-server kubernetes.io/change-cause="image updated to 1.16.1"
Check history again:
$ kubectl rollout history deployments/web-server
deployment.apps/web-server
REVISION CHANGE-CAUSE
1 <none>
2 image updated to 1.16.1
</none>
To add change-cause for the first revision, annotate the original ReplicaSet:
kubectl annotate rs/web-server-66b6c48dd5 kubernetes.io/change-cause="web server deployment created"
Check history:
$ kubectl rollout history deployments/web-server
deployment.apps/web-server
REVISION CHANGE-CAUSE
1 web server deployment created
2 image updated to 1.16.1
Performing Rollbacks
Simulate a failed update by specifying a non-existent image version:
$ kubectl set image deployment/web-server nginx=nginx:1.161
deployment.apps/web-server image updated
$ kubectl get rs --selector=app=webapp
NAME DESIRED CURRENT READY AGE
web-server-559d658b74 3 3 3 168m
web-server-66b6c48dd5 0 0 0 3h13m
web-server-66bc5d6c8 1 1 0 6s
$ kubectl get pod --selector=app=webapp
NAME READY STATUS RESTARTS AGE
web-server-559d658b74-l4bq7 1/1 Running 0 170m
web-server-559d658b74-qhh8m 1/1 Running 0 170m
web-server-559d658b74-vbtl5 1/1 Running 0 170m
web-server-66bc5d6c8-tl848 0/1 ImagePullBackOff 0 2m2s
Add an annotation for the failed revision:
$ kubectl annotate deployment/web-server kubernetes.io/change-cause="image updated to 1.161"
deployment.apps/web-server annotated
$ kubectl rollout history deployments/web-server
deployment.apps/web-server
REVISION CHANGE-CAUSE
1 web server deployment created
2 image updated to 1.16.1
3 image updated to 1.161
Rollback to revision 2:
$ kubectl rollout undo deployment/web-server
deployment.apps/web-server rolled back
$ kubectl rollout history deployments/web-server
deployment.apps/web-server
REVISION CHANGE-CAUSE
1 web server deployment created
3 image updated to 1.161
4 image updated to 1.16.1
Revision 2 becomes the current revision (now revision 4).
View detailed configuration for a specific revision:
$ kubectl rollout history deployments/web-server --revision=1
deployment.apps/web-server with revision #1
Pod Template:
Labels: app=webapp
pod-template-hash=66b6c48dd5
Annotations: kubernetes.io/change-cause: web server deployment created
Containers:
nginx:
Image: nginx:1.14.2
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
</none></none></none>
Rollback to a specific revision:
$ kubectl rollout undo deployment/web-server --to-revision=1
deployment.apps/web-server rolled back
$ kubectl rollout history deployments/web-server
deployment.apps/web-server
REVISION CHANGE-CAUSE
3 image updated to 1.161
4 image updated to 1.16.1
5 web server deployment created
Additional Deployment Properties
Deployment spec includes several important properties:
- minReadySeconds: Default 0. Duration a pod must be ready before considered available.
- paused: Suspends Deployment operations.
- progressDeadlineSeconds: Default 600. Timeout for Deployment operations before marking as failed.
- replicas: Desired number of pod replicas.
- revisionHistoryLimit: Default 10. Number of old ReplicaSets to retain.
- selector: Label selector for identifying managed pods.
- strategy: Pod replacement strategy during updates.
- template: Pod template specification.
The strategy field includes two properties: type and rollingUpdate. Type options are "Recreate" and "RollingUpdate" (default). The rollingUpdate strategy has two configurable parameters:
- maxSurge: Maximum additional pods during rolling update (number or percentage). Controls how many new pods can be created above desired replica count.
- maxUnavailable: Maximum unavailable pods during rolling update (number or percentage). Controls how many old pods can be terminated below desired replica count.
This examination of Deployment capabilities provides context for understanding the implementation details and controller behavior that manages these operations.