Stackvora.tech

Kubernetes in 30 Minutes: Pods, Deployments and Services

This article provides a concise introduction to the fundamental building blocks of Kubernetes: Pods, Deployments, and Services. Understanding these core…

This article provides a concise introduction to the fundamental building blocks of Kubernetes: Pods, Deployments, and Services. Understanding these core abstractions is crucial for deploying and managing containerized applications effectively within a Kubernetes cluster. We will explore their roles, interrelationships, and practical application through command-line examples and YAML definitions.

Pods: The Atomic Unit of Deployment

A Pod is the smallest deployable unit in Kubernetes. It represents a single instance of a running process in your cluster. Pods are designed to encapsulate one or more closely related containers that share resources like network interfaces, storage volumes, and IPC namespaces. While a Pod can contain multiple containers, it's generally best practice to run a single primary container per Pod, with helper containers (sidecars) for tasks like logging, metrics collection, or configuration synchronization.

Key characteristics of Pods:

  • Shared Network Namespace: All containers within a Pod share the same IP address and port space. They can communicate with each other using localhost.
  • Shared Storage: Pods can define shared storage volumes that all containers within the Pod can access, enabling data sharing or persistent storage.
  • Ephemeral: Pods are inherently ephemeral. If a Pod dies (e.g., due to a node failure or a container crash), Kubernetes does not automatically restart it. Higher-level abstractions manage their lifecycle.
  • Resource Limits: You can define CPU and memory requests and limits for containers within a Pod, helping the Kubernetes scheduler place them efficiently and prevent resource starvation.

Example Pod Definition (for illustration, rarely deployed directly)

While you rarely create Pods directly, understanding their structure is vital.

apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx:1.27.0 # Specify a precise version
    ports:
    - containerPort: 80
      name: http-port
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m" # 250 milliCPU = 0.25 CPU core
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: busybox-sidecar
    image: busybox:1.36.1
    command: ["sh", "-c", "while true; do sleep 30; done"] # Keep sidecar running

In this example, two containers, nginx-container and busybox-sidecar, share the same network namespace. The Nginx container exposes port 80. Resource requests and limits are defined for the Nginx container.

Deployments: Managing Replicas and Updates

Deployments are a higher-level abstraction that provide declarative updates for Pods and ReplicaSets. They manage the desired state of your application, ensuring that a specified number of Pod replicas are always running. Deployments handle rolling updates, rollbacks, and scaling.

Key functionalities of Deployments:

  • Replica Management: A Deployment ensures that a specified number of Pod replicas are running at all times, even if Pods fail. It does this by managing ReplicaSets.
  • Declarative Updates: You define the desired state of your application (e.g., new image version, new configuration), and the Deployment controller intelligently updates your Pods.
  • Rolling Updates: Deployments support zero-downtime rolling updates by gradually replacing old Pods with new ones, ensuring continuous application availability.
  • Rollbacks: If a new deployment introduces issues, you can easily roll back to a previous stable version.
  • Scaling: You can easily scale your application up or down by changing the replicas field in the Deployment specification.

Deployment Specification

The Deployment object defines the desired state of your application. The selector field is crucial for the Deployment to know which Pods it manages. The template field contains the Pod definition that the Deployment will create.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  labels:
    app: web
spec:
  replicas: 3 # Desired number of Pod replicas
  selector:
    matchLabels:
      app: web # This selector must match the Pod template's labels
  template:
    metadata:
      labels:
        app: web # Labels applied to the Pods created by this Deployment
    spec:
      containers:
      - name: web-container
        image: nginx:1.27.0 # Specify a precise image version
        ports:
        - containerPort: 80
        env:
        - name: MESSAGE
          value: "Hello from Kubernetes!"
      affinity: # Example of Pod affinity rule
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - web
              topologyKey: "kubernetes.io/hostname" # Try to spread Pods across nodes
  strategy: # Rolling update strategy (default)
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25% # Max number of Pods unavailable during update
      maxSurge: 25%       # Max number of Pods that can be created above desired count

In this YAML, we define a Deployment named web-deployment that will ensure 3 replicas of our Nginx application are running. The Pods generated by this Deployment will have the label app: web, which matches the Deployment's selector. We've also included a simple MESSAGE environment variable and an anti-affinity rule to encourage spreading Pods across different nodes.

Common Deployment Operations

  • Apply the Deployment: kubectl apply -f web-deployment.yaml
  • Check Deployment status: kubectl get deploy web-deployment
  • View Pods managed by Deployment: kubectl get pods -l app=web
  • Scale up/down: kubectl scale deployment web-deployment --replicas=5
  • Perform a rolling update: Update the image in web-deployment.yaml (e.g., from nginx:1.27.0 to nginx:1.28.0) and run kubectl apply -f web-deployment.yaml again.
  • Check deployment history: kubectl rollout history deployment/web-deployment
  • Rollback to previous revision: kubectl rollout undo deployment/web-deployment

