Pulumi vs. Kubernetes YAML Manifests
Pulumi and Kubernetes YAML manifests are both declarative ways to define the desired state of infrastructure. Pulumi lets you define infrastructure in general-purpose languages (Python, TypeScript, JavaScript, Go, C#, Java, or YAML) across any cloud or SaaS provider; Kubernetes YAML manifests are the native configuration format of the Kubernetes API and describe Kubernetes objects only.
This page covers what each tool is, a feature-by-feature comparison, the most important differences in detail, and the available paths for adopting Pulumi alongside or instead of Kubernetes YAML manifests.
What is Pulumi?
Pulumi is an infrastructure as code platform for provisioning and managing resources across any cloud or SaaS platform. Pulumi programs are written in general-purpose programming languages — Python, TypeScript, JavaScript, Go, .NET, and Java — as well as YAML. The Pulumi Registry covers all major clouds, including first-party native providers that are generated from upstream API schemas for same-day coverage of new platform features. The Pulumi CLI and SDKs are open source under the Apache 2.0 license. Pulumi Cloud is the commercial product that adds managed state, secrets, RBAC, audit logs, policy management, and other features for running Pulumi at organizational scale.
For users coming from Kubernetes YAML, Pulumi maintains a first-party Kubernetes provider generated from the Kubernetes OpenAPI spec, so every Kubernetes API object is available with the same fidelity as a hand-written manifest. The same Pulumi program can also provision the cluster itself and any non-Kubernetes cloud resources it depends on.
What are Kubernetes YAML manifests?
Kubernetes YAML manifests are the native declarative configuration format of the Kubernetes API. Each manifest is a YAML (or JSON) document describing the desired state of a Kubernetes API object — a Deployment, Service, ConfigMap, Namespace, and so on. Manifests are applied to a cluster with kubectl apply or by a GitOps controller such as Argo CD or Flux, and the Kubernetes control plane reconciles the cluster toward the state they describe.
Kubernetes is an open-source project governed by the Cloud Native Computing Foundation and licensed under Apache 2.0. Manifests target any conformant Kubernetes cluster — Amazon EKS, Azure AKS, Google GKE, or self-managed — but can only describe Kubernetes resources; cloud resources outside the cluster require separate tooling or an in-cluster operator. There is no separate state file: the live cluster, backed by etcd, is the source of truth, and kubectl apply tracks managed fields directly on each object. Manifests have no commercial product of their own — they are simply the input format of the Kubernetes API — and Kustomize is the common native tool for layering and patching them.
Detailed comparison
| Feature | Pulumi | Kubernetes YAML Manifests |
|---|---|---|
| Language support | Python, TypeScript, JavaScript, Go, C#, Java, and YAML — general-purpose languages with familiar syntax for loops, conditionals, and abstractions | YAML or JSON documents describing Kubernetes API objects; no loops, conditionals, or variables. Kustomize adds bases and overlays but remains declarative YAML |
| Cloud and service support | Pulumi Registry of packages, including bridged, native, parameterized, and dynamic providers; first-party native providers for Kubernetes and Azure Native generated from upstream API schemas; any Terraform provider can be adapted into a Pulumi provider | Kubernetes API objects only, on any conformant cluster (EKS, AKS, GKE, or self-managed); non-Kubernetes cloud resources require separate tooling or an in-cluster operator such as AWS Controllers for Kubernetes or Crossplane |
| Transpiled to another format? | No — programs run directly in their host language | No — manifests are sent directly to the Kubernetes API server |
| State management | Managed by Pulumi Cloud by default; self-managed backends include Amazon S3, Azure Blob Storage, Google Cloud Storage, local files, and others | No separate state file; the live cluster (etcd) is the source of truth, and kubectl apply records managed fields via server-side apply |
| Secrets management | Encrypted in transit and at rest in the state file by default, with per-stack encryption keys; pluggable KMS providers (AWS KMS, Azure Key Vault, Google Cloud KMS, HashiCorp Vault) | Kubernetes Secret objects are base64-encoded, not encrypted, in the manifest; encryption at rest in etcd is configured separately at the cluster level |
| Execution model | Local CLI, programmatic via Automation API, or remote runs in Pulumi Deployments | Local kubectl CLI against a cluster, or a GitOps controller (Argo CD, Flux) running inside the cluster; no centralized service ships with Kubernetes itself |
| Rollback on failed operation | Failed updates leave the stack in a partially updated state; subsequent pulumi up runs reconcile toward the desired state, and you can roll forward by reverting program code | kubectl apply has no transactional rollback; workload controllers support kubectl rollout undo for revision history, and re-applying a previous manifest reconciles back |
| Programmatic API for tools and platforms | Automation API — a programmatic SDK for building custom CLIs, internal developer platforms, and services that drive up, preview, and destroy without shelling out to the Pulumi CLI | The Kubernetes API and client libraries operate on individual objects, but there is no orchestration SDK for driving a full apply/preview/destroy lifecycle |
| Modularity and reuse | Component Resources authored in any supported language; Pulumi Packages let a component written in one language be consumed from any Pulumi language; language-native package managers (npm, PyPI, NuGet, Maven, Go modules); and the Pulumi Registry for publicly available packages | Reuse is by copying manifests or by Kustomize bases and overlays; there is no package manager or typed interface for sharing manifest libraries |
| Import existing resources | pulumi import and the import resource option, both of which generate code in your language | The cluster is itself the source of truth; kubectl get -o yaml exports an object’s current state as a manifest |
| Policy as code | Pulumi Policies — open source, with rules written in Python, TypeScript, or Open Policy Agent Rego; Pulumi Cloud commercial plans add centralized policy management plus Pulumi-maintained policy packs for compliance frameworks like CIS and PCI DSS | No built-in policy-as-code; admission controllers such as OPA Gatekeeper or Kyverno enforce policy inside the cluster as a separate component |
| Open source | Yes — Apache License 2.0 | Yes — Kubernetes and kubectl are Apache License 2.0 |
| Commercial option | Pulumi Cloud | None — manifests are the input format of the Kubernetes API; managed Kubernetes is sold by cloud providers, but the manifest format itself has no commercial tier |
Key differences
Language support and the authoring experience
Kubernetes YAML manifests are static documents: each one describes a single object’s desired state with no loops, conditionals, or variables. Generating many similar objects, or parameterizing them per environment, means copying YAML or layering Kustomize overlays on top of base manifests. Pulumi programs are written in general-purpose languages, so authors get loops, conditionals, functions, classes, package management, IDE features (autocomplete, type checking, refactoring, go-to-definition), and the testing frameworks that already exist in those ecosystems — while still producing the same Kubernetes API objects. Pulumi also supports YAML for users who prefer a markup format.
Cloud and service coverage
Kubernetes YAML manifests describe Kubernetes API objects and nothing else. Provisioning the cluster they run on, or the cloud resources an application depends on — a managed database, an object store, a DNS record — requires separate tooling, or an in-cluster operator such as AWS Controllers for Kubernetes or Crossplane that maps cloud resources onto Kubernetes objects. Pulumi pulls from the Pulumi Registry, which covers all major clouds and SaaS platforms, and includes a first-party Kubernetes provider generated from the Kubernetes OpenAPI spec. A single Pulumi program can provision an EKS, AKS, or GKE cluster, deploy workloads to it, and create the cloud resources those workloads use — without switching tools.
Execution and rollbacks
Manifests are applied with the local kubectl CLI or by an in-cluster GitOps controller such as Argo CD or Flux; Kubernetes itself ships no centralized orchestration service. Pulumi runs through the local CLI, programmatically through the Automation API, or remotely through Pulumi Deployments. Neither approach performs a transactional rollback on failure: kubectl apply leaves successfully applied objects in place, and workload controllers offer kubectl rollout undo against revision history, while Pulumi leaves the stack partially updated and reconciles on the next run. The difference is in surface area — Pulumi adds a preview step, an embeddable SDK, and a first-party managed runner on top of the same declarative reconciliation model.
Secrets handling
A Kubernetes Secret object stores values base64-encoded, not encrypted, so a secret committed in a manifest is effectively plaintext; protecting it requires encryption at rest in etcd configured at the cluster level, plus an external tool such as Sealed Secrets or an external secrets operator to keep cleartext out of source control. Pulumi treats secrets as a first-class primitive: values marked as secrets are encrypted in transit and at rest in the state file, anything derived from a secret is also encrypted, and each stack has its own encryption key. The default encryption provider can be replaced with AWS KMS, Azure Key Vault, Google Cloud KMS, or HashiCorp Vault.
Policy as code
Kubernetes manifests have no built-in policy-as-code mechanism; enforcement is done inside the cluster by an admission controller such as OPA Gatekeeper or Kyverno, installed and managed as a separate component. Pulumi Policies is open source and free, with rules written in Python, TypeScript, or Open Policy Agent Rego that run during pulumi preview and pulumi up — before resources are created. Pulumi Cloud adds centralized management, policy groups, and enforcement across stacks, and commercial plans include Pulumi-maintained policy packs for common compliance frameworks (CIS, PCI DSS, HITRUST, NIST).
Modularity and reuse
Sharing Kubernetes YAML means copying manifests or building Kustomize bases and overlays — there is no package manager and no typed interface for distributing reusable manifest libraries. Pulumi’s Component Resources are runtime objects with explicit parent/child relationships, so a component and the resources inside it form a coherent unit in plan output, deletion, and state. Components can be authored in one language and consumed from any other supported language by publishing them as a Pulumi Package, and they distribute through language-native package managers (npm, PyPI, NuGet, Maven, Go modules) and the Pulumi Registry.
Automation API
The Automation API lets a host application drive Pulumi without shelling out to the CLI. Practical uses include embedding stack creation in a SaaS product, building an internal developer platform that provisions a namespace or a whole cluster per team or per branch, generating ephemeral preview environments from CI, and orchestrating multi-step deployments where each step runs as part of a larger workflow. The Kubernetes API and its client libraries can create and update individual objects, but there is no equivalent SDK for driving a full apply, preview, and destroy lifecycle.
When to choose Pulumi vs. Kubernetes YAML manifests
Choose Pulumi when you:
- Want to write Kubernetes configuration in a general-purpose language with the loops, conditionals, testing frameworks, package managers, and IDE tooling that already exist in that ecosystem.
- Need to provision the cluster and the surrounding cloud resources (databases, object stores, DNS) in the same program that deploys your workloads.
- Want a preview step, first-class encrypted secrets, and policy-as-code that runs before resources are created.
- Need an embeddable SDK (Automation API) to drive deployments from a host application — internal developer platforms, SaaS products, or per-branch preview environments.
Choose Kubernetes YAML manifests when you:
- Want the native, dependency-free input format of the Kubernetes API, with no additional tooling to install or learn.
- Have an existing GitOps workflow (Argo CD, Flux) and tooling built around raw manifests that you don’t want to change.
- Are managing Kubernetes resources only, and provisioning the cluster and cloud resources is handled by a separate team or tool.
The two can also coexist — see Adoption below.
Adoption: coexistence, conversion, and import
There are several common paths for adopting Pulumi alongside or in place of Kubernetes YAML manifests, and they can be combined:
- Consume existing YAML in a Pulumi program. The Kubernetes provider can deploy your existing manifests unchanged through its
ConfigFileandConfigGroupresources, so you can adopt Pulumi for orchestration without rewriting any YAML. See Migrating from Kubernetes YAML or Helm Charts. - Coexist via rendered YAML. Pulumi can render a program to Kubernetes YAML instead of applying it directly, so you can author configuration in a general-purpose language while still deploying with
kubectlor an existing GitOps pipeline. - Convert manifests with
pulumi convert.pulumi convert --from kubernetestranslates existing manifests into a Pulumi program in the language of your choice. - Import existing resources.
pulumi importand theimportresource option bring already-running cluster resources under Pulumi management and generate the corresponding code in your chosen language.
For a complete walkthrough including coexistence patterns, conversion, and rendering, see Migrating from Kubernetes YAML or Helm Charts to Pulumi.
Frequently asked questions
Can Pulumi deploy my existing Kubernetes YAML unchanged?
Yes. The Kubernetes provider includes ConfigFile and ConfigGroup resources that read existing manifests and register every object in them with Pulumi, so you can adopt Pulumi for orchestration without rewriting any YAML. See the migration guide.
How do I migrate from Kubernetes YAML to Pulumi?
You have options that can be combined: deploy your existing manifests as-is through ConfigFile/ConfigGroup, convert them to program code with pulumi convert --from kubernetes, or bring already-running resources under management with pulumi import. The migration guide walks through each path.
Does Pulumi replace kubectl?
For provisioning, yes — pulumi up applies your desired state to the cluster the same way kubectl apply does, with an added preview step. kubectl remains useful for ad-hoc inspection and debugging (kubectl get, kubectl logs, kubectl describe), and Pulumi can also render to YAML if you want to keep applying with kubectl or a GitOps controller.
Can Pulumi manage non-Kubernetes cloud resources too?
Yes. Unlike raw manifests, which describe Kubernetes objects only, a single Pulumi program can provision the cluster itself and any cloud resources your workloads depend on — managed databases, object stores, DNS records — using the Pulumi Registry of providers for AWS, Azure, Google Cloud, and SaaS platforms.
Is Pulumi free like Kubernetes manifests?
The Pulumi CLI and SDKs are open source under Apache 2.0 and free to use, as are Kubernetes and kubectl. Pulumi Cloud has a free Individual tier and paid plans that add managed state, RBAC, audit logs, policy management, and other features for running Pulumi at organizational scale.
Can Pulumi and raw YAML or GitOps coexist during migration?
Yes — and this is a common adoption pattern. Pulumi can deploy existing manifests through ConfigFile/ConfigGroup and can render programs back to YAML for an existing kubectl or GitOps pipeline, so teams typically keep some resources on raw manifests while moving others to Pulumi, converting or importing incrementally as the project allows.
Next steps
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.