Unlocking Kubernetes Deployment Mastery: A Beginner's Guide!

Kubernetes, often abbreviated as K8s, is an open-source platform designed to automate the deployment, scaling, and operation of application containers. A Deployment in Kubernetes is an abstraction layer for managing a group of identical Pods. Pods are the smallest deployable units of computing that can be created and managed in Kubernetes.

Features of Kubernetes Deployment

1. Declarative Updates

In Kubernetes, you describe the desired state of your application using a YAML or JSON file. This file, called a manifest, includes details like the number of replicas (instances of your application) and the container image to use. Kubernetes ensures that the actual state matches your desired state. This is called declarative configuration.

2. Rolling Updates

A rolling update allows you to update your application to a new version without downtime. Instead of stopping all old instances and starting new ones at once, Kubernetes updates the Pods incrementally. This ensures that your application remains available to users during the update.

3. Rollbacks

If an update goes wrong (e.g., the new version has a bug), you can quickly revert to a previous stable version. Kubernetes keeps a history of your Deployment revisions, allowing you to rollback to an earlier version if necessary.

4. Scaling

Scaling involves adjusting the number of replicas (instances) of your application to handle more or less traffic. With Kubernetes Deployments, you can easily increase or decrease the number of Pods.

5. Self-healing

Kubernetes monitors the state of your Pods and automatically replaces any that fail or become unresponsive, ensuring your application is always running smoothly.

Basic Commands for Deployment Management

Here are some essential commands you'll need to manage Deployments in Kubernetes:

Create a Deployment

To create a Deployment, you use a YAML file that describes the desired state of your application. For example:

kind: Deployment
apiVersion: apps/v1
metadata:
   name: mydeployments
spec:
   replicas: 2
   selector:     
    matchLabels:
     name: deployment
   template:
     metadata:
       name: testpod
       labels:
         name: deployment
     spec:
      containers:
        - name: c00
          image: ubuntu
          command: ["/bin/bash", "-c", "while true; do echo Siddhartha; sleep 5; done"]

Key Sections Explained

  • apiVersion: Specifies the API version. For Deployments, this is typically apps/v1.

  • kind: Indicates the type of resource, which is Deployment.

  • metadata: Contains metadata about the Deployment, such as its name and labels.

  • spec: Describes the desired state of the Deployment.

    • replicas: The number of Pod replicas to run.

    • selector: Defines how to identify the Pods managed by this Deployment.

    • template: Specifies the Pod template, defining the Pods to be created.

      • metadata: Contains metadata about the Pods.

      • spec: Describes the container specifications, including the container image and ports.

Apply the Deployment using the following command:

[root@sid-vm deployments]# kubectl apply -f first_deploy.yml
deployment.apps/mydeployments created
[root@sid-vm deployments]#
[root@sid-vm deployments]# kubectl apply -f first_deploy.yml
deployment.apps/mydeployments created
[root@sid-vm deployments]#

View Deployments

To see the Deployments in your cluster:

[root@sid-vm deployments]# kubectl get deployments
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
mydeployments   2/2     2            2           15s
[root@sid-vm deployments]#

Update a Deployment

To update your Deployment (e.g., change the container image from ubuntu to centos), modify the deployment.yaml file and reapply it:

kind: Deployment
apiVersion: apps/v1
metadata:
   name: mydeployments
spec:
   replicas: 2
   selector:     
    matchLabels:
     name: deployment
   template:
     metadata:
       name: testpod
       labels:
         name: deployment
     spec:
      containers:
        - name: c00
          image: centos
          command: ["/bin/bash", "-c", "while true; do echo Siddhartha; sleep 5; done"]
[root@sid-vm deployments]# kubectl apply -f first_deploy.yml
deployment.apps/mydeployments configured
[root@sid-vm deployments]#

Rollout Status

To check the status of a Deployment update:

