platform.engineering/k8sofficialv0.1.14stableresource

Kubernetes resource plugin

installation
$formae plugin install k8s

Kubernetes plugin for formae

Kubernetes resource plugin for formae. This plugin enables formae to manage Kubernetes resources via Server-Side Apply, with strongly-typed Pkl schemas pinned to your cluster's exact K8s minor (v1.21 → v1.36, 16 minors).

formae · Hub · Configuration · Supported resources

Install

Requires the formae CLI: see the quick start.

formae plugin install k8s

Also included in the default plugin set: formae plugin install standard.

Restart the formae agent afterwards so it loads the plugin.

New project: with the agent running, formae project init --include k8s my-project creates my-project with a PklProject that declares the formae and k8s schema packages, so import "@k8s/..." resolves, and a starter main.pkl. Don't run it in an existing project: it overwrites both files.

Existing project: add the plugin to dependencies in your PklProject, with the current version from the hub page, then run pkl project resolve:

["k8s"] {
  uri = "package://hub.platform.engineering/plugins/k8s/schema/pkl/k8s/k8s@<version>"
}

Next: write your first forma, then formae apply (see apply modes).

With an AI coding assistant, use the formae plugin (formerly formae-mcp), which can search the hub and fetch plugin examples. The formae documentation is also available as llms.txt.

Supported Kubernetes versions

Two version ranges are in play, and they are not the same:

Range Minors What it covers
Schema trees 1.21 → 1.36 (16 minors) Typed Pkl authoring and pkl eval-time field validation. Select a minor with kubernetesVersion on the Target; omitted ⇒ most recent supported minor (1.36).
Runtime support window 1.31 → 1.36 Minors the plugin will drive against a live cluster (MinSupportedK8sVersion / MaxSupportedK8sVersion in pkg/config/version.go). Applying against a cluster outside this window returns a clear preflight error.

So schema trees exist for 1.21 → 1.30, but those minors are below the runtime floor: you can author and pkl eval against them, yet the plugin refuses to drive a live cluster older than 1.31. client-go is pinned in lockstep with the highest supported minor.

Supported Resources

This plugin supports 39 Kubernetes resource types across 16 API groups, plus a generic catch-all for arbitrary custom resources.

API Group Resource Type Description
Core K8S::Core::Namespace Virtual cluster partition that scopes names and resources.
Core K8S::Core::Pod Smallest deployable unit — one or more co-located containers.
Core K8S::Core::Service Stable network endpoint and load balancing for a set of pods.
Core K8S::Core::ConfigMap Non-confidential key/value configuration data.
Core K8S::Core::Secret Sensitive key/value data (credentials, tokens, TLS keys).
Core K8S::Core::ServiceAccount Identity for processes running in pods.
Core K8S::Core::PersistentVolume Cluster-level piece of provisioned storage.
Core K8S::Core::PersistentVolumeClaim A workload's request to bind a PersistentVolume.
Core K8S::Core::Endpoints Network addresses backing a Service.
Core K8S::Core::LimitRange Default/min/max resource constraints within a namespace.
Core K8S::Core::ResourceQuota Aggregate resource-usage limits per namespace.
Apps K8S::Apps::Deployment Declarative rollout and scaling of stateless pods.
Apps K8S::Apps::StatefulSet Ordered, stable-identity pods for stateful workloads.
Apps K8S::Apps::DaemonSet Runs one pod per (matching) node.
Apps K8S::Apps::ReplicaSet Maintains a stable set of replica pods.
Batch K8S::Batch::Job Run-to-completion workload.
Batch K8S::Batch::CronJob Schedule-driven Jobs.
Networking K8S::Networking::Ingress HTTP/HTTPS routing rules to Services.
Networking K8S::Networking::IngressClass Selects the ingress controller for an Ingress.
Networking K8S::Networking::NetworkPolicy Pod-level ingress/egress traffic rules.
RBAC K8S::Rbac::ClusterRole Cluster-wide permission set.
RBAC K8S::Rbac::ClusterRoleBinding Binds a ClusterRole to subjects cluster-wide.
RBAC K8S::Rbac::Role Namespace-scoped permission set.
RBAC K8S::Rbac::RoleBinding Binds a Role/ClusterRole within a namespace.
Storage K8S::Storage::StorageClass Dynamic volume-provisioning profile.
Storage K8S::Storage::CSIDriver Registration of a CSI storage driver.
Admission Registration K8S::Admissionregistration::MutatingWebhookConfiguration External mutating admission webhooks.
Admission Registration K8S::Admissionregistration::ValidatingWebhookConfiguration External validating admission webhooks.
Admission Registration K8S::Admissionregistration::MutatingAdmissionPolicy In-tree, CEL-based mutation (GA in 1.36, KEP-3962); v1.36+ schema trees only.
API Extensions K8S::Apiextensions::CustomResourceDefinition Defines a new custom resource kind; blocks until Established.
Custom K8S::Custom::Resource Generic catch-all for any CRD instance (free-form spec, no per-CRD code).
Autoscaling K8S::Autoscaling::HorizontalPodAutoscaler Scales workload replicas on observed metrics.
Policy K8S::Policy::PodDisruptionBudget Minimum availability during voluntary disruptions.
Scheduling K8S::Scheduling::PriorityClass Pod scheduling priority.
Coordination K8S::Coordination::Lease Lightweight lock for leader election / node heartbeats.
Flow Control K8S::Flowcontrol::FlowSchema Classifies API requests into priority levels (APF).
Flow Control K8S::Flowcontrol::PriorityLevelConfiguration Concurrency limits per priority level (APF).
Node K8S::Node::RuntimeClass Selects the container runtime configuration for pods.
Helm K8S::Helm::Release A Helm chart installed as one resource, applied by the embedded Helm SDK.

