Run Pods inside Kubernetes as flow steps.

Schedule a Pod with GPU as a task and stream container logs back to the Kestra execution view. Server-side apply manifests on event, restart Deployments after Secret rotation, patch ConfigMaps when an upstream value changes, and run the same flow across many clusters from one definition.

Direct cluster API, not GitOps reconciliation.

Argo CD reconciles what should be deployed from Git. This plugin acts on the cluster directly: spawns Pods as flow steps, patches Secrets, rolls Deployments, reads live state into flow inputs. Two complementary patterns, two different sources of truth, both first-class in Kestra.

PodCreate runs a workload inside the cluster, no shell-out

PodCreate spawns a Pod from a manifest spec, streams container logs back into the Kestra execution view, handles file upload via init containers and download via sidecars, and deletes the Pod by default after completion. Run a 50GB Python training job, a Spark batch on EMR-on-EKS, or a CUDA workload using the cluster's own GPU nodes. No kubectl in a Shell task, no separate Kestra runner with GPUs.

Server-side apply when the source of truth isn't Git

kubectl.Apply runs server-side apply on YAML or JSON manifests with optional waitUntilReady. Drive the apply from any upstream event: a Vault secret rotation, a config value updated in a non-Git source, an approval gate that just passed. Argo CD reconciles from Git; this task applies directly when the source of truth is upstream events.

Rolling restart on event, not on annotation-poke

kubectl.Restart triggers a rolling restart on a Deployment or StatefulSet by name. Chain it after Secret rotation, ConfigMap update, or external dependency change. The kubectl rollout restart annotation pattern, but driven by an event chain rather than a human running a command. waitUntilReady is ignored here because the rollout itself is the wait.

Patch and Get for surgical changes and state reads

kubectl.Patch applies Strategic Merge (default), JSON Merge, or JSON Patch operations to a namespaced resource. waitUntilReady ensures reconciliation before downstream tasks fire. kubectl.Get reads resources into the flow context, so a ConfigMap value, a Deployment status, or a list of Pods matching a label all become flow inputs without parsing kubectl output.

Delete by kind and name, scoped to the namespace

kubectl.Delete removes named resources of a given kind from a namespace. Use to tear down test environments, clean up ephemeral preview deployments tied to closed PRs, or remove a tenant's resources when an offboarding flow fires. Namespaced resources only, with explicit apiGroup and apiVersion.

Same flow, different clusters via kubeconfig

Every task accepts a kubeconfig path or inline config from Kestra secrets. Run the same flow definition against staging, prod, or a per-customer tenant cluster by parameterizing the kubeconfig per execution. EKS, GKE, AKS, OpenShift, on-prem K8s all addressable from one flow. Pair with the EksToken task from the AWS plugin for short-lived EKS authentication.

How platform teams use Kubernetes and Kestra

Patterns engineering teams run in production today. Each one shows the flow end to end, with the real plugin classes in play.

Compute

Train an ML model on the cluster's GPU nodes from a flow

PodCreate spawns a Pod with nvidia.com/gpu: 1 and a node selector for the GPU pool. An init container mounts the training dataset from S3. The main container runs the training script. A sidecar uploads the model artifact and metrics back to Kestra internal storage. Logs stream into the execution view in real time, so a 4-hour training run is debuggable as it happens, not after it finishes.

Cluster's GPUs, not a separate Kestra worker

The expensive node pool the cluster already runs. No duplicate hardware on the orchestrator side.

Init + sidecar handle data movement

Input dataset mounted before the main container starts; output artifact uploaded after it ends. Same Pod lifecycle.

Logs streamed live to the execution view

Long-running jobs surface their progress in Kestra without external log shipping.

Pod is cleaned up after completion

Default behavior. Set a different lifecycle if you need to keep the Pod around for forensics.

scheduled trigger
or webhook
create gpu pod
PodCreate
stream logs
container output
collect artifact
via sidecar
register model
external registry
notify
Slack with metrics
Secret rotation

Rotate a Vault secret, restart the Deployments that read it

A scheduled flow rotates the DB credential in Vault. Pods read the secret via the Vault sidecar, but they need a restart to pick up the new value if the sidecar caches. kubectl.Patch annotates the affected Deployments with a rollout timestamp; kubectl.Restart triggers a rolling restart; kubectl.Get polls Available replicas until the rollout completes. One flow, one execution ID across Vault and Kubernetes.

Rotation is one flow, not two systems

Vault, the Patch, the Restart, the wait, the notify. One execution to audit, one place to debug a failure.

Per-Deployment scope

Patch and Restart take resource names. List the Deployments that consume the rotated secret; the flow handles each.

Wait gated on real readiness

kubectl.Get with waitUntilReady polls until Available replicas equal desired. No fixed sleep, no flaky timing.

weekly schedule
cron
rotate in vault
new credential
patch deployments
annotate rollout
rolling restart
all reading pods
wait for ready
Available = desired
notify
Slack confirm
State-driven

Promote staging to prod only if Pods are Ready

After kubectl.Apply ships the new manifest to staging, kubectl.Get fetches the Deployment status. An If task branches on the Ready replica count vs desired. If matched, the flow applies the same manifest to prod. If not, the flow opens a GitHub issue with the failing namespace and Pod statuses, then stops. Promotion gated on cluster reality, never on a 'should be ready by now' sleep.

