Python client library for interacting with Kubernetes clusters through the Kubernetes API
—
Work with custom resource definitions, API extensions, and admission controllers. Enables extending Kubernetes with custom APIs and controllers while maintaining full client library support for dynamic resource management and custom operators.
Create and manage custom resource definitions (CRDs) that extend the Kubernetes API with new resource types.
class ApiextensionsV1Api:
def create_custom_resource_definition(
self,
body: V1CustomResourceDefinition,
dry_run: str = None,
field_manager: str = None,
pretty: str = None
) -> V1CustomResourceDefinition:
"""Create a custom resource definition."""
def list_custom_resource_definition(
self,
pretty: str = None,
allow_watch_bookmarks: bool = None,
continue_: str = None,
field_selector: str = None,
label_selector: str = None,
limit: int = None,
resource_version: str = None,
timeout_seconds: int = None,
watch: bool = None
) -> V1CustomResourceDefinitionList:
"""List custom resource definitions."""
def read_custom_resource_definition(
self,
name: str,
pretty: str = None
) -> V1CustomResourceDefinition:
"""Read specified custom resource definition."""
def patch_custom_resource_definition(
self,
name: str,
body: object,
dry_run: str = None,
field_manager: str = None,
force: bool = None,
pretty: str = None
) -> V1CustomResourceDefinition:
"""Patch specified custom resource definition."""
def delete_custom_resource_definition(
self,
name: str,
body: V1DeleteOptions = None,
dry_run: str = None,
grace_period_seconds: int = None,
orphan_dependents: bool = None,
propagation_policy: str = None,
pretty: str = None
) -> V1Status:
"""Delete specified custom resource definition."""Manage instances of custom resources using the generic custom objects API.
class CustomObjectsApi:
def create_namespaced_custom_object(
self,
group: str,
version: str,
namespace: str,
plural: str,
body: object,
dry_run: str = None,
field_manager: str = None,
pretty: str = None
) -> object:
"""Create a namespaced custom object."""
def list_namespaced_custom_object(
self,
group: str,
version: str,
namespace: str,
plural: str,
pretty: str = None,
allow_watch_bookmarks: bool = None,
continue_: str = None,
field_selector: str = None,
label_selector: str = None,
limit: int = None,
resource_version: str = None,
timeout_seconds: int = None,
watch: bool = None
) -> object:
"""List namespaced custom objects."""
def get_namespaced_custom_object(
self,
group: str,
version: str,
namespace: str,
plural: str,
name: str,
pretty: str = None
) -> object:
"""Get a namespaced custom object."""
def patch_namespaced_custom_object(
self,
group: str,
version: str,
namespace: str,
plural: str,
name: str,
body: object,
dry_run: str = None,
field_manager: str = None,
force: bool = None,
pretty: str = None
) -> object:
"""Patch a namespaced custom object."""
def delete_namespaced_custom_object(
self,
group: str,
version: str,
namespace: str,
plural: str,
name: str,
body: V1DeleteOptions = None,
dry_run: str = None,
grace_period_seconds: int = None,
orphan_dependents: bool = None,
propagation_policy: str = None,
pretty: str = None
) -> object:
"""Delete a namespaced custom object."""Manage cluster-scoped custom resources that are not namespaced.
class CustomObjectsApi:
def create_cluster_custom_object(
self,
group: str,
version: str,
plural: str,
body: object,
dry_run: str = None,
field_manager: str = None,
pretty: str = None
) -> object:
"""Create a cluster-scoped custom object."""
def list_cluster_custom_object(
self,
group: str,
version: str,
plural: str,
pretty: str = None,
allow_watch_bookmarks: bool = None,
continue_: str = None,
field_selector: str = None,
label_selector: str = None,
limit: int = None,
resource_version: str = None,
timeout_seconds: int = None,
watch: bool = None
) -> object:
"""List cluster-scoped custom objects."""
def get_cluster_custom_object(
self,
group: str,
version: str,
plural: str,
name: str,
pretty: str = None
) -> object:
"""Get a cluster-scoped custom object."""class V1CustomResourceDefinition:
api_version: str # "apiextensions.k8s.io/v1"
kind: str # "CustomResourceDefinition"
metadata: V1ObjectMeta
spec: V1CustomResourceDefinitionSpec
status: V1CustomResourceDefinitionStatusclass V1CustomResourceDefinitionSpec:
group: str
names: V1CustomResourceDefinitionNames
scope: str # "Namespaced" or "Cluster"
versions: list # List of V1CustomResourceDefinitionVersion
conversion: V1CustomResourceConversion
preserve_unknown_fields: boolclass V1CustomResourceDefinitionNames:
kind: str
plural: str
singular: str
short_names: list
categories: list
list_kind: strclass V1CustomResourceDefinitionVersion:
name: str
served: bool
storage: bool
schema: V1CustomResourceValidation
subresources: V1CustomResourceSubresources
additional_printer_columns: list
deprecated: boolfrom kubernetes import client, config
config.load_kube_config()
api = client.ApiextensionsV1Api()
# Define a CRD for a custom application
crd_manifest = {
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "CustomResourceDefinition",
"metadata": {
"name": "applications.mycompany.io"
},
"spec": {
"group": "mycompany.io",
"versions": [{
"name": "v1",
"served": True,
"storage": True,
"schema": {
"openAPIV3Schema": {
"type": "object",
"properties": {
"spec": {
"type": "object",
"properties": {
"image": {
"type": "string"
},
"replicas": {
"type": "integer",
"minimum": 1,
"maximum": 10
},
"port": {
"type": "integer"
}
},
"required": ["image", "replicas"]
},
"status": {
"type": "object",
"properties": {
"ready": {
"type": "boolean"
},
"message": {
"type": "string"
}
}
}
}
}
},
"subresources": {
"status": {}
}
}],
"scope": "Namespaced",
"names": {
"plural": "applications",
"singular": "application",
"kind": "Application",
"shortNames": ["app"]
}
}
}
# Create the CRD
try:
crd = api.create_custom_resource_definition(body=crd_manifest)
print(f"CRD created: {crd.metadata.name}")
except client.ApiException as e:
print(f"Failed to create CRD: {e}")from kubernetes import client, config
config.load_kube_config()
custom_api = client.CustomObjectsApi()
# Create a custom resource instance
application_manifest = {
"apiVersion": "mycompany.io/v1",
"kind": "Application",
"metadata": {
"name": "my-web-app",
"namespace": "default"
},
"spec": {
"image": "nginx:1.20",
"replicas": 3,
"port": 80
}
}
# Create the custom resource
try:
app = custom_api.create_namespaced_custom_object(
group="mycompany.io",
version="v1",
namespace="default",
plural="applications",
body=application_manifest
)
print(f"Application created: {app['metadata']['name']}")
except client.ApiException as e:
print(f"Failed to create application: {e}")
# List all applications
apps = custom_api.list_namespaced_custom_object(
group="mycompany.io",
version="v1",
namespace="default",
plural="applications"
)
print("Applications:")
for app in apps['items']:
name = app['metadata']['name']
replicas = app['spec']['replicas']
image = app['spec']['image']
print(f" - {name}: {replicas} replicas of {image}")from kubernetes import client, config, dynamic
config.load_kube_config()
dyn_client = dynamic.DynamicClient(client.ApiClient())
# Get the custom resource definition
applications = dyn_client.resources.get(
api_version="mycompany.io/v1",
kind="Application"
)
# Create instance using dynamic client
app_spec = {
"apiVersion": "mycompany.io/v1",
"kind": "Application",
"metadata": {
"name": "dynamic-app",
"namespace": "default"
},
"spec": {
"image": "httpd:2.4",
"replicas": 2,
"port": 8080
}
}
# Create application
app = applications.create(body=app_spec, namespace="default")
print(f"Created application: {app.metadata.name}")
# Get specific application
app = applications.get(name="dynamic-app", namespace="default")
print(f"Application status: {getattr(app, 'status', 'No status')}")
# Update application
patch_data = {
"spec": {
"replicas": 5
}
}
patched_app = applications.patch(
name="dynamic-app",
namespace="default",
body=patch_data
)
print(f"Scaled application to {patched_app.spec.replicas} replicas")from kubernetes import client, config
config.load_kube_config()
api = client.ApiextensionsV1Api()
def add_crd_version(crd_name, new_version_spec):
"""Add a new version to an existing CRD."""
# Get existing CRD
crd = api.read_custom_resource_definition(name=crd_name)
# Add new version
crd.spec.versions.append(new_version_spec)
# Update CRD
updated_crd = api.replace_custom_resource_definition(
name=crd_name,
body=crd
)
return updated_crd
# Define new version
v2_spec = {
"name": "v2",
"served": True,
"storage": False, # Keep v1 as storage version
"schema": {
"openAPIV3Schema": {
"type": "object",
"properties": {
"spec": {
"type": "object",
"properties": {
"image": {"type": "string"},
"replicas": {
"type": "integer",
"minimum": 1,
"maximum": 100 # Increased limit in v2
},
"port": {"type": "integer"},
"healthCheck": { # New field in v2
"type": "object",
"properties": {
"path": {"type": "string"},
"port": {"type": "integer"}
}
}
},
"required": ["image", "replicas"]
}
}
}
}
}
# Add version to CRD
try:
updated_crd = add_crd_version("applications.mycompany.io", v2_spec)
print(f"Added v2 to CRD. Versions: {[v['name'] for v in updated_crd.spec.versions]}")
except client.ApiException as e:
print(f"Failed to update CRD: {e}")from kubernetes import client, config
config.load_kube_config()
custom_api = client.CustomObjectsApi()
def update_application_status(name, namespace, status_data):
"""Update the status subresource of a custom application."""
try:
# Update status subresource
result = custom_api.patch_namespaced_custom_object_status(
group="mycompany.io",
version="v1",
namespace=namespace,
plural="applications",
name=name,
body={"status": status_data}
)
return result
except client.ApiException as e:
print(f"Failed to update status: {e}")
return None
# Update application status
status_update = {
"ready": True,
"message": "Application is healthy and running",
"lastUpdated": "2023-01-01T12:00:00Z",
"readyReplicas": 3
}
updated_app = update_application_status(
"my-web-app",
"default",
status_update
)
if updated_app:
print(f"Status updated for application: {updated_app['metadata']['name']}")from kubernetes import client, config, watch
config.load_kube_config()
custom_api = client.CustomObjectsApi()
w = watch.Watch()
# Watch custom resource events
print("Watching application events...")
for event in w.stream(
custom_api.list_namespaced_custom_object,
group="mycompany.io",
version="v1",
namespace="default",
plural="applications"
):
event_type = event['type']
app = event['object']
app_name = app['metadata']['name']
print(f"{event_type}: Application {app_name}")
if event_type in ['ADDED', 'MODIFIED']:
spec = app.get('spec', {})
status = app.get('status', {})
print(f" Image: {spec.get('image', 'unknown')}")
print(f" Replicas: {spec.get('replicas', 0)}")
print(f" Ready: {status.get('ready', False)}")from kubernetes import client, config
config.load_kube_config()
api = client.ApiextensionsV1Api()
custom_api = client.CustomObjectsApi()
# Create cluster-scoped CRD
cluster_crd = {
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "CustomResourceDefinition",
"metadata": {
"name": "clusters.infrastructure.mycompany.io"
},
"spec": {
"group": "infrastructure.mycompany.io",
"versions": [{
"name": "v1",
"served": True,
"storage": True,
"schema": {
"openAPIV3Schema": {
"type": "object",
"properties": {
"spec": {
"type": "object",
"properties": {
"region": {"type": "string"},
"nodeCount": {"type": "integer"},
"version": {"type": "string"}
}
}
}
}
}
}],
"scope": "Cluster", # Cluster-scoped
"names": {
"plural": "clusters",
"singular": "cluster",
"kind": "Cluster"
}
}
}
# Create cluster-scoped CRD
api.create_custom_resource_definition(body=cluster_crd)
# Create cluster-scoped custom resource instance
cluster_instance = {
"apiVersion": "infrastructure.mycompany.io/v1",
"kind": "Cluster",
"metadata": {
"name": "production-cluster"
},
"spec": {
"region": "us-west-2",
"nodeCount": 5,
"version": "1.25.0"
}
}
# Create cluster resource (no namespace parameter)
cluster = custom_api.create_cluster_custom_object(
group="infrastructure.mycompany.io",
version="v1",
plural="clusters",
body=cluster_instance
)
print(f"Created cluster: {cluster['metadata']['name']}")
# List cluster resources
clusters = custom_api.list_cluster_custom_object(
group="infrastructure.mycompany.io",
version="v1",
plural="clusters"
)
for cluster in clusters['items']:
name = cluster['metadata']['name']
region = cluster['spec']['region']
nodes = cluster['spec']['nodeCount']
print(f"Cluster {name}: {nodes} nodes in {region}")Install with Tessl CLI
npx tessl i tessl/pypi-kubernetes