[root@sid-vm deployments]# kubectl rollout status deployment/mydeployments
deployment "mydeployments" successfully rolled out
[root@sid-vm deployments]#
[root@sid-vm deployments]# kubectl get pods
NAME                             READY   STATUS        RESTARTS   AGE
mydeployments-569b8c554-4v86d    1/1     Terminating   0          25m
mydeployments-569b8c554-rsxfp    1/1     Terminating   0          25m
mydeployments-85767d7855-l9bdc   1/1     Running       0          12s
mydeployments-85767d7855-tmqns   1/1     Running       0          47s

[root@sid-vm deployments]# kubectl exec mydeployments-85767d7855-tmqns -it -- /bin/bash
[root@mydeployments-85767d7855-tmqns /]#
[root@mydeployments-85767d7855-tmqns /]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="8"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PLATFORM_ID="platform:el8"
PRETTY_NAME="CentOS Linux 8"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-8"
CENTOS_MANTISBT_PROJECT_VERSION="8"
[root@mydeployments-85767d7855-tmqns /]#

It terminate the older deployment pods and parallel bring up the new ones.

We verified that the new pod is running now on Centos 8 by logging to the pod.

Rollback a Deployment

To rollback to a previous version of a Deployment:

[root@sid-vm deployments]# kubectl rollout undo deployment/mydeployments
deployment.apps/mydeployments rolled back
[root@sid-vm deployments]#
[root@sid-vm deployments]# kubectl get pods
NAME                             READY   STATUS        RESTARTS   AGE
mydeployments-569b8c554-rjszj    1/1     Running       0          14s
mydeployments-569b8c554-zzqdb    1/1     Running       0          9s
mydeployments-85767d7855-l9bdc   1/1     Terminating   0          8m33s
mydeployments-85767d7855-tmqns   1/1     Terminating   0          9m8s
[root@sid-vm deployments]# kubectl exec mydeployments-569b8c554-rjszj -it -- /bin/bash
root@mydeployments-569b8c554-rjszj:/# cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
root@mydeployments-569b8c554-rjszj:/#

As we enter the command to rollback to the previous version, we see that the newly created pods got terminated and the older pods with ubuntu image came up with new pod Id.

Scale a Deployment

To change the number of replicas:

[root@sid-vm deployments]# kubectl scale deployment/mydeployments --replicas=4
deployment.apps/mydeployments scaled
[root@sid-vm deployments]#
[root@sid-vm deployments]# kubectl get pods
NAME                            READY   STATUS              RESTARTS   AGE
mydeployments-569b8c554-fnkbn   0/1     ContainerCreating   0          3s
mydeployments-569b8c554-n6zlh   0/1     ContainerCreating   0          3s
mydeployments-569b8c554-rjszj   1/1     Running             0          3m58s
mydeployments-569b8c554-zzqdb   1/1     Running             0          3m53s
[root@sid-vm deployments]# kubectl get deploy
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
mydeployments   4/4     4            4           37m
[root@sid-vm deployments]#

View Deployment History

To see the history of a Deployment:

[root@sid-vm deployments]# kubectl rollout history deployment/mydeployments
deployment.apps/mydeployments
REVISION  CHANGE-CAUSE
2         <none>
3         <none>

[root@sid-vm deployments]#

Handling Failed Deployments

Deployments can fail for various reasons, including:

  • Image Pull Errors: The specified container image is not available or doesn't exist.

  • Resource Constraints: Insufficient CPU or memory resources.

  • Configuration Errors: Errors in the deployment manifest, such as incorrect environment variables.

  • Network Issues: Problems with network connectivity or DNS resolution.

Debugging Failed Deployments

Example Manifest File

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: my-app:1.0
        ports:
        - containerPort: 80

Let's deploy the above deployment manifest.

[root@sid-vm deployments]# kubectl apply -f error_deploy.yml
deployment.apps/my-app created
[root@sid-vm deployments]#
[root@sid-vm deployments]# kubectl get deploy
NAME     READY   UP-TO-DATE   AVAILABLE   AGE
my-app   0/3     3            0           23s
[root@sid-vm deployments]#

We can see that we deployed the deployment but pods are not creating.

Example of Handling a Failed Deployment