Gate on actual cluster state

Available replicas, Ready conditions, Pod phases. Not on a 'wait 5 minutes and hope' pattern.

Two environments, one manifest

Same YAML applied to staging and to prod. The branch only decides whether to promote, never what to apply.

Failure produces context, not silence

An errors branch opens a GitHub issue with the namespace, the failing Deployment, and the Pod statuses captured by Get.

release trigger
manual or schedule
apply staging
server-side apply
read status
kubectl.Get
ready?
branch on replicas
apply prod
same manifest
open issue on fail
errors branch
Multi-cluster

Apply the same manifest to every tenant cluster in parallel

A SaaS platform team runs one K8s cluster per customer tenant. A release flow iterates a list of (tenant_name, kubeconfig_secret) tuples via ForEach. Each iteration runs kubectl.Apply against the tenant cluster, waits for Ready, posts per-tenant status to Slack. The same flow definition spans all tenants. No per-cluster pipeline, no duplicated YAML, no separate CI per customer.

Kubeconfig per tenant, in Kestra secrets

One secret per cluster. The flow reads the right kubeconfig per iteration. No long-lived static creds in the flow YAML.

Parallel apply across tenants

ForEach with concurrency runs all tenant applies at once. A blast-radius limit caps concurrency for safety.

Per-tenant rollback path

If a tenant apply fails, the errors branch kubectl.Apply's the previous manifest revision for that tenant only.

release trigger
manual
fetch tenant list
from inventory
ForEach tenant
parallel
apply manifest
per-cluster kubeconfig
wait ready
kubectl.Get
per-tenant status
Slack per tenant

Blueprints for Kubernetes orchestration.

One blueprint per use case above. Copy the YAML, set the kubeconfig in Kestra secrets, point at your cluster, ship it.

Run a GPU Pod and collect its artifact
Vault rotation, patch and restart Deployments
Multi-cluster apply across tenant clusters

PodCreate with GPU request, stream logs, save the model artifact

Spawns a Pod with a GPU resource request on a node selector for the GPU pool. The main container runs a training script; a sidecar collects the resulting model file and writes it to Kestra internal storage. Slack confirms with the artifact URI and runtime metrics.

Explore Blueprints

Rotate a Vault secret, restart every Deployment that reads it

Calls the Vault rotation endpoint, then iterates the list of Deployments that consume the secret. Per Deployment: kubectl.Patch annotates with a rollout timestamp, kubectl.Restart triggers the rolling restart, kubectl.Get waits for Available replicas to match desired.

Explore Blueprints

ForEach tenant: apply the same manifest, wait for Ready, report per tenant

Fetches the tenant list from an inventory API, iterates with parallel ForEach, applies the release manifest to each tenant cluster using the matching kubeconfig from Kestra secrets, waits for Ready, and posts per-tenant status to Slack. Failures route to an errors branch that rolls back that tenant only.

Explore Blueprints

Kestra vs Kubernetes orchestration alternatives

Capability
Argo CD (GitOps reconciliation)
kubectl in a Shell task
Helm + custom CI script
Run a Pod as a first-class flow step with log streaming
PodCreate streams container logs to the execution view
Out of scope, Argo CD deploys workloads, does not run jobsShell out, parse output, hope logs survivehelm run via Shell, same caveats
Server-side apply driven by non-Git events
kubectl.Apply on any upstream trigger
Git-only by designkubectl apply via Shell, no built-in retry or status capturehelm upgrade --install, Git-coupled
Rolling restart on event chain
kubectl.Restart task, chained after the upstream change
Manual annotation poke or Git commitkubectl rollout restart in ShellRe-run helm to force rollout
Read live cluster state into flow inputs
kubectl.Get with fetchType FETCH or STORE
Not in scopekubectl get -o json, parse in Shellhelm status, parse output
Patch with Strategic Merge / JSON Merge / JSON Patch
kubectl.Patch with explicit patchType
Not the GitOps patternkubectl patch in ShellNot native
Same flow, many clusters via per-task kubeconfig
kubeConfig property per task, parameterized
Argo CD project per cluster, separate setupMultiple kubectl contexts, manual switchingHelm-per-cluster, custom CI logic
Chain with non-K8s tasks (Vault, GitHub, Slack)
Outputs flow forward into any plugin task
Argo CD focuses on cluster stateShell glue between every stepCustom CI orchestration
Self-hosted, air-gapped, OSS edition
Self-hosted by default, OSS edition free
Self-hosted on clusterSelf-hostedSelf-hosted
Beyond Kubernetes: orchestrate the rest of the stack
1300+ plugins, cross-stack
Cluster state onlyWhatever you scriptHelm-centric

Kubernetes & Kestra: common questions

Find answers to your questions right here, and don't hesitate to Contact Us if you couldn't find what you're looking for.

See How

Ready to run Pods inside your cluster from a flow?

Spawn GPU Pods as flow steps, restart Deployments after Secret rotation, gate prod on staging readiness, and run the same flow across every tenant cluster. Open source, self-hosted, event-driven.