MutatingAdmissionPolicy reached GA in K8s 1.36 (KEP-3962) and is only present in the v1.36+ schema trees; it cannot be referenced when kubernetesVersion is set to an earlier minor.

Custom resources. K8S::Custom::Resource manages any CRD instance (cert-manager Certificate, Argo Application, and so on) through a generic catch-all — no per-CRD Go code or generated schema. A CRD and instances of the kind it defines can live in one forma and deploy in a single formae apply. Both custom types are discoverable = false, so they are managed via explicit declaration only, not surfaced by discovery.

See schema/pkl/ for the complete list of supported resource types.

Configuration

Target Configuration

Configure a Kubernetes target in your Forma file:

import "@formae/formae.pkl"
import "@k8s/k8s.pkl" as k8s

target: formae.Target = new formae.Target {
  label = "k8s-target"
  namespace = "K8S"
  config = new k8s.Config {
    kubernetesVersion = "1.31"          // K8s minor — selects the schema subtree
    auth = new k8s.KubeconfigAuth {}    // see Credentials below
  }
}

Config fields:

Field Type Purpose
kubernetesVersion String K8s minor (e.g. "1.31"). Selects the schema subtree the plugin validates against. Supported: "1.21", "1.22", "1.23", "1.24", "1.25", "1.26", "1.27", "1.28", "1.29", "1.30", "1.31", "1.32", "1.33", "1.34", "1.35", "1.36". Omitted ⇒ assumes the most recent supported minor (currently 1.36).
auth Auth One of KubeconfigAuth, EKSAuth, GKEAuth, AKSAuth, OVHAuth, OCIAuth, InClusterAuth.

Every namespaced resource MUST set metadata.namespace. Reference a K8S::Core::Namespace declared in the same Forma to keep it single-sourced:

import "@k8s/k8s.pkl" as k8s
import "@k8s/v1.31/core/Namespace.pkl" as ns
import "@k8s/v1.31/core/ConfigMap.pkl" as cm

local appNs = new ns.Namespace {
  label = "my-app-ns"
  metadata = new ns.NamespaceMetadata { name = "my-app" }
}

local appConfig = new cm.ConfigMap {
  label = "my-app-config"
  metadata = new k8s.NamespacedObjectMeta {
    name = "my-app-config"
    namespace = appNs.res.name   // resolvable ref into the Namespace above
  }
  data { "log.level" = "info" }
}

Credentials

The plugin supports six authentication strategies. Configure via the auth field on k8s.Config:

Kubeconfig (local development, any pre-configured cluster):

auth = new k8s.KubeconfigAuth {
  context = "kind-formae-test"        // optional — defaults to current-context
  kubeconfig = "/path/to/kubeconfig"  // optional — defaults to $KUBECONFIG / ~/.kube/config
}

Managed clusters (EKSAuth, GKEAuth, AKSAuth, OVHAuth, OCIAuth) — each takes the cluster endpoint, CA, and provider-specific identifiers, with auth tokens minted from your existing cloud session. See schema/pkl-main/target.pkl for the field shapes.

In-cluster (when formae itself runs as a Pod):

auth = new k8s.InClusterAuth {}

The Pod's ServiceAccount token at /var/run/secrets/kubernetes.io/serviceaccount/ is used automatically.

Helm charts

A chart is installed as a single K8S::Helm::Release, driven by the Helm SDK embedded in the plugin. formae manages the release; Helm manages the objects the chart renders, so hooks, hook weights, CRD install ordering and revision history all work — and helm list, helm history and helm rollback see the release.

import "@k8s/helm/Release.pkl" as helm

