Kubernetes Python Client
Official Python client for the Kubernetes API. Current version: 35.0.0 (Mar 2026). Client major version maps to Kubernetes server minor version (client 35.x ≈ k8s 1.35). Versions jumped from 12.x to 17.x — not a mistake. Two config methods: load_kube_config() for local (~/.kube/config) and load_incluster_config() for pods. Must use stream() module for exec/attach — direct call removed in v4. Still pre-1.0 in practice despite high version numbers.
Warnings
- breaking Client major version must match Kubernetes server minor version. Client 35.x works with k8s 1.35. Mismatched versions cause ApiException or missing API objects.
- breaking Version numbers jumped from 12.x to 17.x — not a typo. Versions 13-16 were skipped to align with Kubernetes minor versions.
- breaking Direct exec/attach calls (v1.connect_get_namespaced_pod_exec()) removed in v4. Must use stream.stream() wrapper.
- gotcha load_kube_config() fails inside Kubernetes pods. load_incluster_config() fails outside pods. Code using only one will break in the other environment.
- gotcha load_incluster_config() raises ConfigException 'Service host/port is not set' when KUBERNETES_SERVICE_HOST env var is missing — i.e. when not running inside a pod.
- gotcha list_* API calls return a V1PodList with .items — not a plain list. Must iterate .items not the response object itself.
- gotcha Watch API streams indefinitely unless stopped or _request_timeout is set. Omitting timeout in production causes memory leaks.
Install
-
pip install kubernetes
Imports
- config loading (local + in-cluster)
from kubernetes import client, config # Correct: handle both local and in-cluster try: config.load_incluster_config() # running inside a pod except config.ConfigException: config.load_kube_config() # running locally v1 = client.CoreV1Api() pods = v1.list_pod_for_all_namespaces(watch=False) for pod in pods.items: print(f'{pod.metadata.namespace}/{pod.metadata.name}') - exec into pod (stream module)
from kubernetes import client, config, stream config.load_kube_config() v1 = client.CoreV1Api() # Must use stream() wrapper for exec/attach resp = stream.stream( v1.connect_get_namespaced_pod_exec, 'my-pod', 'default', command=['ls', '/'], stderr=True, stdin=False, stdout=True, tty=False ) print(resp)
Quickstart
# pip install kubernetes
from kubernetes import client, config
# Load config — handles both local and in-pod
try:
config.load_incluster_config()
except config.ConfigException:
config.load_kube_config()
# Core API — pods, namespaces, nodes
v1 = client.CoreV1Api()
# List pods in all namespaces
pods = v1.list_pod_for_all_namespaces(watch=False)
for pod in pods.items:
print(f'{pod.metadata.namespace}/{pod.metadata.name}: {pod.status.phase}')
# Apps API — deployments
apps_v1 = client.AppsV1Api()
deployments = apps_v1.list_deployment_for_all_namespaces()
for d in deployments.items:
print(f'{d.metadata.name}: {d.spec.replicas} replicas')
# Get specific pod
pod = v1.read_namespaced_pod(name='my-pod', namespace='default')
print(pod.status.pod_ip)