CertGrid CertGrid
Hands-on Lab·Podman

Running Kubernetes YAML with Podman

`podman kube play` runs a Kubernetes manifest on a single host with no cluster, no kubelet and no API server. `podman kube down` then prints a netns error and exits 0 - the pod is gone, and the same pod built by hand tears down silently.

Pods Guide 14 of 47 Intermediate

Written against the versions above. Podman follows the distribution here rather than a vendor repository, so the version you get is the one Ubuntu shipped. The commands are stable across 5.x.

Every command on this page ran on podman01.
Server NameIP AddressOSRolesCPURAMHDD
PODMAN01192.168.0.24Ubuntu 26.04 LTSPrimary Container Host2 Core4 GB50 GB

Before you start

  1. Play it back

    One command, and the pod exists again. No cluster was involved - there is no API server, no scheduler and no kubelet on this machine.

    kube play reads the manifest, creates a pod, and creates one container per spec.containers entry. What it prints is the pod ID followed by a container ID for each.

    bash Example session
    podman kube play shop.yamlPod:91a48f41701aea32709524af38796565f8aa865927d027cfad7f322e337134b2Containers:edd8357786aef2751997b473b79cb2b72e09d839668be44fafabca933af07cef5d392f6ec1f390b903dc58dd1d364d6a8b719829d49ffbc74fccc23b9c476ccfpodman pod psPOD ID        NAME        STATUS      CREATED         INFRA ID      # OF CONTAINERS4194fc9eb7f9  shop        Running     15 seconds ago  2d5e8d85ede5  3

    Expected resultA pod ID and two container IDs, then a running pod with three containers.

    Success conditionA Kubernetes manifest is running on a host with no Kubernetes.

  2. The names changed

    This is the detail that breaks scripts, so it is worth seeing before it costs you anything.

    The manifest says storefront and cache. The running containers are shop-storefront and shop-cache - the pod name, a hyphen, then the container name.

    Podman needs container names to be unique across the whole host, while a manifest only needs them unique within the pod. Prefixing is how it reconciles the two. So the round trip is not symmetric: kube generate strips the prefix and kube play adds it back. Anything addressing a container by name - a podman exec in a script, a log collector - has to use the prefixed form.

    And it genuinely serves traffic. The hostPort from the manifest is published, so curl on the host reaches nginx.

    bash Example session
    podman ps --pod --format 'table {{.Names}} {{.Image}} {{.Status}}'NAMES               IMAGE                           STATUS91a48f41701a-infra                                  Up 1 secondshop-storefront     docker.io/library/nginx:alpine  Up 1 secondshop-cache          docker.io/library/redis:alpine  Up 1 secondcurl -s -o /dev/null -w 'http=%{http_code}\n' http://localhost:8090http=200

    Expected resultshop-storefront and shop-cache running, and http=200 from the host.

    Success conditionYou know the running name of a container the manifest called something else.

  3. Tear it down, and read the error carefully

    podman kube down shop.yaml removes the pod. It also prints this:

    Pods stopped:
    Error: stopping container a5cb6d4e001b...: removing container ... network:
    1 error occurred:
    	* rootless netns: kill network process: permission denied
    
    Pods removed:
    b3063debdee5...

    Three things about it, in order of what matters:

    1. The teardown worked. Pods removed lists the pod, and podman pod ps is empty afterwards.
    2. The exit code is 0. The word Error appears in output that reports success, so a script checking $? sees a clean run while a human reading the terminal sees a failure. If you wrap this in CI, check the exit code and not the output.
    3. It is not your fault and not intermittent. Podman failed to signal the helper process that holds the rootless network namespace, then removed everything anyway.

    This was reproduced on every attempt - three consecutive cycles on a freshly rebooted host with lingering disabled, and again here.

    bash Example session
    podman kube down shop.yamlPods stopped:Error: stopping container a5cb6d4e001ba8035d2f3eee8e8fa777d00135c9589b7dc5e59b1ac621fe4574: removing container a5cb6d4e001ba8035d2f3eee8e8fa777d00135c9589b7dc5e59b1ac621fe4574 network: 1 error occurred:	* rootless netns: kill network process: permission denied  Pods removed:b3063debdee5129b9960376fa8cc4c0aacfcd7cc45fb131bffbdf05eb32159b3Secrets removed:Volumes removed:echo "exit code was $?"exit code was 0podman pod psPOD ID      NAME        STATUS      CREATED     INFRA ID    # OF CONTAINERS

    Expected resultAn Error: line naming the netns process, a populated Pods removed, exit code 0, and no pods left.

    Success conditionThe pod is gone and you are not chasing the error message.

  4. Prove where the fault lies

    The useful question is whether that error is about pods, about published ports, or about kube down specifically. Build the same thing by hand and tear it down the ordinary way.

    Same shape: a pod with a published port, an nginx and a redis. podman pod rm -f twin prints one line, the pod ID, and nothing else.

    So the message belongs to the kube down path. Pods are fine, published ports are fine, and the ordinary teardown is silent. Practical guidance: use kube play freely, and if the noise from kube down matters to you - in a pipeline, or in a demo - podman pod rm -f removes a played pod just as completely, without the message.

    This is worth doing as a habit rather than as a one-off. An error you cannot act on is worth ten minutes of bisecting, because the alternative is learning to ignore error output.

    bash Example session
    podman pod create --name twin -p 8097:80fbe4ad83cb00d73d2b17ddf0f25ae039cacb0cbab48bf31430144935c08fbf54podman run -d --pod twin --name t1 docker.io/library/nginx:alpine692c30317c1b97d804c30a81da6926c7c5fabe68e60f01d67b6fce379cda1c0dpodman run -d --pod twin --name t2 docker.io/library/redis:alpine3d1ba7b532b5ae71dc3e0cd853579b946b7e4b1687c29b5cc2625163813a16acpodman pod rm -f twinfbe4ad83cb00d73d2b17ddf0f25ae039cacb0cbab48bf31430144935c08fbf54

    Expected resultA pod ID and nothing else from podman pod rm -f.

    Success conditionYou have narrowed the error to one command by changing one thing at a time.

Troubleshooting

Official sources