No version segment, unlike every other schema import: no field on a release has a shape that depends on the apiserver minor, so this module ships once at the package root instead of in each v<X.Y>/ tree. No pkl-reader-helm on PATH and no helm repo add either: the plugin embeds the SDK and nothing is rendered at Pkl-eval time.

See examples/helm/ for runnable formae and the drift and adoption scenarios.

Examples

The examples/ directory has runnable forma files covering two patterns.

Cross-cloud workloads

Each workload is a directory of per-cloud entry files — examples/<workload>/<cloud>.pkl, where <cloud> is one of aws, azure, gcp, oci, or local (a kubeconfig-accessible cluster). Pick a cloud by choosing the matching file.

Example Description
bookstore Frontend + backend webapp on a managed cluster
crossplane Crossplane control plane on a managed cluster
lgtm-observability Grafana + Loki + Tempo + Mimir + OTel + MinIO observability stack
# Resolve Pkl deps once per fresh clone
pkl project resolve examples/

# Pick a cloud by choosing the matching file
formae apply --mode reconcile examples/bookstore/local.pkl
formae apply --mode reconcile examples/bookstore/aws.pkl
formae apply --mode reconcile examples/lgtm-observability/azure.pkl
formae apply --mode reconcile examples/crossplane/gcp.pkl

Each workload example has a per-directory README with prerequisites, smoke test commands, and per-provider tear-down steps.

Helm charts

The examples/helm/ directory installs charts as K8S::Helm::Release resources via @k8s/helm/Release.pkl.

File What it deploys
release-nginx.pkl bitnami/nginx from an OCI registry
release-kratos.pkl ory/kratos from an HTTP repo, with values
drift-helm-upgrade/ formae deploys, helm upgrade drifts it, formae reconciles
adopt-and-rollback/ adopt a helm install, upgrade with formae, roll back with Helm
immutable-field-upgrade/ a chart upgrade no tool can perform, refused the same way by formae and by Helm
pkl project resolve examples/
pkl eval examples/helm/release-nginx.pkl --project-dir examples/
formae apply examples/helm/release-nginx.pkl --mode reconcile --yes
formae destroy examples/helm/release-nginx.pkl --yes

Targets

Pick a cloud by choosing examples/<workload>/<cloud>.pkl:

Provider Auth class Cluster type Required setup
aws EKSAuth EKS AutoMode aws configure; defaults to us-west-2
azure AKSAuth AKS az login; set AZURE_SUBSCRIPTION_ID and AZURE_PRINCIPAL_ID (your AAD object id from az ad signed-in-user show --query id -o tsv)
gcp GKEAuth Standard zonal GKE gcloud auth application-default login; set GCP_PROJECT=<your-project> (or GOOGLE_CLOUD_PROJECT)
oci OCIAuth OKE oci session authenticate; set OCI_COMPARTMENT_ID=<ocid>
local KubeconfigAuth none — uses your kubectl context kubectl config current-context should resolve to the target cluster

The cluster-provisioning code lives under examples/clusters/; each provider's <cloud>.pkl is a Pkl module exposing resources(slug) and target(slug) functions that the workload examples consume. To add a new provider, create examples/clusters/<provider>.pkl exposing resources(slug) and target(slug), then add a <provider>.pkl entry file in each workload directory.

License

This plugin is licensed under the Functional Source License, Version 1.1, ALv2 Future License (FSL-1.1-ALv2).

Copyright 2026 Platform Engineering Labs Inc.

type
resource
category
containers
license
FSL-1.1-ALv2
originator
platform.engineering
namespace
K8S
latest
v0.1.14 · stable
platforms
—
repo
github.com/platform-engineering-labs/formae-plugin-kubernetes
versions (21)
v0.1.14stable
2026-10-20
v0.1.13stable
2026-09-22
v0.1.13-dev.2dev
2026-09-21
v0.1.13-dev.1dev
2026-09-19
v0.1.13-dev.0dev
2026-09-18
v0.1.12stable
2026-09-15
v0.1.11stable
2026-09-07
v0.1.10stable
2026-08-30
v0.1.10-dev.1dev
2026-08-21
v0.1.10-dev.0dev
2026-08-11
v0.1.11-dev.0devyanked
2026-08-11
·yanked by — · 2mo ago· reason: wrong version
v0.1.9stable
2026-07-27
v0.1.8stable
2026-07-24
v0.1.7stable
2026-07-16
v0.1.6stable
2026-06-25
v0.1.6-devdev
2026-06-24
v0.1.5stable
2026-06-12
v0.1.4stable
2026-06-12
v0.1.3stable
2026-06-05
v0.1.2stable
2026-05-13
v0.1.1stableyanked
2026-05-13
·yanked by — · 5mo ago