Python Pod Manifests in YAML

Learn to define Python pod manifests in YAML for Kubernetes. Step-by-step tutorial with hands-on exercise, troubleshooting, and next steps.

Focus: define python pod manifests in yaml

Sponsored

You've containerized your Python app, pushed it to a registry, and now you're staring at a blank terminal wondering how to actually run it in Kubernetes. The gap between 'I have a Docker image' and 'it's running in my cluster' is exactly where most beginners get stuck. In this lesson, you'll learn to define Python pod manifests in YAML — the Kubernetes-native way to describe a single running instance of your app. By the end, you'll write a complete manifest from scratch, deploy it with kubectl, and know exactly what every field does.

The Problem This Lesson Solves

Running a container on your laptop is easy: docker run -p 8000:8000 my-python-app. But in a Kubernetes cluster, you can't just type a command and hope. The cluster needs a precise, declarative description of what you want — which container image, what command to run, which ports to expose, what resources it can use, and how to check it's healthy. That description is a pod manifest, and it's written in YAML.

Without a proper manifest, you'll hit roadblocks: containers crash-looping because they can't find dependencies, pods stuck in Pending because resource limits are too small, or apps unreachable because no port is declared. The manifest is your contract with the scheduler — get it wrong, and the cluster can't help you.

This lesson is your entry ticket to Kubernetes. Once you can define Python pod manifests in YAML, you'll be able to deploy any Python service — a FastAPI REST API, a Celery worker, or a data-processing script — with confidence. It's the foundation for everything else: Deployments, Services, ConfigMaps, and more.

Core Concept / Mental Model

Think of a pod as a single instance of your Python app running in a bubble. The bubble is an isolated environment with its own IP address, its own filesystem view, and its own set of containers. Unlike docker run, which is imperative (you say do this), a pod manifest is declarative — you say this is the desired state, and Kubernetes works to make it true.

Here's a mental model to keep in your head:

  • Pod = a wrapper around one or more containers that share the same lifecycle and network namespace.
  • Manifest = a YAML file that acts as a blueprint. You hand it to the Kubernetes API server (via kubectl apply), and the cluster decides where and how to run it.
  • Desired state = the manifest is your 'source of truth'. If the pod dies, Kubernetes (via a controller like a Deployment) will recreate it to match that state.

Every pod manifest has four top-level fields you'll see over and over:

  • apiVersion – the version of the Kubernetes API you're using (e.g., v1 for pods)
  • kind – the resource type (here, Pod)
  • metadata – information like name, labels, and annotations
  • spec – the desired specification, including containers, volumes, and more

Pro tip: Always think in terms of desired state. If the pod's actual state drifts from the manifest, Kubernetes will try to reconcile it. That's the core of Kubernetes' power.

How It Works Step by Step

Creating a Python pod manifest is a three-step process: structure, containers, and deployment.

1. Start with the skeleton

Every manifest begins with the four top-level fields. For a pod, apiVersion is always v1. You also need a name in metadata — keep it valid DNS-1123 (lowercase alphanumeric and hyphens).

2. Define the container spec