Services: Stable Network Endpoints

Pods are ephemeral and can be created or destroyed at any time, leading to dynamic IP addresses. This makes direct communication with Pods challenging. A Kubernetes Service provides a stable network endpoint (a static IP address and DNS name) for a set of Pods. It acts as an abstraction layer, routing traffic to the healthy Pods that match its selector.

Key features of Services:

  • Stable IP and DNS: Services provide a fixed virtual IP address and a DNS name within the cluster, making it easy for other applications to discover and communicate with your Pods.
  • Load Balancing: Services distribute incoming network traffic across all healthy Pods that match its selector.
  • Decoupling: Services decouple your application's consumer from its backend Pods, allowing Pods to be scaled, replaced, or upgraded without impacting the consumer.
  • Service Discovery: Kubernetes automatically updates DNS entries and IP tables to reflect changes in Pods backing a Service.

Service Types

Kubernetes offers several Service types, each serving a different purpose:

  1. ClusterIP (Default): Exposes the Service on an internal IP in the cluster. It's only reachable from within the cluster. This is suitable for internal microservices communication.
  2. NodePort: Exposes the Service on a static port (the NodePort) on each Node's IP address. This makes the Service accessible from outside the cluster via <NodeIP>:<NodePort>. Kubernetes usually picks a port from a high range (e.g., 30000-32767).
  3. LoadBalancer: Exposes the Service externally using a cloud provider's load balancer. This type provisions an external IP address that acts as the entry point to your application. This is primarily used in cloud environments (AWS, GCE, Azure, etc.).
  4. ExternalName: Maps the Service to the contents of the externalName field (e.g., my.database.example.com) by returning a CNAME record. No proxying or internal IP is allocated.

Service Specification

The selector field in a Service is critical. It determines which Pods the Service will route traffic to, based on their labels.

apiVersion: v1
kind: Service
metadata:
  name: web-service
  labels:
    app: web
spec:
  selector:
    app: web # Matches Pods with label app: web
  ports:
    - protocol: TCP
      port: 80       # Port the Service listens on
      targetPort: 80 # Port the Pod container listens on (containerPort)
      name: http
  type: ClusterIP # Or NodePort, LoadBalancer
  sessionAffinity: None # Or ClientIP for sticky sessions

This web-service will forward TCP traffic from port 80 to port 80 on any Pods that have the label app: web. Since its type is ClusterIP, it will only be reachable within the cluster.

Combined Deployment and Service Example (from stub)

This YAML combines a Deployment and a Service to create a web application.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:1.27.0 # Using a specific Nginx version
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
      name: http
  type: ClusterIP # Default, but explicitly stated

To deploy this:

kubectl apply -f web.yaml

Verify the deployment and service:

kubectl get deployments,pods,services -l app=web

You should see the web Deployment, 3 web Pods, and the web Service. To interact with the service from within the cluster (e.g., from another Pod), you can use http://web:80.

Interaction and Lifecycle

The relationship between these three core components is hierarchical:

  1. You define a Deployment, which specifies the desired state for your application's Pods (e.g., image, replica count, resource limits).
  2. The Deployment creates and manages Pods (via ReplicaSets), ensuring the specified number of healthy replicas are running.
  3. A Service provides a stable network entry point and load balancing across the Pods managed by the Deployment, based on their labels.

When a Pod needs to be replaced (e.g., during a rolling update, or if it crashes), the Deployment creates a new Pod. The Service automatically updates its internal endpoint list to include the new Pod and remove the old one, ensuring seamless connectivity.

Common Pitfalls and Troubleshooting

  • Label Mismatch: The most common error is a mismatch between a Deployment's selector.matchLabels (or the Pod template's metadata.labels) and a Service's spec.selector. If these don't match, the Service won't find any Pods to route traffic to. Use kubectl get endpoints <service-name> to check if endpoints are present.
  • Incorrect targetPort: Ensure the targetPort in your Service definition matches the containerPort exposed by your application inside the Pod.
  • Image Pull Errors: Pods can remain in ImagePullBackOff or ErrImagePull state if the image name is wrong, the tag doesn't exist, or credentials are required for a private registry. Check kubectl describe pod <pod-name> and kubectl logs <pod-name>.
  • Readiness/Liveness Probes: Without proper liveness and readiness probes, Kubernetes might send traffic to an unready Pod or not restart a stuck one. Add these to your Pod specification in the Deployment.
  • Resource Constraints: Pods can fail to schedule (Pending status) if nodes don't have enough resources (CPU, memory) to satisfy their requests. Check kubectl describe pod <pod-name> for scheduling events.
  • Service Visibility: A ClusterIP Service is not directly accessible from outside the cluster. If external access is needed, use NodePort or LoadBalancer, or an Ingress controller.

Back to the knowledge base · Ask the AI assistant