k8s
stableGenerate Kubernetes YAML manifests and validate resource names and label keys for use with kubectl or CI pipelines.
use plugin k8s Plugin snippets can be edited in the Playground, but native capabilities are executed locally with the Zolo CLI.
Functions (12)
- build_deployment_yaml Generate a Deployment manifest
- build_service_yaml Generate a Service manifest
- build_configmap_yaml Generate a ConfigMap manifest
- build_secret_yaml Generate a Secret manifest (base64 values)
- build_namespace_yaml Generate a Namespace manifest
- build_ingress_yaml Generate an Ingress manifest
- build_job_yaml Generate a batch Job manifest
- build_pvc_yaml Generate a PersistentVolumeClaim manifest
- build_labels Render a YAML labels block string
- parse_image Parse an image reference into parts
- validate_resource_name Validate a Kubernetes resource name
- validate_label_key Validate a Kubernetes label key
From import to result
- 01Import only what you use
- 02Copy the smallest example
- 03Run it with the Zolo CLI
Overview¶
k8s is a pure manifest-generation toolkit: every build_* function takes plain
arguments (and occasionally a string-keyed table) and returns a ready-to-apply
YAML string. There are no handles, no cluster connection, and no state — the
plugin never talks to an API server, so the strings it produces are safe to print,
write to a file, or pipe into kubectl apply -f -. Use it whenever you want to
template Deployments, Services, ConfigMaps, Secrets, Ingresses, Jobs, and PVCs from
Zolo code instead of hand-maintaining YAML.
Alongside the builders are two validators (validate_resource_name,
validate_label_key) that enforce Kubernetes' RFC 1123 naming rules, and a
parse_image helper that decomposes a Docker/OCI image reference into its registry,
name, and tag. The mental model is simple: validate your inputs, build each
manifest string, then concatenate them (separated by ---) into a single document.
Common patterns¶
Build a Deployment and its Service together and emit a single multi-document manifest:
use plugin k8s::{build_deployment_yaml, build_service_yaml}
let app = "api-server"
let deploy = build_deployment_yaml(app, "my-registry/api:v1.2", 3, 8080)
let svc = build_service_yaml(app, 80, 8080, "ClusterIP")
print("{deploy}\n---\n{svc}")Validate a name before generating anything, so bad input never reaches the cluster:
use plugin k8s::{validate_resource_name, build_namespace_yaml}
let name = "team-staging"
if validate_resource_name(name) {
print(build_namespace_yaml(name))
} else {
print("invalid resource name: {name}")
}Inspect an image reference, then template a Job that runs it:
use plugin k8s::{parse_image, build_job_yaml}
let ref = "my-registry.example.com/team/migrator:v2"
let parts = parse_image(ref)
print("running {parts["name"]} ({parts["tag"]}) from {parts["registry"]}")
print(build_job_yaml("db-migrate", ref, ["./migrate", "--run"]))Generate a Deployment manifest
Generates a apps/v1 Deployment YAML manifest. replicas and port default to 1 and 80 if not provided. The name is used for the metadata name, the app label, and the selector, so a single call wires up a self-consistent Deployment.
use plugin k8s::{build_deployment_yaml}
let yaml = build_deployment_yaml("api-server", "my-registry/api:v1.2", 3, 8080)
print(yaml)A single-replica internal worker on the default port:
use plugin k8s::{build_deployment_yaml}
let worker = build_deployment_yaml("queue-worker", "my-app/worker:latest", 1, 80)
print(worker)Generate a Service manifest
Generates a v1 Service manifest. target_port defaults to port. type_str defaults to "ClusterIP". Common types: "ClusterIP", "NodePort", "LoadBalancer". The selector matches the app: <name> label produced by build_deployment_yaml.
use plugin k8s::{build_service_yaml}
let yaml = build_service_yaml("api-server", 80, 8080, "ClusterIP")
print(yaml)
let lb = build_service_yaml("web", 443, 443, "LoadBalancer")
print(lb)Generate a ConfigMap manifest
Generates a v1 ConfigMap manifest from a string-keyed table of string values. Values containing YAML special characters are automatically quoted.
use plugin k8s::{build_configmap_yaml}
let yaml = build_configmap_yaml("app-config", #{
"DATABASE_URL": "postgres://db:5432/app",
"LOG_LEVEL": "info",
"MAX_CONNECTIONS": "100"
})
print(yaml)A small feature-flag config; the boolean-looking string is quoted automatically so YAML keeps it a string:
use plugin k8s::{build_configmap_yaml}
let flags = build_configmap_yaml("feature-flags", #{
"NEW_CHECKOUT": "true",
"REGION": "us-east"
})
print(flags)Generate a Secret manifest (base64 values)
Generates a v1 Secret manifest of type Opaque. All values are automatically base64-encoded, so pass the plaintext and let the plugin handle the encoding.
use plugin k8s::{build_secret_yaml}
let yaml = build_secret_yaml("app-secrets", #{
"DB_PASSWORD": "s3cr3t",
"API_KEY": "abc123xyz"
})
print(yaml)Generate a Namespace manifest
Generates a minimal v1 Namespace manifest.
use plugin k8s::{build_namespace_yaml}
let yaml = build_namespace_yaml("staging")
print(yaml)Generate an Ingress manifest
Generates a networking.k8s.io/v1 Ingress manifest with a single host/path rule of pathType: Prefix. path defaults to "/". The rule routes traffic to the named Service on service_port.
use plugin k8s::{build_ingress_yaml}
let yaml = build_ingress_yaml("web-ingress", "app.example.com", "/", "web-service", 80)
print(yaml)Route an API subpath to a dedicated backend Service:
use plugin k8s::{build_ingress_yaml}
let api = build_ingress_yaml("api-ingress", "app.example.com", "/api", "api-service", 8080)
print(api)Generate a batch Job manifest
Generates a batch/v1 Job manifest with restartPolicy: Never and backoffLimit: 4. commands is an array of strings used as the container command. Omit it or pass an empty table to use the image's default entrypoint.
use plugin k8s::{build_job_yaml}
let yaml = build_job_yaml("db-migrate", "my-app:latest", ["./migrate", "--run"])
print(yaml)Run a one-off backup job using the image's own entrypoint by passing an empty command list:
use plugin k8s::{build_job_yaml}
let backup = build_job_yaml("nightly-backup", "my-app/backup:latest", [])
print(backup)Generate a PersistentVolumeClaim manifest
Generates a v1 PersistentVolumeClaim manifest. access_mode defaults to "ReadWriteOnce". storage_class is optional and is omitted from the output entirely when not supplied.
use plugin k8s::{build_pvc_yaml}
let yaml = build_pvc_yaml("data-volume", "10Gi")
print(yaml)
let ssd = build_pvc_yaml("fast-volume", "50Gi", "ReadWriteOnce", "ssd")
print(ssd)A shared volume mounted by several pods uses ReadWriteMany:
use plugin k8s::{build_pvc_yaml}
let shared = build_pvc_yaml("shared-assets", "20Gi", "ReadWriteMany", "nfs")
print(shared)Render a YAML labels block string
Renders a YAML labels: block from a string-keyed table, with each entry indented two spaces under a labels: line. Values needing quoting are escaped. Useful for embedding into hand-written manifests.
use plugin k8s::{build_labels}
let block = build_labels(#{
"app": "api",
"env": "production",
"version": "v2"
})
print(block)Parse an image reference into parts
Parses a Docker/OCI image reference into a table with registry, name, and tag fields. The tag defaults to "latest" when absent, digests (@sha256:...) are recognized, and registry is empty for Docker Hub images. A leading component is treated as a registry only when it contains a . or : (host or port).
use plugin k8s::{parse_image}
let parts = parse_image("my-registry.example.com/team/app:v1.5")
print(parts["registry"])
print(parts["name"])
print(parts["tag"])
let hub = parse_image("nginx:alpine")
print(hub["registry"])
print(hub["name"])
print(hub["tag"])A bare image name with no tag falls back to latest:
use plugin k8s::{parse_image}
let p = parse_image("busybox")
print("{p["name"]}:{p["tag"]}")Validate a Kubernetes resource name
Returns true if name is a valid Kubernetes resource name per RFC 1123 subdomain rules: lowercase alphanumeric characters and - or ., max 253 characters, must start and end with an alphanumeric character.
use plugin k8s::{validate_resource_name}
print(validate_resource_name("my-app"))
print(validate_resource_name("My_App"))
print(validate_resource_name(""))Gate a generated manifest on a valid name so invalid input is caught early:
use plugin k8s::{validate_resource_name, build_namespace_yaml}
let name = "Prod-Env"
if validate_resource_name(name) {
print(build_namespace_yaml(name))
} else {
print("rejected: {name}")
}Validate a Kubernetes label key
Returns true if key is a valid Kubernetes label key. Keys may have an optional DNS subdomain prefix separated by / (e.g. app.kubernetes.io/name). The name part must be 63 characters or fewer, the optional prefix 253 or fewer, and both must start and end with an alphanumeric character.
use plugin k8s::{validate_label_key}
print(validate_label_key("app"))
print(validate_label_key("app.kubernetes.io/name"))
print(validate_label_key("INVALID_KEY"))