The DevOps engineer's handbook The DevOps engineer's handbook

Kubernetes deployment: How it works, tutorial, and best practices

Deployments for Kubernetes (also known as ‘K8s’), work differently to typical deployments.

On this page, we explain:

  • The concept and components of a Kubernetes deployment.
  • What a manifest file is and how it deploys to Kubernetes.
  • The difference between the Kubernetes deployment object and pods and ReplicaSets.
  • Kubernetes deployment tools like Helm and Kustomize.
  • How to create a simple Kubernetes deployment.
  • The challenges and best practices that help with Kubernetes deployments.

What is a Kubernetes deployment?

As a term, ‘Kubernetes deployment’ has a few meanings. We use it to describe the process of using declarative YAML files called ‘manifests’ to deliver software and updates as containerized applications on Kubernetes clusters.

YAML manifests act as a blueprint for how your software should run and what resources it needs. With this information, Kubernetes deploys and manages instances of your application for you using a ‘deployment controller’, scaling the number of replicas and resources as needed.

A ‘deployment’ in Kubernetes is also an object created in a cluster when it acts on a manifest. The deployment object is where Kubernetes stores application requirements and triggers the creation of components needed to run your software, like the ReplicaSets that create the containers your software runs on.

The benefits of Kubernetes deployments over standard container deployments are:

  • Self-healing infrastructure: The deployment controller automatically replaces failed or deleted pods.
  • Rolling updates: Updates applications without downtime by gradually replacing old instances.
  • Rollbacks: Roll back to a previous version if a new one fails. This feature has limits and is not suitable for production environments.
  • Scaling: Scale the number of pod replicas up or down based on demand.

What is a Kubernetes manifest?

A manifest is a Kubernetes deployment YAML file; a configuration file that defines a deployment resource. A manifest’s fields list all the details needed for a Kubernetes cluster to create and manage an application, describing its desired state, including the number of replicas, the container image to use, and the update strategy.

A typical deployment YAML file includes these fields:

  • apiVersion: Specifies the API version (e.g., apps/v1).
  • kind: Defines the resources as a deployment.
  • metadata: Provides metadata about the deployment, like its name and namespace.
  • spec: Describes the desired state of the deployment, including:
    • replicas: Number of pod replicas to run.
    • selector: Defines how to identify pods managed by the deployment.
    • template: Describes the pods, including the containers, their images, and other configuration settings.

Here is an example of YAML in a simple Kubernetes manifest:

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

This example file:

  • Defines a deployment named my-deployment.
  • Creates 3 replicas of a pod running a container named my-container using the image my-image.
  • Exposes port 80.

Pods versus the Kubernetes deployment object

The deployment object and pods have different roles in a Kubernetes cluster.

Pods host a single instance of an application or service, with containers that share network and storage resources.

A deployment object hosts the application’s desired state, which the deployment controller uses to control pod lifecycles and maintain the application state. It keeps the declared number of replicas running at all times, replaces failed pods, and manages rolling updates to minimize downtime during updates.

StatefulSets versus ReplicaSets versus the Kubernetes deployment object

Kubernetes uses different controllers for each workload and covers specific scenarios.

Deployments are for stateless applications where each instance is identical. They support features like rolling updates and roll backs, so you can manage application changes without downtime.

StatefulSets are stateful applications that need persistent storage and stable network identities. They ensure Kubernetes creates, deletes, and scales pods in a predictable order to maintain the persistent storage crucial for databases and similar applications.

ReplicaSets ensure the correct number of pod replicas run at all times. It’s common to manage ReplicaSets through deployments to use features like rolling updates.

Kubernetes deployments with Helm and Kustomize

Open-source tools, like Helm and Kustomize, can complement the Kubernetes deployment object by automating and simplifying software deployments.

Helm

Helm is a package manager for Kubernetes that’s helpful if you deploy the same containers many times.

Helm uses ‘charts’ to deploy containerized applications. Charts are a collection of YAML or JSON files that dictate and contain everything Kubernetes needs to run the software in the desired state.

When you install or update software with a Helm chart, you do so with one command line. Helm then creates a template from your configuration files to deploy your software to the cluster.

Kustomize

Kustomize is a YAML-based command line interface (CLI) tool that lets you customize applications without templating.

