Deployment
A deployment is a supervisor for pods and replica sets, giving you fine-grained control over how and when a new pod version is rolled out as well as rolled back to a previous state.
Deployments are intended to replace Replication Controllers. They provide the same replication functions (through Replica Sets) and also the ability to rollout changes and roll them back if necessary.
You describe a desired state in a Deployment object, 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.
Sample Deployment.yml file
Create a deployment using yaml file¶
$ cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
$ kubectl create -f deployment.yaml
deployment "nginx-deployment" created
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 2 2 2 0 14s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-6c54bd5869-47x9z 0/1 ContainerCreating 0 6s
nginx-deployment-6c54bd5869-sx9wm 0/1 ContainerCreating 0 6s
$ kubectl describe deployments/nginx-deployment
Name: nginx-deployment
Namespace: default
CreationTimestamp: Mon, 19 Feb 2018 12:09:23 -0800
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision=1
Selector: app=nginx
Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.7.9
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-6c54bd5869 (2/2 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 1m deployment-controller Scaled up replica set nginx-deployment-6c54bd5869 to 2
Note
1 2 3 |
|
Creating a Deployment using a simple command¶
$ kubectl run kubernetes-bootcamp --image=docker.io/jocatalin/kubernetes-bootcamp:v1 --port=8080
deployment "kubernetes-bootcamp" created
$ kubectl run kubernetes-bootcamp --image=docker.io/jocatalin/kubernetes-bootcamp:v1 --port=8080
deployment "kubernetes-bootcamp" created
jkailasam@k8s-master:~/k8s$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 1 1 1 1 13s
Scalling¶
- Scalling is accomplished by changing the number of replicas in a Deployment.
- Scaling out a Deployment will ensure new Pods are created and scheduled to Nodes with available resources.
- Scaling in will reduce the number of Pods to the new desired state.
- Kubernetes also supports autoscaling of Pods
- Running multiple instances of an application will require a way to distribute the traffic to all of them.
- Services have an integrated load-balancer that will distribute network traffic to all Pods of an exposed Deployment.
- Services will monitor continuously the running Pods using endpoints, to ensure the traffic is sent only to available Pods
- Once you have multiple instances of an Application running, you would be able to do Rolling updates without downtime.
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 1 1 1 1 2d
- The DESIRED state is showing the configured number of replicas
- The CURRENT state show how many replicas are running now
- The UP-TO-DATE is the number of replicas that were updated to match the desired (configured) state
- The AVAILABLE state shows how many replicas are actually AVAILABLE to the users
Scale UP¶
To scale the Deployment to 4 replicas
$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment "kubernetes-bootcamp" scaled
$ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 of 4 updated replicas are available...
Waiting for rollout to finish: 3 of 4 updated replicas are available...
deployment "nginx-deployment" successfully rolled out
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 4 4 4 4 2d
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
kubernetes-bootcamp-5d7f968ccb-g99mf 1/1 Running 0 18m 10.244.1.6 k8s-node2
kubernetes-bootcamp-5d7f968ccb-hplq4 1/1 Running 0 18m 10.244.1.7 k8s-node2
kubernetes-bootcamp-5d7f968ccb-njgzx 1/1 Running 1 2d 10.244.2.4 k8s-node1
kubernetes-bootcamp-5d7f968ccb-txp74 1/1 Running 0 18m 10.244.2.5 k8s-node1
$ kubectl describe deployments/kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
CreationTimestamp: Thu, 01 Feb 2018 18:58:47 -0800
Labels: run=kubernetes-bootcamp
Annotations: deployment.kubernetes.io/revision=1
Selector: run=kubernetes-bootcamp
Replicas: 4 desired | 4 updated | 4 total | 4 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
Pod Template:
Labels: run=kubernetes-bootcamp
Containers:
kubernetes-bootcamp:
Image: docker.io/jocatalin/kubernetes-bootcamp:v1
Port: 8080/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
OldReplicaSets: <none>
NewReplicaSet: kubernetes-bootcamp-5d7f968ccb (4/4 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 19m deployment-controller Scaled up replica set kubernetes-bootcamp-5d7f968ccb to 4
$ kubectl describe services/kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
Labels: run=kubernetes-bootcamp
Annotations: <none>
Selector: run=kubernetes-bootcamp
Type: NodePort
IP: 10.102.232.247
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 32001/TCP
Endpoints: 10.244.1.6:8080,10.244.1.7:8080,10.244.2.4:8080 + 1 more...
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
Autoscale¶
If horizontal pod autoscaling is enabled in your cluster, you can setup an autoscaler for your Deployment and choose the minimum and maximum number of Pods you want to run based on the CPU utilization of your existing Pods.
$ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
deployment "nginx-deployment" autoscaled
Load Balance¶
To find out if the service is load balanced
$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=32001
$ curl 192.168.11.11:32001
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d7f968ccb-g99mf | v=1
jkailasam@k8s-master:~$ curl 192.168.11.11:32001
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d7f968ccb-txp74 | v=1
jkailasam@k8s-master:~$ curl 192.168.11.11:32001
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5d7f968ccb-hplq4 | v=1
Note
The above curl command hit a different Pod with every request. This demonstrates that the load-balancing is working
Scale Down¶
To scale down the service to 2 replicas
$ kubectl scale deployments/kubernetes-bootcamp --replicas=2
deployment "kubernetes-bootcamp" scaled
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 2 2 2 2 2d
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
kubernetes-bootcamp-5d7f968ccb-hplq4 1/1 Running 0 32m 10.244.1.7 k8s-node2
kubernetes-bootcamp-5d7f968ccb-njgzx 1/1 Running 1 2d 10.244.2.4 k8s-node1
Performing a Rolling Update¶
- Rolling updates allow Deployment's update to take place with zero downtime by incrementally updating Pods instances with new ones.
- The new Pods will be scheduled on Nodes with available resources.
- Scalling the applications to run multiple instances is a requirement for performing updates without affecting application availability.
- updates are versioned and any Deployment update can be reverted to previous (stable) version.
Note
By default, the maximum number of Pods that can be unavailable during the update and the maximum number of new Pods that can be created, is one.
Both options can be configured to either numbers or percentages (of Pods).
Update to the latest version¶
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 4 4 4 4 2d
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
kubernetes-bootcamp-5d7f968ccb-bwqxz 1/1 Running 0 14s 10.244.2.6 k8s-node1
kubernetes-bootcamp-5d7f968ccb-hplq4 1/1 Running 0 45m 10.244.1.7 k8s-node2
kubernetes-bootcamp-5d7f968ccb-njgzx 1/1 Running 1 2d 10.244.2.4 k8s-node1
kubernetes-bootcamp-5d7f968ccb-xqhn9 1/1 Running 0 14s 10.244.1.8 k8s-node2
Update the image of the application to Version 2 using set image
command
$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
deployment "kubernetes-bootcamp" image updated
Alternatively, we can edit the Deployment and change
kubectl edit deployment/nginx-deployment
deployment "nginx-deployment" edited
Check the status of the new Pods, and view the old one terminating with the get pods command:
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-5964dfd755 0 0 0 13m
nginx-deployment-6c54bd5869 2 2 2 29m
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-6b7849c495-48lkf 1/1 Terminating 0 2m
kubernetes-bootcamp-6b7849c495-7bjxk 1/1 Terminating 0 2m
kubernetes-bootcamp-6b7849c495-7f6hq 1/1 Terminating 0 2m
kubernetes-bootcamp-6b7849c495-h5rzc 1/1 Terminating 0 2m
kubernetes-bootcamp-7689dc585d-2wt9x 1/1 Running 0 3s
kubernetes-bootcamp-7689dc585d-nll8c 0/1 ContainerCreating 0 1s
kubernetes-bootcamp-7689dc585d-nzfgt 1/1 Running 0 3s
kubernetes-bootcamp-7689dc585d-tg68w 1/1 Running 0 2s
Verify the update¶
$ kubectl rollout status deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp" successfully rolled out
$ kubectl describe services/kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
Labels: run=kubernetes-bootcamp
Annotations: <none>
Selector: run=kubernetes-bootcamp
Type: NodePort
IP: 10.102.232.247
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 32001/TCP
Endpoints: 10.244.1.13:8080,10.244.1.14:8080,10.244.2.11:8080 + 1 more...
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=32001
$ curl 192.168.11.11:32001
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-7689dc585d-nzfgt | v=2
$ curl 192.168.11.11:32001
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-7689dc585d-2wt9x | v=2
Note
The image can be updated using the yaml file and kubectl apply (instead of create) command.
To check the revision of the deployments
$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment"
REVISION CHANGE-CAUSE
1 kubectl create -f docs/user-guide/nginx-deployment.yaml --record
2 kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
3 kubectl set image deployment/nginx-deployment nginx=nginx:1.91
To further see the details of each revision,
$ kubectl rollout history deployment/nginx-deployment --revision=2
deployments "nginx-deployment" revision 2
Labels: app=nginx
pod-template-hash=1159050644
Annotations: kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
Containers:
nginx:
Image: nginx:1.9.1
Port: 80/TCP
QoS Tier:
cpu: BestEffort
memory: BestEffort
Environment Variables: <none>
No volumes.
Rollback the udpate¶
deploy image tagged as v10
$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v10
deployment "kubernetes-bootcamp" image updated
Use get deployments
to see the status of the deployment
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 4 5 1 4 2d
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-5f9999f64c-nmspl 0/1 ContainerCreating 0 1s
kubernetes-bootcamp-5f9999f64c-xpcns 0/1 ContainerCreating 0 1s
kubernetes-bootcamp-7689dc585d-2wt9x 1/1 Running 0 15m
kubernetes-bootcamp-7689dc585d-nll8c 1/1 Terminating 0 15m
kubernetes-bootcamp-7689dc585d-nzfgt 1/1 Running 0 15m
kubernetes-bootcamp-7689dc585d-tg68w 1/1 Running 0 15m
There is no image called v10 in the repository. Lets confirm that rollout is failed
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-5f9999f64c-nmspl 0/1 ImagePullBackOff 0 2m
kubernetes-bootcamp-5f9999f64c-xpcns 0/1 ImagePullBackOff 0 2m
kubernetes-bootcamp-7689dc585d-2wt9x 1/1 Running 0 17m
kubernetes-bootcamp-7689dc585d-nzfgt 1/1 Running 0 17m
kubernetes-bootcamp-7689dc585d-tg68w 1/1 Running 0 17m
$ kubectl describe pods
Name: kubernetes-bootcamp-5f9999f64c-nmspl
Namespace: default
Node: k8s-node2/192.168.11.12
Start Time: Sat, 03 Feb 2018 22:17:33 -0800
Labels: pod-template-hash=1955559207
run=kubernetes-bootcamp
Annotations: <none>
Status: Pending
IP: 10.244.1.15
Controlled By: ReplicaSet/kubernetes-bootcamp-5f9999f64c
Containers:
kubernetes-bootcamp:
Container ID:
Image: jocatalin/kubernetes-bootcamp:v10
Image ID:
Port: 8080/TCP
State: Waiting
Reason: ImagePullBackOff
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-fzcmd (ro)
Conditions:
Type Status
Initialized True
Ready False
PodScheduled True
Volumes:
default-token-fzcmd:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-fzcmd
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m default-scheduler Successfully assigned kubernetes-bootcamp-5f9999f64c-nmspl to k8s-node2
Normal SuccessfulMountVolume 2m kubelet, k8s-node2 MountVolume.SetUp succeeded for volume "default-token-fzcmd"
Normal Pulling 1m (x4 over 2m) kubelet, k8s-node2 pulling image "jocatalin/kubernetes-bootcamp:v10"
Warning Failed 1m (x4 over 2m) kubelet, k8s-node2 Failed to pull image "jocatalin/kubernetes-bootcamp:v10": rpc error: code = Unknown desc = Error response from daemon: manifest for jocatalin/kubernetes-bootcamp:v10 not found
Warning Failed 1m (x4 over 2m) kubelet, k8s-node2 Error: ErrImagePull
Normal BackOff 30s (x6 over 2m) kubelet, k8s-node2 Back-off pulling image "jocatalin/kubernetes-bootcamp:v10"
Warning Failed 30s (x6 over 2m) kubelet, k8s-node2 Error: ImagePullBackOff
Let’s roll back to our previously working version. We’ll use the rollout undo command
$ kubectl rollout undo deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp"
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-7689dc585d-2wt9x 1/1 Running 0 22m
kubernetes-bootcamp-7689dc585d-nzfgt 1/1 Running 0 22m
kubernetes-bootcamp-7689dc585d-p9q5r 1/1 Running 0 12s
kubernetes-bootcamp-7689dc585d-tg68w 1/1 Running 0 22m
Alternatively, you can rollback to a specific revision by specify that in --to-revision
$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment "nginx-deployment" rolled back
Pausing and Resuming a Deployment¶
You can pause a Deployment before triggering one or more updates and then resume it. This will allow you to apply multiple fixes in between pausing and resuming without triggering unnecessary rollouts.
$ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 2 2 2 2 1m
$ kubectl rollout pause deployment/nginx-deployment
deployment "nginx-deployment" paused
Change the image to use 1.9.1
$ kubectl set image deploy/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated
$ kubectl rollout history deploy/nginx-deployment
deployments "nginx-deployment"
REVISION CHANGE-CAUSE
1 <none>
$ kubectl set resources deployment nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
deployment "nginx-deployment" resource requirements updated
$ kubectl rollout history deploy/nginx-deployment
deployments "nginx-deployment"
REVISION CHANGE-CAUSE
1 <none>
$ kubectl rollout resume deploy/nginx-deployment
deployment "nginx-deployment" resumed
$ kubectl get rs -w
NAME DESIRED CURRENT READY AGE
nginx-deployment-6c54bd5869 0 0 0 7m
nginx-deployment-7956fc4bf9 2 2 2 58s
Note
1 |
|
Expose the deployment¶
Delete a deployment¶
$ kubectl delete deployments nginx-deployment
deployment "nginx-deployment" deleted
$ kubectl get pods
No resources found.
kubectl scale deployments/nginx-deployment --replicas=6 kubectl rollout status deployment/nginx-deployment