Suppose you deployed an application, but the Pods are not starting due to an image pull error. Here’s how you can debug and fix the issue:

  1. Get the list of Pods

     [root@sid-vm deployments]# kubectl get pods
     NAME                      READY   STATUS              RESTARTS   AGE
     my-app-5b764c67f8-hd6kn   0/1     ImagePullBackOff    0          2m41s
     my-app-5b764c67f8-j8cf4   0/1     ImagePullBackOff    0          2m41s
     my-app-5b764c67f8-tx7ql   0/1     ImagePullBackOff    0          2m41s
    
  2. Describe the problematic Pod

     [root@sid-vm deployments]# kubectl describe pod my-app-5b764c67f8-hd6kn | tail -20
     Volumes:
       kube-api-access-hvczl:
         Type:                    Projected (a volume that contains injected data from multiple sources)
         TokenExpirationSeconds:  3607
         ConfigMapName:           kube-root-ca.crt
         ConfigMapOptional:       <nil>
         DownwardAPI:             true
     QoS Class:                   BestEffort
     Node-Selectors:              <none>
     Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                                  node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
     Events:
       Type     Reason     Age                  From               Message
       ----     ------     ----                 ----               -------
       Normal   Scheduled  3m20s                default-scheduler  Successfully assigned default/my-app-5b764c67f8-hd6kn to minikube
       Normal   Pulling    96s (x4 over 3m17s)  kubelet            Pulling image "my-app:1.0"
       Warning  Failed     93s (x4 over 3m6s)   kubelet            Failed to pull image "my-app:1.0": Error response from daemon: pull access denied for my-app, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
       Warning  Failed     93s (x4 over 3m6s)   kubelet            Error: ErrImagePull
       Warning  Failed     69s (x6 over 3m6s)   kubelet            Error: ImagePullBackOff
       Normal   BackOff    55s (x7 over 3m6s)   kubelet            Back-off pulling image "my-app:1.0"
     [root@sid-vm deployments]#
    
  3. Look for image pull errors The output will show events related to image pulling, such as:

     Failed to pull image "my-app:1.0": rpc error: code = Unknown desc = Error response from daemon: pull access denied for my-app, repository does not exist or may require 'docker login'
    
  4. Fix the image reference in the deployment manifest and redeploy:

Modify your deployment.yaml file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: nginx
        ports:
        - containerPort: 80

Then apply the Deployment:

[root@sid-vm deployments]# kubectl apply -f error_deploy.yml
deployment.apps/my-app configured
[root@sid-vm deployments]#

Now, let's see the status of our deployment and status of the pods.

[root@sid-vm deployments]# kubectl get deploy
NAME     READY   UP-TO-DATE   AVAILABLE   AGE
my-app   3/3     3            3           5m29s
[root@sid-vm deployments]#
[root@sid-vm deployments]# kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
my-app-97d8bc7bf-b8tkf   1/1     Running   0          54s
my-app-97d8bc7bf-jhbzt   1/1     Running   0          51s
my-app-97d8bc7bf-nhtc9   1/1     Running   0          57s

And finally after correcting the image of the container in our manifest file, our deployment came up successfully.

Conclusion

Kubernetes Deployments provide a powerful and flexible way to manage stateless applications. They simplify the process of updating, scaling, and maintaining applications, ensuring high availability and resilience. By mastering Deployments, you can ensure your applications run smoothly and handle changes gracefully in a Kubernetes environment. Whether you’re rolling out new features, scaling to meet demand, or recovering from errors, Deployments are an essential tool in your Kubernetes toolkit.

0
Subscribe to my newsletter

Read articles from Siddhartha Gaurav directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Siddhartha Gaurav
Siddhartha Gaurav

I'm a passionate DevOps engineer with a knack for streamlining development workflows and ensuring seamless deployment pipelines. With experience in managing cloud infrastructure, implementing DevOps best practices, and leveraging automation tools, I thrive on tackling complex challenges and driving efficiency in software delivery. Let's connect and explore how I can contribute to your projects!