Hi! I'm your Kestra AI assistant. Ask me anything about workflows.
EXAMPLE QUESTIONS
How to schedule flow?
How to set up CI/CD for kestra flows?
How to trigger a flow after another one?
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.
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.
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.
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.
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 jobs
Shell out, parse output, hope logs survive
helm run via Shell, same caveats
Server-side apply driven by non-Git events
kubectl.Apply on any upstream trigger
Git-only by design
kubectl apply via Shell, no built-in retry or status capture
helm upgrade --install, Git-coupled
Rolling restart on event chain
kubectl.Restart task, chained after the upstream change
Manual annotation poke or Git commit
kubectl rollout restart in Shell
Re-run helm to force rollout
Read live cluster state into flow inputs
kubectl.Get with fetchType FETCH or STORE
Not in scope
kubectl get -o json, parse in Shell
helm status, parse output
Patch with Strategic Merge / JSON Merge / JSON Patch
kubectl.Patch with explicit patchType
Not the GitOps pattern
kubectl patch in Shell
Not native
Same flow, many clusters via per-task kubeconfig
kubeConfig property per task, parameterized
Argo CD project per cluster, separate setup
Multiple kubectl contexts, manual switching
Helm-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 state
Shell glue between every step
Custom CI orchestration
Self-hosted, air-gapped, OSS edition
Self-hosted by default, OSS edition free
Self-hosted on cluster
Self-hosted
Self-hosted
Beyond Kubernetes: orchestrate the rest of the stack
1300+ plugins, cross-stack
Cluster state only
Whatever you script
Helm-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.
Argo CD reconciles desired state from Git: you commit a manifest, the controller applies it. This plugin acts on the cluster directly: PodCreate runs a workload now, kubectl.Apply applies a manifest now (driven by a non-Git event), kubectl.Restart rolls a Deployment now. Use Argo CD when Git is the source of truth for what should be deployed. Use this plugin when the trigger source is upstream events (Vault rotation, a flow's prior step output, a schedule) and the cluster needs to react. Most teams run both.
PodCreate spawns a Pod from a manifest spec in a chosen namespace, streams container logs back into the Kestra execution view, supports init containers for input data (download a dataset before the main container starts) and sidecar containers for output data (upload artifacts after the main container ends), and by default deletes the Pod after completion. The Pod runs on the cluster's own nodes, so a GPU job runs on a GPU node, a high-memory job on a high-memory node, no extra infra on Kestra's side.
Yes, anything that runs as a Pod. Spark-on-Kubernetes operators expose a SparkApplication CRD that kubectl.Apply can submit. A plain Python script runs as a Pod with a Python image and args. A long-running batch job runs as a Pod with restartPolicy Never. The plugin does not impose a runtime; the Pod spec is yours. Pair with init/sidecar containers for input/output handling.
Three options. In-cluster: when Kestra runs inside the cluster, the default service account works automatically. Kubeconfig: each task accepts a kubeConfig property containing a path or inline kubeconfig YAML, read from Kestra secrets. Token-based: pair with auth.EksToken from the AWS plugin to generate a short-lived k8s-aws-v1 token for EKS, then pass via kubeConfig. Same patterns for GKE and AKS via their respective auth tasks.
kubectl.Restart targets a Deployment or StatefulSet by name in a namespace, and triggers the same rollout that kubectl rollout restart performs: the controller annotates the Pod template with a timestamp, which forces the Pods to be recreated according to the rollout strategy. waitUntilReady is ignored for this task because the rollout itself is the wait, but pair it with kubectl.Get to block downstream tasks until the rollout completes.
Yes, that is the standard pattern for multi-tenant SaaS, multi-region deployments, and DR. A ForEach over a list of (cluster, kubeconfig_secret_name) tuples runs the same task definition per cluster, reading the matching kubeconfig from Kestra secrets per iteration. Concurrency controls cap blast radius. Per-cluster errors route to an errors branch that rolls back only the affected cluster.
No. The io.kestra.plugin.kubernetes plugin ships in the open-source edition with PodCreate, kubectl.Apply, kubectl.Get, kubectl.Patch, kubectl.Delete, and kubectl.Restart. Kestra Enterprise adds Apps (typed self-service forms so developers trigger a Pod run through a UI), namespace-scoped RBAC, audit logs, worker isolation, and the Kubernetes task runner that runs every flow task itself as a Kubernetes Pod.
Yes. Kestra ships self-hosted on Docker or Kubernetes, often deployed into the same cluster it orchestrates. In-cluster authentication uses the service account by default. The OSS edition runs air-gapped with no external dependency. See Kestra for infrastructure automation for the broader picture across Kubernetes, Argo CD, Terraform, and the rest of the platform.
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.