๐Ÿ›  Understanding Kubernetes Deployment YAML: A Detailed Breakdown with Node Affinity

BalajiBalaji
4 min read

Kubernetes has become the de-facto container orchestration platform for deploying, managing, and scaling applications. If you're starting with Kubernetes, understanding how the YAML manifest files are structured is crucial. These files define everything about how your application runs inside a Kubernetes clusterโ€”from the number of replicas to the node selection strategy.

In this blog post, we'll take a deep dive into a Kubernetes Deployment YAML, breaking down each section line-by-line. We'll use the annotated image below as a visual reference to guide our explanation.


๐Ÿ“„ YAML Manifest Overview

The manifest is used to create a Deployment. A Deployment is a controller in Kubernetes that ensures a specified number of pod replicas are running at all times. It also supports rolling updates and rollbacks.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: type
                    operator: In
                    values:
                      - ssd
          preferredDuringSchedulingIgnoredDuringExecution:
            - preference:
                matchExpressions:
                  - key: type
                    operator: In
                    values:
                      - ssd
              weight: 1
      containers:
        - name: mycontainer
          image: nginx

Letโ€™s walk through the key components of the manifest.


๐Ÿงฉ apiVersion and kind

apiVersion: apps/v1
kind: Deployment
  • apiVersion: Specifies which version of the Kubernetes API you're using to create this object. apps/v1 is the most common for Deployments.

  • kind: The type of Kubernetes object you're definingโ€”in this case, a Deployment.


๐Ÿท metadata

metadata:
  name: myapp
  • name: A unique name for the Deployment resource within the namespace. Here, it's myapp.

๐Ÿ” spec.replicas

spec:
  replicas: 1
  • replicas: Defines the desired number of Pod replicas. In this case, we want 1 pod.

๐ŸŽฏ selector

 selector:
    matchLabels:
      app: myapp
  • selector: Determines which Pods the Deployment should manage.

  • matchLabels: This matches Pods with the label app: myapp.


๐Ÿงฑ template

  template:
    metadata:
      labels:
        app: myapp
  • template.metadata.labels: Labels to assign to the Pods. These should match the selector above so that the Deployment can track the Pods.

โš™๏ธ Pod Specification (spec)

   spec:

This section defines the actual configuration of the Pod the Deployment will create.


๐ŸŒ affinity and nodeAffinity

      affinity:
        nodeAffinity:

Node affinity is used to constrain which nodes your Pod is eligible to be scheduled on, based on labels assigned to the nodes.


๐Ÿ”’ requiredDuringSchedulingIgnoredDuringExecution

          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: type
                    operator: In
                    values:
                      - ssd
  • Required Affinity: This is a hard rule. Pods must be scheduled on nodes that match this condition.

  • key: The node label key.

  • operator: In: Means the node must have a label type with value ssd.

  • If no such node is available, the Pod will not be scheduled.


๐Ÿ’ก preferredDuringSchedulingIgnoredDuringExecution

          preferredDuringSchedulingIgnoredDuringExecution:
            - preference:
                matchExpressions:
                  - key: type
                    operator: In
                    values:
                      - ssd
              weight: 1
  • Preferred Affinity: This is a soft rule. Kubernetes tries to schedule the Pod on a node with this condition but can fall back if needed.

  • weight: Indicates the preference weight (1-100). Higher weight means stronger preference.


๐Ÿ“ฆ containers

      containers:
        - name: mycontainer
          image: nginx
  • name: The name of the container.

  • image: Docker image to be used. In this case, itโ€™s the official nginx image.


Summary

This YAML file defines a Deployment that:

  • Runs 1 replica of a Pod.

  • Labels and matches the Pod using app: myapp.

  • Uses node affinity to control where the Pod runs:

    • It must run on nodes labeled with type=ssd (required).

    • It prefers to run on such nodes if possible (preferred).

  • Runs a simple NGINX container.


๐Ÿง  Why Node Affinity?

Node affinity gives you control over workload placement, which is especially useful in scenarios like:

  • Running workloads on nodes with SSDs or GPUs.

  • Ensuring separation of dev and prod workloads.

  • Optimizing costs by placing workloads on spot instances.


๐Ÿ”š Conclusion

YAML files are the blueprint of your Kubernetes infrastructure. Understanding each section empowers you to design better, more efficient deployments. This example shows not just the basics, but also introduces you to advanced scheduling using node affinity.

If you're just getting started, try modifying this YAML:

  • Change the image to something like httpd or busybox.

  • Add more containers to the containers list.

  • Modify affinity to try different node selection rules.

๐Ÿ“Œ Sample Use Case

Imagine you have a Kubernetes cluster with nodes labeled type=ssd and type=hdd. You want your web application to run only on SSD nodes for better performance. This YAML config ensures that with required and preferred affinity rules.


๐Ÿš€ Want to Try It?

You can apply this YAML file with:

kubectl apply -f my-deployment.yaml

And verify the scheduling with:

kubectl describe pod <pod-name>

Youโ€™ll see where it was scheduled and which node labels matched.

6
Subscribe to my newsletter

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

Written by

Balaji
Balaji

๐Ÿ‘‹ Hi there! I'm Balaji S, a passionate technologist with a focus on AWS, Linux, DevOps, and Kubernetes. ๐Ÿ’ผ As an experienced DevOps engineer, I specialize in designing, implementing, and optimizing cloud infrastructure on AWS. I have a deep understanding of various AWS services like EC2, S3, RDS, Lambda, and more, and I leverage my expertise to architect scalable and secure solutions. ๐Ÿง With a strong background in Linux systems administration, I'm well-versed in managing and troubleshooting Linux-based environments. I enjoy working with open-source technologies and have a knack for maximizing performance and stability in Linux systems. โš™๏ธ DevOps is my passion, and I thrive in bridging the gap between development and operations teams. I automate processes, streamline CI/CD pipelines, and implement robust monitoring and logging solutions to ensure continuous delivery and high availability of applications. โ˜ธ๏ธ Kubernetes is a key part of my toolkit, and I have hands-on experience in deploying and managing containerized applications in Kubernetes clusters. I'm skilled in creating Helm charts, optimizing resource utilization, and implementing effective scaling strategies for microservices architectures. ๐Ÿ“ On Hashnode, I share my insights, best practices, and tutorials on topics related to AWS, Linux, DevOps, and Kubernetes. Join me on my journey as we explore the latest trends and advancements in cloud-native technologies. โœจ Let's connect and dive into the world of AWS, Linux, DevOps, and Kubernetes together!