Skip to content

Kubernetes

The Kubernetes provider manages resources inside Kubernetes clusters — namespaces, deployments, services, ingresses, ConfigMaps, Secrets, PersistentVolumeClaims, and Helm releases.

The Kubernetes provider uses your local kubeconfig, just like kubectl:

Terminal window
export KUBECONFIG=/path/to/kubeconfig # optional, defaults to ~/.kube/config

Or use an in-cluster config when running inside a pod:

Terminal window
# In-cluster config is auto-detected when KUBECONFIG is unset

Kyku communicates with the Kubernetes API server directly via the @kubernetes/client-node SDK — no kubectl subprocesses. Resource managers translate Kyku resource types to native Kubernetes API objects (apps/v1.Deployment, v1.Service, v1.ConfigMap, etc.).

Resource K8s API Object Status
K8sNamespace v1.Namespace
K8sConfigMap v1.ConfigMap
K8sSecret v1.Secret
K8sPersistentVolumeClaim v1.PersistentVolumeClaim
K8sDeployment apps/v1.Deployment
K8sStatefulSet apps/v1.StatefulSet
K8sService v1.Service
K8sIngress networking/v1.Ingress
K8sManifest Raw manifest (inline/file/dir)
K8sHelmRelease Helm chart deployment
K8sCluster Cloud K8s cluster (EKS/GKE/DOKS)

The KubernetesCluster resource provisions a managed Kubernetes cluster on a cloud provider:

Cloud Service
AWS EKS
GCP GKE
DigitalOcean DOKS
Hetzner ❌ (UnsupportedFeatureError)

Once a cluster exists, all K8s resource types reference it:

const cluster = new KubernetesCluster({
id: 'cluster-prod',
name: 'prod-cluster',
version: '1.28',
vpc: myVpc,
});
const namespace = new K8sNamespace({
id: 'ns-app',
name: 'app',
cluster: cluster,
});
const deployment = new K8sDeployment({
id: 'deploy-api',
name: 'api-server',
cluster: cluster,
namespace: namespace,
replicas: 3,
containers: [{
image: 'nginx:1.25',
ports: [{ containerPort: 80 }],
}],
});

K8s resources participate in the Kyku dependency graph:

K8sNamespace ──┐
├── K8sConfigMap ──┐
├── K8sSecret ─────┤
├── K8sPersistentVolumeClaim ──┤
│ ├── K8sDeployment ──┐
│ ├── K8sStatefulSet ─┤
│ ├── K8sService ──┐
│ ├── K8sIngress
└── K8sManifest / K8sHelmRelease (independently)

Use kyku graph to verify the dependency chain before applying.

All K8s resources share a common base:

Property Type Required Description
cluster KubernetesCluster | string Target cluster
namespace K8sNamespace | string Namespace (defaults to default)
dependsOn string[] Explicit dependency ordering

K8sManifest supports arbitrary Kubernetes manifests:

// Inline YAML
new K8sManifest({
id: 'custom-crd',
name: 'custom-crd',
cluster: cluster,
manifest: { apiVersion: 'example.com/v1', kind: 'CustomResource', ... }
});
// File path
new K8sManifest({
id: 'app-manifest',
name: 'app-manifest',
cluster: cluster,
manifestPath: './k8s/app.yaml',
});

K8sHelmRelease deploys Helm charts:

new K8sHelmRelease({
id: 'helm-nginx',
name: 'nginx-ingress',
cluster: cluster,
chart: 'ingress-nginx/ingress-nginx',
version: '4.8.0',
values: { controller: { replicas: 2 } },
});

Every typed K8s resource (Namespace, ConfigMap, Secret, PersistentVolumeClaim, Deployment, StatefulSet, Service, Ingress) accepts a customConfig object — see Custom Config. It deep-merges into the same target the pre-existing raw spec field on Deployment/StatefulSet/Ingress already used, applied after spec so customConfig wins on overlap. Because every apply is a server-side-apply PATCH (always safe to re-run), changing customConfig plans an in-place update rather than a destructive replace. K8sManifest and K8sHelmRelease reject customConfig — the manifest/chart input you give them already is the full escape hatch.

K8s resources depend on a KubernetesCluster. The cluster must be provisioned before any K8s resources can be applied. Kyku’s dependency graph enforces this ordering automatically.

K8sManifest applies manifests via kubectl apply semantics — it does not deep-merge. Large changes to raw manifests may require manual intervention.

Helm releases are tracked in Kyku state. Manual helm upgrade outside Kyku will cause drift.