Kustomize works by allowing you to create overlays for different environments — your development, staging, production environments, for example — and applying specific changes on top of your base configuration.

This way, you can maintain a single source of truth for your application’s deployment while adapting it for different environments. Kustomize integrates seamlessly with kubectl, enabling you to apply configurations using a command line.

Common Kubernetes deployment strategies

Deployment strategies and patterns can help you limit the impact on customers and strain on your infrastructure. You can use the following deployment patterns in Kubernetes deployments:

  • Rolling strategy: Updates applications by gradually replacing old instances with new ones. Kubernetes’ deployment object helps manage this, but we don’t recommend it for production software.
  • Recreate strategy: Involves shutting down all application instances before starting new ones. This pattern is easy to manage but can lead to considerable downtime, so we only recommend for non-critical applications.
  • Blue/green strategy: Uses 2 production environments that swap roles between live and staging with each release. If the live version is on your blue server, you use the green server for staging and testing before redirecting live traffic to it. After cutover, the blue server acts as the new staging area. It’s a great option for when uptime is important, and it’s easy to roll back.
  • Canary deployments: You deploy updates to a small group of users for testing before rolling them out to the rest of your customers. Thanks to its incremental approach, this strategy is great for minimizing risk.
  • A/B testing: Uses 2 versions of an application simultaneously for comparison of performance and user experience. This is useful for testing new features and gathering metrics, and allows you to make changes based on feedback and performance.
  • Shadow deployment: A new version runs alongside the old version to get real-time performance data without interaction with users. It’s useful for stress testing and allows you to find and fix issues in a production-like environment before deployment.

Out-of-box, Kubernetes doesn’t support deployment strategies that use 2 or more live environments at the same time. You’ll need load balancers, service mesh, or dedicated deployment tools to adopt Blue/green, Canary, A/B testing, and Shadow strategies.

Read more about deployment strategies in more depth.

Tutorial: Create a Kubernetes deployment

In this section, we create a Kubernetes deployment step-by-step, demonstrating how to define and deploy a deployment resource using a YAML file.

1. Define the deployment in a YAML manifest

First, create a YAML file that describes the deployment’s desired state, replica number, container image, and other settings. Here is an example YAML file for an Nginx deployment:

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

2. Create the deployment

With the YAML file defined, the next step is to create the deployment in your Kubernetes cluster. Use the following kubectl apply command:

kubectl apply -f nginx-deployment.yaml

This command sends the YAML configuration to the Kubernetes API server, which creates the deployment.

3. Verify the deployment

After creating the deployment, verify successful creation and check the status. Run the following command to see the details of the deployment:

kubectl get deployments

You should see output like this:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   0/3     0            0           1s

The READY column shows how many replicas are ready. Initially, it might show 0/3 as Kubernetes creates the pods.

4. Monitor the rollout status

Run the following command to monitor the rollout status of the deployment:

kubectl rollout status deployment/nginx-deployment

The output will show the progress of the rollout:

Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out

5. Check the ReplicaSets

The deployment creates a ReplicaSet to manage the pods. Run the following command to see the details of the ReplicaSet created by the deployment:

kubectl get rs

The output will look like this:

NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-75675f5897   3         3         3       18s

Here, DESIRED shows the number of desired replicas, CURRENT shows the running replicas, and READY shows the number of replicas ready.

6. See the pods

Finally, you can see the pods created by the deployment to ensure they are running correctly. Use the following command to list the pods along with their labels:

kubectl get pods --show-labels

The output will display the pods and their labels:

NAME                                READY     STATUS    RESTARTS   AGE       LABELS
nginx-deployment-75675f5897-aaaa1   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
nginx-deployment-75675f5897-aaaa2   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
nginx-deployment-75675f5897-aaaa3   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897

Each pod should have a status of Running, indicating that the deployment successfully created and started the pods as specified in the YAML file.

Challenges and concerns with Kubernetes deployments

Scale

Though Kubernetes takes some of the pain out of managing containerized applications at scale, deployments at scale are a different prospect.

Deploying to 1 or 2 clusters is fairly easy, but as your cluster number grows, so does the complexity. Deploying often to tens, hundreds, or thousands of clusters makes your software hard to track, manage securely, and maintain.

Modern software architectures - like multi-tenancy or microservices - complicate things further, where customers or applications need isolated instances or customization.

