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
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.,v1for pods)kind– the resource type (here,Pod)metadata– information like name, labels, and annotationsspec– 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 containerimage– the Docker image to pull (e.g.,python:3.11-slimor your custom image)commandandargs– override the default entrypoint if neededports– declare the container's exposed portsresources– set CPU/memory limits and requestsenv– 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.containersto 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 creategenerators –kubectl create deploymentcan 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
kubernetespackage) – 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: Deploymentinstead ofkind: Podwhen you actually want a standalone pod — this changes the API schema and fields. - Forgotten
containerPortdeclaration leads to services not reaching your app—just declaring the port in the container spec isn't enough for network discovery. - Setting resource
limitsbut notrequestscan 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 aCrashLoopBackOff— your container must run a long-lived process. - Misindenting YAML: because YAML is space-sensitive, even a single missing space causes
kubectl applyto fail with a parse error.
Variations
- Kubectl generators:
kubectl create deployment my-app --image=python:3.11-slim --dry-run=client -o yaml > pod.yamlgives a starting point. - Helm charts: template your manifests to reuse across environments—useful for multiple configs.
- Python client libraries: use the
kubernetespackage 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 yamlbefore applying. - Debug failures using
kubectl describe podfor events andkubectl logsfor application output. - Pods are ephemeral; use Deployments for self-healing, which you'll explore next.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.