Pods, Deployments, and Services: How Kubernetes Runs and Exposes Your App

Kubernetes can feel overwhelming at first, but three core concepts — Pods, Deployments, and Services — are enough to run and expose most apps. This article explains what each piece does, how they work together, and gives small, copy-ready examples you can read and learn from.

Quick mental model

Each of these concepts maps to a Kubernetes object you create with YAML or kubectl — together they let Kubernetes run apps reliably and expose them in a predictable way.

Pods: the runtime unit

A Pod represents one or more containers that run together on the same node and share an IP address, network namespace, and optional volumes. For most beginner use cases you’ll see one container per Pod — Kubernetes treats the Pod as the unit it schedules and manages. Pods are intentionally ephemeral: when a Pod dies, Kubernetes can create a new Pod (usually via a higher-level controller like a Deployment), but the new Pod is a distinct object with a different IP. (kubernetes.io)

Key Pod properties to notice:

A very small Pod manifest (single-container) looks like this:

apiVersion: v1
kind: Pod
metadata:
  name: hello-pod
  labels:
    app: hello
spec:
  containers:
  - name: web
    image: nginx:stable
    ports:
    - containerPort: 80

You normally don’t create standalone Pods for production services; you create a Deployment so Kubernetes can maintain the desired replica count.

Deployments: desired state and safe updates

A Deployment declares the desired state for a set of Pods (how many replicas, what image to run, etc.) and takes care of creating ReplicaSets and Pods to match that state. You tell the Deployment “run 3 replicas of this container image,” and Kubernetes keeps them running. Deployments also enable controlled rollouts: when you update the Pod template (for example, change the container image), Kubernetes performs a rolling update so your service stays available. The rolling-update behavior is the standard update strategy for Deployments. (kubernetes.io)

A basic Deployment manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
    spec:
      containers:
      - name: web
        image: gcr.io/google-samples/echoserver:1.10
        ports:
        - containerPort: 8080

Common kubectl commands you’ll use with a Deployment:

Because a Deployment controls ReplicaSets and Pods, you don’t manage those Pods directly for normal lifecycle tasks; you change the Deployment and let Kubernetes do the rest.

Services: stable networking for changing Pods

Pods come and go, and each Pod gets its own IP. A Service provides a stable network endpoint (IP and DNS name) and a simple way to load-balance across the current set of Pods that match a label selector. Services decouple clients from Pod lifecycle changes: you can scale or replace Pods without changing how clients address your application. (kubernetes.io)

Service types you’ll see early on:

A simple Service that points at the Deployment’s Pods:

apiVersion: v1
kind: Service
metadata:
  name: hello-svc
spec:
  selector:
    app: hello
  ports:
  - protocol: TCP
    port: 80        # service port
    targetPort: 8080  # containerPort on the Pod
  type: ClusterIP

Note the important port distinction:

You can also create Services from existing Deployments with kubectl expose; tutorials and the official getting-started guides show examples of that workflow. (kubernetes.io)

How the three work together (typical flow)

  1. Define a Deployment that describes your app container and the desired replica count.
  2. Apply that Deployment; Kubernetes creates a ReplicaSet and the requested Pods.
  3. Create a Service that selects the Pods by label (the same label used in the Deployment template).
  4. Clients inside the cluster use the Service’s DNS name or ClusterIP; external clients use NodePort/LoadBalancer or Ingress in front of Services.

Why this layering is useful:

Practical pitfalls beginners run into

Useful troubleshooting commands:

Minimal example workflow (commands only)

Below is a minimal command sequence that creates a Deployment and exposes it with a Service of type NodePort (shows how the pieces fit together):

kubectl apply -f hello-deployment.yaml
kubectl apply -f hello-service.yaml       # service that selects app: hello
kubectl get pods -l app=hello
kubectl get svc hello-svc
kubectl rollout status deployment/hello-deployment

The official Kubernetes tutorials provide small, interactive examples you can follow to see this in action. (kubernetes.io)

Closing summary

These three objects together form the fundamental pattern for running and exposing applications in Kubernetes. The official Kubernetes documentation and tutorials are excellent next references if you want to inspect the exact fields and behaviors used in manifests and rollout strategies. (kubernetes.io)