podman play kube lets you run Kubernetes manifests directly on your local machine without a full Kubernetes cluster.

Here’s a quick example. Imagine you have a simple my-app.yaml file:

apiVersion: v1
kind: Pod
metadata:
  name: my-nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

You can run this with:

podman play kube my-app.yaml

Podman will create a pod and a container for you, pulling the nginx:latest image if it’s not already present. You can then check its status:

podman ps

And if you want to stop and clean up:

podman play kube --down my-app.yaml

This is incredibly useful for testing Kubernetes configurations or running simple applications locally without the overhead of a minikube or kind cluster. It leverages Podman’s existing container management capabilities and maps Kubernetes concepts like Pods, Deployments, Services, and ConfigMaps onto Podman’s native primitives.

The magic behind podman play kube is its ability to translate Kubernetes API objects into Podman commands. When you run podman play kube, it parses the YAML, understands the desired state, and then orchestrates local Podman containers to match that state. For a Pod, it creates a Podman pod. For a container within that Pod, it creates a Podman container inside that Podman pod. For a Service, it sets up port forwarding on your local machine to the container.

Let’s look at a slightly more complex example with a Deployment and a Service.

deployment-service.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webserver
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: webserver-svc
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer

Running podman play kube deployment-service.yaml will:

  1. Create a Podman pod named webserver (from the Deployment).
  2. Create two nginx:alpine containers within that webserver pod, managed by Podman to match the replicas: 2 spec.
  3. Create a Podman network and expose port 80 of the webserver pod to your host machine on a random available port, simulating the LoadBalancer service type.

You can see the created Podman pod:

podman pod ps

And the containers:

podman ps

The LoadBalancer service type in Kubernetes typically provisions a cloud load balancer. In podman play kube, this is translated to exposing the service’s port on the host machine. You can find the host port that was assigned by checking the output of podman play kube or by inspecting the Podman network configuration.

To get the exact port mapping, you can use podman pod inspect <pod_name> or podman port <container_name>. For example, if your pod is named webserver:

podman pod inspect webserver

Look for the PortBindings section under the Networks for your pod. It will show something like "80/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "34567" } ]. This means you can access your service via http://localhost:34567.

Podman also supports more advanced Kubernetes objects like ConfigMaps and Secrets, which are mounted as files into your containers. For example, a ConfigMap defined in YAML will be created as a file within the container at a path you specify in your Pod spec.

The --up and --down flags are your primary tools for managing the lifecycle of your Kubernetes manifests. --up applies the manifests, creating resources, and --down removes them. You can also use --replace to reapply a manifest, which is useful when you’ve made changes.

A crucial detail often overlooked is how podman play kube handles networking. When you define a Service of type LoadBalancer, Podman doesn’t magically provision an external IP. Instead, it maps the service’s targetPort on the pod to a random, available port on your host machine. This mapping is dynamic. If you bring the service down and up again, the host port might change. It’s Podman’s way of simulating external accessibility without needing a complex networking setup.

The next step in your local Kubernetes journey might involve exploring how podman play kube handles more complex relationships, like Deployments that depend on PersistentVolumeClaims, or understanding how to integrate this with Podman’s built-in image building capabilities for a truly end-to-end local development workflow.

Want structured learning?

Take the full Podman course →