This is the heart of the pod. In spec.containers, you specify:

  • name – a human-readable name for the container
  • image – the Docker image to pull (e.g., python:3.11-slim or your custom image)
  • command and args – override the default entrypoint if needed
  • ports – declare the container's exposed ports
  • resources – set CPU/memory limits and requests
  • env – pass environment variables (we'll cover ConfigMaps later in the track)

3. Deploy and verify

Once your YAML is ready, you use kubectl apply -f my-pod.yaml to submit it to the cluster. Then check status with kubectl get pods and logs with kubectl logs <pod-name>.

The effect: the API server validates the manifest, schedules the pod to a node, and the container runtime (like containerd) starts your Python app. If the image isn't on the node, it's pulled first.

Remember: Pods are ephemeral by design. A pod created directly (not via a Deployment) won't self-heal — if it dies, it's gone. We'll fix that in a later lesson.

Hands-On Walkthrough

Let's put theory into practice. You'll write a pod manifest for a simple FastAPI app. If you don't have a Python app handy, use a public image like python:3.11-slim with a one-liner command.

Example 1: Minimal Python Pod

Here's a manifest for a pod that runs a simple Python command and sleeps:

apiVersion: v1
kind: Pod
metadata:
  name: python-hello
  labels:
    app: python-demo
spec:
  containers:
  - name: app
    image: python:3.11-slim
    command: ["sh", "-c"]
    args: ["echo 'Hello from Python' && sleep 3600"]

Save it as python-hello.yaml, then deploy:

kubectl apply -f python-hello.yaml
kubectl get pods

Expected output (after image pull):

NAME          READY   STATUS    RESTARTS   AGE
python-hello  1/1     Running   0          10s

Check the logs:

kubectl logs python-hello
# Output: Hello from Python

This proves your manifest is valid and the pod runs.

Example 2: FastAPI with Resource Limits

Now let's define a pod for a realistic Python web app. We'll expose port 8000 and set resource boundaries:

apiVersion: v1
kind: Pod
metadata:
  name: fastapi-app
  labels:
    app: fastapi
spec:
  containers:
  - name: api
    image: your-registry/fastapi-app:latest
    ports:
    - containerPort: 8000
    resources:
      requests:
        memory: "256Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"

Deploy and test:

kubectl apply -f fastapi-pod.yaml
kubectl port-forward pod/fastapi-app 8080:8000 &
curl http://localhost:8080/health

If you don't have an image, replace with python:3.11-slim and a command that runs python -m http.server 8000 to simulate a web server.

Example 3: Passing Environment Variables

Python apps often need configuration. Here's how to pass an env var directly in the manifest:

apiVersion: v1
kind: Pod
metadata:
  name: python-env-demo
spec:
  containers:
  - name: app
    image: python:3.11-slim
    command: ["sh", "-c"]
    args: ["echo $MODE && sleep 3600"]
    env:
    - name: MODE
      value: "production"

Apply it and check the log — you should see production. This lays groundwork for ConfigMaps and Secrets later in the track.

Pro tip: Use kubectl explain pod.spec.containers to explore all available fields interactively. It's a built-in manual that never goes out of date.

Compare Options / When to Choose What

When you define Python pod manifests, you have choices about how much detail to include. Here's a comparison:

Approach When to use Pros Cons
Bare minimum (image only) Quick tests, local experiments Simple, fast to write No resource control, no health checks, no reproducibility
With resources and ports Any application you care about Predictable performance, exposes service Needs careful tuning to avoid waste
With environment variables Apps that need configuration Separation of config from code Inline values in YAML are hard to change later
Generated via kubectl run One-off debugging Instant, no file needed Imperative, not reusable, no version control

For anything beyond a quick test, always write a full manifest. You'll thank yourself when you move to Deployments.

Alternatives to handwritten YAML:

  • kubectl create generatorskubectl create deployment can output YAML with --dry-run=client -o yaml, giving you a starting point.
  • Helm charts – templated manifests that make it easy to reuse across environments. You'll encounter them later in this track.
  • Python client libraries (like kubernetes package) – generate manifests programmatically, good for CI/CD automation.

Troubleshooting & Edge Cases

You'll hit issues — we all do. Here are the most common ones and how to fix them.

Pod stuck in Pending

Symptom: The pod never starts. kubectl describe pod shows FailedScheduling.

Fixes: - Resource requests might exceed node capacity. Lower cpu/memory requests. - The node has taints that your pod can't tolerate. Add tolerations if needed. - No node available at all — check cluster health.

ImagePullBackOff or ErrImagePull

Symptom: The pod fails to pull the image.

Fixes: - Check the image tag exists in the registry (docker pull locally to verify). - If using a private registry, you need an imagePullSecrets entry. - Typo in the image name is common — double-check.

CrashLoopBackOff

Symptom: The container starts but then dies immediately.

Fixes: - Check logs: kubectl logs <pod>. Maybe a missing dependency or a port conflict. - Your Python script might exit because it's not a long-running process. Use sleep or a web server to keep it alive. - If you have a startup check, your app might not be ready in time. Later you'll add livenessProbe to control this.

Environment variable not showing up

Fix: Ensure the env array uses name and value keys. A common mistake is using env as a map — it must be a list.

Pro tip: Always run kubectl describe pod <name> to see events — they often contain the exact reason for failures.

What You Learned & What's Next

By now, you can explain the core idea behind defining Python pod manifests in YAML — a declarative blueprint for a single app instance. You've completed a practical exercise: writing and deploying a manifest for a Python app, with options for resources, ports, and environment variables. You can also troubleshoot common rendering and runtime errors.

This milestone moves you from running containers to orchestrating them. Next in the Kubernetes for Python Developers track, you'll learn about using deployments for scaling and updates. Deployments wrap your pods in a self-healing controller, giving you rolling updates, replicas, and crash recovery. The manifest skills you just built will transfer directly — a Deployment's pod template is exactly what you've been writing, just nested one level deeper.

Keep your python-hello.yaml handy. In the next lesson, you'll turn it into a Deployment, scale it to three replicas, and do a rolling update. You're one step closer to production-grade Python on Kubernetes.

Practice recap

Take the python-hello.yaml example and modify it to pass an environment variable MODE=production to the container. Apply it, verify the log shows 'production', then clean up with kubectl delete pod python-hello. Next, experiment with adding a containerPort and a simple livenessProbe (e.g., an HTTP GET on /) to see how Kubernetes checks health.

Common mistakes

  • Using kind: Deployment instead of kind: Pod when you actually want a standalone pod — this changes the API schema and fields.
  • Forgotten containerPort declaration leads to services not reaching your app—just declaring the port in the container spec isn't enough for network discovery.
  • Setting resource limits but not requests can cause unexpected scheduling and eviction behavior—always set both for predictability.
  • Using a Python command that exits immediately (like python -c "print('done')") results in a CrashLoopBackOff — your container must run a long-lived process.
  • Misindenting YAML: because YAML is space-sensitive, even a single missing space causes kubectl apply to fail with a parse error.

Variations

  1. Kubectl generators: kubectl create deployment my-app --image=python:3.11-slim --dry-run=client -o yaml > pod.yaml gives a starting point.
  2. Helm charts: template your manifests to reuse across environments—useful for multiple configs.
  3. Python client libraries: use the kubernetes package to generate manifests programmatically for automation.

Real-world use cases

  • Deploying a single FastAPI microservice as a lightweight, standalone pod for development or a background job.
  • Running a one-off Python data-processing script that needs to run once and exit cleanly, defined as a pod.
  • Testing a new Python image version or configuration in isolation before rolling it out as a Deployment.

Key takeaways

  • A pod manifest is a declarative description of a single app instance written in YAML.
  • The four top-level fields—apiVersion, kind, metadata, spec—form the skeleton of every manifest.
  • Containers must specify image, and you should set resource requests/limits and ports for production readiness.
  • Validate your YAML with kubectl apply --dry-run=client -o yaml before applying.
  • Debug failures using kubectl describe pod for events and kubectl logs for application output.
  • Pods are ephemeral; use Deployments for self-healing, which you'll explore next.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.