If you’re a software provider managing releases with GitOps, you could also suffer ‘YAML sprawl’. YAML sprawl is where you waste valuable time editing files across your organization’s Git repositories to progress releases.

Observability

DevOps processes suggest giving important information as quickly as possible to those who need it.

As Kubernetes is a command-line first solution, it can be hard to quickly understand what’s deployed where unless you’re a Kubernetes expert. Of course, in modern software development, many non-experts need to understand your application’s status too.

Kubernetes offers an optional dashboard of sorts, but it’s not particularly useful if you have many clusters in different locations or use hybrid environments.

Best practices for Kubernetes deployments

Use labeling and annotations

Labeling and annotations are different metadata options in Kubernetes.

Labels help you give a cluster’s objects meaningful names or descriptions. You could use them to categorize pods for informational or process purposes. You could distinguish between back-end or front-end services, or highlight pods with sensitive data.

As with their text-editing counterparts, Kubernetes annotations exist to give more information to others. You could use them to add context or warnings to objects, or add clarity for why something works the way it works.

The easiest way to think about it is that labels identify, annotations explain.

Use resource and request limits on containers

This one’s pretty simple. When you deploy a container, Kubernetes’ control plane will send it to a node with the resources it needs to run. The container asks; the control plane provides.

Setting limits helps ensure containers only get what they need and won’t impact your overall system. It’s especially useful for fast-scaling applications.

Secure deployments

There are many security recommendations for those running their software in Kubernetes. Some decisions will depend on your tech stack or your software’s structure.

Here’s what we think works best for most Kubernetes use cases:

  • Control access to your clusters - Use security protocols or services like Lightweight Directory Access Protocol (LDAP), Open ID Connect (OIDC), or Role-based Access Control (RBAC).
  • Give your infrastructure as little access to other systems as possible - Known as the Principle of Least Privilege (PoLP).
  • Use your tooling’s security features - Development tools often come with built-in security options - you should use them where it makes sense.
  • Add logging tools to your pipeline - Tracking actions taken in your clusters (and across your infrastructure) will help you see:
    • What caused problems
    • Points of weakness
    • Areas for process or system improvement
  • Use image scanning - Check your images for known security problems before deployment.
  • Track network traffic across your infrastructure - Unexpected traffic could be a sign of a security breach.
  • Keep your tools up-to-date - Software and service providers often update their offerings to fix known vulnerabilities.
  • Follow cyber security news - Being aware of what’s happening in cyber security can alert you to major vulnerabilities.

Integrate with CI/CD pipelines

The most important thing you can do to improve your K8s deployment experience is to embed Kubernetes into your deployment pipeline. Doing so helps reduce manual tasks and gives you fewer things to think about.

More importantly, it ensures you get regular, valuable feedback. Regular feedback helps guide process improvements and results in more reliable, stable software delivery.

Tools to help with Kubernetes deployments

Octopus Deploy

Octopus Deploy helps simplify Kubernetes deployments (and all complex deployments) at scale, with:

  • Consistent deployments with environmental progression
  • Easy-to-understand but thorough observability
  • Routine maintenance features

By using Octopus’s variables to customize different actions in similar deployments, you can easily cut down on YAML sprawl.

Codefresh

Codefresh is a complete CI/CD platform that offers a full deployment pipeline. It’s useful for those practicing GitOps and deploying to Kubernetes thanks to features built on Argo.

Octopus acquired Codefresh in March 2024, so no matter your strategy preferences or needs, we have a tool to help you deploy.

Argo CD

Argo CD is an open-source Kubernetes deployment tool. It’s focused heavily on GitOps, meaning you manage all your pipeline’s components in version control.

Other deployment tools

  • GitLab: An end-to-end CI/CD tool for broad use.
  • Spinnaker: An open-source CI/CD solution created by Netflix. Includes integrations for common pipeline tooling, but also their ‘chaos engineering’ testing tool, Chaos Monkey.
  • Flux: A GitOps-focused Kubernetes Continuous Deployment tool.

More reading

See Additional Guides on Key Kubernetes Topics

Together with our content partners, we have authored in-depth guides on several other topics that can also be useful as you explore the world of Kubernetes.

Help us continuously improve

Please let us know if you have any feedback about this page.

Send feedback

Categories:

Next article
Deployment Strategies