<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0"><channel><title>Pulumi Blog: Platform engineering</title><link>https://www.pulumi.com/blog/tag/platform-engineering/</link><description>Pulumi blog posts: Platform engineering.</description><language>en-us</language><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><item><title>Best Terraform Alternatives in 2026</title><link>https://www.pulumi.com/blog/best-terraform-alternatives/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/best-terraform-alternatives/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/best-terraform-alternatives/index.png" /&gt;
&lt;p&gt;The strongest Terraform alternatives in 2026 split into three groups: general-purpose-language platforms like Pulumi and AWS CDK, HCL-compatible forks like OpenTofu, and cloud- or platform-specific tools like AWS CloudFormation, Azure Bicep, and Crossplane. (Pulumi also supports HCL directly and can serve as a Terraform-compatible state backend, so teams don&amp;rsquo;t have to choose between staying in HCL and gaining Pulumi Cloud&amp;rsquo;s platform capabilities.) Which one fits depends less on syntax preference than on how well it lets your team, and increasingly your AI coding agents, read, test, and safely change infrastructure code.&lt;/p&gt;
&lt;h2 id="why-teams-are-re-evaluating-terraform-in-2026"&gt;Why teams are re-evaluating Terraform in 2026&lt;/h2&gt;
&lt;p&gt;Terraform has been the default infrastructure-as-code tool for most of the last decade, and for good reason: a mature provider ecosystem, a large community, and a state model that most platform teams have learned to live with. But three forces are pushing teams to look again at what else is available.&lt;/p&gt;
&lt;p&gt;The first is licensing. HashiCorp moved Terraform from the open-source Mozilla Public License to the Business Source License in August 2023, a shift that triggered the community fork now known as OpenTofu. HashiCorp itself became a wholly owned subsidiary of IBM when that acquisition closed in February 2025. Neither event breaks anything for existing Terraform users, but both changed how governance and long-term product direction get decided, and that&amp;rsquo;s enough for some platform teams to want a documented Plan B.&lt;/p&gt;
&lt;p&gt;The second is the accumulated cost of working in a domain-specific language. HCL wasn&amp;rsquo;t designed for the abstraction, composition, and testing patterns that platform engineering now expects: sharing logic across teams, writing meaningful unit tests, and building internal libraries that read like software rather than templated configuration. Terraform has closed some of this gap over time, adding a native test framework in version 1.6, but the ceiling on what a declarative DSL can express is still lower than what a general-purpose language offers.&lt;/p&gt;
&lt;p&gt;The third, and the one reshaping the conversation fastest, is agentic AI. Coding agents like GitHub Copilot, Claude, and Pulumi&amp;rsquo;s own Neo are now a standing part of how engineering teams write and review code, and infrastructure is not exempt. These agents were trained on enormous volumes of real Python, TypeScript, Go, and Java, plus their entire testing and tooling ecosystems, but on comparatively little well-formed HCL. When an agent can write and modify infrastructure in a language it already understands deeply, the feedback loop of propose, test, preview, and ship gets tighter. When it has to reason about a purpose-built DSL, that loop lengthens and the agent is more likely to produce configuration nobody would write by hand. That gap doesn&amp;rsquo;t disqualify Terraform, but it does mean &amp;ldquo;which IaC tool works best with AI agents&amp;rdquo; is now a first-class question when teams evaluate alternatives, alongside the perennial ones about multi-cloud reach and governance.&lt;/p&gt;
&lt;p&gt;None of this is an argument that Terraform is going away. It remains a capable, widely adopted tool with a genuinely large provider catalog. It&amp;rsquo;s an argument that 2026 is a reasonable moment to look at what else exists, honestly, and pick the tool that fits where your infrastructure and your engineering workflow are actually headed. For a broader look at how AI agents are changing infrastructure work generally, see &lt;a href="https://www.pulumi.com/releases/agentic-infrastructure-era/"&gt;building for agentic infrastructure&lt;/a&gt;. For a head-to-head look at Pulumi and Terraform specifically, see our &lt;a href="https://www.pulumi.com/docs/iac/comparisons/terraform/"&gt;Pulumi vs. Terraform comparison&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="pulumi"&gt;Pulumi&lt;/h2&gt;
&lt;p&gt;Pulumi is an infrastructure-as-code platform that lets you define cloud infrastructure in general-purpose languages, including Python, TypeScript, Go, C#, and Java, plus a YAML option for teams that prefer a declarative format. Rather than compiling down to another tool&amp;rsquo;s templates, Pulumi programs run directly against a deployment engine that supports more than 180 providers in total, covering AWS, Azure, Google Cloud, Kubernetes, and a long tail of SaaS and on-prem targets.&lt;/p&gt;
&lt;p&gt;Pulumi also supports HCL as a first-class language, and Pulumi Cloud can serve as a drop-in &lt;a href="https://www.pulumi.com/docs/iac/get-started/terraform/terraform-state-backend/"&gt;state backend for existing Terraform code&lt;/a&gt;. That means teams with a large, working Terraform estate aren&amp;rsquo;t required to rewrite anything to get Pulumi Cloud&amp;rsquo;s state management, access controls, and policy enforcement — they can point existing HCL at Pulumi with minimal changes, then migrate configuration into a general-purpose language on their own timeline rather than all at once.&lt;/p&gt;
&lt;p&gt;Writing infrastructure in a real language means you get the tooling that comes with it for free: IDE autocomplete and type checking, unit and integration test frameworks, package managers for sharing reusable components, and the same code review and CI/CD conventions your application teams already use. It also means Pulumi programs run directly through Pulumi&amp;rsquo;s own deployment engine against any cloud or SaaS platform, with no separate compile-to-template step in between, unlike CDK-style tools that transpile into another system&amp;rsquo;s format before anything deploys. For an AI agent iterating on infrastructure, fewer steps between &amp;ldquo;write code&amp;rdquo; and &amp;ldquo;see the result&amp;rdquo; means a tighter feedback loop. &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt;, the platform&amp;rsquo;s infrastructure agent, builds on this directly: it can propose Terraform-to-Pulumi migrations, run policy-checked previews, respond to failures, and open pull requests inside a team&amp;rsquo;s existing review workflow.&lt;/p&gt;
&lt;p&gt;For platform teams, Pulumi adds built-in guardrails that Terraform typically requires bolting on through third-party tooling: &lt;a href="https://www.pulumi.com/what-is/what-is-policy-as-code/"&gt;policy as code&lt;/a&gt; for enforcing organizational rules before a deployment ships, a secrets and configuration management layer (ESC), human-in-the-loop approval gates, and reusable components that teams can publish and consume like any other internal library, in whatever language they use. The tradeoff is ecosystem maturity in the opposite direction from Terraform: Pulumi&amp;rsquo;s provider catalog, while broad, has a shorter history than Terraform&amp;rsquo;s for a handful of niche or long-tail providers, and some teams will need to weigh that against the language and workflow benefits.&lt;/p&gt;
&lt;p&gt;At scale, Pulumi customers report concrete outcomes. BMW&amp;rsquo;s Software Factory manages more than 20,000 cloud resources with Python-based infrastructure code for over 11,000 developers. Wiz manages more than a million cloud resources through Pulumi&amp;rsquo;s Automation API and Kubernetes operator, pushing hundreds of thousands of daily infrastructure updates across hundreds of data centers. Supabase scaled from a single region to 16 regions and roughly 80,000 resources. Atlassian&amp;rsquo;s Bitbucket team reported a 50% reduction in infrastructure maintenance time after adopting Pulumi.&lt;/p&gt;
&lt;h2 id="opentofu"&gt;OpenTofu&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/docs/iac/comparisons/terraform/opentofu/"&gt;OpenTofu&lt;/a&gt; is an open-source fork of Terraform, governed by the Linux Foundation rather than a single vendor. It emerged directly from HashiCorp&amp;rsquo;s August 2023 license change: a group of Terraform users and vendors forked the last MPL-licensed Terraform release and committed to keeping the fork under a permissive open-source license going forward.&lt;/p&gt;
&lt;p&gt;The practical pitch is continuity: OpenTofu aims to stay a close drop-in replacement for Terraform, using the same HCL syntax, the same provider ecosystem (most Terraform providers work unmodified), and largely the same workflow, so teams can migrate with minimal rewriting. Since forking, OpenTofu&amp;rsquo;s maintainers have also started adding features HashiCorp hadn&amp;rsquo;t shipped, including state encryption at rest, giving it a case for teams who want to stay in HCL but prioritize community governance over vendor governance.&lt;/p&gt;
&lt;p&gt;The tradeoff is that OpenTofu inherits HCL&amp;rsquo;s ceiling along with its familiarity. It solves the licensing and governance concern cleanly, but it doesn&amp;rsquo;t address the testing, composability, or general-purpose-language advantages that come with moving to a platform like Pulumi or AWS CDK, and AI coding agents face the same reasoning gap with OpenTofu&amp;rsquo;s HCL that they do with Terraform&amp;rsquo;s.&lt;/p&gt;
&lt;h2 id="aws-cloudformation"&gt;AWS CloudFormation&lt;/h2&gt;
&lt;p&gt;CloudFormation is AWS&amp;rsquo;s native infrastructure-as-code service, using YAML or JSON templates that AWS itself parses, validates, and rolls back on failure. Because it&amp;rsquo;s built and operated by AWS, it gets first access to new AWS service features, and its state is managed entirely by AWS rather than a separate backend your team has to configure and secure.&lt;/p&gt;
&lt;p&gt;The obvious limit is scope: CloudFormation only provisions AWS resources, so any team running infrastructure across more than one cloud, or alongside Kubernetes and SaaS resources, will need a second tool for everything outside AWS. Authoring in raw YAML or JSON also means the same testing and abstraction limitations that HCL-based tools face, without even Terraform&amp;rsquo;s ecosystem of community modules to offset it. Many AWS-focused teams increasingly write CloudFormation stacks through AWS CDK rather than by hand.&lt;/p&gt;
&lt;h2 id="aws-cdk"&gt;AWS CDK&lt;/h2&gt;
&lt;p&gt;AWS CDK (Cloud Development Kit) lets you define AWS infrastructure using general-purpose languages including TypeScript, JavaScript, Python, Java, C#, and Go. Under the hood, CDK code compiles down to standard CloudFormation templates, which AWS then deploys the same way it deploys any other CloudFormation stack.&lt;/p&gt;
&lt;p&gt;CDK gives AWS-only teams most of the general-purpose-language benefits that Pulumi offers: real loops, functions, tests, and packages, plus the IDE support that comes with a mainstream language. The compile step is the notable difference from a platform like Pulumi, which runs your program directly against cloud provider APIs: CDK synthesizes a CloudFormation template first, then hands that off, which adds a layer between what your code says and what gets deployed, and can slow the feedback loop an AI coding agent depends on when it&amp;rsquo;s proposing and testing changes iteratively. CDK is also AWS-only, so it doesn&amp;rsquo;t help teams who need one consistent authoring model across multiple clouds.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s worth distinguishing AWS CDK clearly from HashiCorp&amp;rsquo;s CDK for Terraform (CDKTF), which offered a similar general-purpose-language wrapper around Terraform&amp;rsquo;s HCL engine. HashiCorp sunset and archived CDKTF in December 2025, stating in its own FAQ that the project &amp;ldquo;did not find product-market fit at scale&amp;rdquo; and redirecting investment to Terraform core instead. Existing CDKTF code still runs, but the project receives no further commits, fixes, or provider updates, which makes it a poor foundation for new work regardless of language preference.&lt;/p&gt;
&lt;h2 id="crossplane"&gt;Crossplane&lt;/h2&gt;
&lt;p&gt;Crossplane is a Kubernetes-native framework for infrastructure as code, letting platform teams define and provision cloud resources as Kubernetes custom resources, managed by controllers running inside a cluster. Rather than running a separate CLI-driven apply cycle, Crossplane treats the cluster&amp;rsquo;s control plane as the single source of truth for both application and infrastructure state.&lt;/p&gt;
&lt;p&gt;This model is a natural fit for teams already standardized on Kubernetes as their platform layer: infrastructure gets the same GitOps, RBAC, and reconciliation patterns as application workloads, and platform teams can build self-service abstractions (Crossplane calls these Compositions) that let application developers request infrastructure without learning Crossplane&amp;rsquo;s own resource model directly. The tradeoff is that Crossplane assumes a Kubernetes-centric operating model; teams without an existing cluster-based platform will be adopting Kubernetes as a prerequisite, not just an infrastructure tool, and Crossplane&amp;rsquo;s ecosystem of documented, named enterprise deployments is thinner than Terraform&amp;rsquo;s or Pulumi&amp;rsquo;s, making it harder to evaluate at-scale track record from public case studies alone.&lt;/p&gt;
&lt;h2 id="azure-bicep"&gt;Azure Bicep&lt;/h2&gt;
&lt;p&gt;Bicep is Microsoft&amp;rsquo;s domain-specific language for deploying Azure resources, designed as a cleaner authoring layer over Azure Resource Manager templates. Bicep code transpiles to ARM JSON, but with syntax that&amp;rsquo;s considerably easier to read and write than hand-authored ARM. It&amp;rsquo;s open source under the MIT license, and Microsoft&amp;rsquo;s own documentation recommends it over raw ARM JSON for new Azure-only infrastructure work.&lt;/p&gt;
&lt;p&gt;Like CloudFormation, Bicep&amp;rsquo;s scope is a single cloud, in this case Azure exclusively, so it isn&amp;rsquo;t a candidate for teams managing infrastructure across providers. It&amp;rsquo;s also a DSL rather than a general-purpose language, which means the same testing and reuse ceiling as HCL, though for teams fully committed to Azure and nothing else, it remains a well-supported, low-friction choice.&lt;/p&gt;
&lt;h2 id="ansible"&gt;Ansible&lt;/h2&gt;
&lt;p&gt;Ansible is an agentless configuration management and automation tool that uses YAML playbooks to describe the desired state of servers, software, and application deployments. Red Hat, which acquired Ansible in 2015 and was itself acquired by IBM in 2019, maintains it today as part of Red Hat Ansible Automation Platform.&lt;/p&gt;
&lt;p&gt;Ansible is often grouped with Terraform in &amp;ldquo;IaC tool&amp;rdquo; comparisons, but the two solve different problems and are frequently used together rather than as substitutes: Terraform or Pulumi provisions the resource, and Ansible then configures the operating system, installs software, and manages ongoing configuration state on top of it. Ansible does ship cloud provisioning modules and can create resources directly, but its design center is procedural configuration management, not declarative resource provisioning at the scale Terraform-class tools target. Teams evaluating Terraform alternatives for cloud provisioning specifically will usually want a tool from this list&amp;rsquo;s other categories, with Ansible layered in afterward for day-two configuration.&lt;/p&gt;
&lt;h2 id="terragrunt"&gt;Terragrunt&lt;/h2&gt;
&lt;p&gt;Terragrunt is a thin orchestration wrapper maintained by Gruntwork that sits on top of Terraform or OpenTofu, rather than replacing either one. Its job is keeping multi-environment, multi-module HCL configurations DRY, and coordinating the order in which modules apply across a larger infrastructure codebase.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s worth being precise about what Terragrunt is not: it doesn&amp;rsquo;t introduce a new language, provider model, or state backend, and it doesn&amp;rsquo;t address HCL&amp;rsquo;s testing or abstraction limitations on its own. Teams considering Terragrunt aren&amp;rsquo;t choosing a Terraform alternative; they&amp;rsquo;re choosing a companion tool that makes Terraform or OpenTofu easier to operate at scale. If the underlying frustration is with HCL itself rather than with configuration sprawl, Terragrunt won&amp;rsquo;t resolve it.&lt;/p&gt;
&lt;h2 id="comparison-table"&gt;Comparison table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Cloud coverage&lt;/th&gt;
&lt;th&gt;AI-agent readiness&lt;/th&gt;
&lt;th&gt;Governance &amp;amp; policy&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pulumi&lt;/td&gt;
&lt;td&gt;Python, TypeScript, Go, C#, Java, YAML, HCL&lt;/td&gt;
&lt;td&gt;180+ providers, any cloud&lt;/td&gt;
&lt;td&gt;High — real languages agents are trained on; Neo agent built in&lt;/td&gt;
&lt;td&gt;Policy as code, ESC secrets, human-in-the-loop approvals&lt;/td&gt;
&lt;td&gt;Teams standardizing on AI-native, multi-cloud engineering workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenTofu&lt;/td&gt;
&lt;td&gt;HCL&lt;/td&gt;
&lt;td&gt;Same provider ecosystem as Terraform&lt;/td&gt;
&lt;td&gt;Same as Terraform — DSL limits agent reasoning&lt;/td&gt;
&lt;td&gt;Community-governed; adding features like state encryption&lt;/td&gt;
&lt;td&gt;Terraform users prioritizing open governance with minimal migration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS CloudFormation&lt;/td&gt;
&lt;td&gt;YAML/JSON&lt;/td&gt;
&lt;td&gt;AWS only&lt;/td&gt;
&lt;td&gt;Low — templated config, no native testing&lt;/td&gt;
&lt;td&gt;AWS-managed state and rollback&lt;/td&gt;
&lt;td&gt;Teams fully committed to AWS wanting a fully managed native service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS CDK&lt;/td&gt;
&lt;td&gt;TypeScript, Python, Java, C#, Go&lt;/td&gt;
&lt;td&gt;AWS only (compiles to CloudFormation)&lt;/td&gt;
&lt;td&gt;Medium — real languages, but a compile step slows feedback&lt;/td&gt;
&lt;td&gt;Inherits CloudFormation governance&lt;/td&gt;
&lt;td&gt;AWS-only teams wanting general-purpose languages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crossplane&lt;/td&gt;
&lt;td&gt;Kubernetes YAML/CRDs&lt;/td&gt;
&lt;td&gt;Any cloud, via Kubernetes control plane&lt;/td&gt;
&lt;td&gt;Medium — benefits from Kubernetes-native agent tooling&lt;/td&gt;
&lt;td&gt;RBAC and GitOps via Kubernetes&lt;/td&gt;
&lt;td&gt;Platform teams already standardized on Kubernetes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure Bicep&lt;/td&gt;
&lt;td&gt;Bicep DSL (compiles to ARM)&lt;/td&gt;
&lt;td&gt;Azure only&lt;/td&gt;
&lt;td&gt;Low — DSL, no general-purpose tooling&lt;/td&gt;
&lt;td&gt;Inherits Azure Resource Manager governance&lt;/td&gt;
&lt;td&gt;Azure-only teams wanting a cleaner ARM authoring layer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ansible&lt;/td&gt;
&lt;td&gt;YAML playbooks&lt;/td&gt;
&lt;td&gt;Any cloud, config-management focused&lt;/td&gt;
&lt;td&gt;Low for provisioning; not its design center&lt;/td&gt;
&lt;td&gt;Role-based playbooks, limited policy tooling&lt;/td&gt;
&lt;td&gt;Day-two configuration management alongside an IaC tool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terragrunt&lt;/td&gt;
&lt;td&gt;HCL (wraps Terraform/OpenTofu)&lt;/td&gt;
&lt;td&gt;Same as underlying Terraform/OpenTofu&lt;/td&gt;
&lt;td&gt;Same as underlying Terraform/OpenTofu&lt;/td&gt;
&lt;td&gt;Same as underlying Terraform/OpenTofu&lt;/td&gt;
&lt;td&gt;Keeping large Terraform/OpenTofu codebases DRY, not a language alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="how-to-choose"&gt;How to choose&lt;/h2&gt;
&lt;p&gt;If your team is standardizing on a single cloud and wants the deepest, most tightly integrated tooling for it, the native option, CloudFormation for AWS or Bicep for Azure, is a reasonable default, especially for smaller platform teams that don&amp;rsquo;t need cross-cloud abstraction. If you&amp;rsquo;re on AWS specifically and want general-purpose languages without leaving the CloudFormation ecosystem, AWS CDK is the more capable choice, with the caveat that its compile-then-deploy step adds a layer between code and infrastructure.&lt;/p&gt;
&lt;p&gt;If your team is already running Kubernetes as its platform layer and wants infrastructure provisioning to follow the same GitOps and RBAC model as application workloads, Crossplane is worth a serious look, understanding that it comes with Kubernetes as a hard dependency.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re deep in Terraform today, comfortable with HCL, and your primary concern is licensing and governance rather than language or workflow, OpenTofu is the lowest-friction path: same syntax, same providers, community governance instead of vendor governance.&lt;/p&gt;
&lt;p&gt;If your team is investing in AI coding agents as part of its engineering workflow, wants multi-cloud reach without maintaining separate tools per provider, and values real testing, packaging, and code review practices for infrastructure the same way it does for application code, Pulumi is built specifically for that combination. It&amp;rsquo;s also the most direct migration path for teams currently on Terraform or CDKTF who want to move to a general-purpose language without changing which clouds they manage.&lt;/p&gt;
&lt;h2 id="frequently-asked-questions"&gt;Frequently asked questions&lt;/h2&gt;
&lt;h3 id="is-terraform-still-free-to-use"&gt;Is Terraform still free to use?&lt;/h3&gt;
&lt;p&gt;Yes, for most teams. Terraform&amp;rsquo;s core CLI and the vast majority of its providers remain free under the Business Source License that HashiCorp adopted in August 2023. The license restricts a narrow set of commercial use cases, mainly building a competing managed offering on top of Terraform, which doesn&amp;rsquo;t affect ordinary infrastructure teams using it internally.&lt;/p&gt;
&lt;h3 id="what-is-the-best-open-source-terraform-alternative"&gt;What is the best open-source Terraform alternative?&lt;/h3&gt;
&lt;p&gt;OpenTofu is the closest open-source alternative if you want to keep using HCL and the Terraform provider ecosystem, since it&amp;rsquo;s a direct fork governed by the Linux Foundation. If open-source licensing matters but you&amp;rsquo;re open to a different language, Pulumi&amp;rsquo;s SDKs and CLI are open source (Apache 2.0), and Crossplane is a CNCF project for teams standardized on Kubernetes.&lt;/p&gt;
&lt;h3 id="which-iac-tool-works-best-with-ai-coding-agents"&gt;Which IaC tool works best with AI coding agents?&lt;/h3&gt;
&lt;p&gt;Tools built on general-purpose languages give AI coding agents the strongest foundation, since those agents have far more training exposure to real Python, TypeScript, Go, C#, and Java than to any infrastructure-specific DSL. Pulumi and AWS CDK both fit this category; AWS CDK&amp;rsquo;s compile step to CloudFormation adds a layer of indirection that Pulumi, which runs directly against provider APIs, doesn&amp;rsquo;t have.&lt;/p&gt;
&lt;h3 id="can-i-migrate-from-terraform-without-rewriting-everything"&gt;Can I migrate from Terraform without rewriting everything?&lt;/h3&gt;
&lt;p&gt;It depends on which alternative you choose. Moving to OpenTofu requires essentially no rewriting, since it&amp;rsquo;s HCL-compatible by design. Moving to Pulumi can be just as light-touch, since Pulumi Cloud works as a Terraform state backend and Pulumi IaC speaks HCL natively; teams that do want to move into a general-purpose language, or that are adopting AWS CDK or a similar platform, will need to translate configuration into program code, though tools like Pulumi&amp;rsquo;s import and conversion tooling, and increasingly AI coding agents themselves, can automate a meaningful share of that translation rather than requiring a manual line-by-line rewrite.&lt;/p&gt;
&lt;h3 id="is-pulumi-a-drop-in-terraform-replacement"&gt;Is Pulumi a drop-in Terraform replacement?&lt;/h3&gt;
&lt;p&gt;It can be, if you want it to be. Pulumi Cloud now works as a &lt;a href="https://www.pulumi.com/docs/iac/get-started/terraform/terraform-state-backend/"&gt;Terraform state backend&lt;/a&gt;, so a team can point its existing Terraform or OpenTofu CLI at Pulumi Cloud and keep every &lt;code&gt;.tf&lt;/code&gt; file exactly as written — no rewrite required. Pulumi also &lt;a href="https://www.pulumi.com/docs/iac/languages-sdks/hcl/"&gt;supports HCL as a first-class language&lt;/a&gt; alongside Python, TypeScript, Go, C#, Java, and YAML, so HCL modules can be authored and consumed natively inside Pulumi IaC.&lt;/p&gt;
&lt;p&gt;For teams that do want to move off HCL entirely, that&amp;rsquo;s also an option: Pulumi&amp;rsquo;s general-purpose languages let infrastructure code get loops, functions, tests, and packages that HCL doesn&amp;rsquo;t offer. Moving to that model means translating configuration into code rather than reusing files unchanged, though the underlying model carries over — state, providers, and resources map conceptually in similar ways — and Pulumi provides tooling to import existing Terraform-managed infrastructure and convert Terraform configuration into a starting Pulumi program, which teams typically use as a first draft rather than a finished migration.&lt;/p&gt;
&lt;h3 id="does-opentofu-support-everything-terraform-does"&gt;Does OpenTofu support everything Terraform does?&lt;/h3&gt;
&lt;p&gt;OpenTofu tracks Terraform&amp;rsquo;s last open-source release closely and remains compatible with most existing Terraform configurations and providers. Since forking, its Linux Foundation-governed maintainers have also shipped features Terraform hadn&amp;rsquo;t offered, such as state encryption, while newer HashiCorp-only Terraform features naturally won&amp;rsquo;t appear in OpenTofu unless the community implements equivalents independently.&lt;/p&gt;
&lt;p&gt;For a broader roundup covering the full infrastructure-as-code category rather than Terraform alternatives specifically, see our guide to &lt;a href="https://www.pulumi.com/what-is/top-iac-tools/"&gt;the best IaC tools&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Terraform remains a capable, widely used tool, and for teams with no appetite to change, OpenTofu offers a nearly friction-free path to the same workflow under different governance. But the more interesting question for 2026 isn&amp;rsquo;t whether Terraform still works, it&amp;rsquo;s whether your infrastructure tooling can keep pace with how your engineering organization is actually building software now: with AI coding agents as active participants, not just autocomplete. That question favors platforms built on real, general-purpose languages, tested and reviewed the same way application code is, over any tool, new or established, still built around a purpose-specific configuration syntax. Evaluate honestly against your own cloud footprint, existing platform investment, and how central AI-assisted development already is to your team, and the right alternative, or the right reason to stay put, becomes clear quickly.&lt;/p&gt;</description><author>Pulumi Content Team</author><category>terraform</category><category>infrastructure-as-code</category><category>ai</category><category>platform-engineering</category><category>devops</category></item><item><title>Knowledge as Code: The Memory File Just Got a Spec</title><link>https://www.pulumi.com/blog/knowledge-as-code-the-memory-file-just-got-a-spec/</link><pubDate>Tue, 14 Jul 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/knowledge-as-code-the-memory-file-just-got-a-spec/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/knowledge-as-code-the-memory-file-just-got-a-spec/index.png" /&gt;
&lt;p&gt;Five weeks ago I wrote that the least glamorous piece of an agent loop is also the one that decides whether it compounds: &lt;a href="https://www.pulumi.com/blog/stop-prompting-design-the-loop/"&gt;memory&lt;/a&gt;. A markdown file outside the context window that holds what is done, what is next, and what was learned, because the model forgets all of it between runs. Write the memory file before the loop.&lt;/p&gt;
&lt;p&gt;What I left open, because there was nothing to point at, was the format. My memory file looked nothing like yours, and neither of our agents could read the other&amp;rsquo;s.&lt;/p&gt;
&lt;p&gt;Three days after that post went live, Google shipped an answer.&lt;/p&gt;
&lt;h2 id="the-pattern-everyone-copied"&gt;The pattern everyone copied&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f"&gt;Andrej Karpathy published a gist in April&lt;/a&gt; he called the LLM wiki, and it collected thousands of stars and forks. It&amp;rsquo;s meant to be pasted straight into a coding agent. Instead of indexing your documents for RAG and re-deriving answers from raw text on every query, the agent builds a wiki and keeps it current: interlinked markdown pages, an &lt;code&gt;index.md&lt;/code&gt; with a one-line summary per page, a &lt;code&gt;log.md&lt;/code&gt; recording every change, entity pages that grow as sources come in. Drop in a meeting transcript and the agent reads it, updates a dozen existing pages, fixes the cross-references, and appends to the log in one pass.&lt;/p&gt;
&lt;p&gt;It took off for the same reason wikis usually die. A knowledge base is valuable in exact proportion to the bookkeeping nobody wants to do: summarizing, linking, reconciling contradictions, pruning stale claims. Karpathy&amp;rsquo;s line, which Google now quotes back in its own announcement, is that LLMs &amp;ldquo;don&amp;rsquo;t get bored, don&amp;rsquo;t forget to update a cross-reference, and can touch 15 files in one pass.&amp;rdquo; The human curates sources and asks questions. The agent does the janitorial work that made every previous wiki rot.&lt;/p&gt;
&lt;h2 id="a-wiki-only-your-agent-can-read"&gt;A wiki only your agent can read&lt;/h2&gt;
&lt;p&gt;Then everyone built one, and every one is a dialect. Mine links related pages in the frontmatter; yours links them at the bottom of the body. Mine has a &lt;code&gt;tags&lt;/code&gt; field; yours calls it &lt;code&gt;categories&lt;/code&gt;. None of this matters while the wiki serves one person, because the schema lives in your &lt;code&gt;CLAUDE.md&lt;/code&gt; and your agent reads it on every run.&lt;/p&gt;
&lt;p&gt;It matters the moment the wiki has to travel. Hand your knowledge base to a teammate and their agent starts guessing at your conventions, or misses half the structure entirely. A platform team that wants one shared wiki, queried independently by everyone&amp;rsquo;s agents, has no format to agree on. A knowledge base you can&amp;rsquo;t hand to someone else&amp;rsquo;s agent is a silo of one. And a team&amp;rsquo;s collective knowledge should outlive any single person&amp;rsquo;s markdown habits.&lt;/p&gt;
&lt;h2 id="what-google-actually-shipped-the-open-knowledge-format"&gt;What Google actually shipped: the Open Knowledge Format&lt;/h2&gt;
&lt;p&gt;On June 12, two tech leads in Google Cloud&amp;rsquo;s data analytics engineering org &lt;a href="https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/"&gt;announced the Open Knowledge Format&lt;/a&gt;, with a &lt;a href="https://github.com/GoogleCloudPlatform/knowledge-catalog"&gt;spec and reference tooling on GitHub&lt;/a&gt;. Strip the branding and OKF v0.1 is a formalization of the Karpathy pattern:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A bundle is a directory tree of markdown files. Two filenames are reserved: &lt;code&gt;index.md&lt;/code&gt; for progressive disclosure and &lt;code&gt;log.md&lt;/code&gt; for update history. Everything else is a concept document.&lt;/li&gt;
&lt;li&gt;Every concept carries YAML frontmatter with exactly one required field: &lt;code&gt;type&lt;/code&gt;. Five more are recommended: &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;resource&lt;/code&gt;, &lt;code&gt;tags&lt;/code&gt;, &lt;code&gt;timestamp&lt;/code&gt;. Producers can add anything; consumers must preserve what they don&amp;rsquo;t understand.&lt;/li&gt;
&lt;li&gt;A markdown link from one concept to another asserts a relationship. The prose around the link says what kind.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The whole spec fits on a page, and that&amp;rsquo;s deliberate. The announcement names three principles: minimally opinionated; producers and consumers independently swappable; a format rather than a platform. No required SDK, no compression scheme, no new runtime. Reading a bundle is &lt;code&gt;cat&lt;/code&gt;; distributing one is &lt;code&gt;git clone&lt;/code&gt;. The repo backs it up with reference tooling: an enrichment agent that drafts concept docs from BigQuery datasets, and a static visualizer that renders a bundle as a graph. Three sample bundles, built by that same agent, give you something to copy from.&lt;/p&gt;
&lt;h2 id="the-critique-is-the-feature"&gt;The critique is the feature&lt;/h2&gt;
&lt;p&gt;The pushback writes itself: there is almost nothing here. Folder indexes and five suggested frontmatter fields, on top of a pattern the community already had. True. Also the point.&lt;/p&gt;
&lt;p&gt;The standards that stick are embarrassingly small. &lt;a href="https://www.pulumi.com/docs/ai/mcp-server/"&gt;MCP&lt;/a&gt; didn&amp;rsquo;t model your tools; it standardized the socket they plug into. &lt;code&gt;AGENTS.md&lt;/code&gt; fixed nothing but a filename, and that was enough for &lt;a href="https://www.pulumi.com/blog/pulumi-neo-now-supports-agentsmd/"&gt;Neo to read the same conventions file as every other agent&lt;/a&gt;. &lt;a href="https://www.pulumi.com/docs/ai/skills/"&gt;Agent Skills&lt;/a&gt; gave procedure a place to live, and docs sites settled on &lt;a href="https://www.pulumi.com/llms.txt"&gt;/llms.txt&lt;/a&gt; for published content. Knowledge was the layer still missing its boring little standard. Whether OKF specifically is the one that survives matters less than the shape it commits to: markdown, frontmatter, git. Every other layer of the agent stack already landed there, so that bet is safe.&lt;/p&gt;
&lt;h2 id="knowledge-as-code"&gt;Knowledge as code&lt;/h2&gt;
&lt;p&gt;Platform teams should care about this before anyone else. Infrastructure as code captures the what: the resources, the config, the dependency graph. It has never captured the why. The runbook for rotating credentials, the decision record explaining the pinned CNI version, who owns the cluster, what the incident in November taught you. That knowledge lives in a wiki behind an API, a shared drive, a Slack thread, and the heads of two senior engineers. Google&amp;rsquo;s announcement frames this fragmentation as the problem: agents reassembling answers from systems that each speak a proprietary format.&lt;/p&gt;
&lt;p&gt;OKF&amp;rsquo;s answer is a move platform engineers will recognize, because it&amp;rsquo;s the same one that produced IaC: put it in git, make it diffable, review changes in pull requests. Knowledge as code, sitting next to the infrastructure as code it explains:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;platform/
├── index.md
├── log.md
├── services/
│ ├── index.md
│ ├── checkout-api.md
│ └── payments-worker.md
├── runbooks/
│ ├── index.md
│ └── rotate-database-credentials.md
└── decisions/
├── index.md
└── why-we-pin-the-vpc-cni-version.md
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The recommended &lt;code&gt;resource&lt;/code&gt; field takes a URI naming the asset a concept describes, and a Pulumi URN is exactly that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;runbook&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Rotate the payments database credentials&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Zero-downtime credential rotation for the payments Postgres instance.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;urn:pulumi:prod::payments::aws:rds/instance:Instance::payments-db&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;payments, postgres]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ld"&gt;2026-07-01T09:30:00Z&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the runbook names the exact resource it operates on. An agent planning a change to that database can walk from the URN to the runbook to the decision record that explains the constraint, before it proposes anything. In the loop post I said &lt;a href="https://www.pulumi.com/docs/ai/skills/"&gt;skills&lt;/a&gt; are intent written down, the conventions an agent reads instead of guessing. A knowledge bundle is the other half: experience written down. Tools give the loop hands, skills give it habits, and the bundle is what it gets to remember.&lt;/p&gt;
&lt;p&gt;Before writing any of that down, I ran the test. A fresh agent got two inputs, the spec and this bundle, and one question: which services touch the payments database, and how do I rotate its credentials without downtime? It read six files and answered correctly, down to why rotating a second time too soon is the dangerous move. What sold me was the file it didn&amp;rsquo;t read. It left the CNI decision record closed, because the cross-links mark that page as a cluster concern, not a database one.&lt;/p&gt;
&lt;p&gt;The bundle is public, exactly the tree above. Clone it, hand your agent the spec, and ask your own questions:&lt;/p&gt;
&lt;a href="https://github.com/dirien/pulumi-platform-okf-bundle" target="_blank" rel="noopener noreferrer" class="github-card"&gt;
&lt;img
src="https://opengraph.githubassets.com/1/dirien/pulumi-platform-okf-bundle"
alt="GitHub repository: dirien/pulumi-platform-okf-bundle"
class="github-card-image"
loading="lazy"
/&gt;
&lt;div class="github-card-content"&gt;
&lt;div class="github-card-domain"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon github-card-icon" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#b-github"/&gt;&lt;/svg&gt;
github.com/dirien/pulumi-platform-okf-bundle
&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;h2 id="what-a-standard-wont-do-for-you"&gt;What a standard won&amp;rsquo;t do for you&lt;/h2&gt;
&lt;p&gt;Three caveats, so nobody mistakes this for magic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It formats knowledge; it doesn&amp;rsquo;t create it.&lt;/strong&gt; The warning from the loop post applies with no edits: memory is what lets a loop compound, and slop compounds right alongside it. A wrong runbook in a beautifully conformant bundle is still a wrong runbook, now served to every agent on the team with confidence. The leverage isn&amp;rsquo;t the format. It&amp;rsquo;s that knowledge changes finally go through review like code changes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;v0.1 is a draft, and the name may not survive.&lt;/strong&gt; Google says so itself: the announcement calls v0.1 &amp;ldquo;a starting point, not a finished standard.&amp;rdquo; OKF could lose to a better spec next year. I&amp;rsquo;d start anyway, because converting markdown with frontmatter into markdown with slightly different frontmatter is the cheapest migration you&amp;rsquo;ll ever run, and it&amp;rsquo;s precisely the kind of mechanical pass an agent finishes in an afternoon. The shape is the commitment. The name is a detail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conformance is a floor, not hygiene.&lt;/strong&gt; The spec requires consumers to tolerate broken links, missing indexes, and unknown types. That tolerance keeps readers working, and it also means nothing forces your bundle to stay healthy. Karpathy&amp;rsquo;s gist included a lint pass for a reason: contradictions, orphaned pages, stale claims. Keep it, and run it the way you lint code, on a schedule, with findings that reach a human.&lt;/p&gt;
&lt;h2 id="where-to-start"&gt;Where to start&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pick the knowledge that already hurts.&lt;/strong&gt; The runbook nobody can find during an incident, the onboarding doc that&amp;rsquo;s wrong in ways only one person knows. One domain, not the whole org.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Let the agent do the conversion.&lt;/strong&gt; Paste the &lt;a href="https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md"&gt;spec&lt;/a&gt; into your coding agent, point it at the existing folder of docs, and have it refactor them into a bundle. This is exactly the bookkeeping LLMs are good at, and it works as well on a wiki export as on a fresh start.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Put the bundle where the code lives.&lt;/strong&gt; Same repo or a sibling, but in git, behind pull requests. The day a knowledge change gets a review comment is the day the bundle becomes trustworthy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wire it into the loop.&lt;/strong&gt; Agents read &lt;code&gt;index.md&lt;/code&gt; first and drill down only when a concept earns it, which keeps the context window small. The memory file I told you to write before the loop now has a format, and every agent you run, in &lt;a href="https://www.pulumi.com/blog/stop-tuning-prompts-build-a-harness/"&gt;whatever harness you built&lt;/a&gt;, can read the same one.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The advice from June holds: write the memory file before the loop. What changed is that the file no longer has to be a private dialect. There&amp;rsquo;s now a one-page, git-native spec for the layer your agents think with, and the smallness that makes it look trivial is the property that lets it spread. The loop does the typing. The wiki does the remembering. And the remembering is now something you can put in a pull request and hand to the next agent, like everything else you ship.&lt;/p&gt;
&lt;a
href="https://www.pulumi.com/docs/ai/"
class="btn btn-primary"
&gt;
Wire Pulumi context into your agents
&lt;/a&gt;</description><author>Engin Diri</author><category>ai</category><category>ai-agents</category><category>google-cloud</category><category>platform-engineering</category></item><item><title>Stop Prompting. Design the Loop.</title><link>https://www.pulumi.com/blog/stop-prompting-design-the-loop/</link><pubDate>Tue, 09 Jun 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/stop-prompting-design-the-loop/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/stop-prompting-design-the-loop/index.png" /&gt;
&lt;p&gt;For about two years, the unit of work with a coding agent was the prompt. You wrote a good one, you gave it enough context, you read what came back, and you wrote the next one. The agent was a tool, and you were holding it the entire time, one turn after another.&lt;/p&gt;
&lt;p&gt;That part is ending. &lt;a href="https://x.com/addyosmani"&gt;Addy Osmani&lt;/a&gt;, a director of AI at Google Cloud, has a name for what replaces it, and I have not stopped thinking about it since: &lt;a href="https://x.com/addyosmani/status/2064127981161959567"&gt;loop engineering&lt;/a&gt;. You stop being the person who prompts the agent. You design the loop that prompts it for you.&lt;/p&gt;
&lt;p&gt;In my phrasing: you stop being the thing that runs, and start designing the thing that runs. The leverage moves up a layer. What I want to do here is take an honest look at the pieces, and at the part nobody automates.&lt;/p&gt;
&lt;h2 id="the-leverage-moved-up-a-layer"&gt;The leverage moved up a layer&lt;/h2&gt;
&lt;p&gt;The people building these tools have already made the jump. &lt;a href="https://x.com/steipete"&gt;Peter Steinberger&lt;/a&gt; has been posting it as a monthly reminder.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="./steinberger-loops.png" alt="A post by Peter Steinberger (@steipete) on X: 'Here's your monthly reminder that you shouldn't be prompting coding agents anymore. You should be designing loops that prompt your agents.'"&gt;
&lt;figcaption&gt;&lt;em&gt;Peter Steinberger (&lt;a href="https://x.com/steipete"&gt;@steipete&lt;/a&gt;) on X.&lt;/em&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href="https://x.com/bcherny"&gt;Boris Cherny&lt;/a&gt;, who heads Claude Code at Anthropic, says the same thing about his own job. He does not prompt Claude anymore. He has loops running that prompt Claude and decide what to do next, scanning the issue tracker, the team chat, and the timeline for what to build. &amp;ldquo;My job is to write loops.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;A loop is a goal that prompts itself. You set the purpose, and the system keeps iterating until it&amp;rsquo;s met. In practice it finds the work, hands it out, checks the result, writes down what got finished, and decides the next thing, then it pokes the agent instead of you. You build that small system once and let it run.&lt;/p&gt;
&lt;p&gt;Look closer, and a loop is really two loops nested. The inner one does the work against a spec. The outer one decides what the work should be: it watches an issue tracker, an error feed, a changelog, then writes the next spec and hands it down. Most people are still running that outer loop by hand, in their head, and calling it a backlog.&lt;/p&gt;
&lt;p&gt;The part that surprised me is that this is barely a tooling problem anymore. A year ago a loop meant a pile of bash you wrote and maintained forever. Now the pieces ship inside the products, and the same shapes show up in Claude Code and in Codex. Osmani puts loop engineering one floor above the harness, the context and tooling you wire around a single agent. I wrote about &lt;a href="https://www.pulumi.com/blog/stop-tuning-prompts-build-a-harness/"&gt;that harness&lt;/a&gt; a couple of weeks ago. The loop is the thing that runs on top of it: it runs on a timer, it spawns helpers, and it feeds itself.&lt;/p&gt;
&lt;h2 id="the-five-pieces-and-the-one-that-holds-them-together"&gt;The five pieces, and the one that holds them together&lt;/h2&gt;
&lt;p&gt;Strip loop engineering down and you get roughly five building blocks, plus one place to remember things. Both Claude Code and Codex have all five now. The names differ here and there; the capability is the same.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Automations are the heartbeat.&lt;/strong&gt; They are what make a loop an actual loop and not one run you did once. A prompt or command on a cadence, a scheduled task, a hook that fires at a point in the agent&amp;rsquo;s lifecycle, or a job on CI that keeps running after you close the laptop. Discovery and triage run themselves, and the findings that matter come to you.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Worktrees keep parallel from turning into chaos.&lt;/strong&gt; The second you run more than one agent, the files start colliding. Two agents writing the same file is the same headache as two engineers committing to the same lines with nobody talking first. A git worktree is a separate working directory on its own branch, so one agent&amp;rsquo;s edits cannot touch another&amp;rsquo;s checkout.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skills are intent, written down.&lt;/strong&gt; An agent starts every session cold and fills any hole in your intent with a confident guess. A skill is that intent written on the outside: the conventions, the build steps, the &amp;ldquo;we don&amp;rsquo;t do it like this because of that one incident,&amp;rdquo; recorded once where the agent reads it every run. Without skills, the loop re-derives your whole project from zero every cycle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connectors let the loop touch your real tools.&lt;/strong&gt; Built on MCP, they let the agent read the issue tracker, query a database, hit a staging API, or drop a message in chat. This is the difference between an agent that says &amp;ldquo;here is the fix&amp;rdquo; and a loop that opens the pull request, links the ticket, and pings the channel once CI goes green.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sub-agents keep the maker away from the checker.&lt;/strong&gt; The model that wrote the code is far too generous grading its own homework. A second agent with different instructions, and sometimes a different model, catches the things the first one talked itself into. Worktrees and a cold-context reviewer are two pieces I have &lt;a href="https://www.pulumi.com/blog/parallel-coding-playbook-for-pulumi/"&gt;written about before&lt;/a&gt;, back when the question was running agents in parallel without them trampling each other.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then the sixth thing: memory. A markdown file, a Linear board, a state file, anything that lives outside the single conversation and holds what is done and what is next. It sounds too dumb to matter, and it&amp;rsquo;s the whole game. The model forgets everything between runs, so the memory has to live on disk, not in the context window. The agent forgets. The repo does not.&lt;/p&gt;
&lt;h2 id="what-makes-a-loop-hold-together"&gt;What makes a loop hold together&lt;/h2&gt;
&lt;p&gt;A loop running unattended is also a loop making mistakes unattended. The one thing that keeps it honest is verification, and verification needs an oracle, something outside the model that returns a hard yes or no. Passing tests, a clean build, a green pipeline, a real production signal. Without an oracle, the loop compounds confidently wrong work, faster than you can read it.&lt;/p&gt;
&lt;p&gt;The cleanest version of this already ships in the tools. Claude Code&amp;rsquo;s &lt;code&gt;/goal&lt;/code&gt; keeps working across turns until a condition you actually wrote holds, something like &amp;ldquo;every test in &lt;code&gt;auth/&lt;/code&gt; passes and lint is clean,&amp;rdquo; and after every turn a separate, faster model reads the transcript and decides whether you are there yet. The agent that wrote the code is not the one that grades it. That is the maker-and-checker split applied to the stop condition itself. Codex&amp;rsquo;s &lt;code&gt;/goal&lt;/code&gt; reaches the same finish line a different way: the agent audits its own work against the evidence before it can call the goal done.&lt;/p&gt;
&lt;h2 id="what-the-loop-still-wont-do-for-you"&gt;What the loop still won&amp;rsquo;t do for you&lt;/h2&gt;
&lt;p&gt;The loop changes the shape of the work. It does not take it off your desk. And a few things get sharper as the loop gets better, not softer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Verification is still on you.&lt;/strong&gt; The split reviewer is what makes &amp;ldquo;it&amp;rsquo;s done&amp;rdquo; mean something, but &amp;ldquo;done&amp;rdquo; is a claim, not a proof. Your job is still to ship code you confirmed works, which is harder to remember when the diff arrived while you were at lunch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The bill comes in two currencies.&lt;/strong&gt; Tokens and attention. A single unattended run can burn through millions of tokens, and that is only worth it when the tokens buy something worth more than they cost. The quieter trap is the second currency: memory is what lets a loop compound over time, and slop compounds right alongside it. A loop pointed at a vague goal does not get tired and stop. It gets faster.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Your understanding rots if you let it.&lt;/strong&gt; The faster the loop ships code you did not write, the wider the gap between what exists in the repo and what you actually understand. A smooth loop grows that gap faster, not slower, unless you read what it made. The comfortable posture, where you stop having an opinion and take whatever the loop gives back, is the risky one. Two engineers can build the exact same loop and get opposite results, one moving faster on work they understand deeply, the other avoiding the work entirely. The loop cannot tell which one you are.&lt;/p&gt;
&lt;h2 id="when-the-loop-reaches-production"&gt;When the loop reaches production&lt;/h2&gt;
&lt;p&gt;Most of this thinking grew up around application code, where a bad run costs you a revert. When the loop reaches into infrastructure, the blast radius is a production outage rather than a revert, and the verification bar has to rise to meet it. The upside is that infrastructure hands the loop a better oracle than application code does. A plan diff is deterministic and machine-readable, a policy check returns a hard verdict, and drift and cost are numbers you can put a threshold on. A reviewer, whether human or agent, can read the change cold, with no memory of the prompt that produced it. That cold-context check is exactly what an unattended loop needs, and it&amp;rsquo;s the reason an infrastructure loop can be built to hold together while you sleep. &lt;a href="https://www.pulumi.com/blog/grounded-ai-why-neo-knows-your-infrastructure/"&gt;Pulumi Neo reasons over the state graph directly&lt;/a&gt;, so the checker grounds every claim in what the change actually does, not in what the writer says it does.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Give your loop a real oracle&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Infrastructure gives an agent loop a strong oracle: a deterministic plan diff to read and policy checks that return a hard verdict before anything ships. Wire that verification in through the Pulumi MCP server, Agent Skills, or Pulumi Neo.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/docs/ai/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="where-to-start"&gt;Where to start&lt;/h2&gt;
&lt;p&gt;Pick the loop you can actually trust first. In order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Start where &amp;ldquo;done&amp;rdquo; is unambiguous.&lt;/strong&gt; CI triage, dependency bumps, a flaky-test hunt, a failing job you keep re-running by hand. Loops need an oracle, so begin where the oracle already exists.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write the memory file before the loop.&lt;/strong&gt; One markdown file, or a board. What is done, what is next, what was tried and failed. This is the spine, and everything else hangs off it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Split the checker from the maker.&lt;/strong&gt; Use &lt;code&gt;/goal&lt;/code&gt; with a verifiable condition, or a second agent with its own instructions. Never let the agent that did the work be the one that decides the work is finished.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cap it, then read everything.&lt;/strong&gt; A max-iteration count, a token budget, a teardown step. Run it once, end to end, then read every line it shipped. The first run is the measurement, not the payoff.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then look at what you built. You designed it once, and it ran without you steering each step. That is the real shift. But the leverage only holds if you wire the loop like an engineer, not like someone looking for permission to stop thinking. Read what it ships. Keep an opinion. Judgment is the one part that does not move up a layer.&lt;/p&gt;
&lt;p&gt;The loop will do the typing. The thinking is the work.&lt;/p&gt;
&lt;a
href="https://www.pulumi.com/product/neo/"
class="btn btn-primary"
&gt;
See how Pulumi Neo closes the loop on your infrastructure
&lt;/a&gt;</description><author>Engin Diri</author><category>ai</category><category>ai-agents</category><category>automation</category><category>claude</category><category>pulumi-neo</category><category>platform-engineering</category></item><item><title>Build an EKS Environment Factory with Pulumi and vCluster</title><link>https://www.pulumi.com/blog/eks-vcluster-ephemeral-environments-with-pulumi/</link><pubDate>Thu, 04 Jun 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/eks-vcluster-ephemeral-environments-with-pulumi/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/eks-vcluster-ephemeral-environments-with-pulumi/index.png" /&gt;
&lt;p&gt;AWS reports in an &lt;a href="https://aws.amazon.com/blogs/architecture/deloitte-optimizes-eks-environment-provisioning-and-achieves-89-faster-testing-environments-using-amazon-eks-and-vcluster/"&gt;AWS Architecture Blog case study&lt;/a&gt; that Deloitte&amp;rsquo;s move to a virtual cluster model on Amazon EKS resulted in 89% faster testing environment provisioning. By consolidating dozens of disparate clusters into a single host cluster with over 50 &lt;a href="https://www.vcluster.com/"&gt;vCluster&lt;/a&gt; instances, the case study says Deloitte saved about 500 QA hours per year. This &amp;ldquo;Environment Factory&amp;rdquo; pattern allows platform teams to provide isolated, ephemeral Kubernetes environments on demand without the cost or lag of full cluster provisioning.&lt;/p&gt;
&lt;p&gt;This post adapts that general architecture with Pulumi to orchestrate Amazon &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/automode.html"&gt;EKS Auto Mode&lt;/a&gt; and vCluster.&lt;/p&gt;
&lt;h2 id="the-problem-environment-sprawl-and-provisioning-lag"&gt;The problem: environment sprawl and provisioning lag&lt;/h2&gt;
&lt;p&gt;Traditional development workflows often rely on one full EKS cluster per developer or feature branch. While this provides strong isolation, it introduces major pain points. Provisioning a full cluster can take 15 minutes or more, which slows down CI/CD pipelines. Managing dozens of clusters also leads to high costs and significant operational overhead.&lt;/p&gt;
&lt;p&gt;Platform teams need a &amp;ldquo;soft multi-tenancy&amp;rdquo; model. This model should feel like a dedicated cluster to the developer but run on shared infrastructure to keep costs low and startup times fast.&lt;/p&gt;
&lt;h2 id="architecture-overview-the-host-and-the-tenants"&gt;Architecture overview: the host and the tenants&lt;/h2&gt;
&lt;p&gt;The environment factory architecture consists of two main layers.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Host cluster&lt;/strong&gt;: A single, reliable EKS cluster managed with EKS Auto Mode. This cluster provides the underlying compute, networking, and storage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tenant environments&lt;/strong&gt;: Virtual clusters (vCluster) running as pods within host namespaces.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;According to the &lt;a href="https://www.vcluster.com/docs/vcluster/introduction/architecture"&gt;vCluster architecture&lt;/a&gt;, the virtual control plane handles API requests while a syncer maps virtual resources to the host cluster. This separation allows tenants to manage their own CRDs, namespaces, and RBAC while platform teams use quotas, NetworkPolicies, pod security, IAM boundaries, and node isolation controls to protect the host and other tenants.&lt;/p&gt;
&lt;h2 id="implementation-the-eks-auto-mode-host"&gt;Implementation: the EKS Auto Mode host&lt;/h2&gt;
&lt;p&gt;EKS Auto Mode simplifies the host cluster by automating infrastructure management. It handles node provisioning, scaling, and updates based on pod requirements.&lt;/p&gt;
&lt;p&gt;The following snippet shows how to define an EKS cluster with Auto Mode enabled using Pulumi.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/awsx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;eks&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/eks&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SubnetType&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/awsx/ec2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clusterName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;environment-factory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vpc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Vpc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;environment-factory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;enableDnsHostnames&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;cidrBlock&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;10.0.0.0/16&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;subnetSpecs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SubnetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Public&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sb"&gt;`kubernetes.io/cluster/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;clusterName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;shared&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kubernetes.io/role/elb&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SubnetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Private&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sb"&gt;`kubernetes.io/cluster/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;clusterName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;shared&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kubernetes.io/role/internal-elb&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;subnetStrategy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Auto&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Create an EKS cluster with Auto Mode enabled.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hostCluster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;eks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cluster&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;host-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;: &lt;span class="kt"&gt;clusterName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;authenticationMode&lt;/span&gt;: &lt;span class="kt"&gt;eks.AuthenticationMode.Api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Use API authentication mode for EKS access entries.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;vpcId&lt;/span&gt;: &lt;span class="kt"&gt;vpc.vpcId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;publicSubnetIds&lt;/span&gt;: &lt;span class="kt"&gt;vpc.publicSubnetIds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;privateSubnetIds&lt;/span&gt;: &lt;span class="kt"&gt;vpc.privateSubnetIds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;autoMode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;enabled&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hostProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;host-provider&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kubeconfig&lt;/span&gt;: &lt;span class="kt"&gt;hostCluster.kubeconfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="implementation-the-environment-factory"&gt;Implementation: the environment factory&lt;/h2&gt;
&lt;p&gt;Once the host cluster is ready, we can build the factory that stamps out tenant environments. Each tenant needs a dedicated namespace, resource quotas, and the vCluster itself.&lt;/p&gt;
&lt;h3 id="tenant-guardrails"&gt;Tenant guardrails&lt;/h3&gt;
&lt;p&gt;Before installing vCluster, we set up a namespace and resource quotas to ensure one tenant cannot consume all host resources.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Define a tenant namespace on the host cluster.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tenantNamespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tenant-alpha&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tenant-alpha&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;: &lt;span class="kt"&gt;hostProvider&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Apply resource quotas to the tenant namespace.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quota&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResourceQuota&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tenant-quota&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tenantNamespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;hard&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;pods&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;20&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;requests.cpu&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;4&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;requests.memory&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;8Gi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;limits.cpu&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;limits.memory&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;16Gi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;: &lt;span class="kt"&gt;hostProvider&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Define a Role for the tenant within their namespace.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tenantRole&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rbac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Role&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tenant-role&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tenantNamespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;apiGroups&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pods&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;services&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;configmaps&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;secrets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;verbs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;get&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;list&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;watch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;create&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;update&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;patch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;delete&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;: &lt;span class="kt"&gt;hostProvider&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Bind the Role to a tenant user or group.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tenantRoleBinding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rbac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RoleBinding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tenant-role-binding&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tenantNamespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;subjects&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;User&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Replace &amp;#34;tenant-user&amp;#34; with the IAM-mapped user or group for this tenant.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tenant-user&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;apiGroup&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;rbac.authorization.k8s.io&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;roleRef&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Role&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;: &lt;span class="kt"&gt;tenantRole.metadata.name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;apiGroup&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;rbac.authorization.k8s.io&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;: &lt;span class="kt"&gt;hostProvider&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For production use, map these Kubernetes identities to IAM principals using EKS Access Entries, with the legacy &lt;code&gt;aws-auth&lt;/code&gt; ConfigMap still appearing in older clusters.&lt;/p&gt;
&lt;h3 id="deploying-vcluster-with-helm"&gt;Deploying vCluster with Helm&lt;/h3&gt;
&lt;p&gt;We use the &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/api-docs/helm/v3/release/"&gt;&lt;code&gt;kubernetes.helm.v3.Release&lt;/code&gt;&lt;/a&gt; resource to install vCluster. This resource provides controlled &lt;a href="https://helm.sh/"&gt;Helm&lt;/a&gt; lifecycle management for the vCluster release. The &lt;code&gt;values&lt;/code&gt; block should be adjusted for each tenant profile to control resource synchronization and control plane behavior. Review the &lt;a href="https://github.com/loft-sh/vcluster/releases"&gt;vCluster release notes&lt;/a&gt; when changing chart versions because values schema and generated secret names can change across releases.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Install vCluster using the Helm Release resource.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vcluster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;vcluster-alpha&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;vcluster-alpha&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;vcluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0.20.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Tested with vCluster 0.20.x; review release notes before changing versions.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;repositoryOpts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://charts.loft.sh&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tenantNamespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Explicit sync configuration; adjust per tenant profile.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;toHost&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;pods&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;enabled&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;: &lt;span class="kt"&gt;hostProvider&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="accessing-the-virtual-cluster"&gt;Accessing the virtual cluster&lt;/h3&gt;
&lt;p&gt;The vCluster generates a kubeconfig that allows developers to interact with the virtual API server. We must treat this kubeconfig as a secret, and the endpoint in that kubeconfig must be reachable from the Pulumi runner before using it to create resources inside the virtual cluster.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Retrieve the vCluster kubeconfig from the generated secret.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// The vCluster-generated secret can lag behind Helm release readiness on first creation,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// so teams may choose an explicit readiness check or rerun after the virtual control plane initializes.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vclusterKubeconfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;vcluster-secret&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolate&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tenantNamespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;/vc-vcluster-alpha`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;: &lt;span class="kt"&gt;hostProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;dependsOn&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;vcluster&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;config&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;base64&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Export the kubeconfig as a secret.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tenantKubeconfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;vclusterKubeconfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Create a provider for the virtual cluster using the secret kubeconfig.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vclusterProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;vcluster-provider&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kubeconfig&lt;/span&gt;: &lt;span class="kt"&gt;tenantKubeconfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Provision environments on demand&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Model your host cluster, vCluster tenants, and guardrails in Pulumi so your platform team can hand developers isolated test environments and clean them up as code.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="operational-caveats"&gt;Operational caveats&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RBAC and permissions&lt;/strong&gt;: vCluster generates default RBAC rules that work for most scenarios. However, if your host cluster is heavily locked down, you may need to provide additional permissions to the vCluster service account.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Helm release previews&lt;/strong&gt;: When using &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/api-docs/helm/v3/release/"&gt;&lt;code&gt;kubernetes.helm.v3.Release&lt;/code&gt;&lt;/a&gt;, Pulumi previews may not show every detail of the rendered Kubernetes resources. It primarily tracks the state of the Helm release itself.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EKS Auto Mode node lifetime&lt;/strong&gt;: EKS Auto Mode uses immutable AMIs and has a 21-day node lifetime. Kubernetes reschedules vCluster pods and tenant workloads when nodes are replaced, so configure replicas, PodDisruptionBudgets, requests, and persistent storage for disruption tolerance.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion-ephemeral-environments-at-scale"&gt;Conclusion: ephemeral environments at scale&lt;/h2&gt;
&lt;p&gt;By combining Pulumi with EKS Auto Mode and vCluster, you can build a scalable environment factory. This approach provides the isolation developers need while maintaining the speed and cost-efficiency required by platform teams.&lt;/p&gt;
&lt;p&gt;The snippets provided here are adapted for illustration. In a production environment, you would likely wrap these resources into a Pulumi &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;ComponentResource&lt;/a&gt; to provide a clean, reusable API for your internal developers. When a feature branch is merged, deleting the Pulumi stack removes the resources managed by that stack, but validate namespace finalizers, persistent volume reclaim policies, and external cloud artifacts as part of cleanup.&lt;/p&gt;
&lt;p&gt;For more on managing EKS with Pulumi, see the &lt;a href="https://www.pulumi.com/docs/clouds/aws/guides/eks/"&gt;EKS guide&lt;/a&gt;.&lt;/p&gt;</description><author>Pablo Seibelt</author><category>aws</category><category>kubernetes</category><category>platform-engineering</category></item><item><title>Why Choose Pulumi Over Terraform?</title><link>https://www.pulumi.com/blog/why-choose-pulumi-over-terraform/</link><pubDate>Tue, 02 Jun 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/why-choose-pulumi-over-terraform/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/why-choose-pulumi-over-terraform/index.png" /&gt;
&lt;p&gt;&lt;a href="https://developer.hashicorp.com/terraform/intro"&gt;Terraform&lt;/a&gt; is a proven infrastructure as code tool with a large &lt;a href="https://registry.terraform.io/"&gt;provider and module ecosystem&lt;/a&gt;. Many teams choose Pulumi when they want to keep that infrastructure as code model, but write and maintain infrastructure with general-purpose programming languages, familiar package managers, IDEs, &lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/"&gt;testing&lt;/a&gt;, and software engineering patterns, while still understanding the refactoring tradeoffs in Terraform&amp;rsquo;s own &lt;a href="https://developer.hashicorp.com/terraform/language/modules/develop/refactoring"&gt;module refactoring guidance&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Why choose Pulumi over Terraform? Pulumi&amp;rsquo;s &lt;a href="https://www.pulumi.com/docs/iac/languages-sdks/"&gt;language SDKs&lt;/a&gt; let teams define cloud infrastructure in TypeScript, Python, Go, C#, Java, or YAML while adding first-class workflows for refactoring with &lt;a href="https://www.pulumi.com/docs/iac/concepts/options/aliases/"&gt;Pulumi aliases&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/concepts/secrets/"&gt;secrets&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/concepts/options/protect/"&gt;protect&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/options/retainondelete/"&gt;retainOnDelete&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/concepts/options/deletebeforereplace/"&gt;deleteBeforeReplace&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/concepts/options/replaceonchanges/"&gt;replaceOnChanges&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/providers/"&gt;provider resources&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/concepts/stacks/"&gt;Pulumi stacks&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/"&gt;testing&lt;/a&gt;, and incremental migration with &lt;a href="https://www.pulumi.com/docs/iac/adopting-pulumi/import/"&gt;&lt;code&gt;pulumi import&lt;/code&gt;&lt;/a&gt;. Pulumi does not remove every hard problem in cloud infrastructure, but it gives teams stronger tools for many day-to-day pain points.&lt;/p&gt;
&lt;h2 id="executive-summary"&gt;Executive summary&lt;/h2&gt;
&lt;p&gt;Pulumi is often a better fit when infrastructure code needs to behave like application code: reviewed, tested, packaged, refactored, and shared across teams. The biggest advantages show up when teams need safer refactors, encrypted &lt;a href="https://www.pulumi.com/docs/iac/concepts/secrets/"&gt;secret values&lt;/a&gt;, reusable components, clearer &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/providers/"&gt;provider resources&lt;/a&gt;, and guardrails around destructive changes.&lt;/p&gt;
&lt;p&gt;The tradeoff is important: Pulumi is still an infrastructure as code engine. Provider bugs, cloud API eventual consistency, &lt;a href="https://www.pulumi.com/docs/iac/cli/commands/pulumi_refresh/"&gt;drift&lt;/a&gt;, preview-time unknowns, and poorly designed abstractions still require engineering discipline. The advantage is not magic. The advantage is a stronger programming model and a more familiar developer workflow.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Terraform pattern&lt;/th&gt;
&lt;th&gt;Pulumi advantage&lt;/th&gt;
&lt;th&gt;What still needs care&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Languages and tooling&lt;/td&gt;
&lt;td&gt;HCL plus Terraform-specific functions and expressions&lt;/td&gt;
&lt;td&gt;Pulumi supports general-purpose languages, YAML, and now &lt;a href="https://www.pulumi.com/docs/iac/languages-sdks/hcl/"&gt;HCL&lt;/a&gt; natively, with the normal IDE, test, and package workflows for each&lt;/td&gt;
&lt;td&gt;Teams still need code review and shared conventions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Refactoring&lt;/td&gt;
&lt;td&gt;Moved blocks or state commands for resource identity changes&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.pulumi.com/docs/iac/concepts/options/aliases/"&gt;Pulumi aliases&lt;/a&gt; can map old resource identities to new ones during refactors&lt;/td&gt;
&lt;td&gt;Aliases must model the old identity correctly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secrets&lt;/td&gt;
&lt;td&gt;Sensitive values can still require careful state and plan handling&lt;/td&gt;
&lt;td&gt;Pulumi tracks &lt;a href="https://www.pulumi.com/docs/iac/concepts/secrets/"&gt;secrets&lt;/a&gt; and encrypts secret values in state&lt;/td&gt;
&lt;td&gt;Secrets are still available to code at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lifecycle safety&lt;/td&gt;
&lt;td&gt;Lifecycle meta-arguments and plan review&lt;/td&gt;
&lt;td&gt;Pulumi resource options such as &lt;a href="https://www.pulumi.com/docs/iac/concepts/options/protect/"&gt;protect&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/options/retainondelete/"&gt;retainOnDelete&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/concepts/options/deletebeforereplace/"&gt;deleteBeforeReplace&lt;/a&gt;, and &lt;a href="https://www.pulumi.com/docs/iac/concepts/options/replaceonchanges/"&gt;replaceOnChanges&lt;/a&gt; make intent explicit&lt;/td&gt;
&lt;td&gt;Provider behavior and replacement semantics still matter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environments&lt;/td&gt;
&lt;td&gt;Workspaces or separate configurations&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.pulumi.com/docs/concepts/stacks/"&gt;Pulumi stacks&lt;/a&gt; model environments with per-stack config, secrets, history, and outputs&lt;/td&gt;
&lt;td&gt;Stack boundaries still need thoughtful design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code reuse&lt;/td&gt;
&lt;td&gt;Modules and HCL composition patterns&lt;/td&gt;
&lt;td&gt;Pulumi components and packages use normal language abstractions&lt;/td&gt;
&lt;td&gt;Over-abstracted components can become hard to use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Imports and migration&lt;/td&gt;
&lt;td&gt;Import blocks, generated config, and state operations&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.pulumi.com/docs/iac/adopting-pulumi/import/"&gt;&lt;code&gt;pulumi import&lt;/code&gt;&lt;/a&gt; and migration tooling support gradual adoption&lt;/td&gt;
&lt;td&gt;Imported code still needs review and cleanup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terraform state&lt;/td&gt;
&lt;td&gt;S3, Azure Blob, or Terraform Cloud backends&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.pulumi.com/docs/iac/get-started/terraform/terraform-state-backend/"&gt;Pulumi Cloud can serve as a Terraform state backend&lt;/a&gt; with encrypted storage, locking, history, and RBAC, while you keep using the Terraform or OpenTofu CLI&lt;/td&gt;
&lt;td&gt;State still needs a clean migration plan as resources move to Pulumi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provider wiring&lt;/td&gt;
&lt;td&gt;Provider inheritance and aliases inside modules&lt;/td&gt;
&lt;td&gt;Explicit &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/providers/"&gt;provider resources&lt;/a&gt; make multi-region and multi-account wiring visible in code review&lt;/td&gt;
&lt;td&gt;Provider versions and bugs can still affect deployments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testing&lt;/td&gt;
&lt;td&gt;Validation, plan review, and external test harnesses&lt;/td&gt;
&lt;td&gt;Pulumi programs can use normal &lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/"&gt;unit and integration test frameworks&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Tests complement previews, they do not replace them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Drift detection&lt;/td&gt;
&lt;td&gt;Refresh and refresh-only plans, plus external scheduling&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.pulumi.com/docs/iac/cli/commands/pulumi_refresh/"&gt;&lt;code&gt;pulumi refresh&lt;/code&gt;&lt;/a&gt; reconciles state, and Pulumi Cloud adds &lt;a href="https://www.pulumi.com/docs/deployments/deployments/drift/"&gt;scheduled drift detection and remediation&lt;/a&gt; on a configurable cadence&lt;/td&gt;
&lt;td&gt;Detection still depends on provider behavior and a healthy state backend&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caveats&lt;/td&gt;
&lt;td&gt;Declarative planning still has unknowns and drift&lt;/td&gt;
&lt;td&gt;Pulumi improves the workflow around many pain points&lt;/td&gt;
&lt;td&gt;It does not eliminate provider bugs or eventual consistency&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="use-programming-languages-and-familiar-tools"&gt;Use programming languages and familiar tools&lt;/h2&gt;
&lt;p&gt;Terraform modules are powerful, but larger HCL codebases can require teams to maintain separate conventions for composition, validation, and reuse. Pulumi lets infrastructure teams use the features of whichever &lt;a href="https://www.pulumi.com/docs/iac/languages-sdks/"&gt;supported programming language&lt;/a&gt; they choose, such as classes, functions, types, loops, package managers, linters, and test frameworks.&lt;/p&gt;
&lt;p&gt;Teams with HCL muscle memory are not left out, either. Pulumi now &lt;a href="https://www.pulumi.com/docs/iac/languages-sdks/hcl/"&gt;supports HCL natively&lt;/a&gt; as one of its languages, alongside Python, TypeScript, Go, C#, Java, and YAML. Part of a team can keep authoring in HCL while the project still benefits from Pulumi components, testing, and the same engine and package workflows as every other language.&lt;/p&gt;
&lt;p&gt;For example, a platform team can wrap a standard storage pattern in a &lt;code&gt;ComponentResource&lt;/code&gt; and share it like any other TypeScript abstraction:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/aws&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;WorkQueueArgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;visibilityTimeoutSeconds&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;WorkQueue&lt;/span&gt; &lt;span class="kr"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentResource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;queueUrl&lt;/span&gt;: &lt;span class="kt"&gt;pulumi.Output&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;: &lt;span class="kt"&gt;WorkQueueArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts?&lt;/span&gt;: &lt;span class="kt"&gt;pulumi.ComponentResourceOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;platform:queue:WorkQueue&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-queue`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;visibilityTimeoutSeconds&lt;/span&gt;: &lt;span class="kt"&gt;args.visibilityTimeoutSeconds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queueUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerOutputs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;queueUrl&lt;/span&gt;: &lt;span class="kt"&gt;this.queueUrl&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WorkQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;image-jobs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;visibilityTimeoutSeconds&lt;/span&gt;: &lt;span class="kt"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="refactor-infrastructure-without-surprise-replacement"&gt;Refactor infrastructure without surprise replacement&lt;/h2&gt;
&lt;p&gt;Renaming a resource, moving it into a component, or reorganizing a project should not automatically mean replacing production infrastructure. Pulumi aliases let you tell Pulumi how a resource used to be addressed, so refactors can preserve resource identity when the old and new resources represent the same cloud object.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;app-jobs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;visibilityTimeoutSeconds&lt;/span&gt;: &lt;span class="kt"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;aliases&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;jobs&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://www.pulumi.com/docs/iac/concepts/options/aliases/"&gt;Aliases&lt;/a&gt; are not a substitute for review. They work when the old identity is modeled correctly, including details such as name, parent, type, project, and stack when those changed.&lt;/p&gt;
&lt;h2 id="handle-secrets-with-encrypted-configuration-and-secret-outputs"&gt;Handle secrets with encrypted configuration and secret outputs&lt;/h2&gt;
&lt;p&gt;Secrets are one of the most common places where infrastructure workflows become risky. Terraform has &lt;a href="https://developer.hashicorp.com/terraform/language/manage-sensitive-data"&gt;sensitive values and backend guidance&lt;/a&gt;, but teams still need to understand how plans, state, outputs, and backend access interact. Pulumi treats &lt;a href="https://www.pulumi.com/docs/iac/concepts/secrets/"&gt;secrets&lt;/a&gt; as first-class values, encrypts them in state, and preserves secrecy as values flow through outputs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requireSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;dbPassword&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;passwordParameter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ssm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;db-password&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;SecureString&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;value&lt;/span&gt;: &lt;span class="kt"&gt;dbPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This improves the default experience, but it&amp;rsquo;s not runtime isolation. In the TypeScript SDK, &lt;code&gt;config.requireSecret(&amp;quot;dbPassword&amp;quot;)&lt;/code&gt; retrieves secret configuration, and your program can still access the decrypted value while it runs, so reviews, least privilege, and secret-provider choices still matter. If a value starts as a plain input instead of coming from &lt;code&gt;requireSecret&lt;/code&gt;, &lt;a href="https://www.pulumi.com/docs/iac/concepts/secrets/"&gt;&lt;code&gt;pulumi.secret(...)&lt;/code&gt;&lt;/a&gt; can mark it as secret.&lt;/p&gt;
&lt;p&gt;For secrets that shouldn&amp;rsquo;t live in stack config at all, &lt;a href="https://www.pulumi.com/docs/esc/"&gt;Pulumi ESC&lt;/a&gt; (Environments, Secrets, and Configuration) centralizes them in environments that your stacks consume through config. ESC can pull secrets dynamically from external stores such as HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, and 1Password, and mint short-lived OIDC credentials for AWS, Azure, and GCP. That lets you &lt;a href="https://www.pulumi.com/docs/esc/guides/integrate-with-pulumi-iac/"&gt;wire an environment into a Pulumi program&lt;/a&gt; instead of storing long-lived credentials in state.&lt;/p&gt;
&lt;h2 id="add-safer-lifecycle-controls-for-destructive-changes"&gt;Add safer lifecycle controls for destructive changes&lt;/h2&gt;
&lt;p&gt;Infrastructure mistakes are expensive when they replace or delete stateful resources. Pulumi gives teams explicit resource options for safety-sensitive intent, such as &lt;code&gt;protect&lt;/code&gt;, &lt;code&gt;retainOnDelete&lt;/code&gt;, &lt;code&gt;deleteBeforeReplace&lt;/code&gt;, and &lt;code&gt;replaceOnChanges&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;orders-db&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;instanceClass&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;db.t4g.micro&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;allocatedStorage&lt;/span&gt;: &lt;span class="kt"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;postgres&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;password&lt;/span&gt;: &lt;span class="kt"&gt;dbPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;protect&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;retainOnDelete&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These controls are guardrails, not guarantees. Provider bugs, cloud API eventual consistency, and replacement behavior still require preview review and operational judgment. &lt;a href="https://www.pulumi.com/docs/iac/concepts/options/replaceonchanges/"&gt;&lt;code&gt;replaceOnChanges&lt;/code&gt;&lt;/a&gt; applies to custom resources only, not component resources.&lt;/p&gt;
&lt;h2 id="model-environments-with-stacks"&gt;Model environments with stacks&lt;/h2&gt;
&lt;p&gt;Terraform workspaces can represent environments, but many teams eventually need stronger boundaries for configuration, secrets, history, and cross-environment outputs. &lt;a href="https://www.pulumi.com/docs/concepts/stacks/"&gt;Pulumi stacks&lt;/a&gt; make environment boundaries explicit and pair them with per-stack config and outputs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;networking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StackReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;acme/networking/prod&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vpcId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;networking&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requireOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;vpcId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appSecurityGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SecurityGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;app-sg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;vpcId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;fromPort&lt;/span&gt;: &lt;span class="kt"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;toPort&lt;/span&gt;: &lt;span class="kt"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;cidrBlocks&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;10.0.0.0/8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;egress&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;fromPort&lt;/span&gt;: &lt;span class="kt"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;toPort&lt;/span&gt;: &lt;span class="kt"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;cidrBlocks&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0.0.0.0/0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cross-stack references are cleaner than sharing an entire remote state file, but they are still dependencies. Keep stack outputs intentional and avoid turning one stack into a global variable bag.&lt;/p&gt;
&lt;h2 id="test-infrastructure-with-normal-language-tooling"&gt;Test infrastructure with normal language tooling&lt;/h2&gt;
&lt;p&gt;Because Pulumi programs are real programs, infrastructure testing can use familiar test runners and assertions. Teams can test component defaults, naming conventions, required tags, and policy assumptions before a deployment reaches production.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setMocks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;newResource&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;_id`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;state&lt;/span&gt;: &lt;span class="kt"&gt;args.inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Testing does not replace previews. It catches a different class of problems: broken abstractions, missing required inputs, invalid defaults, and regressions in shared components.&lt;/p&gt;
&lt;h2 id="wire-providers-explicitly"&gt;Wire providers explicitly&lt;/h2&gt;
&lt;p&gt;Provider configuration is another place where explicit code can reduce ambiguity. In Terraform, provider inheritance and aliases are often managed across module boundaries. In Pulumi, &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/providers/"&gt;provider resources&lt;/a&gt; are normal resources that can be passed through resource options, which makes multi-region or multi-account deployments easier to follow in code review.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;west&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;west&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;us-west-2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;east&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;east&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;us-east-1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;primary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;primary-jobs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;: &lt;span class="kt"&gt;west&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;replica&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;replica-jobs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;: &lt;span class="kt"&gt;east&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The provider object does not remove provider versioning or schema-change risk, but it makes provider wiring visible in the same language and review flow as the rest of the program.&lt;/p&gt;
&lt;h2 id="detect-and-reconcile-drift"&gt;Detect and reconcile drift&lt;/h2&gt;
&lt;p&gt;Infrastructure drifts when something changes outside your IaC tool: a hotfix in the console, another controller, or a manual break-glass change. Pulumi gives you first-class tools to find and fix it instead of leaving it to chance. &lt;a href="https://www.pulumi.com/docs/iac/cli/commands/pulumi_refresh/"&gt;&lt;code&gt;pulumi refresh&lt;/code&gt;&lt;/a&gt; reconciles your state with what is actually running in the cloud, and &lt;code&gt;pulumi preview --diff&lt;/code&gt; shows what the next update would change.&lt;/p&gt;
&lt;p&gt;For teams that want this continuously, Pulumi Cloud adds &lt;a href="https://www.pulumi.com/docs/deployments/deployments/drift/"&gt;scheduled drift detection and remediation&lt;/a&gt; that runs on a configurable cadence and can automatically remediate drift when it is detected. That turns finding and correcting out-of-band changes into a managed workflow rather than something a person has to remember to check.&lt;/p&gt;
&lt;p&gt;Drift detection still depends on accurate provider behavior and a healthy state backend, so it complements review and operational discipline rather than replacing them.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Adopt Pulumi at your own pace&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Bring your existing Terraform infrastructure across one stack at a time, using general-purpose languages and the software workflows your team already relies on.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="import-and-migrate-incrementally"&gt;Import and migrate incrementally&lt;/h2&gt;
&lt;p&gt;Teams rarely get to rebuild infrastructure from scratch. Pulumi supports incremental adoption with &lt;a href="https://www.pulumi.com/docs/iac/adopting-pulumi/import/"&gt;&lt;code&gt;pulumi import&lt;/code&gt;&lt;/a&gt;, generated code, and Terraform interoperability paths. That makes it possible to start with one resource, one component, or one stack instead of forcing a big-bang migration.&lt;/p&gt;
&lt;p&gt;Pulumi also supports interoperability paths for teams that need to bring existing Terraform assets forward over time, including Terraform provider access and migration workflows. That makes migration an engineering sequence, not an all-or-nothing rewrite.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;importedRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ecr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Repository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;existing-app-repo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;import&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;existing-app-repo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The CLI flow can also generate declarations with &lt;code&gt;pulumi import&lt;/code&gt;. Generated code is a starting point, not a finished architecture. Review names, options, providers, secrets, and component boundaries before treating imported resources as production-ready Pulumi code.&lt;/p&gt;
&lt;p&gt;You also don&amp;rsquo;t have to do it alone. Pulumi provides &lt;a href="https://www.pulumi.com/migrate/"&gt;self-serve conversion tools and expert migration services&lt;/a&gt;, and for teams leaving HashiCorp, &lt;a href="https://www.pulumi.com/blog/all-iac-including-terraform-and-hcl/"&gt;credits you can apply toward Pulumi to avoid paying for two tools at once&lt;/a&gt;, so budget and timing don&amp;rsquo;t have to block getting started.&lt;/p&gt;
&lt;h2 id="manage-terraform-state-in-pulumi-cloud"&gt;Manage Terraform state in Pulumi Cloud&lt;/h2&gt;
&lt;p&gt;You don&amp;rsquo;t have to rewrite anything to start getting value from Pulumi. Pulumi Cloud can serve as a Terraform state backend, letting you store and manage Terraform state alongside your Pulumi stacks. Your team can keep using the Terraform or OpenTofu CLI for day-to-day operations while gaining encrypted state storage, update history, state locking, role-based access control, audit policies, and unified resource visibility through Pulumi Insights — with agentic infrastructure coding through Neo on top.&lt;/p&gt;
&lt;p&gt;It uses Terraform&amp;rsquo;s standard remote backend, so you point the CLI at Pulumi Cloud without changing your infrastructure code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;remote&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;api.pulumi.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; organization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;your-pulumi-org&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;workspaces&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;_dev&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From there, Pulumi can also read outputs from that state, so a new Pulumi stack can consume Terraform-managed values such as VPC IDs and subnet IDs while you migrate one piece at a time. When you&amp;rsquo;re ready to bring resources fully across, &lt;a href="https://www.pulumi.com/docs/iac/adopting-pulumi/import/"&gt;&lt;code&gt;pulumi import --from terraform&lt;/code&gt;&lt;/a&gt; reads a &lt;code&gt;.tfstate&lt;/code&gt; file and generates matching declarations, and &lt;code&gt;pulumi convert --from terraform&lt;/code&gt; translates the surrounding configuration into your chosen language.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/docs/iac/get-started/terraform/terraform-state-backend/"&gt;Storing Terraform state in Pulumi Cloud&lt;/a&gt; keeps both tools pointed at one system of record, which is what makes a gradual, low-risk migration practical.&lt;/p&gt;
&lt;h2 id="what-pulumi-does-not-magically-fix"&gt;What Pulumi does not magically fix&lt;/h2&gt;
&lt;p&gt;Pulumi does not eliminate cloud API eventual consistency. A deployment can finish successfully while downstream reads, controllers, or other operators still see stale state for a short window. That is a property of the cloud control plane, not of the IaC tool.&lt;/p&gt;
&lt;p&gt;Pulumi also does not eliminate provider bugs. If a provider has a schema issue, a bad default, or a flaky update path, Pulumi still has to ride that provider behavior. Drift will still happen when infrastructure changes outside Pulumi, too. The difference is that Pulumi gives you first-class tooling to detect and reconcile it, as covered in &lt;a href="#detect-and-reconcile-drift"&gt;Detect and reconcile drift&lt;/a&gt; above — but the drift itself, and the discipline to act on it, do not disappear.&lt;/p&gt;
&lt;p&gt;Pulumi does not eliminate preview-time unknowns either. Some values are not known until deployment, so the plan can still contain uncertainty. Bad project decomposition and side-effect-heavy deployment code remain risks too, which is why &lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/"&gt;testing&lt;/a&gt;, clear stack boundaries, and disciplined component design still matter.&lt;/p&gt;
&lt;h2 id="opentofu-compatibility-caveat"&gt;OpenTofu compatibility caveat&lt;/h2&gt;
&lt;p&gt;OpenTofu users face many of the same infrastructure-as-code concerns around state, providers, drift, secrets, lifecycle behavior, and migration planning. This post stays Terraform-focused because that is where most teams begin the Pulumi comparison, but the same Pulumi capabilities are relevant when evaluating OpenTofu alternatives or hybrid migration paths.&lt;/p&gt;
&lt;p&gt;Pulumi can also work with Terraform provider ecosystems, including long-tail providers that may not have a native Pulumi package yet. Treat that as an interoperability path, not a promise that every Terraform or OpenTofu workflow maps one-for-one without design work.&lt;/p&gt;
&lt;h2 id="get-started-with-pulumi"&gt;Get started with Pulumi&lt;/h2&gt;
&lt;p&gt;If your team is evaluating infrastructure as code options, start with the workflow that creates the most leverage: write infrastructure in the language your team already uses, test shared components, protect critical resources, and migrate one stack at a time.&lt;/p&gt;
&lt;p&gt;To go deeper, &lt;a href="https://www.pulumi.com/docs/iac/get-started/"&gt;get started with Pulumi&lt;/a&gt; or read the &lt;a href="https://www.pulumi.com/docs/iac/adopting-pulumi/migrating-to-pulumi/from-terraform/"&gt;Terraform migration guide&lt;/a&gt;.&lt;/p&gt;</description><author>Pablo Seibelt</author><category>infrastructure-as-code</category><category>terraform</category><category>pulumi</category><category>platform-engineering</category></item><item><title>Five Stacks Before Lunch: The Parallel Coding Playbook for Pulumi</title><link>https://www.pulumi.com/blog/parallel-coding-playbook-for-pulumi/</link><pubDate>Tue, 02 Jun 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/parallel-coding-playbook-for-pulumi/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/parallel-coding-playbook-for-pulumi/index.png" /&gt;
&lt;p&gt;AI coding has two shapes right now. One agent in a loop, sequential work, you babysitting the chat window. Call that 2x. Most teams live here. Five agents in worktrees, parallel work, fresh-context review on every change. Call that 10x. The trick: 2x is mostly prompting, 10x is mostly plumbing.&lt;/p&gt;
&lt;p&gt;The parallel coding playbook is a five-pattern setup for running multiple AI coding agents at the same time without them stepping on each other: an issue used as the spec, a plan/build/validate loop, parallel git worktrees, fresh-session review, and a self-healing layer. The whole thing targets application code. The interesting question, and the one I keep ending up at, is what changes when the five agents are touching infrastructure.&lt;/p&gt;
&lt;h2 id="2x-is-prompting-10x-is-plumbing"&gt;2x is prompting, 10x is plumbing&lt;/h2&gt;
&lt;p&gt;2x is one human, one agent, one repo, one branch. The agent writes, you review, you tell it to try again, it tries again. The bottleneck is your attention. Whatever the agent&amp;rsquo;s raw throughput, your reading speed sets the ceiling.&lt;/p&gt;
&lt;p&gt;10x moves you out of the per-change loop and into the issue loop. You write five issues with sharp acceptance criteria, send each one to its own agent in its own worktree, and let them plan, build, and validate end-to-end. You read five PRs at lunch instead of pair-programming on one all morning.&lt;/p&gt;
&lt;p&gt;Concurrent isolation does the work. And isolation is mostly an infrastructure problem.&lt;/p&gt;
&lt;h2 id="the-five-pillars"&gt;The five pillars&lt;/h2&gt;
&lt;p&gt;&lt;img src="./pillars.png" alt="The five pillars of the parallel coding playbook mapped to their Pulumi primitives: issue is the spec to a component contract plus a Pulumi Policies excerpt, plan-build-validate to a markdown plan plus pulumi up &amp;ndash;target plus pulumi preview, parallel worktrees to a per-worktree review stack with its own ESC environment, fresh-session review to a second agent reading the preview JSON cold, and self-healing layer to Pulumi Policies rules phrased as instructions"&gt;&lt;/p&gt;
&lt;p&gt;The five pillars, in one sentence each.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Issue is the spec.&lt;/strong&gt; The GitHub issue carries the acceptance criteria. The pull request is the artifact that gets validated. Input and output of every implementation are versioned, scoped, and reviewable on their own.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plan, build, validate.&lt;/strong&gt; Three stages, three artifacts. A markdown plan you can read in thirty seconds. A build that produces a diff. A validate step that checks the diff against the spec.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Parallel worktrees.&lt;/strong&gt; Each agent runs in its own git worktree so concurrent changes never trample each other. One repo, five working trees, five branches.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fresh-session review.&lt;/strong&gt; A different agent, a different conversation, no shared context, reads the output and judges it. The reviewer never sees the writer&amp;rsquo;s chat. An agent reviewing its own output in the same context is theater.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Self-healing layer.&lt;/strong&gt; When the same issue keeps coming back, fix the system that allowed it. Update the rules, the skills, the &lt;code&gt;AGENTS.md&lt;/code&gt;. The agent gets better; the bug class disappears.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The application-code version of this playbook leans on ports, node_modules, and databases to get isolation right. The infrastructure version has a different toolbox.&lt;/p&gt;
&lt;h2 id="what-changes-when-the-agents-are-touching-infrastructure"&gt;What changes when the agents are touching infrastructure&lt;/h2&gt;
&lt;p&gt;Walk the pillars again, this time with a Pulumi shop in mind.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Issue is the spec.&lt;/strong&gt; For application code, the spec describes behavior. For infrastructure, the spec is a &lt;a href="https://www.pulumi.com/docs/iac/concepts/components/"&gt;Pulumi component&lt;/a&gt; contract plus a &lt;a href="https://www.pulumi.com/docs/insights/policy/"&gt;Pulumi Policies&lt;/a&gt; excerpt. &amp;ldquo;The resulting bucket is private, lives in eu-west-1, has SSE-KMS, and is tagged &lt;code&gt;owner=team-x&lt;/code&gt;.&amp;rdquo; That sentence compiles to a typed component signature and three policy assertions. The agent does not get to interpret &amp;ldquo;looks right.&amp;rdquo; The acceptance criteria are deterministic, which is the whole reason this works.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Plan, build, validate.&lt;/strong&gt; Pulumi already ships the validate step. &lt;code&gt;pulumi preview&lt;/code&gt; produces a deterministic, machine-readable diff a second reviewer can judge without the conversation that produced it. The plan is a markdown doc the agent writes before touching code. The build is &lt;code&gt;pulumi up --target&lt;/code&gt; against a review stack scoped to the resources the issue covers. The validate step is the preview output plus the &lt;a href="https://www.pulumi.com/docs/insights/policy/"&gt;Pulumi Policies&lt;/a&gt; verdict.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Parallel worktrees.&lt;/strong&gt; Worktrees alone are not enough. Two worktrees pointing at the same Pulumi stack will fight over state on the first concurrent &lt;code&gt;up&lt;/code&gt;. The unit of isolation for infrastructure is the &lt;a href="https://www.pulumi.com/docs/iac/concepts/stacks/"&gt;stack&lt;/a&gt;, not the worktree. Each worktree gets its own ephemeral &lt;a href="https://www.pulumi.com/docs/deployments/deployments/review-stacks/"&gt;review stack&lt;/a&gt; and its own &lt;a href="https://www.pulumi.com/docs/esc/"&gt;ESC environment&lt;/a&gt; for credentials. State branches with the work, credentials branch with the work, and the cloud account does not see five agents elbowing each other.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fresh-session review.&lt;/strong&gt; The hardest part of the application-code version is keeping the reviewer cold. For infrastructure, the substrate hands you the cold context. The &lt;code&gt;pulumi preview&lt;/code&gt; JSON has no memory of the prompt that produced it. A separate agent reading it has the same starting point a human reviewer has: a diff, a stack name, a policy report. &lt;a href="https://www.pulumi.com/blog/grounded-ai-why-neo-knows-your-infrastructure/"&gt;Pulumi Neo reasons over the state graph directly&lt;/a&gt;, so the reviewer grounds every claim in what the change actually does, not what the writer says it does. Reviewer quality still depends on how well your policies cover the stack, but the cold-context part comes built in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Self-healing layer.&lt;/strong&gt; Most Pulumi Policies rule messages today read like assertions. &amp;ldquo;S3 bucket has no encryption.&amp;rdquo; A self-healing layer needs them to read like instructions. &amp;ldquo;S3 bucket has no encryption. Set &lt;code&gt;serverSideEncryptionConfiguration&lt;/code&gt; with SSE-KMS to fix.&amp;rdquo; That single rewrite is the difference between an agent flailing and an agent fixing the violation on the first try. When the same rule keeps tripping, the fix is upstream of the next pull request: in the rules, in the skills, in the policy itself.&lt;/p&gt;
&lt;h2 id="the-five-catches-infra-edition"&gt;The five catches, infra edition&lt;/h2&gt;
&lt;p&gt;&lt;img src="./catches.png" alt="The five parallel-coding catches and their infrastructure equivalents: port conflicts become stack-name collisions handled by hashing the worktree into the stack name, node_modules sprawl becomes provider plugin sprawl which Pulumi already solves through a shared plugin cache, database conflicts become state conflicts solved by giving every worktree its own review stack, token blowouts become cloud spend per ephemeral stack controlled with TTLs and retainOnDelete, and PR pile-up is the same problem solved with stack-scoped reviewers and auto-merge for clean previews"&gt;&lt;/p&gt;
&lt;p&gt;Every parallelism story has a catch list. The application-code version lists port conflicts, node_modules sprawl, database conflicts, token blowouts, and PR pile-up. The infrastructure equivalents map almost one to one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Port conflicts become stack-name collisions.&lt;/strong&gt; Two agents naming their stack &lt;code&gt;dev&lt;/code&gt; and racing each other into Pulumi Cloud. The fix is the same hash-the-path trick the app-code playbook uses: derive the stack name from &lt;code&gt;pulumi.getProject()&lt;/code&gt; plus a hash of the worktree path. Resource names follow the same pattern. Collisions go away.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;node_modules sprawl becomes provider plugin sprawl, mostly already solved.&lt;/strong&gt; Three worktrees each pulling their own copy of &lt;code&gt;pulumi-aws&lt;/code&gt; would add up fast, except &lt;a href="https://www.pulumi.com/docs/iac/concepts/plugins/"&gt;Pulumi already shares plugins through a single cache&lt;/a&gt; at &lt;code&gt;~/.pulumi/plugins&lt;/code&gt;. Identical provider versions are reused across worktrees automatically. Per-worktree language SDKs (&lt;code&gt;node_modules&lt;/code&gt;, &lt;code&gt;venv&lt;/code&gt;) still need the usual care, but the provider layer is free.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Database conflicts become state conflicts.&lt;/strong&gt; Two agents racing each other into &lt;code&gt;pulumi up&lt;/code&gt; on the same stack is the same hazard as two agents writing to the same migrated database. The app-code playbook reaches for Neon branches or per-worktree SQLite files to isolate state. The infra answer is simpler: each worktree gets its own &lt;a href="https://www.pulumi.com/docs/deployments/deployments/review-stacks/"&gt;review stack&lt;/a&gt;. State branches with the work, by construction.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Token blowouts become cloud spend per ephemeral stack.&lt;/strong&gt; The cost vector flips. For app code, the worry is LLM bills. For infrastructure, the worry is what your five agents just spun up in five review stacks. The mitigations are boring and they work. Use &lt;a href="https://www.pulumi.com/docs/deployments/deployments/ttl/"&gt;TTL stacks&lt;/a&gt; to tear review stacks down on a schedule. Avoid &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/options/retainondelete/"&gt;&lt;code&gt;retainOnDelete&lt;/code&gt;&lt;/a&gt; on review-stack resources so the teardown actually frees them. Cap retries per spec. Watch the bill.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PR pile-up is the same problem.&lt;/strong&gt; Five reviewed diffs are still five things waiting on the merge queue. The infra-flavored mitigations: stack-scoped reviewers (the human who owns the stack approves the change to it), the &lt;a href="https://www.pulumi.com/docs/administration/security-compliance/audit-logs/"&gt;Pulumi Cloud audit log&lt;/a&gt; for grouping by stack and time, and auto-merge for the narrow class of changes where the preview diff is clean and every policy passes. That last one is where most of the throughput hides.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Run any agent on your stacks&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Pulumi hands every coding agent a deterministic preview, isolated stacks, and policy as code to work against, whether that agent is Claude Code, Cursor, or Pulumi Neo.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/docs/ai/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="where-to-start-this-afternoon"&gt;Where to start, this afternoon&lt;/h2&gt;
&lt;p&gt;Three steps, in order, on a stack with a small blast radius.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Write an &lt;code&gt;AGENTS.md&lt;/code&gt; for the repo.&lt;/strong&gt; Five paragraphs is enough. The component library, the stack naming convention, the policy rules, the review-stack TTL, and the one thing in this repo that bites every newcomer. &lt;a href="https://www.pulumi.com/blog/pulumi-neo-now-supports-agentsmd/"&gt;Neo reads &lt;code&gt;AGENTS.md&lt;/code&gt; natively&lt;/a&gt;, as do most coding agents. This file is the spec for how the agent should behave even before you write a spec for what it should build.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cut a 24-hour review-stack TTL.&lt;/strong&gt; Spin up a review stack on PR open, tear it down on PR close or after 24 hours, whichever comes first. This is the gate that turns &amp;ldquo;ephemeral&amp;rdquo; from a slogan into a line item that does not appear on next month&amp;rsquo;s bill.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Run three issues in parallel.&lt;/strong&gt; Pick three open issues that touch unrelated resources. Spin up three worktrees, three review stacks, three ESC environments. Let each agent run end-to-end against its own stack. Then have a fourth agent read each preview JSON cold and produce a one-paragraph review. Read three PRs plus the reviewer&amp;rsquo;s summary at lunch.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That last step is the measurement. The first time you run it, half of the changes will fail validation. The second time, fewer. By the third time you will know whether your spec quality, your policies, and your stack hygiene are good enough to scale this to five, then ten, then to every issue tagged &lt;code&gt;infra:fix&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If three issues finish cleanly, you have the substrate. If they do not, the gap is almost always in the spec or the policy rules, not the agent. Fix the spec, tighten the rule, run it again.&lt;/p&gt;
&lt;h2 id="five-stacks-before-lunch"&gt;Five stacks before lunch&lt;/h2&gt;
&lt;p&gt;10x is five concurrent agents, working from five issues, against five stacks, behind five fresh-session reviews. The substrate is already there. Stacks isolate state. ESC isolates credentials. &lt;code&gt;pulumi preview&lt;/code&gt; is the deterministic artifact a fresh reviewer can read cold. Pulumi Policies is the self-healing layer when you write the rule messages as instructions.&lt;/p&gt;
&lt;p&gt;The remaining work is small and mostly wiring. Write the &lt;code&gt;AGENTS.md&lt;/code&gt;. Cut the TTL. Pick three issues that touch unrelated resources. Read three PRs at lunch. Five stacks before the room empties out is a realistic Monday.&lt;/p&gt;
&lt;a
href="https://www.pulumi.com/product/neo/"
class="btn btn-primary"
&gt;
See how Pulumi Neo runs your stacks
&lt;/a&gt;</description><author>Engin Diri</author><category>ai</category><category>ai-agents</category><category>automation</category><category>infrastructure-as-code</category><category>pulumi-neo</category><category>platform-engineering</category></item><item><title>Best AI Infrastructure Tools in 2026</title><link>https://www.pulumi.com/blog/ai-infrastructure-tools/</link><pubDate>Mon, 25 May 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/ai-infrastructure-tools/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/ai-infrastructure-tools/index.png" /&gt;
&lt;p&gt;&amp;ldquo;AI infrastructure tools&amp;rdquo; covers two distinct markets: infrastructure &lt;em&gt;for&lt;/em&gt; AI (GPU clouds like CoreWeave, MLOps platforms like Weights &amp;amp; Biases) and AI &lt;em&gt;for&lt;/em&gt; infrastructure (agentic platforms like Pulumi Neo that generate, deploy, and govern cloud resources for you). Most teams need tools from both categories, and picking the wrong one wastes budget and adoption goodwill.&lt;/p&gt;
&lt;p&gt;The pressure to get this right is real. &lt;a href="https://www.mckinsey.com/capabilities/mckinsey-digital/our-insights/the-economic-potential-of-generative-ai-the-next-productivity-frontier"&gt;McKinsey research&lt;/a&gt; puts the productivity lift from generative AI in software development at 20–45%, which is great for application teams and a problem for platform teams trying to keep up with the resulting feature flow. Infrastructure investment is climbing on both fronts: more spend on the compute that trains and serves models, more spend on AI tools that manage everything else.&lt;/p&gt;
&lt;p&gt;This guide covers both categories: the compute and MLOps stack in Part 1, and AI-powered infrastructure management in Part 2, where the more interesting product shift is happening.&lt;/p&gt;
&lt;h2 id="ai-infrastructure-tools-overview"&gt;AI infrastructure tools overview&lt;/h2&gt;
&lt;h3 id="tools-for-building-ai-infrastructure"&gt;Tools for building AI infrastructure&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#coreweave"&gt;CoreWeave&lt;/a&gt;: GPU cloud built for AI workloads&lt;/li&gt;
&lt;li&gt;&lt;a href="#lambda-labs"&gt;Lambda Labs&lt;/a&gt;: straightforward GPU cloud for research and startups&lt;/li&gt;
&lt;li&gt;&lt;a href="#modal"&gt;Modal&lt;/a&gt;: serverless GPU compute&lt;/li&gt;
&lt;li&gt;&lt;a href="#weights--biases"&gt;Weights &amp;amp; Biases&lt;/a&gt;: ML experiment tracking and model management&lt;/li&gt;
&lt;li&gt;&lt;a href="#mlflow"&gt;MLflow&lt;/a&gt;: open-source ML lifecycle platform&lt;/li&gt;
&lt;li&gt;&lt;a href="#hyperscaler-ai-platforms"&gt;Hyperscaler AI platforms&lt;/a&gt;: AWS SageMaker, Google Vertex AI, Azure ML&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="ai-powered-infrastructure-management-tools"&gt;AI-powered infrastructure management tools&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#pulumi-neo"&gt;Pulumi Neo&lt;/a&gt;: agentic AI with policy automation&lt;/li&gt;
&lt;li&gt;&lt;a href="#firefly-aiac"&gt;Firefly AIaC&lt;/a&gt;: asset codification and IaC generation&lt;/li&gt;
&lt;li&gt;&lt;a href="#env0-cloud-compass"&gt;env0 Cloud Compass&lt;/a&gt;: multi-IaC insights and analysis&lt;/li&gt;
&lt;li&gt;&lt;a href="#spacelift-ai"&gt;Spacelift AI&lt;/a&gt;: run explanation and troubleshooting&lt;/li&gt;
&lt;li&gt;&lt;a href="#crossplane-with-upbound"&gt;Crossplane with Upbound&lt;/a&gt;: Kubernetes-native infrastructure&lt;/li&gt;
&lt;li&gt;&lt;a href="#general-purpose-code-assistants"&gt;General-purpose code assistants&lt;/a&gt;: Copilot, Claude Code, Cursor, Gemini&lt;/li&gt;
&lt;li&gt;&lt;a href="#aws-application-composer"&gt;AWS Application Composer&lt;/a&gt;: visual serverless builder&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="quick-picks"&gt;Quick picks&lt;/h2&gt;
&lt;p&gt;If you only have two minutes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enterprise compliance&lt;/strong&gt;: &lt;a href="#pulumi-neo"&gt;Pulumi Neo&lt;/a&gt;. Executes changes (not only suggestions), ships with policy packs for CIS, HITRUST, NIST, and PCI DSS, and works with Terraform, CloudFormation, and resources created by hand.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Serious GPU compute&lt;/strong&gt;: &lt;a href="#coreweave"&gt;CoreWeave&lt;/a&gt;. Purpose-built for AI workloads, deep NVIDIA partnership, and prices that generally undercut the hyperscalers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best developer experience for ML&lt;/strong&gt;: &lt;a href="#modal"&gt;Modal&lt;/a&gt;. Decorate a Python function, get a GPU, pay by the second.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open-source MLOps&lt;/strong&gt;: &lt;a href="#mlflow"&gt;MLflow&lt;/a&gt;. No vendor lock-in, runs anywhere, plays well with everything.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-is-ai-infrastructure"&gt;What is AI infrastructure?&lt;/h2&gt;
&lt;p&gt;The term covers two distinct categories that share almost no vendors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Infrastructure for AI&lt;/strong&gt; is the compute, storage, and orchestration that AI workloads run on. Training a large model is not a normal cloud workload: it wants thousands of GPUs talking to each other over fat, low-latency networks for weeks at a time. Inference is different again: lower latency, smarter batching, different hardware. General-purpose cloud was not designed for either case, which is why specialized GPU clouds and MLOps platforms exist.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI-powered infrastructure management&lt;/strong&gt; is the inverse: AI tools that manage cloud infrastructure. They generate &lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;infrastructure as code&lt;/a&gt;, run deployments, detect drift, and remediate policy violations. The pitch is that modern infrastructure (multi-cloud, containers, microservices, regulated workloads) has gotten too complex for humans to manage by hand and too varied for scripted automation to keep up with.&lt;/p&gt;
&lt;p&gt;Most organizations end up needing both: somewhere to run their ML workloads, and something to keep the rest of the cloud sane.&lt;/p&gt;
&lt;h2 id="part-1-tools-for-building-ai-infrastructure"&gt;Part 1: Tools for building AI infrastructure&lt;/h2&gt;
&lt;p&gt;These are the platforms you run AI and ML workloads on: GPU clouds for raw compute, MLOps platforms for the lifecycle around them.&lt;/p&gt;
&lt;h3 id="coreweave"&gt;CoreWeave&lt;/h3&gt;
&lt;p&gt;CoreWeave is the GPU cloud that broke out of the AI hype cycle into a real public company. They went public in 2025, signed a multi-billion-dollar capacity deal with OpenAI, and acquired Weights &amp;amp; Biases. Their thesis from day one was that AI workloads deserve infrastructure designed for AI workloads, not a GPU SKU bolted onto a general-purpose cloud.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Proprietary&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Large-scale training and high-throughput inference; teams that need dedicated GPU capacity with first access to new NVIDIA hardware&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strengths&lt;/strong&gt;: GPU infrastructure designed for AI; Kubernetes-native; direct NVIDIA partnership; handles distributed training at scale&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watch out for&lt;/strong&gt;: Smaller global footprint than AWS/GCP/Azure; not a general-purpose cloud, so if you need RDS, S3, and a managed Kafka in the same provider, this isn&amp;rsquo;t it&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="lambda-labs"&gt;Lambda Labs&lt;/h3&gt;
&lt;p&gt;Lambda has been the approachable GPU cloud for a long time. Environments come pre-configured with PyTorch and TensorFlow, and you can be running on an H100 in about as long as it takes to copy your SSH key.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Proprietary&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Research teams, startups, and individual practitioners who want GPUs without a configuration tax&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strengths&lt;/strong&gt;: Straightforward to start on; pre-configured deep learning environments; competitive on-demand pricing; strong learning resources&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watch out for&lt;/strong&gt;: Smaller scale than CoreWeave or the hyperscalers; availability gets tight during demand spikes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="modal"&gt;Modal&lt;/h3&gt;
&lt;p&gt;Modal&amp;rsquo;s pitch is that you write a Python function, decorate it, and Modal handles the GPU. No capacity planning, no idle instances burning money overnight, no Dockerfile to maintain.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Proprietary&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Variable ML workloads where reserved capacity would sit idle; data scientists who&amp;rsquo;d rather not learn Kubernetes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strengths&lt;/strong&gt;: Strong developer experience; serverless GPUs with automatic scaling; pay-per-second pricing; cold starts are fast for what they are&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watch out for&lt;/strong&gt;: You give up infrastructure control. Not ideal for long training jobs that need reserved hardware or strict configuration requirements.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="weights--biases"&gt;Weights &amp;amp; Biases&lt;/h3&gt;
&lt;p&gt;Weights &amp;amp; Biases is the de facto standard for ML experiment tracking and model management, integrated with essentially every framework and cloud you&amp;rsquo;d plausibly use. CoreWeave acquired the company in 2025, which has accelerated the joint roadmap but raised some neutrality questions for teams that prefer their tooling cloud-agnostic.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Proprietary with a free tier&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: ML teams that need shared experiment tracking, model versioning, and reporting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strengths&lt;/strong&gt;: Industry-leading experiment tracking and visualization; comprehensive model registry; strong team collaboration; broad integration surface&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watch out for&lt;/strong&gt;: Costs scale quickly past the free tier; some teams self-host alternatives for data residency reasons&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mlflow"&gt;MLflow&lt;/h3&gt;
&lt;p&gt;MLflow is the leading open-source MLOps platform: experiment tracking, packaging, registry, and serving, with no lock-in. Originally built at Databricks, it&amp;rsquo;s now a broad open-source ecosystem with managed offerings from multiple vendors (including Databricks and the major clouds).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Apache 2.0&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Teams that want MLOps without a vendor; or want the option to start managed and self-host later&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strengths&lt;/strong&gt;: Open source; covers the full ML lifecycle; runs locally, on-prem, or managed; broad framework support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watch out for&lt;/strong&gt;: Self-hosting carries the usual operational tax; commercial alternatives have stronger collaboration UX out of the box&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="hyperscaler-ai-platforms"&gt;Hyperscaler AI platforms&lt;/h3&gt;
&lt;p&gt;The major clouds all sell end-to-end ML platforms. Each leads on the dimensions that line up with its parent cloud (Vertex for Google&amp;rsquo;s models and TPUs, SageMaker for AWS-native data pipelines, Azure ML for Microsoft-stack integration), but the wider integration with the rest of the cloud is the deciding factor.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AWS SageMaker&lt;/strong&gt;: end-to-end ML on AWS, deeply integrated with S3 and Glue, with first-class connections to Lambda for serverless inference and to the rest of the AWS data stack. The default pick if your data already lives in AWS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google Vertex AI&lt;/strong&gt;: Google&amp;rsquo;s ML stack, including TPUs for workloads that need them, plus access to Google&amp;rsquo;s foundation models. Strongest when paired with BigQuery.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure Machine Learning&lt;/strong&gt;: the natural choice when the rest of your stack is Microsoft; first-party MLOps integrations across GitHub Actions, Azure DevOps, and Microsoft Fabric for downstream reporting. The right choice if you&amp;rsquo;re already an Azure shop with Microsoft compliance requirements.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The shared tradeoff: hyperscaler GPU compute typically runs 2–3x the per-hour price of specialized providers, and the platforms work best when you commit to them top to bottom. For organizations already inside one cloud, the unified billing and single support contract usually justifies the premium. For a new ML team starting from scratch, it rarely does.&lt;/p&gt;
&lt;h2 id="part-2-ai-powered-infrastructure-management-tools"&gt;Part 2: AI-powered infrastructure management tools&lt;/h2&gt;
&lt;p&gt;This is where the more interesting product shift is happening. Instead of running AI on infrastructure, these tools point AI at your infrastructure and let it do work. They&amp;rsquo;re a newer, AI-native layer on top of the broader &lt;a href="https://www.pulumi.com/blog/infrastructure-as-code-tools/"&gt;infrastructure as code tooling landscape&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="from-code-generation-to-agentic-execution"&gt;From code generation to agentic execution&lt;/h3&gt;
&lt;p&gt;Before the tool list, one distinction matters more than any feature comparison: whether the tool generates code or executes changes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code generation tools&lt;/strong&gt; like GitHub Copilot suggest infrastructure code based on context. You review it, maybe edit it, run it yourself. The AI helps, but you&amp;rsquo;re still the one doing the work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agentic platforms&lt;/strong&gt; generate the code and run it, with the guardrails you define. They understand your environment, handle multi-step workflows, and enforce policies on the way through. You describe the outcome; the platform makes it happen.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Code generation&lt;/th&gt;
&lt;th&gt;Agentic execution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Generates infrastructure code&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Understands infrastructure context&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Deep&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Executes changes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Handles multi-step workflows&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enforces policies automatically&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remediates drift and violations&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Where you want to land on this spectrum is mostly a governance question, not a productivity one.&lt;/p&gt;
&lt;h3 id="pulumi-neo"&gt;Pulumi Neo&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt; is Pulumi&amp;rsquo;s agentic AI for infrastructure. The distinguishing claim is execution: Neo doesn&amp;rsquo;t only suggest a Terraform snippet, it figures out the right resources, generates the code, and runs the deployment inside whatever guardrails you&amp;rsquo;ve set.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Proprietary (Pulumi Cloud)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Platform engineering teams that want AI automation with real policy controls, especially in regulated industries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A few things that set it apart in practice:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Policy automation and compliance.&lt;/strong&gt; Neo is integrated with &lt;a href="https://www.pulumi.com/product/insights-governance/"&gt;Pulumi Insights and Governance&lt;/a&gt;, which ships pre-built policy packs for CIS benchmarks, HITRUST CSF, NIST SP 800-53, and PCI DSS. Detection and remediation run in the same loop: Neo finds a violation, generates a fix, and (subject to approvals) applies it. You can batch-remediate across stacks and accounts with prompts like &amp;ldquo;find and fix all unencrypted S3 buckets across our AWS accounts.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Works with infrastructure you didn&amp;rsquo;t create with Pulumi.&lt;/strong&gt; Neo&amp;rsquo;s governance applies to Pulumi-managed resources, Terraform state, CloudFormation stacks, and resources someone clicked together in the AWS console. That matters because the realistic adoption path is to point Neo at what you have, audit it, and gradually bring it under management, not to migrate everything first.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Progressive autonomy.&lt;/strong&gt; Trust levels are configurable. Start with human approval for everything; loosen it for well-defined, low-risk operations as confidence builds; keep production and sensitive resources behind strict approvals. This is the part that tends to determine whether enterprises actually deploy agentic AI in anger, versus letting it sit as a sandbox toy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IDE and CI/CD integration.&lt;/strong&gt; The Pulumi MCP Server brings Neo into Cursor, Claude Code, Claude Desktop, Windsurf, and any other MCP-compatible client. The Pulumi Cloud UI is the home base for approvals, history, and remediation status. Neo also slots into CI/CD pipelines for pre-merge policy remediation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Case studies&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Werner Enterprises&lt;/strong&gt; reduced infrastructure provisioning time from 3 days to 4 hours using Pulumi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spear AI&lt;/strong&gt; cut their Authority to Operate (ATO) timeline from an expected 1.5 years to roughly 3 months by using policy-as-code to evidence compliance controls for auditors.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Tradeoff to be honest about&lt;/strong&gt;: Neo gets more valuable the deeper you are in the Pulumi ecosystem. If you&amp;rsquo;re running IaC, ESC, and policy packs already, Neo has a lot of context to draw on. If you&amp;rsquo;re kicking the tires, it&amp;rsquo;s still useful, but the differentiating capability (context-aware, policy-respecting agentic execution) is harder to feel.&lt;/p&gt;
&lt;h3 id="firefly-aiac"&gt;Firefly AIaC&lt;/h3&gt;
&lt;p&gt;Firefly is an asset management platform with AI features bolted on top of a strong core. The core capability is asset codification: it discovers cloud resources you already have and generates the IaC for them.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Proprietary&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Teams that need to codify existing cloud footprints or generate IaC from natural language&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Strengths: solid asset discovery, multi-cloud coverage, natural-language IaC generation, drift detection with remediation hooks. Caveat: AI features here are supplementary to the asset management product, not the main event, and Firefly is less focused on agentic execution than on inventory and policy.&lt;/p&gt;
&lt;h3 id="env0-cloud-compass"&gt;env0 Cloud Compass&lt;/h3&gt;
&lt;p&gt;env0&amp;rsquo;s Cloud Compass adds AI to env0&amp;rsquo;s IaC automation platform, focusing on analysis rather than autonomous execution.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Proprietary&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Multi-IaC shops that want AI-generated PR summaries, drift explanations, and cost insights&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Strengths: multi-tool support across Terraform, OpenTofu, Pulumi, and Terragrunt; AI-generated PR summaries; drift cause analysis; cost estimation. Caveat: this is analysis and explanation, not action: Cloud Compass complements an agentic tool rather than replacing one.&lt;/p&gt;
&lt;h3 id="spacelift-ai"&gt;Spacelift AI&lt;/h3&gt;
&lt;p&gt;Spacelift&amp;rsquo;s AI work is focused on the post-run experience: explaining what happened in a deployment and helping troubleshoot failures.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Proprietary&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: GitOps shops that want AI assistance reading complex runs and diagnosing failed deployments&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Strengths: AI-powered run explanation; troubleshooting guidance for failures; broad IaC tool support; mature CI/CD integration. Caveat: like Spacelift as a whole, this is observation and explanation, not generation or execution. Pair with something that writes the code.&lt;/p&gt;
&lt;h3 id="crossplane-with-upbound"&gt;Crossplane with Upbound&lt;/h3&gt;
&lt;p&gt;Crossplane brings Kubernetes-style declarative management to cloud resources. Upbound is the company that commercializes it, and is layering AI-native control-plane capabilities into the 2.0 generation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Apache 2.0 (Crossplane); proprietary (Upbound)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Teams already deep in Kubernetes that want to manage cloud resources the same way&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Strengths: Kubernetes-native model; native GitOps fit; very active OSS community; AI control-plane work emerging from Upbound. Caveat: the learning curve is real if you&amp;rsquo;re not already living in Kubernetes; the commercial AI features are still maturing.&lt;/p&gt;
&lt;h3 id="general-purpose-code-assistants"&gt;General-purpose code assistants&lt;/h3&gt;
&lt;p&gt;General-purpose AI coding assistants are the tools your developers already have open: GitHub Copilot, Claude Code, Cursor, and Google&amp;rsquo;s Gemini and Antigravity. They write Terraform HCL, Pulumi programs, and CloudFormation templates competently, about as well as they write anything else.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Proprietary (subscription), varies by tool&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Developers who want broad code assistance, including infrastructure code, inside their existing editor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Strengths: excellent line-by-line code completion; broad language support; first-class editor integration; trained on huge corpora. Caveat: no infrastructure context. They don&amp;rsquo;t know what&amp;rsquo;s in your account, what your policies are, or which subnet you should pick. Treat their IaC suggestions as first-pass scaffolding, not production output.&lt;/p&gt;
&lt;h3 id="aws-application-composer"&gt;AWS Application Composer&lt;/h3&gt;
&lt;p&gt;Application Composer is AWS&amp;rsquo;s visual builder for serverless applications. Drag services onto a canvas, get a CloudFormation template out, with AI suggestions for service configuration along the way.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;License&lt;/strong&gt;: Proprietary (AWS, included)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Teams building AWS serverless apps who prefer a visual workflow&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Strengths: visual development for serverless; direct AWS integration; AI suggestions for service configuration; emits CloudFormation. Caveat: AWS-only, CloudFormation-only, and best suited to serverless rather than general infrastructure.&lt;/p&gt;
&lt;h2 id="comparison-tables"&gt;Comparison tables&lt;/h2&gt;
&lt;h3 id="infrastructure-for-ai"&gt;Infrastructure for AI&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Key strength&lt;/th&gt;
&lt;th&gt;Limitation&lt;/th&gt;
&lt;th&gt;Pricing&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CoreWeave&lt;/td&gt;
&lt;td&gt;GPU cloud&lt;/td&gt;
&lt;td&gt;Purpose-built GPU infra, NVIDIA partnership&lt;/td&gt;
&lt;td&gt;Not a general-purpose cloud&lt;/td&gt;
&lt;td&gt;Per-GPU-hour&lt;/td&gt;
&lt;td&gt;Large-scale AI training&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda Labs&lt;/td&gt;
&lt;td&gt;GPU cloud&lt;/td&gt;
&lt;td&gt;Approachable, pre-configured environments&lt;/td&gt;
&lt;td&gt;Smaller scale&lt;/td&gt;
&lt;td&gt;Per-GPU-hour&lt;/td&gt;
&lt;td&gt;Research teams, startups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modal&lt;/td&gt;
&lt;td&gt;Serverless GPU&lt;/td&gt;
&lt;td&gt;Developer experience, pay-per-second&lt;/td&gt;
&lt;td&gt;Less infrastructure control&lt;/td&gt;
&lt;td&gt;Pay-per-use&lt;/td&gt;
&lt;td&gt;Variable ML workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weights &amp;amp; Biases&lt;/td&gt;
&lt;td&gt;MLOps&lt;/td&gt;
&lt;td&gt;Industry-standard experiment tracking&lt;/td&gt;
&lt;td&gt;Costs scale quickly&lt;/td&gt;
&lt;td&gt;Free tier + paid&lt;/td&gt;
&lt;td&gt;ML team collaboration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MLflow&lt;/td&gt;
&lt;td&gt;MLOps&lt;/td&gt;
&lt;td&gt;Open source, no lock-in&lt;/td&gt;
&lt;td&gt;Self-hosting overhead&lt;/td&gt;
&lt;td&gt;Free (self-hosted)&lt;/td&gt;
&lt;td&gt;Flexible ML lifecycle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS SageMaker&lt;/td&gt;
&lt;td&gt;Hyperscaler&lt;/td&gt;
&lt;td&gt;AWS ecosystem integration&lt;/td&gt;
&lt;td&gt;Higher cost, lock-in&lt;/td&gt;
&lt;td&gt;Per-use&lt;/td&gt;
&lt;td&gt;AWS-native orgs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Vertex AI&lt;/td&gt;
&lt;td&gt;Hyperscaler&lt;/td&gt;
&lt;td&gt;Google models, TPU access&lt;/td&gt;
&lt;td&gt;Lock-in&lt;/td&gt;
&lt;td&gt;Per-use&lt;/td&gt;
&lt;td&gt;Google Cloud users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure ML&lt;/td&gt;
&lt;td&gt;Hyperscaler&lt;/td&gt;
&lt;td&gt;Microsoft integration, enterprise features&lt;/td&gt;
&lt;td&gt;Lock-in&lt;/td&gt;
&lt;td&gt;Per-use&lt;/td&gt;
&lt;td&gt;Microsoft ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="ai-powered-infrastructure-management"&gt;AI-powered infrastructure management&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Key strength&lt;/th&gt;
&lt;th&gt;Limitation&lt;/th&gt;
&lt;th&gt;Pricing&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pulumi Neo&lt;/td&gt;
&lt;td&gt;Agentic AI&lt;/td&gt;
&lt;td&gt;Execution + policy automation&lt;/td&gt;
&lt;td&gt;Best within Pulumi ecosystem&lt;/td&gt;
&lt;td&gt;Pulumi Cloud tiers&lt;/td&gt;
&lt;td&gt;Enterprise platform teams&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firefly AIaC&lt;/td&gt;
&lt;td&gt;Asset management&lt;/td&gt;
&lt;td&gt;Asset codification, IaC generation&lt;/td&gt;
&lt;td&gt;AI is supplementary&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;Codifying existing infra&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;env0 Cloud Compass&lt;/td&gt;
&lt;td&gt;Multi-IaC platform&lt;/td&gt;
&lt;td&gt;Multi-tool support, PR analysis&lt;/td&gt;
&lt;td&gt;Analysis, not execution&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;Multi-IaC environments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spacelift AI&lt;/td&gt;
&lt;td&gt;CI/CD platform&lt;/td&gt;
&lt;td&gt;Run explanation, troubleshooting&lt;/td&gt;
&lt;td&gt;Observation, not action&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;GitOps workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crossplane / Upbound&lt;/td&gt;
&lt;td&gt;Kubernetes-native&lt;/td&gt;
&lt;td&gt;K8s patterns for infra&lt;/td&gt;
&lt;td&gt;Requires K8s expertise&lt;/td&gt;
&lt;td&gt;Open source + commercial&lt;/td&gt;
&lt;td&gt;Kubernetes-native teams&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code assistants&lt;/td&gt;
&lt;td&gt;Code assistant&lt;/td&gt;
&lt;td&gt;Broad language support, IDE&lt;/td&gt;
&lt;td&gt;No infrastructure context&lt;/td&gt;
&lt;td&gt;Subscription&lt;/td&gt;
&lt;td&gt;General code assistance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Composer&lt;/td&gt;
&lt;td&gt;Visual builder&lt;/td&gt;
&lt;td&gt;Visual serverless development&lt;/td&gt;
&lt;td&gt;AWS- and CFN-only&lt;/td&gt;
&lt;td&gt;Included with AWS&lt;/td&gt;
&lt;td&gt;AWS serverless apps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;See agentic infrastructure in action&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Pulumi Neo generates, deploys, and governs cloud infrastructure across the resources you already have, with the policy guardrails you define.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/product/neo/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Explore Pulumi Neo
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="how-to-choose"&gt;How to choose&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s no universal best tool. Five questions sort the field quickly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cloud strategy.&lt;/strong&gt; Multi-cloud means tools like Pulumi Neo, Firefly, env0, or Crossplane. Single-cloud commitment means hyperscaler-native tools may integrate more deeply (AWS Composer, SageMaker, and so on).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Team expertise.&lt;/strong&gt; Programmers gravitate to tools that use real languages (Pulumi Neo, Pulumi IaC). Kubernetes teams find Crossplane natural; everyone else finds it steep. Teams that prefer visual workflows should look at AWS Composer or env0&amp;rsquo;s UI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compliance.&lt;/strong&gt; Regulated industries (healthcare, finance, government) get the most value from tools with pre-built compliance packs and audit trails. Pulumi Neo&amp;rsquo;s CIS/HITRUST/NIST/PCI packs are the most direct fit. If preventative policy enforcement matters, prefer tools that block non-compliant deployments rather than flag them after the fact.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Existing footprint.&lt;/strong&gt; Greenfield projects can use anything. Brownfield is where it gets interesting: Pulumi Neo works against Terraform, CloudFormation, and manually-created resources, which lets you adopt incrementally instead of migrating first. Mixed-IaC shops should also look at env0.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Budget.&lt;/strong&gt; Open source first: MLflow for MLOps, Crossplane for Kubernetes-native infra. Open source is not free, though: self-hosting carries a real total cost of ownership in hosting, maintenance, and the expertise to operate it. Commercial tools (Pulumi Cloud, env0, Spacelift) fold that operational cost into the price, on top of support, SLAs, and the enterprise-tier features open source can lack.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before adopting anything, get visibility into what you have today, pilot on staging where mistakes are cheap, and define success metrics up front: time to provision, policy violation rates, mean time to remediate. The best AI infrastructure tool is the one your team will actually use, which means meeting developers where they already work.&lt;/p&gt;
&lt;h2 id="key-trends-and-outlook"&gt;Key trends and outlook&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;From copilots to agents.&lt;/strong&gt; &amp;ldquo;AI suggests code&amp;rdquo; and &amp;ldquo;AI runs the deploy&amp;rdquo; are different products with different governance implications. The teams getting value from agentic tools have figured out which tasks to delegate fully, which to keep human-in-the-loop, and which to leave alone.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Progressive autonomy.&lt;/strong&gt; Enterprise adoption follows a predictable shape: visibility → recommendations → human-approved execution → autonomous execution for well-understood scenarios. Tools that support that graduation will see stronger enterprise traction than tools that force an all-or-nothing choice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Policy as the control plane.&lt;/strong&gt; As AI takes on more infrastructure tasks, policy frameworks become the primary control plane. Done well, policy becomes an enabler (guardrails that let you safely expand automation) rather than a brake on velocity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MCP standardization.&lt;/strong&gt; The Model Context Protocol is becoming the integration standard between AI assistants and infrastructure tools. The practical upshot is that the IDE is increasingly a viable surface for managing infrastructure, with AI mediating between natural language and the underlying APIs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Consolidation.&lt;/strong&gt; CoreWeave acquiring Weights &amp;amp; Biases and NVIDIA acquiring Run:ai both point toward integrated platforms across the AI infrastructure stack. For tool selection today, that&amp;rsquo;s an argument for picking vendors with clear strategic direction over point solutions likely to be acquired or out-competed.&lt;/p&gt;
&lt;h2 id="frequently-asked-questions"&gt;Frequently asked questions&lt;/h2&gt;
&lt;h3 id="what-is-the-best-ai-agent-for-cloud-infrastructure-management"&gt;What is the best AI agent for cloud infrastructure management?&lt;/h3&gt;
&lt;p&gt;For enterprise governance plus true agentic capability, &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt; is currently the most complete offering: it executes changes (not just suggests them), integrates with pre-built compliance frameworks, and works with infrastructure regardless of how it was provisioned. For Kubernetes-native shops, Crossplane with Upbound&amp;rsquo;s emerging AI features is worth tracking.&lt;/p&gt;
&lt;h3 id="how-can-i-use-generative-ai-to-manage-cloud-infrastructure"&gt;How can I use generative AI to manage cloud infrastructure?&lt;/h3&gt;
&lt;p&gt;Start by identifying the repetitive, time-consuming infrastructure work in your team. The highest-value early use cases tend to be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Code generation&lt;/strong&gt;: write IaC from natural-language descriptions, then review.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: explain unfamiliar configurations and reduce onboarding time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;: analyze logs, errors, and configs to suggest likely causes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security and compliance&lt;/strong&gt;: scan for violations and generate fixes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full automation&lt;/strong&gt;: for shops that want it, agentic platforms like Pulumi Neo execute provisioning workflows end-to-end with governance controls intact.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="what-is-agentic-ai-for-infrastructure"&gt;What is agentic AI for infrastructure?&lt;/h3&gt;
&lt;p&gt;Agentic AI for infrastructure means AI systems that autonomously execute infrastructure tasks, not just generate code suggestions. The difference from a code assistant is action: an agent understands your environment, respects your policies, and performs multi-step work (provisioning, configuration, security controls) within the boundaries you&amp;rsquo;ve defined.&lt;/p&gt;
&lt;h3 id="how-do-ai-agents-improve-devops-workflows"&gt;How do AI agents improve DevOps workflows?&lt;/h3&gt;
&lt;p&gt;By automating the repetitive parts (provisioning, drift remediation, policy enforcement), reducing context-switching, and catching issues earlier. Teams that have rolled out agentic tools well report faster provisioning, fewer policy violations slipping into production, and quicker compliance remediation. The compounding effect (engineers freed for higher-value work as the agent absorbs the routine) is the actual point.&lt;/p&gt;
&lt;h3 id="whats-the-difference-between-ai-code-generation-and-agentic-execution"&gt;What&amp;rsquo;s the difference between AI code generation and agentic execution?&lt;/h3&gt;
&lt;p&gt;Code generation suggests IaC for a human to review and run. Agentic execution generates the code and runs it, with policy and governance enforced along the way. It&amp;rsquo;s the difference between a knowledgeable colleague who suggests an approach and a knowledgeable colleague who also ships the change with appropriate oversight.&lt;/p&gt;
&lt;h3 id="can-ai-generate-terraform-or-pulumi-programs"&gt;Can AI generate Terraform or Pulumi programs?&lt;/h3&gt;
&lt;p&gt;Yes. Most general-purpose AI assistants (Copilot, Claude, Gemini, ChatGPT, Cursor) can produce Terraform HCL, Pulumi programs in TypeScript / Python / Go, and CloudFormation. Quality varies. Generic assistants lack environment context and will happily emit syntactically correct but operationally wrong code. Infrastructure-specific tools like Pulumi Neo generate code that&amp;rsquo;s aware of your existing resources, policies, and provider constraints.&lt;/p&gt;
&lt;h3 id="can-ai-help-with-infrastructure-compliance-and-policy-automation"&gt;Can AI help with infrastructure compliance and policy automation?&lt;/h3&gt;
&lt;p&gt;Yes, and this is one of the highest-leverage uses of AI in infrastructure. Tools like Pulumi Neo detect policy violations across your footprint (including resources created outside IaC), generate compliant remediation, and apply it with the approvals you require. Pre-built frameworks for CIS, HITRUST, NIST, and PCI DSS shorten what would otherwise be a long manual compliance project.&lt;/p&gt;
&lt;h3 id="are-ai-infrastructure-tools-secure-for-enterprise-use"&gt;Are AI infrastructure tools secure for enterprise use?&lt;/h3&gt;
&lt;p&gt;Enterprise-grade ones are. Look for RBAC, full audit logging of AI actions, preventative policy enforcement (not just detection), and human-in-the-loop approvals for sensitive operations. SOC 2, data residency options, and configurable autonomy levels are table stakes. The risk to avoid is wiring a consumer AI assistant directly into a production cloud account without those controls.&lt;/p&gt;
&lt;h3 id="how-do-i-choose-between-different-ai-infrastructure-tools"&gt;How do I choose between different AI infrastructure tools?&lt;/h3&gt;
&lt;p&gt;Match the tool to your context: existing clouds and IaC, team skills, compliance requirements, budget. Enterprise platform teams with governance needs should evaluate Pulumi Neo first. MLOps-focused teams should look at Weights &amp;amp; Biases or MLflow. For general code assistance inside the editor, a general-purpose assistant like Copilot, Cursor, or Gemini is the default. Most organizations end up with more than one: a code assistant for daily development and an agentic platform for production infrastructure.&lt;/p&gt;
&lt;h3 id="what-are-the-best-tools-for-machine-learning-infrastructure"&gt;What are the best tools for machine learning infrastructure?&lt;/h3&gt;
&lt;p&gt;For GPU compute, CoreWeave leads at scale, Modal wins for variable workloads and developer experience, and the hyperscalers are the default pick if you&amp;rsquo;re already inside one of them. For experiment tracking and model management, Weights &amp;amp; Biases is the leading commercial platform; MLflow is the leading open-source one. Most teams pick on the deploy model and pricing fit rather than capability gap. For the cloud infrastructure underneath the ML workloads, the same infrastructure management story applies: Pulumi Neo can provision and govern ML infrastructure the same way it handles everything else.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Two categories, two problems. GPU clouds and MLOps platforms (CoreWeave, Lambda, Modal, hyperscaler trio, W&amp;amp;B, MLflow) solve the compute and lifecycle problem for running AI workloads. AI-powered infrastructure tools (Neo, Firefly, env0, Spacelift, Crossplane, code assistants, Composer) solve the management problem for everything else.&lt;/p&gt;
&lt;p&gt;For GPU workloads, the choice mostly comes down to scale and where you already are. For infrastructure management, the real question is how much you actually want AI to do. Code assistants help you write IaC faster, but you&amp;rsquo;re still running it. Agentic platforms like Pulumi Neo execute changes and enforce policy on the way through, with the guardrails you control.&lt;/p&gt;
&lt;p&gt;The pattern from teams getting real value: treat AI as a force multiplier on routine work (provisioning, drift, compliance) and keep human judgment in the loop for the architecture and the edge cases.&lt;/p&gt;
&lt;p&gt;If you want to see agentic infrastructure management running against real resources, &lt;a href="https://www.pulumi.com/product/neo/"&gt;start with Pulumi Neo&lt;/a&gt;.&lt;/p&gt;</description><author>Alex Leventer</author><category>ai</category><category>infrastructure-as-code</category><category>platform-engineering</category><category>devops</category><category>announcements</category></item><item><title>Ten More Things You Can Do With Pulumi Neo</title><link>https://www.pulumi.com/blog/10-more-things-you-can-do-with-neo/</link><pubDate>Tue, 19 May 2026 05:00:00 -0700</pubDate><guid>https://www.pulumi.com/blog/10-more-things-you-can-do-with-neo/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/10-more-things-you-can-do-with-neo/index.png" /&gt;
&lt;p&gt;Last fall, after launching &lt;a href="https://www.pulumi.com/neo/"&gt;Pulumi Neo&lt;/a&gt;, we wrote up &lt;a href="https://www.pulumi.com/blog/10-things-you-can-do-with-neo/"&gt;10 things you could do with it&lt;/a&gt;. In the months that followed, as platform teams handed Neo more real work, we watched and listened, shipping a steady stream of features like &lt;a href="https://www.pulumi.com/blog/neo-plan-mode/"&gt;plan mode&lt;/a&gt;, &lt;a href="https://www.pulumi.com/blog/neo-read-only-mode/"&gt;read-only mode&lt;/a&gt;, &lt;a href="https://www.pulumi.com/blog/pulumi-neo-now-supports-agentsmd/"&gt;AGENTS.md&lt;/a&gt;, an &lt;a href="https://www.pulumi.com/blog/neo-integration-catalog/"&gt;integration catalog&lt;/a&gt;, &lt;a href="https://www.pulumi.com/blog/neo-migration/"&gt;cross-cloud migration&lt;/a&gt;, and &lt;a href="https://www.pulumi.com/blog/neo-task-sharing/"&gt;task sharing&lt;/a&gt;. With &lt;a href="https://www.pulumi.com/releases/agentic-infrastructure-era/"&gt;today&amp;rsquo;s release&lt;/a&gt;, Neo extends beyond the Pulumi Cloud console into the Pulumi CLI, GitHub, and Slack.&lt;/p&gt;
&lt;p&gt;So here are &lt;strong&gt;10 more&lt;/strong&gt; things you can do with Neo.&lt;/p&gt;
&lt;h2 id="1-deploy-your-app-to-aws-without-writing-iac"&gt;1. Deploy your app to AWS without writing IaC&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Hand Neo a repo. Neo picks the right services — ECS, AWS Fargate, ALB — writes the Pulumi, and opens a PR.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The cloud infrastructure part of getting a new service running, especially one in a new language, is always a few hours of boilerplate: a VPC and subnets, an IAM role, security groups, a load balancer, DNS, and a TLS cert.&lt;/p&gt;
&lt;p&gt;With Neo, that work collapses into a prompt. Point Neo at a repo and ask:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Deploy this app to AWS as a publicly accessible service.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/blog/neo-plan-mode/"&gt;Plan mode&lt;/a&gt; comes back with the resources Neo will create, named and sized: ECS running on AWS Fargate, an ALB, and the VPC wiring. Approve, and Neo writes the Pulumi program, runs a preview, and opens a PR. You, the human in the loop, merge it after review.&lt;/p&gt;
&lt;p&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded-lg w-full" title="Neo deploying an app to AWS: prompt, plan mode, PR, public URL"
autoplay muted playsinline
loop &gt;
&lt;source src="deploy-to-aws2.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;figcaption&gt;
&lt;center&gt;
&lt;i&gt;
Neo planning a PR and deploying an app to AWS.
&lt;/i&gt;
&lt;/center&gt;
&lt;/figcaption&gt;
&lt;/p&gt;
&lt;a href="https://app.pulumi.com/neo?prompt=I%27d&amp;#43;like&amp;#43;to&amp;#43;deploy&amp;#43;this&amp;#43;app&amp;#43;to&amp;#43;AWS.&amp;#43;Confirm&amp;#43;what&amp;#43;you%27ll&amp;#43;create." class="neo-card"&gt;
&lt;div class="neo-card-content"&gt;
&lt;div class="neo-card-icon"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular" fill="currentColor" role="img" aria-label="Pulumi Neo AI icon"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#c-pulumi-neo-regular"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;div class="neo-card-text"&gt;
&lt;span class="neo-card-subtitle"&gt;Start a Neo task&lt;/span&gt;
&lt;span class="neo-card-title"&gt;Ask Neo to deploy your app to AWS and make a PR&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="neo-card-arrow"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--bold" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-caret-right-bold"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;h2 id="2-diagnose-a-slow-api-from-metrics-logs-and-code"&gt;2. Diagnose a slow API from metrics, logs, and code&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Slow endpoints live at the seam between runtime metrics and the stack that runs them. Neo reads both and proposes a fix with the metric evidence as the rationale.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Production incidents often involve multiple tools. When the &lt;code&gt;checkout&lt;/code&gt; endpoint&amp;rsquo;s p95 latency climbs from 200ms to 1.2s, the metric is in Datadog, but the cause might be somewhere in your AWS account: maybe RDS is out of IOPS, maybe the connection pool is too small, maybe the autoscaler isn&amp;rsquo;t keeping up. Connecting &amp;ldquo;this metric looks bad&amp;rdquo; to a recent backend change and then to a one-line fix in your Pulumi program is an exercise in detective work.&lt;/p&gt;
&lt;p&gt;Neo&amp;rsquo;s &lt;a href="https://www.pulumi.com/blog/neo-integration-catalog/"&gt;integration catalog&lt;/a&gt; bridges this gap. With built-in Datadog APM, PagerDuty, and Honeycomb integrations sitting alongside your Pulumi state, Neo can read traces and metrics from the tools your team already uses and take action.&lt;/p&gt;
&lt;p&gt;Ask Neo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Find the scaling bottleneck on &lt;code&gt;/checkout&lt;/code&gt; from the last 7 days of metrics and propose a fix.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neo pulls the metric history, matches the Datadog tag &lt;code&gt;db.cluster=checkout-rds&lt;/code&gt; to the RDS instance in your &lt;code&gt;prod-checkout&lt;/code&gt; Pulumi stack, and opens a PR with a Pulumi diff that bumps the storage IOPS and raises the connection-pool ceiling. You review and roll out the fix.&lt;/p&gt;
&lt;p&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded-lg w-full" title="Enabling the Honeycomb integration in Neo"
autoplay muted playsinline
loop &gt;
&lt;source src="honey-comb.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;figcaption&gt;
&lt;center&gt;
&lt;i&gt;
Toggle on the Honeycomb integration so Neo can read traces and metrics alongside your Pulumi stacks.
&lt;/i&gt;
&lt;/center&gt;
&lt;/figcaption&gt;
&lt;/p&gt;
&lt;h2 id="3-automate-pagerduty-incident-response-from-slack"&gt;3. Automate PagerDuty incident response from Slack&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;A page comes in. You paste it into your on-call channel and tag Neo, and Neo replies with the cross-system view you&amp;rsquo;d otherwise spend the first 20 minutes assembling.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;On-call triage is often about getting up to speed quickly. You get paged because something is in the red, and you don&amp;rsquo;t know why.&lt;/p&gt;
&lt;p&gt;You mention Neo in the on-call Slack channel:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;@neo, what&amp;rsquo;s going on with this alert?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neo starts querying metrics and traces. With PagerDuty and Datadog in the integration catalog, it correlates the alert with every deploy and stack change tagged with the alert&amp;rsquo;s service in the last hour, and finds the change that lines up:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Two deploys in the last hour touched services tagged &lt;code&gt;service:checkout&lt;/code&gt;: &lt;code&gt;checkout-api@a3f9c2&lt;/code&gt; (12 min ago, app-layer deploy) and Pulumi stack &lt;code&gt;prod-checkout-rds&lt;/code&gt; (45 min ago, decreased &lt;code&gt;max_connections&lt;/code&gt; from 200 → 100). p99 latency inflection at 14:03 lines up with the stack change. Likely cause: the connection-pool reduction is starving the API under current load.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You ask a couple of clarifying questions in-thread, then ask Neo to open a rollback PR against the Pulumi stack.&lt;/p&gt;
&lt;p&gt;&lt;img src="neo-integration-catalog.png" alt="Neo Settings → Integrations page: six integrations available with Authorize buttons for Atlassian, Datadog, Honeycomb, Linear, PagerDuty, and Supabase"&gt;
&lt;figcaption&gt;
&lt;center&gt;
&lt;i&gt;
Authorize PagerDuty and Datadog in Neo's settings. Neo can then read alerts in your on-call Slack channel, find the change that correlates, and open a PR when you ask.
&lt;/i&gt;
&lt;/center&gt;
&lt;/figcaption&gt;
&lt;/p&gt;
&lt;h2 id="4-implement-a-jira-or-linear-ticket-end-to-end"&gt;4. Implement a Jira or Linear ticket end-to-end&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Hand Neo a ticket number from Linear, Jira, or GitHub Issues. Neo reads the description and acceptance criteria, plans against your stack, and opens a PR.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Tickets often pile up not because they&amp;rsquo;re unimportant, but because they&amp;rsquo;re not urgent. Ongoing maintenance quietly accumulates. Bumping a provider version, centralizing secret management, working through small policy violations: each one matters, but none of them ever moves to the top of the queue. Explaining each one to an agent is its own overhead.&lt;/p&gt;
&lt;p&gt;The fix is letting Neo read the ticket itself. Connect Linear integration or Jira automation through the integration catalog (GitHub Issues works too), and Neo pulls the ticket the same way an engineer would: title, description, acceptance criteria.&lt;/p&gt;
&lt;p&gt;Ask Neo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Implement CAD-1234 in our payments stack.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neo reads the ticket, plans against your existing stack, opens a PR, and drops a comment back on the ticket. The ticket and the PR end up linked, and your backlog shrinks.&lt;/p&gt;
&lt;p&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded-lg w-full" title="Neo running locally in the Pulumi CLI: fielding a Linear issue, analyzing the codebase, and producing a PR that upgrades multiple projects to the latest Pulumi and AWS provider versions"
autoplay muted playsinline
loop &gt;
&lt;source src="neo-linear.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;figcaption&gt;
&lt;center&gt;
&lt;i&gt;
Neo running locally in the Pulumi CLI: fielding a Linear issue, analyzing the codebase, and producing a PR that upgrades multiple projects to the latest Pulumi and AWS provider versions.
&lt;/i&gt;
&lt;/center&gt;
&lt;/figcaption&gt;
&lt;/p&gt;
&lt;a href="https://app.pulumi.com/neo?prompt=I%27d&amp;#43;like&amp;#43;to&amp;#43;implement&amp;#43;a&amp;#43;ticket&amp;#43;from&amp;#43;Linear&amp;#43;%28or&amp;#43;Jira%2C&amp;#43;or&amp;#43;GitHub&amp;#43;Issues%29.&amp;#43;Ask&amp;#43;me&amp;#43;for&amp;#43;the&amp;#43;ticket&amp;#43;number." class="neo-card"&gt;
&lt;div class="neo-card-content"&gt;
&lt;div class="neo-card-icon"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular" fill="currentColor" role="img" aria-label="Pulumi Neo AI icon"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#c-pulumi-neo-regular"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;div class="neo-card-text"&gt;
&lt;span class="neo-card-subtitle"&gt;Start a Neo task&lt;/span&gt;
&lt;span class="neo-card-title"&gt;Implement a Linear ticket end-to-end&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="neo-card-arrow"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--bold" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-caret-right-bold"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;h2 id="5-audit-and-tighten-over-privileged-iam-roles"&gt;5. Audit and tighten over-privileged IAM roles&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Neo audits each role against what your stack code actually does, and proposes scoped policies that improve your security posture.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;IAM cleanup is the kind of work nobody has the time to prioritize. Production has 40 roles. Half of them started with &lt;code&gt;s3:*&lt;/code&gt; because nobody had time to scope them, and the cleanup slips quarter to quarter.&lt;/p&gt;
&lt;p&gt;Ask Neo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Audit IAM permissions across my accounts and propose narrower policies for over-privileged stack-managed roles.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neo cross-references each role&amp;rsquo;s policy against what the stack code actually calls, and opens a PR per role. The PR body lists the API calls Neo found in the stack code, like &lt;code&gt;s3:GetObject&lt;/code&gt; on &lt;code&gt;audit-logs-*&lt;/code&gt; and &lt;code&gt;s3:PutObject&lt;/code&gt; on &lt;code&gt;audit-logs-staging&lt;/code&gt;, as the justification for the scoped policy. The evidence sits next to the diff.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re unclear about which roles count as in-scope or what your team considers over-privileged, start in &lt;a href="https://www.pulumi.com/blog/neo-plan-mode/"&gt;plan mode&lt;/a&gt; and agree on that with Neo first.&lt;/p&gt;
&lt;p&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded-lg w-full" title="Neo auditing IAM and proposing narrower policies"
autoplay muted playsinline
loop &gt;
&lt;source src="iam-narrow.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;figcaption&gt;
&lt;center&gt;
&lt;i&gt;
Neo auditing an over-privileged IAM role and proposing a narrower policy, with the actually-used permissions as evidence.
&lt;/i&gt;
&lt;/center&gt;
&lt;/figcaption&gt;
&lt;/p&gt;
&lt;a href="https://app.pulumi.com/neo?prompt=Audit&amp;#43;IAM&amp;#43;permissions&amp;#43;across&amp;#43;my&amp;#43;accounts&amp;#43;and&amp;#43;propose&amp;#43;narrower&amp;#43;policies&amp;#43;for&amp;#43;over-privileged&amp;#43;stack-managed&amp;#43;roles." class="neo-card"&gt;
&lt;div class="neo-card-content"&gt;
&lt;div class="neo-card-icon"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular" fill="currentColor" role="img" aria-label="Pulumi Neo AI icon"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#c-pulumi-neo-regular"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;div class="neo-card-text"&gt;
&lt;span class="neo-card-subtitle"&gt;Start a Neo task&lt;/span&gt;
&lt;span class="neo-card-title"&gt;Audit IAM and tighten over-privileged roles&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="neo-card-arrow"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--bold" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-caret-right-bold"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;h2 id="6-migrate-from-aws-cdk-onto-your-platforms-golden-paths"&gt;6. Migrate from AWS CDK onto your platform&amp;rsquo;s golden paths&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Neo reads your existing AWS CDK app and lands a PR that swaps AWS&amp;rsquo;s defaults for your team&amp;rsquo;s published components.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;CDK&amp;rsquo;s L2 constructs encode AWS&amp;rsquo;s defaults. &lt;code&gt;s3.Bucket&lt;/code&gt; with &lt;code&gt;encryption: BucketEncryption.S3_MANAGED&lt;/code&gt; is a sane choice, but it&amp;rsquo;s AWS&amp;rsquo;s idea of sane, not yours. A platform team that&amp;rsquo;s published its own components to the &lt;a href="https://www.pulumi.com/docs/idp/concepts/private-registry/"&gt;Pulumi Private Registry&lt;/a&gt; has already decided what &lt;em&gt;your&lt;/em&gt; bucket defaults look like: encryption with the right KMS key, tagging by cost center.&lt;/p&gt;
&lt;p&gt;Ask Neo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Migrate the &lt;code&gt;payments-vpc&lt;/code&gt; CDK stack to Pulumi using our published components.&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neo reads the source CDK app and your registry side by side. It maps each CDK construct to its closest team-published equivalent, clarifying with you where the mapping is ambiguous.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Before (AWS CDK, AWS&amp;#39;s defaults)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Assets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;bucketName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;payments-assets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;encryption&lt;/span&gt;: &lt;span class="kt"&gt;s3.BucketEncryption.S3_MANAGED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;versioned&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// After (Pulumi, your team&amp;#39;s published component)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;platform&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@payments/platform&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;assets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;bucketName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;payments-assets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;classification&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;a href="https://app.pulumi.com/neo?prompt=I%27d&amp;#43;like&amp;#43;to&amp;#43;migrate&amp;#43;this&amp;#43;CDK&amp;#43;stack&amp;#43;to&amp;#43;Pulumi.&amp;#43;Use&amp;#43;our&amp;#43;published&amp;#43;components&amp;#43;where&amp;#43;you&amp;#43;can." class="neo-card"&gt;
&lt;div class="neo-card-content"&gt;
&lt;div class="neo-card-icon"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular" fill="currentColor" role="img" aria-label="Pulumi Neo AI icon"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#c-pulumi-neo-regular"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;div class="neo-card-text"&gt;
&lt;span class="neo-card-subtitle"&gt;Start a Neo task&lt;/span&gt;
&lt;span class="neo-card-title"&gt;Migrate CDK onto your golden paths&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="neo-card-arrow"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--bold" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-caret-right-bold"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;p&gt;Neo handles &lt;a href="https://www.pulumi.com/blog/neo-migration/"&gt;Terraform and Azure ARM migrations&lt;/a&gt; the same way.&lt;/p&gt;
&lt;h2 id="7-containerize-a-service-and-migrate-it-to-kubernetes-from-a-runbook"&gt;7. Containerize a service and migrate it to Kubernetes from a runbook&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Write the containerization pattern down once. Every service after that is a prompt away.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Containerizing an application and moving it to Kubernetes involves several small decisions: which Docker image, what labels go on deployments, how ingress is wired, and how secrets reach the pod. But after a team has moved two or three services, the pattern is set. The decisions get written down in a runbook, and every subsequent migration is mostly the same shape.&lt;/p&gt;
&lt;p&gt;Ask Neo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Containerize the &lt;code&gt;billing-api&lt;/code&gt; service and write its Kubernetes manifests, following our K8s migration runbook in Confluence.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neo reads the source repo and the runbook in Confluence via the &lt;a href="https://www.pulumi.com/blog/neo-integration-catalog/"&gt;integration catalog&lt;/a&gt; and starts working on your request.&lt;/p&gt;
&lt;p&gt;You can save this as a Neo skill that splits the work into multiple PRs — Dockerfile first, ECR config next, Deployment/Service/Ingress manifests after — and link back to each runbook convention for ease of review. The output reflects your conventions: the labels you actually use, the ingress class you&amp;rsquo;ve standardized on, and the External Secrets Operator config your team prefers.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;re still the one reviewing the PRs and deciding what the cutover looks like in production. Neo follows your internal standards, so the new service ends up shaped like the last one you migrated.&lt;/p&gt;
&lt;p&gt;&lt;img src="neo-migration-prs.png" alt="Five GitHub PRs in a row, one per migration step (Dockerfile, Deployment, Service+Ingress, ExternalSecret, HPA+PDB), each citing the runbook section it implements"&gt;
&lt;figcaption&gt;
&lt;center&gt;
&lt;i&gt;
Neo migrating a VM-based service to Kubernetes step by step, following the team's Confluence runbook.
&lt;/i&gt;
&lt;/center&gt;
&lt;/figcaption&gt;
&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve delegated something a few times, the next move is to automate it. The remaining three tasks are the kind Neo doesn&amp;rsquo;t need to be asked for. Drift, deps, compliance: they&amp;rsquo;re the operations you put on a schedule via &lt;a href="https://www.pulumi.com/blog/neo-automations/"&gt;Neo Automations&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="8-schedule-daily-configuration-drift-detection-across-your-cloud-infrastructure"&gt;8. Schedule daily configuration drift detection across your cloud infrastructure&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Schedule a daily drift check across your cloud. Wake up to PRs that fix what changed overnight.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Configuration drift is an ongoing challenge. The security team rotated an IAM role at 04:47 UTC. Someone changed a security group in the AWS console three weeks ago. Left alone, drift turns into security gaps, into compliance issues, and into the kind of &amp;ldquo;wait, who changed that?&amp;rdquo; confusion nobody wants to chase down.&lt;/p&gt;
&lt;p&gt;Pulumi Cloud is already good at configuration drift detection. Neo takes it a step further.&lt;/p&gt;
&lt;p&gt;Ask Neo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Every morning at 6 AM, check all production infrastructure for drift and create PRs to fix any issues you find.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From then on, the task runs on its own, and you wake up to a PR per drifted resource. The description spells out what happened (&lt;code&gt;iam_role.audit-reader&lt;/code&gt; had inline policy &lt;code&gt;AllowReadAuditLogs&lt;/code&gt; added at 04:47 UTC) and cites the section of &lt;code&gt;infra/runbooks/drift.md&lt;/code&gt; Neo followed.&lt;/p&gt;
&lt;p&gt;Some drift gets encoded into the Pulumi program, like the IAM rotation above. Some gets reverted, like the security group rule added from the console. Some gets ignored entirely, like autoscaler-managed Lambda concurrency reservations the runbook tells Neo to skip. You write the runbook once; Neo follows it every morning to decide what to do.&lt;/p&gt;
&lt;p&gt;&lt;img src="neo-drift-pr.png" alt="Neo&amp;rsquo;s morning drift PR: encodes a security-team IAM rotation into the prod-audit stack, citing the runbook section that says to accept and encode the change"&gt;
&lt;figcaption&gt;
&lt;center&gt;
&lt;i&gt;
Neo's morning drift PR. The body names the resource, the change, when it happened, and the section of the runbook Neo followed to decide what to do.
&lt;/i&gt;
&lt;/center&gt;
&lt;/figcaption&gt;
&lt;/p&gt;
&lt;a href="https://app.pulumi.com/neo?prompt=Every&amp;#43;morning&amp;#43;at&amp;#43;6&amp;#43;AM%2C&amp;#43;check&amp;#43;all&amp;#43;production&amp;#43;infrastructure&amp;#43;for&amp;#43;drift&amp;#43;and&amp;#43;create&amp;#43;PRs&amp;#43;to&amp;#43;fix&amp;#43;any&amp;#43;issues&amp;#43;you&amp;#43;find." class="neo-card"&gt;
&lt;div class="neo-card-content"&gt;
&lt;div class="neo-card-icon"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular" fill="currentColor" role="img" aria-label="Pulumi Neo AI icon"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#c-pulumi-neo-regular"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;div class="neo-card-text"&gt;
&lt;span class="neo-card-subtitle"&gt;Start a Neo task&lt;/span&gt;
&lt;span class="neo-card-title"&gt;Schedule a daily drift check&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="neo-card-arrow"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--bold" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-caret-right-bold"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;h2 id="9-schedule-weekly-upgrades-for-outdated-lambda-runtimes-and-providers"&gt;9. Schedule weekly upgrades for outdated Lambda runtimes and providers&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Lambda runtimes and container base images age out. Schedule the upgrade pass; review the PRs Neo opens.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;AWS Lambda end-of-life notices come out months ahead. Node 20 stopped receiving updates as an AWS Lambda runtime at the end of April. Python 3.9 reached end-of-support last December. After the deadline, AWS blocks new deploys and eventually stops invoking the function. Each one needs to move to a supported runtime before the cutoff.&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Schedule it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Every Sunday night at 10 PM, check our Lambda functions for runtimes nearing end-of-support and open PRs to upgrade them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neo reads the AWS Lambda runtime deprecation page, matches the end-of-support runtimes against every Lambda function in your stacks, and opens one PR per stack.&lt;/p&gt;
&lt;p&gt;If Python 3.9 is reaching end-of-support, the upgrade is to Python 3.12, and &lt;code&gt;datetime.utcnow()&lt;/code&gt; calls need to move to &lt;code&gt;datetime.now(datetime.UTC)&lt;/code&gt;. Neo can make all of those replacements in the same PR.&lt;/p&gt;
&lt;p&gt;The same task can catch container base images with critical CVEs and bump them too.&lt;/p&gt;
&lt;p&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded-lg w-full" title="Setting up a weekly scheduled task in Neo"
autoplay muted playsinline
loop &gt;
&lt;source src="neo-schedule-setup.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;figcaption&gt;
&lt;center&gt;
&lt;i&gt;
Setting up a weekly task in the Scheduled Tasks UI. Once saved, Neo runs the prompt every Sunday night and opens PRs you review on Monday.
&lt;/i&gt;
&lt;/center&gt;
&lt;/figcaption&gt;
&lt;/p&gt;
&lt;a href="https://app.pulumi.com/neo?prompt=Every&amp;#43;Sunday&amp;#43;night&amp;#43;at&amp;#43;10&amp;#43;PM%2C&amp;#43;check&amp;#43;our&amp;#43;Lambda&amp;#43;functions&amp;#43;for&amp;#43;runtimes&amp;#43;nearing&amp;#43;end-of-support&amp;#43;and&amp;#43;open&amp;#43;PRs&amp;#43;to&amp;#43;upgrade&amp;#43;them." class="neo-card"&gt;
&lt;div class="neo-card-content"&gt;
&lt;div class="neo-card-icon"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular" fill="currentColor" role="img" aria-label="Pulumi Neo AI icon"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#c-pulumi-neo-regular"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;div class="neo-card-text"&gt;
&lt;span class="neo-card-subtitle"&gt;Start a Neo task&lt;/span&gt;
&lt;span class="neo-card-title"&gt;Schedule a weekly runtime upgrade check&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="neo-card-arrow"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--bold" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-caret-right-bold"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;h2 id="10-fix-aws-cis-benchmark-failures-with-daily-prs"&gt;10. Fix AWS CIS Benchmark failures with daily PRs&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Run the AWS CIS Benchmark on a schedule. Wake up to PRs that fix every failure.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://docs.aws.amazon.com/securityhub/latest/userguide/cis-aws-foundations-benchmark.html"&gt;CIS AWS Foundations Benchmark&lt;/a&gt;, available through AWS Security Hub, is something every team should be keeping an eye on. The benchmark finds issues like S3 buckets that allow public read access (&lt;code&gt;S3.1&lt;/code&gt;), root user access keys that shouldn&amp;rsquo;t exist (&lt;code&gt;IAM.4&lt;/code&gt;), or CloudTrail not being enabled (&lt;code&gt;CloudTrail.1&lt;/code&gt;). Scanning for these issues is a solved problem, but closing and addressing them is not. They pile up between audits because each one is a code change in a different stack, and nobody owns the cross-stack cleanup.&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Schedule the cleanup:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Every morning, read CIS Benchmark failures from Security Hub. For every failure on an IaC-managed resource, open a PR with the fix.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neo opens one PR per failure. A bucket failing &lt;code&gt;S3.1&lt;/code&gt; arrives as a Pulumi diff that adds &lt;code&gt;blockPublicAccess&lt;/code&gt; to the bucket in your &lt;code&gt;prod-checkout&lt;/code&gt; stack. The PR body lists the CIS rule number, the resource ID, the diff, and a clean &lt;code&gt;pulumi preview&lt;/code&gt; against the live infrastructure.&lt;/p&gt;
&lt;p&gt;The runbook is where your security team writes down what each control means for your stacks. Block public S3 buckets, except the ones tagged &lt;code&gt;public-content=true&lt;/code&gt; for CloudFront origins. Don&amp;rsquo;t auto-touch the break-glass IAM roles; page a human instead. Multi-region CloudTrail stays on, no exceptions. Neo reads that file, checks each Security Hub finding against it, and only opens a PR for the ones you&amp;rsquo;ve said are safe to fix. The rest get routed or ignored, the way your team already handles them.&lt;/p&gt;
&lt;p&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded-lg w-full" title="Scrolling through Neo&amp;#39;s morning CIS Benchmark PR"
autoplay muted playsinline
loop &gt;
&lt;source src="neo-cis-pr.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;figcaption&gt;
&lt;center&gt;
&lt;i&gt;
A PR raised by Neo to fix a CIS Benchmark failure, with the failing rule, the resource, and the runbook decision laid out in the body.
&lt;/i&gt;
&lt;/center&gt;
&lt;/figcaption&gt;
&lt;/p&gt;
&lt;a href="https://app.pulumi.com/neo?prompt=Every&amp;#43;morning%2C&amp;#43;verify&amp;#43;all&amp;#43;resources&amp;#43;meet&amp;#43;our&amp;#43;compliance&amp;#43;policies&amp;#43;and&amp;#43;create&amp;#43;PRs&amp;#43;to&amp;#43;fix&amp;#43;violations." class="neo-card"&gt;
&lt;div class="neo-card-content"&gt;
&lt;div class="neo-card-icon"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular" fill="currentColor" role="img" aria-label="Pulumi Neo AI icon"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#c-pulumi-neo-regular"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;div class="neo-card-text"&gt;
&lt;span class="neo-card-subtitle"&gt;Start a Neo task&lt;/span&gt;
&lt;span class="neo-card-title"&gt;Schedule daily AWS CIS Benchmark scans&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="neo-card-arrow"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--bold" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-caret-right-bold"/&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;h2 id="neo-your-newest-platform-engineer"&gt;Neo: your newest platform engineer&lt;/h2&gt;
&lt;p&gt;Over the past year, many product teams have stopped treating AI as a request-by-request assistant and started delegating to it outright.&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt; Agents open pull requests, investigate issues, and iterate on review feedback.&lt;/p&gt;
&lt;p&gt;But platform engineers have held back because a bad infrastructure change doesn&amp;rsquo;t just fail, it can take production down. Coding agents benefit from fast, forgiving feedback loops, but infrastructure recovery is rarely as simple as reverting a commit.&lt;/p&gt;
&lt;p&gt;What was missing wasn&amp;rsquo;t the appetite. It was an agent with enough organizational context and &lt;a href="https://www.pulumi.com/blog/grounded-ai-why-neo-knows-your-infrastructure/"&gt;grounding&lt;/a&gt; to plan reliably, enough guardrails to feel safe and contain mistakes, and enough discipline to keep working without being asked.&lt;/p&gt;
&lt;p&gt;The theme across these tasks is clear. A thing platform engineers used to keep in their heads becomes a task you delegate, then becomes work that runs without you. Neo isn&amp;rsquo;t generating infrastructure from a template. It&amp;rsquo;s a teammate who knows your code, your providers, your conventions, your production metrics, and can raise PRs for you to review.&lt;/p&gt;
&lt;p&gt;Neo now lives in your terminal, in your pull requests, in your Slack workspace, and in Pulumi Cloud. Pick one of these workflows and &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/neo/"&gt;give it a try&lt;/a&gt;.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;The observant reader will notice Terraform-to-Pulumi was covered &lt;a href="https://www.pulumi.com/blog/10-things-you-can-do-with-neo/"&gt;in the original post&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Also covered in the &lt;a href="https://www.pulumi.com/blog/10-things-you-can-do-with-neo/"&gt;original post&lt;/a&gt;. Last year you could ask Neo to do it once. This year you can put it on a schedule.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;Also covered in the &lt;a href="https://www.pulumi.com/blog/10-things-you-can-do-with-neo/"&gt;original post&lt;/a&gt;. Last year Neo could remediate violations on demand. This year Security Hub feeds findings to a scheduled task that knows your runbook&amp;rsquo;s interpretation of each control.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;For a concrete example, see &lt;a href="https://www.pulumi.com/blog/seven-rules-ai-native-software-factory/"&gt;Seven Rules for Building an AI-Native Software Factory&lt;/a&gt;: Ewan Dawson, CTO of Compostable AI, runs nineteen client deployments with five engineers, using Pulumi Neo to handle most of the infrastructure work.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><author>Adam Gordon Bell</author><category>ai</category><category>platform-engineering</category><category>pulumi-neo</category><category>aws</category></item><item><title>The Dark Factory Pattern for Infrastructure: Running Pulumi Lights-Out</title><link>https://www.pulumi.com/blog/dark-factory-pattern-pulumi-autonomous-iac/</link><pubDate>Tue, 05 May 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/dark-factory-pattern-pulumi-autonomous-iac/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/dark-factory-pattern-pulumi-autonomous-iac/index.png" /&gt;
&lt;p&gt;The original dark factory was &lt;a href="https://www.imeche.org/news/news-article/inside-the-rise-of-unmanned-dark-factories"&gt;Fanuc&amp;rsquo;s robotics plant in Oshino, Japan&lt;/a&gt;, where the lights are off because nobody is on the floor. Robots build robots. Parts move through the line for weeks at a time without a person walking past them.&lt;/p&gt;
&lt;p&gt;The same pattern is now showing up in software. Three engineers at StrongDM &lt;a href="https://simonwillison.net/2026/Feb/7/software-factory/"&gt;shipped roughly 32,000 lines of production code&lt;/a&gt; without writing or reviewing any of it. Stripe&amp;rsquo;s &amp;ldquo;Minions&amp;rdquo; agent system &lt;a href="https://stripe.dev/blog/minions-stripes-one-shot-end-to-end-coding-agents"&gt;merges over a thousand pull requests every week&lt;/a&gt;. In January, Dan Shapiro of Glowforge published &lt;a href="https://www.danshapiro.com/blog/2026/01/the-five-levels-from-spicy-autocomplete-to-the-software-factory/"&gt;a five-level autonomy ladder&lt;/a&gt; that landed cleanly enough to become the shorthand most people now use, and BCG put out &lt;a href="https://www.bcgplatinion.com/insights/the-dark-software-factory"&gt;a piece calling it the dark software factory&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Almost every public writeup so far is about application code. The harder question is what this looks like for infrastructure.&lt;/p&gt;
&lt;h2 id="what-a-dark-factory-actually-is"&gt;What a dark factory actually is&lt;/h2&gt;
&lt;p&gt;Shapiro&amp;rsquo;s ladder is the cleanest framing I&amp;rsquo;ve seen. He borrows it from the SAE&amp;rsquo;s self-driving levels, and it fits surprisingly well:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;Driving analogy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Spicy autocomplete&lt;/td&gt;
&lt;td&gt;Stick shift; you do everything.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Coding intern (boilerplate)&lt;/td&gt;
&lt;td&gt;Cruise control.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Junior developer (interactive pair)&lt;/td&gt;
&lt;td&gt;One hand on the wheel.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;AI writes the majority; you review every PR&lt;/td&gt;
&lt;td&gt;Eyes still on the road.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Spec-driven; agent runs unattended for hours; you review later&lt;/td&gt;
&lt;td&gt;Sleeping at the wheel, you can still wake up.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Dark factory; no human review of code before production&lt;/td&gt;
&lt;td&gt;No steering wheel at all.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Most teams are at level 2 or 3. A few of the more aggressive ones are at 4. Level 5 is the experiment. Most teams won&amp;rsquo;t get there safely, and probably shouldn&amp;rsquo;t try to. The interesting design question is what has to be true for level 5 to be safe at all, and that question gets sharper when the thing being shipped is infrastructure.&lt;/p&gt;
&lt;p&gt;A dark factory is not a coding harness. A harness is the framework an agent runs inside; the dark factory is the surrounding system that makes a harness&amp;rsquo;s output mergeable without a human reading the diff. Copilot and Cursor sit at the other end: interactive, the human stays in the loop on every keystroke. The dark factory takes the human out of the per-change loop entirely and puts them at the top, writing the spec and the acceptance criteria.&lt;/p&gt;
&lt;h2 id="the-wall-between-generator-and-validator"&gt;The wall between generator and validator&lt;/h2&gt;
&lt;p&gt;Strip the dark factory down to its layers and there are four of them.&lt;/p&gt;
&lt;pre class="mermaid"&gt;
flowchart LR
A[Inputs&amp;lt;br/&amp;gt;Humans] --&amp;gt; B[Code Generation&amp;lt;br/&amp;gt;Autonomous]
B --&amp;gt; C[Validation&amp;lt;br/&amp;gt;Autonomous, isolated]
C --&amp;gt;|pass| D[Merge &amp;amp; Deploy&amp;lt;br/&amp;gt;Autonomous + existing CI/CD]
C --&amp;gt;|fail| B
A -.-&amp;gt;|holdout scenarios&amp;lt;br/&amp;gt;generator never sees these| C
&lt;/pre&gt;
&lt;p&gt;The single most important rule is that Code Generation and Validation must be completely isolated. The generator never sees the acceptance scenarios. A separate evaluator does, and it judges the generator&amp;rsquo;s output against scenarios the generator could not have memorized.&lt;/p&gt;
&lt;p&gt;The reason is sycophancy. LLMs are too eager to agree with their own prior turns and too willing to declare victory on something they just produced. Without isolation, the same model that wrote the change is the one telling you it&amp;rsquo;s fine. The practical concern is direct: a test stored in the same codebase as the implementation will get lazily rewritten to match the code, not the other way around. It isn&amp;rsquo;t malice; it&amp;rsquo;s the agent doing exactly what it was asked, badly. The wall is what stops that.&lt;/p&gt;
&lt;p&gt;StrongDM&amp;rsquo;s pattern for this is &lt;strong&gt;holdout scenarios&lt;/strong&gt;: plain-English BDD acceptance tests stored where the generator cannot reach them. Each scenario runs three times against an ephemeral deployment, two of three must pass, and the overall pass rate has to clear 90% before the change moves forward. If the generator fails, it gets a one-line failure message (&amp;ldquo;SQL Injection Detection failed: endpoint returned 500&amp;rdquo;), not the scenario text. It cannot game the test.&lt;/p&gt;
&lt;p&gt;Without that wall, you don&amp;rsquo;t have a quality gate. You have theater.&lt;/p&gt;
&lt;h2 id="why-infrastructure-is-the-harder-version"&gt;Why infrastructure is the harder version&lt;/h2&gt;
&lt;p&gt;Application code factories can lean on tests, linters, and type checkers. Infrastructure adds blast radius, drift, secrets, irreversible actions, and multi-region state. A code dark factory shipping a broken UI causes a bad user experience. An infrastructure dark factory shipping a broken IAM policy ends in a postmortem.&lt;/p&gt;
&lt;p&gt;A few things make this manageable on Pulumi specifically.&lt;/p&gt;
&lt;p&gt;The orchestrator does not need to be invented. The &lt;a href="https://www.pulumi.com/automation/"&gt;Pulumi Automation API&lt;/a&gt; is the engine as an SDK in Python, TypeScript, Go, .NET, Java, or YAML, which is the same surface a dark factory orchestrator runs on. Credentials don&amp;rsquo;t have to be long-lived: &lt;a href="https://www.pulumi.com/docs/esc/"&gt;ESC and OIDC&lt;/a&gt; issue short-lived ones per run, so the agent never sees a static secret.&lt;/p&gt;
&lt;p&gt;Policy doesn&amp;rsquo;t have to be probabilistic: &lt;a href="https://www.pulumi.com/docs/iac/using-pulumi/crossguard/"&gt;CrossGuard&lt;/a&gt; enforces deterministic rules at preview time. Execution doesn&amp;rsquo;t have to happen on a laptop: &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;Pulumi Cloud Deployments&lt;/a&gt; runs &lt;code&gt;pulumi up&lt;/code&gt; inside a governed runner with audit logs and approval rules already wired. And the reasoning layer doesn&amp;rsquo;t have to start from scratch: &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt; is grounded in your state graph and ships with &lt;a href="https://www.pulumi.com/blog/neo-levels-up/"&gt;three modes (Auto, Balanced, Review)&lt;/a&gt; that line up cleanly with Shapiro&amp;rsquo;s levels 5, 4, and 3.&lt;/p&gt;
&lt;p&gt;That doesn&amp;rsquo;t make Pulumi a dark factory by itself. It means the parts that an application-code factory has to build from scratch are pieces a Pulumi shop already has: a credential broker, a policy engine, a governed runner, a state-aware reasoning layer, an audit trail.&lt;/p&gt;
&lt;p&gt;And one more piece nobody talks about: &lt;code&gt;pulumi preview&lt;/code&gt; produces a clean, deterministic validation artifact, and CrossGuard evaluates that artifact without ever seeing the conversation that produced the program. That&amp;rsquo;s the same context-free judgment the holdout pattern depends on, applied at the policy layer instead of the acceptance-test layer. For infrastructure, half the wall is already built.&lt;/p&gt;
&lt;p&gt;The interesting work is the part that nobody ships in a box.&lt;/p&gt;
&lt;h2 id="the-interesting-work"&gt;The interesting work&lt;/h2&gt;
&lt;p&gt;What no platform ships for you is the wall: the holdout scenarios for infrastructure, the isolated evaluator that runs them, and the agreement on which stacks are even allowed to run lights-out.&lt;/p&gt;
&lt;p&gt;The happy-path orchestrator is small. It pulls a spec, runs &lt;code&gt;preview&lt;/code&gt;, hands the preview to an isolated evaluator (with its own credentials and its own access to the cloud, no access to the generator&amp;rsquo;s prompt or output), and branches on the verdict. Auto mode runs &lt;code&gt;up&lt;/code&gt; immediately. Balanced mode submits a deployment that requires approval. Review mode opens a PR for a human. Every branch records a stack version traceable in the audit log. Retries, observability, secret rotation, and the rest of the production-grade plumbing add up to real code, but the shape is small.&lt;/p&gt;
&lt;p&gt;The wall is the part that takes a week to get right. You write five plain-English scenarios for one stack (&amp;ldquo;after &lt;code&gt;pulumi up&lt;/code&gt;, the bucket is private, has SSE-KMS, lives in eu-west-1, and is tagged &lt;code&gt;owner=team-x&lt;/code&gt;&amp;rdquo;) and a janky evaluator that runs &lt;code&gt;preview&lt;/code&gt; and &lt;code&gt;up&lt;/code&gt; against an ephemeral copy, queries the cloud, and asks a separate model whether the resulting state satisfies the scenario. Triple-run, 90% pass gate. Then you watch it for a few weeks before you let anything auto-apply.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Ground your agent in real state&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Pulumi Neo reasons over your actual state graph and runs in Review, Balanced, or Auto mode, so you can grant it more autonomy as your confidence grows.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/product/neo/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="a-four-phase-rollout"&gt;A four-phase rollout&lt;/h2&gt;
&lt;p&gt;This is the same path the application-code factories walked, with the gates tightened.&lt;/p&gt;
&lt;h3 id="phase-1-better-context-this-afternoon"&gt;Phase 1: better context, this afternoon&lt;/h3&gt;
&lt;p&gt;Write an &lt;code&gt;AGENTS.md&lt;/code&gt; for your most active stack repo. Pulumi Neo &lt;a href="https://www.pulumi.com/blog/pulumi-neo-now-supports-agentsmd/"&gt;reads it natively&lt;/a&gt;, as do most coding agents. While you&amp;rsquo;re there, look at your CrossGuard rules and rewrite the error messages as instructions. Not &amp;ldquo;S3 bucket has no encryption&amp;rdquo; but &amp;ldquo;S3 bucket has no encryption. Set &lt;code&gt;serverSideEncryptionConfiguration&lt;/code&gt; with SSE-KMS to fix.&amp;rdquo; That single change is the difference between an agent flailing and an agent fixing the policy violation on the first try. Wire &lt;code&gt;pulumi preview&lt;/code&gt; as a build-before-push gate so PRs don&amp;rsquo;t show up just to fail CI.&lt;/p&gt;
&lt;h3 id="phase-2-spec-driven-with-holdouts-this-week"&gt;Phase 2: spec-driven with holdouts, this week&lt;/h3&gt;
&lt;p&gt;Pick one stack with a small blast radius. A review-stack lifecycle is ideal. Write five plain-English holdout scenarios for it and the janky evaluator above. Humans still approve every PR. Don&amp;rsquo;t auto-merge yet. You&amp;rsquo;re earning the data, not declaring trust.&lt;/p&gt;
&lt;h3 id="phase-3-take-the-human-out-of-the-merge"&gt;Phase 3: take the human out of the merge&lt;/h3&gt;
&lt;p&gt;Only after the three measurable gates hold over twenty PRs (scenario pass rate above 90%, false positive rate below 5%, human override rate below 10%) flip auto-apply on for that one stack. Add a weekly drift sweep that goes through the same scenario gate as everything else.&lt;/p&gt;
&lt;h3 id="phase-4-lights-out"&gt;Phase 4: lights out&lt;/h3&gt;
&lt;p&gt;Expand the auto-apply flag to every stack with strong scenario numbers. Wire your issue tracker so tickets tagged &lt;code&gt;infra:fix&lt;/code&gt; flow through the pipeline. Mock the cloud APIs that are slow or flaky enough to make scenario evaluation expensive. At this point the orchestrator is configuration, not architecture.&lt;/p&gt;
&lt;h2 id="what-could-go-wrong"&gt;What could go wrong&lt;/h2&gt;
&lt;p&gt;None of these have clean fixes. The mitigations below reduce risk; they don&amp;rsquo;t eliminate it. Any team running level 5 should expect to eat one or two of these in the first year.&lt;/p&gt;
&lt;p&gt;The validator approves a bad change. This is the obvious one. The standard mitigation is layered: triple-run each scenario with a 2-of-3 threshold, a 90% gate over the run set, a human audit of the first fifty auto-applied changes, and your existing policies still run after the validator says yes.&lt;/p&gt;
&lt;p&gt;The agent gets a destroy permission it shouldn&amp;rsquo;t have. There&amp;rsquo;s a class of operations that should not sit in the autonomous loop yet: dropping a database, deleting a hosted zone, rotating a root key, anything that crosses a regulated data boundary. Scope what each agent identity can do at the credential layer, require human approval for anything destructive, and start every stack at Review mode. Tag changes, security-group adjustments, and instance resizes can run autonomously today. Release-branch cuts and config promotions can probably run by next quarter. The destructive class earns its way in over months.&lt;/p&gt;
&lt;p&gt;You need all three of those layers. Approvals without policy means anything a human approves in a hurry ships. Policy without approvals means a sufficiently clever spec eventually finds the gap. Both without a human kill switch means an incident at 3 a.m. has nobody to escalate to.&lt;/p&gt;
&lt;p&gt;Costs blow up. Cap retries at three per spec, alert on token spend per run, and remember that StrongDM reported roughly $1,000 per day per engineer-equivalent. That&amp;rsquo;s still cheaper than a salary, but only if you put the cap in place before you find out.&lt;/p&gt;
&lt;h2 id="where-to-start"&gt;Where to start&lt;/h2&gt;
&lt;p&gt;Most of what a dark factory needs already exists in any reasonably mature platform. Whatever you have for state, policy, credentials, audit, and a deployment runner is the substrate. The interesting work is not building the factory. It&amp;rsquo;s the wall: the holdout scenarios that make the gap between &amp;ldquo;the model says it&amp;rsquo;s fine&amp;rdquo; and &amp;ldquo;the system is actually fine&amp;rdquo; mean something.&lt;/p&gt;
&lt;p&gt;For most teams, Phase 1 alone is the win. Full Level 5 may stay out of reach indefinitely, and that&amp;rsquo;s fine. The path itself forces useful work: clearer specs, named bottlenecks, the deterministic gates humans had been running in their heads.&lt;/p&gt;
&lt;p&gt;Write an &lt;code&gt;AGENTS.md&lt;/code&gt; and five holdout scenarios for one stack this week. That&amp;rsquo;s enough to get a real signal on whether the pattern fits your team. The rest of the path is the same problem the application-code factories have already worked through, with the gates set tighter.&lt;/p&gt;</description><author>Engin Diri</author><category>ai</category><category>ai-agents</category><category>automation</category><category>infrastructure-as-code</category><category>pulumi-neo</category><category>platform-engineering</category></item><item><title>Agent Sprawl Is Here. Your IaC Platform Is the Answer.</title><link>https://www.pulumi.com/blog/agent-sprawl-iac-platform-is-the-answer/</link><pubDate>Wed, 22 Apr 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/agent-sprawl-iac-platform-is-the-answer/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/agent-sprawl-iac-platform-is-the-answer/index.png" /&gt;
&lt;p&gt;Somewhere in your company right now, a developer is building an AI agent. Maybe it&amp;rsquo;s a release agent that cuts tags when tests pass. Maybe it&amp;rsquo;s a cost agent that shuts down idle EC2 overnight. It&amp;rsquo;s running, it&amp;rsquo;s in production, and there&amp;rsquo;s a decent chance the platform team doesn&amp;rsquo;t know it exists.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t a thought experiment. OutSystems just surveyed 1,900 IT leaders and the numbers are rough: 96% of enterprises run AI agents in production today, 94% say the sprawl is becoming a real security problem, and only 12% have any central way to manage it. Twelve percent. You can &lt;a href="https://www.outsystems.com/news/enterprise-ai-agent-report-2026/"&gt;read the full report here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The real question is where those agents run. Inside the platform you&amp;rsquo;ve already built, or somewhere off to the side where nobody on the platform team can see them.&lt;/p&gt;
&lt;h2 id="the-new-platform-tension"&gt;The new platform tension&lt;/h2&gt;
&lt;p&gt;Platform teams have always had two jobs that pull in opposite directions. Let developers ship without waiting on a ticket. Keep the infrastructure coherent while they do. Golden paths, review stacks, a catalog of components that don&amp;rsquo;t fight each other.&lt;/p&gt;
&lt;p&gt;Agents break the second half of that deal.&lt;/p&gt;
&lt;p&gt;A developer with a sharp prompt can spin up an SRE agent that watches a queue, a release agent that cuts tags when the test suite goes green, or a cost agent that kills idle infra at 2 a.m. That&amp;rsquo;s useful. It&amp;rsquo;s also running on your production cloud account, using credentials you never provisioned, writing to systems you never approved, and the only audit trail is whatever the developer remembered to log. The &lt;a href="https://www.salesforce.com/news/stories/connectivity-report-announcement-2026/"&gt;Salesforce 2026 Connectivity Benchmark&lt;/a&gt; pegs the average enterprise at twelve agents today, projected to grow 67% over the next two years. Most teams aren&amp;rsquo;t ready for one, let alone twenty.&lt;/p&gt;
&lt;p&gt;This is the same shape as every sprawl problem before it. I wrote about the last one in &lt;a href="https://www.pulumi.com/blog/how-secrets-sprawl-is-slowing-you-down/"&gt;&lt;em&gt;How Secrets Sprawl Is Slowing You Down&lt;/em&gt;&lt;/a&gt;, and the pattern keeps repeating. When something useful gets cheap, it proliferates. When it proliferates without structure, it becomes a liability.&lt;/p&gt;
&lt;p&gt;The clock is also ticking on the compliance side. The &lt;a href="https://artificialintelligenceact.eu/implementation-timeline/"&gt;EU AI Act&amp;rsquo;s high-risk obligations kick in on 2 August 2026&lt;/a&gt;. &lt;a href="https://leg.colorado.gov/bills/sb25b-004"&gt;Colorado&amp;rsquo;s AI Act goes live on 30 June 2026&lt;/a&gt; after last year&amp;rsquo;s delay. A folder of unreviewed agent scripts isn&amp;rsquo;t going to hold up against either of those.&lt;/p&gt;
&lt;h2 id="three-ways-to-respond-only-one-of-them-works"&gt;Three ways to respond (only one of them works)&lt;/h2&gt;
&lt;p&gt;There are roughly three paths from here.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/agent-sprawl-iac-platform-is-the-answer/three-responses.png" alt="Three platform responses to agent sprawl: do nothing leads to unmanaged sprawl, mandating centralization creates developer friction, and making the platform the obvious path produces voluntary adoption"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do nothing.&lt;/strong&gt; Accept the sprawl and hope nothing catches fire. This is the default, and it&amp;rsquo;s also how you end up explaining to an auditor why some finance agent moved data between three systems last Thursday and nobody remembers which prompt triggered it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mandate centralization.&lt;/strong&gt; Tell developers every agent has to be registered and approved before it runs. This sounds responsible on a slide, and it falls apart inside a sprint. Developers route around friction. If the official path takes a week and the unofficial path takes an afternoon, the unofficial path wins, and you&amp;rsquo;ve just pushed the sprawl underground where you can&amp;rsquo;t see it anymore.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Make the platform the obvious path.&lt;/strong&gt; Build the thing developers actually want to use. A place where an agent inherits the guardrails, credentials, policies, and audit trail by default, because that&amp;rsquo;s what&amp;rsquo;s on offer. Adoption becomes a side effect of shipping something good.&lt;/p&gt;
&lt;p&gt;Option three is the only one that scales. It&amp;rsquo;s also the one where most platform teams look at their existing stack and assume they need to build a pile of new scaffolding. I don&amp;rsquo;t think they do, and the rest of this post is why.&lt;/p&gt;
&lt;h2 id="the-seven-things-an-ai-agent-needs-from-your-platform"&gt;The seven things an AI agent needs from your platform&lt;/h2&gt;
&lt;p&gt;An agent needs seven concrete things from the platform it runs on. Each one maps to a Pulumi primitive you already own.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/agent-sprawl-iac-platform-is-the-answer/seven-pillars.png" alt="Seven things an AI agent needs from your platform mapped to their Pulumi primitives: context to state graph and Neo, integrations to providers and ESC, actions to Deployments and Automation API, policy to CrossGuard, audit to Pulumi Cloud activity log, review to pulumi preview and review stacks, approval to Deployments approvals and Neo"&gt;&lt;/p&gt;
&lt;h3 id="1-a-trustworthy-context-lake"&gt;1. A trustworthy context lake&lt;/h3&gt;
&lt;p&gt;Agents are only as good as the context they can reason over. Drop a generic LLM into your cloud account and you&amp;rsquo;ll get plausible-sounding nonsense, because the model has never seen your environment. What you actually need is a grounded source of truth: what resources exist, how they relate, which stack owns what, which version is running where.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/docs/iac/concepts/state-and-backends/"&gt;Pulumi state&lt;/a&gt; is already that. Your program graph, your stack outputs, your resource metadata, all of it adds up to a structured record of what you&amp;rsquo;ve actually deployed. &lt;a href="https://www.pulumi.com/blog/grounded-ai-why-neo-knows-your-infrastructure/"&gt;Pulumi Neo reasons directly over that graph&lt;/a&gt;, which is why it can tell you why a deployment drifted instead of guessing. I wrote the long version of that argument there. Short version: you already have the context lake. Point agents at it.&lt;/p&gt;
&lt;h3 id="2-pre-cleared-integrations"&gt;2. Pre-cleared integrations&lt;/h3&gt;
&lt;p&gt;An agent that needs to touch five systems shouldn&amp;rsquo;t need five separate credential dances. That&amp;rsquo;s where credential sprawl starts. Every agent gets a long-lived key, every key ends up in somebody&amp;rsquo;s &lt;code&gt;.env&lt;/code&gt;, and every rotation turns into an incident.&lt;/p&gt;
&lt;p&gt;The Pulumi surface here is the &lt;a href="https://www.pulumi.com/registry/"&gt;200+ providers&lt;/a&gt; plus &lt;a href="https://www.pulumi.com/product/esc/"&gt;Pulumi ESC&lt;/a&gt; handling dynamic credentials through OIDC. An agent doesn&amp;rsquo;t ask for an AWS access key. It asks ESC for a short-lived, scoped token bound to the environment it&amp;rsquo;s allowed to operate in, and the token expires when the task ends. No static keys, no rotation pain, no awkward postmortem about how something got committed to GitHub. &lt;a href="https://www.pulumi.com/blog/top-8-claude-skills-devops-2026/"&gt;The ESC patterns I walked through in the Claude skills post&lt;/a&gt; work just as well for an autonomous agent as they do for a human developer, which is really the whole point.&lt;/p&gt;
&lt;h3 id="3-governed-actions"&gt;3. Governed actions&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s a real difference between &amp;ldquo;an agent can see your infrastructure&amp;rdquo; and &amp;ldquo;an agent can change your infrastructure.&amp;rdquo; The second one is where you actually need structure. &lt;a href="https://www.pulumi.com/docs/deployments/"&gt;Pulumi Deployments&lt;/a&gt; gives you that structure: defined workflows, controlled triggers, running inside your Pulumi Cloud boundary instead of whatever environment the developer happened to spin up. &lt;a href="https://www.pulumi.com/docs/iac/automation-api/"&gt;The Automation API&lt;/a&gt; lets you build higher-order orchestration on the same primitives your developers already use.&lt;/p&gt;
&lt;p&gt;The framing I keep coming back to goes like this. An agent shouldn&amp;rsquo;t call &lt;code&gt;pulumi up&lt;/code&gt; directly. It should submit an action to a governed pipeline that runs &lt;code&gt;pulumi up&lt;/code&gt; on its behalf, inside an environment you control, with a log trail and the guardrails already in place. Same effect, very different threat model.&lt;/p&gt;
&lt;h3 id="4-deterministic-policy"&gt;4. Deterministic policy&lt;/h3&gt;
&lt;p&gt;Real governance lives outside the prompt. &amp;ldquo;Please don&amp;rsquo;t delete production&amp;rdquo; is a wish written into a system prompt, not an enforced control. And when an agent overrides your intent to do what it thought you meant, it&amp;rsquo;s behaving exactly the way the technology was designed to behave.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/docs/insights/policy/"&gt;Pulumi Policies&lt;/a&gt; is the answer the IaC community landed on years ago: policy as code, written in a real programming language, evaluated deterministically at preview and update time. Disallow production RDS deletions. Require encryption at rest. Block S3 buckets with public ACLs. An agent running through Pulumi hits those gates whether it &amp;ldquo;wants&amp;rdquo; to or not, because the gates live in the pipeline and not in the prompt. This is the pillar most teams underweight, and it&amp;rsquo;s the first one most auditors ask about.&lt;/p&gt;
&lt;h3 id="5-an-audit-trail"&gt;5. An audit trail&lt;/h3&gt;
&lt;p&gt;When something goes wrong at 3 a.m. (and with enough agents running, something will), you need answers fast. What changed, who changed it, and why. Not just &amp;ldquo;which agent,&amp;rdquo; but which version of which agent, triggered by what event, authorized by which policy, touching which resources.&lt;/p&gt;
&lt;p&gt;Pulumi Cloud&amp;rsquo;s activity log, the stack update history, and &lt;a href="https://www.pulumi.com/docs/esc/administration/audit-logs/"&gt;ESC audit logs&lt;/a&gt; already capture all of that. Every update is versioned. Every secret access is logged. Every policy evaluation is recorded. When an agent submits a change through your Pulumi pipeline, it inherits that audit surface for free. The alternative is reconstructing an incident from a mix of Slack messages, container logs, and developer memory, which is roughly the state most teams without a platform are in today.&lt;/p&gt;
&lt;h3 id="6-a-review-process"&gt;6. A review process&lt;/h3&gt;
&lt;p&gt;Not every agent action should wait for a human. But agents do need a promotion path, the same way new platform components do. Experimental, then reviewed, then trusted, then autonomous. That&amp;rsquo;s exactly what &lt;code&gt;pulumi preview&lt;/code&gt;, review stacks, and Deployments PR workflows already model for human contributors. An agent that wants to make a change should have to submit it the same way a junior engineer would. As a diff, with a plan, against a preview environment, until it earns the trust to skip steps.&lt;/p&gt;
&lt;p&gt;This connects back to the pattern I laid out in &lt;a href="https://www.pulumi.com/blog/golden-paths-infrastructure-components-and-templates/"&gt;&lt;em&gt;Golden Paths: Infrastructure Components and Templates&lt;/em&gt;&lt;/a&gt;. Golden paths were never only for humans. They&amp;rsquo;re just paths, and agents can walk them too.&lt;/p&gt;
&lt;h3 id="7-human-in-the-loop-approval"&gt;7. Human-in-the-loop approval&lt;/h3&gt;
&lt;p&gt;The last pillar is the one that keeps the other six honest. Some decisions shouldn&amp;rsquo;t be automated, full stop. Production rollbacks outside business hours. Destructive changes above a certain blast-radius threshold. Anything that touches a regulated data boundary. For those cases, you want a forced human checkpoint that the agent can&amp;rsquo;t route around.&lt;/p&gt;
&lt;p&gt;Pulumi Deployments approvals already play that role for human changes. &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&amp;rsquo;s review steps&lt;/a&gt; add the AI-aware version: a structured plan, a diff, a named approver, and a record of what they decided and why. I walked through what this looks like in practice in &lt;a href="https://www.pulumi.com/blog/self-verifying-ai-agents-vercels-agent-browser-in-the-ralph-wiggum-loop/"&gt;&lt;em&gt;Self-Verifying AI Agents&lt;/em&gt;&lt;/a&gt;. Short version: an agent that proposes is much safer than an agent that commits.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Govern agent changes through your platform&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Route changes from any coding agent, including Claude Code, Cursor, and Pulumi Neo, through the same infrastructure as code controls, policies, and audit trail your team already runs.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/docs/ai/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="why-iac-is-the-natural-substrate-for-this"&gt;Why IaC is the natural substrate for this&lt;/h2&gt;
&lt;p&gt;Step back from the seven pillars and look at what they have in common. Context, integrations, governed actions, deterministic policy, audit, review, approval. None of those are new problems that AI agents invented. They&amp;rsquo;re the problems infrastructure-as-code has been quietly solving for a decade, for human developers.&lt;/p&gt;
&lt;p&gt;Every meaningful agent action ends up being a change, whether that&amp;rsquo;s to infrastructure, configuration, secrets, or state. IaC is the one layer in your stack that already treats change as the unit of work. Plan, preview, apply, record. If you want governance for agents and you don&amp;rsquo;t want to build it twice, the most efficient move is to route agent changes through the same substrate your humans already use.&lt;/p&gt;
&lt;p&gt;I made the same point from a different angle in &lt;a href="https://www.pulumi.com/blog/token-efficiency-vs-cognitive-efficiency-choosing-iac-for-ai-agents/"&gt;&lt;em&gt;Token Efficiency vs Cognitive Efficiency: Choosing IaC for AI Agents&lt;/em&gt;&lt;/a&gt;. An IaC platform that models your world as a graph of typed resources is a much better reasoning surface for an agent than a stack of YAML or a bash script somebody wrote on a Friday. The structure is what makes it work.&lt;/p&gt;
&lt;h2 id="what-this-means-for-the-platform-engineer"&gt;What this means for the platform engineer&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s a narrative floating around that AI is going to make platform engineers less relevant. I haven&amp;rsquo;t seen it hold up against an actual production environment. Every stat I&amp;rsquo;ve looked at points the other way. Gartner expects &lt;a href="https://www.itential.com/resource/analyst-report/gartner-predicts-2026-ai-agents-will-reshape-infrastructure-operations/"&gt;70% of enterprises to deploy agentic AI as part of IT infrastructure and operations by 2029, up from less than 5% in 2025&lt;/a&gt;. LangChain&amp;rsquo;s &lt;a href="https://www.langchain.com/state-of-agent-engineering"&gt;State of Agent Engineering report already has 57% of teams running agents in production today&lt;/a&gt;. And Gartner projects that &lt;a href="https://deviniti.com/blog/leadership-teamwork/40-devops-stats-for-2026/"&gt;80% of large software engineering orgs will have a platform team by end of 2026, up from 45% in 2022&lt;/a&gt;. More agents means more changes, more changes means more blast radius, and more blast radius means more need for the thing platform teams are uniquely equipped to provide.&lt;/p&gt;
&lt;p&gt;Your classic responsibilities haven&amp;rsquo;t gone anywhere either. Golden paths, service catalogs, CI/CD, on-call rotations, all of that is still yours. Agents are an additional layer that needs the same discipline. The upside is that if your platform already runs on a mature IaC surface, you&amp;rsquo;re extending a muscle you&amp;rsquo;ve been building for years instead of growing a new one.&lt;/p&gt;
&lt;p&gt;The developer-facing side matters too. A developer building an agent needs to know what&amp;rsquo;s available to them, needs templates that work on the first try, and needs to see what teammates have already built so they don&amp;rsquo;t start from a blank page. That&amp;rsquo;s the territory &lt;a href="https://www.pulumi.com/blog/top-8-claude-skills-devops-2026/"&gt;the Claude skills post&lt;/a&gt; and &lt;a href="https://www.pulumi.com/blog/idp-strategy-planning-self-service-infrastructure-that-balances-developer-autonomy-with-operational-control/"&gt;&lt;em&gt;IDP Strategy: Self-Service Infrastructure That Balances Autonomy With Control&lt;/em&gt;&lt;/a&gt; cover. That&amp;rsquo;s the experience layer that makes developers actually choose your platform instead of routing around it. You need both sides working at once. The governance your security team cares about, and the experience your developers will actually reach for.&lt;/p&gt;
&lt;h2 id="close-the-window"&gt;Close the window&lt;/h2&gt;
&lt;p&gt;The agents your developers are shipping this week are going to outlive the experiment that started them. Some of them will become critical. At least one will cause an incident. At least one will eventually show up in an audit. All of them are going to be easier to govern if they were built on your platform from day one than if you try to wrap policy around them later.&lt;/p&gt;
&lt;p&gt;If you want the longer view on where this is going, &lt;a href="https://www.pulumi.com/blog/ai-predictions-2026-devops-guide/"&gt;&lt;em&gt;AI Predictions for 2026: A DevOps Engineer&amp;rsquo;s Guide&lt;/em&gt;&lt;/a&gt; is the companion piece. If you want the developer-facing version of the grounding argument, &lt;a href="https://www.pulumi.com/blog/grounded-ai-why-neo-knows-your-infrastructure/"&gt;&lt;em&gt;Grounded AI&lt;/em&gt;&lt;/a&gt; is what to read next.&lt;/p&gt;
&lt;p&gt;Either way, here&amp;rsquo;s where I land. The substrate for agent governance is already running in your stack. You&amp;rsquo;ve been pointing it at human changes for years. Now point it at the agents too.&lt;/p&gt;
&lt;a
href="https://www.pulumi.com/product/neo/"
class="btn btn-primary"
&gt;
See how Pulumi Neo governs agent actions
&lt;/a&gt;</description><author>Engin Diri</author><category>ai</category><category>ai-agents</category><category>platform-engineering</category><category>devops</category><category>infrastructure-as-code</category></item><item><title>KubeCon EU 2026 Recap: The Year AI Moved Into Production on Kubernetes</title><link>https://www.pulumi.com/blog/kubecon-eu-2026-recap/</link><pubDate>Wed, 01 Apr 2026 00:00:00 -0700</pubDate><guid>https://www.pulumi.com/blog/kubecon-eu-2026-recap/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/kubecon-eu-2026-recap/index.png" /&gt;
&lt;p&gt;Amsterdam in late March still has that sharp North Sea wind, but inside the RAI Convention Centre, 13,350 people generated enough energy to heat the building twice over. &lt;a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-europe-2026/"&gt;KubeCon + CloudNativeCon EU 2026&lt;/a&gt; was the biggest European edition yet, and the shift from previous years was impossible to miss. AI dominated the conference.&lt;/p&gt;
&lt;p&gt;I spent most of the conference at the Pulumi booth, and that turned out to be the best vantage point. Hundreds of visitors stopped by over four days, and I kept asking the same question: what are you actually running in production with AI on Kubernetes? The answers shaped this post more than any keynote did. Almost everyone had a proof of concept. Almost nobody had a production story they were happy with.&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi-booth.jpg" alt="The Pulumi crew at our booth at KubeCon EU 2026 in Amsterdam"&gt;&lt;/p&gt;
&lt;p&gt;Here is the stat that framed the entire conference for me: &lt;a href="https://www.cncf.io/reports/the-cncf-annual-cloud-native-survey/"&gt;66% of organizations use Kubernetes to host generative AI workloads, but only 7% deploy to production daily&lt;/a&gt;. That gap between experimentation and actual production use matched what I was hearing at the booth. The CNCF&amp;rsquo;s own survey now counts &lt;a href="https://www.cncf.io/reports/state-of-cloud-native-development-q1-2026/"&gt;19.9 million cloud native developers worldwide, 7.3 million of them building AI workloads&lt;/a&gt;. The tooling and the infrastructure need to catch up.&lt;/p&gt;
&lt;p&gt;My takeaway after four days on the ground: lots of working demos, very few production setups people trust. Teams are trying to scale inference, put guardrails around agents, and make GPU infrastructure behave like anything else they run.&lt;/p&gt;
&lt;p&gt;Here is what I saw.&lt;/p&gt;
&lt;h2 id="from-training-to-inference-the-big-pivot"&gt;From training to inference: the big pivot&lt;/h2&gt;
&lt;p&gt;About &lt;a href="https://www.deloitte.com/us/en/insights/industry/technology/technology-media-and-telecom-predictions/2026/compute-power-ai.html"&gt;67% of AI compute now goes to inference&lt;/a&gt;, not training. The inference market is projected to hit &lt;a href="https://www.marketsandmarkets.com/Market-Reports/ai-inference-market-189921964.html"&gt;$255 billion by 2030&lt;/a&gt;. It&amp;rsquo;s also where most of the operational complexity lives.&lt;/p&gt;
&lt;p&gt;NVIDIA leaned into this hard. Their open-source stack around &lt;a href="https://github.com/NVIDIA-NeMo/NeMo"&gt;NeMo&lt;/a&gt; and &lt;a href="https://github.com/ai-dynamo/dynamo"&gt;Dynamo&lt;/a&gt; got significant stage time, but the bigger move was donating three projects to the CNCF: the &lt;a href="https://github.com/NVIDIA/k8s-dra-driver-gpu"&gt;DRA driver&lt;/a&gt; for fractional GPU allocation, the &lt;a href="https://github.com/kai-scheduler/KAI-Scheduler"&gt;KAI Scheduler&lt;/a&gt; for GPU-aware scheduling, and &lt;a href="https://github.com/ai-dynamo/grove"&gt;Grove&lt;/a&gt;. Moving these to community governance signals that GPU infra is becoming part of the standard Kubernetes toolkit.&lt;/p&gt;
&lt;h2 id="the-cncf-donations-that-will-reshape-ai-on-kubernetes"&gt;The CNCF donations that will reshape AI on Kubernetes&lt;/h2&gt;
&lt;p&gt;Every KubeCon has its crop of new CNCF projects, but this year&amp;rsquo;s batch felt different. We are starting to see the building blocks of an AI runtime for Kubernetes.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/llm-d/llm-d"&gt;&lt;strong&gt;llm-d&lt;/strong&gt;&lt;/a&gt; was the headline donation. Created by IBM Research, Red Hat, and Google Cloud, it splits inference workloads by separating prefill and decode phases across different pods. The collaborator list reads like an industry consortium: NVIDIA, CoreWeave, AMD, Cisco, Hugging Face, Intel, Lambda, Mistral AI, UC Berkeley, and UChicago. When that many organizations agree on a single approach to distributed inference, pay attention.&lt;/p&gt;
&lt;p&gt;NVIDIA&amp;rsquo;s &lt;a href="https://github.com/NVIDIA/k8s-dra-driver-gpu"&gt;&lt;strong&gt;DRA driver&lt;/strong&gt;&lt;/a&gt; enables fractional GPU allocation and multi-node NVLink support. GPU multi-tenancy is one of the hardest unsolved problems in Kubernetes right now. Scheduling, isolation, cost attribution — all of it breaks down when multiple workloads share a GPU. The DRA driver does not solve everything, but it gives the community a real starting point.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/kai-scheduler/KAI-Scheduler"&gt;&lt;strong&gt;KAI Scheduler&lt;/strong&gt;&lt;/a&gt; entered the CNCF Sandbox for GPU-aware scheduling. If llm-d handles the inference runtime and the DRA driver handles allocation, KAI Scheduler handles placement. Together, these three projects form the skeleton of a GPU-native Kubernetes stack.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/vmware-tanzu/velero"&gt;&lt;strong&gt;Velero&lt;/strong&gt;&lt;/a&gt;, donated by Broadcom, moved into CNCF Sandbox for backup and restore. AI workloads are stateful now (model weights, checkpoints, fine-tuning data), and backup is no longer optional. Good timing.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/kaito-project/airunway"&gt;&lt;strong&gt;Microsoft AI Runway&lt;/strong&gt;&lt;/a&gt; is an open-source Kubernetes API for inference that plugs in Hugging Face model discovery, GPU memory fit calculations, and cost estimates. Think of it as a model-aware control plane. &lt;a href="https://github.com/HolmesGPT/holmesgpt"&gt;&lt;strong&gt;HolmesGPT&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://github.com/project-dalec/dalec"&gt;&lt;strong&gt;Dalec&lt;/strong&gt;&lt;/a&gt;, also from Microsoft, entered CNCF Sandbox for AI-powered troubleshooting and dependency analysis.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Kubernetes AI Conformance Program&lt;/strong&gt; is growing fast, with certifications nearly doubled and three new requirements proposed for Kubernetes 1.36. Conformance programs are boring until they are not. This one will determine which distributions can credibly claim AI readiness.&lt;/p&gt;
&lt;h2 id="agentic-ai-gets-an-identity-layer"&gt;Agentic AI gets an identity layer&lt;/h2&gt;
&lt;p&gt;If inference was this year&amp;rsquo;s production story, agentic AI was the architecture story. Agents are proliferating, and nobody has quite figured out how to manage and secure them inside Kubernetes yet.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/kagent-dev/kagent"&gt;&lt;strong&gt;kagent&lt;/strong&gt;&lt;/a&gt;, donated to CNCF Sandbox by Solo.io, defines agents as Kubernetes CRDs. It ships with pre-built &lt;a href="https://github.com/modelcontextprotocol/modelcontextprotocol"&gt;MCP&lt;/a&gt; (Model Context Protocol) servers for Kubernetes, Istio, Helm, Argo, Prometheus, Grafana, and Cilium. An agent becomes a first-class Kubernetes resource, schedulable and observable and subject to RBAC, instead of a rogue process running in someone&amp;rsquo;s notebook.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/kagenti/kagenti"&gt;&lt;strong&gt;kagenti&lt;/strong&gt;&lt;/a&gt; from IBM goes after the identity problem directly. Using &lt;a href="https://github.com/spiffe/spire"&gt;SPIFFE/SPIRE&lt;/a&gt;, it gives agents cryptographic identities. When an agent calls an API, you can verify exactly which agent made the call, what trust domain it belongs to, and whether it is authorized. This kind of security work needs to happen before agents proliferate across production clusters. Retrofitting identity later is ugly.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dapr/dapr-agents"&gt;&lt;strong&gt;Dapr Agents&lt;/strong&gt;&lt;/a&gt; took a different angle with the actor model and durable execution. Each agent gets reliable state management and exactly-once messaging semantics. If your workflows cannot tolerate lost messages or duplicate actions, this matters.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/agentregistry-dev/agentregistry"&gt;&lt;strong&gt;agentregistry&lt;/strong&gt;&lt;/a&gt; showed up as a centralized discovery service for MCP servers and agents. As agents and tool servers multiply, you need a registry to find and manage them, the same way container registries became necessary for images.&lt;/p&gt;
&lt;p&gt;David Soria Parra from Anthropic gave a talk on &lt;a href="https://blog.modelcontextprotocol.io/posts/2026-mcp-roadmap/"&gt;MCP evolving beyond simple tool-calling&lt;/a&gt; into richer interaction patterns (&lt;a href="https://colocatedeventseu2026.sched.com/event/2E7Db/agentics-day-mcp-+-agents-mcp-in-2026-context-is-all-you-need-david-soria-parra-anthropic"&gt;sched&lt;/a&gt;). Google announced the &lt;a href="https://github.com/kubernetes-sigs/agent-sandbox"&gt;&lt;strong&gt;Kubernetes Agent Sandbox&lt;/strong&gt;&lt;/a&gt; for running agentic AI workloads in secure, isolated environments — we&amp;rsquo;ve since published a full &lt;a href="https://www.pulumi.com/blog/kubernetes-agent-sandbox/"&gt;walkthrough of what it is and how to deploy it&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="ai-gateways-and-inference-routing"&gt;AI gateways and inference routing&lt;/h2&gt;
&lt;p&gt;Gateway infrastructure had its own mini-conference within KubeCon. The &lt;a href="https://github.com/kubernetes-sigs/gateway-api-inference-extension"&gt;Gateway API Inference Extension&lt;/a&gt; from the Kubernetes SIG introduces model-aware routing and load balancing at the gateway level. Instead of routing by URL path, your gateway routes by model name, version, and capacity. That changes how inference traffic flows through a cluster in a fundamental way.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/envoyproxy/ai-gateway"&gt;&lt;strong&gt;Envoy AI Gateway&lt;/strong&gt;&lt;/a&gt; builds on &lt;a href="https://github.com/envoyproxy/envoy"&gt;Envoy&lt;/a&gt;&amp;rsquo;s existing proxy capabilities with token-aware rate limiting and provider failover. If your primary inference provider is saturated, traffic shifts to a secondary automatically. Rate limiting by token count rather than request count makes much more sense for LLM workloads, where a single request can consume vastly different amounts of compute.&lt;/p&gt;
&lt;p&gt;I want to call out &lt;a href="https://github.com/agentgateway/agentgateway"&gt;&lt;strong&gt;Agentgateway&lt;/strong&gt;&lt;/a&gt; specifically. Written in Rust, it proxies LLM traffic, MCP connections, and agent-to-agent communication, with &lt;a href="https://github.com/cedar-policy/cedar"&gt;Cedar&lt;/a&gt; and &lt;a href="https://github.com/google/cel-spec"&gt;CEL&lt;/a&gt; policy engines for fine-grained access control. Rust&amp;rsquo;s performance characteristics matter here because inference gateway latency adds directly to user-perceived response time.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Kuadrant/kuadrant-operator"&gt;&lt;strong&gt;Kuadrant&lt;/strong&gt;&lt;/a&gt;, now in CNCF Sandbox, layers policy on top of gateway infrastructure and includes MCP server aggregation. Gateways are evolving from dumb traffic proxies into intelligent control planes for AI workloads, and these four projects are driving that shift.&lt;/p&gt;
&lt;h2 id="platform-engineering-absorbs-llmops"&gt;Platform engineering absorbs LLMOps&lt;/h2&gt;
&lt;p&gt;The observability and platform engineering vendors showed up in force. The message was consistent: LLMOps is just platform engineering with new requirements.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Chronosphere&lt;/strong&gt; demonstrated parallel AI investigation, with multiple agents analyzing different aspects of an incident simultaneously and combining their findings. &lt;strong&gt;SUSE Liz&lt;/strong&gt; takes a domain-specialized approach, deploying different AI agents for different operational domains rather than one general-purpose assistant. &lt;strong&gt;groundcover&lt;/strong&gt; combines eBPF with &lt;a href="https://opentelemetry.io/"&gt;OpenTelemetry&lt;/a&gt; to give coding agents rich runtime context about the systems they are modifying. That last one is subtle but important: if an AI agent is writing code that touches a service, it should understand that service&amp;rsquo;s actual runtime behavior, not just its source code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dynatrace&lt;/strong&gt; and &lt;strong&gt;DevCycle&lt;/strong&gt; partnered to make feature flags observable primitives via &lt;a href="https://github.com/open-feature/spec"&gt;OpenFeature&lt;/a&gt;. Rolling out AI features behind feature flags is table stakes, but having those flags show up in your observability pipeline as first-class signals closes a real gap.&lt;/p&gt;
&lt;p&gt;Shadow AI governance emerged as its own theme. &lt;strong&gt;CAST AI&amp;rsquo;s Kimchi&lt;/strong&gt; can route requests across 50+ models while providing centralized visibility into what models are being used, by whom, and at what cost. Every large organization I talked to had some version of the same problem: teams spinning up model endpoints without central oversight, burning through GPU budgets, creating compliance blind spots they did not even know about.&lt;/p&gt;
&lt;p&gt;GPU multi-tenancy remains genuinely unsolved. Scheduling, workload isolation, cost attribution across shared GPUs — all of it breaks down at scale. Multiple talks addressed pieces of this, but nobody had a complete answer.&lt;/p&gt;
&lt;h2 id="sovereignty-shapes-infrastructure-architecture"&gt;Sovereignty shapes infrastructure architecture&lt;/h2&gt;
&lt;p&gt;Regulation came up in almost every conversation. The EU Cyber Resilience Act is driving compliance requirements deep into software supply chains, and every European organization I spoke with is feeling the pressure. Teams are already changing how they build and deploy software.&lt;/p&gt;
&lt;p&gt;Sovereign Kubernetes is a platform architecture requirement now, not something you can defer to next quarter. Organizations need Kubernetes distributions and cloud regions that guarantee data residency, and they need the tooling to enforce those guarantees programmatically. Self-hosted models are proliferating partly because of capability and cost, but data sovereignty is the accelerant. If your data cannot leave a jurisdiction, neither can your model.&lt;/p&gt;
&lt;p&gt;Runtime isolation is expanding beyond containers. Several talks covered KVM-based isolation for AI workloads, which is heavier than containers but necessary when the threat model includes side-channel attacks on shared GPU memory. The sandboxing conversation has gotten more sophisticated since last year.&lt;/p&gt;
&lt;p&gt;These constraints are not uniquely European. Any organization operating across jurisdictions faces similar pressures, and the regulatory direction globally is toward more data sovereignty requirements, not fewer.&lt;/p&gt;
&lt;p&gt;&lt;img src="showroom.jpg" alt="The KubeCon EU 2026 show floor at the RAI Convention Centre in Amsterdam"&gt;&lt;/p&gt;
&lt;h2 id="what-this-means-for-your-team"&gt;What this means for your team&lt;/h2&gt;
&lt;p&gt;Four days in Amsterdam distilled into five things I would act on now:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Treat inference workloads like production services.&lt;/strong&gt; If you are still deploying models with scripts and hope, stop. Inference infrastructure needs the same IaC discipline as any other production system: version-controlled, tested, policy-enforced.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Evaluate the &lt;a href="https://github.com/kubernetes-sigs/gateway-api-inference-extension"&gt;Gateway API Inference Extension&lt;/a&gt; and &lt;a href="https://github.com/llm-d/llm-d"&gt;llm-d&lt;/a&gt;.&lt;/strong&gt; These are not speculative projects. They have broad industry backing and solve real problems around inference routing and distributed serving. Get them into your test environments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Plan agent identity before agents proliferate.&lt;/strong&gt; &lt;a href="https://github.com/spiffe/spire"&gt;SPIFFE/SPIRE&lt;/a&gt; for agent identity is not optional if you are running agents in production. Retrofitting identity onto an existing agent fleet is painful. Start with &lt;a href="https://github.com/kagenti/kagenti"&gt;kagenti&lt;/a&gt; now.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Platform teams should own AI infrastructure.&lt;/strong&gt; Shadow AI is already happening in your organization. The platform engineering team needs to provide self-service AI infrastructure with guardrails before ungoverned model endpoints become a security and cost problem.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sovereignty and GPU multi-tenancy are universal.&lt;/strong&gt; Even if you are not subject to the EU Cyber Resilience Act today, data residency requirements are spreading globally. GPU multi-tenancy will affect every organization running inference at scale.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Kubernetes spent the past decade proving it could orchestrate containers. The next decade will test whether it can orchestrate intelligence. Based on what I saw in Amsterdam, the community is building the right pieces, but the gap between what exists and what production demands is still wide. That gap is where the interesting work happens.&lt;/p&gt;</description><author>Engin Diri</author><category>kubernetes</category><category>kubecon</category><category>ai</category><category>platform-engineering</category><category>cloud-native</category></item><item><title>Registry usage insights: know which stacks run which versions</title><link>https://www.pulumi.com/blog/registry-usage-insights/</link><pubDate>Thu, 12 Feb 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/registry-usage-insights/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/registry-usage-insights/index.png" /&gt;
&lt;p&gt;Platform teams need visibility into package adoption at scale. Responding to security advisories, planning deprecations, and tracking version sprawl all require knowing which stacks run which package versions across your organization.&lt;/p&gt;
&lt;h2 id="from-individual-to-organizational-visibility"&gt;From Individual to Organizational Visibility&lt;/h2&gt;
&lt;p&gt;Previously, we &lt;a href="https://www.pulumi.com/blog/announcing-pulumi-private-registry/"&gt;introduced the &amp;ldquo;Used by&amp;rdquo; tab&lt;/a&gt; on individual package pages, giving you visibility into which stacks use a specific package. However, navigating package by package doesn&amp;rsquo;t scale when you&amp;rsquo;re managing dozens of packages across hundreds of stacks.&lt;/p&gt;
&lt;p&gt;Today, we&amp;rsquo;re extending that visibility to the organization level. You can now see adoption data for all packages at a glance, filter by usage status, and share specific views with your team.&lt;/p&gt;
&lt;h2 id="what-you-can-see"&gt;What You Can See&lt;/h2&gt;
&lt;p&gt;&lt;img src="usage-columns.png" alt="Package list showing usage columns"&gt;&lt;/p&gt;
&lt;p&gt;The package list now displays three usage columns for each package:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Stacks on latest&lt;/strong&gt;: the number of stacks running the latest version&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not on latest&lt;/strong&gt;: the number of stacks running older versions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total&lt;/strong&gt;: all stacks using any version of the package&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These numbers update as stacks are deployed, giving you a real-time view of adoption across your organization.&lt;/p&gt;
&lt;h2 id="find-what-matters-with-filters"&gt;Find What Matters with Filters&lt;/h2&gt;
&lt;p&gt;&lt;img src="filter-dropdown.png" alt="Filter dropdown"&gt;&lt;/p&gt;
&lt;p&gt;Three filters help you find packages that need attention:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Used&lt;/strong&gt;: packages with at least one stack&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unused&lt;/strong&gt;: packages with zero usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not on latest&lt;/strong&gt;: packages where stacks are running older versions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Combine filters with search to find specific packages.&lt;/p&gt;
&lt;h2 id="browse-all-packages-in-one-place"&gt;Browse All Packages in One Place&lt;/h2&gt;
&lt;p&gt;&lt;img src="registry-tab.png" alt="Registry tab"&gt;&lt;/p&gt;
&lt;p&gt;The new &lt;strong&gt;Registry&lt;/strong&gt; tab under Platform shows all packages available to your organization, including public providers and components from &lt;a href="https://www.pulumi.com/registry/"&gt;pulumi.com/registry&lt;/a&gt; alongside your organization&amp;rsquo;s private packages. The &lt;strong&gt;Private Components&lt;/strong&gt; tab (previously called Components) now includes the same usage columns and filters.&lt;/p&gt;
&lt;h2 id="share-specific-views"&gt;Share Specific Views&lt;/h2&gt;
&lt;p&gt;Search queries, filters, and pagination sync to the URL. Copy the URL to share a specific view with your team, or bookmark it for quick access to your regular monitoring workflow.&lt;/p&gt;
&lt;h2 id="why-this-matters"&gt;Why This Matters&lt;/h2&gt;
&lt;p&gt;These features are designed for the scenarios platform teams face regularly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Security response&lt;/strong&gt;: filter to &amp;ldquo;Not on latest&amp;rdquo; to identify stacks running vulnerable versions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deprecation planning&lt;/strong&gt;: before retiring a package, check its usage to understand the migration scope&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Version sprawl&lt;/strong&gt;: identify packages where teams are running many different versions and prioritize standardization efforts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Adoption tracking&lt;/strong&gt;: see which packages are gaining traction and which aren&amp;rsquo;t being adopted&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="get-started"&gt;Get Started&lt;/h2&gt;
&lt;p&gt;Navigate to &lt;strong&gt;Platform &amp;gt; Registry&lt;/strong&gt; in Pulumi Cloud to explore your organization&amp;rsquo;s packages with the new usage columns and filters. For more details on the private registry features, see the &lt;a href="https://www.pulumi.com/docs/idp/concepts/private-registry/"&gt;Private Registry documentation&lt;/a&gt;.&lt;/p&gt;</description><author>Pulumi IDP Team</author><category>internal-developer-platform</category><category>features</category><category>platform-engineering</category><category>pulumi-cloud</category></item><item><title>The Claude Skills I Actually Use for DevOps</title><link>https://www.pulumi.com/blog/top-8-claude-skills-devops-2026/</link><pubDate>Mon, 09 Feb 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/top-8-claude-skills-devops-2026/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/top-8-claude-skills-devops-2026/index.png" /&gt;
&lt;p&gt;When Claude Code first released &lt;a href="https://docs.anthropic.com/en/docs/claude-code/skills"&gt;skills&lt;/a&gt;, I ignored them. They looked like fancy prompts, another feature to add to the pile of things I would get around to learning eventually. Then I watched a few engineers demonstrate what skills actually do, and something clicked. By default, language models do not write good code. They write plausible code based on what they have read. Plausible code turns into bugs, horrible UX, and infrastructure that breaks at 3am.&lt;/p&gt;
&lt;p&gt;Skills fill that gap. They package engineering expertise into something Claude can use. The workflows and judgment matter more than the raw information. Without skills, every conversation starts from zero. You explain the same conventions and correct the same mistakes. Every morning, back to zero.&lt;/p&gt;
&lt;p&gt;Think about what separates a junior engineer from a senior one. Both can write code that compiles. Both can deploy infrastructure that runs. The difference is that the senior engineer knows the patterns that prevent problems before they happen. They know when to use component resources instead of plain resources. They know that creating infrastructure inside an &lt;code&gt;apply()&lt;/code&gt; callback (Pulumi&amp;rsquo;s way of transforming outputs that are not known until deployment) breaks preview. They know that hardcoded credentials will eventually end up in a git log somewhere embarrassing.&lt;/p&gt;
&lt;p&gt;This knowledge takes years to accumulate through painful experience. Skills let you transfer that knowledge to Claude in minutes. And here is the thing that makes them practical: if you find yourself doing the same type of task with different content each time, that is a skill waiting to be built. You encode the process once, then feed it new inputs forever.&lt;/p&gt;
&lt;h2 id="the-mechanic-the-tools-and-the-manual"&gt;The mechanic, the tools, and the manual&lt;/h2&gt;
&lt;p&gt;I heard an analogy recently that made skills click for me. Imagine Claude as a mechanic. A capable mechanic who knows engines, can diagnose problems, and fix most cars that come through the shop.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://modelcontextprotocol.io/"&gt;MCP servers&lt;/a&gt; are like giving that mechanic a set of tools. Wrenches, diagnostic equipment, lift systems. Without tools, the mechanic cannot do much. With tools, the mechanic can work on whatever comes through the door.&lt;/p&gt;
&lt;p&gt;But what happens when someone brings in a Formula 1 race car? Or a 1967 Ford Mustang that has been modified beyond recognition? The mechanic knows engines in general, but these specific vehicles require specific knowledge. The F1 car has procedures that must be followed in exact order. The vintage Mustang has quirks that only someone who has worked on that model would know.&lt;/p&gt;
&lt;p&gt;Skills are the user manuals and standard operating procedures for these specific vehicles. They tell the mechanic what needs to happen and when. They encode the expertise of someone who has done this work a thousand times.&lt;/p&gt;
&lt;p&gt;Or think about it from a carpenter&amp;rsquo;s perspective. Skills are the process to make the table: the measurements, the design, the exact steps. MCPs are the tools: the saw, the hammer, the drill. You need both. The process alone is theoretical, and tools without a process just sit in the garage.&lt;/p&gt;
&lt;p&gt;For DevOps engineers working with Pulumi, this matters because infrastructure as code has its own quirks and patterns. Generic AI assistance produces code that looks reasonable but breaks conventions the community learned the hard way. Skills teach Claude those conventions.&lt;/p&gt;
&lt;h2 id="why-skills-instead-of-mcps"&gt;Why skills instead of MCPs&lt;/h2&gt;
&lt;p&gt;Before skills clicked for me, I tried solving the expertise problem with MCPs. I kept adding servers until I noticed Claude getting slower and making worse decisions. Turns out the GitHub MCP alone &lt;a href="https://smcleod.net/2025/08/stop-polluting-context-let-users-disable-individual-mcp-tools/"&gt;eats 46,000 tokens across 91 tools&lt;/a&gt; before you type anything. Cursor eventually &lt;a href="https://demiliani.com/2025/09/04/model-context-protocol-and-the-too-many-tools-problem/"&gt;capped MCPs at 40 tools&lt;/a&gt; because &lt;a href="https://jentic.com/blog/the-mcp-tool-trap"&gt;too many options made everything worse&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Slash commands were another option, but you had to remember to invoke them. Anthropic apparently agreed, because in January 2026 they &lt;a href="https://medium.com/@asher-at-plato/why-did-anthropic-merge-slash-commands-into-skills-4bf6464c96ca"&gt;merged slash commands into skills&lt;/a&gt;. One unified system instead of two.&lt;/p&gt;
&lt;p&gt;Skills avoid this through progressive disclosure. Claude reads just the description at startup, maybe a hundred tokens. The full procedures only load when Claude decides they are relevant. Unlike those massive system prompts that used to eat through your context window, skills stay out of the way until they are needed. For DevOps engineers running long infrastructure sessions with dozens of resources, this matters. You keep your context budget for the actual work instead of burning it on instructions. Skills can also fork context, spinning up isolated subagents that do work without polluting your main conversation. Think of it like handing a colleague a written brief. They go work on it, hand back a summary, and never sit in on your conversation.&lt;/p&gt;
&lt;p&gt;I still use MCPs for connecting Claude to external systems. The &lt;a href="https://www.pulumi.com/blog/mcp-server-ai-assistants/"&gt;Pulumi MCP server&lt;/a&gt; lets Claude query the registry and validate code. But MCPs give Claude access to things. Skills teach Claude how to think about things. Different jobs. They get more useful when you combine them. One engineer built a financial reporting skill that connects to his Mercury bank account via MCP, pulls every transaction for a given month, classifies the expenses into categories, and generates a styled HTML report with totals and breakdowns. A skill that knows your deployment process connecting to MCPs that talk to your actual infrastructure is the same idea, just pointed at ops instead of accounting.&lt;/p&gt;
&lt;div class="note note-note"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-pencil-simple-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;Skills are portable. They follow an &lt;a href="https://agentskills.io"&gt;open standard&lt;/a&gt;, so a skill you write for Claude Code works in Cursor, GitHub Copilot, or anywhere else that supports agent skills. You can even copy the skill content into ChatGPT as a starting prompt. No vendor lock-in.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="teaching-claude-to-write-pulumi-like-an-expert"&gt;Teaching Claude to write Pulumi like an expert&lt;/h2&gt;
&lt;p&gt;The first time you ask Claude to help with a Pulumi project, the process is painful. You have to explain the patterns you want. You correct mistakes. You explain why creating resources inside &lt;code&gt;apply()&lt;/code&gt; breaks things. By the third or fourth project, you start copying your corrections from previous conversations.&lt;/p&gt;
&lt;p&gt;I built the &lt;a href="https://github.com/dirien/claude-skills"&gt;dirien/claude-skills&lt;/a&gt; &lt;code&gt;pulumi-typescript&lt;/code&gt; skill after going through this painful process too many times. It knows the patterns that prevent common mistakes: &lt;a href="https://www.pulumi.com/blog/pulumi-esc-ga/"&gt;Pulumi ESC (Environments, Secrets, and Configuration)&lt;/a&gt; integration, &lt;a href="https://www.pulumi.com/blog/oidc-trust-relationships/"&gt;OIDC (OpenID Connect) instead of hardcoded access keys&lt;/a&gt;, ComponentResource abstractions (reusable groups of related resources), and proper output structuring so dependent stacks can consume them cleanly.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it teaches Claude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pulumi-typescript&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pulumi with TypeScript, ESC secrets management, component patterns, and multi-cloud deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/dirien/claude-skills --skill pulumi-typescript
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Skills install as markdown files in your project&amp;rsquo;s &lt;code&gt;.claude/skills/&lt;/code&gt; directory, so they travel with your repo and are easy to review.&lt;/p&gt;
&lt;p&gt;The next time you ask Claude to create infrastructure, it applies these patterns automatically. You do not have to remember to invoke the skill or correct the same mistakes repeatedly.&lt;/p&gt;
&lt;h2 id="the-official-pulumi-skills"&gt;The official Pulumi skills&lt;/h2&gt;
&lt;p&gt;Pulumi maintains its own skills repository at &lt;a href="https://github.com/pulumi/agent-skills"&gt;pulumi/agent-skills&lt;/a&gt;, which they &lt;a href="https://www.pulumi.com/blog/pulumi-agent-skills/"&gt;announced recently&lt;/a&gt;. The repo includes skills for ComponentResource patterns, Automation API, and migration from Terraform, CDK, CloudFormation, and ARM. The two I use daily are &lt;code&gt;pulumi-esc&lt;/code&gt; and &lt;code&gt;pulumi-best-practices&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;pulumi-esc&lt;/code&gt; skill teaches Claude how to work with &lt;a href="https://www.pulumi.com/product/esc/"&gt;Pulumi ESC (Environments, Secrets, and Configuration)&lt;/a&gt;. It knows the difference between &lt;code&gt;pulumi env get&lt;/code&gt;, &lt;code&gt;pulumi env open&lt;/code&gt;, and &lt;code&gt;pulumi env run&lt;/code&gt;. It sets up OIDC for dynamic credentials, integrates with external secret stores like AWS Secrets Manager and Vault, and structures layered environment composition so your dev, staging, and production configs inherit from a shared base.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;pulumi-best-practices&lt;/code&gt; skill catches the mistakes that burn you in production. It stops Claude from creating resources inside &lt;code&gt;apply()&lt;/code&gt; callbacks, enforces proper parent relationships in ComponentResources, encrypts secrets from day one, and makes sure &lt;code&gt;pulumi preview&lt;/code&gt; runs before any deployment. These are the patterns that took me years to internalize, and now Claude follows them by default.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it teaches Claude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pulumi-esc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Environment, secrets, and configuration management with OIDC, dynamic credentials, and secret store integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pulumi-best-practices&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Resource dependencies, ComponentResource patterns, secret encryption, and safe refactoring&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/pulumi/agent-skills --skill pulumi-esc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/pulumi/agent-skills --skill pulumi-best-practices
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="making-claude-a-monitoring-expert-by-default"&gt;Making Claude a monitoring expert by default&lt;/h2&gt;
&lt;p&gt;You deploy something, it works, and six months later something breaks and you realize you never added monitoring. We have all been there. The monitoring skills from the community teach Claude to add observability from the start.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/jeffallan/claude-skills"&gt;jeffallan/claude-skills&lt;/a&gt; repository contains a &lt;code&gt;monitoring-expert&lt;/code&gt; skill that knows Prometheus, Grafana, and DataDog.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it teaches Claude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;monitoring-expert&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Structured logging, metrics, distributed tracing, alerting, and performance testing for production systems&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/jeffallan/claude-skills --skill monitoring-expert
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In my testing, deploying a static website with these skills installed looks different from vanilla Claude. Instead of just creating the S3 bucket and CloudFront distribution, Claude asked about error rate thresholds before writing any code. It suggested CloudWatch alarms and created an SNS topic for alerts. The results are not always this clean. Sometimes the monitoring suggestions are generic or miss your specific SLO requirements. But the baseline shifted from &amp;ldquo;no monitoring at all&amp;rdquo; to &amp;ldquo;monitoring that needs tuning,&amp;rdquo; and that is a better starting point.&lt;/p&gt;
&lt;h2 id="kubernetes-configuration-that-actually-passes-security-review"&gt;Kubernetes configuration that actually passes security review&lt;/h2&gt;
&lt;p&gt;Kubernetes has hundreds of configuration options. Most deployments use a handful of them. The problem is that the important options like security contexts, resource limits, and pod disruption budgets are easy to forget when you are focused on getting something to run.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/jeffallan/claude-skills"&gt;jeffallan/claude-skills&lt;/a&gt; &lt;code&gt;kubernetes-specialist&lt;/code&gt; skill focuses on configurations that production deployments actually need. Without it, ask Claude for a deployment and you get something that runs: the right image, the right ports, maybe a service. With the skill, the same request comes back with &lt;code&gt;runAsNonRoot: true&lt;/code&gt; in the security context, resource requests and limits that reflect actual usage patterns, liveness and readiness probes with sensible intervals, and a pod disruption budget. These are the things that make the difference between &amp;ldquo;it works in staging&amp;rdquo; and &amp;ldquo;it survives a node failure in production.&amp;rdquo; The skill also understands when RollingUpdate makes sense versus Recreate, which is the kind of judgment call that usually requires context a generic model does not have.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/wshobson/agents"&gt;wshobson/agents&lt;/a&gt; repository fills in the gaps around Kubernetes with CI/CD, cost management, and deployment workflows:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it teaches Claude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;kubernetes-specialist&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Production cluster management, security hardening, and cloud-native architectures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cost-optimization&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cloud cost reduction across AWS, Azure, and GCP with right-sizing and reserved instances&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;github-actions-templates&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CI/CD workflows, Docker builds, Kubernetes deployments, security scanning, and matrix builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gitops-workflow&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ArgoCD and Flux CD for automated Kubernetes deployments&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/jeffallan/claude-skills --skill kubernetes-specialist
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/wshobson/agents --skill gitops-workflow
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/wshobson/agents --skill github-actions-templates
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/wshobson/agents --skill cost-optimization
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="debugging-like-a-senior-engineer"&gt;Debugging like a senior engineer&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://github.com/obra/superpowers"&gt;obra/superpowers&lt;/a&gt; repository contains a skill that changed how I debug with Claude. The &lt;code&gt;systematic-debugging&lt;/code&gt; skill implements a four-phase framework: root cause investigation, pattern analysis, hypothesis testing, and implementation.&lt;/p&gt;
&lt;p&gt;Without this skill, Claude tends to suggest solutions immediately. Something is broken, here are five things that might fix it. This feels helpful but often wastes time because none of the suggestions address the actual problem.&lt;/p&gt;
&lt;p&gt;With the systematic debugging skill, Claude approaches problems differently. It asks clarifying questions. It wants to see logs. It builds a model of what is happening before suggesting changes. When it proposes a fix, it explains why that fix addresses the root cause. Sometimes skills find problems you did not know about. One engineer pointed a skills-equipped Claude at a set of SEO pages and discovered they had been decaying for months with nobody watching. The infrastructure parallel is obvious: configuration drift, unused resources, permissions that expanded over time. A debugging skill that investigates before prescribing will find these things.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it teaches Claude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;systematic-debugging&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Root cause investigation, pattern analysis, hypothesis testing, and verified implementation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/obra/superpowers --skill systematic-debugging
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="catching-security-issues-before-they-ship"&gt;Catching security issues before they ship&lt;/h2&gt;
&lt;p&gt;Two skills cover different sides of security review. The &lt;a href="https://github.com/wshobson/agents"&gt;wshobson/agents&lt;/a&gt; &lt;code&gt;k8s-security-policies&lt;/code&gt; skill handles Kubernetes-specific hardening: NetworkPolicies, Pod Security Standards, RBAC, OPA Gatekeeper constraints, and service mesh mTLS configuration. The &lt;a href="https://github.com/sickn33/antigravity-awesome-skills"&gt;sickn33/antigravity-awesome-skills&lt;/a&gt; &lt;code&gt;security-review&lt;/code&gt; skill covers application-level concerns like secrets management, SQL injection, XSS prevention, and input validation.&lt;/p&gt;
&lt;p&gt;I asked Claude to check a Pulumi program that created an S3 bucket. Without the security skills, Claude confirmed the code was correct and moved on. With the skills loaded, it flagged that the bucket had no server-side encryption configured, the bucket policy allowed &lt;code&gt;s3:*&lt;/code&gt; from an overly broad principal, and there was no access logging enabled. On the Kubernetes side, the &lt;code&gt;k8s-security-policies&lt;/code&gt; skill catches things like missing default-deny NetworkPolicies and containers running as root. These skills are not a replacement for deterministic tools like tfsec, checkov, or trivy. Those catch known issues every time. Skills are probabilistic and work best as an extra layer during development, not as your only security gate.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it teaches Claude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;k8s-security-policies&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Network policies, pod security standards, RBAC, and admission control for defense-in-depth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;security-review&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Secrets management, input validation, SQL injection, XSS/CSRF prevention, and dependency auditing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/wshobson/agents --skill k8s-security-policies
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/sickn33/antigravity-awesome-skills --skill security-review
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="incident-response-before-you-need-it"&gt;Incident response before you need it&lt;/h2&gt;
&lt;p&gt;At 3am when something breaks, you want runbooks. The &lt;code&gt;incident-runbook-templates&lt;/code&gt; skill from &lt;a href="https://github.com/wshobson/agents"&gt;wshobson/agents&lt;/a&gt; helps Claude create these before you need them. It includes a four-level severity model (SEV1 through SEV4) with response time expectations, escalation decision trees, and communication templates for status updates.&lt;/p&gt;
&lt;p&gt;When you ask Claude to document your deployment process, it produces runbooks with diagnostic steps, rollback protocols, and verification checks. It knows kubectl commands for Kubernetes recovery and SQL procedures for PostgreSQL troubleshooting. The output needs editing. Generated runbooks tend to be thorough on the happy path but thin on the failure modes that matter most at 3am. I treat them as a first draft that gets me to 60% in minutes instead of hours, then fill in the gaps from experience.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it teaches Claude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;incident-runbook-templates&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Detection, triage, mitigation, resolution, and communication procedures for production incidents&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/wshobson/agents --skill incident-runbook-templates
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="general-purpose-devops-and-sre-skills"&gt;General-purpose DevOps and SRE skills&lt;/h2&gt;
&lt;p&gt;The skills above target specific problems. The &lt;a href="https://github.com/jeffallan/claude-skills"&gt;jeffallan/claude-skills&lt;/a&gt; repository also includes two broader skills that cover the day-to-day work that does not fit neatly into one category.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;devops-engineer&lt;/code&gt; skill gives Claude a senior DevOps engineer persona covering CI/CD pipelines, container management, deployment strategies like blue-green and canary, and infrastructure as code across AWS, GCP, and Azure. It enforces constraints I care about: no deploying to production without approval, no secrets in code, no unversioned container images.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;sre-engineer&lt;/code&gt; skill focuses on reliability: SLO/SLI definitions, error budget calculations, golden signal dashboards, and toil reduction through automation. It produces Prometheus/Grafana configs, remediation runbooks, and reliability assessments. If you run production systems and want Claude to think about error budgets instead of just uptime, this is the skill.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it teaches Claude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;devops-engineer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CI/CD pipelines, container management, deployment strategies, and infrastructure as code across clouds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sre-engineer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;SLI/SLO management, error budgets, monitoring, automation, and incident response&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/jeffallan/claude-skills --skill devops-engineer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/jeffallan/claude-skills --skill sre-engineer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="vetting-the-skills-you-install"&gt;Vetting the skills you install&lt;/h2&gt;
&lt;p&gt;Before you install everything in sight, a warning. Skills run with the same permissions as your AI agent. A malicious skill can exfiltrate credentials, download backdoors, or disable safety mechanisms, and it will look like your agent doing it.&lt;/p&gt;
&lt;p&gt;Snyk researchers published &lt;a href="https://snyk.io/blog/toxicskills-malicious-ai-agent-skills-clawhub/"&gt;ToxicSkills&lt;/a&gt; in February 2026 after scanning 3,984 skills from public registries. 13.4% had critical-level vulnerabilities, and they found 76 confirmed malicious payloads. The attack techniques included base64-encoded commands that steal AWS credentials, skills that direct you to download password-protected executables from attacker infrastructure, and jailbreak attempts that try to disable safety mechanisms. 91% of malicious skills combine code-level malware with prompt injection, so they attack on two fronts simultaneously.&lt;/p&gt;
&lt;p&gt;Treat skills like you treat any third-party dependency:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Read the source before installing. Skills are markdown and YAML files. If you cannot read the full skill in a few minutes, that is a red flag.&lt;/li&gt;
&lt;li&gt;Check the repository. Look at stars, contributors, and commit history. A single-commit repository from an unknown account deserves scrutiny.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;uvx mcp-scan@latest --skills&lt;/code&gt; to scan installed skills for known malicious patterns, prompt injection, and credential exposure.&lt;/li&gt;
&lt;li&gt;Be cautious with skills that fetch external content at runtime. The Snyk research found 17.7% of skills on ClawHub pull from third-party URLs, which means the skill&amp;rsquo;s behavior can change after you install it.&lt;/li&gt;
&lt;li&gt;Stick to known repositories. Every skill recommended in this post comes from a repository with visible maintainers and community activity.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Eight malicious skills were still publicly available on ClawHub when Snyk published their findings. The skills ecosystem is young, and the vetting infrastructure is still catching up.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Build infrastructure with agent skills&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Pulumi&amp;rsquo;s Agent Skills teach Claude Code, Cursor, or any coding agent the infrastructure patterns covered here. Install them, then build and deploy your stacks with fewer corrections.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/docs/ai/skills/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="putting-it-together"&gt;Putting it together&lt;/h2&gt;
&lt;p&gt;Stacking skills is where this pays off. Install the Pulumi skills and Claude writes better infrastructure code. Add monitoring and security on top and you start catching problems that used to slip through to production.&lt;/p&gt;
&lt;p&gt;A note on stacking: I have not hit conflicts running all of these simultaneously, but more skills means more descriptions for Claude to evaluate at startup. If you notice Claude getting slower or making odd choices, pare back to the skills you actually use for that project. Start with the Pulumi and monitoring skills, add others as you need them.&lt;/p&gt;
&lt;p&gt;Here is how to set up a new project with all of them:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p pulumi-skills-demo &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; pulumi-skills-demo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi new aws-typescript --name skills-demo --yes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/dirien/claude-skills --skill pulumi-typescript
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/pulumi/agent-skills --skill pulumi-esc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/pulumi/agent-skills --skill pulumi-best-practices
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/obra/superpowers --skill systematic-debugging
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/jeffallan/claude-skills --skill monitoring-expert
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/jeffallan/claude-skills --skill kubernetes-specialist
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/wshobson/agents --skill gitops-workflow
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/wshobson/agents --skill github-actions-templates
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/wshobson/agents --skill cost-optimization
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/wshobson/agents --skill incident-runbook-templates
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/jeffallan/claude-skills --skill devops-engineer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/jeffallan/claude-skills --skill sre-engineer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/wshobson/agents --skill k8s-security-policies
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add https://github.com/sickn33/antigravity-awesome-skills --skill security-review
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then try these two prompts to see how many skills activate at once:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Static website — triggers Pulumi TypeScript, monitoring, and security skills&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Create a Pulumi TypeScript program &lt;span class="k"&gt;for&lt;/span&gt; a static website on AWS with S3, CloudFront, OIDC credentials via Pulumi ESC, CloudWatch monitoring, and /security-review the infrastructure before deploying
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# EKS cluster — stacks Kubernetes, GitOps, incident response, cost, and SRE skills&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Create a Pulumi TypeScript program &lt;span class="k"&gt;for&lt;/span&gt; an EKS cluster with /kubernetes-specialist security hardening, /gitops-workflow &lt;span class="k"&gt;for&lt;/span&gt; ArgoCD deployment, /incident-runbook-templates &lt;span class="k"&gt;for&lt;/span&gt; the cluster, /cost-optimization recommendations, and /sre-engineer SLO definitions &lt;span class="k"&gt;for&lt;/span&gt; the services
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first prompt triggers the Pulumi TypeScript, monitoring, and security review skills in a single conversation. The second stacks Kubernetes, GitOps, incident response, cost, and SRE skills on one cluster build. You get infrastructure code, operational runbooks, and security policies from a single request.&lt;/p&gt;
&lt;h2 id="what-changes"&gt;What changes&lt;/h2&gt;
&lt;p&gt;Fair warning: not every skill works perfectly on the first try. Some need iteration. Some produce output that you have to review and tweak before it matches your standards. Skills do not replace your judgment.&lt;/p&gt;
&lt;p&gt;That said, after a few weeks with these skills installed, I stopped correcting the same mistakes. The code Claude writes now looks like code I would write, not code I would have to fix. That is the whole point. Skills just stop you from repeating the same corrections across every conversation.&lt;/p&gt;
&lt;h2 id="get-started"&gt;Get started&lt;/h2&gt;
&lt;p&gt;Every skill in this post includes its install command. Pick the section that matches your biggest pain point, run the &lt;code&gt;npx skills add&lt;/code&gt; command, and try it on your next task. Skills work in Claude Code, Cursor, GitHub Copilot, and anything else that supports the &lt;a href="https://agentskills.io"&gt;Agent Skills standard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://www.pulumi.com/blog/pulumi-agent-skills/"&gt;Pulumi Agent Skills announcement&lt;/a&gt; has more details, and the &lt;a href="https://github.com/pulumi/agent-skills"&gt;GitHub repository&lt;/a&gt; has the source. If you want something that goes further, with organizational context and deployment governance, look at &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt;. Neo is &lt;a href="https://www.pulumi.com/blog/grounded-ai-why-neo-knows-your-infrastructure/"&gt;grounded in your actual infrastructure&lt;/a&gt;, not internet patterns. The &lt;a href="https://www.pulumi.com/blog/10-things-you-can-do-with-neo/"&gt;10 things you can do with Neo&lt;/a&gt; post shows what that looks like in practice.&lt;/p&gt;
&lt;p&gt;Give it one project. That is all it took for me.&lt;/p&gt;
&lt;a
href="https://www.pulumi.com/docs/get-started/"
class="btn btn-primary"
&gt;
Try Pulumi for Free
&lt;/a&gt;</description><author>Engin Diri</author><category>ai</category><category>devops</category><category>platform-engineering</category><category>claude-code</category><category>ai-agents</category></item><item><title>Pulumi Agent Skills: Best practices and more for AI coding assistants</title><link>https://www.pulumi.com/blog/pulumi-agent-skills/</link><pubDate>Thu, 29 Jan 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/pulumi-agent-skills/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/pulumi-agent-skills/index.png" /&gt;
&lt;p&gt;AI coding assistants have transformed how developers write software, including infrastructure code. Tools like Claude Code, Cursor, and GitHub Copilot can generate code, explain complex systems, and automate tedious tasks. But when it comes to infrastructure, these tools often produce code that works but misses the mark on patterns that matter: proper secret handling, correct resource dependencies, idiomatic component structure, and the dozens of other details that separate working infrastructure from production-ready infrastructure.&lt;/p&gt;
&lt;p&gt;We built &lt;a href="https://www.pulumi.com/product/neo/"&gt;Neo&lt;/a&gt; for teams that want deep Pulumi expertise combined with organizational context and deployment governance. But developers have preferred tools, and we want people to succeed with Pulumi wherever they work. Some teams live in Claude Code. Others use Cursor, Copilot, Codex, Gemini CLI, or other platforms. That is why we are releasing Pulumi Agent Skills, a collection of packaged expertise that teaches any AI coding assistant how to work with Pulumi the way an experienced practitioner would.&lt;/p&gt;
&lt;h2 id="what-are-agent-skills"&gt;What are agent skills?&lt;/h2&gt;
&lt;p&gt;Skills are structured knowledge packages that follow the open &lt;a href="https://agentskills.io"&gt;Agent Skills&lt;/a&gt; specification. They work across multiple AI coding platforms including Claude Code, GitHub Copilot, Cursor, VS Code, Codex, and Gemini CLI. When you install Pulumi skills, your AI assistant gains access to detailed workflows, code patterns, and decision trees for common infrastructure tasks.&lt;/p&gt;
&lt;h2 id="available-pulumi-skills"&gt;Available Pulumi skills&lt;/h2&gt;
&lt;p&gt;We are launching a set of skills organized into two plugin groups: authoring and migration. You can install all skills at once or choose specific plugin groups based on your needs.&lt;/p&gt;
&lt;h3 id="authoring-skills"&gt;Authoring skills&lt;/h3&gt;
&lt;p&gt;This plugin includes four skills focused on code quality, reusability, and configuration.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pulumi best practices&lt;/strong&gt; encodes the patterns that prevent common mistakes. It covers output handling, component structure, secrets management, safe refactoring with aliases, and deployment workflows. The skill flags anti-patterns that can cause issues with preview, dependencies, and production deployments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pulumi Component&lt;/strong&gt; provides a complete guide for authoring ComponentResource classes. The skill covers designing component interfaces, multi-language support, and distribution. It teaches assistants how to build reusable infrastructure abstractions that work across TypeScript, Python, Go, C#, Java, and YAML.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pulumi Automation API&lt;/strong&gt; covers programmatic orchestration of Pulumi operations. The skill explains when to use Automation API versus the CLI, the tradeoffs between local source and inline programs, and patterns for multi-stack deployments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pulumi ESC&lt;/strong&gt; covers centralized secrets and configuration management. The skill guides assistants through setting up dynamic OIDC credentials, composing environments, and integrating secrets into Pulumi programs and other applications.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="migration-skills"&gt;Migration skills&lt;/h3&gt;
&lt;p&gt;Convert and import infrastructure from other tools to Pulumi. This plugin includes four skills covering complete migration workflows, not just syntax translation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Terraform to Pulumi&lt;/strong&gt; walks through the full migration workflow. It handles state translation, provider version alignment, and the iterative process of achieving a clean &lt;code&gt;pulumi preview&lt;/code&gt; with no unexpected changes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CloudFormation to Pulumi&lt;/strong&gt; covers the complete AWS CloudFormation migration workflow, from template conversion and stack import to handling CloudFormation-specific constructs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CDK to Pulumi&lt;/strong&gt; covers the complete AWS CDK migration workflow end to end, from conversion and import to handling CDK-specific constructs like Lambda-backed custom resources and cross-stack references.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Azure to Pulumi&lt;/strong&gt; covers the complete Azure Resource Manager and Bicep migration workflow, handling template conversion and resource import with guidance on achieving zero-diff validation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="how-to-install"&gt;How to install&lt;/h2&gt;
&lt;h3 id="claude-code-plugin-marketplace"&gt;Claude Code plugin marketplace&lt;/h3&gt;
&lt;p&gt;For Claude Code users, the plugin system provides the simplest installation experience:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;claude plugin marketplace add pulumi/agent-skills
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;claude plugin install pulumi-authoring &lt;span class="c1"&gt;# Install authoring skills&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;claude plugin install pulumi-migration &lt;span class="c1"&gt;# Install migration skills&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can install both plugin groups or choose only the ones you need.&lt;/p&gt;
&lt;h3 id="universal-installation"&gt;Universal installation&lt;/h3&gt;
&lt;p&gt;For Cursor, GitHub Copilot, VS Code, Codex, Gemini and other platforms, use the universal &lt;a href="https://agentskills.io"&gt;Agent Skills&lt;/a&gt; CLI:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx skills add pulumi/agent-skills --skill &lt;span class="s1"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works across all platforms that support the Agent Skills specification.&lt;/p&gt;
&lt;h2 id="using-skills"&gt;Using skills&lt;/h2&gt;
&lt;p&gt;Once installed, skills activate automatically based on context. When you ask your assistant to help migrate a Terraform project, it draws on the Terraform skill&amp;rsquo;s workflow. When you are debugging why resources are being recreated unexpectedly, the best practices skill helps the assistant check for missing aliases.&lt;/p&gt;
&lt;p&gt;In Codex and Claude Code, you can invoke skills directly via slash commands.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/pulumi-terraform-to-pulumi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or describe what you need in natural language:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Help me migrate this CDK application to Pulumi&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Review this Pulumi code for best practices issues&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Create a reusable component for a web service with load balancer&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The assistant will follow the skill&amp;rsquo;s procedures, ask clarifying questions when needed, and produce output that reflects Pulumi best practices rather than generic code generation.&lt;/p&gt;
&lt;h2 id="get-started"&gt;Get started&lt;/h2&gt;
&lt;p&gt;We expect this collection to grow. If you have Pulumi expertise worth packaging, whether provider-specific patterns, debugging workflows, or operational practices, we welcome contributions. See the &lt;a href="https://github.com/pulumi/agent-skills/blob/main/CONTRIBUTING.md"&gt;contributing guide&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;The skills are available now in the &lt;a href="https://github.com/pulumi/agent-skills"&gt;agent-skills repository&lt;/a&gt;. Install them in your preferred AI coding environment and let us know what you build.&lt;/p&gt;</description><author>Pulumi Neo Team</author><category>ai</category><category>platform-engineering</category><category>features</category><category>claude-code</category><category>codex</category><category>ai-agents</category></item><item><title>AI Predictions for 2026: A DevOps Engineer's Guide</title><link>https://www.pulumi.com/blog/ai-predictions-2026-devops-guide/</link><pubDate>Thu, 11 Dec 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/ai-predictions-2026-devops-guide/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/ai-predictions-2026-devops-guide/index.png" /&gt;
&lt;p&gt;The IDE is dying, and so is tool calling. OpenAI is not going to win. And next year, you&amp;rsquo;re going to be shipping code that you&amp;rsquo;ve never reviewed before, even as an experienced engineer.&lt;/p&gt;
&lt;p&gt;These are bold claims, but the way we use AI in 2026 for coding and agents is going to look completely different. In this post, I want to cover my predictions and why they matter right now for DevOps engineers. Some of these are definitely hot takes, but that&amp;rsquo;s what makes this conversation worth having.&lt;/p&gt;
&lt;h2 id="ides-are-dead-at-least-as-we-know-them"&gt;IDEs are dead (at least as we know them)&lt;/h2&gt;
&lt;p&gt;Traditional IDEs where the code is the focus of the interface are simply going to become irrelevant. We&amp;rsquo;re moving toward agent manager interfaces where we can kick off agents in parallel to work on different features in a codebase or even work on different projects at the exact same time.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re already seeing this transition. &lt;a href="https://developers.googleblog.com/en/build-with-google-antigravity-our-new-agentic-development-platform/"&gt;Google Antigravity&lt;/a&gt; combines a familiar AI-powered coding experience with a new agent-first interface. You can deploy agents that autonomously plan, execute, and verify complex tasks across your editor, terminal, and browser. &lt;a href="https://cursor.com/changelog/2-0"&gt;Cursor 2.0&lt;/a&gt; lets you run up to eight agents in parallel on a single prompt, using git worktrees or remote machines to prevent file conflicts. Each agent operates in its own isolated copy of your codebase.&lt;/p&gt;
&lt;p&gt;AWS validated this direction at &lt;a href="https://www.pulumi.com/blog/aws-reinvent-2025-roundup/"&gt;re:Invent 2025&lt;/a&gt; by announcing &amp;ldquo;frontier agents&amp;rdquo; including Kiro for autonomous coding, along with dedicated security and DevOps agents. These agents maintain state, log actions, operate with policy guardrails, and integrate directly with CI/CD pipelines.&lt;/p&gt;
&lt;p&gt;For infrastructure specifically, &lt;a href="https://www.pulumi.com/docs/ai/get-started/"&gt;Pulumi Neo&lt;/a&gt; represents this same shift. Instead of writing code or running CLI commands for every operation, you describe what you need in natural language and Neo handles the implementation. It works across your entire infrastructure, understanding dependencies and creating execution plans that go through pull requests for review.&lt;/p&gt;
&lt;p&gt;For DevOps engineers, this means your pipelines need to accommodate AI-generated code at scale. Multiple agents working simultaneously need isolated, reproducible environments. More generated code means more artifacts to track, version, and deploy.&lt;/p&gt;
&lt;h2 id="the-different-paths-to-ai-dominance"&gt;The different paths to AI dominance&lt;/h2&gt;
&lt;p&gt;A lot of people think that in the future, a single large language model will have a monopoly and be the best at absolutely everything. But what&amp;rsquo;s really going to happen is different providers will specialize and focus on being the best at different things.&lt;/p&gt;
&lt;p&gt;Google is going down the generalist route with Gemini, aiming to be the jack-of-all-trades. Anthropic is focusing on being the best for coding. You can see this in the benchmarks: when Opus 4.5 came out, the first benchmark they highlighted was for software engineering, because that&amp;rsquo;s what Anthropic is focusing on.&lt;/p&gt;
&lt;p&gt;Amazon is carving out its own niche with the &lt;a href="https://www.aboutamazon.com/news/aws/aws-agentic-ai-amazon-bedrock-nova-models"&gt;Nova model family&lt;/a&gt;, announced at re:Invent 2025. The Nova 2 lineup includes specialized models: Pro for complex reasoning, Sonic for real-time voice conversations, and Omni for simultaneous text, audio, and video processing. With &lt;a href="https://www.pulumi.com/blog/aws-reinvent-2025-roundup/#rent-the-lab-nova-forge"&gt;Nova Forge&lt;/a&gt;, organizations can build custom frontier models by combining their proprietary data with AWS open weight models. The re:Invent message was clear: leveraging your first-party data is now fundamental to going beyond generic AI. We&amp;rsquo;re talking about 30-40% increases in accuracy when you bring your own data into the equation.&lt;/p&gt;
&lt;p&gt;But here&amp;rsquo;s the hot take: I don&amp;rsquo;t think OpenAI is going to come out on top with any kind of specialization. They&amp;rsquo;ve &lt;a href="https://garymarcus.substack.com/p/gpt-5-overdue-overhyped-and-underwhelming"&gt;disappointed time and time again&lt;/a&gt; with GPT-5 and GPT-4.5. With 4.5, they seemed to try to be the creative specialist, but it just didn&amp;rsquo;t work. The &lt;a href="https://www.axios.com/2025/08/12/gpt-5-bumpy-launch-openai"&gt;GPT-5 launch in August 2025&lt;/a&gt; was described as &amp;ldquo;barely better than last month&amp;rsquo;s flavor of the month&amp;rdquo; and on some metrics it&amp;rsquo;s actually worse than earlier models.&lt;/p&gt;
&lt;p&gt;For DevOps teams, this specialization means you&amp;rsquo;ll need infrastructure that&amp;rsquo;s model-agnostic and supports multiple AI backends. Plan for secrets management across multiple LLM providers and design your systems to swap models based on the task at hand.&lt;/p&gt;
&lt;h2 id="the-local-ai-breakthrough"&gt;The local AI breakthrough&lt;/h2&gt;
&lt;p&gt;2026 will be the year of local AI. We didn&amp;rsquo;t see that much this year besides DeepSeek at the start of 2025, which was a big deal. We had a couple of new models like Qwen 3, but nothing that fundamentally changed the game. Now we&amp;rsquo;re starting to see new hardware that makes it obvious we&amp;rsquo;re going to be able to run very large models on smaller devices.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s new AI chips that can run upwards of 120 billion parameter large language models on the edge, which would be a complete game-changer. Right now, hardware requirements are one of the biggest challenges for scaling local AI. If we can solve the hardware problem, we get 100% data privacy and zero-millisecond latency for our agents.&lt;/p&gt;
&lt;p&gt;AWS is addressing this with &lt;a href="https://techcrunch.com/2025/12/02/amazon-releases-an-impressive-new-ai-chip-and-teases-a-nvidia-friendly-roadmap/"&gt;Trainium3 UltraServers&lt;/a&gt;, their 3nm AI chips delivering 4.4x more compute than the previous generation. More significantly, &lt;a href="https://www.geekwire.com/2025/amazon-unveils-frontier-agents-new-chips-and-private-ai-factories-in-aws-reinvent-rollout/"&gt;AWS AI Factories&lt;/a&gt; allow organizations to deploy racks of Trainium chips and NVIDIA GPUs directly into their own data centers, addressing data sovereignty concerns while keeping AI inference close to the data.&lt;/p&gt;
&lt;p&gt;For DevOps, this opens the door to zero-latency inference in CI/CD pipelines, complete data privacy for sensitive codebases, and reduced cloud costs for AI-heavy workloads.&lt;/p&gt;
&lt;h2 id="engineers-as-system-architects"&gt;Engineers as system architects&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;re finally going to get to the point where we&amp;rsquo;re not the coders. We delegate that entirely to our coding agents, and we become the system architects. This mirrors the evolution of other engineering disciplines. Civil engineers don&amp;rsquo;t fabricate the steel beams; they design the structure and verify the integrity.&lt;/p&gt;
&lt;p&gt;I think of this as a three-step process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Define&lt;/strong&gt;: Set your objectives and the system that your agents will operate under&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Orchestrate&lt;/strong&gt;: Delegate the coding to your agents&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validate&lt;/strong&gt;: Ensure the quality of the outputs and the overall system&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We&amp;rsquo;re still in the loop. We are the final say in whatever is created, but we&amp;rsquo;re delegating the grunt work to our coding agents.&lt;/p&gt;
&lt;p&gt;This is exactly the model that &lt;a href="https://www.pulumi.com/docs/ai/tasks/"&gt;Pulumi Neo&lt;/a&gt; implements for infrastructure. When you give Neo a complex request, it creates a task plan outlining the steps it will take to accomplish your goal. This plan provides transparency into Neo&amp;rsquo;s approach and gives you the opportunity to adjust the strategy before execution begins. Neo operates in different modes: Review mode where everything requires approval, Balanced mode where only deployments need sign-off, or Auto mode for full autonomy. You define the boundaries, Neo orchestrates the work, and you validate through pull requests and previews.&lt;/p&gt;
&lt;p&gt;For DevOps engineers, this shift means building robust validation infrastructure becomes critical. When AI writes the code, you need automated testing pipelines, security scanning, and verification systems that can operate at the speed of AI-generated changes.&lt;/p&gt;
&lt;h2 id="code-execution-is-replacing-tool-calling"&gt;Code execution is replacing tool calling&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s a key insight that kept coming up at re:Invent: models are no longer the bottleneck. Context is. Our agents are going to change a lot next year because code execution is starting to replace tool calling. The problem with tool calling right now is that all the capabilities you give an agent take up context upfront. When you try to give a lot of different tools to an agent, you completely overwhelm it.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.anthropic.com/engineering/code-execution-with-mcp"&gt;Anthropic&amp;rsquo;s research on code execution with MCP&lt;/a&gt; addresses exactly this problem. Code execution is a massive token reduction, faster, and more flexible. You&amp;rsquo;re giving the agent the ability to generate its own capabilities at runtime by writing code to interact with APIs. A workflow that previously consumed about 150,000 tokens when tools were passed directly through the model was reimplemented with code execution and used only about 2,000 tokens. That&amp;rsquo;s a 98.7% reduction.&lt;/p&gt;
&lt;p&gt;AWS embraced this pattern with &lt;a href="https://www.aboutamazon.com/news/aws/amazon-sagemaker-ai-amazon-bedrock-aws-ai-agents"&gt;Amazon Bedrock AgentCore&lt;/a&gt;, which now includes code interpretation capabilities. AgentCore supports any agent framework (CrewAI, LangGraph, OpenAI SDK) and provides memory, browser tools, and observability features that make code execution practical at enterprise scale.&lt;/p&gt;
&lt;p&gt;For DevOps, this means you need sandboxed, secure execution environments for AI-generated code. Running agent-generated code requires appropriate isolation, resource limits, and monitoring.&lt;/p&gt;
&lt;h2 id="progressive-disclosure-and-composable-skills"&gt;Progressive disclosure and composable skills&lt;/h2&gt;
&lt;p&gt;The best part about code execution flexibility is it unlocks progressive disclosure. All I mean by that is: you have a lot of capabilities for an agent, but you don&amp;rsquo;t actually give all of them upfront. Instead, you allow the agent to discover capabilities and then leverage them in a more flexible way.&lt;/p&gt;
&lt;p&gt;For each capability, you just have a bit of metadata or description that loads upfront. When the agent decides to leverage that capability, then you load the full instructions. Now you can practically scale to infinity because all capabilities don&amp;rsquo;t have to be loaded at runtime.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills"&gt;Claude Skills&lt;/a&gt; is a good example of this pattern. Skills are organized folders of instructions, scripts, and resources that agents can discover and load dynamically. At session start, the agent scans available skills and populates the system prompt with just a brief name and description (around 100 tokens). The full skill prompt loads only after Claude selects it, preventing context bloat while maintaining discoverability.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://kiro.dev/powers/"&gt;Kiro Powers&lt;/a&gt; addresses the same problem. Connecting five MCP servers can consume over 50,000 tokens, roughly 40% of an AI model&amp;rsquo;s context window, before you even type your first request. Powers bundle MCP servers, steering files, and hooks into units that load dynamically based on conversation context. Mention &amp;ldquo;payment&amp;rdquo; and the Stripe power activates. &lt;a href="https://venturebeat.com/ai/aws-launches-kiro-powers-with-stripe-figma-and-datadog-integrations-for-ai"&gt;Datadog, Figma, and others&lt;/a&gt; have powers available.&lt;/p&gt;
&lt;p&gt;For DevOps, this translates to modular infrastructure definitions, on-demand capability loading, and efficient resource utilization. Think about how you can apply this pattern to your own automation.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Equip your agents with Pulumi skills&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Give Claude Code, Cursor, or any coding agent working Pulumi patterns through Agent Skills and the Pulumi MCP server, so it generates infrastructure that deploys.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/docs/ai/skills/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="agent-to-agent-protocols-are-finally-happening"&gt;Agent-to-agent protocols are finally happening&lt;/h2&gt;
&lt;p&gt;Agent-to-agent protocols are where AI agents operate in a peer network, discover each other&amp;rsquo;s capabilities in real time, and interact autonomously. When Google released their &lt;a href="https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/"&gt;A2A protocol&lt;/a&gt; earlier this year, there was a ton of buzz. A lot of people thought it was going to be the next big standard, like the next MCP. But then it kind of fell to the wayside.&lt;/p&gt;
&lt;p&gt;The big reason is the chicken-and-egg problem. For A2A to be useful, you need many people to adopt it at the same time. Otherwise, if you build an A2A-compatible agent, it has no other agents to talk to. The whole value proposition is lost unless you already have a big network to attach to.&lt;/p&gt;
&lt;p&gt;But that&amp;rsquo;s finally changing. The &lt;a href="https://www.linuxfoundation.org/press/linux-foundation-launches-the-agent2agent-protocol-project-to-enable-secure-intelligent-communication-between-ai-agents"&gt;Linux Foundation launched the A2A project&lt;/a&gt; in June 2025, and adoption is accelerating. Adobe, Microsoft, SAP, ServiceNow, and S&amp;amp;P Global are all implementing A2A. In July 2025, Google released &lt;a href="https://cloud.google.com/blog/products/ai-machine-learning/agent2agent-protocol-is-getting-an-upgrade"&gt;version 0.3 of the A2A protocol&lt;/a&gt; with a more stable interface critical to accelerating enterprise adoption.&lt;/p&gt;
&lt;h2 id="machines-paying-machines"&gt;Machines paying machines&lt;/h2&gt;
&lt;p&gt;My next big prediction is that machines paying machines is going to become a very big thing. &lt;a href="https://www.coinbase.com/developer-platform/discover/launches/x402"&gt;Coinbase released the x402 protocol&lt;/a&gt; for exactly this: building AI agents that you expose over the internet but require payment whenever someone else interacts with them.&lt;/p&gt;
&lt;p&gt;This goes really well with agent-to-agent protocols. You can create a peer network where you monetize your agents. They all leverage each other but make payments whenever they take advantage of another agent&amp;rsquo;s capabilities. Cryptocurrency is the perfect solution for this kind of machine-to-machine network because it enables micropayments to be made quickly and globally.&lt;/p&gt;
&lt;p&gt;The x402 protocol has achieved &lt;a href="https://www.coingecko.com/learn/x402-autonomous-ai-agent-payment-coinbase"&gt;156,000 weekly transactions with 492% growth&lt;/a&gt; since launching in May 2025. It&amp;rsquo;s now integrated with &lt;a href="https://docs.cdp.coinbase.com/x402/welcome"&gt;Anthropic&amp;rsquo;s MCP Protocol&lt;/a&gt;, Google Gemini, OpenAI Codex, and other platforms. Stablecoins like USDC enable charging per request, per service, or per second of usage at near-zero transaction costs, enabling payments as low as $0.001 per request.&lt;/p&gt;
&lt;h2 id="artifact-reviews-instead-of-diff-reviews"&gt;Artifact reviews instead of diff reviews&lt;/h2&gt;
&lt;p&gt;When we want to do a rigorous code review, traditionally, we look line by line at all the changes. But coding agents are getting to the point where they can prove their code works through artifacts. Instead of reviewing line by line, we can look at browser recordings, full working demos of a backend API, and other artifacts.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developers.googleblog.com/en/build-with-google-antigravity-our-new-agentic-development-platform/"&gt;Google Antigravity&lt;/a&gt; is a perfect example. As part of its coding process, it can autonomously spin up your website, visit it, scroll through it, take screenshots, and record everything. Agents generate artifacts, including tangible deliverables like task lists, implementation plans, screenshots, and browser recordings. You can verify the agent&amp;rsquo;s logic at a glance.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://aws.amazon.com/blogs/aws/build-reliable-ai-agents-for-ui-workflow-automation-with-amazon-nova-act-now-generally-available/"&gt;Amazon Nova Act&lt;/a&gt; takes this further. It enables AI agents to automate browser-based tasks like form filling, QA testing, and workflow validation with over 90% reliability. The service includes built-in observability through live viewing, CloudTrail logging, and session replay, making it possible to review what an agent actually did rather than parsing through code changes.&lt;/p&gt;
&lt;h2 id="shipping-code-youve-never-read"&gt;Shipping code you&amp;rsquo;ve never read&lt;/h2&gt;
&lt;p&gt;For the last prediction, we&amp;rsquo;re tying everything together. We&amp;rsquo;ve talked about reviewing artifacts instead of diffs, creating systems instead of coding, and the new capabilities for agents with code execution.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re going to get to the point very quickly where we&amp;rsquo;re shipping code that we have never read before. And I&amp;rsquo;m not talking about people who vibe code. Even experienced engineers are going to trust their systems so much that they have the ability to review the code but they&amp;rsquo;re not going to. We&amp;rsquo;re just going to ship to production after reviewing the artifacts.&lt;/p&gt;
&lt;p&gt;I presented on this exact topic at &lt;a href="https://www.meetup.com/tel-aviv-pulumi-user-group/events/310498800/"&gt;the Tel Aviv Pulumi User Group meetup at Qodo HQ&lt;/a&gt; back in October, where I demonstrated how Pulumi Neo&amp;rsquo;s autonomous decision-making capabilities can handle infrastructure tasks that we traditionally managed manually. &lt;a href="https://www.qodo.ai/"&gt;Qodo&lt;/a&gt; is doing fascinating work in this space with their agentic development tools, building systems that let you trust the output without necessarily reviewing every line.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not saying we&amp;rsquo;re taking the human completely out of the loop. I&amp;rsquo;m saying we&amp;rsquo;re going to have a lot of trust in our systems and a validation process that includes us, but that doesn&amp;rsquo;t necessarily have to be us actually looking at the code. Tools like Pulumi Neo create pull requests with clear documentation of changes, run previews to validate infrastructure modifications, and provide the transparency needed to ship with confidence.&lt;/p&gt;
&lt;h2 id="the-path-forward"&gt;The path forward&lt;/h2&gt;
&lt;p&gt;The predictions I&amp;rsquo;ve outlined point to a fundamental shift in how software gets built and deployed. For DevOps engineers, this isn&amp;rsquo;t a threat but an opportunity to become more strategic and less operational. We&amp;rsquo;re entering the battle of the agentic frameworks, where the winners will be those who can build faster, cheaper agentic applications through their platforms.&lt;/p&gt;
&lt;p&gt;The immediate reality is that your CI/CD pipelines need to accommodate AI-generated code at scale, your secrets management needs to handle multiple LLM providers, and your execution environments need proper sandboxing for agent-generated code. These aren&amp;rsquo;t future concerns; they&amp;rsquo;re requirements for working effectively with the AI tools available today.&lt;/p&gt;
&lt;p&gt;Looking further out, the engineers who thrive will be those who embrace the system architect role. Define clear objectives and constraints for your AI agents. Build validation frameworks that can verify outcomes without requiring line-by-line code review. Design infrastructure that&amp;rsquo;s modular enough to load capabilities on demand.&lt;/p&gt;
&lt;p&gt;The technology to make this happen already exists. Agent orchestration platforms are shipping. Code execution is replacing tool calling. Progressive disclosure patterns are proven. The question isn&amp;rsquo;t whether these changes are coming; it&amp;rsquo;s whether you&amp;rsquo;ll be ready when they arrive.&lt;/p&gt;
&lt;h2 id="start-building-for-the-ai-driven-future-today"&gt;Start building for the AI-driven future today&lt;/h2&gt;
&lt;p&gt;If you want to experience what this future looks like right now, &lt;a href="https://www.pulumi.com/product/neo/#video"&gt;Pulumi Neo&lt;/a&gt; is the place to start. Neo lets you make natural language requests for routine infrastructure tasks, analysis, and management. Instead of writing code for every operation, you describe what you need, and Neo handles the implementation, creating task plans, running previews, and opening pull requests for your review.&lt;/p&gt;
&lt;p&gt;Whether you&amp;rsquo;re looking to update outdated resources across your infrastructure, analyze your cloud spend, or automate complex multi-step workflows, Neo provides the agent-first experience that&amp;rsquo;s defining the next generation of DevOps tooling.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/ai/get-started/"&gt;&lt;strong&gt;Get started with Pulumi Neo&lt;/strong&gt;&lt;/a&gt; and see how AI-powered infrastructure automation can transform your workflow.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/blog/from-works-on-my-machine-to-production-ready-ai-agents-with-amazon-bedrock-agentcore/"&gt;Build a production-ready AI agent&lt;/a&gt; by moving from local prototypes to deployed infrastructure with Amazon Bedrock AgentCore, the Strands SDK, and Pulumi.&lt;/li&gt;
&lt;/ul&gt;</description><author>Engin Diri</author><category>ai</category><category>devops</category><category>platform-engineering</category><category>automation</category><category>aws</category><category>nova-forge</category><category>bedrock-agentcore</category><category>pulumi-neo</category></item><item><title>Encode What You Know With Neo: Custom Instructions and Slash Commands</title><link>https://www.pulumi.com/blog/slash-commands-custom-instructions/</link><pubDate>Tue, 09 Dec 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/slash-commands-custom-instructions/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/slash-commands-custom-instructions/index.png" /&gt;
&lt;p&gt;Every organization builds up knowledge over time: naming standards, compliance requirements, patterns your team has settled on, and proven approaches to common tasks. Until now, bringing this knowledge into Neo meant repeating it manually each time - specifying preferences, describing how your team works, and recreating prompts that someone already perfected.&lt;/p&gt;
&lt;p&gt;Two new features change this. Custom Instructions teach Neo your standards so it applies them automatically. Slash Commands capture proven prompts so anyone on your team can use them with a keystroke.&lt;/p&gt;
&lt;h2 id="custom-instructions-standards-applied-automatically"&gt;Custom Instructions: Standards Applied Automatically&lt;/h2&gt;
&lt;p&gt;Custom Instructions let you define what Neo should know about your organization and how it should behave. This includes naming conventions, required tags and compliance requirements, technology preferences, and cost guidelines - but also actions Neo should take automatically, like including a rough cost estimate whenever it proposes new infrastructure. You configure them once in your organization settings, and Neo applies them to every task from that point forward.&lt;/p&gt;
&lt;p&gt;Consider the difference. Before Custom Instructions, a simple request required loading context:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Neo, update our Lambda functions to Node 20. Remember, we use TypeScript exclusively, our naming convention is service-region-env, we always deploy to us-east-1 first for testing, and all resources need our standard compliance tags including CostCenter and DataClassification.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With those details captured in Custom Instructions, the same request becomes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Neo, update our Lambda functions to Node 20.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neo already knows how your team works, so you can focus on what you&amp;rsquo;re trying to accomplish.&lt;/p&gt;
&lt;h2 id="slash-commands-capture-what-works"&gt;Slash Commands: Capture What Works&lt;/h2&gt;
&lt;p&gt;Over time, your team figures out the right way to ask Neo for certain tasks. Maybe someone wrote the perfect prompt for checking policy violations, or discovered an approach to drift detection that catches issues others miss. That knowledge tends to live in someone&amp;rsquo;s head or buried in a Slack thread.&lt;/p&gt;
&lt;p&gt;Slash Commands turn these prompts into shortcuts anyone can use. When you type &lt;code&gt;/&lt;/code&gt; in Neo, you&amp;rsquo;ll see available commands, select one, and Neo receives the full prompt behind it.&lt;/p&gt;
&lt;p&gt;&lt;img src="slash-commands.gif" alt="Slash Commands in action"&gt;&lt;/p&gt;
&lt;p&gt;Neo ships with built-in commands for common tasks:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/get-started&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Learn what Neo can do and how to structure effective requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/policy-issues-report&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lists your most severe policy violations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/component-version-report&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lists components that are outdated in your private registry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/provider-version-report&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lists providers that are outdated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;You can also create your own. In Pulumi Cloud, you define the prompt - no coding required. Once saved, your team can start using it immediately. If a command needs more information than what&amp;rsquo;s provided, Neo will ask follow-up questions to fill in the gaps.&lt;/p&gt;
&lt;h2 id="get-started"&gt;Get Started&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/docs/ai/settings/#custom-instructions"&gt;Custom Instructions&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/ai/settings/#slash-commands"&gt;Slash Commands&lt;/a&gt; are available now. You can configure Custom Instructions in Neo Settings. Slash Commands come with several built-in options, and you can create custom ones tailored to your workflow.&lt;/p&gt;</description><author>Pulumi Neo Team</author><category>ai</category><category>ai-agents</category><category>platform-engineering</category><category>pulumi-neo</category></item><item><title>Future of the Cloud: 10 Trends Shaping 2026 and Beyond</title><link>https://www.pulumi.com/blog/future-cloud-infrastructure-10-trends-shaping-2024-and-beyond/</link><pubDate>Thu, 04 Dec 2025 07:56:40 +0000</pubDate><guid>https://www.pulumi.com/blog/future-cloud-infrastructure-10-trends-shaping-2024-and-beyond/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/future-cloud-infrastructure-10-trends-shaping-2024-and-beyond/index.png" /&gt;
&lt;p&gt;In 2026, several trends will dominate cloud computing, driving innovation, efficiency, and scalability. From Infrastructure as Code (IaC) to AI/ML, platform engineering to multi-cloud and hybrid strategies, and security practices, let&amp;rsquo;s explore the 10 biggest emerging trends.&lt;/p&gt;
&lt;h2 id="on-this-article"&gt;On This Article&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#1-cloud-will-become-a-business-necessity-by-2028"&gt;1. Cloud Will Become a Business Necessity by 2028&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#2-hyperscalers-accelerate-ai-driven-cloud-expansion"&gt;2. Hyperscalers Accelerate AI-Driven Cloud Expansion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#3-hybrid-and-multi-cloud-to-drive-innovation"&gt;3. Hybrid and Multi-Cloud to Drive Innovation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#4-enterprises-rebuild-their-cloud-foundations-to-operationalize-ai"&gt;4. Enterprises Rebuild Their Cloud Foundations to Operationalize AI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#5-iac-drives-scalable-cloud-multi-cloud-and-ai-operations"&gt;5. IaC Drives Scalable Cloud, Multi-Cloud, and AI Operations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#6-devsecops-evolves-into-ai-integrated-security"&gt;6. DevSecOps Evolves Into AI-Integrated Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#7-platform-engineering--internal-developer-platforms-idps"&gt;7. Platform Engineering and Internal Developer Platforms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#8-aiops-matures-into-a-cloud-operations-standard"&gt;8. AIOps Matures Into a Cloud Operations Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#9-kubernetes-dominance-and-increased-complexity"&gt;9. Kubernetes Dominance and Increased Complexity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#10-ai-code-assistants-in-the-enterprise"&gt;10. AI Code Assistants in the Enterprise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-future-of-cloud-reinvented-for-an-ai-first-decade"&gt;The Future of Cloud: Reinvented for an AI-First Decade&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="1-cloud-will-become-a-business-necessity-by-2028"&gt;1. Cloud Will Become a Business Necessity by 2028&lt;/h2&gt;
&lt;p&gt;According to &lt;a href="https://www.gartner.com/en/infrastructure-and-it-operations-leaders/topics/cloud-computing"&gt;Gartner&lt;/a&gt;, by 2028 the cloud will be the key driver for business innovation, and estimates that over 95% of new digital workloads will be deployed on cloud-native platforms.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/future-cloud-infrastructure-10-trends-shaping-2024-and-beyond/gartner-cloud-2028.png"
alt="The future of cloud computing. Credit: Gartner" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;The future of cloud computing. Credit: Gartner&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;According to McKinsey &amp;amp; Company&amp;rsquo;s &amp;ldquo;&lt;a href="https://www.mckinsey.com/capabilities/mckinsey-digital/our-insights/in-search-of-cloud-value-can-generative-ai-transform-cloud-roi"&gt;In search of cloud value&lt;/a&gt;&amp;rdquo; report:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cloud value is driven by innovation&lt;/strong&gt;, worth 5x more than cost savings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EBITDA uplift of 20–30% by 2030&lt;/strong&gt; for high-performing organizations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Asia leads in projected cloud value&lt;/strong&gt;, followed by the US and Europe.&lt;/li&gt;
&lt;li&gt;High-ROI organizations excel by aligning cloud strategy with business priorities, building strong cloud foundations, and using modern operating models.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Teams succeeding in this transition increasingly use Infrastructure as Code, automation, and unified governance frameworks like &lt;a href="https://www.pulumi.com/product/insights-governance/"&gt;Pulumi Insights + Policies&lt;/a&gt; to operationalize this value.&lt;/p&gt;
&lt;h2 id="2-hyperscalers-accelerate-ai-driven-cloud-expansion"&gt;2. Hyperscalers Accelerate AI-Driven Cloud Expansion&lt;/h2&gt;
&lt;p&gt;Hyperscalers are making the largest infrastructure investments in cloud history — nearly all centered on AI workloads, inference, and high-performance compute.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AWS&lt;/strong&gt; has integrated &lt;a href="https://www.aboutamazon.com/news/aws/anthropic-claude-4-opus-sonnet-amazon-bedrock"&gt;Anthropic’s Claude 3 and Claude 4 models into Amazon Bedrock&lt;/a&gt; for enterprise LLM workflows. “Claude Opus 4 and Claude Sonnet 4 are available today in Amazon Bedrock, enabling customers to build agents with stronger reasoning, memory, and tool use.” — AWS, May 2025&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Microsoft Azure&lt;/strong&gt; revenue rose 33% year-over-year in Q3 (ended March 31), outperforming estimates of ~29.7%. &lt;a href="https://www.reuters.com/business/microsoft-beats-quarterly-revenue-estimates-ai-shift-bolsters-cloud-demand-2025-04-30/"&gt;AI contributed 16 percentage points to this growth&lt;/a&gt;, up from 13 points in the prior quarter. &amp;ldquo;Microsoft is on track to invest approximately $80 billion to build out AI-enabled datacenters to train AI models and deploy AI and cloud-based applications around the world,&amp;rdquo; said Brad Smith, the Microsoft Vice Chair and President.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google Cloud&lt;/strong&gt; is committing &lt;a href="https://www.utilitydive.com/news/google-cloud-blackstone-aws-us-ai-data-center-buildouts/753202"&gt;$25 billion over two years for data center and AI infrastructure expansion&lt;/a&gt; across the PJM grid, with total capital expenditure for 2025 ranging from $75–85 billion. &amp;ldquo;As our CEO has said, in these early days of a very transformative technology, the risks of under-investing are dramatically higher than the risks of over-investing,&amp;rdquo; said Eunice Huang, Head of AI and Emerging Tech Policy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Oracle&lt;/strong&gt; anticipates 15–20% cloud revenue growth in FY 2026–2027 attributable to AI infrastructure demand, tied to its partnership in the &lt;a href="https://www.pcgamer.com/software/ai/openais-skyrocketing-spending-could-see-billions-of-dollars-in-silicon-headed-down-the-ai-mines-in-the-next-few-years-including-2-million-nvidia-chips-headed-to-texas-stargate-facility/"&gt;Stargate initiative&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As hyperscalers integrate AI deeper into their service layers, engineering teams must adapt with IaC-driven automation, reusable patterns, and policy controls to deploy cloud and AI infrastructure consistently.
See how organizations &lt;a href="https://www.pulumi.com/aws/#video"&gt;deploy AWS infrastructure at the speed of AI with Pulumi&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/insights/policy/"&gt;Pulumi Policies&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="3-hybrid-and-multi-cloud-to-drive-innovation"&gt;3. Hybrid and Multi-Cloud to Drive Innovation&lt;/h2&gt;
&lt;p&gt;Hybrid and multi-cloud strategies are now mainstream:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hybrid cloud will grow from &lt;strong&gt;$130B to $310–330B&lt;/strong&gt; by 2030 (&lt;a href="https://www.businesswire.com/news/home/20250513124988/en/Hybrid-Cloud-Market-Analysis-Growth-Trends-and-Forecasts-Report-2024-2025-2030-Surging-Demand-for-Seamless-Interoperability-Between-Cloud-Services-and-Existing-Systems---ResearchAndMarkets.com"&gt;ResearchAndMarkets&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;87% of enterprises&lt;/strong&gt; run workloads across multiple clouds (&lt;a href="https://www.mordorintelligence.com/industry-reports/hybrid-cloud-market"&gt;Mordor Intelligence&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Gartner predicts that &lt;strong&gt;40% of enterprises&lt;/strong&gt; will adopt hybrid compute architectures in mission-critical workflows by 2028 (up from 8%).&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/future-cloud-infrastructure-10-trends-shaping-2024-and-beyond/most-popular-cloud-computing-infrastructure-by-industry.png"
alt="Most popular cloud computing infrastructure by industry. Credit: Cloud Worldwide Service, Forbes" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;Credit: Cloud Worldwide Service, Forbes&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;As AI and regulatory requirements grow, organizations must deploy workloads across AWS, Azure, Google Cloud, on-prem, and edge — while maintaining consistent security, compliance, and configuration.&lt;/p&gt;
&lt;p&gt;Modern cloud teams use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure as Code&lt;/strong&gt; for consistent multi-cloud provisioning and environment standardization, forming the backbone of AI infrastructure orchestration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reusable components and internal platforms&lt;/strong&gt; to define scalable architecture patterns and accelerate delivery across Kubernetes, AI/ML pipelines, and hybrid environments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Policy-driven guardrails&lt;/strong&gt; to maintain cost, security, and compliance across environments, supporting cloud governance automation and modern cloud cost governance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pulumi enables all three through its &lt;a href="https://www.pulumi.com/docs/iac/"&gt;multi-cloud IaC model&lt;/a&gt;, &lt;a href="https://www.pulumi.com/product/insights-governance#video"&gt;Pulumi Policies&lt;/a&gt;, and &lt;a href="https://www.pulumi.com/product/internal-developer-platforms/#video"&gt;internal developer platform capabilities&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="4-enterprises-rebuild-their-cloud-foundations-to-operationalize-ai"&gt;4. Enterprises Rebuild Their Cloud Foundations to Operationalize AI&lt;/h2&gt;
&lt;p&gt;While hyperscalers are transforming the global cloud platform, enterprises face a different challenge: adapting their own cloud foundations to support AI at scale. Organizations are moving beyond prototypes and integrating AI into core products, internal workflows, and customer-facing systems, requiring new levels of automation, governance, and AI infrastructure orchestration.&lt;/p&gt;
&lt;p&gt;According to &lt;a href="https://www.networkworld.com/article/4058786/gartner-ai-spending-to-reach-1-5-trillion-dollars-this-year.html"&gt;Gartner&lt;/a&gt;, global AI infrastructure spending is expected to surpass &lt;strong&gt;$2 trillion in 2026&lt;/strong&gt;. &lt;a href="https://blogs.idc.com/2025/10/22/futurescape-2026-moving-into-the-agentic-future/"&gt;IDC predicts that by 2027&lt;/a&gt;, more than 50% of enterprises will use AI agents to drive core workflows, which requires scalable, secure, and automated cloud architectures to support model execution and orchestration.&lt;/p&gt;
&lt;p&gt;To enable this transition, enterprises are investing in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GPU provisioning and orchestration&lt;/strong&gt;, data pipelines, vector databases, feature stores, and LLM infrastructure needed for real-time AI workloads.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data pipelines, vector databases, and feature stores&lt;/strong&gt; needed for real-time AI workloads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model-serving infrastructure&lt;/strong&gt;, including gateways, inference routers, and autoscaling layers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strong identity, secrets, and access controls&lt;/strong&gt; as AI systems increase security exposure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation through Infrastructure as Code&lt;/strong&gt; to ensure reproducibility and reduce drift&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Policy-driven governance&lt;/strong&gt; to secure cost, compliance, and architectural consistency&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As AI becomes deeply embedded across engineering organizations, teams are increasingly using software engineering approaches such as Infrastructure as Code, reusable components, platform engineering, and policy automation to standardize how AI infrastructure is deployed, scaled, and secured across clouds.&lt;/p&gt;
&lt;p&gt;To support this shift, Pulumi&amp;rsquo;s perspective on &lt;a href="https://www.pulumi.com/product/superintelligence-infrastructure/"&gt;Superintelligence Infrastructure&lt;/a&gt; explains why AI workloads, from pre-training to inference at massive scale, require dynamic infrastructure orchestration rather than static configuration.&lt;/p&gt;
&lt;h3 id="pulumi-users-increasingly-rely-on"&gt;Pulumi users increasingly rely on:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/iac/"&gt;Pulumi IaC&lt;/a&gt; for standardized AI infrastructure&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/product/secrets-management/"&gt;Pulumi ESC&lt;/a&gt; to manage all secrets and configuration at scale&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/product/insights-governance/"&gt;Pulumi Insights&lt;/a&gt; for visibility and misconfiguration analysis&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/insights/policy/"&gt;Pulumi Policies&lt;/a&gt; for AI-specific guardrails in code, cost detection, and to provide automated compliance protections&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="5-iac-drives-scalable-cloud-multi-cloud-and-ai-operations"&gt;5. IaC Drives Scalable Cloud, Multi-Cloud, and AI Operations&lt;/h2&gt;
&lt;p&gt;As cloud environments expand and AI workloads demand highly dynamic infrastructure, Infrastructure as Code (IaC) is becoming the foundation for scaling reliably across all environments. Organizations are increasingly adopting IaC in general-purpose languages to unify development and infrastructure workflows, reduce configuration drift, and deliver cloud resources at speed.&lt;/p&gt;
&lt;p&gt;Modern &lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;Infrastructure as Code&lt;/a&gt; is advancing far beyond simple provisioning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Standardizing multi-cloud and hybrid patterns&lt;/strong&gt; so teams can deploy consistently across AWS, Azure, Google Cloud, on-prem, and edge environments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integrating seamlessly with cloud providers and third-party services&lt;/strong&gt;, including data platforms and messaging systems like CockroachDB, Confluent Cloud, and Kafka.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Providing deeper validation and type-safety&lt;/strong&gt;, ensuring parameters, dependencies, and security controls are correct before deployment.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improving cloud resource efficiency and visibility&lt;/strong&gt; with tools like &lt;a href="https://www.pulumi.com/docs/insights/discovery/"&gt;Pulumi Insights Discovery&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Embedding security and compliance through &lt;a href="https://www.pulumi.com/docs/insights/policy/"&gt;Policy as Code&lt;/a&gt;&lt;/strong&gt;, enforcing guardrails, cost controls, and regulatory requirements automatically, enabling truly policy-driven cloud management.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enabling intelligent automation&lt;/strong&gt;, from unit and integration tests to auto-remediation policies and policy-driven approvals.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incorporating AI-driven optimization and insights&lt;/strong&gt;, helping teams detect misconfigurations, analyze usage patterns, and generate infrastructure updates with tools like &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt; and &lt;a href="https://www.pulumi.com/blog/policy-next-gen/"&gt;Pulumi Policies&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As organizations scale both traditional cloud workloads and AI-driven systems, IaC has become critical for achieving secure, repeatable, and high-velocity operations across every environment.&lt;/p&gt;
&lt;h2 id="6-devsecops-evolves-into-ai-integrated-security"&gt;6. DevSecOps Evolves Into AI-Integrated Security&lt;/h2&gt;
&lt;p&gt;As AI becomes embedded across cloud-native systems, DevSecOps is entering a new era. Gartner predicts that by &lt;strong&gt;2028, over 50% of enterprises will use AI security platforms&lt;/strong&gt; to protect their AI investments. Below are the 3 key predictions for the future of DevSecOps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AI-driven security automation&lt;/strong&gt;: Teams will increasingly rely on AI to detect threats, enforce policies, and generate secure infrastructure patches. See Pulumi’s capabilities in &lt;a href="https://www.pulumi.com/product/insights-governance/#video"&gt;AI-powered remediation&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;More focus on secrets management&lt;/strong&gt;: With AI systems accessing more sensitive data, secure secret storage will be essential. &lt;a href="https://www.pulumi.com/product/secrets-management/"&gt;Pulumi ESC&lt;/a&gt; helps teams centralize and govern credentials, keys, and tokens safely.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Greater cross-team collaboration&lt;/strong&gt;: Dev, Sec, and Ops workflows will converge under shared frameworks: IaC, policy automation, runtime scanning, and GitOps.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As organizations increase their use of AI across cloud-native systems, the need for tightly aligned security, governance, and cloud governance automation becomes even more urgent. At the Gartner Data &amp;amp; Analytics Summit in Sydney, Carlie Idoine, VP Analyst at Gartner, emphasized this growing dependency:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;[AI]&amp;hellip; it doesn’t deliver value on its own – AI needs to be tightly aligned with data, analytics, and governance to enable intelligent, adaptive decisions and actions across the organization.&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This perspective mirrors what we’re seeing across modern DevSecOps practices: AI can amplify security, but only when paired with strong foundations in secrets management, governance, and cross-team collaboration.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Build for an AI-first cloud&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Pulumi gives teams infrastructure as code, reusable components, and policy guardrails to deliver consistently across every cloud and AI workload.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="7-platform-engineering--internal-developer-platforms-idps"&gt;7. Platform Engineering &amp;amp; Internal Developer Platforms (IDPs)&lt;/h2&gt;
&lt;p&gt;According to &lt;a href="https://www.gartner.com/en/articles/what-is-platform-engineering"&gt;Gartner&lt;/a&gt;, &lt;strong&gt;by 2026, 80% of large software engineering organizations will establish platform engineering teams&lt;/strong&gt; as internal providers of reusable services, components, and tools for application delivery. Platform engineering will ultimately solve the central problem of cooperation between software developers and operators.&lt;/p&gt;
&lt;p&gt;Mid-size to large companies will begin or continue to invest in implementing &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-3/"&gt;platform engineering practices&lt;/a&gt;, with large tech companies as first adopters. They will provide &lt;a href="https://www.pulumi.com/blog/announcing-pulumi-idp/"&gt;Internal Developer Platforms (IDP)&lt;/a&gt; to elevate the &lt;a href="https://www.pulumi.com/blog/developer-experience-business-critical/"&gt;Developer Experience&lt;/a&gt; (DX, sometimes referred to as DE or DevEx), helping them work faster, like abstracting the complexities of configuring, testing, and validation, deploying infrastructure, and scanning their code for security.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/developer-portal-platform-teams/platform-teams.png"
alt="Internal developer platform-in-a-box. Credit: Pulumi" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;Internal developer platform-in-a-box. Credit: Pulumi&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;IDPs are reshaping how developers interact with cloud infrastructure, bringing together platform engineering, automation, and emerging AI platform engineering practices.&lt;/p&gt;
&lt;h2 id="8-aiops-matures-into-a-cloud-operations-standard"&gt;8. AIOps Matures into a Cloud Operations Standard&lt;/h2&gt;
&lt;p&gt;AIOps is becoming mainstream, helping teams predict failures, auto-scale infrastructure, and resolve incidents with minimal manual effort. As AI and automation continue to evolve, the fusion of these technologies will enable organizations to achieve unprecedented levels of efficiency and scalability.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Proactive Operations&lt;/strong&gt;: AI-powered tools will assist teams in foreseeing issues with greater accuracy, minimizing downtime, and reducing the firefighting nature of incident management. These tools will automatically detect anomalies, optimize performance, and trigger remediation actions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/automation-api/"&gt;Intelligent Automation&lt;/a&gt;&lt;/strong&gt;: Routine operational tasks like patching, monitoring, and resource scaling will be fully automated. AI-driven decision-making will allow for smarter resource allocation and optimization, dynamically adjusting infrastructure and workloads in response to real-time demands and predictions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/insights/"&gt;Data-Driven Insights&lt;/a&gt;&lt;/strong&gt;: AIOps will analyze vast amounts of operational data and provide actionable insights, enabling teams to focus on high-impact tasks such as improving system architecture and user experience. The AI-powered insights will also inform better strategic decisions, helping teams to continuously evolve their DevOps practices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaboration Across Teams&lt;/strong&gt;: AIOps will bridge the gap between DevOps, SecOps, and IT operations by bridging monitoring and automation. Cross-team collaboration will improve as AI systems consolidate and interpret data from various departments, allowing for a more cohesive approach to system management.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AIOps features include observability, automation, and real-time analytics to bridge DevOps, SRE, and IT operations.&lt;/p&gt;
&lt;h2 id="9-kubernetes-dominance-and-increased-complexity"&gt;9. Kubernetes Dominance and Increased Complexity&lt;/h2&gt;
&lt;p&gt;Kubernetes will continue its ascent in 2026. According to &lt;a href="https://www.researchandmarkets.com/reports/6110428/kubernetes-global-strategic-business-report"&gt;Research &amp;amp; Markets&lt;/a&gt;, the global Kubernetes market was valued at USD 2.3 billion in 2024 and is projected to reach USD 8.2 billion by 2030, with a CAGR of 23.8% over the forecast period.&lt;/p&gt;
&lt;p&gt;The CNCF Annual Survey shows AI/ML workloads rapidly moving onto Kubernetes — including batch pipelines, model experimentation, real-time inference, and data preprocessing — even as only 41% of ML/AI developers are cloud-native today. This shift is accelerating as teams need flexible GPU scheduling, distributed pipelines, and portable execution environments.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/#the-2026-convergence-of-ai-platforms-and-policy-in-kubernetes"&gt;Kubernetes is also evolving in response to AI demands&lt;/a&gt;. Inference workloads, powered by LLMs and GPUs, now require low-latency execution closer to the user. This shift is pushing organizations to build intelligent orchestration layers that schedule AI pipelines across edge and core clusters, often leveraging Kubernetes as the common control plane for AI cluster orchestration.&lt;/p&gt;
&lt;p&gt;As we move into 2026, three patterns are becoming clear:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes is evolving to support AI&lt;/strong&gt; through GPU-aware scheduling, Kubernetes GPU scheduling optimizations, and more advanced workload orchestration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Governance and consistency matter more than ever&lt;/strong&gt;, as teams struggle to secure and manage multi-cluster, multi-cloud environments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platform engineering is essential&lt;/strong&gt;, providing curated patterns and automation rather than raw YAML to reduce cognitive load.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Kubernetes will remain a strategic foundation — but operating it effectively now depends on robust automation, strong security controls, and standardized delivery models that scale across clouds, clusters, and AI pipelines.&lt;/p&gt;
&lt;h2 id="10-ai-code-assistants-in-the-enterprise"&gt;10. AI Code Assistants in the Enterprise&lt;/h2&gt;
&lt;p&gt;AI-powered coding assistants like GitHub Copilot, Claude Code, Cursor, and others are rapidly becoming part of modern software development.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By 2027, the use of AI assistants will dramatically increase developer velocity&lt;/strong&gt; to meet functional business requirements for 70% of new digital solutions in production (source: &lt;a href="https://www.digitalnewsasia.com/business/idc-reveals-its-top-predictions-cloud-2023-and-beyond"&gt;IDC&lt;/a&gt;).&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/future-cloud-infrastructure-10-trends-shaping-2024-and-beyond/ai_code_assistants_value.png"
alt="The value of AI code assistants. Credit: Gartner" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;The value of AI code assistants. Credit: Gartner&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;According to &lt;a href="https://www.gartner.com/en/newsroom/press-releases/2024-04-11-gartner-says-75-percent-of-enterprise-software-engineers-will-use-ai-code-assistants-by-2028"&gt;Gartner&lt;/a&gt;, &lt;strong&gt;by 2028, 75% of enterprise software engineers will use dedicated AI code assistants&lt;/strong&gt;, and 63% of organizations are currently piloting, deploying or beginning to use AI code assistants.&lt;/p&gt;
&lt;p&gt;As enterprise adoption of AI assistants increases, expectations are rising: they must not only generate code but also understand the state of infrastructure, configurations, and security posture. That means being able to answer questions about environments, surface misconfigurations, or act directly on infrastructure.&lt;/p&gt;
&lt;p&gt;One of the newest developments is the release of &lt;a href="https://www.pulumi.com/blog/pulumi-agent-skills/"&gt;Pulumi Agent Skills&lt;/a&gt;, a collection of infrastructure expertise packaged for use in AI coding assistants. These skills teach tools such as Claude Code, Cursor, or Gemini CLI to reason about Pulumi projects, reducing hallucination and improving outputs based on real infrastructure conventions and practices.&lt;/p&gt;
&lt;p&gt;Combined with infrastructure access via tools like &lt;a href="https://www.pulumi.com/blog/remote-mcp-server/"&gt;Pulumi’s Remote MCP Server&lt;/a&gt;, teams can build secure, AI-driven workflows where assistants provide insights and Pulumi Neo safely executes actions with previews, policies, and orchestration.&lt;/p&gt;
&lt;p&gt;AI code assistants are no longer experimental; they&amp;rsquo;re fast becoming a competitive advantage in cloud software development.&lt;/p&gt;
&lt;h2 id="the-future-of-cloud-reinvented-for-an-ai-first-decade"&gt;The Future of Cloud: Reinvented for an AI-First Decade&lt;/h2&gt;
&lt;p&gt;Cloud infrastructure is entering its most transformative era since the rise of Kubernetes. The trends shaping 2026 reveal a clear pattern: AI is no longer a workload — it’s becoming the organizing principle of cloud strategy.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AI-native cloud architectures&lt;/strong&gt; that require elastic compute, GPU orchestration, fast data access, and governance built into every layer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure as Code as the operational backbone&lt;/strong&gt;, standardizing deployments across AI, cloud, and hybrid environments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platform engineering and IDPs&lt;/strong&gt; to enable self-service, gold-standard patterns, and automated guardrails&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security integrated into every pipeline&lt;/strong&gt;, with AI-assisted threat detection, strong secrets management, and policy-driven compliance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AIOps and intelligent automation&lt;/strong&gt; are becoming standard for scaling modern cloud systems&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes evolving for AI&lt;/strong&gt;, driving new orchestration patterns across edge, core, and inference clusters&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-cloud and hybrid ecosystems&lt;/strong&gt; accelerating to support interoperability, resilience, and global workload placement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Taken together, these shifts point to a new model of cloud operations that is intelligent, automated, policy-aware, and built on software engineering principles rather than manual configuration.&lt;/p&gt;
&lt;p&gt;Organizations that invest now in &lt;strong&gt;modern IaC&lt;/strong&gt;, &lt;strong&gt;unified governance&lt;/strong&gt;, &lt;strong&gt;reusable components&lt;/strong&gt;, and &lt;strong&gt;policy frameworks&lt;/strong&gt; — all core capabilities of the Pulumi Cloud platform — will be positioned to lead in an AI-first world. The gap between teams that modernize and those that do not will widen rapidly in 2026 and beyond.&lt;/p&gt;
&lt;a
href="https://www.pulumi.com/docs/get-started/"
class="btn btn-primary"
&gt;
Try Pulumi for Free
&lt;/a&gt;</description><author>Sara Huddleston</author><category>ai</category><category>cloud-native</category><category>infrastructure-as-code</category><category>cloud-computing</category><category>multi-cloud</category><category>platform-engineering</category><category>devops</category><category>devsecops</category><category>security</category><category>kubernetes</category></item><item><title>Beyond YAML in Kubernetes: The 2026 Automation Era</title><link>https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/</link><pubDate>Wed, 12 Nov 2025 07:09:46 +0000</pubDate><guid>https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/beyond-yaml-kubernetes-2026-automation-era/index.png" /&gt;
&lt;p&gt;Kubernetes continues to evolve, powering not only applications but entire AI and ML systems across clouds, edges, and enterprises. By 2026, DevOps engineers, SREs, cloud engineers, and platform teams face growing pressure to deliver faster, smarter, and more secure infrastructure at scale.&lt;/p&gt;
&lt;p&gt;Kubernetes automation is entering a new era where infrastructure as code, policy enforcement, and AI-driven orchestration work together to manage cloud environments intelligently.&lt;/p&gt;
&lt;p&gt;Pulumi’s 2025 advancements, including &lt;a href="https://www.pulumi.com/blog/pko-2-0-ga/"&gt;Pulumi Kubernetes Operator 2.0 GA&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/clouds/kubernetes/guides/playbooks/"&gt;new Kubernetes best practices playbooks&lt;/a&gt;, &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt; for AI assisted infrastructure management, and &lt;a href="https://www.pulumi.com/docs/insights/policy/"&gt;Policy Automation&lt;/a&gt;, set the foundation for a new era of Kubernetes automation that extends across every role involved in managing modern infrastructure.&lt;/p&gt;
&lt;h2 id="in-this-kubernetes-article"&gt;In this Kubernetes article:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/#why-kubernetes-needs-to-go-beyond-yaml"&gt;Why Kubernetes Needs to Go Beyond YAML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/#the-2026-convergence-of-ai-platforms-and-policy-in-kubernetes"&gt;The 2026 Convergence of AI, Platforms, and Policy in Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/#the-2026-shift-ai-assisted-kubernetes-operations"&gt;The 2026 Shift: AI-Assisted Kubernetes Operations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/#operator-first-kubernetes-deploys-your-cloud"&gt;Operator-First: Kubernetes Deploys Your Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/#intelligent-infrastructure-across-every-cloud"&gt;Intelligent Kubernetes Infrastructure Across Every Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/#bring-your-yaml-and-helm-then-evolve"&gt;Bring Your YAML and Helm, Then Evolve&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/#begin-your-kubernetes-automation-journey"&gt;Begin Your Kubernetes Automation Journey&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/#workshop-from-zero-to-production-in-kubernetes"&gt;Workshop: From Zero to Production in Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/beyond-yaml-kubernetes-2026-automation-era/#final-thoughts"&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="why-kubernetes-needs-to-go-beyond-yaml"&gt;Why Kubernetes Needs to Go Beyond YAML&lt;/h2&gt;
&lt;p&gt;The article &lt;a href="https://www.pulumi.com/blog/kubernetes-best-practices-i-wish-i-had-known-before/"&gt;&lt;em&gt;Kubernetes Best Practices I Wish I Had Known Before&lt;/em&gt;&lt;/a&gt; highlights a key challenge: relying solely on YAML as the source of truth for Kubernetes is no longer sustainable. Clusters are dynamic, environments multiply, and static YAML files cannot keep up with the complexity of modern infrastructure.&lt;/p&gt;
&lt;p&gt;Teams across disciplines face similar challenges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Multi-cluster and hybrid-cloud sprawl&lt;/li&gt;
&lt;li&gt;Inefficient manual configuration and drift&lt;/li&gt;
&lt;li&gt;Lack of policy enforcement and governance at scale&lt;/li&gt;
&lt;li&gt;Secrets scattered across systems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pulumi addresses these challenges by introducing &lt;strong&gt;general-purpose programming languages&lt;/strong&gt; such as TypeScript, Python, Go, C#, and Java into Kubernetes management. This approach enables teams to define, test, and share reusable infrastructure code, bridging the gap between declarative manifests and modern software engineering practices.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/Q8WKLq-v_6k?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Learn more: &lt;a href="https://www.pulumi.com/docs/iac/clouds/kubernetes/"&gt;Pulumi Kubernetes documentation&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="the-2026-convergence-of-ai-platforms-and-policy-in-kubernetes"&gt;The 2026 Convergence of AI, Platforms, and Policy in Kubernetes&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://www.cncf.io/wp-content/uploads/2025/11/cncf_report_stateofcloud_111025a.pdf"&gt;CNCF State of Cloud Native Development Q3 2025&lt;/a&gt; report shows that more than half of DevOps professionals and nearly a third of all developers now identify as cloud native. Adoption of hybrid and multi-cloud architectures continues to grow, while AI and ML workloads are becoming first-class citizens in Kubernetes environments. The report notes that 41% of professional ML and AI developers are cloud native, confirming that Kubernetes has become a foundational technology for building intelligent, scalable systems.&lt;/p&gt;
&lt;p&gt;This trend highlights how the next generation of Kubernetes operations is evolving. Teams need unified platforms that simplify AI-driven workloads, automatically enforce governance, and reduce operational complexity across environments. Pulumi already delivers this through an integrated platform that brings automation, security, and developer productivity together in one place.&lt;/p&gt;
&lt;p&gt;Pulumi’s platform provides a complete foundation for intelligent infrastructure management that extends from development to production.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/product/neo/"&gt;&lt;strong&gt;Pulumi Neo&lt;/strong&gt;&lt;/a&gt; adds AI-assisted infrastructure management that turns natural language into production-ready Kubernetes and cloud code.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/product/internal-developer-platforms/"&gt;&lt;strong&gt;Pulumi IDP&lt;/strong&gt;&lt;/a&gt; enables engineering and platform teams to build self-service environments that abstract complexity for developers while maintaining consistency and control.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/product/insights-governance/"&gt;&lt;strong&gt;Pulumi Policies&lt;/strong&gt;&lt;/a&gt; brings continuous compliance and policy enforcement directly into the delivery workflow.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/product/secrets-management/"&gt;&lt;strong&gt;Pulumi ESC&lt;/strong&gt;&lt;/a&gt; secures credentials, API keys, and sensitive configurations across Kubernetes and cloud environments.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together, these capabilities form a unified automation and governance layer for Kubernetes and cloud native systems.&lt;/p&gt;
&lt;p&gt;The result is a model where infrastructure, policy, and developer experience work together to power secure, scalable, and AI-ready platforms that meet the needs of engineering teams of every size and discipline, from application development to security and cloud operations.&lt;/p&gt;
&lt;h2 id="the-2026-shift-ai-assisted-kubernetes-operations"&gt;The 2026 Shift: AI-Assisted Kubernetes Operations&lt;/h2&gt;
&lt;p&gt;The next phase of Kubernetes management will be AI-driven, context-aware, and self-healing. Infrastructure will not only follow instructions but also understand intent. This is the vision behind &lt;a href="https://www.pulumi.com/product/neo/"&gt;&lt;strong&gt;Pulumi Neo&lt;/strong&gt;&lt;/a&gt;, an AI Infrastructure Agent designed to help teams automate complex systems.&lt;/p&gt;
&lt;p&gt;Pulumi Neo can interpret natural-language requests such as “deploy a GPU-backed EKS cluster with three node groups,” generate infrastructure code that adheres to organizational policies, and continuously refine that code as environments change.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AI-powered observability and decision-making.&lt;/strong&gt; According to the &lt;a href="https://www.cncf.io/reports/cncf-annual-survey-2024/"&gt;CNCF Annual Survey&lt;/a&gt;, 93% of organizations already use or plan to adopt AI-driven monitoring and predictive analysis for Kubernetes environments. The goal is to identify performance and reliability issues before they affect users. Pulumi Policies assists to get clean and stay clean, while Neo extends this capability by acting on those insights, transforming detected issues into actionable infrastructure updates that teams can validate or deploy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ML and GPU workloads on Kubernetes.&lt;/strong&gt; As organizations expand AI and ML pipelines across clusters, automation and cost efficiency become critical (&lt;a href="https://www.finops.org/wg/scaling-kubernetes-for-ai-ml-workloads-with-finops/"&gt;FinOps Foundation&lt;/a&gt;). &lt;a href="https://www.pulumi.com/docs/insights/discovery/get-started/"&gt;Pulumi Insights&lt;/a&gt; is an intelligent infrastructure management service that helps you discover, understand, manage, and improve your infrastructure. Insights improves security, compliance, and efficiency through AI-powered asset and compliance management.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unifying DevOps, SRE, and MLOps workflows.&lt;/strong&gt; The convergence of software and model delivery continues to accelerate (&lt;a href="https://www.techradar.com/pro/breaking-silos-unifying-devops-and-mlops-into-a-unified-software-supply-chain"&gt;TechRadar&lt;/a&gt;). Pulumi’s code-based approach, combined with Neo’s agentic reasoning, creates a unified workflow for infrastructure, applications, and AI systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additional insights and demonstrations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/product/neo/#video"&gt;Founder/CEO Joe Duffy on Pulumi Neo’s AI Infrastructure Agent vision&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7391188887337000960"&gt;Pulumi Neo 90sec demo and agentic workflows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Kubernetes and Pulumi Neo together represent a future of &lt;strong&gt;autonomous infrastructure management&lt;/strong&gt;, where AI assists teams in deploying, maintaining, and improving their environments intelligently and securely.&lt;/p&gt;
&lt;h2 id="operator-first-kubernetes-deploys-your-cloud"&gt;Operator-First: Kubernetes Deploys Your Cloud&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://www.pulumi.com/blog/pulumi-kubernetes-operator-2-0-ga/"&gt;Pulumi Kubernetes Operator 2.0 GA&lt;/a&gt; introduced a Kubernetes-native approach to infrastructure management. Each Pulumi stack becomes a &lt;strong&gt;Kubernetes Custom Resource&lt;/strong&gt;, allowing Kubernetes itself to execute Pulumi programs written in any supported language. This enables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Management of AWS, Azure, and GCP infrastructure from within the cluster&lt;/li&gt;
&lt;li&gt;Integration with GitOps systems such as Argo CD and Flux&lt;/li&gt;
&lt;li&gt;Continuous reconciliation and drift detection through Pulumi’s state and policy engine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the new &lt;a href="https://www.pulumi.com/blog/pulumi-kubernetes-operator-2-3/"&gt;Pulumi Kubernetes Operator 2.3&lt;/a&gt;, the operator gets even more production-ready features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Faster and more resilient stack updates through improved workspace lifecycle management&lt;/li&gt;
&lt;li&gt;Support for multi-namespace and multi-tenant deployments&lt;/li&gt;
&lt;li&gt;Better visibility with enhanced events, status reporting, and error surfacing&lt;/li&gt;
&lt;li&gt;Performance improvements for large-scale environments and parallel stack operations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Documentation: &lt;a href="https://www.pulumi.com/docs/iac/guides/continuous-delivery/pulumi-kubernetes-operator/"&gt;Using the Pulumi Kubernetes Operator&lt;/a&gt;&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Kubernetes beyond YAML&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Define clusters, workloads, and policies in TypeScript, Python, or Go, and manage EKS, AKS, and GKE from a single code-first workflow.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="intelligent-infrastructure-across-every-cloud"&gt;Intelligent Infrastructure Across Every Cloud&lt;/h2&gt;
&lt;p&gt;Kubernetes has become the control plane for everything from application deployments to AI and ML workloads across clouds and environments. Engineering teams are running clusters on Amazon EKS, Microsoft AKS, and Google GKE while also managing edge, hybrid, and on-premises environments. Pulumi extends Kubernetes automation across all of them, unifying clusters, workloads, and cloud resources under a consistent model of infrastructure as code.&lt;/p&gt;
&lt;p&gt;With Pulumi, teams can use familiar programming languages to define Kubernetes resources, cloud infrastructure, and policies together. This approach provides a single workflow for managing compute, networking, storage, and identity across multiple clouds without relying on brittle YAML templates. It enables consistent provisioning, policy enforcement, and automation across every cluster and environment.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/2P8JLgAc5QI?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;By treating Kubernetes as the universal control plane for cloud infrastructure, Pulumi gives teams a scalable foundation that adapts to any workload and environment. The result is an intelligent, multi-cloud Kubernetes infrastructure that combines the flexibility of cloud providers with the reliability of modern automation.&lt;/p&gt;
&lt;h2 id="bring-your-yaml-and-helm-then-evolve"&gt;Bring Your YAML and Helm, Then Evolve&lt;/h2&gt;
&lt;p&gt;Teams do not need to start from scratch. Pulumi supports &lt;a href="https://www.pulumi.com/docs/iac/guides/migration/migrating-to-pulumi/from-kubernetes/"&gt;importing existing YAML manifests and Helm charts&lt;/a&gt; to help organizations adopt a code-first approach incrementally. Many teams begin by wrapping existing manifests in Pulumi code, then refactor them into reusable components that enforce best practices and compliance policies.&lt;/p&gt;
&lt;p&gt;This hybrid approach enables modernization without disrupting existing CI/CD pipelines or team workflows.&lt;/p&gt;
&lt;h2 id="begin-your-kubernetes-automation-journey"&gt;Begin Your Kubernetes Automation Journey&lt;/h2&gt;
&lt;p&gt;For teams preparing for the next phase of Kubernetes management in 2026:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/iac/get-started/kubernetes/"&gt;Get Started with Kubernetes&lt;/a&gt; to create your first Pulumi program.&lt;/li&gt;
&lt;li&gt;Add the &lt;a href="https://www.pulumi.com/docs/iac/guides/continuous-delivery/pulumi-kubernetes-operator/"&gt;Pulumi Kubernetes Operator&lt;/a&gt; to enable infrastructure deployments from within your clusters.&lt;/li&gt;
&lt;li&gt;Integrate GitOps workflows with Argo CD, Flux, or Jenkins X.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/insights/policy/"&gt;Apply policy guardrails&lt;/a&gt; to enforce security and compliance automatically.&lt;/li&gt;
&lt;li&gt;Refactor infrastructure into &lt;a href="https://www.pulumi.com/docs/iac/concepts/components/"&gt;reusable components&lt;/a&gt; for consistent, scalable operations.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="agentic-workflows-for-production-ready-kubernetes"&gt;Agentic Workflows for Production-ready Kubernetes&lt;/h2&gt;
&lt;p&gt;Experience Kubernetes automation in practice. See how agentic workflows power production-ready Kubernetes by automating GitOps operations, managing environments, and reducing manual effort in this on-demand workshop.&lt;/p&gt;
&lt;p&gt;Watch &lt;a href="https://www.pulumi.com/events/from-zero-to-production-in-kubernetes/"&gt;&lt;em&gt;Agentic Workflows for Production-ready Kubernetes&lt;/em&gt;&lt;/a&gt; to learn how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provision and manage clusters across clouds using general-purpose programming languages&lt;/li&gt;
&lt;li&gt;Multi-cloud Kubernetes infrastructure management&lt;/li&gt;
&lt;li&gt;Fleet management with GitOps (Argo CD)&lt;/li&gt;
&lt;li&gt;Reduce YAML complexity while maintaining reliability and speed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/events/from-zero-to-production-in-kubernetes/"&gt;Watch On Demand&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="final-thoughts"&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Kubernetes in 2026 and beyond is not just for platform engineers. It is for DevOps professionals, SREs, and cloud teams, big and small, responsible for maintaining infrastructure security, reliability, and performance.
Pulumi unifies infrastructure as code, secrets management, policy governance, and AI automation into a single platform, enabling every team to adopt an intelligent, code-driven approach to Kubernetes that scales across workloads, clouds, and the AI-driven future.&lt;/p&gt;
&lt;a
href="https://www.pulumi.com/docs/get-started/"
class="btn btn-primary"
&gt;
Try Pulumi for Free
&lt;/a&gt;</description><author>Sara Huddleston</author><category>kubernetes</category><category>gitops</category><category>pulumi-neo</category><category>infrastructure-as-code</category><category>platform-engineering</category><category>devops</category><category>mlops</category></item><item><title>Announcing the Next Generation of Pulumi Policies: AI-Accelerated Governance for the Cloud</title><link>https://www.pulumi.com/blog/policy-next-gen/</link><pubDate>Wed, 05 Nov 2025 00:05:00 +0000</pubDate><guid>https://www.pulumi.com/blog/policy-next-gen/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/policy-next-gen/index.png" /&gt;
&lt;p&gt;The era of AI-accelerated development has created a paradox: the faster developers move, the bigger the governance challenge becomes. For years, security and platform teams have worked to &amp;ldquo;shift left,&amp;rdquo; but the tools available have been incomplete. Most focus on detection, which is necessary but not sufficient. They identify thousands of policy violations across an organization&amp;rsquo;s infrastructure but leave teams with an overwhelming backlog and no scalable way to remediate it. This creates a persistent gap between finding a problem and fixing it. The result is an impossible choice between development velocity and organizational control, forcing leadership to slow down innovation to manage risk.&lt;/p&gt;
&lt;p&gt;Today, we end that compromise.&lt;/p&gt;
&lt;p&gt;We are thrilled to announce the next generation of Pulumi Policies, a comprehensive governance solution that moves beyond detection to deliver AI-powered remediation at scale. We’re introducing a new lifecycle to secure your cloud: first, &lt;strong&gt;Get Clean&lt;/strong&gt; by using AI to fix your existing policy violations. Second, &lt;strong&gt;Stay Clean&lt;/strong&gt; by using policy as a universal guardrail that makes AI-driven development not just fast, but fundamentally safe. These are not strictly sequential steps; you can begin enforcing &amp;ldquo;Stay Clean&amp;rdquo; policies for all new infrastructure while you simultaneously work on the &amp;ldquo;Get Clean&amp;rdquo; process for your existing footprint.&lt;/p&gt;
&lt;p&gt;Watch our Launch Video:&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/mwcrOTEf1EQ?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id="part-1-get-clean---from-thousands-of-issues-to-a-compliant-state"&gt;Part 1: Get Clean - From Thousands of Issues to a Compliant State&lt;/h2&gt;
&lt;p&gt;The first step to a secure cloud is tackling the mountain of existing misconfigurations spread across your environments.&lt;/p&gt;
&lt;h3 id="first-gain-complete-visibility-with-the-new-policy-findings-hub"&gt;First, Gain Complete Visibility with the New Policy Findings Hub&lt;/h3&gt;
&lt;p&gt;To fix your issues, you first need to see them clearly. We have introduced a powerful &lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/policy-issue-management/"&gt;Policy Findings Hub&lt;/a&gt;&lt;/strong&gt; designed to give every stakeholder the exact view they need.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Overview Tab:&lt;/strong&gt; A high-level dashboard with compliance scores for leadership to track trends and measure your organization&amp;rsquo;s posture.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Compliance Tab:&lt;/strong&gt; A control-centric view for auditors and infosec teams, grouping findings by policy (e.g., CIS, NIST) to simplify evidence gathering and prove compliance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Issues Tab:&lt;/strong&gt; A collaborative workspace for platform and development teams to triage, assign, prioritize, and track the remediation of every policy issue.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This hub is powered by our flexible audit capabilities. With &lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/policy-audit-scans-for-stacks/"&gt;Audit Scans for IaC Stacks&lt;/a&gt;&lt;/strong&gt;, you can get an instant compliance baseline on all your existing Pulumi-managed infrastructure without blocking developers or re-deploying thousands of stacks. This is combined with discovery scans of your cloud accounts to give you a single, unified view of every resource, whether managed by Pulumi or not.&lt;/p&gt;
&lt;h3 id="the-solution-to-remediation-at-scale-ai-powered-fixes-with-pulumi-neo"&gt;The Solution to Remediation at Scale: AI-Powered Fixes with Pulumi Neo&lt;/h3&gt;
&lt;p&gt;Visibility creates a new problem: an overwhelming backlog. Manually fixing thousands of issues is an impossible task.&lt;/p&gt;
&lt;p&gt;This is where Pulumi Neo provides a powerful solution.&lt;/p&gt;
&lt;p&gt;Pulumi Neo, our AI platform engineer, is now integrated directly into the Policy Findings hub to automate the most difficult part of the process: the fix itself. From the Issues tab, your teams can now select a group of policy issues, assign them to Neo, and trigger a remediation flow.&lt;/p&gt;
&lt;p&gt;Neo is smart. It will:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Analyze the non-compliant resources and the policies they are violating.&lt;/li&gt;
&lt;li&gt;Understand the required configuration to make them compliant.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generate a pull request with the exact code changes needed to fix the issues.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Most powerfully, for an unmanaged resource discovered via a cloud scan, Neo will generate the code to &lt;strong&gt;import the resource into a Pulumi stack and apply the fix.&lt;/strong&gt; This &amp;ldquo;Import and Fix&amp;rdquo; workflow transforms unmanaged infrastructure into governed, compliant code, turning a task that could take a developer hours into a simple review-and-merge process. Your teams can finally burn down their issue backlog and achieve a state of continuous compliance.&lt;/p&gt;
&lt;h2 id="part-2-stay-clean---the-universal-guardrail-for-humans-and-ai"&gt;Part 2: Stay Clean - The Universal Guardrail for Humans and AI&lt;/h2&gt;
&lt;p&gt;Once you begin cleaning your environment, the next challenge is to &lt;em&gt;stay&lt;/em&gt; clean. As AI accelerates infrastructure creation, you need robust guardrails to ensure it doesn&amp;rsquo;t also accelerate the creation of security risks.&lt;/p&gt;
&lt;p&gt;The answer is &lt;strong&gt;Policy as &lt;em&gt;Real&lt;/em&gt; Code.&lt;/strong&gt; Pulumi Policies uses general-purpose languages like TypeScript and Python to create sophisticated guardrails that govern every change. To help you establish these controls immediately, we are launching a new suite of pre-built compliance packs authored and maintained by Pulumi experts.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th style="text-align: center"&gt;AWS&lt;/th&gt;
&lt;th style="text-align: center"&gt;Azure&lt;/th&gt;
&lt;th style="text-align: center"&gt;Google Cloud&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CIS Controls v8.1&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NIST SP 800-53 Rev. 5&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCI DSS v4.0&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HITRUST CSF v11.5&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pulumi Best Practices&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;These policies act as a universal guardrail for your entire organization by blocking non-compliant changes during &lt;code&gt;pulumi up&lt;/code&gt;, before they are ever created. Learn more about our &lt;a href="https://www.pulumi.com/blog/policy-packs-cis-nist-pci/"&gt;compliance packs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And now, you can even use &lt;strong&gt;Neo to author new policies&lt;/strong&gt;. You can ask Neo in plain English to &amp;ldquo;create a policy that prevents overly permissive IAM roles,&amp;rdquo; and it will generate the code for you. This creates a powerful, dynamic governance system where AI can help you build the very rules that then govern its own actions. If you then ask Neo to create an admin role, the deployment will be blocked by the policy it just helped write. This is how we make AI safe to go fast.&lt;/p&gt;
&lt;h2 id="a-new-era-of-collaboration"&gt;A New Era of Collaboration&lt;/h2&gt;
&lt;p&gt;This &amp;ldquo;Get Clean, Stay Clean&amp;rdquo; lifecycle transforms how teams work together:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Platform Teams&lt;/strong&gt; lead prevention by building real-code guardrails, proving their value with measurable compliance scores.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security Teams&lt;/strong&gt; drive the &amp;ldquo;Get Clean&amp;rdquo; process with continuous, non-blocking audit scans and use the Findings hub to manage compliance without slowing development.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="governance-that-accelerates-you"&gt;Governance That Accelerates You&lt;/h2&gt;
&lt;p&gt;The age of AI-driven development demands AI-powered governance. With this new generation of Pulumi Policies, we are providing the essential infrastructure for platform engineering teams to not just survive, but thrive. You can finally build preventative guardrails that developers love, secure your cloud at scale, and transform governance from a blocker into a business accelerator. Learn more about &lt;a href="https://www.pulumi.com/product/insights-governance/"&gt;Pulumi Insights &amp;amp; Governance capabilities&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This powerful new experience is available today. Navigate to the &lt;strong&gt;Policies&lt;/strong&gt; and &lt;strong&gt;Policy Findings&lt;/strong&gt; tab in Pulumi Cloud to explore your new governance capabilities and meet the future of platform engineering.&lt;/p&gt;
&lt;h2 id="try-pulumi-policies"&gt;Try Pulumi Policies&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Ready to try these features?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://app.pulumi.com/signup"&gt;Sign up for Pulumi Cloud&lt;/a&gt; and start a Neo task&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/insights/policy/get-started/"&gt;Read the Get Started guide&lt;/a&gt; to set up and apply a policy group to stacks and clouds.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://slack.pulumi.com/"&gt;Join the Community Slack&lt;/a&gt; to share feedback on the new features&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For complete documentation, visit our &lt;a href="https://www.pulumi.com/docs/insights/policy/"&gt;Policies documentation&lt;/a&gt;.&lt;/p&gt;</description><author>Craig Symonds</author><author>Tyler D</author><author>Arun Loganathan</author><category>policy-as-code</category><category>features</category><category>compliance</category><category>governance</category><category>pulumi-neo</category><category>ai</category><category>platform-engineering</category></item><item><title>Component Usage Tracking in Pulumi Private Registry</title><link>https://www.pulumi.com/blog/idp-component-usage-tracking/</link><pubDate>Tue, 28 Oct 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/idp-component-usage-tracking/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/idp-component-usage-tracking/index.png" /&gt;
&lt;p&gt;Platform teams publishing components to the Pulumi Private Registry can now see exactly which stacks are using each component and at which version.&lt;/p&gt;
&lt;h2 id="the-visibility-problem"&gt;The visibility problem&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ve published a new major version of a component to your private registry. Most teams across your organization have adopted it. Then you need to answer a critical question: &amp;ldquo;Which teams still haven&amp;rsquo;t adopted it?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This visibility gap creates real consequences. When a security vulnerability appears in an old version, you can&amp;rsquo;t assess the blast radius. When you want to deprecate a version, you don&amp;rsquo;t know which teams need to migrate. When you release a new feature, you can&amp;rsquo;t measure adoption. Version sprawl accumulates silently.&lt;/p&gt;
&lt;h2 id="centralized-components-centralized-visibility"&gt;Centralized components, centralized visibility&lt;/h2&gt;
&lt;p&gt;The Pulumi IDP registry solves this by providing both centralized distribution and centralized insight. When you publish a component to the registry, you automatically gain visibility into its usage across your organization.&lt;/p&gt;
&lt;p&gt;The new usage tracking feature shows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Which stacks are using your component&lt;/li&gt;
&lt;li&gt;What version each stack is running&lt;/li&gt;
&lt;li&gt;When each stack was last updated&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="idp-component-used-by.png" alt="Component usage tracking in the Pulumi IDP registry"&gt;&lt;/p&gt;
&lt;p&gt;Access usage data through the &amp;ldquo;Used By&amp;rdquo; tab on any component&amp;rsquo;s detail page in the registry. The view respects your existing access controls, showing only stacks you have permission to see.&lt;/p&gt;
&lt;h2 id="why-this-matters"&gt;Why this matters&lt;/h2&gt;
&lt;p&gt;This visibility transforms conversations that were previously not possible or painfully slow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Security response:&lt;/strong&gt; When a vulnerability is discovered in version 1.2.0 of your component, you can immediately identify every affected stack and reach out to the right teams. What used to take hours or days of detective work now takes minutes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Deprecation planning:&lt;/strong&gt; Before removing support for version 1.x, you can see exactly which teams are still using it and coordinate migration timelines with complete information.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Version sprawl management:&lt;/strong&gt; See the full distribution of versions in use across your organization and make informed decisions about consolidation.&lt;/p&gt;
&lt;p&gt;The registry becomes your source of truth, not just for distributing components, but for understanding how they&amp;rsquo;re used.&lt;/p&gt;
&lt;h2 id="get-started"&gt;Get started&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re already publishing components to the Pulumi IDP registry, usage tracking is automatically available. Visit any component detail page to see the &amp;ldquo;Used By&amp;rdquo; tab.&lt;/p&gt;
&lt;p&gt;If you haven&amp;rsquo;t published to the registry yet, now is the time to start. Publishing a component is as simple as running &lt;code&gt;pulumi publish&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For more information, see the &lt;a href="https://www.pulumi.com/docs/idp/get-started/private-registry/"&gt;private registry documentation&lt;/a&gt;.&lt;/p&gt;</description><author>Pulumi IDP Team</author><category>internal-developer-platform</category><category>features</category><category>platform-engineering</category></item><item><title>Grounded AI: Why Neo Knows Your Infrastructure</title><link>https://www.pulumi.com/blog/grounded-ai-why-neo-knows-your-infrastructure/</link><pubDate>Fri, 24 Oct 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/grounded-ai-why-neo-knows-your-infrastructure/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/grounded-ai-why-neo-knows-your-infrastructure/index.png" /&gt;
&lt;p&gt;Ask a generic LLM to &amp;ldquo;fix my broken deployment,&amp;rdquo; and you&amp;rsquo;ll get generic advice. Ask Pulumi Neo the same question, and you&amp;rsquo;ll get a fix plan grounded in your actual infrastructure state.&lt;/p&gt;
&lt;p&gt;The difference isn&amp;rsquo;t about better prompts or newer models. It&amp;rsquo;s about what the AI actually knows. Generic LLMs have been trained on the internet. Neo has been trained on your infrastructure.&lt;/p&gt;
&lt;p&gt;This distinction matters more than you&amp;rsquo;d think.&lt;/p&gt;
&lt;h2 id="the-grounding-problem"&gt;The grounding problem&lt;/h2&gt;
&lt;p&gt;Most AI tools treat infrastructure like a text generation problem. You describe what you want, the model produces code, and you hope it works.&lt;/p&gt;
&lt;p&gt;This approach fails more often than it succeeds because the AI has no connection to your actual infrastructure. It doesn&amp;rsquo;t know what resources you&amp;rsquo;ve already deployed, what dependencies exist, or what policies you need to follow. It&amp;rsquo;s generating code from patterns it learned on the internet, not from understanding your environment.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-neo/"&gt;Pulumi Neo&lt;/a&gt; takes a different approach. It&amp;rsquo;s trained on your infrastructure context: your programs, your state, your resource relationships. When you ask Neo about drift, it doesn&amp;rsquo;t guess. It queries your actual deployment history. When it suggests a fix, it reasons from your program graph, not generic examples.&lt;/p&gt;
&lt;p&gt;Neo doesn&amp;rsquo;t just autocomplete code. It &lt;a href="https://www.pulumi.com/docs/ai/"&gt;understands state, resources, dependencies&lt;/a&gt;, and cloud behavior. When something fails, Neo explains why, not just what.&lt;/p&gt;
&lt;p&gt;This is what makes it grounded AI: it&amp;rsquo;s anchored to the reality of your infrastructure, not floating in a sea of internet-trained probabilities.&lt;/p&gt;
&lt;h2 id="what-makes-neo-different"&gt;What makes Neo different&lt;/h2&gt;
&lt;p&gt;The foundation matters more than you&amp;rsquo;d think.&lt;/p&gt;
&lt;p&gt;Traditional AI tools fail in DevOps because they operate in a vacuum. Ask a generic LLM to &amp;ldquo;fix my broken deployment,&amp;rdquo; and you&amp;rsquo;ll get generic advice that ignores your specific infrastructure, your state, your constraints.&lt;/p&gt;
&lt;p&gt;The difference with systems like Pulumi Neo comes down to what powers them: not just data, but &lt;strong&gt;context&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Think of it this way: a data lake is a massive repository of information sitting inert, waiting to be queried. A &lt;strong&gt;context lake&lt;/strong&gt; is something else entirely. It&amp;rsquo;s a structured repository that aggregates knowledge about your domain and feeds it to AI systems.&lt;/p&gt;
&lt;p&gt;&lt;img src="img_1.png" alt="img_1.png"&gt;&lt;/p&gt;
&lt;p&gt;A context lake contains things that matter:&lt;/p&gt;
&lt;p&gt;Your infrastructure programs, resource definitions, API schemas, service dependencies. In Pulumi&amp;rsquo;s case, this includes your program graph, component models, stack configurations.&lt;/p&gt;
&lt;p&gt;Real-time metrics, deployment history, drift detection, policy violations. The live pulse of your infrastructure as it actually runs in production.&lt;/p&gt;
&lt;p&gt;Ownership information, compliance policies, access controls, quality signals. The organizational context that determines what changes are safe, who can make them, and why they matter.&lt;/p&gt;
&lt;p&gt;Pulumi&amp;rsquo;s approach builds on this principle. Your infrastructure programs, state files, resource metadata, policy definitions. All of this becomes queryable context. Neo doesn&amp;rsquo;t hallucinate solutions because it&amp;rsquo;s grounded in your actual infrastructure. It knows what you&amp;rsquo;ve deployed, how resources relate to each other, what dependencies exist, what&amp;rsquo;s drifted.&lt;/p&gt;
&lt;p&gt;This is the architectural shift that makes AI-powered DevOps actually work. AI agents are only as effective as the context they can access and the guardrails you have in place to keep them in check. You&amp;rsquo;re not just automating actions anymore. You&amp;rsquo;re automating understanding.&lt;/p&gt;
&lt;h2 id="grounded-reasoning-in-practice"&gt;Grounded reasoning in practice&lt;/h2&gt;
&lt;p&gt;Early DevOps automated actions. Modern AI agents automate decisions. But grounded AI does something different: it automates understanding.&lt;/p&gt;
&lt;p&gt;When you combine observability data, infrastructure-as-code programs, and deployment history into a context lake, the AI doesn&amp;rsquo;t just predict what might happen. It reasons about what is happening based on your actual infrastructure state.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/blog/10-things-you-can-do-with-neo/"&gt;Neo can watch infrastructure drift&lt;/a&gt;, identify whether it stems from a manual change or a misconfigured resource, and generate a fix plan that maps back to your Pulumi program. That feedback isn&amp;rsquo;t guesswork. It&amp;rsquo;s grounded in the same infrastructure metadata developers already use. The context lake ensures Neo isn&amp;rsquo;t making probabilistic predictions. It&amp;rsquo;s reasoning from your specific infrastructure truth.&lt;/p&gt;
&lt;p&gt;&lt;img src="img_2.png" alt="img_2.png"&gt;&lt;/p&gt;
&lt;p&gt;This is what separates grounded AI from generic LLMs. Neo doesn&amp;rsquo;t just automate deployment. It understands the intent behind it.&lt;/p&gt;
&lt;h2 id="the-human-layer-stays-critical"&gt;The human layer stays critical&lt;/h2&gt;
&lt;p&gt;Grounded AI doesn&amp;rsquo;t replace engineering judgment. Every engineer who&amp;rsquo;s tried to prompt a generic LLM to &amp;ldquo;write a Pulumi program for me&amp;rdquo; knows how quickly hallucinations creep in. You still need human context: the judgment to choose the right platform, the discipline to model dependencies, the awareness of compliance and cost.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s where grounded AI like Neo fits best. It&amp;rsquo;s not a chatbot for infrastructure. &lt;a href="https://www.pulumi.com/docs/ai/get-started/"&gt;It&amp;rsquo;s an extension of your own reasoning&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Neo learns from the same program graph and state data you already manage, drawing from a continuously updated context lake of your infrastructure reality. Its recommendations stay grounded in your environment, not floating in a generic prompt window trained on the public internet.&lt;/p&gt;
&lt;p&gt;The opportunity isn&amp;rsquo;t about replacing engineers. It&amp;rsquo;s about creating smarter feedback loops between human expertise and AI that actually understands your infrastructure.&lt;/p&gt;
&lt;h2 id="what-grounded-ai-enables"&gt;What grounded AI enables&lt;/h2&gt;
&lt;p&gt;The first generation of DevOps automated deployment. Grounded AI automates understanding.&lt;/p&gt;
&lt;p&gt;Infrastructure becomes queryable. AI-powered observability correlates incidents before they cascade. CI/CD becomes continuous reasoning rather than continuous execution. &lt;a href="https://www.pulumi.com/blog/why-every-platform-engineer-should-care-about-kubernetes-operators/"&gt;Platform teams&lt;/a&gt; spend less time fighting YAML and more time guiding systems that reason alongside them.&lt;/p&gt;
&lt;p&gt;The context lake architecture makes this possible. Instead of static documentation and scattered tribal knowledge, your infrastructure context becomes something AI agents can actually query and reason over.&lt;/p&gt;
&lt;p&gt;Grounded AI won&amp;rsquo;t replace engineers. But it will change what engineering means: less time translating intent into YAML, more time reasoning about systems at a higher level.&lt;/p&gt;
&lt;h2 id="try-it-yourself"&gt;Try it yourself&lt;/h2&gt;
&lt;p&gt;Want to see what infrastructure cognition looks like in practice? &lt;a href="https://www.pulumi.com/docs/ai/get-started/"&gt;Get started with Neo&lt;/a&gt; and ask it about your infrastructure. Watch it reason through drift detection, generate fix plans, or explain complex resource relationships in plain English. For a wider survey of the category, see our guide to the &lt;a href="https://www.pulumi.com/blog/ai-infrastructure-tools/"&gt;best AI infrastructure tools&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Neo is available today for teams using Pulumi Cloud. The cognitive layer isn&amp;rsquo;t coming. It&amp;rsquo;s already here.&lt;/p&gt;</description><author>Engin Diri</author><category>ai</category><category>devops</category><category>pulumi-neo</category><category>platform-engineering</category><category>infrastructure-as-code</category><category>context-lake</category></item><item><title>Day 2 Operations: Drift Detection and Remediation</title><link>https://www.pulumi.com/blog/day-2-operations-drift-detection-and-remediation/</link><pubDate>Fri, 24 Oct 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/day-2-operations-drift-detection-and-remediation/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/day-2-operations-drift-detection-and-remediation/index.png" /&gt;
&lt;p&gt;Welcome to the fourth post in our &lt;strong&gt;IDP Best Practices&lt;/strong&gt; series. Today we&amp;rsquo;re diving into the world of drift detection and remediation, those critical day 2 operations that keep your infrastructure aligned with its intended configuration long after the initial deployment.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve built a beautiful platform with robust guardrails, comprehensive templates, and well-defined golden paths. Your developers are productive, deployments are smooth, and everything seems perfect. Then reality hits. An on-call engineer makes an emergency change through the AWS console during a 3 AM incident. A team member tweaks a security group rule to debug a connection issue and forgets to revert it. Auto-scaling adjusts capacity based on load patterns. Before you know it, your actual infrastructure has quietly diverged from what your code describes.&lt;/p&gt;
&lt;p&gt;This post continues our journey through the IDP Best Practices series. We&amp;rsquo;ve covered strategy and self-service infrastructure, built golden paths with components and templates, and established deployment guardrails through policy as code. Now we&amp;rsquo;re tackling what happens after deployment when the real world starts making changes to your carefully crafted infrastructure.&lt;/p&gt;
&lt;h2 id="the-reality-of-infrastructure-drift"&gt;The Reality of Infrastructure Drift&lt;/h2&gt;
&lt;p&gt;Let me paint you a picture that might feel uncomfortably familiar. It&amp;rsquo;s Saturday afternoon, and you&amp;rsquo;re enjoying a barbecue with friends when your phone buzzes with that dreaded alert: production is down. You rush to your laptop, but you&amp;rsquo;re not on the corporate VPN. The AWS console is accessible, but you can&amp;rsquo;t reach the application itself to properly diagnose the issue.&lt;/p&gt;
&lt;p&gt;Faced with a growing incident and impatient stakeholders, you make a quick decision. You modify the security group directly in the console, temporarily allowing access from anywhere (0.0.0.0/0) just so you can get in and fix the problem. Twenty minutes later, the issue is resolved, everyone&amp;rsquo;s relieved, and you return to your barbecue. That temporary security group change? It stays there, a silent time bomb waiting to be discovered in your next security audit.&lt;/p&gt;
&lt;p&gt;This scenario plays out in organizations every day. Your infrastructure has now drifted from its intended state, and it will continue drifting, accumulating more changes, until someone or something notices and fixes it. Each untracked change increases the gap between what you think you have and what actually exists in production.&lt;/p&gt;
&lt;h2 id="understanding-the-prevention-vs-detection-paradigm"&gt;Understanding the Prevention vs. Detection Paradigm&lt;/h2&gt;
&lt;p&gt;When building a robust platform, you need to think in layers of defense. Your first instinct might be to prevent all drift from happening in the first place, and that&amp;rsquo;s absolutely the right starting point. But prevention alone isn&amp;rsquo;t enough in the messy reality of production operations.&lt;/p&gt;
&lt;h3 id="prevention-the-first-line-of-defense"&gt;Prevention: The First Line of Defense&lt;/h3&gt;
&lt;p&gt;Prevention is what we&amp;rsquo;ve been building throughout this series. You establish code reviews where teammates scrutinize infrastructure changes before they go live. You implement automated testing that validates configurations before deployment. You deploy &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard"&gt;CrossGuard policies&lt;/a&gt; that act as guardrails, blocking misconfigurations before they can cause damage. You create &lt;a href="https://www.pulumi.com/blog/golden-paths-infrastructure-components-and-templates"&gt;standardized components&lt;/a&gt; that encode best practices, making it easier to do the right thing than the wrong thing.&lt;/p&gt;
&lt;p&gt;These preventative measures work brilliantly for changes that flow through your normal IaC pipeline. They catch typos, enforce standards, and maintain consistency across your infrastructure. But they have a critical blind spot: they can&amp;rsquo;t see changes that bypass your pipeline entirely.&lt;/p&gt;
&lt;h3 id="detection-and-remediation-the-safety-net"&gt;Detection and Remediation: The Safety Net&lt;/h3&gt;
&lt;p&gt;This is where drift detection enters the picture. Think of it as continuous verification, constantly comparing what should exist with what actually exists. While prevention blocks most issues at the gate, detection catches everything that finds another way in.&lt;/p&gt;
&lt;p&gt;What kinds of changes slip past prevention? Emergency modifications made during incidents when there&amp;rsquo;s no time for a proper code review. Console changes made by well-meaning engineers debugging production issues. External factors you can&amp;rsquo;t control, like AWS changing service limits or deprecating API endpoints. Even accidental modifications by team members who thought they were in the staging environment.&lt;/p&gt;
&lt;p&gt;The truth is, no matter how robust your preventative controls, you need detective controls to maintain infrastructure integrity. Prevention and detection work together, creating a comprehensive defense against infrastructure chaos.&lt;/p&gt;
&lt;h2 id="what-is-infrastructure-drift"&gt;What Is Infrastructure Drift?&lt;/h2&gt;
&lt;p&gt;Infrastructure drift sounds technical, but the concept is surprisingly simple. Drift occurs when your actual infrastructure state doesn&amp;rsquo;t match your declared state in code. It&amp;rsquo;s the gap between intention and reality, between what you coded and what&amp;rsquo;s actually running.&lt;/p&gt;
&lt;p&gt;To understand drift properly, you need to grasp three distinct states that Pulumi manages. First, there&amp;rsquo;s the &lt;strong&gt;desired state&lt;/strong&gt;, which is what your Pulumi program declares in code. This is your intention, your blueprint for how things should be. Then there&amp;rsquo;s the &lt;strong&gt;current state&lt;/strong&gt;, stored in Pulumi&amp;rsquo;s &lt;a href="https://www.pulumi.com/docs/iac/concepts/state-and-backends"&gt;state file&lt;/a&gt;, which tracks what Pulumi believes exists based on its last interaction with your cloud provider. Finally, there&amp;rsquo;s the &lt;strong&gt;actual state&lt;/strong&gt;, the ground truth of what really exists in your cloud provider right now.&lt;/p&gt;
&lt;p&gt;The journey to drift typically follows a predictable pattern. You start by running &lt;code&gt;pulumi up&lt;/code&gt; to deploy your resources, and everything is in perfect harmony. Pulumi creates the resources, records their configuration in its state file, and all three states align perfectly. Time passes, and your resources continue running in the cloud, serving traffic and doing their job.&lt;/p&gt;
&lt;p&gt;Then someone makes a manual change. Maybe they modify a resource directly in the console, or an external system alters a configuration. Suddenly, your actual state has diverged from both your current state (what Pulumi thinks exists) and your desired state (what your code says should exist). You now have drift, and it will persist until you detect and address it.&lt;/p&gt;
&lt;h2 id="pulumis-drift-detection-and-remediation-workflow"&gt;Pulumi&amp;rsquo;s Drift Detection and Remediation Workflow&lt;/h2&gt;
&lt;p&gt;Pulumi provides a complete workflow for handling drift that&amp;rsquo;s both powerful and surprisingly straightforward. Rather than treating drift as an exceptional case, Pulumi makes it a routine part of infrastructure management.&lt;/p&gt;
&lt;h3 id="1-drift-detection-with-pulumi-refresh"&gt;1. Drift Detection with &lt;code&gt;pulumi refresh&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The foundation of drift detection is the &lt;a href="https://www.pulumi.com/docs/iac/cli/commands/pulumi_refresh"&gt;&lt;code&gt;pulumi refresh&lt;/code&gt;&lt;/a&gt; command. When you run this command, Pulumi springs into action, querying your cloud providers to discover the actual state of your resources. It then compares this reality against what it has recorded in its state file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Run drift detection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi refresh --preview-only
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# This command:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. Reads your current Pulumi state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. Queries cloud providers for actual resource configurations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. Identifies any differences&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4. Reports what has drifted&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;--preview-only&lt;/code&gt; flag is particularly useful here. It shows you exactly what&amp;rsquo;s drifted without making any changes to your state file. You get a clear report of the differences, allowing you to review and understand the drift before deciding how to handle it.&lt;/p&gt;
&lt;h3 id="2-state-reconciliation-with-pulumi-refresh"&gt;2. State Reconciliation with &lt;code&gt;pulumi refresh&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;After reviewing the drift, you face a decision. If the changes are legitimate and should be preserved, you can update your state file to match reality:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Update state file to match cloud reality&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi refresh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# This command:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. Detects drift (as above)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. Updates state file to match actual cloud state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. Prepares for remediation via pulumi up&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This reconciliation step is crucial. It acknowledges the current reality and updates Pulumi&amp;rsquo;s understanding of your infrastructure without making any actual changes to your resources. You&amp;rsquo;re essentially telling Pulumi, &amp;ldquo;This is what actually exists right now.&amp;rdquo;&lt;/p&gt;
&lt;h3 id="3-drift-remediation-with-pulumi-up"&gt;3. Drift Remediation with &lt;code&gt;pulumi up&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;With your state file now reflecting reality, you can use &lt;a href="https://www.pulumi.com/docs/iac/cli/commands/pulumi_up"&gt;&lt;code&gt;pulumi up&lt;/code&gt;&lt;/a&gt; to remediate the drift. This command compares the updated state against your code and determines what changes are needed to restore your infrastructure to its intended configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Remediate drift - restore to desired state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi up
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# This command:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. Compares updated state with your Pulumi program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. Identifies required changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. Applies changes to restore infrastructure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This three-step dance of detect, reconcile, and remediate gives you complete control over how you handle drift. You can review changes, decide whether to keep or revert them, and ensure your infrastructure returns to its intended state.&lt;/p&gt;
&lt;h2 id="automating-drift-detection-with-pulumi-deployments"&gt;Automating Drift Detection with Pulumi Deployments&lt;/h2&gt;
&lt;p&gt;Running &lt;code&gt;pulumi refresh&lt;/code&gt; manually works great for small teams and simple infrastructures, but it doesn&amp;rsquo;t scale. As your platform grows to dozens or hundreds of stacks across multiple environments, manual drift detection becomes impossible. This is where &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments"&gt;Pulumi Deployments&lt;/a&gt; transforms drift detection from a manual chore into an automated safeguard.&lt;/p&gt;
&lt;h3 id="setting-up-automated-drift-detection"&gt;Setting Up Automated Drift Detection&lt;/h3&gt;
&lt;p&gt;The journey to automated drift detection starts with connecting your infrastructure code to Pulumi&amp;rsquo;s deployment system. Let&amp;rsquo;s walk through the setup process.&lt;/p&gt;
&lt;h4 id="step-1-configure-deployment-settings"&gt;Step 1: Configure Deployment Settings&lt;/h4&gt;
&lt;p&gt;Your first step is connecting Pulumi to your source control system using &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/get-started"&gt;Deployment Settings&lt;/a&gt;. This integration allows Pulumi to access your infrastructure code and run automated operations:&lt;/p&gt;
&lt;p&gt;&lt;img src="img.png" alt="img.png"&gt;&lt;/p&gt;
&lt;p&gt;Pulumi offers native integrations with all major version control systems. If you&amp;rsquo;re using GitHub, you get full app integration with &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/ci-cd-integration-assistant"&gt;PR previews&lt;/a&gt;, making it easy to see the impact of changes before merging. GitLab users enjoy similar functionality with merge request automation. For other Git providers or self-hosted solutions, you can use raw Git integration with direct repository access using credentials.&lt;/p&gt;
&lt;h4 id="step-2-create-drift-detection-schedules"&gt;Step 2: Create Drift Detection Schedules&lt;/h4&gt;
&lt;p&gt;With your source control connected, you can now configure &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/drift"&gt;automated drift detection&lt;/a&gt; to run on whatever schedule makes sense for your organization. Some teams check hourly for production environments, while others might run daily checks for development stacks:&lt;/p&gt;
&lt;p&gt;&lt;img src="img_1.png" alt="img_1.png"&gt;&lt;/p&gt;
&lt;p&gt;For environments where you&amp;rsquo;re confident in your automation, you can take it a step further and enable automatic remediation:&lt;/p&gt;
&lt;p&gt;&lt;img src="img_2.png" alt="img_2.png"&gt;&lt;/p&gt;
&lt;p&gt;With auto-remediation enabled, Pulumi not only detects drift but automatically runs &lt;code&gt;pulumi up&lt;/code&gt; to restore your infrastructure to its intended state. This is powerful but should be used carefully, especially in production environments.&lt;/p&gt;
&lt;h4 id="step-3-configure-webhooks-for-notifications"&gt;Step 3: Configure Webhooks for Notifications&lt;/h4&gt;
&lt;p&gt;Detecting drift is only valuable if the right people know about it. Pulumi&amp;rsquo;s &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/webhooks"&gt;webhook system&lt;/a&gt; ensures your team stays informed when drift occurs:&lt;/p&gt;
&lt;p&gt;&lt;img src="img_3.png" alt="img_3.png"&gt;&lt;/p&gt;
&lt;p&gt;You can route notifications wherever your team actually pays attention. Send alerts directly to Slack channels where your ops team congregates. Push notifications to Microsoft Teams if that&amp;rsquo;s your collaboration platform. Use custom webhooks to integrate with PagerDuty, Datadog, or any other monitoring system. You can even use deployment triggers to automatically run dependent stacks when drift is detected and fixed.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Automate drift detection with Pulumi&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Connect your stacks to Pulumi Deployments, schedule drift checks across every environment, and route alerts to Slack or Teams the moment your infrastructure diverges from code.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="handling-common-drift-scenarios"&gt;Handling Common Drift Scenarios&lt;/h2&gt;
&lt;p&gt;Every organization faces similar drift scenarios. Understanding how to handle these common cases will prepare you for real-world operations.&lt;/p&gt;
&lt;h3 id="scenario-1-emergency-hotfix"&gt;Scenario 1: Emergency Hotfix&lt;/h3&gt;
&lt;p&gt;The most common drift scenario occurs during incidents. Someone makes an emergency change to fix production, and now you need to decide whether to keep or revert that change:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. Acknowledge the drift&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi refresh --stack production
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. Review the changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi preview --stack production
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. Either incorporate or revert&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Option A: Accept the change&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi refresh --stack production --yes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Option B: Revert to code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi up --stack production --yes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The key here is having a clear process. First, acknowledge the drift by running refresh to update your state. Then review the changes carefully. Finally, make an explicit decision: either accept the change by updating your code to match, or revert it by running &lt;code&gt;pulumi up&lt;/code&gt; to restore the original configuration.&lt;/p&gt;
&lt;h3 id="scenario-2-legitimate-external-changes"&gt;Scenario 2: Legitimate External Changes&lt;/h3&gt;
&lt;p&gt;Not all drift is bad. Auto-scaling groups adjust capacity based on load. Managed services update configurations automatically. Some changes are legitimate and should be preserved:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Mark resources that can change externally
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;autoScalingGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;autoscaling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;app-asg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;minSize&lt;/span&gt;: &lt;span class="kt"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;maxSize&lt;/span&gt;: &lt;span class="kt"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// ... other config
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;ignoreChanges&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;desiredCapacity&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// Ignore scaling changes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;ignoreChanges&lt;/code&gt; option tells Pulumi to ignore specific properties when detecting drift. Use it for fields that legitimately change outside your control, like auto-scaling capacity or last-modified timestamps.&lt;/p&gt;
&lt;h3 id="scenario-3-configuration-drift"&gt;Scenario 3: Configuration Drift&lt;/h3&gt;
&lt;p&gt;Sometimes drift occurs in configuration values rather than resource structure. IP allowlists, feature flags, and environment-specific settings often drift. Handle these with Pulumi&amp;rsquo;s configuration system:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Use Pulumi&amp;#39;s configuration system&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;allowed_ips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;allowed_ips&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;10.0.0.0/8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;security_group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ec2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SecurityGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;app-sg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ingress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;from_port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;to_port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;protocol&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;cidr_blocks&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;allowed_ips&lt;/span&gt; &lt;span class="c1"&gt;# Managed via configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By externalizing configuration values, you make them easier to update without code changes. This pattern works particularly well for values that change frequently or differ between environments.&lt;/p&gt;
&lt;h2 id="the-value-of-automated-drift-detection"&gt;The Value of Automated Drift Detection&lt;/h2&gt;
&lt;p&gt;After implementing drift detection for hundreds of stacks, patterns emerge that tell a compelling story about its value. The transformation begins subtly but grows profound as teams discover what they&amp;rsquo;ve been missing.&lt;/p&gt;
&lt;p&gt;The first change most organizations notice is in their security posture. Where once unauthorized changes might lurk undetected for weeks, only surfacing during quarterly audits or worse, during incident investigations, now they&amp;rsquo;re caught within minutes. Security teams who previously dreaded audit season find themselves with continuous compliance data at their fingertips. Every change, whether legitimate or not, creates an audit trail that transforms compliance reporting from a scrambling fire drill into a routine export of already-collected data.&lt;/p&gt;
&lt;p&gt;As teams settle into this new reality, operational improvements become apparent. Incidents that used to take hours to diagnose now resolve in minutes because engineers can immediately check whether drift contributed to the problem. One team reported that their mean time to recovery dropped by 40% simply because they could eliminate drift as a cause within seconds rather than spending hours manually comparing configurations. Change management, once a bureaucratic nightmare of spreadsheets and approval chains, transforms into an automated system where every modification is tracked, timestamped, and traceable to its source.&lt;/p&gt;
&lt;p&gt;Then come the unexpected discoveries. Drift detection becomes a cost optimization tool that nobody anticipated. It uncovers orphaned resources spinning away forgotten in some corner of your cloud account, created during a debugging session six months ago. It catches that instance someone manually upgraded to a larger size during a performance investigation and forgot to downsize. One organization discovered they were spending $15,000 monthly on resources that weren&amp;rsquo;t even supposed to exist, all caught by their drift detection system in its first week of operation.&lt;/p&gt;
&lt;p&gt;Perhaps most importantly, drift detection changes how teams work. Engineers stop wasting time on manual infrastructure audits. Debugging accelerates when you have clear reports showing exactly what changed and when. The constant anxiety about whether production matches your code disappears, replaced by confidence that any discrepancies will be caught and reported immediately. Teams report feeling more empowered to move quickly, knowing they have a safety net that will catch configuration drift before it causes problems.&lt;/p&gt;
&lt;p&gt;The cumulative effect is transformative. Organizations running drift detection report not just fewer incidents and lower costs, but a fundamental shift in how they think about infrastructure management. It becomes proactive rather than reactive, confident rather than anxious, automated rather than manual. What starts as a simple scheduled check evolves into a cornerstone of operational excellence.&lt;/p&gt;
&lt;h2 id="getting-started-with-drift-detection"&gt;Getting Started with Drift Detection&lt;/h2&gt;
&lt;p&gt;Ready to implement drift detection for your IDP? Here&amp;rsquo;s a practical action plan that you can execute today.&lt;/p&gt;
&lt;h3 id="quick-start-checklist"&gt;Quick Start Checklist&lt;/h3&gt;
&lt;p&gt;Begin with the simplest possible drift detection: a manual check on your production stack. Run &lt;code&gt;pulumi refresh --preview-only --stack production&lt;/code&gt; to see if you have any existing drift. This takes just 15 minutes and often reveals surprising discrepancies.&lt;/p&gt;
&lt;p&gt;Next, invest 30 minutes in setting up automated detection. Configure &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/get-started"&gt;Pulumi Deployments&lt;/a&gt;, create an hourly detection schedule for your most critical stack, and set up Slack notifications so you&amp;rsquo;ll know immediately when drift occurs.&lt;/p&gt;
&lt;p&gt;Spend the next week monitoring and learning. Review the drift patterns that emerge. Identify common causes. Are certain resources drifting repeatedly? Are changes happening at predictable times? Document which changes are legitimate and which represent problems.&lt;/p&gt;
&lt;p&gt;After a week of observation, you&amp;rsquo;re ready to implement remediation. Start with non-production environments where mistakes have lower impact. Enable auto-remediation gradually, monitoring success rates and adjusting your configuration based on what you learn.&lt;/p&gt;
&lt;p&gt;Finally, optimize and scale your drift detection. Adjust schedules based on the patterns you&amp;rsquo;ve observed. Implement custom workflows for complex scenarios. Expand coverage to all your environments and stacks. What starts as a simple check becomes a comprehensive system protecting your entire infrastructure.&lt;/p&gt;
&lt;h2 id="conclusion-day-2-operations-as-a-competitive-advantage"&gt;Conclusion: Day 2 Operations as a Competitive Advantage&lt;/h2&gt;
&lt;p&gt;Drift detection and remediation represent more than just good hygiene; they&amp;rsquo;re competitive advantages in a world where infrastructure complexity keeps growing.&lt;/p&gt;
&lt;p&gt;Teams with robust day 2 operations move faster because they have confidence in their infrastructure state. They recover quickly from incidents because they can immediately identify what changed. They maintain security without slowing development by automatically detecting and reverting unauthorized modifications. Most importantly, they scale operations without scaling headcount, automating work that would otherwise require armies of engineers manually checking infrastructure.&lt;/p&gt;
&lt;p&gt;The math is compelling. A single undetected security group change could lead to a breach costing millions. One overlooked configuration drift might cause hours of downtime. Yet implementing comprehensive drift detection takes just hours of setup and minutes of ongoing maintenance. The ROI is immediate and substantial.&lt;/p&gt;
&lt;p&gt;Our IDP journey continues with &lt;strong&gt;&amp;ldquo;Extend Your IDP for AI Applications: GPUs, Models, and Cost Controls&amp;rdquo;&lt;/strong&gt;. As AI workloads become central to modern applications, we&amp;rsquo;ll explore how to adapt your platform for machine learning workflows. You&amp;rsquo;ll learn about GPU orchestration, model deployment pipelines, and the unique cost management challenges that AI infrastructure presents.&lt;/p&gt;
&lt;p&gt;But don&amp;rsquo;t wait for the next post to get started with drift detection. Even a simple hourly check can prevent major incidents. Set up basic detection today, and your future self will thank you the next time you&amp;rsquo;re debugging a production issue at 3 AM. More importantly, your on-call team will appreciate not having to debug issues caused by accumulated drift that could have been prevented.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Ready to implement drift detection?&lt;/strong&gt; &lt;a href="https://app.pulumi.com/signup"&gt;Start your free Pulumi Cloud trial&lt;/a&gt; and set up your first drift detection schedule in minutes. No credit card required.&lt;/p&gt;</description><author>Mitch Gerdisch</author><author>Josh Kodroff</author><category>internal-developer-platform</category><category>drift-detection</category><category>day-2-operations</category><category>infrastructure-as-code</category><category>pulumi-deployments</category><category>automation</category><category>platform-engineering</category><category>devops</category><category>remediation</category></item><item><title>Neo Gets Smarter: New Modes, CLI Access &amp; Sonnet 4.5</title><link>https://www.pulumi.com/blog/neo-levels-up/</link><pubDate>Mon, 20 Oct 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/neo-levels-up/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/neo-levels-up/index.png" /&gt;
&lt;p&gt;Neo just got significantly more capable. We&amp;rsquo;ve shipped three major updates: Operating Modes for flexible control, full ecosystem tool access, and Claude Sonnet 4.5 for better performance on complex infrastructure tasks.&lt;/p&gt;
&lt;h2 id="you-decide-how-much-control-you-keep"&gt;You decide how much control you keep&lt;/h2&gt;
&lt;p&gt;The same action has different risks in different contexts. Building a new dev environment is low risk. Opening a PR that changes shared infrastructure requires more scrutiny.&lt;/p&gt;
&lt;p&gt;Operating Modes let you adjust autonomy based on context:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Review Mode&lt;/strong&gt;: You approve the task plan, preview, and PR. You see everything before it happens.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Balanced Mode&lt;/strong&gt;: Neo handles planning and previews. You approve mutating operations, such as updates or destroys. Less friction, control where it matters.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto Mode&lt;/strong&gt;: Neo runs without stopping. For when you need speed and trust the outcome.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can use Review Mode when Neo is updating production infrastructure. Use Balanced Mode when deploying application updates where you want to verify destructive changes but trust routine operations. Switch to Auto Mode when spinning up temporary dev environments for testing. You pick the mode that matches your situation. The same agent, flexible levels of autonomy.&lt;/p&gt;
&lt;h2 id="neo-can-do-more"&gt;Neo can do more&lt;/h2&gt;
&lt;p&gt;Neo now has access to more tools and information. This means it can handle more complex scenarios and work with the broader ecosystem your infrastructure depends on.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Full Pulumi CLI access&lt;/strong&gt;: Neo can now run all Pulumi CLI operations, including stack imports, state management, and plugin operations that previously required manual intervention.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ecosystem tooling built in&lt;/strong&gt;: Neo now includes kubectl, Helm, AWS CLI, GCP, and Oracle Cloud CLI. This means Neo can verify Kubernetes deployments, install Helm charts, and run cloud-specific operations without leaving your workflow.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Private registry search&lt;/strong&gt;: Your team builds reusable components to accelerate development and codify standards. Neo can now search your organization&amp;rsquo;s private registry, including READMEs, to find and use them. You get the benefit of your team&amp;rsquo;s existing work.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="sonnet-45"&gt;Sonnet 4.5&lt;/h2&gt;
&lt;p&gt;Neo now runs on Anthropic&amp;rsquo;s Sonnet 4.5 by default. Sonnet 4.5 delivers better performance on complex, multi-step infrastructure tasks that require sustained reasoning across multiple files and services.&lt;/p&gt;
&lt;h2 id="try-neo"&gt;Try Neo&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Ready to try these features?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://app.pulumi.com/signin"&gt;Sign in to Pulumi Cloud&lt;/a&gt; and start a Neo task&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/ai/"&gt;Read the Neo documentation&lt;/a&gt; for detailed guides&lt;/li&gt;
&lt;li&gt;&lt;a href="https://slack.pulumi.com/"&gt;Join the Community Slack&lt;/a&gt; to share feedback on the new features&lt;/li&gt;
&lt;/ul&gt;</description><author>Pulumi Neo Team</author><category>ai</category><category>ai-agents</category><category>platform-engineering</category><category>pulumi-neo</category></item><item><title>10 Things You Can Do With Our Infrastructure Agent, Neo</title><link>https://www.pulumi.com/blog/10-things-you-can-do-with-neo/</link><pubDate>Mon, 06 Oct 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/10-things-you-can-do-with-neo/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/10-things-you-can-do-with-neo/index.png" /&gt;
&lt;p&gt;Since launching &lt;a href="https://www.pulumi.com/blog/pulumi-neo/"&gt;Pulumi Neo&lt;/a&gt; two weeks ago, we&amp;rsquo;ve seen platform teams discover creative ways to put their newest AI teammate to work. We have also been using Neo internally for a handful of use cases. Neo shifts the conversation from &amp;ldquo;what could AI do for infrastructure?&amp;rdquo; to &amp;ldquo;what can I actually accomplish with Neo today?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The answer is quite a bit. Here are 10 concrete workflows that platform teams can use Neo for right now, each one designed to save hours of manual work while keeping humans in the driver seat.&lt;/p&gt;
&lt;h2 id="1-explain-infrastructure-in-plain-english-or-diagrams"&gt;1. Explain infrastructure in plain English or diagrams&lt;/h2&gt;
&lt;p&gt;Neo answers questions about your infrastructure instantly, turning complex resource relationships into conversational insights (and diagrams!).&lt;/p&gt;
&lt;p&gt;No more digging through AWS consoles or parsing state files to understand what you have deployed. Neo speaks your language about your infrastructure. Ask questions like &lt;em&gt;&amp;ldquo;What databases do we have?&amp;rdquo;&lt;/em&gt;, &lt;em&gt;&amp;ldquo;Which S3 buckets aren&amp;rsquo;t encrypted?&amp;rdquo;&lt;/em&gt;, &lt;em&gt;&amp;ldquo;Show me all resources in us-east-1&amp;rdquo;&lt;/em&gt; or &amp;ldquo;draw an architecture diagram of our service&amp;rdquo; and get immediate, accurate answers.&lt;/p&gt;
&lt;p&gt;&lt;img src="neo-diagram.png" alt="Neo explaining and diagramming infrastructure"&gt;&lt;/p&gt;
&lt;h2 id="2-generate-infrastructure-code-from-natural-language"&gt;2. Generate infrastructure code from natural language&lt;/h2&gt;
&lt;p&gt;Neo turns plain English descriptions into production-ready Pulumi code, eliminating the blank-page problem that slows down new projects.&lt;/p&gt;
&lt;p&gt;Instead of starting from scratch or hunting through documentation, describe what you need and Neo generates the complete infrastructure. Ask Neo: &lt;em&gt;&amp;ldquo;Create a serverless API with PostgreSQL database and Redis cache on AWS&amp;rdquo;&lt;/em&gt; and it produces fully configured resources with proper networking, security groups, and IAM policies.&lt;/p&gt;
&lt;p&gt;&lt;img src="neo-postgresql-redis.png" alt="Neo generating infrastructure code for a serverless API with PostgreSQL and Redis"&gt;&lt;/p&gt;
&lt;h2 id="3-assist-with-terraform-to-pulumi-migration"&gt;3. Assist with Terraform to Pulumi migration&lt;/h2&gt;
&lt;p&gt;Neo analyzes existing Terraform code (and/or state files) and generates equivalent Pulumi programs, accelerating migration without starting from scratch.&lt;/p&gt;
&lt;p&gt;Migrating from Terraform to Pulumi traditionally means rewriting everything. Neo understands both languages and can convert HCL to TypeScript, Python, or Go while preserving your infrastructure patterns. You can also use the Terraform state file. Ask Neo: &lt;em&gt;&amp;ldquo;Analyze the provided terraform state. Based on it, generate a python pulumi program that imports the resources without requiring updates.&amp;rdquo;&lt;/em&gt; and it generates equivalent code with proper typing and best practices.&lt;/p&gt;
&lt;p&gt;Using this prompt with a Terraform state file containing EC2 instances and supporting resources, Neo generated a complete Pulumi program that imported everything without requiring updates:&lt;/p&gt;
&lt;p&gt;&lt;img src="tf-up.png" alt="Neo converting Terraform state to Pulumi code"&gt;&lt;/p&gt;
&lt;h2 id="4-automate-cicd-pipeline-generation"&gt;4. Automate CI/CD pipeline generation&lt;/h2&gt;
&lt;p&gt;Neo creates complete GitHub Actions workflows configured specifically for Pulumi deployments, with proper preview stages.&lt;/p&gt;
&lt;p&gt;Setting up CI/CD for infrastructure projects usually involves copying workflows from other repos and adapting them. Neo generates purpose-built pipelines that understand your stack structure and deployment patterns. Ask Neo: &lt;em&gt;&amp;ldquo;Create a GitHub Actions pipeline for this Pulumi project with preview and production stages&amp;rdquo;&lt;/em&gt; and it produces workflows with proper secrets management, approval gates, and deployment strategies.&lt;/p&gt;
&lt;p&gt;Here is what Neo gives us using that prompt on a very basic Pulumi project:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Simple Pulumi Deploy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;main]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PULUMI_ACCESS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ secrets.PULUMI_ACCESS_TOKEN }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ secrets.AWS_ACCESS_KEY_ID }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ secrets.AWS_SECRET_ACCESS_KEY }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Checkout code&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Install Pulumi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pulumi/actions@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pulumi-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Configure AWS credentials&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws-actions/configure-aws-credentials@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws-access-key-id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ secrets.AWS_ACCESS_KEY_ID }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws-secret-access-key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ secrets.AWS_SECRET_ACCESS_KEY }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws-region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;us-west-2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy infrastructure&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; pulumi stack select production
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; pulumi up --yes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;working-directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./infrastructure&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="5-identify-inefficient-infrastructure-patterns"&gt;5. Identify inefficient infrastructure patterns&lt;/h2&gt;
&lt;p&gt;Neo analyzes your infrastructure and spots patterns that create unnecessary management overhead, helping you consolidate and optimize.&lt;/p&gt;
&lt;p&gt;When you have 10 identical EC2 instances that should be an auto-scaling group, or multiple Lambda functions doing the same job, Neo spots these patterns. Ask Neo: &lt;em&gt;&amp;ldquo;Analyze our infrastructure for inefficient patterns&amp;rdquo;&lt;/em&gt; and it can identify consolidation opportunities.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example analysis:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Neo identified these optimization opportunities:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Duplicate EC2 Instances (High Priority)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; • Found 8 identical t3.medium instances running the same application
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; • Recommendation: Consolidate into an Auto Scaling Group
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; • Benefits: Simplified management, automatic scaling, reduced configuration drift
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Scattered Lambda Functions (Medium Priority)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; • Found 12 Lambda functions with identical runtime and dependencies
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; • Recommendation: Combine into a single function with routing logic
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; • Benefits: Reduced cold starts, simplified monitoring, easier updates
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Redundant Security Groups (Low Priority)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; • Found 15 security groups with identical rules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; • Recommendation: Create shared security groups for common patterns
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; • Benefits: Easier rule management, reduced complexity
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="6-upgrade-ekskubernetes-clusters"&gt;6. Upgrade EKS/Kubernetes clusters&lt;/h2&gt;
&lt;p&gt;Neo manages Kubernetes version upgrades across multiple clusters, planning upgrade paths and validating compatibility.&lt;/p&gt;
&lt;p&gt;Kubernetes upgrades are complex, especially across multiple clusters with different workloads. Neo analyzes your cluster configurations, identifies upgrade blockers, and creates systematic upgrade plans. Ask Neo: &lt;em&gt;&amp;ldquo;Plan an upgrade path for our EKS clusters from 1.27 to 1.28&amp;rdquo;&lt;/em&gt; and it maps dependencies, checks add-on compatibility, and sequences the upgrades.&lt;/p&gt;
&lt;h2 id="7-respond-to-security-vulnerabilities"&gt;7. Respond to security vulnerabilities&lt;/h2&gt;
&lt;p&gt;When CVEs are announced, Neo can help security teams move at machine speed addressing them.&lt;/p&gt;
&lt;p&gt;Security vulnerabilities require immediate response across your entire infrastructure. Neo understands your resource inventory and can quickly identify what&amp;rsquo;s affected by new CVEs. When you ask Neo: &lt;em&gt;&amp;ldquo;Identify all resources affected by CVE-2025-XXXXX and create remediation PRs&amp;rdquo;&lt;/em&gt;, it scans your infrastructure, maps vulnerable components, and generates targeted fixes.&lt;/p&gt;
&lt;p&gt;&lt;img src="neo-cves.png" alt="Neo identifying and remediating CVE vulnerabilities"&gt;&lt;/p&gt;
&lt;h2 id="8-remediate-policy-violations"&gt;8. Remediate policy violations&lt;/h2&gt;
&lt;p&gt;Neo detects non-compliant resources and generates pull requests to fix them, turning compliance headaches into automated workflows.&lt;/p&gt;
&lt;p&gt;When your policy violations detect unencrypted EBS volumes, overly permissive security groups, or missing resource tags, Neo identifies the issues and proposes specific fixes. Ask Neo: &lt;em&gt;&amp;ldquo;Fix all policy violations in our production account&amp;rdquo;&lt;/em&gt; and it analyzes your compliance dashboard, identifies the problematic resources, and creates PRs with the exact changes needed.&lt;/p&gt;
&lt;p&gt;&lt;img src="neo-policies.png" alt="Neo identifying and fixing policy violations"&gt;&lt;/p&gt;
&lt;h2 id="9-update-lambda-runtimes-across-multiple-accounts"&gt;9. Update Lambda runtimes across multiple accounts&lt;/h2&gt;
&lt;p&gt;Neo identifies outdated Lambda runtimes, stages updates, and manages the rollout across your entire AWS organization.&lt;/p&gt;
&lt;p&gt;When AWS announces runtime deprecations, Neo scans all your accounts, identifies functions running outdated versions, and creates a systematic upgrade plan. Ask Neo: &lt;em&gt;&amp;ldquo;Upgrade all Lambda functions to Python 3.11&amp;rdquo;&lt;/em&gt; and it maps your functions, checks compatibility, and generates account-by-account PRs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Before (outdated runtime):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Create the process email Lambda function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lambdaFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;emailProcessor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;runtime&lt;/span&gt;: &lt;span class="kt"&gt;aws.lambda.Runtime.Python3d8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Deprecated
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;code&lt;/span&gt;: &lt;span class="kt"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AssetArchive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FileArchive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./lambda&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// ... other configuration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;After (Neo&amp;rsquo;s upgrade):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Create the process email Lambda function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lambdaFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;emailProcessor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;runtime&lt;/span&gt;: &lt;span class="kt"&gt;aws.lambda.Runtime.Python3d11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// ✅ Upgraded
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;code&lt;/span&gt;: &lt;span class="kt"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AssetArchive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FileArchive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./lambda&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// ... other configuration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="10-enforce-multi-account-policy-compliance"&gt;10. Enforce multi-account policy compliance&lt;/h2&gt;
&lt;p&gt;Neo applies organizational policies across your entire AWS Organizations structure, ensuring governance at scale without creating bottlenecks.&lt;/p&gt;
&lt;p&gt;Large organizations struggle to maintain consistent policies across dozens of AWS accounts. Neo understands your organizational structure and can enforce tagging standards, encryption requirements, and security policies uniformly. Ask Neo: &lt;em&gt;&amp;ldquo;Ensure all accounts follow our tagging and encryption policies&amp;rdquo;&lt;/em&gt; and it audits compliance across your organization.&lt;/p&gt;
&lt;h2 id="your-newest-platform-engineer"&gt;Your newest platform engineer&lt;/h2&gt;
&lt;p&gt;These workflows represent just the beginning of what&amp;rsquo;s possible when an AI agent deeply understands infrastructure context.&lt;/p&gt;
&lt;p&gt;The outcome is simple: spend less time on operational toil and more time on the architecture and policies that make your organizations successful.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/neo/"&gt;Get started with Neo&lt;/a&gt; and discover what becomes possible when AI truly understands infrastructure.&lt;/p&gt;
&lt;p&gt;The future of platform engineering isn&amp;rsquo;t about choosing between speed and safety. It&amp;rsquo;s about having tools that help you with both simultaneously.&lt;/p&gt;</description><author>Meagan Cojocar</author><category>ai</category><category>platform-engineering</category><category>pulumi-neo</category><category>aws</category></item><item><title>How to Implement Robust Security Guardrails Using Policy as Code</title><link>https://www.pulumi.com/blog/deployment-guardrails-with-policy-as-code/</link><pubDate>Tue, 30 Sep 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/deployment-guardrails-with-policy-as-code/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/deployment-guardrails-with-policy-as-code/index.png" /&gt;
&lt;p&gt;Welcome to the third post in our &lt;strong&gt;IDP Best Practices&lt;/strong&gt; series, where we explore how to implement &lt;strong&gt;policy as code&lt;/strong&gt; with &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard"&gt;Pulumi CrossGuard&lt;/a&gt; to create deployment guardrails that make self-service infrastructure both powerful and safe.&lt;/p&gt;
&lt;p&gt;Platform engineering presents a fundamental tension: we want to enable developer velocity while maintaining security and compliance. Every platform team faces the same question: how do you give teams the freedom to deploy infrastructure quickly without compromising on safety, security, or organizational standards? The answer isn&amp;rsquo;t to choose between speed and safety, but rather to embrace &lt;strong&gt;automated guardrails&lt;/strong&gt; powered by policy as code that make both possible simultaneously.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;strong&gt;Want hands-on experience?&lt;/strong&gt; Access the &lt;a href="https://github.com/pulumi/workshops/tree/main/idp-component-policies"&gt;complete demo code&lt;/a&gt; and &lt;a href="https://github.com/pulumi/workshops/tree/main/idp-component-policies/demo-policies"&gt;policy examples&lt;/a&gt; from this workshop.&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="the-platform-engineering-challenge-speed-vs-safety"&gt;The Platform Engineering Challenge: Speed vs. Safety&lt;/h2&gt;
&lt;p&gt;Let me tell you a story that perfectly captures the platform engineering dilemma. Statsig, a fast-growing feature flag platform processing an incredible 2 trillion events daily, had one infrastructure engineer named Jason who handled all infrastructure requests. Everything worked smoothly until Jason went on parental leave. Suddenly, the entire engineering organization ground to a halt. Infrastructure requests piled up, deployments slowed to a crawl, and the team faced a stark realization: their entire infrastructure capability depended on a single person.&lt;/p&gt;
&lt;p&gt;This crisis forced them to confront a fundamental question that every growing engineering team eventually faces: How do you enable self-service infrastructure without sacrificing security, compliance, or operational stability? The answer wasn&amp;rsquo;t to hire more Jasons or to lock down infrastructure even tighter. Instead, they discovered that deployment guardrails with policy as code could transform their infrastructure conversation from &amp;ldquo;talk to the infrastructure person&amp;rdquo; to &amp;ldquo;ship with confidence, knowing guardrails will catch any issues.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Think of it like building a system of roads with guardrails. When you create well-designed infrastructure components with proper safety barriers, teams can drive fast and confidently, knowing they&amp;rsquo;re protected from going off the cliff. The guardrails don&amp;rsquo;t slow them down; they enable speed by removing fear.&lt;/p&gt;
&lt;h2 id="understanding-platform-engineering-layers"&gt;Understanding Platform Engineering Layers&lt;/h2&gt;
&lt;p&gt;Before we dive into implementing guardrails, we need to understand the architecture of a modern platform and where policies fit within it. Think of your platform as having three distinct layers, each with different security and access requirements.&lt;/p&gt;
&lt;p&gt;At the foundation, you have your &lt;strong&gt;Layer 1: Foundational Infrastructure&lt;/strong&gt;, which includes security controls, shared networking, and identity management systems like OIDC and IAM. Platform teams typically manage this layer with strict access controls because it forms the security backbone of your entire infrastructure.&lt;/p&gt;
&lt;p&gt;Building on that foundation is &lt;strong&gt;Layer 2: Shared Infrastructure&lt;/strong&gt;, which encompasses VPCs, compute platforms, and load balancers. These are standardized components that teams can use but with some room for customization based on specific needs.&lt;/p&gt;
&lt;p&gt;The most dynamic layer is &lt;strong&gt;Layer 3: The Workloads Layer&lt;/strong&gt;, where deployable artifacts, pipelines, and operability tools live. This is where the rubber meets the road, where most self-service activity happens and, consequently, where guardrails become absolutely critical. Developers need maximum freedom at this layer to innovate and ship quickly, but this freedom also introduces the most risk. It&amp;rsquo;s precisely here that policy-driven guardrails prove their worth, enabling that freedom while automatically preventing dangerous configurations.&lt;/p&gt;
&lt;h2 id="what-are-deployment-guardrails"&gt;What Are Deployment Guardrails?&lt;/h2&gt;
&lt;p&gt;Deployment guardrails are automated policies that act as your infrastructure&amp;rsquo;s safety net. Rather than relying on manual reviews or hoping developers remember all the security requirements, guardrails automatically prevent misconfigurations before they reach production. They enforce security standards without human intervention, guide developers toward best practices through immediate feedback, and enable safe self-service by catching issues at the earliest possible moment.&lt;/p&gt;
&lt;p&gt;A helpful analogy is to think of guardrails like type checking in programming languages. Just as TypeScript doesn&amp;rsquo;t restrict your ability to write JavaScript but rather catches type errors before runtime, deployment guardrails don&amp;rsquo;t limit your infrastructure creativity. They simply ensure you&amp;rsquo;re following secure patterns and catch potentially dangerous configurations before they cause problems in production.&lt;/p&gt;
&lt;h2 id="introducing-pulumi-crossguard-policy-as-code"&gt;Introducing Pulumi CrossGuard: Policy as Code&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard"&gt;Pulumi CrossGuard&lt;/a&gt; is Pulumi&amp;rsquo;s policy as code framework that brings the same engineering rigor to compliance and security that you apply to your application code. Instead of maintaining policy documents in wikis or relying on manual reviews, you can write policies in familiar programming languages like &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/get-started#writing-policies-in-python"&gt;Python&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/get-started#writing-policies-in-typescript"&gt;TypeScript&lt;/a&gt;, or Go. These policies then enforce themselves across all your cloud resources and providers, running at different stages of the deployment lifecycle and integrating seamlessly with your CI/CD pipelines for automated enforcement.&lt;/p&gt;
&lt;h3 id="key-policy-types"&gt;Key Policy Types&lt;/h3&gt;
&lt;p&gt;CrossGuard supports two fundamental types of policies, each serving different validation needs:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/core-concepts#resource-validation"&gt;Resource Policies&lt;/a&gt;&lt;/strong&gt;: Validate individual resources&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;restrict_dangerous_ports&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResourceValidationArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ReportViolation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws:lb/targetGroup:TargetGroup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dangerous_ports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;22&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;23&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;3389&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dangerous_ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Dangerous port detected. Avoid using SSH, Telnet, or RDP ports.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/core-concepts#stack-validation"&gt;Stack Policies&lt;/a&gt;&lt;/strong&gt;: Validate relationships across resources&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_microservice_encryption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StackValidationArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ReportViolation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;microservice_components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s3_buckets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;custom:infrastructure:Microservice&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;microservice_components&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws:s3/bucket:Bucket&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s3_buckets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;microservice_components&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;s3_buckets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;s3_buckets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;encryption&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;serverSideEncryptionConfiguration&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;encryption&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;S3 bucket must have encryption enabled when used with microservice components.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="building-practical-guardrails-real-world-examples"&gt;Building Practical Guardrails: Real-World Examples&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s walk through building guardrails for a microservice platform, starting with the component from our &lt;a href="https://www.pulumi.com/blog/golden-paths-infrastructure-components-and-templates/"&gt;previous workshop&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="example-1-port-security-policy"&gt;Example 1: Port Security Policy&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Developers might accidentally expose services on dangerous ports like SSH (22) or RDP (3389).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: A policy that blocks dangerous port configurations.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_policy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;policy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;restrict_dangerous_ports_validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Prevent services from running on dangerous ports.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws:lb/targetGroup:TargetGroup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dangerous_ports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;22&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;23&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;3389&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5432&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;3306&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dangerous_ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Port &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is not allowed. This port is commonly used for &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;administrative services and should not be exposed via load balancer.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;restrict_dangerous_ports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceValidationPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;restrict-dangerous-ports&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Prevent services from using dangerous ports&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;restrict_dangerous_ports_validation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;enforcement_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnforcementLevel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MANDATORY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="example-2-resource-limits-policy"&gt;Example 2: Resource Limits Policy&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Teams might request oversized resources, leading to cost overruns.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: A policy that enforces reasonable resource limits with advisory warnings.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;limit_memory_validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Limit memory allocation for microservices.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;custom:infrastructure:Microservice&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Extract memory from component tags or properties&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;memory_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;memory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;512Mi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Parse memory value (assuming format like &amp;#34;2Gi&amp;#34;, &amp;#34;1024Mi&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;memory_str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Gi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;memory_gb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory_str&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;memory_gb&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Memory allocation of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;memory_str&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; exceeds recommended limit of 1Gi &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;for microservices. Consider optimizing your application or &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;contact the platform team for exceptions.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;limit_memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceValidationPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;limit-microservice-memory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Enforce reasonable memory limits for microservices&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;limit_memory_validation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;enforcement_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnforcementLevel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ADVISORY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="example-3-cross-resource-security-policy"&gt;Example 3: Cross-Resource Security Policy&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: When microservices use S3 buckets, encryption should be mandatory.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: A stack policy that validates encryption across related resources.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;microservice_s3_encryption_validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Ensure S3 buckets used with microservices have encryption enabled.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;microservice_resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s3_buckets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Collect relevant resources&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;custom:infrastructure:Microservice&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;microservice_resources&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws:s3/bucket:Bucket&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;s3_buckets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# If we have both microservices and S3 buckets, check encryption&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;microservice_resources&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;s3_buckets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;s3_buckets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sse_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;serverSideEncryptionConfiguration&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;sse_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;S3 bucket &amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39; must have server-side encryption &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;enabled when used with microservice components.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;microservice_s3_encryption&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StackValidationPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;microservice-s3-encryption&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Ensure S3 buckets used with microservices are encrypted&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;microservice_s3_encryption_validation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;enforcement_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnforcementLevel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MANDATORY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="policy-enforcement-models"&gt;Policy Enforcement Models&lt;/h2&gt;
&lt;p&gt;Pulumi CrossGuard supports multiple &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/core-concepts#enforcement-levels"&gt;enforcement models&lt;/a&gt; to fit different workflows, and understanding when to use each model is crucial for effective policy implementation.&lt;/p&gt;
&lt;h3 id="the-preventative-model"&gt;The Preventative Model&lt;/h3&gt;
&lt;p&gt;The most common approach is the preventative model, where policies run before resources are created. This gives you fast feedback and prevents bad deployments from ever reaching the cloud. When you run &lt;code&gt;pulumi preview&lt;/code&gt;, policies are evaluated immediately, and if violations are found during &lt;code&gt;pulumi up&lt;/code&gt;, the deployment is blocked. This model works particularly well for validating port configurations, resource limits, and other settings that you can check without needing to see the actual deployed resource.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Policies run automatically during preview and deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi preview &lt;span class="c1"&gt;# Policies evaluated here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi up &lt;span class="c1"&gt;# Policies block deployment if violations found&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="the-detective-model"&gt;The Detective Model&lt;/h3&gt;
&lt;p&gt;Sometimes you need to validate the actual cloud state, including auto-generated values like ARNs or IP addresses. That&amp;rsquo;s where the detective model comes in. These policies run after resources are created, making them perfect for compliance scanning and drift detection. While they can&amp;rsquo;t prevent initial deployment of non-compliant resources, they excel at catching configuration drift and validating properties that only exist after deployment.&lt;/p&gt;
&lt;h3 id="cicd-integration"&gt;CI/CD Integration&lt;/h3&gt;
&lt;p&gt;The third model integrates policies directly into your deployment pipeline. This ensures consistent enforcement across all teams and creates natural deployment gates. For example, you might configure &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/continuous-delivery/github-actions"&gt;GitHub Actions&lt;/a&gt; to run policy validation on every pull request, blocking merges if violations are found. This approach combines the best of both worlds: early feedback during development and guaranteed enforcement before production.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# GitHub Actions example&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Run Policy Validation&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; pulumi preview --policy-pack ./policies
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; if [ $? -ne 0 ]; then
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo &amp;#34;Policy violations found. Deployment blocked.&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; exit 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; fi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="policy-remediation-beyond-detection"&gt;Policy Remediation: Beyond Detection&lt;/h2&gt;
&lt;p&gt;Modern policy frameworks don&amp;rsquo;t just detect violations; they can &lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/core-concepts#remediation-policies"&gt;automatically fix&lt;/a&gt;&lt;/strong&gt; them:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;auto_tag_resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Automatically add required tags to resources.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws:s3/bucket:Bucket&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Department&amp;#34;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Instead of just reporting, fix the issue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nb"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;tags&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Department&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Engineering&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt; &lt;span class="c1"&gt;# Return modified properties&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;# No changes needed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;auto_tag_policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceValidationPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;auto-tag-resources&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Automatically add required tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;auto_tag_resources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;enforcement_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnforcementLevel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;REMEDIATE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="server-side-policy-enforcement"&gt;Server-Side Policy Enforcement&lt;/h2&gt;
&lt;p&gt;For enterprise deployments, Pulumi provides &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/get-started#enforcing-a-policy-pack"&gt;server-side policy enforcement&lt;/a&gt; that ensures policies can&amp;rsquo;t be bypassed. The process starts by publishing your policies to your Pulumi organization with &lt;code&gt;pulumi policy publish ./my-policies&lt;/code&gt;. Once published, you can &lt;a href="https://www.pulumi.com/docs/iac/crossguard/configuration/#using-pulumi-cloud"&gt;create policy groups&lt;/a&gt; that combine multiple policies with specific enforcement levels, targeting particular stacks or environments while configuring exceptions for special cases. The beauty of this approach is that policies run automatically without requiring CLI flags, providing consistent governance across your entire organization without relying on developers to remember to include policy packs in their commands.&lt;/p&gt;
&lt;h2 id="compliance-ready-policies"&gt;Compliance-Ready Policies&lt;/h2&gt;
&lt;p&gt;While custom policies address your specific organizational needs, compliance requirements often follow industry standards. Pulumi provides hundreds of &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies"&gt;pre-built policies&lt;/a&gt; for common compliance frameworks:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PolicyManager&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/policy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;policyManager&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/compliance-ready-policies/policy-manager&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PolicyPack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;aws-compliance-ready-policies-typescript&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;policyManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectPolicies&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;vendors&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;aws&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ec2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;s3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;severities&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;medium&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;high&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;critical&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;topics&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;encryption&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;frameworks&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pcidss&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;mandatory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This automatically includes policies for major compliance frameworks like &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies#frameworks"&gt;PCI DSS&lt;/a&gt; for payment card industry standards, &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies#frameworks"&gt;SOC 2&lt;/a&gt; for security and compliance controls, &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies#frameworks"&gt;ISO 27001&lt;/a&gt; for information security management, and &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies#frameworks"&gt;CIS Benchmarks&lt;/a&gt; for security configuration standards.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Add guardrails with policy as code&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Write policies in Python or TypeScript, enforce them across every deployment, and give teams self-service infrastructure that stays secure and compliant.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/docs/insights/policy/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="best-practices-for-policy-implementation"&gt;Best Practices for Policy Implementation&lt;/h2&gt;
&lt;p&gt;After implementing policies at dozens of organizations, we&amp;rsquo;ve learned that successful policy adoption follows predictable patterns. The key is to adopt a product mindset: think of your policies as a product serving your development teams, not as bureaucratic rules imposed from above. Start small and iterate based on real feedback rather than trying to implement a comprehensive policy framework from day one.&lt;/p&gt;
&lt;h3 id="start-small-and-iterate"&gt;Start Small and Iterate&lt;/h3&gt;
&lt;p&gt;Begin with just two or three critical policies that address your most pressing risks. Use &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/core-concepts#enforcement-levels"&gt;advisory enforcement&lt;/a&gt; initially, which warns developers about violations but doesn&amp;rsquo;t block deployments. This gives your team time to understand and adapt to the policies. Only after gathering feedback and refining the policies should you graduate to mandatory enforcement.&lt;/p&gt;
&lt;h3 id="provide-clear-actionable-error-messages"&gt;Provide Clear, Actionable Error Messages&lt;/h3&gt;
&lt;p&gt;Nothing frustrates developers more than cryptic policy violations. Your error messages should explain not just what&amp;rsquo;s wrong, but how to fix it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;good_error_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;violation_detected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;S3 bucket encryption is required for compliance. &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Add serverSideEncryptionConfiguration to fix this. &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;See: https://docs.company.com/s3-encryption&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="embrace-progressive-enforcement"&gt;Embrace Progressive Enforcement&lt;/h3&gt;
&lt;p&gt;Think of enforcement levels as a dial, not a switch. Start with &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/core-concepts#advisory"&gt;advisory&lt;/a&gt; mode to warn about issues, move to &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/core-concepts#mandatory"&gt;mandatory&lt;/a&gt; to block deployments, and eventually implement &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/core-concepts#remediation-policies"&gt;remediation&lt;/a&gt; to automatically fix common issues. This progression gives teams time to adapt while gradually raising the security bar.&lt;/p&gt;
&lt;h3 id="test-your-policies-thoroughly"&gt;Test Your Policies Thoroughly&lt;/h3&gt;
&lt;p&gt;Policies are code, and like any code, they need testing. Write unit tests for your policies to ensure they catch violations correctly and don&amp;rsquo;t produce false positives:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Test policies with unit tests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_dangerous_port_policy&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Mock resource with port 22&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_mock_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;aws:lb/targetGroup:TargetGroup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;violations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;run_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;restrict_dangerous_ports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dangerous port&amp;#34;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="document-escape-hatches"&gt;Document Escape Hatches&lt;/h3&gt;
&lt;p&gt;No matter how well-designed your policies are, there will always be edge cases. Rather than forcing teams to work around policies in dangerous ways, provide clear, documented escape hatches. Create processes for requesting exceptions, handling emergency exemptions, and appealing for policy changes. As one platform engineer put it, you need &amp;ldquo;guardrails outside the guardrails&amp;rdquo; because platform adoption will never be 100%, and that&amp;rsquo;s okay. This transparency builds trust and ensures policies remain effective enablers rather than bureaucratic obstacles to circumvent.&lt;/p&gt;
&lt;h2 id="real-world-success-statsigs-transformation"&gt;Real-World Success: Statsig&amp;rsquo;s Transformation&lt;/h2&gt;
&lt;p&gt;Remember Statsig&amp;rsquo;s infrastructure crisis when Jason went on parental leave? Let&amp;rsquo;s look at how they transformed their platform using the guardrails approach we&amp;rsquo;ve been discussing. After implementing policy-driven guardrails, their infrastructure story completely changed.&lt;/p&gt;
&lt;p&gt;As Tyrone Wong, Infrastructure Engineer at Statsig, explains: &amp;ldquo;We had a single infra owner. Parental leave forced us to build self-service, and that&amp;rsquo;s when everything clicked. Developers open a PR, Pulumi previews the change right in the PR, and CI blocks risky changes. That&amp;rsquo;s how you move fast safely. The magic was turning &amp;rsquo;talk to the infra person&amp;rsquo; into &amp;lsquo;ship with guardrails.&amp;rsquo;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The results speak for themselves. Deployment times dropped from 1.5 weeks to mere minutes. The infrastructure ticket queue that once haunted their Slack channels disappeared entirely. Security actually improved through automated policy enforcement, eliminating the human error factor. Most importantly, developer satisfaction soared as teams gained the autonomy to ship infrastructure changes without friction or fear.&lt;/p&gt;
&lt;p&gt;When asked if developers were actually using the self-service platform, Tyrone&amp;rsquo;s response was telling: &amp;ldquo;Yeah, people are actually using it because there&amp;rsquo;s changes they wanted to get done. Previously it became this giant effort with lots of meetings, people being concerned, and Google docs about what the changes would be. Now people can just put together a PR, we have our discussions there, see if anything gets flagged, and move forward.&amp;rdquo;&lt;/p&gt;
&lt;h2 id="building-your-policy-strategy"&gt;Building Your Policy Strategy&lt;/h2&gt;
&lt;p&gt;Implementing deployment guardrails isn&amp;rsquo;t a big-bang transformation; it&amp;rsquo;s a journey that unfolds in phases. Based on patterns we&amp;rsquo;ve seen across successful implementations, the first week or two should focus on assessment. Start by understanding your current state, auditing existing infrastructure patterns to identify what teams are actually deploying. Look for common misconfigurations that have caused incidents or near-misses, and document your security and compliance requirements as specific, enforceable rules. Most importantly, survey your developers to understand their pain points with the current infrastructure process, as this assessment forms the foundation for policies that solve real problems rather than creating new ones.&lt;/p&gt;
&lt;p&gt;In weeks three and four, build your foundation by implementing three to five core policies that address your most critical risks. Set up &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/continuous-delivery"&gt;CI/CD integration&lt;/a&gt; so policies run automatically on every pull request, starting with advisory enforcement to gather feedback without blocking deployments. Create clear documentation and runbooks that explain not just what the policies do, but why they exist and how to work with them.&lt;/p&gt;
&lt;p&gt;By the second month, you&amp;rsquo;re ready to expand. Add &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies"&gt;compliance-specific policies&lt;/a&gt; for regulatory requirements and implement &lt;a href="https://www.pulumi.com/docs/iac/crossguard/get-started/#enforcing-a-policy-pack"&gt;server-side enforcement&lt;/a&gt; to ensure policies can&amp;rsquo;t be bypassed. Create formal processes for policy exemptions and exceptions, and begin measuring policy effectiveness through metrics like violation rates and remediation times.&lt;/p&gt;
&lt;p&gt;Remember that policy implementation is never &amp;ldquo;done.&amp;rdquo; Continuously monitor violation patterns to identify areas where policies might be too strict or too lenient. Refine policies based on developer feedback and incident data, add &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/core-concepts#remediation-policies"&gt;automated remediation&lt;/a&gt; for common violations to reduce manual fixes, and gradually expand coverage to new services and teams using lessons learned from early adopters.&lt;/p&gt;
&lt;h2 id="measuring-policy-success"&gt;Measuring Policy Success&lt;/h2&gt;
&lt;p&gt;You can&amp;rsquo;t improve what you don&amp;rsquo;t measure, and policy effectiveness is no exception. Successful teams track metrics across three critical dimensions to validate their policy strategy.&lt;/p&gt;
&lt;p&gt;From a security perspective, start by monitoring your policy violation rate: the percentage of deployments that trigger policy warnings or blocks. This tells you whether your policies are catching real issues or creating unnecessary friction. Track time to remediation to understand how quickly teams fix violations when they occur. Most importantly, measure the reduction in security incidents caused by misconfigurations. If your policies aren&amp;rsquo;t reducing incidents, they&amp;rsquo;re not addressing the right risks.&lt;/p&gt;
&lt;p&gt;Security is only half the equation, though. The developer experience dimension is equally important. Monitor deployment velocity to ensure policies aren&amp;rsquo;t slowing teams down. Regular developer satisfaction surveys reveal whether teams see policies as helpful guardrails or annoying obstacles. Track support ticket volume; successful policy implementation should reduce infrastructure-related requests as teams become more self-sufficient.&lt;/p&gt;
&lt;p&gt;Finally, don&amp;rsquo;t forget to measure the operational health of your policy system itself. Policy coverage shows what percentage of your resources are protected by policies, while the exemption rate reveals whether policies are practical or if teams constantly need exceptions. Track remediation automation to see how many violations are fixed automatically versus requiring manual intervention. Together, these metrics paint a complete picture of your policy program&amp;rsquo;s health and help you continuously improve your approach.&lt;/p&gt;
&lt;h2 id="common-pitfalls-and-how-to-avoid-them"&gt;Common Pitfalls and How to Avoid Them&lt;/h2&gt;
&lt;p&gt;Even with the best intentions, policy implementations can go wrong. Through years of helping organizations implement policy as code, we&amp;rsquo;ve identified four critical pitfalls that can derail your efforts.&lt;/p&gt;
&lt;p&gt;The first and most common trap is over-engineering policies. It&amp;rsquo;s tempting to create sophisticated policies that handle every edge case, but overly complex policies are hard to understand and maintain. Teams won&amp;rsquo;t trust what they don&amp;rsquo;t understand. Instead, start with simple, clear policies that address specific risks. Use descriptive naming and provide examples of both compliant and non-compliant configurations. Remember, a simple policy that everyone follows is better than a perfect policy that everyone circumvents.&lt;/p&gt;
&lt;p&gt;Equally dangerous is falling into &amp;ldquo;policy theater&amp;rdquo;: implementing policies because you think you should, not because they address real risks. This creates friction without improving security. Every policy should trace back to an actual incident, security requirement, or compliance need. If you can&amp;rsquo;t explain why a policy exists with a concrete example, it probably shouldn&amp;rsquo;t exist.&lt;/p&gt;
&lt;p&gt;Poor developer experience is another common failure point. Nothing kills policy adoption faster than cryptic error messages and unclear remediation steps. When a developer hits a policy violation at 5 PM on a Friday, they need clear guidance on how to fix it. Invest heavily in documentation, helpful error messages, and examples. Consider your policies&amp;rsquo; error messages as part of your product&amp;rsquo;s user experience.&lt;/p&gt;
&lt;p&gt;Finally, inadequate testing can erode trust quickly. Policies that break legitimate use cases will be worked around or disabled. Before enforcing any policy, test it thoroughly with real scenarios from your production workloads. Run policies in advisory mode first to catch false positives, and have teams attempt real deployments with policies enabled to ensure they don&amp;rsquo;t block valid configurations.&lt;/p&gt;
&lt;h2 id="the-future-of-policy-as-code"&gt;The Future of Policy as Code&lt;/h2&gt;
&lt;p&gt;As infrastructure becomes increasingly complex and distributed, policy as code is evolving beyond simple rule enforcement to become an intelligent layer that understands context and intent. Three major trends are shaping this evolution.&lt;/p&gt;
&lt;p&gt;First, we&amp;rsquo;re seeing the emergence of AI-enhanced policies with smart detection systems that use machine learning to identify anomalies that rule-based policies might miss. These systems learn from your infrastructure patterns and can provide contextual recommendations that adapt based on actual usage. Even more exciting is predictive enforcement: imagine policies that can identify risky patterns before they become violations, guiding developers away from problems they haven&amp;rsquo;t encountered yet.&lt;/p&gt;
&lt;p&gt;Second, the multi-cloud reality is driving the need for universal governance. Organizations need policies that work seamlessly across &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies-aws"&gt;AWS&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies-azure"&gt;Azure&lt;/a&gt;, and &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies-gcp"&gt;GCP&lt;/a&gt;, with federated enforcement that maintains consistency across multiple cloud accounts and regions. Compliance automation is also maturing, with systems that automatically collect evidence for audits and generate compliance reports without manual intervention.&lt;/p&gt;
&lt;p&gt;Finally, policy enforcement is moving closer to where developers actually work. IDE integration will soon provide real-time policy feedback as you write infrastructure code, catching issues before you even attempt to deploy. Self-service exemption workflows will let developers request and receive policy exceptions through automated approval processes. Perhaps most intriguingly, we&amp;rsquo;re seeing the development of learning policies: systems that improve and adapt based on developer feedback and usage patterns, becoming more helpful over time rather than more restrictive.&lt;/p&gt;
&lt;h2 id="conclusion-enabling-safe-self-service-at-scale"&gt;Conclusion: Enabling Safe Self-Service at Scale&lt;/h2&gt;
&lt;p&gt;We started this post with a fundamental tension in platform engineering: the need for both speed and safety. Through the lens of Statsig&amp;rsquo;s transformation and the technical deep-dive into Pulumi CrossGuard, we&amp;rsquo;ve seen that this isn&amp;rsquo;t actually a tension that needs resolving. It&amp;rsquo;s a false dichotomy that policy as code eliminates entirely.&lt;/p&gt;
&lt;p&gt;The key insight from successful platform teams like Statsig is that guardrails don&amp;rsquo;t restrict freedom; they enable it. When developers know that automated policies will catch dangerous configurations, they gain the confidence to move fast and experiment. When platform teams know that policies automatically enforce security and compliance standards, they can focus on building better platforms instead of reviewing every change. This is the magic of policy as code: it transforms infrastructure governance from a bottleneck into an accelerator.&lt;/p&gt;
&lt;p&gt;But perhaps the most important lesson is that policy as code isn&amp;rsquo;t about saying &amp;ldquo;no&amp;rdquo; to developers. It&amp;rsquo;s about intelligent automation that makes the secure path the path of least resistance. It&amp;rsquo;s about catching mistakes before they become incidents. It&amp;rsquo;s about encoding your organization&amp;rsquo;s hard-won knowledge into systems that help every developer benefit from that experience.&lt;/p&gt;
&lt;p&gt;As you embark on your own journey to implement deployment guardrails, remember that perfection isn&amp;rsquo;t the goal; progress is. Start small, iterate based on feedback, and gradually expand your coverage. Your developers will thank you for the clarity and confidence that comes with well-designed guardrails, and your security team will sleep better knowing that policies are enforced automatically and consistently.&lt;/p&gt;
&lt;p&gt;The path from manual reviews to automated guardrails is well-traveled and well-documented. Our &lt;a href="https://github.com/pulumi/workshops/tree/main/idp-component-policies/demo-policies"&gt;complete policy examples&lt;/a&gt; provide real-world implementations you can adapt to your needs, while the &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard"&gt;CrossGuard documentation&lt;/a&gt; offers deep technical details for advanced use cases. If you&amp;rsquo;re on AWS, &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/awsguard"&gt;AWSGuard&amp;rsquo;s pre-built policies&lt;/a&gt; offer immediate value, and our &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies"&gt;compliance-ready policy catalog&lt;/a&gt; addresses specific regulatory requirements.&lt;/p&gt;
&lt;p&gt;The future of infrastructure management isn&amp;rsquo;t about choosing between developer autonomy and operational control. It&amp;rsquo;s about using policy as code to achieve both, creating platforms that are simultaneously powerful and safe, flexible and compliant, fast and secure.&lt;/p&gt;
&lt;p&gt;In our next post, we&amp;rsquo;ll explore Day 2 Platform Operations, diving into how to maintain infrastructure compliance after deployment and automatically remediate configuration drift. Because getting to production is just the beginning; keeping your infrastructure secure and compliant over time is where the real challenge lies.&lt;/p&gt;
&lt;section class="my-16"&gt;
&lt;div class="container mx-auto max-w-5xl md:flex my-8 align-top justify-center text-center"&gt;
&lt;div class="md:w3-/12 mr-4"&gt;
&lt;h2 class="no-anchor"&gt;Get Started with Pulumi&lt;/h2&gt;
&lt;p class="text-gray-700 dark:text-gray-300 text-sm"&gt;Use Pulumi's open-source SDK to create, deploy, and manage infrastructure on any cloud.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="mx-auto max-w-4xl"&gt;
&lt;div class="tiles flex-wrap mt-4"&gt;
&lt;div class="pb-4 md:pr-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/aws/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/aws.svg" alt="AWS" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="pb-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/azure/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/azure.svg" alt="Azure" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="pb-4 md:pr-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/gcp/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/gcp.svg" alt="Google Cloud" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="pb-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/kubernetes/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/k8s.svg" alt="Kubernetes" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;</description><author>Adam Gordon Bell</author><category>internal-developer-platform</category><category>platform-engineering</category><category>policy-as-code</category><category>crossguard</category><category>compliance</category><category>security</category><category>self-service</category><category>guardrails</category></item><item><title>Meet Neo, Your Newest Platform Engineer</title><link>https://www.pulumi.com/blog/pulumi-neo/</link><pubDate>Tue, 16 Sep 2025 07:00:00 -0600</pubDate><guid>https://www.pulumi.com/blog/pulumi-neo/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/pulumi-neo/index.png" /&gt;
&lt;p&gt;AI coding assistants have transformed the speed at which developers can write and deploy code. Pull request velocity has increased significantly. Feature delivery has accelerated beyond what we thought possible just two years ago. This should be a victory for everyone in the software organization.&lt;/p&gt;
&lt;p&gt;Instead, it&amp;rsquo;s created significant challenges for infrastructure and platform teams.&lt;/p&gt;
&lt;p&gt;Every line of code that ships faster creates new platform needs: monitoring, secrets management, deployment pipelines, and compliance checks. The rapid pace also increases the risk of insecure or non-compliant code reaching production. Developer velocity has increased dramatically, but platform teams haven&amp;rsquo;t scaled to match.&lt;/p&gt;
&lt;p&gt;Platform teams are struggling because they lack the proper tools for their unique challenges. They&amp;rsquo;re caught in a velocity trap where generic AI accelerates developers while leaving platform teams behind. We&amp;rsquo;re optimizing software development speed while creating global infrastructure debt.&lt;/p&gt;
&lt;p&gt;The very success of developer AI has become a challenge for the platform team.&lt;/p&gt;
&lt;h2 id="introducing-pulumi-neo"&gt;Introducing Pulumi Neo&lt;/h2&gt;
&lt;p&gt;Neo is a purpose-built infrastructure automation agent that amplifies your platform engineering capabilities. Built on Pulumi&amp;rsquo;s platform, Neo has a deep understanding of cloud context, IaC, secrets and configuration, internal developer platforms, and more. It automatically respects your security and policy guardrails and works in tandem with human-in-the-loop approvals and controls.&lt;/p&gt;
&lt;p&gt;&lt;img src="introducing-pulumi-neo.png" alt="Pulumi Neo automating AWS Lambda Node.js runtime upgrades with policy validation and pull request creation"&gt;&lt;/p&gt;
&lt;p&gt;For years, we&amp;rsquo;ve worked closely with platform and infrastructure teams. We&amp;rsquo;ve observed how the demands on these teams have intensified as development velocity has increased. We understand the challenges they face in keeping pace with rapidly evolving infrastructure needs.&lt;/p&gt;
&lt;p&gt;The pattern became clear. Generic AI tools excel at generating code but lack the context to understand the unique challenges of infrastructure, including state management, tracking dependencies across services, scaling across tens to hundreds of repositories, and anticipating the effects of changes across an organization.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve heard countless stories from platform engineers about spending hours tracking down dependencies, credential locations, and configuration relationships across their systems. When they try to use generic AI tools for these tasks, the tools often suggest changes without understanding the broader organizational context and dependencies.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s when we realized: Platform engineers don&amp;rsquo;t need faster AI tools. They need their own dedicated AI tool, one that understands infrastructure context, speaks their language, and works within their constraints.&lt;/p&gt;
&lt;p&gt;These insights led us to develop Neo, an AI agent specifically designed for platform and infrastructure engineering teams. Unlike generic coding assistants, Neo understands the full context of infrastructure: it knows that changes span multiple repositories, that every modification has downstream effects, and that compliance and security policies matter as much as the code itself.&lt;/p&gt;
&lt;h2 id="built-for-enterprise-trust"&gt;Built for Enterprise Trust&lt;/h2&gt;
&lt;p&gt;Neo represents a fundamentally different approach to AI in infrastructure. We view the Pulumi platform&amp;rsquo;s existing features, like IaC, ESC, and policies, as the foundation for trustworthy AI automation. These aren&amp;rsquo;t additional guardrails we&amp;rsquo;ve added; they&amp;rsquo;re the very platform capabilities you&amp;rsquo;re already using. Understanding the impact scope through your infrastructure graph gives you confidence to move faster. Knowing compliance implications through your existing policies before making changes is what actually accelerates platform teams.&lt;/p&gt;
&lt;p&gt;While other solutions retrofit generic AI models with infrastructure plugins, Neo is built from the ground up on proven enterprise foundations. It operates within your existing Pulumi governance frameworks, respects your policies, and maintains the audit trails and compliance controls your organization requires. Your investment in Pulumi&amp;rsquo;s platform features—the same ones that govern your infrastructure today—becomes Neo&amp;rsquo;s operational guardrails.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t experimental AI, it&amp;rsquo;s enterprise-ready automation that amplifies your expertise while working within the same platform controls that keep your infrastructure secure and compliant. The Pulumi features you rely on for governance become the accelerants that enable confident, rapid automation.&lt;/p&gt;
&lt;h2 id="the-reinforcement-cycle"&gt;The Reinforcement Cycle&lt;/h2&gt;
&lt;p&gt;Neo becomes more capable the more you invest in infrastructure as code. Every Pulumi component you write, every policy you define, every environment configuration you establish becomes Neo&amp;rsquo;s operational context that guides its decisions.&lt;/p&gt;
&lt;p&gt;This is the key shift. We&amp;rsquo;re talking about AI amplifying platform expertise. The engineers who understand the why behind infrastructure decisions become even more valuable when they have tools that can execute the how at scale.&lt;/p&gt;
&lt;p&gt;The teams that lean into this cycle will find themselves accelerating while others are still struggling. They&amp;rsquo;ll be writing policies while others are responding to issues. They&amp;rsquo;ll be designing systems while others are updating versions.&lt;/p&gt;
&lt;h2 id="the-platform-engineering-evolution"&gt;The Platform Engineering Evolution&lt;/h2&gt;
&lt;p&gt;The bigger picture extends far beyond task automation. Platform engineering evolves from reactive to proactive. Teams shift from ticket takers to strategic enablers. Infrastructure becomes self-healing and self-documenting. The profession transforms from responding to urgent issues to crafting foundations.&lt;/p&gt;
&lt;p&gt;Imagine infrastructure that evolves as fast as the code it supports. Imagine platform teams that can actually think about next quarter instead of just surviving next sprint. Imagine organizations that can sustain AI-driven development velocity because their infrastructure keeps pace automatically.&lt;/p&gt;
&lt;p&gt;For the industry, this means the end of the &amp;ldquo;platform team bottleneck&amp;rdquo; narrative. No longer will infrastructure be the reason features don&amp;rsquo;t ship. No longer will platform engineers be seen as blockers in the velocity story. Instead, they&amp;rsquo;ll be the enablers who made sustainable speed possible.&lt;/p&gt;
&lt;p&gt;This is the rise of strategic platform engineering. These are professionals who shape how organizations build and operate software, who establish the foundations that make everything else possible, and who finally have tools that match the complexity and importance of their work.&lt;/p&gt;
&lt;h2 id="the-choice-before-us"&gt;The Choice Before Us&lt;/h2&gt;
&lt;p&gt;What we&amp;rsquo;re launching is more than an AI agent. We&amp;rsquo;re introducing your newest platform engineer, who gets smarter as your infrastructure evolves. We&amp;rsquo;re launching a new era for platform engineering, one where the teams that enable everyone else finally have tools built specifically for their reality.&lt;/p&gt;
&lt;p&gt;Neo represents our belief that platform engineers shouldn&amp;rsquo;t have to choose between speed and safety, between automation and control, between serving developers and driving strategy. These are false choices created by tools that lack an understanding of infrastructure.&lt;/p&gt;
&lt;p&gt;The age of generic AI taught us what&amp;rsquo;s possible. The era of specialized AI shows us what&amp;rsquo;s practical. Platform teams have been overloaded by everyone else&amp;rsquo;s velocity long enough.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s time for platform engineering to keep pace instead of falling behind.&lt;/p&gt;
&lt;p&gt;Neo is available today in public preview. Ready to meet your newest platform engineer? Join thousands of teams already transforming their infrastructure workflows with the Pulumi platform.&lt;/p&gt;
&lt;p&gt;The future of platform engineering starts now, and it starts with &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/neo/"&gt;Neo&lt;/a&gt;.&lt;/p&gt;</description><author>Pulumi Neo Team</author><category>ai</category><category>ai-agents</category><category>platform-engineering</category><category>pulumi-neo</category></item><item><title>Introducing Automatic API Docs in Private Registry</title><link>https://www.pulumi.com/blog/registry-component-api-docs/</link><pubDate>Wed, 27 Aug 2025 00:00:05 -0600</pubDate><guid>https://www.pulumi.com/blog/registry-component-api-docs/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/registry-component-api-docs/index.png" /&gt;
&lt;p&gt;Building and maintaining reusable infrastructure has always been about more than just writing good code. It&amp;rsquo;s about making that code discoverable, understandable, and easy to adopt across your organization. Today, we&amp;rsquo;re excited to announce a new feature that removes significant friction from sharing and consuming &lt;a href="https://www.pulumi.com/docs/concepts/resources/components/"&gt;infrastructure components&lt;/a&gt;: automatic multi-language API documentation in &lt;a href="https://www.pulumi.com/docs/idp/get-started/private-registry/"&gt;Pulumi Private Registry&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-challenge-of-sharing-infrastructure-at-scale"&gt;The Challenge of Sharing Infrastructure at Scale&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/product/internal-developer-platforms/"&gt;Platform teams&lt;/a&gt; invest significant effort in creating &lt;a href="https://www.pulumi.com/docs/idp/best-practices/patterns/"&gt;reusable infrastructure components&lt;/a&gt;. But creating the infrastructure is only half the battle. The real challenge comes in making these resources discoverable and usable by development teams across the organization.&lt;/p&gt;
&lt;p&gt;Until now, platform teams publishing components faced a discovery challenge. While developers get excellent IDE support with autocomplete once they&amp;rsquo;re coding, teams first need to know what components exist, understand their capabilities, and evaluate which one fits their needs. Without browsable API documentation in the registry, developers couldn&amp;rsquo;t easily discover available components or compare versions. Security and compliance teams lacked visibility into what infrastructure patterns were being shared. And platform teams had no central place to showcase their catalog of approved, battle-tested components that encode organizational best practices.&lt;/p&gt;
&lt;h2 id="from-code-to-comprehensive-docs"&gt;From Code to Comprehensive Docs&lt;/h2&gt;
&lt;p&gt;Starting today, whenever you publish a component to your Pulumi private registry, whether it&amp;rsquo;s a brand new component or an updated version, Pulumi automatically generates comprehensive API documentation for all of the component&amp;rsquo;s resources.&lt;/p&gt;
&lt;h3 id="how-it-works"&gt;How It Works&lt;/h3&gt;
&lt;p&gt;When you run &lt;code&gt;pulumi package publish&lt;/code&gt; for your component, we analyze your component&amp;rsquo;s structure, inputs, outputs, and resources to generate rich, interactive API documentation. This documentation is immediately available in your private registry, formatted consistently across all Pulumi-supported languages.&lt;/p&gt;
&lt;h3 id="multi-language-support-out-of-the-box"&gt;Multi-Language Support Out of the Box&lt;/h3&gt;
&lt;p&gt;One of Pulumi&amp;rsquo;s core strengths is our &lt;a href="https://www.pulumi.com/blog/pulumi-components/"&gt;multi-language components&lt;/a&gt;: write once in your preferred language, and teams can consume the component in &lt;a href="https://www.pulumi.com/docs/languages-sdks/"&gt;Python, TypeScript, Go, C#, Java, or YAML&lt;/a&gt;. The automatic documentation generation embraces this philosophy.&lt;/p&gt;
&lt;p&gt;When you &lt;a href="https://www.pulumi.com/docs/idp/get-started/publishing-from-github-actions/"&gt;publish a component&lt;/a&gt; written in Python, developers using TypeScript can view the TypeScript-specific documentation. The same component shows Go developers idiomatic Go code. This language-specific documentation removes the last barrier to &lt;a href="https://www.pulumi.com/docs/idp/best-practices/patterns/components-using-other-components/"&gt;cross-team component adoption&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="multi-lang-apis.jpg" alt="Multi-language component support"&gt;&lt;/p&gt;
&lt;h3 id="improving-discoverability-and-adoption"&gt;Improving Discoverability and Adoption&lt;/h3&gt;
&lt;p&gt;With automatic API documentation, your &lt;a href="https://www.pulumi.com/blog/announcing-pulumi-private-registry/"&gt;private registry&lt;/a&gt; transforms from a simple package repository into a comprehensive catalog. Developers can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Browse available components and immediately understand their purpose and usage&lt;/li&gt;
&lt;li&gt;See all available configuration options with type information&lt;/li&gt;
&lt;li&gt;Evaluate what infrastructure each component provisions before choosing to adopt it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This dramatically reduces the time from component discovery to successful deployment, accelerating your organization&amp;rsquo;s &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-2/"&gt;infrastructure velocity&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="getting-started"&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Automatic API docs are available today for all &lt;a href="https://www.pulumi.com/product/pulumi-cloud/"&gt;Pulumi Cloud&lt;/a&gt; customers with access to private registry. To start generating docs, simply &lt;a href="https://www.pulumi.com/docs/idp/get-started/private-registry/#publishing-components"&gt;publish your component&lt;/a&gt;. Documentation generation happens automatically with no configuration required, and docs will automatically appear for existing components.&lt;/p&gt;
&lt;h2 id="looking-ahead"&gt;Looking Ahead&lt;/h2&gt;
&lt;p&gt;Automatic API docs represent our continued investment in making Pulumi the most productive platform for infrastructure teams. By removing friction from the component lifecycle, we&amp;rsquo;re enabling platform teams to focus on what matters most: building robust, secure, and scalable &lt;a href="https://www.pulumi.com/docs/idp/best-practices/patterns/"&gt;infrastructure patterns&lt;/a&gt; that accelerate their entire organization.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re excited to see how teams use them to build more effective &lt;a href="https://www.pulumi.com/blog/announcing-pulumi-idp/"&gt;internal developer platforms&lt;/a&gt;. As always, we&amp;rsquo;d love to hear your feedback and learn about your use cases on our &lt;a href="https://github.com/pulumi/pulumi-cloud-requests"&gt;Pulumi Cloud requests repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ready to streamline your infrastructure development workflow? Get started with &lt;a href="https://app.pulumi.com/signup"&gt;Pulumi Cloud&lt;/a&gt; or check out our &lt;a href="https://www.pulumi.com/docs/idp/get-started/"&gt;IDP documentation&lt;/a&gt; to learn more about &lt;a href="https://www.pulumi.com/docs/idp/best-practices/four-factors/"&gt;building with components&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/idp/get-started/workflows/"&gt;workflows&lt;/a&gt;.&lt;/p&gt;</description><author>Pulumi IDP Team</author><category>internal-developer-platform</category><category>private-registry</category><category>infrastructure-components</category><category>platform-engineering</category></item><item><title>Golden Paths in IDPs: A Complete Guide to Reusable Infrastructure with Pulumi Components and Templates</title><link>https://www.pulumi.com/blog/golden-paths-infrastructure-components-and-templates/</link><pubDate>Wed, 20 Aug 2025 10:00:00 +0200</pubDate><guid>https://www.pulumi.com/blog/golden-paths-infrastructure-components-and-templates/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/golden-paths-infrastructure-components-and-templates/index.png" /&gt;
&lt;p&gt;Welcome to the second post in our &lt;strong&gt;IDP Best Practices&lt;/strong&gt; series. In this article, we explore how to create &lt;strong&gt;golden paths&lt;/strong&gt;, pre-architected, reusable infrastructure patterns that help standardize and accelerate cloud development.&lt;/p&gt;
&lt;p&gt;Modern cloud platforms offer endless options, over 200 AWS services, sprawling Azure catalogs, and countless DevOps tools. The result? Developers face decision fatigue and inconsistent implementations. Golden paths solve this by providing &lt;strong&gt;ready-to-use, production-grade infrastructure&lt;/strong&gt; that encodes your organization’s best practices, security policies, and operational standards.&lt;/p&gt;
&lt;p&gt;In this guide, you&amp;rsquo;ll learn how to build golden paths for your Internal Developer Platform using two core Pulumi constructs: &lt;strong&gt;Components&lt;/strong&gt;, reusable infrastructure building blocks, and &lt;strong&gt;Templates&lt;/strong&gt;, predefined, deployable patterns. You&amp;rsquo;ll see how to create infrastructure abstractions that are written once, shared across teams, and consumed in any language, turning weeks of setup into minutes of developer-ready infrastructure.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;The complete code examples from this post are available on &lt;a href="https://github.com/pulumi/workshops/tree/main/golden-paths-infrastructure-components-and-templates"&gt;GitHub&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="the-platform-engineering-layer-cake-a-model-for-idps"&gt;The Platform Engineering Layer Cake: A Model for IDPs&lt;/h2&gt;
&lt;p&gt;To understand where golden paths fit into an Internal Developer Platform (IDP), think in layers. This three-tier model structures your platform to deliver increasing levels of abstraction, reuse, and developer value:&lt;/p&gt;
&lt;h3 id="layer-1-infrastructure-layer"&gt;Layer 1: Infrastructure Layer&lt;/h3&gt;
&lt;p&gt;This is the foundation: raw cloud resources include VMs, databases, networks, and storage, which are the fundamental building blocks from AWS, Azure, GCP, and other providers. Pulumi gives you programmatic access to these resources through &lt;a href="https://www.pulumi.com/registry/"&gt;native providers&lt;/a&gt;, but working at this level requires deep infrastructure knowledge.&lt;/p&gt;
&lt;h3 id="layer-2-platform-layer---components"&gt;Layer 2: Platform Layer - Components&lt;/h3&gt;
&lt;p&gt;This is where the magic happens. &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;Pulumi Components&lt;/a&gt; take those raw resources and package them into higher-level abstractions. Instead of manually configuring 20+ AWS resources for a secure web application, you create a component that handles all that complexity and exposes just the configuration that matters:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SecureWebApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;instanceType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;t3.medium&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;minReplicas&lt;/span&gt;: &lt;span class="kt"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;maxReplicas&lt;/span&gt;: &lt;span class="kt"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;enableWAF&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;production&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="part-1-building-reusable-infrastructure-components"&gt;Part 1: Building Reusable Infrastructure Components&lt;/h2&gt;
&lt;p&gt;Reusable infrastructure components act as the foundation of your platform. They encapsulate complexity while remaining composable and scalable. Let&amp;rsquo;s build a real-world example: a component that deploys containerized microservices to AWS Fargate.&lt;/p&gt;
&lt;h3 id="the-power-of-multi-language-components"&gt;The Power of Multi-Language Components&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s what makes Pulumi components revolutionary: &lt;strong&gt;write once, consume anywhere&lt;/strong&gt;. Your platform team can author components in TypeScript, but application teams can consume them in Python, Go, .NET, Java, or even YAML. This separation of concerns is crucial for scaling platform engineering across diverse teams.&lt;/p&gt;
&lt;h3 id="building-a-microservice-component-step-by-step"&gt;Building a Microservice Component Step-by-Step&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s create a component that encapsulates everything needed to deploy a production-ready microservice:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// microservice-component.ts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/aws&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/awsx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceArgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;appPath&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Path to application code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;cpu?&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// CPU units (256, 512, 1024, etc.)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;memory?&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Memory in MB
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;port?&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Application port
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;desiredCount?&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Number of tasks
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceComponent&lt;/span&gt; &lt;span class="kr"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentResource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;: &lt;span class="kt"&gt;pulumi.Output&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;serviceName&lt;/span&gt;: &lt;span class="kt"&gt;pulumi.Output&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;clusterName&lt;/span&gt;: &lt;span class="kt"&gt;pulumi.Output&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;: &lt;span class="kt"&gt;MicroserviceArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts?&lt;/span&gt;: &lt;span class="kt"&gt;pulumi.ComponentResourceOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;custom:infrastructure:Microservice&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Set defaults
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cpu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cpu&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;desiredCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;desiredCount&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Create ECR repository for Docker images
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ecr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Repository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-repo`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;forceDelete&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Build and push Docker image
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ecr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-image`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;repositoryUrl&lt;/span&gt;: &lt;span class="kt"&gt;repository.url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;context&lt;/span&gt;: &lt;span class="kt"&gt;args.appPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;linux/amd64&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Create Application Load Balancer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loadBalancer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ApplicationLoadBalancer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-lb`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;defaultTargetGroup&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;port&lt;/span&gt;: &lt;span class="kt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;HTTP&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;healthCheck&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/health&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;interval&lt;/span&gt;: &lt;span class="kt"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt;: &lt;span class="kt"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;healthyThreshold&lt;/span&gt;: &lt;span class="kt"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;unhealthyThreshold&lt;/span&gt;: &lt;span class="kt"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Create ECS cluster
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ecs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cluster&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-cluster`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Create Fargate service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ecs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FargateService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-service`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt;: &lt;span class="kt"&gt;cluster.arn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;taskDefinitionArgs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;: &lt;span class="kt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;image&lt;/span&gt;: &lt;span class="kt"&gt;image.imageUri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;cpu&lt;/span&gt;: &lt;span class="kt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;memory&lt;/span&gt;: &lt;span class="kt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;essential&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;portMappings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;containerPort&lt;/span&gt;: &lt;span class="kt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;targetGroup&lt;/span&gt;: &lt;span class="kt"&gt;loadBalancer.defaultTargetGroup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;desiredCount&lt;/span&gt;: &lt;span class="kt"&gt;desiredCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;assignPublicIp&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Export outputs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolate&lt;/span&gt;&lt;span class="sb"&gt;`http://&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;loadBalancer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadBalancer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dnsName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clusterName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Register outputs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerOutputs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;url&lt;/span&gt;: &lt;span class="kt"&gt;this.url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;serviceName&lt;/span&gt;: &lt;span class="kt"&gt;this.serviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;clusterName&lt;/span&gt;: &lt;span class="kt"&gt;this.clusterName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="documenting-for-discoverability-and-adoption"&gt;Documenting for Discoverability and Adoption&lt;/h3&gt;
&lt;p&gt;To make your component easy to use, add comprehensive documentation and examples to a &lt;code&gt;README.md&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MicroserviceComponent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Abstraction &lt;span class="k"&gt;for&lt;/span&gt; resources needed when using AWS container services.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A component to abstract the details related to:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Creating a docker image and pushing it to AWS ECR.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Deploy to ECS Fargate using the docker image.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Inputs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* appPath: Path to &lt;span class="nb"&gt;local&lt;/span&gt; folder containing the app and Dockerfile.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* port: Port to expose via an ALB.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* cpu &lt;span class="o"&gt;(&lt;/span&gt;Optional&lt;span class="o"&gt;)&lt;/span&gt;: CPU capacity. Defaults to &lt;span class="m"&gt;256&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;i.e. 0.25 vCPU&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* memory &lt;span class="o"&gt;(&lt;/span&gt;Optional&lt;span class="o"&gt;)&lt;/span&gt;: Memory capacity. Defaults to &lt;span class="m"&gt;512&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;i.e. 0.5GB&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* containerName &lt;span class="o"&gt;(&lt;/span&gt;Optional&lt;span class="o"&gt;)&lt;/span&gt;: Name of the container. Defaults to &lt;span class="s2"&gt;&amp;#34;my-app&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Outputs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* publicUrl: The DNS name &lt;span class="k"&gt;for&lt;/span&gt; the loadbalancer fronting the app.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Usage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Specify Package in `Pulumi.yaml`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Add the following to your &lt;span class="sb"&gt;`&lt;/span&gt;Pulumi.yaml&lt;span class="sb"&gt;`&lt;/span&gt; file:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Note: If no version is specified, the latest version will be used.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;... omit &lt;span class="k"&gt;for&lt;/span&gt; brevity ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This documentation will help developers understand how to use your component effectively, including required inputs, outputs, and example usage.&lt;/p&gt;
&lt;h3 id="publishing-your-component-via-private-registry"&gt;Publishing Your Component via Private Registry&lt;/h3&gt;
&lt;p&gt;Once your component is ready, publish it to your &lt;a href="https://www.pulumi.com/docs/idp/get-started/private-registry/"&gt;Pulumi Private Registry&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Tag your component version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git tag v1.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Publish to your organization&amp;#39;s registry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi package publish https://registry.pulumi.com/myorg/microservice-component
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now any team in your organization can discover and use your component, regardless of their language preference. All they need is to navigate to the &lt;code&gt;Components&lt;/code&gt; section in the Pulumi IDP and search for &lt;code&gt;microservice-component&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi_idp_components_view.png" alt="img_2.png"&gt;&lt;/p&gt;
&lt;h2 id="part-2-from-building-blocks-to-golden-paths"&gt;Part 2: From Building Blocks to Golden Paths&lt;/h2&gt;
&lt;p&gt;While components are powerful, they&amp;rsquo;re just the starting point. Golden path templates layer on opinionated scaffolding, workflows, and compliance best practices that guide developers to production.&lt;/p&gt;
&lt;h3 id="golden-path-maturity-from-zero-to-product-grade-platforms"&gt;Golden Path Maturity: From Zero to Product-Grade Platforms&lt;/h3&gt;
&lt;p&gt;Teams evolve from ad hoc deployments to mature, productized templates with versioning, metrics, and governance. These maturity levels reflect how deeply your platform enables safe, consistent delivery.&lt;/p&gt;
&lt;p&gt;&lt;img src="golden_paths_maturity_level.png" alt="img_8.png"&gt;&lt;/p&gt;
&lt;p&gt;Organizations typically progress through three stages of golden path maturity:&lt;/p&gt;
&lt;h4 id="stage-1-no-golden-paths"&gt;Stage 1: No Golden Paths&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Every team reinvents the wheel&lt;/li&gt;
&lt;li&gt;Inconsistent practices across projects&lt;/li&gt;
&lt;li&gt;High cognitive load on developers&lt;/li&gt;
&lt;li&gt;Security and compliance gaps&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="stage-2-dawn-of-templates"&gt;Stage 2: Dawn of Templates&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Basic cookie-cutter templates emerge&lt;/li&gt;
&lt;li&gt;Some standardization begins&lt;/li&gt;
&lt;li&gt;Manual processes still dominate&lt;/li&gt;
&lt;li&gt;Limited support and evolution&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="stage-3-templates-as-products"&gt;Stage 3: Templates as Products&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Golden paths have dedicated owners&lt;/li&gt;
&lt;li&gt;Regular release cycles and versioning&lt;/li&gt;
&lt;li&gt;Migration guides for updates&lt;/li&gt;
&lt;li&gt;Metrics track adoption and success&lt;/li&gt;
&lt;li&gt;Continuous improvement based on feedback&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="what-makes-a-golden-path-golden"&gt;What Makes a Golden Path Golden?&lt;/h3&gt;
&lt;p&gt;Drawing from &lt;a href="https://engineering.atspotify.com/2020/08/how-we-use-golden-paths-to-solve-fragmentation-in-our-software-ecosystem/"&gt;Spotify&amp;rsquo;s pioneering work&lt;/a&gt;, golden paths share these characteristics:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pre-architected and Supported&lt;/strong&gt;: The platform team owns and supports the path&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional but Recommended&lt;/strong&gt;: Developers can deviate, but staying on the path ensures support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transparent Abstractions&lt;/strong&gt;: The implementation is visible, not a black box&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extensible&lt;/strong&gt;: Teams can add project-specific resources without breaking the pattern&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evolutionary&lt;/strong&gt;: Templates improve based on feedback and new requirements&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="building-a-go-microservice-golden-path"&gt;Building a Go Microservice Golden Path&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s create a complete golden path for Go microservices that includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Application scaffolding with best practices&lt;/li&gt;
&lt;li&gt;Infrastructure deployment using our component&lt;/li&gt;
&lt;li&gt;CI/CD pipeline configuration&lt;/li&gt;
&lt;li&gt;Observability setup&lt;/li&gt;
&lt;li&gt;Security controls&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="step-1-template-structure"&gt;Step 1: Template Structure&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;go-microservice-boilerplate/
├── Pulumi.yaml # Infrastructure definition
├── src/ # Application code
│ ├── main.go # Go microservice
│ ├── Dockerfile # Container definition
│ └── go.mod # Dependencies
└── README.md # Documentation
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="step-2-application-scaffolding"&gt;Step 2: Application Scaffolding&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;src/main.go&lt;/code&gt; file contains a minimal Go microservice with all the best practices and compliance guardrails baked in. This helps developers to quickly get started and extend the application without worrying too much about selecting the right libraries or frameworks.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// source/main.go&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;os/signal&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/labstack/echo/v4&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/labstack/echo/v4/middleware&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/otel&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/otel/sdk/resource&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/otel/sdk/trace&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;semconv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/otel/semconv/v1.34.0&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;initTracer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TracerProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;exporter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;otlptracehttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewWithAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;semconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SchemaURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;semconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ServiceNameKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;${PROJECT}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;semconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ServiceVersionKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewTracerProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithBatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exporter&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithSampler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AlwaysSample&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;otel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetTracerProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;echoHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;QueryParam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello from Go microservice!&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;echo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;service&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;${PROJECT}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RFC3339&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;healthHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;healthy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;service&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;${PROJECT}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;healthCheck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;health-check&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Run health check and exit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;healthCheck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://localhost:8080/health&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusCode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusOK&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;initTracer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Recover&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CORS&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;otelecho&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;${PROJECT}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/echo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;echoHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/health&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;healthHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;:8080&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ErrServerClosed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;shutting down the server&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Interrupt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-3-infrastructure-template-with-yaml"&gt;Step 3: Infrastructure Template with YAML&lt;/h4&gt;
&lt;p&gt;Here&amp;rsquo;s how you define the infrastructure using Pulumi YAML. You can instantly spot one of the features of Pulumi Components. We consume the &lt;code&gt;micorservice-component&lt;/code&gt; in YAML without knowing that it was authored in a different language. This is the power of Pulumi Components: write once, consume anywhere.&lt;/p&gt;
&lt;p&gt;And we see another feature of Pulumi Components: As it is a first-class citizen, we can embed the component and add additional resources like auto-scaling policies, alarms, and more directly in the YAML file. This allows us to create a complete golden path for deploying Go microservices on AWS ECS with auto-scaling capabilities.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Pulumi.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${PROJECT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${DESCRIPTION}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;component-microservice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://github.com/smithrobs/component-microservice@v1.0.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;A template for deploying a Go microservice on AWS ECS with auto-scaling capabilities.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;microserviceComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;component-microservice:MicroserviceComponent&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;appPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./src&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${PROJECT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ecsTarget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws:appautoscaling:Target&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs_target&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxCapacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minCapacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service/${microserviceComponent.clusterName}/${microserviceComponent.serviceName}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalableDimension&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs:service:DesiredCount&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serviceNamespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ecsPolicyUP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws:appautoscaling:Policy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs_policy_up&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs_policy_up&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;policyType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;StepScaling&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.resourceId}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalableDimension&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.scalableDimension}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serviceNamespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.serviceNamespace}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stepScalingPolicyConfiguration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;adjustmentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ChangeInCapacity&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cooldown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metricAggregationType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Maximum&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stepAdjustments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;metricIntervalUpperBound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalingAdjustment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ecsPolicyDown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws:appautoscaling:Policy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs_policy_down&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs_policy_down&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;policyType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;StepScaling&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.resourceId}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalableDimension&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.scalableDimension}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serviceNamespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.serviceNamespace}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stepScalingPolicyConfiguration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;adjustmentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ChangeInCapacity&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cooldown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metricAggregationType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Maximum&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stepAdjustments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;metricIntervalLowerBound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalingAdjustment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serviceCPUHighUtilization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws:cloudwatch:MetricAlarm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service_cpu_high_utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service_cpu_high_utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;comparisonOperator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;GreaterThanOrEqualToThreshold&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;evaluationPeriods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metricName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;CPUUtilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;AWS/ECS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;statistic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Average&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alarmActions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;${ecsPolicyUP.arn}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ClusterName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${microserviceComponent.clusterName}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ServiceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${microserviceComponent.serviceName}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serviceCPULowUtilization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws:cloudwatch:MetricAlarm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service_cpu_low_utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service_cpu_low_utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;comparisonOperator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;LessThanOrEqualToThreshold&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;evaluationPeriods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metricName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;CPUUtilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;AWS/ECS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;statistic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Average&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alarmActions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;${ecsPolicyDown.arn}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ClusterName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${microserviceComponent.clusterName}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ServiceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${microserviceComponent.serviceName}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;publicUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${microserviceComponent.publicUrl}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-4-documentation-and-examples"&gt;Step 4: Documentation and Examples&lt;/h4&gt;
&lt;p&gt;Add a &lt;code&gt;README.md&lt;/code&gt; file to your template directory to provide clear instructions on how to use the template, including prerequisites, configuration options, and example commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Go Microservice Golden Path&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;A **golden path** template that gets your Go microservice from code to production on AWS in minutes, not weeks.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;## What You Get&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;This golden path provides everything your development team needs to deploy production-ready Go microservices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **Production-ready Go microservice** with Echo framework and OpenTelemetry tracing&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **AWS infrastructure that scales** - ECS with auto-scaling from 1-4 instances&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **Security by default** - Hardened containers, IAM roles, security groups&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **Monitoring built-in** - Health checks, load balancer monitoring, CloudWatch alarms&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **One-command deployment** - `pulumi up` handles everything&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **No AWS expertise required** - Complex ECS setup abstracted away&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;## For Development Teams: What to Expect&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;### Your Experience&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;**Day&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Getting Started**&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Clone this repo, run `pulumi up`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Your service is live on AWS in 5-10 minutes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Public URL provided automatically - no manual setup needed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;**Day&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;2-N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Development Workflow**&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Write your Go code in `microservice/main.go`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Test locally with `go run main.go`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Deploy changes with `pulumi up`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;AWS automatically rebuilds and redeploys your container&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;**Production&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Operations**&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Service automatically scales with CPU load (80% up, 10% down)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Health checks ensure unhealthy containers are replaced&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Load balancer distributes traffic across healthy instances&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Distributed tracing helps debug issues across services&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;### What&amp;#39;s Handled For You&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;You **don&amp;#39;t** need to learn or configure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;ECS clusters, services, and task definitions&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Application Load Balancers and target groups&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Auto-scaling policies and CloudWatch alarms&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Security groups and IAM roles&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Container registries and image building&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Health check configuration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;You **do** focus on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Writing your Go application logic&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Adding your business endpoints&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Testing your service locally&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Deploying with confidence&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="making-templates-available-in-pulumi-idp"&gt;Making Templates Available in Pulumi IDP&lt;/h3&gt;
&lt;p&gt;Publishing your template to &lt;a href="https://www.pulumi.com/docs/idp/"&gt;Pulumi IDP&lt;/a&gt; enables true self-service. Head to &lt;code&gt;Settings&lt;/code&gt; → &lt;code&gt;Integrations&lt;/code&gt; → &lt;code&gt;Organization Template Sources&lt;/code&gt; and add your template repository.&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi_idp_integrations_view.png" alt="img_4.png"&gt;&lt;/p&gt;
&lt;p&gt;Once published, developers can discover and deploy it directly from the IDP interface.&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi_idp_templates_view.png" alt="img_5.png"&gt;&lt;/p&gt;
&lt;p&gt;Now developers can deploy through multiple interfaces:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CLI Deployment:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi new https://github.com/myorg/go-microservice-boilerplate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;No-Code Deployment:&lt;/strong&gt;
Navigate to &lt;a href="https://www.pulumi.com/docs/idp/get-started/workflows/"&gt;Pulumi IDP&lt;/a&gt; → &lt;code&gt;Templates&lt;/code&gt; → &lt;code&gt;Deploy with Pulumi&lt;/code&gt; → Configure and launch&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi_idp_deployment_no_code_view.png" alt="img_7.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pulumi Deployment:&lt;/strong&gt;
Navigate to &lt;a href="https://www.pulumi.com/docs/idp/get-started/workflows/"&gt;Pulumi IDP&lt;/a&gt; → &lt;code&gt;Templates&lt;/code&gt; → &lt;code&gt;Deploy with Pulumi&lt;/code&gt; → Configure and launch&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi_idp_deployment_git_view.png" alt="img_6.png"&gt;&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Build golden paths with Pulumi&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Package your infrastructure patterns into reusable components and templates, publish them to a private registry, and let teams deploy production-ready stacks in minutes.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="best-practices-for-reusable-infrastructure-components-and-templates"&gt;Best Practices for Reusable Infrastructure Components and Templates&lt;/h2&gt;
&lt;p&gt;Well-designed components and templates are the foundation of scalable, self-service infrastructure. These best practices ensure your abstractions are maintainable, discoverable, and production-ready.&lt;/p&gt;
&lt;h3 id="1-design-for-day-2-operations-from-day-1"&gt;1. Design for Day 2 Operations from Day 1&lt;/h3&gt;
&lt;p&gt;Think beyond deployment. A golden path must also support ongoing operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How will teams safely update their infrastructure?&lt;/li&gt;
&lt;li&gt;What happens during scaling events?&lt;/li&gt;
&lt;li&gt;How do you handle disaster recovery?&lt;/li&gt;
&lt;li&gt;What metrics and logs are needed for troubleshooting?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-expose-complexity-progressively"&gt;2. Expose Complexity Progressively&lt;/h3&gt;
&lt;p&gt;Provide sensible defaults that work, while enabling customization for advanced use cases:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ComponentArgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Required - what users must provide
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;appName&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Common customizations with good defaults
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;instanceType?&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// default: &amp;#34;t3.micro&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;replicas?&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// default: 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Advanced options for power users
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;networkConfig?&lt;/span&gt;: &lt;span class="kt"&gt;NetworkConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;securityPolicies?&lt;/span&gt;: &lt;span class="kt"&gt;SecurityPolicy&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;customMetrics?&lt;/span&gt;: &lt;span class="kt"&gt;MetricDefinition&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-use-semantic-versioning-everywhere"&gt;4. Use Semantic Versioning Everywhere&lt;/h3&gt;
&lt;p&gt;Clear versioning for both components and templates indicate stability and reliability:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Major versions&lt;/strong&gt; (1.0.0 → 2.0.0): Breaking changes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minor versions&lt;/strong&gt; (1.0.0 → 1.1.0): New features, backward compatible&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Patch versions&lt;/strong&gt; (1.0.0 → 1.0.1): Bug fixes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This lets teams adopt updates with confidence and control.&lt;/p&gt;
&lt;h3 id="5-test-your-abstractions"&gt;5. Test Your Abstractions&lt;/h3&gt;
&lt;p&gt;Don&amp;rsquo;t ship black boxes. Create automated tests to validate key functionality and resource creation. Focus on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Smoke tests that validate resource existence&lt;/li&gt;
&lt;li&gt;Output validation to ensure correctness&lt;/li&gt;
&lt;li&gt;Integration tests to confirm end-to-end behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;chai&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;MicroserviceComponent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;should create required resources&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;appPath&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./test-app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;port&lt;/span&gt;: &lt;span class="kt"&gt;3000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allResources&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;aws:ecs/cluster:Cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;aws:ecs/service:Service&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;aws:lb/loadBalancer:LoadBalancer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="how-to-measure-golden-path-success"&gt;How to Measure Golden Path Success&lt;/h2&gt;
&lt;p&gt;Golden paths aren’t complete until they deliver measurable value. Use these KPIs to assess performance and drive iteration:&lt;/p&gt;
&lt;h3 id="adoption-metrics"&gt;Adoption Metrics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Template usage rate&lt;/strong&gt;: Percentage of new projects using golden paths&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Component reuse&lt;/strong&gt;: Number of stacks consuming shared components&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time to first deployment&lt;/strong&gt;: Deployment time and frequency from code to production&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="quality-metrics"&gt;Quality Metrics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Security compliance rate&lt;/strong&gt;: Percentage of deployments passing security policies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stability&lt;/strong&gt;: Deployment incident frequency&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mean time to recovery (MTTR)&lt;/strong&gt;: Time to recover from production issues&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="developer-experience-metrics"&gt;Developer Experience Metrics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Developer satisfaction&lt;/strong&gt;: Survey teams about their platform experience&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support ticket volume&lt;/strong&gt;: Ticket volume related to infrastructure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contribution&lt;/strong&gt;: Number of PRs or issues submitted to platform templates&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="real-world-results-success-stories"&gt;Real-World Results: Success Stories&lt;/h2&gt;
&lt;p&gt;Organizations using golden paths report significant improvements in speed and reliability:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/case-studies/snowflake/"&gt;Snowflake&lt;/a&gt;&lt;/strong&gt; reduced deployment time from 1.5 weeks to less than a day&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/case-studies/mercedes-benz/"&gt;Mercedes-Benz&lt;/a&gt;&lt;/strong&gt; decreased infrastructure provisioning from weeks to minutes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/case-studies/starburst/"&gt;Starburst Data&lt;/a&gt;&lt;/strong&gt; cut deployment time from 2 weeks to 3 hours&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These results show that golden paths are not just developer tools, they&amp;rsquo;re a competitive advantage. To learn more, download the whitepaper: &lt;a href="https://info.pulumi.com/whitepaper-the-golden-path-to-cloud-success"&gt;The Golden Path to Cloud Success: Your IDP Roadmap&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="common-pitfalls-and-how-to-avoid-them"&gt;Common Pitfalls and How to Avoid Them&lt;/h2&gt;
&lt;h3 id="pitfall-1-over-abstraction"&gt;Pitfall 1: Over-Abstraction&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Creating components so abstract they&amp;rsquo;re unusable
&lt;strong&gt;Solution&lt;/strong&gt;: Start with concrete use cases, then generalize based on actual patterns&lt;/p&gt;
&lt;h3 id="pitfall-2-insufficient-escape-hatches"&gt;Pitfall 2: Insufficient Escape Hatches&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Golden paths become golden cages
&lt;strong&gt;Solution&lt;/strong&gt;: Always provide ways to extend or override default behavior&lt;/p&gt;
&lt;h3 id="pitfall-3-poor-versioning-strategy"&gt;Pitfall 3: Poor Versioning Strategy&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Breaking changes without migration paths
&lt;strong&gt;Solution&lt;/strong&gt;: Maintain backward compatibility and provide clear upgrade guides&lt;/p&gt;
&lt;h3 id="pitfall-4-lack-of-ownership"&gt;Pitfall 4: Lack of Ownership&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Templates become orphaned and outdated
&lt;strong&gt;Solution&lt;/strong&gt;: Assign clear ownership and establish maintenance schedules&lt;/p&gt;
&lt;h2 id="the-future-of-golden-paths-ai-and-beyond"&gt;The Future of Golden Paths: AI and Beyond&lt;/h2&gt;
&lt;p&gt;The future of golden paths is intelligent, cross-cloud, and fully integrated with modern workflows.&lt;/p&gt;
&lt;h3 id="ai-enhanced-templates"&gt;AI-Enhanced Templates&lt;/h3&gt;
&lt;p&gt;Imagine templates that adapt based on your application&amp;rsquo;s actual behavior, automatically tuning resources and configurations for optimal performance and cost.&lt;/p&gt;
&lt;h3 id="cross-cloud-portability"&gt;Cross-Cloud Portability&lt;/h3&gt;
&lt;p&gt;Components that abstract not just resources but entire cloud providers, enabling true multi-cloud golden paths.&lt;/p&gt;
&lt;h3 id="gitops-native-workflows"&gt;GitOps-Native Workflows&lt;/h3&gt;
&lt;p&gt;Templates that include not just infrastructure but complete GitOps pipelines, from code commit to production deployment.&lt;/p&gt;
&lt;h2 id="your-first-steps-to-golden-paths"&gt;Your First Steps to Golden Paths&lt;/h2&gt;
&lt;p&gt;Ready to get started? Here&amp;rsquo;s your action plan:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Audit Current Patterns&lt;/strong&gt;: Document the infrastructure patterns your teams use most frequently&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build one reusable component&lt;/strong&gt;: Pick your most common pattern and build a reusable component&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create Your First Template&lt;/strong&gt;: Build a complete golden path for one project type&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gather Feedback&lt;/strong&gt;: Deploy with a pilot team and iterate based on their experience&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale Gradually&lt;/strong&gt;: Expand your component library and template catalog based on demand&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Measure and Iterate&lt;/strong&gt;: Track adoption and continuously improve based on metrics&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="conclusion-from-fragmentation-to-flow"&gt;Conclusion: From Fragmentation to Flow&lt;/h2&gt;
&lt;p&gt;Golden paths aren&amp;rsquo;t about restricting creativity or enforcing rigid standards. They&amp;rsquo;re about &lt;strong&gt;removing friction&lt;/strong&gt; from the development process, &lt;strong&gt;encoding expertise&lt;/strong&gt; into reusable patterns, and &lt;strong&gt;empowering developers&lt;/strong&gt; to move at the speed of business.&lt;/p&gt;
&lt;p&gt;By building a library of components and templates, you transform your Internal Developer Platform from a collection of tools into a &lt;strong&gt;force multiplier&lt;/strong&gt; for your entire engineering organization. You give developers the gift of not having to solve solved problems, while maintaining the flexibility to innovate where it matters.&lt;/p&gt;
&lt;p&gt;Start small. Solve one problem well. Expand from there. With the right foundation, your developer platform will evolve into a system of self-service, speed, and stability.&lt;/p&gt;
&lt;h3 id="ready-to-build-your-golden-paths"&gt;Ready to Build Your Golden Paths?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Code examples&lt;/strong&gt;: &lt;a href="https://github.com/pulumi/workshops/tree/main/golden-paths-infrastructure-components-and-templates"&gt;Explore golden path examples on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build with Components&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;Pulumi Components documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable Self-Service&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/idp/"&gt;Pulumi IDP documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Join the Community&lt;/strong&gt;: Connect with platform engineers in our &lt;a href="https://slack.pulumi.com"&gt;Pulumi Slack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Next in our series: Policy as Code for Safer IDPs. You will learn how to add automated guardrails that make sure every deployment meets your security and compliance standards without slowing down development.&lt;/em&gt;&lt;/p&gt;</description><author>Engin Diri</author><author>Robert Smith</author><category>internal-developer-platform</category><category>platform-engineering</category><category>golden-paths</category><category>infrastructure-components</category><category>pulumi-templates</category><category>developer-experience</category><category>reusable-infrastructure</category></item><item><title>How to Build an Internal Developer Platform: Strategy, Best Practices, and Self-Service Infrastructure</title><link>https://www.pulumi.com/blog/idp-strategy-planning-self-service-infrastructure-that-balances-developer-autonomy-with-operational-control/</link><pubDate>Thu, 14 Aug 2025 05:13:02 +0200</pubDate><guid>https://www.pulumi.com/blog/idp-strategy-planning-self-service-infrastructure-that-balances-developer-autonomy-with-operational-control/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/idp-strategy-planning-self-service-infrastructure-that-balances-developer-autonomy-with-operational-control/index.png" /&gt;
&lt;p&gt;Welcome to the first post in our &lt;strong&gt;IDP Best Practices&lt;/strong&gt; series. In this guide, we’ll walk through the strategic foundations for designing an Internal Developer Platform that empowers developers without sacrificing governance, security, or operational control.&lt;/p&gt;
&lt;p&gt;At Pulumi, we’ve worked with hundreds of teams facing the same core challenge: &lt;strong&gt;How do you give developers the infrastructure access they need, while maintaining the governance and security your organization requires?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That tension is at the heart of every IDP conversation. Teams want to &lt;strong&gt;move faster and innovate&lt;/strong&gt;, but also need to stay compliant, control costs, and maintain operational stability.&lt;/p&gt;
&lt;p&gt;The good news? You can do both, with a clear strategy and the right approach. This series shares &lt;strong&gt;proven best practices&lt;/strong&gt; for designing, building, and scaling IDPs using Pulumi.&lt;/p&gt;
&lt;p&gt;These lessons come from real-world implementations across industries and company sizes—and are built to grow with you.&lt;/p&gt;
&lt;h2 id="understanding-the-platform-engineering-layers-in-your-internal-developer-platform"&gt;Understanding the Platform Engineering Layers in Your Internal Developer Platform&lt;/h2&gt;
&lt;p&gt;&lt;img src="internal-developer-platform-key-layers.png" alt="internal-developer-platform-key-layers.png"&gt;&lt;/p&gt;
&lt;p&gt;When we work with customers on their platform strategy, we often start by referring to the &amp;ldquo;platform engineering layer cake.&amp;rdquo;
Here is a quick walkthrough of each layer and how Pulumi IDP constructs fit this layer cake approach:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 1: Infrastructure Layer&lt;/strong&gt; - This is your raw cloud resources: VMs, databases, networks, storage.
These are the fundamental building blocks that exist in AWS, Azure, GCP, and other cloud providers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 2: Platform Layer&lt;/strong&gt; - This is where &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;Pulumi Components&lt;/a&gt; live.
Components take those raw infrastructure resources and package them into higher-level abstractions that encapsulate best practices, security policies, and organizational standards.
For example, instead of manually configuring 15 different AWS resources to create a secure web application, you create a component that handles all that complexity and exposes just the configuration options that matter to your developers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 3: Developer Experience Layer&lt;/strong&gt; - This is where &lt;a href="https://www.pulumi.com/templates/"&gt;Pulumi Templates&lt;/a&gt; and the &lt;a href="https://www.pulumi.com/docs/idp/get-started/private-registry/"&gt;Private Registry&lt;/a&gt; come into play.
Templates provide ready-to-deploy patterns that developers can customize, while the private registry makes everything discoverable and manageable at scale.&lt;/p&gt;
&lt;p&gt;In our workshop, we focused specifically on those top two layers because that&amp;rsquo;s where the transformation happens. This is where you turn raw infrastructure into something developers can actually use productively without becoming infrastructure experts themselves.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how this maps to what you&amp;rsquo;re actually building:&lt;/p&gt;
&lt;h3 id="infrastructure-layer--raw-cloud-resources"&gt;Infrastructure Layer → Raw Cloud Resources&lt;/h3&gt;
&lt;p&gt;Your foundation is still the same: AWS EC2 instances, Azure Virtual Networks, GCP Cloud Functions.
Pulumi&amp;rsquo;s providers give you access to these resources using real programming languages instead of YAML or proprietary DSLs.&lt;/p&gt;
&lt;h3 id="platform-layer--pulumi-components"&gt;Platform Layer → Pulumi Components&lt;/h3&gt;
&lt;p&gt;This is where you create your reusable building blocks. A component might encapsulate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A complete microservice infrastructure pattern (load balancer, auto-scaling group, database, monitoring)&lt;/li&gt;
&lt;li&gt;A secure data pipeline (storage, processing, access controls, encryption)&lt;/li&gt;
&lt;li&gt;A standardized Kubernetes application deployment (ingress, service, deployment, secrets management)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Components are written once in any supported language (TypeScript, Python, Go, .NET, Java) but can be consumed by teams using any of these languages.
This is crucial. Your platform team might write components in Go, but your application teams can consume them in Python or TypeScript.&lt;/p&gt;
&lt;h3 id="developer-experience-layer--templates--private-registry"&gt;Developer Experience Layer → Templates + Private Registry&lt;/h3&gt;
&lt;p&gt;Templates are complete, deployable projects that use your components. They provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Getting started patterns: &amp;ldquo;Deploy a new microservice&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Reference architectures: &amp;ldquo;Deploy a three-tier web application&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Environment patterns: &amp;ldquo;Set up a complete dev/staging/prod pipeline&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Private Registry is your distribution mechanism.
It&amp;rsquo;s where components and templates become discoverable, versioned, and manageable.
Developers don&amp;rsquo;t need to hunt through Git repositories or Slack channels to find the right building blocks. Everything is catalogued, documented, and accessible through familiar package management workflows.&lt;/p&gt;
&lt;h2 id="idp-example-building-a-web-application-platform-step-by-step"&gt;IDP Example: Building a Web Application Platform Step-by-Step&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s make this concrete with an example from our workshops.
Say you want to enable teams to deploy secure web applications:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Infrastructure Layer:&lt;/strong&gt; You need an Application Load Balancer, EC2 Auto Scaling Group, RDS database, VPC with proper subnets, Security Groups, IAM roles, CloudWatch monitoring, and S3 bucket for static assets.
That&amp;rsquo;s about 20+ individual AWS resources that need to be configured correctly and securely.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Platform Layer (Components):&lt;/strong&gt; You create a &lt;code&gt;WebApplication&lt;/code&gt; component that encapsulates all this complexity.
Your component exposes simple configuration options like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;instanceType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;t3.medium&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;minSize&lt;/span&gt;: &lt;span class="kt"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;maxSize&lt;/span&gt;: &lt;span class="kt"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;databaseSize&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;small&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;production&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Behind the scenes, your component handles all the security configurations, networking setup, monitoring, and best practices.
You publish this component to your private registry.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Developer Experience Layer (Templates):&lt;/strong&gt; You create templates like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;web-app-starter&lt;/code&gt;: A simple web application using your &lt;code&gt;WebApplication&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;&lt;code&gt;microservice-template&lt;/code&gt;: API service with database and monitoring&lt;/li&gt;
&lt;li&gt;&lt;code&gt;full-stack-template&lt;/code&gt;: Frontend, backend, and database in a complete environment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Developers can now run &lt;code&gt;pulumi new web-app-starter&lt;/code&gt; and get a production-ready, secure web application in minutes instead of weeks.
The template uses your component, which handles all the underlying infrastructure complexity.&lt;/p&gt;
&lt;p&gt;This layered approach solves the core challenge we see every platform team struggling with: how do you provide developers with the infrastructure they need without creating operational bottlenecks or compromising security standards.&lt;/p&gt;
&lt;h2 id="why-internal-developer-platforms-matter-in-2025-and-beyond"&gt;Why Internal Developer Platforms Matter in 2025 and Beyond&lt;/h2&gt;
&lt;p&gt;While DevOps brought us incredible advances in how we ship and maintain software, we&amp;rsquo;ve watched many organizations struggle with the unintended consequences: tool sprawl, Day 2 operational pain, and developers who are drowning in infrastructure complexity.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why platform teams have emerged.
You exist to solve these challenges by building tools and workflows that enable your internal customers (the developers) to provision infrastructure and deploy software without getting blocked.
But here&amp;rsquo;s the thing I&amp;rsquo;ve learned from working with hundreds of platform teams: success isn&amp;rsquo;t just about the tools you choose.
It&amp;rsquo;s about the strategy behind how you implement them.&lt;/p&gt;
&lt;h2 id="5-core-components-of-a-successful-internal-developer-platform"&gt;5 Core Components of a Successful Internal Developer Platform&lt;/h2&gt;
&lt;p&gt;Through years of working with platform teams and analyzing what separates successful IDPs from those that struggle to gain adoption, we&amp;rsquo;ve identified five essential components that every platform strategy needs.
These aren&amp;rsquo;t theoretical concepts. They&amp;rsquo;re battle-tested patterns that work across organizations of all sizes and industries.&lt;/p&gt;
&lt;h3 id="1-abstractions"&gt;1. Abstractions&lt;/h3&gt;
&lt;p&gt;Let me be clear about something: abstractions aren&amp;rsquo;t about dumbing down infrastructure for developers.
The abstraction is really where you&amp;rsquo;re hiding the complexity of the underlying infrastructure from your end users, but you&amp;rsquo;re doing it intentionally to provide appropriate interfaces for different personas in your organization.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve seen too many platform teams get this wrong by either over-abstracting (creating black boxes that developers can&amp;rsquo;t customize) or under-abstracting (exposing too much complexity).
The sweet spot is creating &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;component resources&lt;/a&gt; that encapsulate your infrastructure patterns and best practices into reusable building blocks that can be consumed across different programming languages and deployment scenarios, while still providing escape hatches when needed.&lt;/p&gt;
&lt;h3 id="2-blueprints"&gt;2. Blueprints&lt;/h3&gt;
&lt;p&gt;Blueprints are your templatized, well-architected patterns that developers can use to bootstrap their infrastructure.
But here&amp;rsquo;s what I want you to understand about blueprints: they&amp;rsquo;re not just starting points that you throw over the wall to developers.
They&amp;rsquo;re carefully designed patterns that embody your organizational best practices and architectural decisions.&lt;/p&gt;
&lt;p&gt;When we see successful platform teams, their templates serve as both accelerators and guardrails.
They give developers a fast path to production-ready infrastructure while ensuring that everything they deploy follows your organization&amp;rsquo;s standards.
That&amp;rsquo;s the power of good blueprint design: speed and compliance working together, not against each other.&lt;/p&gt;
&lt;h3 id="3-workflows"&gt;3. Workflows&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s where many platform teams get trapped: they try to build one workflow to rule them all.
But in our experience working with organizations across every industry, you need to support multiple consumption patterns because you have multiple types of users.
You need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No-code workflows&lt;/strong&gt; for users who want point-and-click deployment (think product managers or junior developers who just need to spin up a database)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low-code workflows&lt;/strong&gt; using tools like &lt;a href="https://www.pulumi.com/docs/iac/languages-sdks/yaml/"&gt;Pulumi YAML&lt;/a&gt; for configuration-driven infrastructure (perfect for developers who understand infrastructure but don&amp;rsquo;t want to write Go or TypeScript)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full-code workflows&lt;/strong&gt; for developers who need maximum flexibility and want to leverage the full power of general-purpose programming languages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key insight? These aren&amp;rsquo;t three different platforms.
They&amp;rsquo;re three different interfaces to the same underlying components and templates.&lt;/p&gt;
&lt;h3 id="4-security-guardrails"&gt;4. Security guardrails&lt;/h3&gt;
&lt;p&gt;This is probably the most important distinction we can share with you: you want to have guardrails, not gates.
Too many platform teams create approval processes and manual checkpoints that completely undermine the self-service promise they&amp;rsquo;re trying to deliver.&lt;/p&gt;
&lt;p&gt;Guardrails are different.
They start with the best practices and security built into the reusable abstractions. But even the most secure solutions need a safety net.
This safety net is policy-as-code that runs automatically, preventing violations before deployment happens.
When we work with customers on implementing &lt;a href="https://www.pulumi.com/crossguard/"&gt;Pulumi CrossGuard&lt;/a&gt;, we&amp;rsquo;re not creating new friction. We&amp;rsquo;re embedding security, compliance, and cost controls directly into the deployment process.
The developer gets immediate feedback, and you get the assurance that nothing goes to production without meeting your standards.&lt;/p&gt;
&lt;h3 id="5-self-service"&gt;5. Self-service&lt;/h3&gt;
&lt;p&gt;Everything we&amp;rsquo;ve talked about so far builds toward this moment: enabling developers to provision and manage infrastructure independently.
But self-service isn&amp;rsquo;t just about providing a UI. It&amp;rsquo;s about carefully orchestrating all the other components to create experiences that are both powerful and intuitive.&lt;/p&gt;
&lt;p&gt;When we walked through the demo in our workshop, what you saw was the culmination of thoughtful platform design.
Developers can discover available services, deploy infrastructure through whatever interface makes sense for them, and manage their resources over time, all without requiring tickets or manual intervention from platform teams.
That&amp;rsquo;s the promise of a well-designed IDP: developer autonomy without operational chaos.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Put your IDP strategy into practice&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Build reusable components, golden paths, and self-service workflows on Pulumi, and give developers autonomy while you keep governance and costs in check.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="how-to-implement-your-idp-strategy"&gt;How to Implement Your IDP Strategy&lt;/h2&gt;
&lt;h3 id="supporting-different-personas-in-your-internal-developer-platform-design"&gt;Supporting Different Personas in Your Internal Developer Platform Design&lt;/h3&gt;
&lt;p&gt;One of the biggest mistakes we see platform teams make: they try to build for their most sophisticated users first.
But here&amp;rsquo;s what I&amp;rsquo;ve learned from working with hundreds of organizations: you need to think about all your personas from day one.&lt;/p&gt;
&lt;p&gt;In most organizations, you&amp;rsquo;re serving:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure engineers&lt;/strong&gt; who want full control and flexibility (they&amp;rsquo;ll use the full-code workflows)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application developers&lt;/strong&gt; who need infrastructure but prefer higher-level abstractions (perfect for low-code approaches)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Non-technical users&lt;/strong&gt; who want simple, point-and-click deployment (your no-code users)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The breakthrough insight that separates successful platform teams from struggling ones is this: all these personas can be served by the same underlying components and templates, just consumed through different interfaces.
You don&amp;rsquo;t need to build three different platforms—you need to build one platform with three different consumption models.&lt;/p&gt;
&lt;h3 id="why-a-private-registry-is-key-to-idp-adoption"&gt;Why a Private Registry Is Key to IDP Adoption&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s something we always tell platform teams: if you don&amp;rsquo;t solve the discoverability problem, your beautiful components and templates will sit unused in Git repositories where no one can find them.
That&amp;rsquo;s why the private registry isn&amp;rsquo;t just a nice-to-have. It&amp;rsquo;s the foundation that makes everything else work.&lt;/p&gt;
&lt;p&gt;When you establish a private registry as your source of truth for components, templates, providers, and policies, you&amp;rsquo;re solving two critical problems at once.
First, discoverability: developers can actually find and explore what&amp;rsquo;s available.
Second, lifecycle management: you can see where each package is being used, track version drift, and understand the impact of changes before you make them.&lt;/p&gt;
&lt;p&gt;The workflow is beautifully simple: you publish standardized building blocks with a single &lt;code&gt;pulumi publish&lt;/code&gt; command, and developers discover and consume these assets through familiar package management workflows they already know.&lt;/p&gt;
&lt;h3 id="aligning-your-idp-to-organizational-context-and-services"&gt;Aligning Your IDP to Organizational Context and Services&lt;/h3&gt;
&lt;p&gt;One pattern we see in every successful IDP implementation is that the platform reflects how the organization actually works.
Your developers don&amp;rsquo;t think in terms of individual stacks or resources. They think in terms of services, applications, and business functionality.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why we built &lt;a href="https://www.pulumi.com/docs/idp/get-started/services/"&gt;Pulumi Services&lt;/a&gt; - to let teams logically group stacks and ESC environments in ways that make sense to your organization.
Pulumi Services improve organization by helping your team model infrastructure in a way that&amp;rsquo;s familiar - simplifying Day 2 operations by providing additional context like links to relevant dashboards, Slack channels and more.
When something breaks at 2 AM, your on-call engineer needs to understand dependencies, track usage, and manage infrastructure in the context of the business services that are actually impacted.&lt;/p&gt;
&lt;h2 id="how-to-measure-the-success-of-your-internal-developer-platform"&gt;How to Measure the Success of Your Internal Developer Platform&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s something that might surprise you: the most successful platform teams we work with don&amp;rsquo;t measure their success by how many cool features they&amp;rsquo;ve built.
They measure success by the business outcomes they&amp;rsquo;re driving:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reduced time-to-market&lt;/strong&gt; through faster infrastructure provisioning (because at the end of the day, your platform exists to help the business move faster)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved developer productivity&lt;/strong&gt; by eliminating infrastructure bottlenecks (happy developers ship more features)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced security posture&lt;/strong&gt; through consistent policy enforcement (security that doesn&amp;rsquo;t slow people down is security that actually gets used)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lower operational overhead&lt;/strong&gt; through standardization and automation (because your platform team&amp;rsquo;s time is better spent on innovation than toil)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The numbers speak for themselves.
We&amp;rsquo;ve worked with customers like Snowflake who reduced deployment times from one and a half weeks to less than a day.
Starburst Data cut their infrastructure deployments from two weeks to just three hours.
These aren&amp;rsquo;t vanity metrics. They&amp;rsquo;re business transformations.&lt;/p&gt;
&lt;h2 id="idp-strategy-5-key-steps-to-build-a-strong-foundation"&gt;IDP Strategy: 5 Key Steps to Build a Strong Foundation&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re just starting your IDP journey, here&amp;rsquo;s the roadmap we give to every platform team we work with:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Start with user research:&lt;/strong&gt; Before you write a single line of code, go talk to your developers.
Understand your different personas and their actual needs, not what you think they need. Do your users like to work from the command line? Do they prefer interacting with a UI?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Identify common patterns:&lt;/strong&gt; Look for infrastructure patterns that get repeated across teams.
These are your goldmine—the patterns that, once abstracted and templatized, will provide immediate value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Begin with components:&lt;/strong&gt; Build reusable infrastructure building blocks before you worry about fancy UIs or workflow orchestration.
You need solid foundations before you can build the house.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implement progressive disclosure:&lt;/strong&gt; Give people simple interfaces for common use cases, but always provide escape hatches for complex scenarios.
The moment your abstraction becomes a prison, developers will route around it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Measure and iterate:&lt;/strong&gt; Track adoption and gather feedback religiously.
Your platform is only as good as its adoption rate, and adoption only happens when you&amp;rsquo;re solving real problems for real people.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="the-future-of-idps-and-platform-engineering"&gt;The Future of IDPs and Platform Engineering&lt;/h2&gt;
&lt;p&gt;Trends come and go, but platform engineering is here to stay.
It&amp;rsquo;s not just another tool or methodology. This is how modern organizations scale infrastructure to match the speed of innovation. The companies that win are the ones that treat their &lt;strong&gt;Internal Developer Platform (IDP)&lt;/strong&gt; as a strategic foundation, not just a tool.&lt;/p&gt;
&lt;p&gt;Your job isn’t just to manage infrastructure and choose the right tools - it&amp;rsquo;s to enable developers to move faster while keeping governance, security, and costs under control. Get that balance right, and your platform becomes a force multiplier across your entire engineering department.&lt;/p&gt;
&lt;p&gt;The fastest way to get there? Focus on these five essential components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Abstractions&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blueprints&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Workflows&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security guardrails&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Self-service&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together, they turn your IDP into more than just infrastructure automation, they create a platform that developers trust and your business relies on.&lt;/p&gt;
&lt;h3 id="ready-to-build-a-successful-idp-that-scales"&gt;Ready to Build a Successful IDP that Scales?&lt;/h3&gt;
&lt;p&gt;Pulumi makes it easy to go from static IaC to dynamic, self-service infrastructure with real programming languages and built-in guardrails.&lt;/p&gt;
&lt;p&gt;Explore &lt;a href="https://www.pulumi.com/product/internal-developer-platforms/"&gt;Pulumi IDP&lt;/a&gt; or &lt;a href="https://app.pulumi.com/signup"&gt;sign up for free&lt;/a&gt; to get started today.&lt;/p&gt;</description><author>Mitch Gerdisch</author><author>Engin Diri</author><category>internal-developer-platform</category><category>platform-engineering</category><category>developer-experience</category><category>self-service</category><category>governance</category><category>components</category><category>templates</category></item><item><title>Backstage vs Pulumi IDP: Why Infrastructure-First Wins!</title><link>https://www.pulumi.com/blog/backstage-vs-pulumi-idp-why-infrastructure-first-platform-engineering-matters/</link><pubDate>Wed, 13 Aug 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/backstage-vs-pulumi-idp-why-infrastructure-first-platform-engineering-matters/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/backstage-vs-pulumi-idp-why-infrastructure-first-platform-engineering-matters/index.png" /&gt;
&lt;p&gt;Developers are losing days every month to infrastructure bottlenecks, compliance hurdles, and inconsistent environments.
Platform engineering promised to fix that, yet &lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices"&gt;too many platforms fail&lt;/a&gt; before they deliver real impact.&lt;/p&gt;
&lt;p&gt;In this comparison of &lt;strong&gt;Backstage vs Pulumi IDP&lt;/strong&gt;, we&amp;rsquo;ll explore why choosing the right architectural approach matters more than the tool itself.&lt;/p&gt;
&lt;h2 id="quick-comparison-backstage-vs-pulumi-idp"&gt;Quick comparison: Backstage vs Pulumi IDP&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Backstage&lt;/strong&gt; is an open-source developer portal framework from Spotify that focuses on service catalogs and documentation. It requires significant setup time (12-18 months) and ongoing maintenance (3-5 FTEs).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pulumi IDP&lt;/strong&gt; is an infrastructure-first internal developer platform that embeds governance, cost control, and security from day one. It can be deployed in hours with minimal ongoing maintenance.&lt;/p&gt;
&lt;p&gt;The problem isn&amp;rsquo;t whether you choose Backstage or Pulumi IDP.
The real question is: &lt;strong&gt;Will your platform treat infrastructure as a first-class concern, or as an afterthought?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;According to Gartner, &lt;strong&gt;80% of large enterprises will deploy &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-platforms"&gt;internal developer platforms&lt;/a&gt; within the next two years&lt;/strong&gt;.
But without a strong &lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code"&gt;infrastructure foundation&lt;/a&gt;, those platforms risk becoming expensive, hard-to-maintain bottlenecks instead of accelerators.&lt;/p&gt;
&lt;h2 id="why-platform-engineering-efforts-fail-common-mistakes"&gt;Why platform engineering efforts fail: Common mistakes&lt;/h2&gt;
&lt;p&gt;Platform teams consistently make four critical mistakes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Neglecting Infrastructure Foundations&lt;/strong&gt;&lt;br&gt;
Over-focusing on the developer portal experience while letting infrastructure governance and scalability lag behind.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ignoring Cost Efficiency&lt;/strong&gt;&lt;br&gt;
Prioritizing productivity at the expense of &lt;a href="https://www.pulumi.com/blog/finops-with-pulumi"&gt;cloud cost management&lt;/a&gt;.&lt;br&gt;
Example: One company considered giving every developer their own cluster, a scaling nightmare both technically and financially.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Treating Security &amp;amp; Governance as Add-Ons&lt;/strong&gt;&lt;br&gt;
Bolting on compliance after launch leads to constant firefighting and &lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health"&gt;security debt&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Building for Yesterday&amp;rsquo;s Architecture&lt;/strong&gt;&lt;br&gt;
Designing general-purpose platforms that can&amp;rsquo;t keep up with &lt;a href="https://www.pulumi.com/docs/iac/clouds/kubernetes"&gt;Kubernetes-native workloads&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="portal-first-vs-infrastructure-first-platform-engineering"&gt;Portal-first vs infrastructure-first platform engineering&lt;/h2&gt;
&lt;p&gt;There are two dominant approaches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Portal-First&lt;/strong&gt; typified by Backstage, which starts with developer experience and service catalogs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure-First&lt;/strong&gt; exemplified by Pulumi IDP, which builds the platform foundation around scalable, policy-driven infrastructure.&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform Engineering Feature&lt;/th&gt;
&lt;th&gt;Backstage (Portal-First)&lt;/th&gt;
&lt;th&gt;Pulumi IDP (Infrastructure-First)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Focus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Developer portal &amp;amp; catalog&lt;/td&gt;
&lt;td&gt;Scalable, policy-driven infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup Time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12-18 months&lt;/td&gt;
&lt;td&gt;Hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maintenance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3-5 FTE ongoing&lt;/td&gt;
&lt;td&gt;Minimal ongoing overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infra Provisioning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Requires separate tooling&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost Awareness&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Depends on infra layer&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security &amp;amp; Governance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add-on&lt;/td&gt;
&lt;td&gt;Built-in from day one&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="backstage-the-portal-first-platform-engineering-approach"&gt;Backstage: The portal-first platform engineering approach&lt;/h2&gt;
&lt;p&gt;Backstage is an open-source framework for building developer portals.
Originally built by Spotify, it excels at unifying tools, services, and documentation.&lt;/p&gt;
&lt;h3 id="strengths"&gt;Strengths&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mature Ecosystem&lt;/strong&gt; with over 1,200 integrations and a large community.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Excellent Service Catalog&lt;/strong&gt; providing centralized metadata, ownership, and discovery.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docs-as-Code&lt;/strong&gt; that keeps documentation close to the codebase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Self-Service Templates&lt;/strong&gt; that standardize &lt;a href="https://www.pulumi.com/templates"&gt;scaffolding for new projects&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="challenges"&gt;Challenges&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;High Maintenance Overhead&lt;/strong&gt; requiring 3-5 FTEs just to keep it running in large orgs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Complex Setup&lt;/strong&gt; with Yarn version headaches, TypeScript complexity, plugin upkeep.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infra as an Afterthought&lt;/strong&gt; that lacks built-in provisioning, often pushing infra concerns down the road.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hidden Costs&lt;/strong&gt; resulting in multi-million dollar TCO over three years for a 300-dev team when factoring in staffing and infra complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pulumi-idp-the-infrastructure-first-platform-engineering-approach"&gt;Pulumi IDP: the infrastructure-first platform engineering approach&lt;/h2&gt;
&lt;p&gt;Pulumi IDP brings &lt;strong&gt;&lt;a href="https://www.pulumi.com/what-is/what-is-platform-engineering"&gt;Infrastructure Platform Engineering&lt;/a&gt; (IPE)&lt;/strong&gt; to the forefront by embedding scalable, secure, cost-aware infrastructure into the platform from day one.&lt;/p&gt;
&lt;h3 id="strengths-1"&gt;Strengths&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure as a First-Class Concern&lt;/strong&gt; with built-in multitenancy, isolation, and &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard"&gt;governance&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Efficiency &amp;amp; Cost Awareness&lt;/strong&gt; through &lt;a href="https://www.pulumi.com/templates"&gt;golden paths&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/iac/concepts/components"&gt;reusable components&lt;/a&gt; optimized from the start.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Policy-Driven by Design&lt;/strong&gt; that enforces security, compliance, and cost &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/get-started"&gt;policies&lt;/a&gt; automatically.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud-Native Ready&lt;/strong&gt; ideal for ephemeral workloads, Kubernetes, and multi-cloud.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="considerations"&gt;Considerations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Newer Platform&lt;/strong&gt; with a smaller plugin ecosystem than Backstage&amp;rsquo;s.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infra-Heavy Focus&lt;/strong&gt; that&amp;rsquo;s best fit for infra-intensive orgs; overpowered if you only need a catalog and docs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="real-world-platform-engineering-outcomes-backstage-vs-pulumi-idp"&gt;Real-world platform engineering outcomes: Backstage vs Pulumi IDP&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Pulumi IDP Adoption&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/events/from-infrastructure-engineering-to-platform-engineering"&gt;CLEAR leveraged Pulumi IDP&amp;rsquo;s prebuilt capabilities&lt;/a&gt; instead of building infra automation from scratch, speeding up delivery while keeping governance tight.&lt;/p&gt;
&lt;h2 id="backstage-vs-pulumi-idp-decision-guide"&gt;Backstage vs Pulumi IDP decision guide&lt;/h2&gt;
&lt;h3 id="when-to-choose-backstage"&gt;When to choose Backstage&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Backstage for platform engineering if you:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have a dedicated platform team with strong React/TypeScript skills&lt;/li&gt;
&lt;li&gt;Primarily need service cataloging and documentation&lt;/li&gt;
&lt;li&gt;Already have robust infrastructure provisioning and governance tools&lt;/li&gt;
&lt;li&gt;Have 18+ months and budget for ongoing maintenance (3-5 FTEs)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="when-to-choose-pulumi-idp"&gt;When to choose Pulumi IDP&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Pulumi IDP for platform engineering if you:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Need &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard"&gt;infrastructure governance&lt;/a&gt; from day one&lt;/li&gt;
&lt;li&gt;Want &lt;a href="https://www.pulumi.com/blog/finops-with-pulumi"&gt;cost management&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/get-started"&gt;policy automation&lt;/a&gt; built in&lt;/li&gt;
&lt;li&gt;Must scale efficiently across &lt;a href="https://www.pulumi.com/docs/iac/clouds/kubernetes"&gt;Kubernetes&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/iac/concepts/how-pulumi-works"&gt;multi-cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Prefer to avoid building everything from scratch&lt;/li&gt;
&lt;li&gt;Need to deploy quickly (hours vs months)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Build your platform on infrastructure&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Pulumi IDP embeds governance, cost control, and security into your platform from day one, giving your teams self-service golden paths with policy enforced automatically.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/product/internal-developer-platforms/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="the-shift-to-infrastructure-platform-engineering-ipe"&gt;The shift to infrastructure platform engineering (IPE)&lt;/h2&gt;
&lt;p&gt;Platform engineering isn&amp;rsquo;t failing because the idea is flawed. It&amp;rsquo;s failing because too many efforts start with the portal and leave infrastructure for later.&lt;/p&gt;
&lt;p&gt;Infrastructure Platform Engineering flips that model, ensuring the platform&amp;rsquo;s foundation is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-4"&gt;Scalable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-7"&gt;Governed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/finops-with-pulumi"&gt;Cost-efficient&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering"&gt;Secure&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hybrid approaches are also possible. Pulumi offers a &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-platforms"&gt;Backstage plugin&lt;/a&gt; so teams can pair Backstage&amp;rsquo;s portal features with Pulumi IDP&amp;rsquo;s infrastructure power.&lt;/p&gt;
&lt;h2 id="bottom-line-infrastructure-first-wins-for-platform-engineering"&gt;Bottom line: infrastructure-first wins for platform engineering&lt;/h2&gt;
&lt;p&gt;If your platform is slow, costly, or hard to govern, it&amp;rsquo;s not a developer problem. It&amp;rsquo;s an infrastructure problem.
Treating infrastructure as a first-class concern from day one isn&amp;rsquo;t optional.
It&amp;rsquo;s the difference between a platform that scales and one that stalls.&lt;/p&gt;
&lt;h2 id="frequently-asked-questions"&gt;Frequently asked questions&lt;/h2&gt;
&lt;h3 id="what-is-the-main-difference-between-backstage-and-pulumi-idp"&gt;What is the main difference between Backstage and Pulumi IDP?&lt;/h3&gt;
&lt;p&gt;Backstage is a portal-first developer platform that focuses on service catalogs and documentation, requiring separate tools for infrastructure provisioning. Pulumi IDP is an infrastructure-first platform that embeds governance, cost control, and infrastructure automation from the start.&lt;/p&gt;
&lt;h3 id="how-long-does-it-take-to-implement-backstage-vs-pulumi-idp"&gt;How long does it take to implement Backstage vs Pulumi IDP?&lt;/h3&gt;
&lt;p&gt;Backstage typically requires 12-18 months for full implementation with ongoing maintenance by 3-5 FTEs. Pulumi IDP can be deployed in hours with minimal ongoing maintenance overhead.&lt;/p&gt;
&lt;h3 id="can-i-use-backstage-and-pulumi-idp-together"&gt;Can I use Backstage and Pulumi IDP together?&lt;/h3&gt;
&lt;p&gt;Yes, Pulumi offers a &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-platforms"&gt;Backstage plugin&lt;/a&gt; that allows teams to combine Backstage&amp;rsquo;s portal features with Pulumi IDP&amp;rsquo;s infrastructure capabilities for a hybrid approach.&lt;/p&gt;
&lt;h3 id="what-are-the-costs-of-running-backstage-vs-pulumi-idp"&gt;What are the costs of running Backstage vs Pulumi IDP?&lt;/h3&gt;
&lt;p&gt;Backstage&amp;rsquo;s TCO for a 300-developer team can reach multiple millions over three years when factoring in staffing and infrastructure complexity. Pulumi IDP has lower operational costs due to built-in automation and minimal maintenance requirements.&lt;/p&gt;
&lt;h3 id="which-platform-is-better-for-kubernetes-environments"&gt;Which platform is better for Kubernetes environments?&lt;/h3&gt;
&lt;p&gt;Pulumi IDP is purpose-built for cloud-native and Kubernetes environments with built-in support for ephemeral workloads and multi-cloud deployments. Backstage requires additional tooling for Kubernetes infrastructure management.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/product/internal-developer-platforms"&gt;Learn more about Pulumi IDP&lt;/a&gt; and how infrastructure-first platform engineering avoids &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-7"&gt;common failure patterns&lt;/a&gt;.&lt;/p&gt;</description><author>Engin Diri</author><category>platform-engineering</category><category>backstage</category><category>pulumi-idp</category><category>infrastructure-as-code</category><category>devops</category><category>governance</category><category>internal-developer-platform</category></item><item><title>Governance as an Enabler: Scaling Safely and Confidently</title><link>https://www.pulumi.com/blog/platform-engineering-pillars-7/</link><pubDate>Tue, 17 Jun 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/platform-engineering-pillars-7/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/platform-engineering-pillars-7/index.png" /&gt;
&lt;p&gt;In previous articles in this series, we&amp;rsquo;ve explored how &lt;a href="https://www.pulumi.com/blog/series/platform-engineering-pillars/"&gt;platform engineering&lt;/a&gt; transforms infrastructure chaos into consistent provisioning, empowers engineering teams through self-service infrastructure, optimizes workflows, embeds security directly into your platform, and provides observability as a superpower. Each pillar builds upon the previous ones, creating a cohesive foundation that accelerates innovation and productivity.&lt;/p&gt;
&lt;p&gt;But as your platform scales, new challenges inevitably emerge. You&amp;rsquo;ve empowered engineering teams with self-service infrastructure, streamlined workflows, and embedded security directly into your platform. But as your platform scales, new challenges emerge: How do you ensure consistency, compliance, and cost control without slowing your teams down?&lt;/p&gt;
&lt;p&gt;In this article, we&amp;rsquo;ll explore how Platform Engineering transforms governance from a manual, bureaucratic process into an automated, built-in enabler, helping your organization scale safely and confidently. By embedding governance directly into your platform, you can maintain control, ensure compliance, and manage costs effectively, all while preserving the autonomy and speed your engineering teams have come to expect.&lt;/p&gt;
&lt;h2 id="the-problem-governance-as-a-manual-bottleneck"&gt;The Problem: Governance as a Manual Bottleneck&lt;/h2&gt;
&lt;span style="width: 225px; float: right; margin-left: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="frustrated.png" width="200px" alt="frustrated expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Dealing with manual compliance checks and red tape&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;With increased team autonomy and self-service capabilities, how do you ensure consistency, compliance, and cost control across your entire organization?&lt;/p&gt;
&lt;p&gt;Governance often feels like a necessary evil: manual, bureaucratic, and slow. Application teams see it as red tape, while operations teams struggle to maintain control. Manual compliance checks, lengthy audits, and unclear or inconsistent policies create friction and frustration. Teams may bypass governance processes entirely, leading to shadow IT, inconsistent resource configurations, and hidden risks.&lt;/p&gt;
&lt;p&gt;The consequences of manual, bureaucratic governance are clear:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Increased compliance risks and audit failures:&lt;/strong&gt; Without automated enforcement, compliance becomes reactive and error-prone, increasing the likelihood of regulatory violations and audit findings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unpredictable cloud costs and budget overruns:&lt;/strong&gt; Without clear guardrails, self-service infrastructure can lead to resource sprawl, wasted resources, and unexpected cloud bills.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced team autonomy and slower innovation:&lt;/strong&gt; Manual governance processes reintroduce bottlenecks, slowing down deployments and undermining the agility your platform was designed to achieve.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-solution-embedding-governance-into-your-platform"&gt;The Solution: Embedding Governance into Your Platform&lt;/h2&gt;
&lt;span style="width: 225px; float: left; margin-right: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="satisfied.png" width="200px" alt="satisfied expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Successfully scaling safely with embedded governance&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;Governance should live inside your platform, not off to the side as a separate process. To make that happen, build these four capabilities into your IDP:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Policy-as-Code for Automated Compliance:&lt;/strong&gt; Declare rules (like approved regions or required tags) as code. The platform enforces them whenever infrastructure is created or updated, so compliance happens automatically.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Platform-Level RBAC for Permission Boundaries:&lt;/strong&gt; Decide who can act on projects, stacks, and templates before any cloud credentials run. This early check prevents unauthorized requests from ever reaching cloud provider.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Audit Logs and Drift Detection for Real-Time Visibility:&lt;/strong&gt; Record every deployment, who ran it, and what changed. Continuously compare live infrastructure to the desired state in code. If someone bypasses approved processes, the platform flags it and alerts the team.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Resource Lifecycle and Deployment Controls:&lt;/strong&gt; Automatically retire idle environments after a set time (Resource TTLs) so forgotten test clusters don’t rack up bills. Also if needed, gate production changes behind lightweight approval workflows. Routine dev or staging updates roll out instantly, but high impact production changes wait until a reviewer signs off.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s dive into each of these.&lt;/p&gt;
&lt;h3 id="a-policy-as-code-for-compliance-and-operational-standards-automating-trust-and-consistency"&gt;A. Policy-as-Code for Compliance and Operational Standards: Automating Trust and Consistency&lt;/h3&gt;
&lt;p&gt;An engineering team is ready to launch a new service. They’ve tested it and everything looks good, until the deployment fails. Not because of a bug. Because it’s targeting an unapproved cloud region.&lt;/p&gt;
&lt;p&gt;Now they’re stuck. A compliance review kicks off. Slack threads fly. A ticket gets filed. What should’ve been a smooth release turns into a delay, all because of a policy someone missed.&lt;/p&gt;
&lt;p&gt;Policy-as-code prevents this.&lt;/p&gt;
&lt;p&gt;When teams deploy something that breaks the rules (like using an unapproved region), the platform blocks it automatically. The error shows up right away, with a clear message. Nothing gets provisioned, and nobody has to file a ticket.&lt;/p&gt;
&lt;p&gt;If you’re already using intent-based components (“I need a Java service with Kafka and PostgreSQL”), most details are handled for you: tags, regions, naming. But people still override things. That’s why policy-as-code matters.&lt;/p&gt;
&lt;p&gt;Think of it as a safety net. A menu of components handle the defaults. Policies catch anything that slips through. Together, they keep your platform consistent without slowing anyone down.&lt;/p&gt;
&lt;h3 id="b-role-based-access-control-rbac-balancing-autonomy-and-control"&gt;B. Role-Based Access Control (RBAC): Balancing Autonomy and Control&lt;/h3&gt;
&lt;span style="width: 225px; float: right; margin-left: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="blocked.png" width="200px" alt="blocked expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Stopped by lengthy approval processes&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;As your platform grows, managing permissions manually gets messy. If an engineer needs to fix a production issue but doesn’t have access, they file a ticket and wait, sometimes for days. Give developers too many rights, and they might change production by accident. Both options slow teams down and increase risk.&lt;/p&gt;
&lt;p&gt;The fix is an RBAC model built into your platform. First, the platform decides who can deploy, who can publish components, and who can manage templates. This check runs before any cloud credentials are used, so invalid requests get blocked early. Second, the cloud IAM layer controls which API calls are allowed, like creating an EC2 instance or updating a database.&lt;/p&gt;
&lt;p&gt;This pairs well with a two-level intent-based approach. Teams describe what they need (“I want a Python Lambda with an SQS queue”), and the platform enforces access only for users with the right scopes. Everyone gets just enough access to do their job, no more, no less.&lt;/p&gt;
&lt;p&gt;A Platform with RBAC makes permissions clear, reduces mistakes, and keeps everything auditable. Devs move fast, spinning up resources as needed, while strong guardrails stay in place. The result is a scalable, least-privilege model that balances autonomy and control, so your organization can grow safely.&lt;/p&gt;
&lt;h3 id="c-auditability-traceability-and-drift-detection-ensuring-visibility-and-trust"&gt;C. Auditability, Traceability, and Drift Detection: Ensuring Visibility and Trust&lt;/h3&gt;
&lt;span style="width: 225px; float: left; margin-right: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="stressed.png" width="200px" alt="stressed expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Anxious about audit failures and compliance risks&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;An ops engineer spots a production database misbehaving. A quick check shows someone changed its configuration outside the approved workflow. Without an audit trail or drift detection, the team scrambles to figure out who made the change and when. Meanwhile, the incorrect setting stays active, posing a security and compliance risk. No one can fix it without guessing.&lt;/p&gt;
&lt;p&gt;A platform with audit logs records every action: who deployed, when, and what changed. Drift detection watches live infrastructure and compares it to the desired state in code. If someone bypasses the workflow (say, editing a database setting in the console), the platform flags it and alerts:
“User Alice changed max_connections on prod-db-01 at 3:42 PM, which no longer matches the expected state.”
Now the team can pinpoint the change, talk to the right person, and revert or update the code, restoring consistency in minutes, not hours.&lt;/p&gt;
&lt;p&gt;Together, audit logs and drift detection give you real-time visibility into every change. You stop playing detective. You see who did what, when, and how it deviated from code, all in one place. That transparency speeds audits, catches unauthorized changes fast, and builds trust across teams. With automatic traces of every change, your platform scales without surprises.&lt;/p&gt;
&lt;h3 id="d-resource-lifecycle-and-deployment-controls-scaling-responsibly-and-safely"&gt;D. Resource Lifecycle and Deployment Controls: Scaling Responsibly and Safely&lt;/h3&gt;
&lt;p&gt;An engineer spins up a test environment, then walks away. Another pushes a change straight to production without review. The abandoned test cluster runs up cloud costs; the unreviewed prod tweak risks an outage. Without automation, both lead to wasted spend and stressful cleanups.&lt;/p&gt;
&lt;p&gt;A modern platform handles this with &lt;strong&gt;ephemeral environments where possible&lt;/strong&gt; and &lt;strong&gt;approval gates where it matters&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In dev and staging, engineers can move quickly. They can create test or preview environments, often tied to users or pull requests, that shut down automatically after a set time. TTL rules keep things tidy without manual cleanup.&lt;/p&gt;
&lt;p&gt;Production, by contrast, is gated. High-impact changes, like modifying a database schema or adjusting a load balancer, require approval. Before anything is provisioned, sign-off is required. Every approval (or denial) is logged: who, when, and why.&lt;/p&gt;
&lt;p&gt;This setup keeps development fast and flexible, while making production changes deliberate and auditable. Your platform stays clean, cost-effective, and safe without getting in the way.&lt;/p&gt;
&lt;span style="width: 225px; float: right; margin-left: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="overwhelmed.png" width="200px" alt="overwhelmed expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Drowning in resource sprawl and unexpected costs&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;h2 id="real-world-example-governance-enablement-in-action"&gt;Real-World Example: Governance Enablement in Action&lt;/h2&gt;
&lt;p&gt;An engineering team opens a pull request for a new customer-facing service. The platform spins up a preview environment using a template with secure defaults, pre-approved modules, and policy checks. CI runs tests and policy checks in preview (names, regions, encryption, compliance) so the team catches issues early. If a rule fails (say, an unencrypted database), the PR fails before it reaches main. After the PR merges to main, it deploys to production, confident all policy validations have passed.&lt;/p&gt;
&lt;p&gt;Idle QA environments shut down after 48 hours, so forgotten clusters don’t rack up bills. Sensitive production changes, like updating a load balancer or altering a critical schema, are carefully reviewed via pull request. Once approved, the platform deploys automatically and logs every action. Drift detection flags console edits, letting the team revert or update code in minutes.&lt;/p&gt;
&lt;p&gt;Result: Governance becomes an invisible safety net. Engineers move fast, knowing policy-as-code, RBAC, TTL cleanup, approval gates, and change tracking catch mistakes. Ops stays in control without firefighting or chasing orphan resources. The platform scales safely, balancing freedom with built-in guardrails.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;h2 id="metrics-measuring-governance-enablement"&gt;Metrics: Measuring Governance Enablement&lt;/h2&gt;
&lt;p&gt;To ensure your governance practices truly empower your organization, it&amp;rsquo;s essential to track clear, actionable metrics. These metrics help you understand the effectiveness of your governance processes, identify areas for improvement, and ensure governance remains frictionless and enabling:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Spent on Manual Compliance Checks and Audits&lt;/strong&gt;:
Measure how much time your teams spend manually verifying compliance or performing audits. Effective governance automation should significantly reduce this overhead, freeing teams to focus on higher-value tasks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Number of Compliance Violations or Audit Findings&lt;/strong&gt;:
Track how frequently compliance violations or audit issues occur. Effective governance should reduce these incidents, demonstrating that automated policies and guardrails are working as intended.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cloud Cost Predictability and Budget Adherence&lt;/strong&gt;:
Monitor how accurately your cloud spending aligns with forecasts and budgets. Good governance practices, such as automated tagging, resource lifecycle management, and cost controls, should improve predictability and reduce unexpected cost overruns.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Engineering Team Satisfaction with Governance Processes&lt;/strong&gt;:
Regularly survey engineering teams to gauge their satisfaction with governance processes. High satisfaction indicates that governance is enabling rather than hindering their workflows.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tracking these metrics helps you continuously improve your platform&amp;rsquo;s governance practices, ensuring they remain effective and frictionless.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style="width: 225px; float: left; margin-right: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="confident.png" width="200px" alt="confident expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Working within clear, automated guardrails&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;h2 id="pulumi-and-governance-enablement"&gt;Pulumi and Governance Enablement&lt;/h2&gt;
&lt;p&gt;Pulumi provides built-in governance features that help you scale safely and confidently, embedding compliance, consistency, and control directly into your platform:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CrossGuard (Policy as Code)&lt;/strong&gt;
Define and enforce compliance and operational policies automatically. CrossGuard checks every resource against your organization’s standards before deployment, preventing non-compliant resources and reducing manual audits.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Role-Based Access Control (RBAC) and Teams&lt;/strong&gt;
Manage permissions with precision. Pulumi’s RBAC ensures teams get exactly the access they need, no more, no less, so developers can move quickly within clear boundaries and ops can reduce risk.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Audit Logs and Drift Detection&lt;/strong&gt;
Capture a full history of every change and compare live infrastructure to the desired state in code. Audit logs simplify compliance reviews, drift detection spots unauthorized edits, and teams can fix issues in minutes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time-to-Live (TTL) Stacks / Ephemeral Environments&lt;/strong&gt;
Spin up short-lived environments for testing or previews. You can assign a TTL to any stack so it shuts down automatically after a set period. That keeps forgotten test resources from racking up costs and ensures your platform stays clean.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By leveraging Pulumi’s governance features, including CrossGuard, RBAC, audit logs, and TTL stacks, your platform becomes a powerful enabler. You automate compliance, maintain consistency, and empower engineering teams to innovate quickly and safely.&lt;/p&gt;
&lt;h2 id="conclusion-governance-as-a-platform-feature"&gt;Conclusion: Governance as a Platform Feature&lt;/h2&gt;
&lt;span style="width: 225px; float: right; margin-left: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="empowered.png" width="200px" alt="empowered expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Having autonomy with built-in controls&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;Governance doesn&amp;rsquo;t have to slow you down. By embedding governance directly into your platform, you empower engineering teams to innovate quickly while ensuring compliance, consistency, and control. Instead of manual checks, governance becomes automatic, transparent, and frictionless, enabling your organization to scale safely and confidently.&lt;/p&gt;
&lt;p&gt;Your engineering teams gain autonomy and speed, your operations teams gain visibility and control, and your organization gains the confidence to innovate at scale.&lt;/p&gt;
&lt;p&gt;You’ve now seen all six pillars of a modern internal developer platform—&lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-2/"&gt;provisioning&lt;/a&gt;, &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-3/"&gt;self-service&lt;/a&gt;, &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-4/"&gt;developer experience&lt;/a&gt;, &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-5/"&gt;security&lt;/a&gt;, &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-6/"&gt;observability&lt;/a&gt;, and governance. If you’d like to see how Pulumi makes building and running a platform like this simpler, check out &lt;a href="https://www.pulumi.com/product/internal-developer-platforms/"&gt;Pulumi IDP&lt;/a&gt;.&lt;/p&gt;</description><author>Adam Gordon Bell</author><category>platform-engineering</category></item><item><title>Observability as a Developer Superpower</title><link>https://www.pulumi.com/blog/platform-engineering-pillars-6/</link><pubDate>Tue, 10 Jun 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/platform-engineering-pillars-6/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/platform-engineering-pillars-6/index.png" /&gt;
&lt;span style="width: 225px; float: right; margin-left: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="frustrated.png" width="200px" alt="frustrated expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Frustratedly trying to figure out what's actually happening&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;In previous articles in this series, we’ve shown how &lt;a href="https://www.pulumi.com/blog/series/platform-engineering-pillars/"&gt;platform engineering&lt;/a&gt; turns infrastructure chaos into consistency, gives teams self-service tools, smooths developer workflows, and bakes security into the platform. Each pillar builds on the last. Together, they create an internal developer platform that cuts friction and speeds innovation.&lt;/p&gt;
&lt;p&gt;Even so, teams still face a big challenge: seeing what’s really happening. Whether things go wrong or run smoothly, engineering teams need clear, actionable insights into their systems. Without observability, you end up guessing, reacting slowly, and hunting through scattered data.&lt;/p&gt;
&lt;p&gt;This article shows how observability can be a superpower, giving teams the visibility, insights, and confidence to build better software. Embedding observability into your platform lets teams spot, understand, and fix problems fast, turning reactive firefighting into proactive innovation.&lt;/p&gt;
&lt;h2 id="the-problem-data-overload-without-insights"&gt;The Problem: Data Overload Without Insights&lt;/h2&gt;
&lt;p&gt;Teams drown in metrics, logs, and traces but lack useful insights. In practice, this shows up in three common friction points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tool sprawl:&lt;/strong&gt; Teams use separate tools for metrics, logs, and traces. They waste time flipping between dashboards and stitching data together.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Alert fatigue:&lt;/strong&gt; Teams get hit with noisy, context-free alerts. With no clear priority or context, key alerts get lost, causing missed issues or slow responses.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reactive debugging:&lt;/strong&gt; Troubleshooting turns into a late-night fire drill. Teams spend hours digging through logs and metrics after users have already noticed the problem.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When observability is limited to post-mortems and fragmented dashboards, your team wastes time reacting instead of preventing problems, and innovation grinds to a halt.&lt;/p&gt;
&lt;h2 id="the-solution-observability-as-an-engineering-superpower"&gt;The Solution: Observability as an Engineering Superpower&lt;/h2&gt;
&lt;span style="width: 225px; float: left; margin-right: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="tired.png" width="200px" alt="tired expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Exhausted from hours of reactive debugging when the problem could have been caught earlier&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;The solution isn’t just about bolting on more monitoring tools. it’s about baking visibility, context, and guidance into your platform. To do this, embrace three key principles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Centralized Service Dashboards &amp;amp; Service List&lt;/strong&gt;
Surface every running service (or database, function, etc.) in one “Services” portal, complete with health badges (CPU, error rate), on-call owner info, and one-click links to that service’s metrics, logs, and traces. By unifying all telemetry behind a single service card, you eliminate context-switching and help engineers find exactly what they need in seconds, not minutes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Actionable Alerts and Insights&lt;/strong&gt;
Replace vague, noisy notifications with context-rich, prioritized alerts that include severity, correlated root-cause data, and recommended next steps (“Database latency jumped 200% since last deploy: rollback or scale up replicas”). Group and surface only the most critical issues first to reduce alert fatigue and speed up resolution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Embedding Observability into Engineering Workflows&lt;/strong&gt;
Ship every new microservice with built-in logging, metrics, and tracing by including those hooks in your platform’s service templates and CI/CD pipelines. When instrumentation is automatic, “oops, I forgot to add a span” moments disappear, and teams gain immediate visibility into performance and errors from day one.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When observability becomes a superpower, engineering teams gain the visibility and insights they need to confidently build, deploy, and operate software. Instead of drowning in data, they proactively identify and resolve issues, optimize performance, and innovate with confidence.&lt;/p&gt;
&lt;h3 id="a-centralized-service-dashboards--service-list"&gt;A. Centralized Service Dashboards &amp;amp; Service List&lt;/h3&gt;
&lt;span style="width: 225px; float: right; margin-left: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="learning.png" width="200px" alt="learning expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Reading the Service Catalog&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;Imagine you’re paged at 2 AM because “OrderService” is failing, but you don’t know where to look. Metrics live in Grafana, logs are in Elasticsearch, traces in Jaeger, and you still have to hunt down who’s on call. You spend precious minutes clicking through multiple UIs and Slack channels just to figure out who owns the service and where its telemetry lives.&lt;/p&gt;
&lt;p&gt;A centralized service list solves this by surfacing every running microservice (or database, or function) in one place. In your platform’s web portal, you land on a “Services” page that shows OrderService alongside CPU and error‐rate badges, an on-call owner, and links to its real-time dashboard, filtered logs, and trace waterfall. No matter which team spun it up, you know exactly where to click: metrics, logs, traces, deployment history, and contact info all live behind a single service card.&lt;/p&gt;
&lt;p&gt;By embedding a service list into your platform, you eliminate context switching and reduce onboarding friction. If a service isn’t listed, it isn’t properly instrumented, so gaps stand out immediately. In practice, this “one‐pane‐of‐glass” approach means engineers spend seconds finding the right dashboard and the right person, instead of minutes piecing together fragments across disconnected tools.&lt;/p&gt;
&lt;h3 id="b-actionable-alerts-and-insights-reducing-noise-and-accelerating-response"&gt;B. Actionable Alerts and Insights: Reducing Noise and Accelerating Response&lt;/h3&gt;
&lt;span style="width: 225px; float: left; margin-right: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="angry.png" width="200px" alt="locked-in expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Digging through alert noise&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;It’s 4 AM and your phone buzzes with three simultaneous alerts, each with vague descriptions like &amp;ldquo;High CPU usage detected&amp;rdquo; or &amp;ldquo;Error rate increased.&amp;rdquo; Without clear context or recommended actions, you must manually investigate each alert, digging through logs and metrics to determine severity and root cause. This manual triage process is slow, frustrating, and error-prone, increasing the risk of missing critical issues or delaying resolution.&lt;/p&gt;
&lt;p&gt;Engineering teams often face a constant barrage of alerts, many of which lack clear context, severity, or actionable next steps. This flood of noisy, ambiguous notifications creates alert fatigue, causing your team to overlook critical issues or waste valuable time investigating false positives.&lt;/p&gt;
&lt;p&gt;A platform approach should focus on actionable metrics. Instead of vague notifications, clearly state the issue (&amp;ldquo;Database latency increased by 200%&amp;rdquo;), provide relevant context (&amp;ldquo;Latency spike correlated with recent deployment&amp;rdquo;), and suggest immediate actions (&amp;ldquo;Rollback recent deployment or scale database resources&amp;rdquo;). Additionally, alerts are automatically grouped and prioritized based on severity and impact, ensuring you focus on the most critical issues first.&lt;/p&gt;
&lt;p&gt;By holistically approaching alerts and insights, you significantly reduce alert fatigue and noise, accelerate incident response and resolution, and empower engineering teams with greater confidence and autonomy. Your team spends less time manually triaging alerts and more time proactively resolving issues, improving reliability, productivity, and overall team satisfaction.&lt;/p&gt;
&lt;h3 id="c-embedding-observability-into-engineering-workflows-visibility-from-day-one"&gt;C. Embedding Observability into Engineering Workflows: Visibility from Day One&lt;/h3&gt;
&lt;span style="width: 225px; float: right; margin-left: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="sleepy.png" width="200px" alt="sleepy expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;At 2 AM, where are the logs for this service.&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;You’ve just deployed a brand-new microservice to production, only to discover performance issues or unexpected behavior. Sure, you should remember to add tracing, logging, and metrics by hand, but in practice, things slip through the cracks. It isn’t until real-world traffic hits that you realize you forgot to instrument X or Y, and now you’re scrambling to retroactively add code, redeploy, and wait for data to appear, delaying resolution and frustrating your team.&lt;/p&gt;
&lt;p&gt;If your platform’s service templates already include all the necessary logging, metrics gathering, and tracing out of the box, it makes life a lot easier. Embedding observability into those templates and engineering workflows ensures every new microservice ships with built-in instrumentation.&lt;/p&gt;
&lt;p&gt;This proactive approach reduces “oops, I forgot” moments, accelerates troubleshooting, and increases team productivity and satisfaction, ultimately improving the reliability and quality of your software.&lt;/p&gt;
&lt;h2 id="real-world-example-observability-superpower-in-action"&gt;Real-World Example: Observability Superpower in Action&lt;/h2&gt;
&lt;span style="width: 225px; float: left; margin-right: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="excited.png" width="200px" alt="excited expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Applying an Actional Metric&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;At 3:15 AM, your pagerduty alert goes off: “CheckoutService latency spiked 150%.” You log into your platform’s Services portal and immediately see CheckoutService highlighted with a red latency badge and Todd Rivera listed as the on-call owner. Rather than scouring multiple dashboards, you click its service card to jump straight to the metrics, logs, and trace views.&lt;/p&gt;
&lt;p&gt;The alert itself is remarkably precise: “CheckoutService latency rose 150% at 3:10 AM following the v2.3.1 deployment. PaymentGatewayService upstream error rate jumped from 0.2% to 2.3%. Recommendation: rollback v2.3.1 or scale PaymentGateway pods. Contact Todd Rivera.” Instantly, you know where the problem lies, which upstream service is impacted, and what the next step should be.
In the trace waterfall, you spot a 200 ms delay on CheckoutService calls to PaymentGateway. The logs, automatically instrumented by your service template, filter to TimeoutException entries all timestamped at 3:10 AM. Opening the “Ask Platform” AI widget, you type, “Why did CheckoutService latency spike at 3:10 AM?” The AI responds: “Likely cause: v2.3.1 added index idx_created_at to PaymentGateway’s transactions table, causing an 80 ms delay per request. Rollback v2.3.1 or patch queries to remove the new index.”&lt;/p&gt;
&lt;p&gt;Armed with this precise diagnosis, you open a rollback pull request and, after Todd&amp;rsquo;s ok, deploy it within minutes.&lt;/p&gt;
&lt;p&gt;CheckoutService latency and PaymentGateway errors immediately return to baseline. By moving from alert to resolution entirely within the platform (thanks to built-in instrumentation, actionable alerts, and AI-driven analysis, you’ve squashed a major incident before most users ever noticed.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;h2 id="metrics-measuring-observability-enablement"&gt;Metrics: Measuring Observability Enablement&lt;/h2&gt;
&lt;p&gt;To ensure your observability practices truly empower engineering teams, it&amp;rsquo;s essential to track clear, actionable metrics. These metrics help you understand the effectiveness of your observability tools and processes, identify areas for improvement, and demonstrate the tangible impact observability has on your organization.&lt;/p&gt;
&lt;p&gt;Key metrics to measure observability enablement include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mean Time to Detection (MTTD)&lt;/strong&gt;:&lt;br&gt;
How quickly are issues identified after they occur? Effective observability should significantly reduce the time it takes to detect problems, enabling faster responses and minimizing user impact.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mean Time to Resolution (MTTR)&lt;/strong&gt;:&lt;br&gt;
How quickly are issues resolved once detected? With clear, actionable insights and unified observability, your teams should resolve issues faster, reducing downtime and improving reliability.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Engineering Team Satisfaction with Observability Tools&lt;/strong&gt;:&lt;br&gt;
Regularly survey your teams to gauge their satisfaction with observability tools and workflows. Higher satisfaction indicates that observability is effectively embedded into engineering workflows, reducing friction and increasing productivity.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Adoption Rate of Observability Tools and Dashboards&lt;/strong&gt;:&lt;br&gt;
Track how widely observability tools and dashboards are adopted across teams. Increased adoption indicates that your teams find these tools valuable, intuitive, and helpful in their daily work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reduction in Alert Noise and False Positives&lt;/strong&gt;:&lt;br&gt;
Measure the volume and accuracy of alerts over time. Effective observability should reduce noisy, irrelevant alerts, ensuring your teams focus on meaningful, actionable notifications.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tracking these metrics helps you continuously improve your observability practices, ensuring they remain effective and empowering. By regularly reviewing and acting on these insights, you can proactively enhance team productivity, reliability, and overall satisfaction.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="pulumi-and-observability-enablement"&gt;Pulumi and Observability Enablement&lt;/h2&gt;
&lt;span style="width: 225px; float: right; margin-left: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="new-idea.png" width="200px" alt="new-idea expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Platform insights&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;Pulumi’s platform features let you explore observability without bolting on extra tools. Key Pulumi features that enable observability include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pulumi Insights&lt;/strong&gt;:&lt;br&gt;
Provides unified visibility and powerful search across all your cloud resources. Your teams can quickly discover, explore, and understand their infrastructure, eliminating manual searches and reducing cognitive load.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Centralized Service List&lt;/strong&gt;:
Pulumi IDP’s Services portal gives you a single place to register each microservice, database, or cloud resource and link to its dashboards, logs, and traces.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pulumi Co-Pilot&lt;/strong&gt;:&lt;br&gt;
Delivers AI-powered troubleshooting and insights directly within your workflows. Your teams can ask natural-language questions about their infrastructure (such as &amp;ldquo;What infrastructure changed yesterday?&amp;rdquo;) and receive immediate, actionable answers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-In Instrumentation via IDP Components&lt;/strong&gt;:&lt;br&gt;
When you author components and templates in Pulumi IDP, you can bake in standard logging, metrics, and tracing hooks. Every service spun up from those templates ships with consistent instrumentation on day one.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With Pulumi, observability can become an integrated part of your platform, accelerating innovation, improving reliability, and empowering engineering teams to confidently build, deploy, and operate software.&lt;/p&gt;
&lt;h2 id="conclusion-observability-as-a-platform-feature"&gt;Conclusion: Observability as a Platform Feature&lt;/h2&gt;
&lt;span style="width: 225px; float: left; margin-right: 20px;"&gt;
&lt;span style="text-align:center"&gt;
&lt;img src="happy.png" width="200px" alt="happy expression"&gt;
&lt;figcaption&gt;
&lt;i&gt;Happy resolving an incident in minutes.&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/span&gt;
&lt;/span&gt;
&lt;p&gt;Observability isn’t just about plugging in more tools. It’s about baking-in consistent instrumentation, measurement, and context so every engineer (platform, DevOps/SRE, or application) knows exactly where to look and how to act.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Service-Templates with Built-In Telemetry&lt;/strong&gt;
By providing service templates that already include logging, metrics gathering, and tracing, you eliminate “Oops, I forgot to instrument X” moments. Every new microservice inherits a standard setup, so you never have to retroactively add code or scramble when traffic first hits production.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consistent Service Dashboards &amp;amp; Centralized Service List&lt;/strong&gt;
Instead of hunting across eight different dashboards, engineers always start from a single “Service List” page. From there, one click takes them to that service’s metrics overview, log stream, or trace waterfall. This unified entry point reduces cognitive load and cuts straight to “Where’s the problem?”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Measuring Alert Quality and Actionability&lt;/strong&gt;
A truly mature platform doesn’t just send alerts. It tracks whether those alerts are helpful or noise. By measuring “ratio of actionable alerts vs. false positives,” you continuously fine-tune thresholds and eliminate alert fatigue. The result? Engineers trust their notifications and respond faster to real incidents.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AI-Driven Context and Natural-Language Troubleshooting&lt;/strong&gt;
On top of unified telemetry and alert quality metrics, AI can instantly correlate recent deployments, configuration changes, and error spikes. Engineers can ask, “Why did latency jump at 3 AM?” or “What changed in production last night?” in plain English, and the platform provides a clear, context-enriched answer. This additional layer turns reactive firefighting into proactive problem prevention.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When you combine these elements (components and templates, a single service dashboard, alert quality measurement, and AI/natural-language querying), you transform observability into a genuine superpower. Issues are spotted, triaged, and fixed before customers even notice.&lt;/p&gt;
&lt;p&gt;Next time, we’ll dive into the final pillar, Platform Governance, showing how to enforce policy, manage costs, and keep your platform secure and compliant as it scales.&lt;/p&gt;</description><author>Adam Gordon Bell</author><category>platform-engineering</category></item><item><title>Platform Engineering Buffet at SEITENBAU</title><link>https://www.pulumi.com/blog/platform-engineering-buffet/</link><pubDate>Tue, 27 May 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/platform-engineering-buffet/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/platform-engineering-buffet/index.png" /&gt;
&lt;p&gt;&lt;em&gt;This post is based on my video interview with Nico Thomas, a platform engineer at SEITENBAU. In this article, Nico shares how he and his team built a flexible, reusable platform to support 20+ diverse projects using Pulumi. Watch the video below or read on for Nico’s take on building an infrastructure buffet. - Adam Gordon Bell&lt;/em&gt;&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/wF9COpHJ9b4?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Imagine your company isn&amp;rsquo;t Spotify with one product pipeline, but 20 independent government projects running on Ansible-provisioned VMs—some on Kubernetes, some delivered into other customer data centers, some operated by clients themselves. Each team is building its own CI/CD, secrets management, and integrations. You’re left with a million reinvented wheels.&lt;/p&gt;
&lt;p&gt;That was the situation my team and I faced at SEITENBAU, a German software company specializing in custom development for both public and private sectors. Unlike the typical platform engineering stories—where teams build infrastructure for a single product with multiple microservices—we had a fundamentally different challenge: &lt;strong&gt;How do you build a platform that serves dozens of completely independent projects, each with their own technology choices, deployment targets, and operational models?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The answer? Stop trying to force everyone onto the same plate. Instead, build a buffet.&lt;/p&gt;
&lt;h2 id="the-buffet-philosophy"&gt;The Buffet Philosophy&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-02.png" alt="Buffet visualization with labeled containers showing NPM Artifact Storage, Container Registry, and various infrastructure components"&gt;&lt;/p&gt;
&lt;p&gt;Think of a traditional platform as a set menu—also known as prix fixe—where everyone gets the same courses, prepared the same way, in the same order. But what if your diners include vegans, carnivores, and people with various dietary restrictions? What if some want a quick snack while others need a seven-course meal?&lt;/p&gt;
&lt;p&gt;That was exactly the situation we faced. We had:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Government projects that needed to run on-premises due to data sovereignty requirements.&lt;/li&gt;
&lt;li&gt;Modern cloud-native applications leveraging Kubernetes and GitOps.&lt;/li&gt;
&lt;li&gt;Legacy systems still operating on virtual machines managed with Ansible.&lt;/li&gt;
&lt;li&gt;Projects we ran as managed services and others we simply delivered to customers.&lt;/li&gt;
&lt;li&gt;Teams using various CI/CD tools, artifact repositories, and deployment strategies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A one-size-fits-all platform would have been a disaster. Instead, my team built a platform offering a rich selection of pre-configured, production-ready components. Teams could mix and match according to their specific needs, creating their own unique infrastructure combinations.&lt;/p&gt;
&lt;h2 id="the-challenge-beyond-microservices"&gt;The Challenge: Beyond Microservices&lt;/h2&gt;
&lt;p&gt;Most platform engineering resources assume you&amp;rsquo;re building infrastructure for a single product – Spotify&amp;rsquo;s Backstage, for example. But what happens when you&amp;rsquo;re dealing with over 20 completely independent projects, each with distinct requirements?&lt;/p&gt;
&lt;p&gt;Each project is distinct, featuring its own:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Technology stack (Java predominates, but we support various frameworks and languages).&lt;/li&gt;
&lt;li&gt;Infrastructure requirements (cloud, on-premises, or hybrid setups).&lt;/li&gt;
&lt;li&gt;Security and compliance constraints.&lt;/li&gt;
&lt;li&gt;Operational models (managed by us, the client, or jointly).&lt;/li&gt;
&lt;li&gt;Release cadences and deployment strategies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="slide-07.png" alt="Choose your menu"&gt;&lt;/p&gt;
&lt;p&gt;Initially, this diversity seemed chaotic, but we quickly noticed that underneath these variations, common patterns emerged. Every project consistently required source control, CI/CD pipelines, artifact storage, secrets management, and deployment targets. The critical realization was that &lt;strong&gt;we didn&amp;rsquo;t need to standardize what teams chose—we needed to standardize how they connected these building blocks.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s where Pulumi became essential. Its flexibility allowed us to construct an infrastructure buffet that genuinely accommodated the diverse appetites and needs of every team.&lt;/p&gt;
&lt;h2 id="building-the-kitchen-architecture-with-pulumi"&gt;Building the Kitchen: Architecture with Pulumi&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-09.png" alt="Unified project configuration"&gt;&lt;/p&gt;
&lt;p&gt;Behind every great buffet is a well-organized kitchen. For our infrastructure, that kitchen is powered by Pulumi and Python, orchestrating a complex web of infrastructure services, configurations, and deployments. Using Pulumi together with Python has proven extremely valuable—it makes our day-to-day tasks easier to maintain and understand.&lt;/p&gt;
&lt;h3 id="the-multi-stack-approach"&gt;The Multi-Stack Approach&lt;/h3&gt;
&lt;p&gt;Rather than creating a single monolithic infrastructure program, we adopted a modular approach with multiple Pulumi stacks. This decision was essential for managing complexity and empowering team autonomy.&lt;/p&gt;
&lt;p&gt;&lt;img src="slide-10.png" alt="A look in the kitchen"&gt;&lt;/p&gt;
&lt;p&gt;Our architecture comprises several specialized Pulumi programs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GitLab System&lt;/strong&gt;: Manages installations and configurations of GitLab.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project Configuration&lt;/strong&gt;: Sets up team-specific GitLab groups, CI/CD runners, and agents.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cluster Management&lt;/strong&gt;: Provisions Kubernetes clusters complete with standard add-ons.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VM Infrastructure&lt;/strong&gt;: Manages traditional VM-based deployments utilizing Ansible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platform Services&lt;/strong&gt;: Configures shared services such as artifact repositories and identity providers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each program can maintain multiple stacks (dev, staging, prod), allowing us to manage various environments independently while leveraging shared infrastructure code.&lt;/p&gt;
&lt;h2 id="from-ingredients-to-ready-made-dishes-reusable-components"&gt;From Ingredients to Ready-Made Dishes: Reusable Components&lt;/h2&gt;
&lt;p&gt;&lt;img src="slide-06.png" alt="Platform vision showing the complete self-service platform"&gt;&lt;/p&gt;
&lt;p&gt;The real magic happens in our component library. Just as a buffet offers complete dishes rather than raw ingredients, we&amp;rsquo;ve built high-level components that encapsulate complex infrastructure patterns.&lt;/p&gt;
&lt;h3 id="example-the-kubernetes-storage-component"&gt;Example: The Kubernetes Storage Component&lt;/h3&gt;
&lt;p&gt;&lt;img src="slide-15.png" alt="KubeLonghorn component diagram"&gt;&lt;/p&gt;
&lt;p&gt;Consider our Longhorn storage component. Instead of requiring teams to understand Helm charts, storage classes, and snapshot configurations, they simply declare they need persistent storage.&lt;/p&gt;
&lt;p&gt;The component handles all the complexity: installing Longhorn, configuring appropriate replication for test vs. production environments, setting up snapshot classes, and integrating with our internal certificate authority.&lt;/p&gt;
&lt;h2 id="two-years-later-the-buffet-is-open"&gt;Two Years Later: The Buffet is Open&lt;/h2&gt;
&lt;p&gt;After two years of running this platform in production, we&amp;rsquo;ve learned what works and what we&amp;rsquo;d do differently.&lt;/p&gt;
&lt;p&gt;Building a platform for diverse, independent projects requires a different mindset than traditional platform engineering. Instead of forcing standardization, we&amp;rsquo;ve embraced flexibility while maintaining consistency where it matters.&lt;/p&gt;
&lt;p&gt;The buffet approach—powered by Pulumi&amp;rsquo;s flexibility and Python&amp;rsquo;s expressiveness—has allowed us to serve 20+ different projects efficiently while giving teams the autonomy they need. It&amp;rsquo;s not about having one perfect dish; it&amp;rsquo;s about having a kitchen flexible enough to satisfy everyone.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re facing similar challenges with diverse project requirements, consider building a buffet instead of a prix fixe menu. Your teams will thank you for it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Want to build your own infrastructure buffet? &lt;a href="https://www.pulumi.com/docs/get-started/"&gt;Get started with Pulumi&lt;/a&gt; and join &lt;a href="https://slack.pulumi.com/"&gt;our community Slack&lt;/a&gt; to connect with engineers solving similar challenges.&lt;/em&gt;&lt;/p&gt;</description><author>Nico Thomas</author><author>Adam Gordon Bell</author><category>platform-engineering</category><category>kubernetes</category><category>infrastructure-as-code</category></item><item><title>Platform Engineering: Evolution or Rebranding?</title><link>https://www.pulumi.com/blog/platform-eng-rebrand/</link><pubDate>Mon, 12 May 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/platform-eng-rebrand/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/platform-eng-rebrand/index.png" /&gt;
&lt;p&gt;2 Months ago, user &lt;a href="https://old.reddit.com/r/devops/comments/1izpca1/platform_engineering_fad/"&gt;&lt;code&gt;deacon91&lt;/code&gt;&lt;/a&gt;, after years of working in the industry has declared DevOps to be a dead end on Reddit&amp;rsquo;s &lt;code&gt;r/devops&lt;/code&gt;. And I&amp;rsquo;ve been thinking about his thoughts on the industry since then.&lt;/p&gt;
&lt;img src="Picyard_1746641886795.png" alt="crossroads photo" style="width:100%;" /&gt;
&lt;p&gt;His point was that DevOps, the breaking down of silos between development and operations, had been tried. We learned the lessons of this approach and need to do something better: Platform Engineering.&lt;/p&gt;
&lt;p&gt;And platform engineering has certainly emerged as a new hot area. But is it truly an evolutionary step toward a greater way of developing and operating software? Or is it, as others in that same Reddit group declare, merely a fad and a rebranding of existing ideas?&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s what I want to explore: is platform engineering a rebrand or a genuine evolution?&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start by summarizing the cynical case - that it&amp;rsquo;s merely a rebrand.&lt;/p&gt;
&lt;h2 id="the-rebrand-case"&gt;The Rebrand Case&lt;/h2&gt;
&lt;img src="Picyard_1746642618981.png" alt="There were fad chasers yesterday, there are fad chasers today, and there will be fad chasers tomorrow until the sun burns out" style="width:100%;" /&gt;
&lt;h3 id="title-drift"&gt;Title Drift&lt;/h3&gt;
&lt;p&gt;This title drift happens in many fields. Just as the garbage man becomes the sanitation worker so does the sysadmin becomes the DevOps engineer.&lt;/p&gt;
&lt;p&gt;This creates title inflation in our competitive industry. People who job-hop regularly update their LinkedIn profiles from &amp;ldquo;business analyst&amp;rdquo; to &amp;ldquo;product manager.&amp;rdquo; Meanwhile, the person who stays put for years might still be called a &amp;ldquo;programmer&amp;rdquo; while everyone around them becomes a &amp;ldquo;Staff-plus Senior Backend Engineer.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;That ops wizard who&amp;rsquo;s been at the same company for eight years? Still an &amp;ldquo;Operations Engineer.&amp;rdquo; Their friend who switches jobs every 18 months? Now a &amp;ldquo;Senior SRE&amp;rdquo; making 50% more money.&lt;/p&gt;
&lt;p&gt;Title drift becomes a self-reinforcing cycle. When the recruiter discovers that the best DevOps candidates now call themselves &amp;ldquo;Platform Engineers,&amp;rdquo; your company&amp;rsquo;s job postings change overnight—even if no one plans to build an actual platform.&lt;/p&gt;
&lt;p&gt;This is how you end up with people like &lt;code&gt;u/hajimenogio92&lt;/code&gt; doing the exact same sysadmin work they&amp;rsquo;ve always done, just with &amp;ldquo;Platform Engineer&amp;rdquo; on their LinkedIn profile.&lt;/p&gt;
&lt;p&gt;This is one aspect of what people mean why they say &amp;ldquo;platform engineering is just a rebrand.&amp;rdquo; The other thing they sometimes mean is that it&amp;rsquo;s a fad everyone is chasing.&lt;/p&gt;
&lt;h3 id="hype-cycle-reboot"&gt;Hype Cycle Reboot&lt;/h3&gt;
&lt;img src="Picyard_1746642250343.png" alt="There were fad chasers yesterday, there are fad chasers today, and there will be fad chasers tomorrow until the sun burns out" style="width:100%;" /&gt;
&lt;p&gt;Tech movements decay in predictable ways. Remember Extreme Programming? It began as a revolution to empower developers. Then it morphed into Agile, and in some places, into the 12 steps, 7 competencies, and many processes of SAFe.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Scaled Agile Framework® (SAFe®) is a set of organization and workflow patterns for implementing agile practices at enterprise scale.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Maybe SAFe makes sense for your work place, but it&amp;rsquo;s certainly a lot more complex than it&amp;rsquo;s root and this pattern is what skeptics see in platform engineering.&lt;/p&gt;
&lt;p&gt;DevOps started at grassroots conferences with a simple message: &amp;ldquo;Let&amp;rsquo;s tear down the wall between developers and operations.&amp;rdquo; But once it peaked, everyone scrambled to slap &amp;ldquo;DevOps&amp;rdquo; on whatever they were already doing. Just like companies today adding &amp;ldquo;AI&amp;rdquo; to their products.&lt;/p&gt;
&lt;p&gt;Eventually, the original movement gets so diluted that we need a fresh start. New terminology. New conferences. New keynote speakers recycling old ideas with updated slides. New vendors selling solutions to problems you didn&amp;rsquo;t know you had.&lt;/p&gt;
&lt;p&gt;In this view, platform engineering isn&amp;rsquo;t revolutionary—it&amp;rsquo;s just the next square on the buzzword bingo card. DevOps plateaued. SRE plateaued. The Kubernetes experts ran out of things to say. So the industry needed something new to hype.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s some truth to this cynicism, but it blinds us to what platform engineering actually offers. More importantly, this view misses something crucial: where a platform approach succeeds, it reveals fundamental flaws in the original DevOps vision.&lt;/p&gt;
&lt;h2 id="the-case-for-evolution"&gt;The Case for Evolution&lt;/h2&gt;
&lt;img src="stickers.png" alt="laptop stickers" style="width:100%;" /&gt;
&lt;p&gt;The original DevOps movement introduced valuable ideas about breaking down silos and encouraging collaboration. However, its purest vision—where &amp;ldquo;everybody does everything&amp;rdquo;—faces practical limitations at scale.&lt;/p&gt;
&lt;p&gt;Totally cross-functional teams work well at small organizations but struggle when engineering teams grow beyond 20 people because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;People naturally have different specializations and preferences&lt;/li&gt;
&lt;li&gt;Few individuals want to perform both development and operations roles&lt;/li&gt;
&lt;li&gt;Staying current on everything in your Ops and Dev stack is often unrealistic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But most importantly, as organizations grow, specializations natuarally emerge. Governance and corporate policies often force the issue. A platform team is one such specialization and a powerful one if done right.&lt;/p&gt;
&lt;p&gt;Instead of focusing on eliminating silos, it focuses on creating productive abstractions and interfaces between application teams and operating services. The platform functions as an abstraction layer (similar to how a database abstracts data storage), with dedicated teams treating it as a product with clear boundaries.&lt;/p&gt;
&lt;p&gt;This approach contradicts the original DevOps vision but represents a necessary evolution. Platform Engineering acknowledges inevitable organizational divisions while still enabling collaboration. It leverages skills and organizational workflows from application development and product management to build a way to operate software effectively.&lt;/p&gt;
&lt;h2 id="why-not-both"&gt;Why not both?&lt;/h2&gt;
&lt;img src="bingo.png" alt="buzzword bingo" style="width:100%;" /&gt;
&lt;p&gt;So yeah, title drift is a thing. And the hype cycle is real. But the idea of a dedicated team removing frictions by building tools and reusable abstractions is an idea that&amp;rsquo;s here to stay.&lt;/p&gt;
&lt;p&gt;In fact, it&amp;rsquo;s just a way to scale the principles inherent in the original ideas of DevOps. It may technically diverge from the literal principles of DevOps, but it is most definitely true to the spirit.&lt;/p&gt;
&lt;p&gt;At Pulumi, we see this evolution firsthand. Our most forward-looking users aren’t chasing titles—they’re building internal platforms that empower teams, reduce friction, and let developers focus on what matters most. That’s why we’re investing in &lt;a href="https://www.pulumi.com/blog/announcing-pulumi-idp/#platform-teams"&gt;platform team features&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Not because it’s trendy—but because, done well, it works. And I think that’s the insight &lt;code&gt;deacon91&lt;/code&gt; was getting at.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://info.pulumi.com/ebook/platform-engineering-iac-recommended-practices"&gt;&lt;strong&gt;Get a Free Platform Engineering Guide →&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;</description><author>Adam Gordon Bell</author><category>platform-engineering</category></item><item><title>Security as an Enabler: Building Trust into Your Platform</title><link>https://www.pulumi.com/blog/platform-engineering-pillars-5/</link><pubDate>Fri, 11 Apr 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/platform-engineering-pillars-5/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/platform-engineering-pillars-5/index.png" /&gt;
&lt;p&gt;In previous articles, we looked at how &lt;a href="https://www.pulumi.com/blog/series/platform-engineering-pillars/"&gt;platform engineering&lt;/a&gt; fixes infrastructure chaos, enables self-service, and improves developer workflows. These pillars work together to boost both developer productivity and organizational speed.&lt;/p&gt;
&lt;p&gt;But there&amp;rsquo;s still one critical element that can make or break all this progress: security.&lt;/p&gt;
&lt;p&gt;Traditional security efforts — even &amp;ldquo;shift-left&amp;rdquo; initiatives — often create friction instead of clearing the way for innovation. Embedding security directly into your platform changes that. By weaving in policy-as-code, centralized secrets management, and identity-based authentication, you turn security from a blocker into an enabler. And with the right metrics, you can measure how well your platform balances protection and speed.&lt;/p&gt;
&lt;p&gt;When security is baked into your internal developer platform, it stops being a gatekeeper. Developers move faster — and with more confidence.&lt;/p&gt;
&lt;p&gt;Done right, your teams gain autonomy without compromising safety. Security people become partners instead of blockers. Your organization builds trust that speeds up innovation rather than slowing it down.&lt;/p&gt;
&lt;h2 id="the-problem-security-as-a-gatekeeper"&gt;The Problem: Security as a Gatekeeper&lt;/h2&gt;
&lt;p&gt;Traditional security practices often create friction rather than enable innovation. Developers run into several pain points: last-minute security reviews that delay deployments, unclear policies that feel arbitrary, and security teams that act more like blockers than partners.&lt;/p&gt;
&lt;p&gt;This friction has real consequences. When security becomes a bottleneck, developers find ways around it. They take shortcuts. All of this increases risk through inconsistent security practices.&lt;/p&gt;
&lt;p&gt;The end result is that innovation slows down. Developer autonomy shrinks. And the agility your platform was supposed to deliver disappears.&lt;/p&gt;
&lt;p&gt;Many organizations try to fix this by &amp;ldquo;shifting security left&amp;rdquo; - moving security checks earlier in development. But just dumping security responsibilities onto developers isn&amp;rsquo;t the answer. It overwhelms them and can still create inconsistencies.&lt;/p&gt;
&lt;p&gt;The real solution isn&amp;rsquo;t just about changing when security happens. It&amp;rsquo;s about changing how it works.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;h3 id="key-security-functions-within-a-platform"&gt;Key Security Functions within a Platform&lt;/h3&gt;
&lt;p&gt;Effective platform security involves several key functions, regardless of how they are distributed across teams or individuals in your organization:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Defining Security Strategy &amp;amp; Policy:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Developing and maintaining security policies, standards, and architectural best practices tailored to the organization.&lt;/li&gt;
&lt;li&gt;Providing security guidance, education, and support across engineering teams.&lt;/li&gt;
&lt;li&gt;Performing threat modeling, security architecture reviews, and proactive security assessments.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monitoring &amp;amp; Responding to Threats:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Actively monitoring systems to detect security events and potential threats in real-time.&lt;/li&gt;
&lt;li&gt;Managing security tooling (like SIEMs, vulnerability scanners) and orchestrating incident response procedures.&lt;/li&gt;
&lt;li&gt;Investigating incidents, coordinating remediation efforts, and managing security automation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Integrating Security into Development &amp;amp; Infrastructure:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Embedding security controls directly into the development lifecycle and infrastructure provisioning processes.&lt;/li&gt;
&lt;li&gt;Implementing secure-by-default configurations, automated security checks (SAST, DAST, SCA), and policy-as-code guardrails.&lt;/li&gt;
&lt;li&gt;Ensuring security considerations are built into CI/CD pipelines, service templates, and infrastructure modules from the start.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Collaboration &lt;em&gt;between&lt;/em&gt; these functions is crucial. A successful platform ensures that policy definition, operational monitoring, and practical implementation work together seamlessly to create a secure environment without hindering velocity.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="the-solution-embedding-security-into-developer-workflows"&gt;The Solution: Embedding Security into Developer Workflows&lt;/h3&gt;
&lt;p&gt;The key to solving security friction isn&amp;rsquo;t just adding more checkpoints earlier. It&amp;rsquo;s weaving security directly into your platform and your developers&amp;rsquo; daily work.&lt;/p&gt;
&lt;p&gt;Adding automated scans to your CI/CD pipeline is a good start. Tools like Dependabot, Snyk, and Trivy catch problems early and alert developers quickly. But these &amp;ldquo;shift-left&amp;rdquo; checks alone aren&amp;rsquo;t enough. Developers still need to interpret findings and fix issues, often without adequate support.&lt;/p&gt;
&lt;p&gt;Platform engineering takes a different approach. It builds security in from the start, rather than treating it as a final hurdle or dumping complex responsibilities on developers. It uses secure-by-default components and automated guardrails that work continuously.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see what this looks like in practice.&lt;/p&gt;
&lt;h3 id="policy-as-code-for-security-automating-trust"&gt;Policy-as-Code for Security: Automating Trust&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;ve implemented the &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-3/"&gt;intent-based approach&lt;/a&gt; we covered earlier, your developers already use secure-by-default modules. They simply request what they need (&amp;ldquo;I need a Java service with Kafka and PostgreSQL&amp;rdquo;), and the platform handles security details like IAM roles, encryption, and permissions.&lt;/p&gt;
&lt;p&gt;But secure defaults aren&amp;rsquo;t enough. You still need automated guardrails. Policy-as-Code adds this enforcement layer, keeping security standards consistent—even when someone tries to bypass or change the modules. It&amp;rsquo;s a backup system: secure modules provide your first defense, and Policy-as-Code catches anything that might slip through.&lt;/p&gt;
&lt;p&gt;For Example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;IAM Roles with Least Privilege:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Secure Default (Module):&lt;/strong&gt; The platform team&amp;rsquo;s IAM module automatically generates roles with least-privilege permissions. Developers don&amp;rsquo;t specify IAM roles directly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Policy-as-Code (Additional Guardrail):&lt;/strong&gt; A policy explicitly checks all IAM roles provisioned by the platform, ensuring no role grants overly broad permissions (e.g., no wildcard permissions). If a module is accidentally modified or misconfigured, the policy catches it immediately.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mandatory Encryption at Rest:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Secure Default (Module):&lt;/strong&gt; The platform team&amp;rsquo;s database module automatically provisions databases with encryption at rest enabled. Developers don&amp;rsquo;t specify encryption settings directly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Policy-as-Code (Additional Guardrail):&lt;/strong&gt; A policy explicitly checks all storage resources to ensure encryption at rest is always enabled. If a developer or platform engineer accidentally modifies the module or bypasses it, the policy immediately flags the issue.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you add Policy-as-Code to your platform, security becomes automatic and clear. Developers get instant feedback they can trust, and security teams maintain control without slowing things down. Your teams can move fast without taking shortcuts that create risk.&lt;/p&gt;
&lt;h3 id="protecting-sensitive-credentials-by-default"&gt;Protecting Sensitive Credentials by Default&lt;/h3&gt;
&lt;p&gt;Policy-as-Code secures your infrastructure, but you still need to protect how applications access sensitive resources like databases and APIs.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what often happens: A developer copies database passwords into a local .env file. They accidentally commit this file to Git, exposing the credentials to anyone with repository access. Or they inadvertently bake these secrets into a Docker image that others can download. Worse yet, if their laptop gets hacked, attackers can use these credentials to break into production systems.&lt;/p&gt;
&lt;p&gt;When these breaches happen, everything stops. Teams scramble to rotate credentials, investigate the damage, and fix systems—creating delays and increasing risk.&lt;/p&gt;
&lt;p&gt;Centralized secrets management provides a robust solution to credential security. It stores sensitive information in a secure vault and offers controlled access methods at runtime. Developers work with the secrets management solution instead of handling credentials directly, which significantly reduces exposure risk.&lt;/p&gt;
&lt;p&gt;Platform teams build these secure patterns into their service templates. They create clear pathways for accessing credentials that guide developers toward secure practices in both development and production environments.&lt;/p&gt;
&lt;p&gt;With this approach, your deployments become both faster and safer. Developers follow simpler, more consistent security procedures, while security teams gain confidence that credentials are properly protected throughout your systems.&lt;/p&gt;
&lt;h3 id="identity-and-access-management-frictionless-security-through-identity"&gt;Identity and Access Management: Frictionless Security through Identity&lt;/h3&gt;
&lt;p&gt;Your platform must also solve another security problem: how people and systems safely access cloud resources.&lt;/p&gt;
&lt;p&gt;Developers hate juggling multiple credentials—cloud provider keys, passwords, or tokens. These credentials can expire, get lost, or leak, causing headaches and security risks.&lt;/p&gt;
&lt;p&gt;Consider a common scenario: A developer trying to fix a broken production system finds their credentials have expired. Now they&amp;rsquo;re stuck hunting for new credentials instead of fixing the problem.&lt;/p&gt;
&lt;p&gt;Identity-based authentication fixes this. Developers just use their regular login. When developers log in normally, they automatically get secure access to cloud resources through OIDC or SAML. No more managing credentials. Access stays secure and current.&lt;/p&gt;
&lt;p&gt;This approach simplifies access and removes barriers. Developers get secure access to resources when they need them, speeding up work without weakening security.&lt;/p&gt;
&lt;p&gt;Identity-based authentication, combined with policy-as-code guardrails and centralized secrets management, creates a comprehensive security system that protects without impeding work. To see how these practices function together, let&amp;rsquo;s look at a real example.&lt;/p&gt;
&lt;h2 id="real-world-example-security-enablement-from-build-to-incident-response"&gt;Real-World Example: Security Enablement from Build to Incident Response&lt;/h2&gt;
&lt;p&gt;A developer deploys a new microservice. They select a secure template from the service catalog. Policy-as-code instantly checks that encryption and permissions are set correctly, and credentials are setup in a centralized secrets management environment.&lt;/p&gt;
&lt;p&gt;As the service builds, automatic scans check dependencies and container images for vulnerabilities. The system creates a dependency list (SBOM), tracking every component used. Build pipelines verify and sign code, so only trusted code reaches production.&lt;/p&gt;
&lt;p&gt;Once deployed, security monitoring begins automatically, showing the service&amp;rsquo;s security status in real time. Later, someone discovers a vulnerability in a library used by the microservice. Thanks to the dependency list, the security team immediately knows which services are vulnerable. Monitoring spots suspicious activity and sends clear alerts to the team&amp;rsquo;s dashboards.&lt;/p&gt;
&lt;p&gt;Clear incident response plans help teams contain and fix the problem. The team patches the vulnerable component, using the same secure pipelines to quickly roll out the fix.&lt;/p&gt;
&lt;p&gt;In this scenario, security helps rather than blocks at every stage. From building to responding to incidents, your platform helps teams build secure software quickly.&lt;/p&gt;
&lt;p&gt;But how do you know if your security practices are truly enabling your teams? To answer that, you need clear, actionable metrics.&lt;/p&gt;
&lt;h2 id="metrics-measuring-security-enablement"&gt;Metrics: Measuring Security Enablement&lt;/h2&gt;
&lt;p&gt;To check if your security approach works, track two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Security Incident Rate:&lt;/strong&gt;&lt;br&gt;
Count how many security problems reach production. Fewer incidents means your security is working.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Developer Security Friction Score:&lt;/strong&gt;&lt;br&gt;
Include security questions in your regular developer surveys. Ask how much security processes slow their work or cause frustration. Improving scores show that security fits naturally into their workflow.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These two measures combined tell you your security works and at what cost, so your team can build good software fast.&lt;/p&gt;
&lt;h2 id="pulumi-and-security-enablement"&gt;Pulumi and Security Enablement&lt;/h2&gt;
&lt;p&gt;Achieving these goals, a decreasing incident rate coupled with a low developer friction score, requires a platform built with the right foundations. Pulumi helps you construct such a platform by providing built-in capabilities that directly embed security into your infrastructure workflows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/crossguard/"&gt;Policy as Code (CrossGuard)&lt;/a&gt;:&lt;/strong&gt; Automatically enforce security and compliance standards.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/product/esc/"&gt;Secure Secrets Management (Pulumi ESC)&lt;/a&gt;:&lt;/strong&gt; Centralize and securely inject secrets without manual handling.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/"&gt;Identity-Based Authentication&lt;/a&gt;:&lt;/strong&gt; Simplify secure access to cloud resources using existing identities.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With Pulumi, security becomes an integrated, frictionless part of your platform—accelerating innovation while building trust.&lt;/p&gt;
&lt;h2 id="security-as-a-platform-feature"&gt;Security as a Platform Feature&lt;/h2&gt;
&lt;p&gt;Security can help, not hinder. By building security into your platform, you help developers work faster and safer. Security becomes a feature, not an obstacle.&lt;/p&gt;
&lt;p&gt;Security completes the platform foundation we&amp;rsquo;ve built in previous articles on &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-2/"&gt;Provisioning&lt;/a&gt;, &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-3/"&gt;Self-Service&lt;/a&gt;, and &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-4/"&gt;Developer Experience&lt;/a&gt;, creating a platform that speeds up development.&lt;/p&gt;
&lt;p&gt;But developers still need to see what&amp;rsquo;s happening in their systems. Next time, we&amp;rsquo;ll explore how Observability helps developers spot and fix problems quickly.&lt;/p&gt;</description><author>Adam Gordon Bell</author><category>platform-engineering</category></item><item><title>Why Choose Pulumi Cloud Over DIY Backends?</title><link>https://www.pulumi.com/blog/why-choose-pulumi-cloud-over-diy-backends/</link><pubDate>Wed, 19 Mar 2025 09:00:00 -0700</pubDate><guid>https://www.pulumi.com/blog/why-choose-pulumi-cloud-over-diy-backends/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/why-choose-pulumi-cloud-over-diy-backends/index.png" /&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Note: This post discusses Pulumi Copilot, which Pulumi Neo has replaced. &lt;a href="https://www.pulumi.com/docs/ai/"&gt;Learn about Neo →&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Pulumi Cloud empowers engineers to automate, secure, and manage modern infrastructure platforms.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Many companies are building internal developer platforms or modern infrastructure platforms to provide developer self-service while maintaining security and compliance. Companies adopt Pulumi IaC so they can apply software engineering practices to their infrastructure scaling problems and because it is fully open source with a strong community and &lt;a href="https://github.com/orgs/pulumi/projects/44/"&gt;public roadmap&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At Pulumi, we’re committed to open source—always have been; always will be. Pulumi IaC is &lt;a href="https://github.com/pulumi/pulumi"&gt;entirely open source&lt;/a&gt; (Apache 2.0 license), meaning you can adopt and extend it however you like. If you’re new to Pulumi, the open source edition is an excellent way to start modernizing your infrastructure. But as your organization grows and the complexity of your environment increases, you may find yourself devoting significant time to rolling your own enterprise IaC backend features.&lt;/p&gt;
&lt;p&gt;That’s why we built &lt;a href="https://www.pulumi.com/product/pulumi-cloud/"&gt;Pulumi Cloud&lt;/a&gt;—to help you avoid building and maintaining these capabilities from scratch while ensuring you can automate, secure, and manage your infrastructure at scale. Pulumi Cloud provides enterprise capabilities that make it easier to build modern infrastructure platforms. Companies receive increasing value from Pulumi Cloud as their organization and their infrastructure platforms grow in size and complexity.&lt;/p&gt;
&lt;p&gt;As companies expand or &lt;a href="https://www.pulumi.com/what-is/what-is-platform-engineering/"&gt;platform engineering&lt;/a&gt; mandates become more expansive, challenges arise around collaboration, security, governance, and scaling. Some questions that need answering include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How do teams collaborate?&lt;/li&gt;
&lt;li&gt;How do you securely manage infrastructure state?&lt;/li&gt;
&lt;li&gt;How do you enable self-service infrastructure?&lt;/li&gt;
&lt;li&gt;How do you adhere to IT security standards?&lt;/li&gt;
&lt;li&gt;How do you enforce governance policies?&lt;/li&gt;
&lt;li&gt;How do you protect sensitive data?&lt;/li&gt;
&lt;li&gt;How do you enforce least privileged access across the organization?&lt;/li&gt;
&lt;li&gt;How do you maintain uptime or get support for your architecture?&lt;/li&gt;
&lt;li&gt;How do you manage the cost and complexity of multi-cloud environments?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If some of these questions apply to you or your team, learn more about Pulumi Cloud below to understand when it makes sense to transition to a &lt;a href="https://www.pulumi.com/pricing/"&gt;paid Pulumi offering&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="what-drives-the-most-value-in-pulumi-cloud"&gt;What drives the most value in Pulumi Cloud?&lt;/h2&gt;
&lt;p&gt;The most frequent business values that our existing customers experience with Pulumi Cloud relate to speed, scale, security, and savings.&lt;/p&gt;
&lt;h3 id="speed"&gt;Speed&lt;/h3&gt;
&lt;p&gt;There are speed benefits that customers typically experience across three areas: the infrastructure platform, developer productivity, and operations. Pulumi Cloud simplifies building and running complex infrastructure automation workflows through the Automation API. It also makes it easy to componentize best practices that can be easily shared and distributed through a centralized repository.&lt;/p&gt;
&lt;p&gt;Pulumi Cloud streamlines the software delivery pipeline with &lt;a href="https://www.pulumi.com/product/pulumi-deployments/"&gt;Pulumi Deployments&lt;/a&gt; and a wide range of 3rd party &lt;a href="https://www.pulumi.com/docs/iac/using-pulumi/continuous-delivery/"&gt;CI/CD integrations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pulumi Cloud provides &lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;Pulumi Insights&lt;/a&gt;, offering search, analytics, and AI-driven insights over your infrastructure. With Insights, you can instantly search for critical information - such as finding MySQL databases on end-of-life versions across all your cloud assets, reducing the operational time it takes to find needles in haystacks.&lt;/p&gt;
&lt;h3 id="scale"&gt;Scale&lt;/h3&gt;
&lt;p&gt;Part of building an infrastructure platform is so your organization can scale and make it easy to onboard new developers. Pulumi Cloud integrates seamlessly with various &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/oidc/"&gt;identity providers&lt;/a&gt; like Azure ActiveDirectory, Okta, G Suite, or any &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/saml/"&gt;SAML/SSO provider&lt;/a&gt;, offering deep support for role-based access control (RBAC) and SCIM for automatic synchronization and revocation of access based on identity provider groups. Audit logs keep track of developer activity within an organization, recording what actions were taken, when, and by whom.&lt;/p&gt;
&lt;p&gt;Pulumi Cloud also makes it easy to &lt;a href="https://www.pulumi.com/product/internal-developer-platforms/"&gt;build developer portals&lt;/a&gt; for developer self-service. Organization Templates can provide a centralized repository for cloud components, best practices and configurations. The New Project Wizard also provides a gallery interface to pick a template and easily walk through configuration and deployment of the infrastructure.&lt;/p&gt;
&lt;h3 id="security"&gt;Security&lt;/h3&gt;
&lt;p&gt;Another reason your organization is investing in an infrastructure platform is so that security and compliance can be automated as infrastructure is self-serviced. Your platform must prevent infrastructure deployments that violate security, reliability, cost, or compliance policies. Pulumi Cloud, through Pulumi CrossGuard, provides out-of-the-box support for common security and compliance policies, ensuring PCIDSS, ISO27001, SOC2, and CIS compliance for cloud applications and infrastructure.&lt;/p&gt;
&lt;p&gt;For applications being built across the organization, securing sensitive information like database passwords, cloud credentials, and API keys is paramount. Secrets can inadvertently end up in insecurely stored state files, leading to potential breaches. Pulumi Cloud, however, encrypts all data in transit and at rest, utilizing hardware security module (HSM) based encryption. Read the &lt;a href="https://www.pulumi.com/security/pulumi-cloud-security-whitepaper"&gt;Pulumi Cloud Security Whitepaper&lt;/a&gt; for more information.&lt;/p&gt;
&lt;p&gt;Pulumi Cloud further enhances security with Pulumi ESC, a centralized &lt;a href="https://www.pulumi.com/what-is/what-is-secrets-management/"&gt;secrets management&lt;/a&gt; and orchestration service. This service pulls and syncs secrets from various stores like HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, and 1Password, making it easy to adopt dynamic, short-lived secrets on demand. Secrets can be accessed via CLI, API, Kubernetes operator, the Pulumi Cloud UI, and in-code with TypeScript/JavaScript, Python, and Go SDKs. Pulumi ESC leverages the same identity, RBAC, Teams, SAML/SCIM, OIDC, and scoped access tokens used by Pulumi IaC, ensuring that secrets management complies with enterprise security policies.&lt;/p&gt;
&lt;h3 id="savings"&gt;Savings&lt;/h3&gt;
&lt;p&gt;Building a platform and managing cloud infrastructure demands considerable time and energy. As discussed above, &lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;Pulumi Insights&lt;/a&gt; X-Rays your entire cloud footprint, so you can observe, plan, and drive changes across your infrastructure. With this total visibility, Pulumi Insights helps you reduce waste by showing you usage information and identifying potentially stale infrastructure, which can lead to substantial cost savings.&lt;/p&gt;
&lt;p&gt;You can also have a conversation with &lt;a href="https://www.pulumi.com/product/copilot/"&gt;Pulumi Copilot&lt;/a&gt; about your infrastructure in natural language and get answers to operational questions that would take hours to piece together from other sources.&lt;/p&gt;
&lt;h2 id="why-not-build-your-own-enterprise-features-on-top-of-pulumi-iac-open-source"&gt;Why not build your own enterprise features on top of Pulumi IaC open source?&lt;/h2&gt;
&lt;p&gt;Build vs buy is a question of opportunity cost. Should you and your team build and operate your own enterprise backend service that engineers at Pulumi have already built to handle the needs and scale of the world’s biggest companies? Or is their time better spent focused on building a modern infrastructure platform that will increase development velocity across the company and drive business growth?&lt;/p&gt;
&lt;h3 id="maintenance-costs"&gt;Maintenance costs&lt;/h3&gt;
&lt;p&gt;When you build and operate your own enterprise backend, you’ll need to dedicate one full-time engineer for every team of ten - that’s nearly 10% of your engineering expense. Running a backend requires maintenance, updates, and troubleshooting. Outages and incidents can lead to significant financial losses. Pulumi Cloud, as a fully managed service, frees up your team’s time from the operational and maintenance burdens of managing an IaC backend.&lt;/p&gt;
&lt;h3 id="operational-reliability-and-availability"&gt;Operational reliability and availability&lt;/h3&gt;
&lt;p&gt;One of the primary functions of the enterprise backend is managing state. State management involves managing concurrency controls, preventing state corruption, ensuring backup and recovery, maintaining high availability of the state service, and providing consistent visibility across all managed resources; this is easy to get wrong. Manual human intervention is frequently required to recover and repair state files, a process that is time-consuming, can create or prolong outages, and carries significant risk.&lt;/p&gt;
&lt;h3 id="security-and-compliance"&gt;Security and compliance&lt;/h3&gt;
&lt;p&gt;Building your own enterprise backend also requires you to design and manage the service to adhere to numerous IT security standards, including SOC 1/SSAE 16/ISAE 3402, SOC 2, SOC 3, FISMA, FedRAMP, DOD SRG Levels 2 and 4, PCI DSS Level 1, EU Model Clauses, ISO 9001 / ISO 27001 / ISO 27017 / ISO 27018, ITAR, IRAP, FIPS 140-2, MLPS Level 3, and MTCS. This involves a manual assessment and validation process for each standard, which can be time-consuming and complex.&lt;/p&gt;
&lt;h3 id="customer-support"&gt;Customer support&lt;/h3&gt;
&lt;p&gt;You will also be giving up 12x5 or 24x7 customer support, which helps ensure your organization receives immediate assistance with any architectural, cloud-related, or Pulumi best-practices issues. Pulumi also has an experienced group of Solutions Architects and Customer Success Architects that have experience scaling &lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;infrastructure as code&lt;/a&gt; and building modern infrastructure platforms.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Pulumi Cloud is an enterprise-ready solution that comes with less risk and less maintenance costs than the DIY approach. With Pulumi Cloud, you get a fully managed service that automates deployments, ensures compliance, and offers comprehensive security features out-of-the-box. You’ll get a clear understanding of the product roadmap as well as talented engineers supporting your architecture and use cases.&lt;/p&gt;
&lt;p&gt;Pulumi Cloud gives you the platform to automate, secure, and manage your modern infrastructure platform so your company can choose to focus on innovation and growth.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://app.pulumi.com/signup"&gt;Try Pulumi Cloud for free&lt;/a&gt; and see how it can accelerate your infrastructure automation. Sign up today and start building with Pulumi Cloud.&lt;/p&gt;</description><author>Aaron Kao</author><category>infrastructure-as-code</category><category>platform-engineering</category><category>pulumi-cloud</category></item><item><title>Improve Developer Experience: Increase Dev Productivity with Internal Developer Platforms</title><link>https://www.pulumi.com/blog/platform-engineering-pillars-4/</link><pubDate>Thu, 13 Mar 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/platform-engineering-pillars-4/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/platform-engineering-pillars-4/index.png" /&gt;
&lt;p&gt;In the last article in this &lt;a href="https://www.pulumi.com/blog/series/platform-engineering-pillars/"&gt;Platform Engineering Pillars series&lt;/a&gt;, we explored how &lt;strong&gt;self-service infrastructure&lt;/strong&gt; frees developers from bottlenecks and dependency gates. By providing reusable infrastructure modules and intent-based configurations, platform teams dramatically reduce infrastructure friction. This self-service model powers faster deployments, increased autonomy, and fewer delays.&lt;/p&gt;
&lt;p&gt;However, &lt;strong&gt;infrastructure provisioning alone isn’t enough to improve developer experience&lt;/strong&gt;. Even with efficient provisioning, developers can still face inconsistent local setups, sluggish CI/CD pipelines, poor documentation, and fragmented tooling. These obstacles quietly reduce &lt;strong&gt;developer productivity&lt;/strong&gt;, slow &lt;strong&gt;developer velocity&lt;/strong&gt;, and increase operational overhead.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/is83TV8nrTg?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Your platform’s ability to support daily workflows directly impacts core success metrics like &lt;strong&gt;time to first commit&lt;/strong&gt;, &lt;strong&gt;time to production&lt;/strong&gt;, and &lt;strong&gt;developer satisfaction&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;When improving &lt;strong&gt;developer experience&lt;/strong&gt; as part of a platform engineering initiative, measure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time to First Commit&lt;/strong&gt; – How quickly a developer can become productive in a new environment or project. Pay particular attention to new hires.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time to Production&lt;/strong&gt; – How fast code moves from commit to successful production release.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developer Satisfaction&lt;/strong&gt; – Regularly survey friction points and prioritize fixing the top issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Friction logs&lt;/strong&gt; are also a powerful way to identify roadblocks, recording every obstacle encountered during common workflows. This reveals hidden friction and provides a roadmap for improvement.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A great &lt;strong&gt;developer experience&lt;/strong&gt; accelerates iteration, improves problem-solving, and drives better products. An &lt;strong&gt;internal developer platform (IDP)&lt;/strong&gt; designed for &lt;a href="https://www.pulumi.com/blog/developer-experience-business-critical/"&gt;DevEx is a fundamental competitive advantage&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-service-catalog-foundation-for-developer-experience"&gt;The Service Catalog: Foundation for Developer Experience&lt;/h2&gt;
&lt;p&gt;Developer friction often starts with something simple: not knowing what’s already available or who owns it. Without a single, reliable source of truth, developers reinvent the wheel, duplicate work, and waste time chasing information.&lt;/p&gt;
&lt;p&gt;A well-structured &lt;strong&gt;service catalog&lt;/strong&gt; in your internal developer platform addresses this by providing a central repository for all services and applications. At its most basic, it&amp;rsquo;s just a web page with each service&amp;rsquo;s README, service metadata, and operational information.&lt;/p&gt;
&lt;p&gt;But, properly structured, this delivers some large benefits:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Context at a Glance&lt;/strong&gt;: Every catalog entry follows a standardized template, capturing core information such as purpose, interfaces (REST, gRPC, events, etc.), language/runtime, and environment requirements. New developers can quickly grasp a service&amp;rsquo;s role and easily jump into productive work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Discoverability and Reuse&lt;/strong&gt;: Without a catalog, teams often recreate services they don&amp;rsquo;t realize already exist. Duplicate services not only waste resources but lead to fragmented knowledge and inconsistencies. With a catalog, developers quickly find and leverage existing solutions, increasing reusability and reducing churn.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ownership Transparency&lt;/strong&gt;: Each entry in the catalog explicitly names team ownership, CODEOWNERS files, and pertinent contact details like Slack channels or on-call rotations. Clear ownership streamlines communication, issue resolution, and collaboration, saving precious time and avoiding frustrations.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A &lt;strong&gt;service catalog&lt;/strong&gt; supports autonomy, reduces wasted cycles, and increases &lt;strong&gt;developer velocity&lt;/strong&gt; by making essential information instantly accessible.&lt;/p&gt;
&lt;p&gt;But a Service Catalog alone isn&amp;rsquo;t enough. To fully streamline and enhance your development workflow, you must pair it with consistent local environments and reliable CI/CD processes. Both of which can be serviced by standardized service templates.&lt;/p&gt;
&lt;h2 id="service-templates-golden-paths-for-improving-developer-productivity"&gt;Service Templates: Golden Paths for Improving Developer Productivity&lt;/h2&gt;
&lt;p&gt;Earlier in this &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-2/"&gt;series&lt;/a&gt;, we introduced &lt;strong&gt;service templates&lt;/strong&gt; as a way to scaffold consistent, ready-to-go services. In an &lt;strong&gt;internal developer platform&lt;/strong&gt;, templates aren’t just for infrastructure, they’re the &lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/golden-paths-infrastructure-components-and-templates/"&gt;golden paths&lt;/a&gt;&lt;/strong&gt; that define how developers start and succeed.&lt;/p&gt;
&lt;p&gt;If 90% of new services are Go GRPC services, then a carefully crafted, opinionated go GRPC service blueprint will remove a lot of friction. It will give developers everything they need to begin delivering real business value immediately. A few select curated options of common starting points will help guide developers to generate projects complete with standardized structure, built-in quality checks, documentation, and clear guidelines for contribution.&lt;/p&gt;
&lt;p&gt;A great service template provides:&lt;/p&gt;
&lt;h3 id="project-bootstrapping"&gt;Project Bootstrapping&lt;/h3&gt;
&lt;p&gt;The template quickly scaffolds an entire service—including all necessary files and directories. Everything essential for your organization&amp;rsquo;s standards should be included, from CI/CD configurations and dependency management to directory structures and environment-specific configuration files.&lt;/p&gt;
&lt;h3 id="built-in-quality-tools"&gt;Built-in Quality Tools&lt;/h3&gt;
&lt;p&gt;Templates embed guardrails that maintain consistency and high-quality standards across teams:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Linting rules and formatters&lt;/strong&gt;: Tools like ESLint, flake8, or Checkstyle that ensure code style and consistency across your codebase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Testing frameworks&lt;/strong&gt;: Unit tests, integration tests, and contract testing tools set up and pre-configured (JUnit, pytest, Jest, Pact), helping teams maintain high quality right out of the gate.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="documentation-and-contribution-guides"&gt;Documentation and Contribution Guides&lt;/h3&gt;
&lt;p&gt;Many platform teams overlook how clear, consistent documentation is crucial for initial and ongoing developer productivity. Every new service should arrive out-of-the-box with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;README&lt;/strong&gt;: Describing at a glance what the project does, why it exists, and how to run it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: Service template establishes a place for service-specific documentation that will be surfaced in the Service catalog. Markdown explanations, example input/output, and real-world use-cases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contribution guidelines and coding standards&lt;/strong&gt;: Clearly documenting the expectations, conventions, and standards every developer can follow with confidence.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Embedding this documentation into templates ensures that even brand-new services are discoverable, understandable, and maintainable — right from their first commit.&lt;/p&gt;
&lt;p&gt;A great template means the service catalog becomes more than just an organizational listing. These thoughtfully designed templates can directly power it. Every new service entering your catalog aligns neatly with your organization&amp;rsquo;s best practices in code quality, documentation, and process standards.&lt;/p&gt;
&lt;p&gt;When paired with your &lt;strong&gt;service catalog&lt;/strong&gt;, templates ensure every new service aligns with best practices — boosting &lt;strong&gt;developer productivity&lt;/strong&gt; and &lt;strong&gt;developer velocity&lt;/strong&gt; from day one.&lt;/p&gt;
&lt;h2 id="streamlining-local-development-to-reduce-friction"&gt;Streamlining Local Development to Reduce Friction&lt;/h2&gt;
&lt;p&gt;One of the fastest ways to improve &lt;strong&gt;time to first commit&lt;/strong&gt; is to standardize local development workflows through your &lt;strong&gt;internal developer platform&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Your service templates provide the ideal mechanism for simplifying how quickly developers can get projects running locally. By embedding standardized local-development tooling into these templates, you ensure they&amp;rsquo;re available consistently across your service catalog. Good templates typically contain:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A preconfigured, containerized environments:&lt;/strong&gt; Using Dev Containers, Docker Compose, or similar tools lets developers launch an environment that closely resembles production with minimal friction, completely avoiding dependency drift or local environment inconsistencies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simple, standardized command runner:&lt;/strong&gt; Makefiles, just scripts, package.json scripts—whatever works as they&amp;rsquo;re consistently documented and easy to run commands such as &lt;code&gt;make build&lt;/code&gt;, &lt;code&gt;make test&lt;/code&gt;, or &lt;code&gt;make lint&lt;/code&gt;. Teams might diverge on preferred tooling over time; if so, simply record clearly in the project&amp;rsquo;s readme (and thus in your service catalog) exactly what&amp;rsquo;s needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-in documentation:&lt;/strong&gt; Each service template includes clear instructions in a README outlining step-by-step processes for setup, running tests, and other everyday developer tasks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With these pieces fully integrated into your catalog and templates, you significantly reduce friction and speed up development cycles, moving you meaningfully closer to improving your core developer-experience metrics.&lt;/p&gt;
&lt;p&gt;The next critical area we need to address is how smoothly and quickly code moves from a local commit to a production release.&lt;/p&gt;
&lt;h2 id="cicd-integration-fast-reliable-pipelines-for-experienced-developers"&gt;CI/CD Integration: Fast, Reliable Pipelines for Experienced Developers&lt;/h2&gt;
&lt;p&gt;Experienced developers cite unreliable or slow pipelines as major productivity killers. Their frustrations often revolve around flaky builds, unreliable tests, and cumbersome environment setups. Slow or unpredictable pipelines break developer flow, causing frustration, delays, and lower productivity.&lt;/p&gt;
&lt;p&gt;A strong &lt;strong&gt;internal developer platform&lt;/strong&gt; integrates fast, stable, and predictable CI/CD processes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stable, Fast Feedback:&lt;/strong&gt;&lt;br&gt;
Every new service comes pre-configured with build acceleration strategies like intelligent caching (Gradle, Bazel, Docker layers) and automatic parallel test execution. Stable and speedy pipelines help teams iterate quickly and confidently.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ephemeral, Self-service Environments:&lt;/strong&gt;&lt;br&gt;
Instead of battling shared staging environments – which get blocked by other teams— developers spin up short-lived testing environments directly from pull requests. Need to test your payment-service changes against the latest user-authentication service? Create a dedicated, temporary environment on-the-fly, validate interactions, then shut it down automatically when finished.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Test Reliability:&lt;/strong&gt;&lt;br&gt;
Strictly enforce policies to quarantine flaky tests, quickly escalate notifications to responsible developers, and provide clear paths for fixing instabilities. Proactive flakiness management ensures credibility and reliability for test pipelines over time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reliable CI/CD pipelines protect developer focus, reduce cognitive load, maintain &lt;strong&gt;developer velocity&lt;/strong&gt;, and prevent wasted time, increasing &lt;strong&gt;developer productivity&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;Developer experience is a vast, nuanced topic, and there&amp;rsquo;s much more a comprehensive platform can include than we&amp;rsquo;ve been able to explore fully here. Even just within your Service Catalog and developer workflows, valuable additions might include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Onboarding Guides&lt;/strong&gt;: Step-by-step guides rapidly bringing new developers up to speed on teams, tools, and processes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frictionless Product Backlog Integration&lt;/strong&gt;: Quick access from codebases to the product backlog to connect code directly with the business context.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code Coverage &amp;amp; Quality Dashboards&lt;/strong&gt;: Easy-to-use visualizations offering fast insights into quality metrics and test coverage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deprecation Notices &amp;amp; Change Management&lt;/strong&gt;: Automated notifications about changes, upcoming maintenance, or decommission plans to keep developers informed and prepared.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pre-built Common Components&lt;/strong&gt;: Shared libraries and components solving everyday needs like logging, authentication, validation, and configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And that&amp;rsquo;s truly just scratching the surface. But remember: Platform engineering is an iterative journey, you don&amp;rsquo;t need to tackle every single area all at once. If you start with friction logs and surveys to regularly identify and address pain points affecting daily workflows, you&amp;rsquo;ll already be heading confidently in the right direction.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="conclusion-idps-as-a-devex-multiplier"&gt;Conclusion: IDPs as a DevEx Multiplier&lt;/h2&gt;
&lt;p&gt;A great &lt;strong&gt;developer experience&lt;/strong&gt; is not optional — it’s a force multiplier for &lt;strong&gt;developer productivity&lt;/strong&gt; and &lt;strong&gt;developer velocity&lt;/strong&gt;. An &lt;strong&gt;internal developer platform&lt;/strong&gt; with service catalogs, golden path templates, streamlined local dev, and integrated CI/CD removes friction at every step of the developer journey.&lt;/p&gt;
&lt;p&gt;The result? Faster onboarding, quicker delivery, and happier teams.&lt;/p&gt;
&lt;p&gt;With Pulumi, platform teams can automate consistent environments, implement golden paths, and enable self-service infrastructure that scales with your organization.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/templates/"&gt;Organization Templates&lt;/a&gt; enables standardized service creation and consistent developer experiences&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/concepts/stack/#stackreferences"&gt;Stack References&lt;/a&gt; for managing dependencies between environments and services&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;Pulumi Deployments&lt;/a&gt; to streamline CI/CD workflows and enable self-service infrastructure&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/review-stacks/"&gt;Review Stacks&lt;/a&gt; for creating ephemeral, on-demand testing environments&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/automation-api/"&gt;Automation API&lt;/a&gt; for programmatically managing infrastructure and implementing platform workflows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By prioritizing &lt;strong&gt;developer experience&lt;/strong&gt; in your &lt;a href="https://www.pulumi.com/blog/idp-strategy-planning-self-service-infrastructure-that-balances-developer-autonomy-with-operational-control/"&gt;platform engineering strategy&lt;/a&gt;, you empower teams to move faster, build better, and maintain momentum, making your internal developer platform one of the most valuable assets in your organization.&lt;/p&gt;</description><author>Adam Gordon Bell</author><category>platform-engineering</category></item><item><title>Self-Service Infrastructure: From Tickets to Tools</title><link>https://www.pulumi.com/blog/platform-engineering-pillars-3/</link><pubDate>Thu, 06 Mar 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/platform-engineering-pillars-3/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/platform-engineering-pillars-3/index.png" /&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/blog/series/platform-engineering-pillars/"&gt;Previous articles&lt;/a&gt; in this series explored &lt;a href="https://www.pulumi.com/what-is/what-is-platform-engineering/"&gt;platform engineering&lt;/a&gt; principles and how Infrastructure as Code creates a solid foundation. But there&amp;rsquo;s still an important challenge to address: the infrastructure provisioning process itself. Without proper modularity and a clear separation between intent and infrastructure details, things get messy—leading to friction, delays, and unnecessary complexity.&lt;/p&gt;
&lt;h2 id="the-missing-layer-abstraction-through-modularity"&gt;The Missing Layer: Abstraction Through Modularity&lt;/h2&gt;
&lt;p&gt;The root issue here is how teams define and work with infrastructure. Without good abstraction layers, infrastructure code typically becomes unwieldy and complex.&lt;/p&gt;
&lt;p&gt;You end up with&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Highly detailed specifications that require deep domain knowledge&lt;/li&gt;
&lt;li&gt;Environment-specific configurations with subtle variations across resources&lt;/li&gt;
&lt;li&gt;Complex interdependencies that are difficult to trace and verify&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach burdens developers with low-level details they don’t need to worry about, while platform teams become gatekeepers, reviewing intricate configurations. Alternatively, a traditional ticketing model takes over, discarding the benefits of modern practices.&lt;/p&gt;
&lt;div style="text-align: center; width: 100%; margin: 0 auto;"&gt;
&lt;img src="platform.png" alt="" style="width: 100%;"&gt;
&lt;figcaption&gt;
&lt;i&gt;Solution: A Platform Engineering Approach&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/div&gt;
&lt;p&gt;What’s missing is a proper abstraction layer between raw infrastructure code and developer needs. &lt;strong&gt;That layer is the platform. A Platform for self-service infrastructure.&lt;/strong&gt; Without modular, reusable infrastructure patterns, every new application deployment becomes an exercise in starting from scratch and defining every detail instead of just stating what the application requires and deferring details to the platform.&lt;/p&gt;
&lt;h3 id="common-anti-patterns-without-proper-abstraction"&gt;Common Anti-Patterns Without Proper Abstraction&lt;/h3&gt;
&lt;p&gt;Without this modular platform approach to cloud infrastructure, organizations typically fall into one of two problematic patterns.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Copy-Paste Anti-Pattern&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Developers copy infrastructure code from previous projects. They find something similar, duplicate large chunks of configuration, make a few changes, and hope everything is right, and submit it for review. This leads to a brittle system with siloed knowledge. Security fixes must be applied manually across every instance – no one has a full picture of the infrastructure – and Day 2 Operations become error prone.&lt;/p&gt;
&lt;p&gt;And this isn&amp;rsquo;t limited to infrastructure: CI scripts get copied and modified, Dockerfiles and Kubernetes manifests get copied and modified.&lt;/p&gt;
&lt;p&gt;It feels like control, but it&amp;rsquo;s not. Developers still rely on platform specialists to validate changes and catch mistakes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Ticketing Anti-Pattern&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Alternatively, some organizations rely on rigid ticketing systems for infrastructure changes. A platform specialist applies writes and applies all changes, ensuring consistency — but also creating bottlenecks. Developers might wait days or weeks for simple modifications, leaving the process entirely unfinished.&lt;/p&gt;
&lt;p&gt;This guarantees expert oversight but strips developers of autonomy, making the platform team a bottleneck for every deployment.&lt;/p&gt;
&lt;p&gt;Neither anti-pattern strikes a balance between standardization and autonomy, leading to either sloppy infrastructure (copy-paste) or slow deployments (ticketing).&lt;/p&gt;
&lt;h3 id="the-resulting-problems"&gt;The Resulting Problems&lt;/h3&gt;
&lt;h4 id="day-1-bottleneck-slow-manual-infrastructure--developer-gridlock"&gt;Day 1 Bottleneck: Slow, Manual Infrastructure = Developer Gridlock&lt;/h4&gt;
&lt;p&gt;When provisioning becomes a bottleneck, developers with finished code wait days for infrastructure. This disrupts focus and forces frequent context switching. They juggle tasks to stay productive and then have to rebuild focus when the requested infrastructure is ready.&lt;/p&gt;
&lt;p&gt;These delays slow the entire delivery pipeline. Teams add buffer time for infrastructure delays, projects slip, and the business sees technology as slow-moving. Meanwhile, the real culprit is slow provisioning that kills momentum.&lt;/p&gt;
&lt;h4 id="day-2-and-beyond-chaos-sprawling-unpredictable-infrastructure--operational-nightmare"&gt;Day 2 And Beyond Chaos: Sprawling, Unpredictable Infrastructure = Operational Nightmare&lt;/h4&gt;
&lt;p&gt;Day 1 bottlenecks frustrate developers, but the real long-term cost is patching hell. Copy-paste infrastructure creates hundreds of snowflakes, each needing manual attention for every security fix or version bump. One-off configurations and custom environments pile up, creating technical debt no one fully understands.&lt;/p&gt;
&lt;p&gt;Operations teams are overwhelmed by the basic, critical task of simply keeping the lights on across a sprawling, inconsistent landscape.&lt;/p&gt;
&lt;h2 id="the-solution-a-platform-of-options-and-self-service"&gt;The Solution: A Platform of Options and Self Service&lt;/h2&gt;
&lt;p&gt;A Self-service platform is the solution to these problems. The platform is this curated list of modules, providing application developers with a set of pre-built options that let them work at a higher level of abstraction. By choosing from these modules, developers express their intent for infrastructure, leaving the platform to handle the implementation details. Let me explain.&lt;/p&gt;
&lt;p&gt;A strong self-service approach divides responsibilities into two clear layers:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level 1: Platform Team (Module Definition)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Builds and updates reusable infrastructure modules&lt;/li&gt;
&lt;li&gt;Bakes in security, compliance, and best practices&lt;/li&gt;
&lt;li&gt;Hides complexity so developers don’t need to worry about copy and pasting low-level details&lt;/li&gt;
&lt;li&gt;Sets guardrails for scalability, security, and compliance&lt;/li&gt;
&lt;li&gt;Updates modules as technologies and needs change&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Level 2: Application Developers (Module Consumption)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Browse a catalog of ready-made modules&lt;/li&gt;
&lt;li&gt;Compose pre-built modules to set up application infrastructure&lt;/li&gt;
&lt;li&gt;Spend time on code, not cloud configurations&lt;/li&gt;
&lt;li&gt;Operate within built-in guardrails&lt;/li&gt;
&lt;li&gt;Deploy applications faster using standardized components&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This setup keeps things fast and flexible. Developers get the autonomy to build without reinventing infrastructure, while platform teams maintain control where it matters.&lt;/p&gt;
&lt;h2 id="the-power-of-intent-based-specification"&gt;The Power of Intent-Based Specification&lt;/h2&gt;
&lt;div style="text-align: center; width: 100%; margin: 0 auto;"&gt;
&lt;img src="developer-intent.png" alt="" style="width: 100%;"&gt;
&lt;figcaption&gt;
&lt;i&gt;Layer of Abstraction to the Rescue&lt;/i&gt;
&lt;/figcaption&gt;
&lt;/div&gt;
&lt;p&gt;The two-level approach works by replacing over-specification with intent-based design.&lt;/p&gt;
&lt;p&gt;Over-specification happens when developers specify too many infrastructure details that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Require expertise they might not have&lt;/li&gt;
&lt;li&gt;Tightly coupled infrastructure to specific implementations&lt;/li&gt;
&lt;li&gt;Make future changes hard or even impossible&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Intent-based specification means developers state what their app needs, not how to implement it, meaning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Platform teams can update underlying infrastructure without breaking applications&lt;/li&gt;
&lt;li&gt;New capabilities can be added without disrupting existing applications&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Focusing on what developers need, not how it&amp;rsquo;s built, creates a system that’s easier to maintain and evolve for both platform teams and developers.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s walk through an example.&lt;/p&gt;
&lt;h2 id="practical-example-java-application-with-kafka-postgresql-and-redis"&gt;Practical Example: Java Application with Kafka, PostgreSQL, and Redis&lt;/h2&gt;
&lt;p&gt;The platform team provides reusable modules:&lt;/p&gt;
&lt;h3 id="java-application-module"&gt;Java Application Module&lt;/h3&gt;
&lt;p&gt;This module handles everything needed to run a Java app. It covers the Java runtime, memory settings, JVM options, scaling rules, health checks, monitoring, and Kubernetes namespacing. It also manages containers, security scans, resource limits, and logging integration—so developers don’t have to.&lt;/p&gt;
&lt;h4 id="kafka-integration-module"&gt;Kafka Integration Module&lt;/h4&gt;
&lt;p&gt;Similarly, this module simplifies Kafka integration, handling broker connections, authentication, topics, and security. It takes care of SASL/SSL authentication, replication factors, ACLs, and encryption. Developers just specify topics and schemas.&lt;/p&gt;
&lt;p&gt;And so on for common infrastructure components used in the org.&lt;/p&gt;
&lt;h3 id="level-2-developer-implementation"&gt;Level 2: Developer Implementation&lt;/h3&gt;
&lt;p&gt;Developers use a simpler interface. To deploy a new Java service with Kafka, PostgreSQL, and Redis, they only need to specify the required input parameters in the platform-defined modules:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Developer&amp;#39;s intent-based configuration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;application&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;order-processing-service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;java-application&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;2GB&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaling&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;integrations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;incoming-orders&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;partitions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;processed-orders&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;partitions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;consumer_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;order-processors&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;postgresql&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;orders_db&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;medium&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;backup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;enabled&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;redis&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;small&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3600&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;( Note: YAML not required. This pseudo-code could be UI driven, or it could be written in your programming language of choice. The point is it specifies intent and defers specifics to the platform. )&lt;/p&gt;
&lt;h2 id="solving-day-1-and-day-2-challenges"&gt;Solving Day 1 and Day 2 Challenges&lt;/h2&gt;
&lt;p&gt;The intent-based specification solves immediate and long-term problems:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Self-Service Transformation in Action:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Developer Experience&lt;/th&gt;
&lt;th&gt;Platform Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Submits simple intent-based configuration&lt;/td&gt;
&lt;td&gt;Expands into complete infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Focuses on application needs, not infrastructure details&lt;/td&gt;
&lt;td&gt;Provisions resources with appropriate sizing and security controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Specifies &amp;ldquo;what&amp;rdquo; is needed, not &amp;ldquo;how&amp;rdquo; to configure it&lt;/td&gt;
&lt;td&gt;Handles networking, monitoring, backups, and credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Limited expertise required in Kubernetes, networking, or security&lt;/td&gt;
&lt;td&gt;Implements best practices automatically across all deployments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Maintains and updates the underlying implementation over time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This approach transforms infrastructure from a developer burden into an organizational asset that becomes more valuable over time, rather than decaying into technical debt.&lt;/p&gt;
&lt;h3 id="developer-interaction-models-choosing-your-platform-interface"&gt;&lt;strong&gt;Developer Interaction Models: Choosing Your Platform Interface&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Hopefully, now you are bought in on the value of separate layers of abstraction and building a platform to expose those.&lt;/p&gt;
&lt;p&gt;The next key decision is how developers will actually &lt;em&gt;use&lt;/em&gt; this platform. The ideal interface balances ease of use with the necessary flexibility. Organizations and requirements vary, so a spectrum of interaction models exists, each with its own trade-offs. Tree common approaches are: CLI-Driven Infrastructure as Code, the Self-Service Portal, and a Hybrid model.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;CLI-Driven&lt;/th&gt;
&lt;th&gt;Self-Service Portal&lt;/th&gt;
&lt;th&gt;Hybrid Approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Developer Experience&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Code-based, using IaC modules and components directly&lt;/td&gt;
&lt;td&gt;Click-based UI with forms and catalogs&lt;/td&gt;
&lt;td&gt;Portal for common tasks, code for customization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Code Visibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full visibility and control&lt;/td&gt;
&lt;td&gt;Limited or no visibility&lt;/td&gt;
&lt;td&gt;Visible but with varying levels of access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Governance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Trust-based or PR reviews&lt;/td&gt;
&lt;td&gt;Enforced through portal constraints&lt;/td&gt;
&lt;td&gt;Guided paths with managed exceptions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Higher (requires IaC knowledge)&lt;/td&gt;
&lt;td&gt;Lower (minimal infrastructure knowledge)&lt;/td&gt;
&lt;td&gt;Moderate (basic UI with optional advanced use)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Experienced teams needing flexibility&lt;/td&gt;
&lt;td&gt;Teams prioritizing speed and standardization&lt;/td&gt;
&lt;td&gt;Organizations with diverse skill levels&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="1-cli-driven-infrastructure-as-code-empowering-developers-with-familiar-tools"&gt;&lt;strong&gt;1. CLI-Driven Infrastructure as Code: Empowering Developers with Familiar Tools&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;In this approach, platform teams build reusable infrastructure modules while developers consume them directly through code. Developers use familiar IaC tools like Pulumi CLI to instantiate these modules, with changes flowing through version control like any other code.&lt;/p&gt;
&lt;p&gt;The key strength is transparency and familiarity. Developers maintain visibility and ownership of their intent-based definitions. This code-centric workflow integrates naturally with existing development practices.&lt;/p&gt;
&lt;p&gt;However, this flexibility creates governance challenges and requires either strong trust or approval processes that might reintroduce bottlenecks. The approach also assumes developers have some IaC knowledge, making it best suited for organizations with mature DevOps practices and experienced teams.&lt;/p&gt;
&lt;h4 id="2-self-service-portal-click-ops-simplicity-for-rapid-provisioning"&gt;&lt;strong&gt;2. Self-Service Portal: Click-Ops Simplicity for Rapid Provisioning&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;The self-service portal approach creates a web interface where developers provision infrastructure without writing code. They simply browse a catalog, fill out forms, and click buttons to deploy standardized resources—all pre-configured by the platform team.&lt;/p&gt;
&lt;p&gt;This approach keeps infrastructure code completely centralized and hidden from developers. The portal translates simple selections (&amp;ldquo;Add Database: Medium Size&amp;rdquo;) into the appropriate underlying configurations, ensuring perfect compliance with organizational standards.&lt;/p&gt;
&lt;p&gt;The result is dramatically reduced friction and learning curve, enabling even infrastructure novices to deploy resources in minutes. However, this simplicity comes at the cost of flexibility. Customizations and unique needs typically require platform team involvement, making this model ideal for organizations with predictable workloads or where standardization outweighs customization needs.&lt;/p&gt;
&lt;h4 id="3-hybrid-approach-code-backed-self-service"&gt;&lt;strong&gt;3. Hybrid Approach: Code-Backed Self-Service&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;The hybrid approach generates and modifies infrastructure code via pull requests from UI interactions. When developers configure resources through the portal, the system commits code to repositories automatically, creating a transparent workflow where changes are visible, reviewable, and auditable through standard Git processes.&lt;/p&gt;
&lt;p&gt;This model provides both simplicity and flexibility. Routine tasks remain point-and-click while complex scenarios allow direct code editing within the same PR workflow. The approach maintains a complete audit trail through commit history while giving platform teams visibility into all changes.&lt;/p&gt;
&lt;p&gt;A significant tradeoff is implementation complexity: building a system that generates commits and PRs based on version control integration requires substantial investment. Organizations must weigh this upfront cost against the long-term benefits of combining UI simplicity with code transparency.&lt;/p&gt;
&lt;h4 id="lifecycle-management"&gt;Lifecycle Management&lt;/h4&gt;
&lt;p&gt;More effective lifecycle management is an advantage of a platform approach. Consider migrating from Kafka to AWS Kinesis. Traditionally, this would involve significant application developer effort, including updating connection details, authentication, and application logic. However, with the two-level abstraction and intent-based approach described earlier, this migration becomes simpler. Platform teams introduce a new Kinesis module matching the existing Kafka module&amp;rsquo;s intent-based interface. Data is mirrored, and developers can plan a switchover. Migration will not be free, but efforts and coordination will be reduced.&lt;/p&gt;
&lt;p&gt;Life-Cycle management is a huge topic in Day 2 operations and outside the scope of what can be covered here, but introducing abstractions and a platform of modules will pay off long term.&lt;/p&gt;
&lt;h3 id="looking-ahead-operational-excellence-and-beyond"&gt;Looking Ahead: Operational Excellence and Beyond&lt;/h3&gt;
&lt;p&gt;The two-level abstraction model does not just simplify provisioning. It also lays a strong foundation for operational excellence. By standardizing infrastructure through reusable modules and intent-based specifications, we create consistency and visibility that significantly simplify critical operational concerns such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Drift Detection and Reconciliation:&lt;/strong&gt; Standardized modules make it easier to detect and correct deviations from desired state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Continuous Compliance and Security:&lt;/strong&gt; Centralized module definitions allow security and compliance controls to be consistently enforced and audited.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost Management and FinOps:&lt;/strong&gt; Intent-based specifications enable clearer cost attribution and optimization opportunities.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability and Incident Response:&lt;/strong&gt; Consistent infrastructure patterns simplify monitoring, alerting, and troubleshooting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Later articles in this series will explore each of these areas in greater depth, demonstrating how a platform approach provides a powerful foundation for addressing them effectively.&lt;/p&gt;
&lt;h2 id="self-service-with-pulumi"&gt;Self-Service with Pulumi&lt;/h2&gt;
&lt;p&gt;The two-level architecture of IDP self-service creates a powerful interface between platform teams and application developers. By embracing intent-based specification, this approach enables developers to clearly express what they need with minimal complexity while giving platform teams the flexibility to implement and evolve the underlying infrastructure.&lt;/p&gt;
&lt;p&gt;As you build out your self-service approach, consider how Pulumi might fit in. With Pulumi, you get:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;Component resources&lt;/a&gt; for creating reusable infrastructure modules that encapsulate best practices.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-portals/templates/"&gt;Organization templates&lt;/a&gt; for building a catalog of infrastructure templates.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/product/packages/"&gt;Packages&lt;/a&gt; in your language of choice for a code-first self-service workflow.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://www.pulumi.com/product/internal-developer-platforms/"&gt;Platform-in-the-box&lt;/a&gt; experience for those who want a portal-first experience for self-service infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-portals/backstage/"&gt;A Backstage plugin&lt;/a&gt; for those who prefer to use Backstage for an IDP.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A great self-service workflow and abstraction layer are key to making platform engineering work. &lt;a href="https://www.pulumi.com/blog/series/platform-engineering-pillars/"&gt;Next in this series&lt;/a&gt;, we’ll tackle developer experience directly.&lt;/p&gt;</description><author>Adam Gordon Bell</author><category>platform-engineering</category></item><item><title>Provisioning: From Chaos to Control</title><link>https://www.pulumi.com/blog/platform-engineering-pillars-2/</link><pubDate>Thu, 27 Feb 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/platform-engineering-pillars-2/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/platform-engineering-pillars-2/index.png" /&gt;
&lt;p&gt;Provisioning is the first &lt;a href="https://www.pulumi.com/blog/series/platform-engineering-pillars/"&gt;pillar of platform engineering&lt;/a&gt;. Without consistent infrastructure provisioning – the automated creation and management of the underlying cloud resources – the rest of the platform suffers. Self-service, governance, and streamlined developer workflows all depend on it. Ultimately, a self-service layer on top of your cloud infrastructure is the goal, enabling developers to quickly and safely provision the resources they need, while adhering to organizational best practices and policies. But before self-service, the foundation of a good IDP is a robust and reliable provisioning system.&lt;/p&gt;
&lt;p&gt;By defining cloud resources as code and automating deployments, platform engineering teams ensure every environment – development, staging, and production – stays consistent and maintainable. This cuts down on configuration drift, reduces manual work, and supports auditable, collaborative workflows for every change.&lt;/p&gt;
&lt;p&gt;Let’s explore how platform engineering teams can achieve this by version-controlling infrastructure, automating deployments, separating environments properly, and limiting console interventions. By applying these principles, teams can create a platform where developers can move fast without breaking things, and where infrastructure supports innovation rather than slowing it down.&lt;/p&gt;
&lt;div class="note note-warning"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-warning-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;h3 id="top-5-iac-anti-patterns"&gt;Top 5 IaC anti-patterns&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Console-Only Changes:&lt;/strong&gt; Making &amp;ldquo;quick fixes&amp;rdquo; in production without updating IaC leads to drift, confusion, and hidden risks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hard-Coded Secrets:&lt;/strong&gt; Sensitive values in code or config files are a security liability. Use encrypted state or a secrets manager.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Copy-Paste Config:&lt;/strong&gt; Reusing half-baked snippets across projects creates cruft. Break out shared modules or templates.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Clear File Structure:&lt;/strong&gt; Throwing all configs into a single file or folder obscures dependencies. Organize by environment, service, or module.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skipping Peer Reviews:&lt;/strong&gt; Infrastructure mistakes can be costly. A simple pull request process can catch errors before deployment.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="-tip-read-our-list-of-iac-best-practices-"&gt;💡 Tip: Read our list of &lt;a href="https://www.pulumi.com/blog/iac-recommended-practices-code-organization-and-stacks/"&gt;IaC Best Practices&lt;/a&gt; 💡&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="building-a-reliable-iac-foundation"&gt;Building a reliable IaC foundation&lt;/h2&gt;
&lt;p&gt;&lt;img src="infra-workflow.png" alt="infra-workflow"&gt;&lt;/p&gt;
&lt;p&gt;It’s not enough to simply define your resources in code. A reliable IaC foundation should ensure that infrastructure changes move smoothly from idea to production, without surprising developers or straining operations. Here’s how to structure these workflows so they’re both transparent and resilient:&lt;/p&gt;
&lt;h2 id="version-control-as-the-single-source-of-truth"&gt;Version control as the single source of truth&lt;/h2&gt;
&lt;p&gt;&lt;img src="commits.png" alt="iac commits"&gt;&lt;/p&gt;
&lt;p&gt;Whether you’re using GitHub, GitLab, or something else, every infrastructure definition needs to live in version control. This is just the basics – and hopefully, you are already doing this, as you have been for years. Version-controlled changes allow you to track history, compare revisions, and peer review. A pull request might catch a misconfigured subnet or a database that was accidentally left publicly accessible, mistakes that could be catastrophic if they slip into production. This also means anyone can propose improvements or bug fixes, expanding the pool of expertise beyond a single “infrastructure guru.”&lt;/p&gt;
&lt;h2 id="automating-changes-with-cicd"&gt;Automating changes with CI/CD&lt;/h2&gt;
&lt;p&gt;&lt;img src="ci.png" alt="iac ci"&gt;&lt;/p&gt;
&lt;p&gt;Next, consider how to apply infrastructure modifications after they’re merged into main. A CI pipeline can automatically run a “plan” or “preview,” then only proceed with the actual update if no blockers appear. Policy checks can also be added, enforcing rules such as “no public S3 buckets” or “use encrypted volumes only.” By codifying these conditions, you avoid manual verification steps and reduce the chance of risky configurations slipping past manual review.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;h3 id="trunk-based-infrastructure-workflow"&gt;Trunk-based infrastructure workflow&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Protected main Branch:&lt;/strong&gt; No direct commits&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pull Request Merges:&lt;/strong&gt; Integrate changes via Pull Requests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automated PR Checks:&lt;/strong&gt; Previews and Policy-as-Code run on every PR&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Merge:&lt;/strong&gt; Merge to main triggers automated deployments&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="distinguish-each-environment"&gt;Distinguish each environment&lt;/h2&gt;
&lt;p&gt;&lt;img src="envs.png" alt="each environment"&gt;&lt;/p&gt;
&lt;p&gt;Not all environments have the same requirements or budgets, so it’s wise to separate dev, staging, and production configurations. You might share core modules across these environments, but keep each environment’s parameters and secrets in independent config files or stack definitions. This deliberate separation ensures that dev changes are tested in a realistic but contained environment before they can impact production. As a result, teams can experiment more confidently without risking live workloads.&lt;/p&gt;
&lt;h2 id="modularity-and-reusability"&gt;Modularity and reusability&lt;/h2&gt;
&lt;p&gt;A key principle of effective IaC, and a cornerstone of any good Internal Developer Platform, is reusability. You shouldn&amp;rsquo;t be copying and pasting large chunks of infrastructure code. Instead, you should build reusable components (or modules, or constructs, depending on the tool&amp;rsquo;s terminology) that encapsulate best practices and can be easily consumed by developers. This achieves several critical goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consistency:&lt;/strong&gt; Ensures that similar resources are provisioned in the same way, reducing configuration drift.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; Hides complexity from developers. They don&amp;rsquo;t need to know how a secure, compliant database is created, just that it is.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maintainability:&lt;/strong&gt; Changes to the underlying implementation of a component can be rolled out to all consumers of that component.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speed:&lt;/strong&gt; Developers can provision infrastructure faster by using pre-built components.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced Errors:&lt;/strong&gt; Standard components means that there will be less opportunities to make mistakes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Think of these reusable components as the &amp;ldquo;building blocks&amp;rdquo; of your IDP. Your platform team creates and maintains them, and developers use them to assemble their applications.&lt;/p&gt;
&lt;p&gt;Regardless of the specific IaC tool you choose, reusable components generally share these characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parameterized Inputs:&lt;/strong&gt; Components accept inputs (parameters, properties, configuration – the term varies) that allow users to customize their behavior. For example, a &amp;ldquo;database&amp;rdquo; component might accept a database_size parameter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Defined Outputs:&lt;/strong&gt; Components expose outputs that other parts of the infrastructure can consume. For example, a &amp;ldquo;database&amp;rdquo; component might output the database&amp;rsquo;s connection string.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encapsulation:&lt;/strong&gt; The internal implementation details of the component are hidden from the consumer. The consumer interacts with a well-defined interface (inputs and outputs).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Versioned:&lt;/strong&gt; Components should be versioned (e.g., using semantic versioning) to allow for controlled updates and rollbacks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Discoverable:&lt;/strong&gt; Components should be easily discoverable by developers, often through a central catalog or registry.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="example-an-iam-roles-component"&gt;Example: An IAM roles component&lt;/h3&gt;
&lt;p&gt;IAM roles are one of the most commonly misconfigured AWS resources, making them a perfect candidate for abstraction into a reusable component. Developers frequently make mistakes when setting up roles, leading to overly permissive access, broken permissions, or operational headaches.&lt;/p&gt;
&lt;h3 id="common-iam-role-mistakes"&gt;Common IAM role mistakes&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Overly Broad Permissions&lt;/strong&gt; – Developers often grant &lt;code&gt;*&lt;/code&gt; permissions instead of following the principle of least privilege.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Missing Assume Role Policies&lt;/strong&gt; – Without a proper trust policy, services may not be able to use the role at all.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Directly Attaching Policies to Users&lt;/strong&gt; – Instead of assigning roles to groups, users might manually attach policies, leading to hard-to-audit permission structures.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lack of Naming Conventions &amp;amp; Tagging&lt;/strong&gt; – Unstructured role names and missing tags make governance difficult.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="how-a-reusable-iam-module-fixes-this"&gt;How a reusable IAM module fixes this&lt;/h4&gt;
&lt;p&gt;A platform team can provide a self-service IAM role module that enforces best practices while still allowing customization. This module would:&lt;/p&gt;
&lt;p&gt;✅ &lt;strong&gt;Require a Least Privilege Policy&lt;/strong&gt; – The module only allows explicitly defined permissions, preventing wildcards. &lt;br&gt;
✅ &lt;strong&gt;Auto-Generate Trust Policies&lt;/strong&gt; – Ensures correct settings, reducing misconfigurations. &lt;br&gt;
✅ &lt;strong&gt;Enforce Naming Standards &amp;amp; Tagging&lt;/strong&gt; – Ensures roles are easily identifiable and trackable.&lt;/p&gt;
&lt;p&gt;By using a reusable IAM role module, developers can self-service their permissions while the platform team ensures security, consistency, and maintainability. This removes a major source of security risk and operational overhead.&lt;/p&gt;
&lt;h2 id="no-console-interventions"&gt;No console interventions&lt;/h2&gt;
&lt;p&gt;No matter how carefully IaC is managed, emergencies may occasionally necessitate direct console changes. However, such interventions are strictly forbidden except under an official “break glass” procedure. If a quick fix is applied in the cloud console, it’s critical that the change is immediately documented and returned to code. Regular drift detection can help with this: once a day or once a week, automated scans can compare actual cloud resources to your declared infrastructure. When it detects a mismatch, you decide whether the code or the running resource is the correct version. Either way, human “hotfixes” never linger as hidden surprises for long.&lt;/p&gt;
&lt;p&gt;By combining version control, automation pipelines, environment-based configs, and drift checks, you build a solid provisioning foundation. Once you have that in place, the next step is making these patterns easy to use, so teams can start new services without reinventing the wheel.&lt;/p&gt;
&lt;p&gt;But first, let&amp;rsquo;s cover some metrics and roadblocks.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;h3 id="metrics-that-matter"&gt;Metrics that matter&lt;/h3&gt;
&lt;p&gt;The classic &lt;a href="https://dora.dev/guides/dora-metrics-four-keys/"&gt;DORA metrics&lt;/a&gt; focus on software delivery. Adapting and modifying them for infrastructure provisioning can help measure how effectively your platform delivers reliable, self-service cloud resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lead Time for Infrastructure Changes:&lt;/strong&gt; How fast does a merged PR turn into running infrastructure? Shorter indicates efficient automation and fewer manual steps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure Drift Frequency:&lt;/strong&gt; Are developers constantly making console tweaks, or does your infrastructure stay in sync with code? A low drift rate means your code and actual resources stay aligned.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure Change Failure Rate:&lt;/strong&gt; What percentage of infrastructure changes result in incidents or rollbacks? A low failure rate indicates a robust, well-tested infrastructure pipeline, reducing wasted effort and potential outages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platform Self-Service Rate:&lt;/strong&gt; What percentage of provisioning changes are implemented by the requesting team (without needing to involve a central operations team)? A high self-service rate shows that your platform empowers developers and reduces bottlenecks.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="common-roadblocks"&gt;Common roadblocks&lt;/h2&gt;
&lt;p&gt;Adopting Infrastructure as Code helps teams automate provisioning, but common pitfalls can slow progress before they see results. Left unaddressed, problems hidden configuration tweaks, scattered code, or reliance on a single &amp;ldquo;infrastructure hero&amp;rdquo; make it hard to keep environments consistent and secure.&lt;/p&gt;
&lt;p&gt;By spotting these roadblocks early, teams can build a stronger foundation for a repeatable, collaborative IaC workflow.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Knowledge silos:&lt;/strong&gt; Relying on just one person (&amp;ldquo;Go ask Sarah&amp;rdquo;) for all infrastructure tasks creates a risky bottleneck. The broader team can&amp;rsquo;t replicate or improve the process, slowing new initiatives and leaving you vulnerable if that individual is out of office or leaves the company. Moving to a collaborative, version-controlled IaC model ensures that no single engineer is a gatekeeper for new environments or configuration changes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Overly complex or unstructured IaC:&lt;/strong&gt; Bloated or disorganized infrastructure code leads to confusion, duplication, and frequent errors. Engineers might copy-paste configurations from previous projects or cram all resources into a single file. By refactoring IaC into smaller modules, adopting a clear folder structure, and removing dead code, teams gain consistency and accelerate ramp-up times for new services.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Learning curves:&lt;/strong&gt; Teams new to IaC often encounter a steep learning curve. There is initially a lot to learn, and resistance from people used to quickly working through cloud UI can slow down full adoption. But time invested in learning tools and setting cultural norms pay off in agility and a platform strategy with guidance and golden paths can help reduce the burden.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cultural inertia:&lt;/strong&gt; The adoption of a platform engineering approach is a shift in how organizations manage infrastructure, and like all, change is not merely technical but also organizational. Resistance to change and organizational inertia can make it difficult to implement new ways of getting work done. Expecting, understanding, and working through this resistance is key to overcoming it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lack of comprehensive approach:&lt;/strong&gt; IaC tools are great for provisioning, but without a full platform approach, covering monitoring, logging, and the full life cycle of cloud resources, provisioning efforts may fall short. We will see in this series how the pillars of a comprehensive approach strengthen themselves.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These roadblocks highlight why a thoughtful, well-structured approach to provisioning is essential. But that’s not enough because the next step is to make these consistent patterns easily accessible so teams can spin up entire services without starting from scratch. And that’s where “golden path” templates come in.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;h3 id="platform-team-provisioning-responsibilities"&gt;Platform team provisioning responsibilities&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Setting up the initial IaC foundation&lt;/li&gt;
&lt;li&gt;Creating and maintaining templates&lt;/li&gt;
&lt;li&gt;Automating workflows&lt;/li&gt;
&lt;li&gt;Monitoring usage and compliance&lt;/li&gt;
&lt;li&gt;Internal Platform Evangelism&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="service-templates"&gt;Service templates&lt;/h2&gt;
&lt;p&gt;&lt;img src="abstraction-levels.png" alt="abstraction-levels"&gt;&lt;/p&gt;
&lt;p&gt;Even with a solid IaC foundation and reusable modules, spinning up a brand-new service can still require developers to understand how to pull in the underlying infrastructure components and how to use them. That’s where templates come in.&lt;/p&gt;
&lt;p&gt;These are pre-vetted, ready-to-use blueprints that capture your organization’s best practices for a complete service or application, including infrastructure, application, and security components. They are the key to enabling true self-service.&lt;/p&gt;
&lt;p&gt;Think of service templates as the next step up from the reusable components we discussed earlier. While a component might represent a single &amp;ldquo;building block&amp;rdquo; (like a secure S3 bucket or a database), a service template represents an entire structure built from those blocks (like a complete web application with a database, load balancer, and containerized application). They combine those building blocks with sensible default configurations and best practices for things like logging, Kubernetes setup, and security baked in.&lt;/p&gt;
&lt;p&gt;Beyond bundling your organization’s best practices into a single repository, these service templates can also include a preconfigured CI/CD pipeline.&lt;/p&gt;
&lt;p&gt;This means that when a team spins up a new service from the template, they inherit not just the infrastructure modules and best-practice configurations, but a fully operational CI/CD workflow. No extra setup is required. Developers get immediate feedback on their changes, and the merge to main triggers automatic deployments that keep every environment consistent.&lt;/p&gt;
&lt;p&gt;Instead of cobbling together snippets from old repos, teams can scaffold out a service by simply selecting the template that fits their need – whether it’s a containerized web app, a serverless function, or a data-processing pipeline – and providing a few key parameters.&lt;/p&gt;
&lt;p&gt;&lt;img src="service-template.png" alt="service template"&gt;&lt;/p&gt;
&lt;p&gt;These curated paths cut onboarding time, reduce configuration missteps, and ensure that the IaC modules are used in new services. If developers don’t have to remember which tags to apply or how to route logs, or even where to import infrastructure modules from, they can focus on delivering features rather than wrestling with infrastructure details. And as your platform matures, and new versions of your modules are introduced, you can update these templates, automatically sharing improvements with every new project.&lt;/p&gt;
&lt;h2 id="bringing-it-all-together-the-impact-of-effective-provisioning"&gt;Bringing it all together: The impact of effective provisioning&lt;/h2&gt;
&lt;p&gt;With reusable modules and service templates in place, and a deployment workflow that takes changes from git commits all the way to your cloud account, your platform engineering team creates a foundation that transforms how developers interact with infrastructure. This transformation yields measurable benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lower Infrastructure Change Failure Rate:&lt;/strong&gt; Automated validations and peer reviews catch issues early, reducing the number of failed deployments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Increased Platform Self-Service Efficiency:&lt;/strong&gt; Developers can provision resources in minutes instead of days, boosting productivity and reducing bottlenecks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced Lead Time for Infrastructure Changes:&lt;/strong&gt; Streamlined automation shortens the time from code commit to deployed infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minimized Infrastructure Drift:&lt;/strong&gt; Fewer manual console interventions mean your actual infrastructure stays aligned with what’s declared in code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(In the upcoming article, we’ll dig deeper into how governance guards these golden paths, ensuring that new projects comply with security and corporate policies right from day one.)&lt;/p&gt;
&lt;h2 id="managing-infrastructure-provisioning-with-pulumi"&gt;Managing infrastructure provisioning with Pulumi&lt;/h2&gt;
&lt;p&gt;As you build out your platform engineering plan, consider how Pulumi might fit in. With Pulumi, you get:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;Infrastructure as Code&lt;/a&gt; in the language of your choice.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;Component resources&lt;/a&gt; for creating reusable infrastructure modules that encapsulate best practices.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;Pulumi Deployments&lt;/a&gt; for a fully managed infrastructure deployment solution.&lt;/li&gt;
&lt;li&gt;And a &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;Platform in the box&lt;/a&gt; experience.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reliable infrastructure provisioning is the cornerstone that supports your entire platform engineering initiative. By implementing the practices outlined in this article – version-controlled IaC, automated CI/CD workflows, environment separation, and golden-path templates – you establish a foundation that enables consistency, speed, and trust.&lt;/p&gt;
&lt;p&gt;But provisioning alone isn’t enough. In upcoming articles, we’ll explore how policy-as-code and broader governance tie into this foundation, ensuring that all those newly created services meet security and compliance standards from the moment they’re deployed. But first, we’ll look at expanding the provisioning foundation covered here into a true self-service platform, so teams can quickly spin up services without risking the organizational chaos that often accompanies speed.&lt;/p&gt;
&lt;p&gt;Provisioning is the foundation – &lt;a href="https://www.pulumi.com/blog/series/platform-engineering-pillars/"&gt;next in this series&lt;/a&gt; we’ll build on it.&lt;/p&gt;</description><author>Adam Gordon Bell</author><category>platform-engineering</category></item><item><title>Platform Pillars: Build Platforms, Not Infrastructure</title><link>https://www.pulumi.com/blog/platform-engineering-pillars-1/</link><pubDate>Wed, 26 Feb 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/platform-engineering-pillars-1/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/platform-engineering-pillars-1/index.png" /&gt;
&lt;p&gt;Software drives innovation. Development teams face pressure to ship features faster. But speed collides with infrastructure complexity. Developers struggle with cloud setups, juggle scattered tools, and wait on operations teams for resources. The result is friction and slower innovation.&lt;/p&gt;
&lt;p&gt;This is where &lt;a href="https://www.pulumi.com/what-is/what-is-platform-engineering/"&gt;Platform Engineering&lt;/a&gt; comes in. It helps developers move faster by creating tools that actually work. A good internal platform lets teams self-serve infrastructure, find documentation, follow best practices, and focus on what they do best: writing useful software.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/AUCt28gVR6Y?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Building a platform isn&amp;rsquo;t about finding one perfect tool. It&amp;rsquo;s about assembling the right pieces, or pillars. These pillars define what every successful internal developer platform needs.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/blog/series/platform-engineering-pillars/"&gt;This series&lt;/a&gt; explores these key pillars of Platform Engineering, offering a practical guide to building platforms that remove barriers to developer speed. Each pillar addresses a specific challenge organizations face when scaling developer productivity. The first challenge is overcoming infrastructure chaos.&lt;/p&gt;
&lt;img align="right" style="margin: 15px;" width="300px" src="provisioning.png"&gt;
&lt;h3 id="problem-infrastructure-chaos-and-bottlenecks"&gt;&lt;strong&gt;Problem: Infrastructure chaos and bottlenecks&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Developers face many pain points with manual provisioning, which is why &lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;Infrastructure as Code&lt;/a&gt; has become so essential:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inconsistent environments&lt;/strong&gt;: Dev, staging, and production drift apart. &amp;ldquo;Works on my machine&amp;rdquo; becomes everyone&amp;rsquo;s excuse.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Slow processes&lt;/strong&gt;: Console clicking and waiting on ops creates bottlenecks. Developers wait days for basic infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration drift&lt;/strong&gt;: Manual configs lead to errors. Quick production fixes become undocumented mysteries that cause problems later.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lack of repeatability&lt;/strong&gt;: Spinning up new environments or replicating existing ones is a complex, time-consuming, and often unreliable process.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s why provisioning is the first pillar to master if you want to build a successful developer platform.&lt;/p&gt;
&lt;img align="left" style="margin: 15px; margin-right:25px;" width="300px" src="self-service.png"&gt;
&lt;h3 id="problem-dependency-bottlenecks-and-limited-developer-autonomy"&gt;&lt;strong&gt;Problem: Dependency bottlenecks and limited developer autonomy&lt;/strong&gt;&lt;/h3&gt;
&lt;span style="margin-left:-15px"&gt;
Even with automated provisioning, another challenge emerges - developers still struggle when tools are provided without considering usability.
&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hard to find what you need&lt;/strong&gt;: Developers waste time hunting for the right infrastructure modules. They end up searching docs, bothering colleagues, or rebuilding something that already exists.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Too much complexity&lt;/strong&gt;: Most developers aren&amp;rsquo;t infrastructure experts. Learning all the options and parameters creates hesitation and mistakes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lack of real autonomy&lt;/strong&gt;: Developers have the tools but not the confidence to use them. They still need approvals or fear breaking production.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inconsistent workflows&lt;/strong&gt;: Teams create their own ways of using infrastructure, making collaboration harder.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By implementing self-service infrastructure provisioning, you transform your platform from a centrally controlled system to a developer-centric environment. You unlock developer autonomy, accelerate development cycles, and free up operations teams to focus on higher-value activities.&lt;/p&gt;
&lt;img align="right" style="margin: 15px;" width="300px" src="developer-workflow.png"&gt;
&lt;h3 id="problem-inefficient-and-fragmented-development-processes"&gt;&lt;strong&gt;Problem: Inefficient and fragmented development processes&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Infrastructure is just one piece of the puzzle. Developers still face daily friction moving code to production.&lt;/p&gt;
&lt;p&gt;A typical developer&amp;rsquo;s day is full of frustrations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inconsistent local environments&lt;/strong&gt;: Variations in local setups, dependency conflicts, and operating system differences lead to debugging headaches and wasted time getting started.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Slow CI/CD pipelines&lt;/strong&gt;: Long builds, flaky tests, and mysterious pipeline configs block progress. Developers stare at progress bars instead of writing code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cumbersome testing and staging setups&lt;/strong&gt;: Provisioning environments for testing and staging can be a manual process. Environments may not accurately mirror production, leading to surprises and integration issues late in the development cycle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lack of discoverability and reusability&lt;/strong&gt;: Nobody knows what code already exists, so everyone rebuilds it. Duplication becomes the norm.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developer toil and context switching&lt;/strong&gt;: Developers spend more time on environment setup and troubleshooting than on writing features.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These inefficiencies add up, creating significant friction in the developer workflow. Developers spend more time wrestling with processes and less time focused on building and innovating. A Platform approach can help solve these challenges.&lt;/p&gt;
&lt;img align="left" style="margin: 15px;" width="300px" src="security.png"&gt;
&lt;h3 id="problem-security-as-a-bottleneck-and-source-of-friction"&gt;&lt;strong&gt;Problem: Security as a bottleneck and source of friction&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Speed and efficiency matter, but security can&amp;rsquo;t be compromised. Traditionally, security acts as a gate – a necessary hurdle before releasing software. Platform Engineering aims to transform security from a bottleneck into an enabler.&lt;/p&gt;
&lt;p&gt;For many developers, security feels like a roadblock, leading to common friction points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Last-minute security&lt;/strong&gt;: Checks happen at the end of development, causing costly rework when issues are found.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restrictive policies&lt;/strong&gt;: Security rules feel arbitrary and unclear, slowing down deployments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The &amp;ldquo;No&amp;rdquo; department&lt;/strong&gt;: Security teams are seen as blockers who enforce policies without offering solutions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speed vs. security mindset&lt;/strong&gt;: Everyone believes you must choose between going fast and being secure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security is &amp;ldquo;Someone else&amp;rsquo;s job&amp;rdquo;&lt;/strong&gt;: Developers think security is only the security team&amp;rsquo;s responsibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This &amp;ldquo;security as a gate&amp;rdquo; approach not only slows things down but leads to workarounds as developers try to bypass security to meet deadlines.&lt;/p&gt;
&lt;p&gt;By integrating security into your platform, you transform security from a gatekeeper into a built-in feature of the development process. Security becomes an enabler of trust and speed, letting developers innovate with confidence.&lt;/p&gt;
&lt;img align="right" style="margin: 15px;" width="300px" src="observability.png"&gt;
&lt;h3 id="problem-data-overload-without-insights"&gt;&lt;strong&gt;Problem: Data overload without insights&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Developers in modern cloud environments often find themselves in a paradox: they are drowning in data, yet starving for actionable information. Monitoring systems pump out metrics, logs, and traces, but finding what matters feels impossible. An ideal internal developer platform shifts the focus from data collection to actionable insights.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what developers typically experience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tool sprawl&lt;/strong&gt;: Teams use different tools for metrics, logs, and traces. Developers waste time jumping between dashboards and manually connecting the dots.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alert noise&lt;/strong&gt;: Developers get bombarded with alerts lacking context or clear next steps. Important signals get buried in the noise.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dashboard overload&lt;/strong&gt;: Existing dashboards overwhelm developers with granular metrics that are hard to connect to application behavior.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reactive debugging&lt;/strong&gt;: Troubleshooting becomes a time-consuming fire drill. Developers spend hours sifting through logs to pinpoint issues.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Missing proactive insights&lt;/strong&gt;: Observability is only used for firefighting. Developers lack insights to optimize performance or prevent issues before they affect users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disconnected from production&lt;/strong&gt;: Many developers feel blind to how their code actually runs in production, limiting their ability to improve it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This data flood without clear insights leaves developers reactive rather than proactive, hampering their ability to build reliable applications.&lt;/p&gt;
&lt;p&gt;By improving observability in your platform, you transform it from an operations function into a developer superpower. Developers gain the insights they need to build better applications with greater confidence, using AI to focus on what truly matters.&lt;/p&gt;
&lt;img align="left" style="margin: 15px;" width="300px" src="goverance.png"&gt;
&lt;h3 id="problem-balancing-autonomy-with-control-and-cost-efficiency"&gt;&lt;strong&gt;Problem: Balancing autonomy with control and cost efficiency&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Empowering developers with self-service is essential, but unchecked autonomy leads to chaos. As platform adoption grows, organizations need to maintain control without creating bottlenecks. This is where Governance as Code becomes critical, establishing guardrails while preserving speed.&lt;/p&gt;
&lt;p&gt;Self-service creates new challenges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Configuration drift&lt;/strong&gt;: In decentralized environments, infrastructure setups diverge from standards, creating security risks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud cost explosion&lt;/strong&gt;: Without proper controls, self-service can lead to wasted resources and budget overruns. Teams over-provision or forget to clean up unused environments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compliance headaches&lt;/strong&gt;: Meeting regulatory requirements becomes harder when infrastructure is created in an uncontrolled way.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audit gaps&lt;/strong&gt;: Without clear governance, tracking who created what and when becomes nearly impossible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manual governance slows everything&lt;/strong&gt;: If governance relies on approvals and tickets, it defeats the purpose of self-service.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These challenges highlight the need for automated governance that scales with your platform, ensuring control without slowing developers down.&lt;/p&gt;
&lt;p&gt;By implementing Governance as Code, you ensure that self-service doesn&amp;rsquo;t conflict with security, compliance, and cost efficiency. Governance becomes an automated part of your platform, enabling responsible scaling.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;These six challenges represent the core obstacles standing between your organization and true developer velocity. When properly addressed, each transforms into a capability that empowers developers and accelerates innovation.&lt;/p&gt;
&lt;p&gt;The upcoming articles in this series will explore each area in depth, with practical strategies and real-world examples to help you build an effective internal developer platform.&lt;/p&gt;
&lt;p&gt;Ready to implement these principles in your organization? Check out &amp;ldquo;Platform Engineering: Recommended Practices for Infrastructure as Code&amp;rdquo;. It provides detailed guidance on building scalable internal developer platforms.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to structure infrastructure code for scalability&lt;/li&gt;
&lt;li&gt;Managing development environments with developer stacks and Git branches&lt;/li&gt;
&lt;li&gt;Designing modular and reusable Pulumi projects&lt;/li&gt;
&lt;li&gt;Implementing cross-stack dependencies with stack references&lt;/li&gt;
&lt;li&gt;Setting up RBAC, security, and governance at scale&lt;/li&gt;
&lt;li&gt;Automating infrastructure management with stack orchestration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://info.pulumi.com/ebook/platform-engineering-iac-recommended-practices"&gt;&lt;strong&gt;Get the Free Platform Engineering Ebook →&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And don&amp;rsquo;t miss the next article in this series, where we&amp;rsquo;ll explore provisioning as the foundation of your developer platform journey.&lt;/p&gt;</description><author>Adam Gordon Bell</author><category>platform-engineering</category></item><item><title>Integrating DevOps and Security in Platform Engineering</title><link>https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/</link><pubDate>Wed, 11 Dec 2024 07:41:06 +0000</pubDate><guid>https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/integrating-devops-and-security-for-scalable-platform-engineering/index.png" /&gt;
&lt;p&gt;Platform engineering has become essential for mid-to-large organizations, moving beyond a DevOps trend. Gartner predicts that by 2026, 80% of software companies will have internal platform services to streamline development. The goal is to empower developers with self-service tools while maintaining security, compliance, and reliability through DevSecOps practices.&lt;/p&gt;
&lt;p&gt;At PulumiUP Europe 2024, experts shared insights on aligning DevOps with security to build scalable, secure platforms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Jess Mink, Sr. Director of Platform Engineering at Honeycomb&lt;/li&gt;
&lt;li&gt;Kief Morris, Global Head of Infrastructure Engineering at ThoughtWorks&lt;/li&gt;
&lt;li&gt;Lindsay Jack, VP of Engineering &amp;amp; Security at Snyk&lt;/li&gt;
&lt;li&gt;Nariman Aga-Tagiyev, Application Security Architect at WiseFrog Security&lt;/li&gt;
&lt;li&gt;Komal Ali, Engineering Manager at Pulumi&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The panel discussed key strategies, challenges, and pillars of successful platform engineering.&lt;/p&gt;
&lt;h2 id="in-this-article"&gt;In this article:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#the-core-pillars-of-platform-engineering"&gt;The Core Pillars of Platform Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#aligning-devops-and-security-for-secure-platform-engineering"&gt;Aligning DevOps and Security for Secure Platform Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#shift-left-security"&gt;Shift Left Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#embrace-automation-and-standardization"&gt;Embrace Automation and Standardization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#prioritize-observability-and-monitoring"&gt;Prioritize Observability and Monitoring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#foster-a-culture-of-collaboration"&gt;Foster a Culture of Collaboration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#challenges-of-integrating-security-in-platform-engineering"&gt;Challenges of Integrating Security in Platform Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#balancing-autonomy-and-control"&gt;Balancing Autonomy and Control&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#driving-adoption-and-changing-mindsets"&gt;Driving Adoption and Changing Mindsets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#adapting-to-evolving-needs-and-technologies"&gt;Adapting to Evolving Needs and Technologies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#measuring-success-in-secure-platform-engineering"&gt;Measuring Success in Secure Platform Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#the-future-of-secure-platform-engineering"&gt;The Future of Secure Platform Engineering&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-core-pillars-of-platform-engineering"&gt;The Core Pillars of Platform Engineering&lt;/h2&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/WUpyqn1Jfwg?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices/"&gt;Platform engineering teams&lt;/a&gt; comprise multiple professionals with many responsibilities and focus areas. According to our panel of experts, the core pillars of platform engineering include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/"&gt;Developer Experience (DevEx)&lt;/a&gt;&lt;/strong&gt;: Provide developers with the tools, frameworks, and abstractions they need to be productive and proactive without getting stuck in infrastructure or operational concerns.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#an-effective-internal-developer-platform"&gt;Reliability and Scalability&lt;/a&gt;&lt;/strong&gt;: Ensure that the platform and infrastructure can support the organization&amp;rsquo;s needs, with the ability to scale up or down as required.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/"&gt;Security and Compliance&lt;/a&gt;&lt;/strong&gt;: Embed robust, accessible security and compliance frameworks into the development lifecycle while making it easy for developers to adhere to these policies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/automation-api/"&gt;Automation and Tooling&lt;/a&gt;&lt;/strong&gt;: Leverage &lt;a href="https://www.pulumi.com/product/infrastructure-as-code/"&gt;Infrastructure as Code (IaC)&lt;/a&gt; and automation to enforce standardized processes and consistency and reduce cognitive load and manual effort.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;Observability and Monitoring&lt;/a&gt;&lt;/strong&gt;: Provide visibility into the platform&amp;rsquo;s health and performance, delivering actionable insights that allow teams to identify and resolve issues quickly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These pillars work together to create a platform that empowers developers to innovate and deliver value to the organization and customers while maintaining the necessary controls and safeguards.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;As Jess Mink, Director of Platform Engineering at &lt;a href="https://www.pulumi.com/blog/observability-with-infrastructure-as-code/"&gt;Honeycomb&lt;/a&gt;, explains:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;The goal of platform engineering is to help the company run smoother and faster and unlock things people didn&amp;rsquo;t know were possible [&amp;hellip;] We tend to focus on tools and software, but it&amp;rsquo;s really about people, processes, and tools. If you consider this, platforms are responsible for social and technical support across the organization. A common pitfall is building tools no one uses because you didn’t meet people where they are.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="aligning-devops-and-security-for-secure-platform-engineering"&gt;Aligning DevOps and Security for Secure Platform Engineering&lt;/h2&gt;
&lt;p&gt;Integrating security into platform engineering ensures it becomes a proactive part of the development lifecycle and ensures that &amp;ldquo;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/"&gt;DevSecOps&lt;/a&gt;&amp;rdquo; is not an afterthought but a core consideration.&lt;/p&gt;
&lt;p&gt;Key best practices shared by the panel include:&lt;/p&gt;
&lt;h3 id="shift-left-security"&gt;Shift Left Security&lt;/h3&gt;
&lt;p&gt;One of the fundamental principles of DevSecOps is to &amp;ldquo;shift left&amp;rdquo; - that is, to integrate security earlier in the development process rather than waiting until the end. This can involve activities such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Incorporating security requirements and threat modeling into the initial design phase&lt;/li&gt;
&lt;li&gt;Automating security scans and tests as part of the continuous integration (CI) pipeline&lt;/li&gt;
&lt;li&gt;Providing developers with secure coding guidelines and tools to &lt;a href="https://www.pulumi.com/blog/drift-detection/#why-pulumi-cloud-drift-detection-and-remediation"&gt;identify and remediate vulnerabilities&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By addressing security concerns upfront, organizations can reduce the time and cost of remediating issues later in the development lifecycle.&lt;/p&gt;
&lt;h3 id="embrace-automation-and-standardization"&gt;Embrace Automation and Standardization&lt;/h3&gt;
&lt;p&gt;Consistency is key. Platform engineering teams should leverage automation and built-in safeguards and security processes. This may include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automating the provisioning of secure infrastructure and application environments&lt;/li&gt;
&lt;li&gt;Implementing Infrastructure as Code (IaC) to define and &lt;a href="https://www.pulumi.com/blog/pulumi-is-imperative-declarative-imperative/"&gt;manage infrastructure in a declarative&lt;/a&gt;, version-controlled manner&lt;/li&gt;
&lt;li&gt;Standardizing security controls, policies, and configurations across the platform&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By automating these tasks, platform engineering teams can reduce the risk of human error, improve visibility and auditability, and free up developers to focus on building features rather than managing infrastructure.&lt;/p&gt;
&lt;h3 id="prioritize-observability-and-monitoring"&gt;Prioritize Observability and Monitoring&lt;/h3&gt;
&lt;p&gt;Effective security requires visibility into the health and performance of the platform. Platform engineering teams should invest in robust observability and monitoring solutions to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/drift-detection/"&gt;Detect and respond&lt;/a&gt; to security incidents and anomalies in real-time&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;Gain insights&lt;/a&gt; into the behavior and usage patterns of the platform&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#policy-enforcement-ensuring-compliance-and-security"&gt;Identify and address&lt;/a&gt; vulnerabilities or misconfigurations proactively&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By integrating security-focused monitoring and alerting into the platform, organizations can quickly identify and mitigate threats while also providing developers with the necessary context to understand and address security-related issues.&lt;/p&gt;
&lt;h3 id="foster-a-culture-of-collaboration"&gt;Foster a Culture of Collaboration&lt;/h3&gt;
&lt;p&gt;Platform engineering is often referred to as being the practical application of DevOps practices. Integrating security practices often requires a cultural shift towards collaboration and shared responsibility between all teams in development, operations, and security, thus the name DevSecOps. Platform engineering teams can facilitate this by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Treating &lt;a href="https://www.pulumi.com/blog/platform-engineering-cncf-maturity-model/#platforms-as-products-driving-success"&gt;Platforms as Products&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Involving security stakeholders in the design and planning of platform initiatives&lt;/li&gt;
&lt;li&gt;Providing security training and education to developers to empower them to make informed decisions&lt;/li&gt;
&lt;li&gt;Establishing communication channels and feedback loops between teams&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;As Kief Morris, Global Head of Infrastructure Engineering at &lt;a href="https://www.thoughtworks.com/en-us"&gt;ThoughtWorks&lt;/a&gt;, explains:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;There is a new way of thinking that is trying to avoid that &amp;ldquo;build it, and they will come mentality,&amp;rdquo; which leads to building it and nobody using it. One of the trends we are seeing is product thinking [&amp;hellip;]—using techniques like creating user personas of different types of users in the organization, conducting research to understand their needs, and talking with them.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Breaking silos and fostering communication helps organizations build secure, scalable platforms that support the needs of developers, platform engineers, architects, and security teams.&lt;/p&gt;
&lt;h2 id="challenges-of-integrating-security-in-platform-engineering"&gt;Challenges of Integrating Security in Platform Engineering&lt;/h2&gt;
&lt;p&gt;While the benefits of integrating DevOps and security in platform engineering are clear, the journey has expected challenges. Our panel of experts highlighted several key obstacles that organizations may face:&lt;/p&gt;
&lt;h3 id="balancing-autonomy-and-control"&gt;Balancing Autonomy and Control&lt;/h3&gt;
&lt;p&gt;The primary goal is to empower developers to be more productive and proactive. However, this autonomy needs to be balanced with necessary security controls and governance measures.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;Jess Mink points out the importance of achieving harmony between developer autonomy and operational control, stating:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;It&amp;rsquo;s a delicate balance - you want to make things easy for developers, but you also need to maintain the right level of control and security. It&amp;rsquo;s about finding the right abstractions and interfaces that give developers the freedom they need while still ensuring the platform remains secure and compliant.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="driving-adoption-and-changing-mindsets"&gt;Driving Adoption and Changing Mindsets&lt;/h3&gt;
&lt;p&gt;Integrating security into the platform engineering workflow can often be met with resistance from developers accustomed to moving quickly and may view security as an obstacle to their productivity.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;As Nariman, a Software Security Architect, notes:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;The challenge is not just about the tools or the technology - it&amp;rsquo;s about changing the mindset and getting people to understand the importance of security. You need to find ways to motivate developers and make them feel like they&amp;rsquo;re part of the solution rather than just imposing more rules and processes.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Effective communication, education, and a focus on the business value of security are key to driving adoption and fostering a culture of shared responsibility.&lt;/p&gt;
&lt;h3 id="adapting-to-evolving-needs-and-technologies"&gt;Adapting to Evolving Needs and Technologies&lt;/h3&gt;
&lt;p&gt;As organizations grow and their technology stacks evolve, the demands on the platform engineering team can shift rapidly. Keeping up with these changes, while maintaining a secure and reliable platform, can be a significant challenge.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;Lindsay Jack, VP of Engineering for the Platform Division at &lt;a href="https://partners.snyk.io/English/solutions/solution/2908/pulumi"&gt;Snyk&lt;/a&gt;, explains:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;You might have a platform team that&amp;rsquo;s really good at a certain set of technologies, but then the organization starts moving in a new direction, and suddenly those skills don&amp;rsquo;t match up anymore. It&amp;rsquo;s about being agile and adaptable and making sure you have the right mix of skills and expertise to support the organization&amp;rsquo;s evolving needs&lt;/em&gt;.&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Fostering internal mobility, continuous learning, and a flexible, modular platform architecture can help platform engineering teams navigate these changes more effectively.&lt;/p&gt;
&lt;h2 id="measuring-success-in-secure-platform-engineering"&gt;Measuring Success in Secure Platform Engineering&lt;/h2&gt;
&lt;p&gt;Measuring the success of a platform engineering initiative can be complex as it involves balancing a range of technical, operational, and business-oriented metrics but also considers human factors. According to our panel, some key metrics to include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Developer Experience&lt;/strong&gt;: Metrics such as developer satisfaction surveys, time-to-onboard new developers, and the number of self-service platform capabilities can provide insights into the effectiveness of the platform in supporting developer productivity and autonomy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reliability and Scalability&lt;/strong&gt;: Monitoring service-level objectives (SLOs), incident response times, and the ability to handle increased traffic or user demands can help assess the platform&amp;rsquo;s reliability and scalability.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security and Compliance&lt;/strong&gt;: Tracking the number of security incidents, the ratio of security issues found during threat modeling versus post-deployment, and the adoption of security best practices can indicate the platform&amp;rsquo;s security posture.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation and Tooling&lt;/strong&gt;: Metrics like the percentage of infrastructure provisioned through code, the frequency of platform updates, and the time saved through automation can demonstrate the platform&amp;rsquo;s operational efficiency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability and Monitoring&lt;/strong&gt;: Measuring the effectiveness of observability tools, the time to detect and resolve issues, and the quality of incident reports can &lt;a href="https://www.pulumi.com/blog/insights-cloud-account-discovery/"&gt;provide insights into the platform&amp;rsquo;s overall health&lt;/a&gt; and performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;As Jess Mink emphasizes, it&amp;rsquo;s important not just to collect these metrics but to use them to drive meaningful action and improvement:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;We look at all of those [metric categories] every quarter and write summaries that go up to the executive level. This creates visibility and a shared understanding of problems so that there&amp;rsquo;s room for movement and change in the right ways.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="the-future-of-secure-platform-engineering"&gt;The Future of Secure Platform Engineering&lt;/h2&gt;
&lt;p&gt;Software development and infrastructure management are evolving, and the role of platform engineering will only become more critical to support it. By integrating DevOps and security practices, platform engineering teams can create scalable, secure platforms that empower developers to be more productive and innovate, delivering business value.&lt;/p&gt;
&lt;p&gt;Learn how Pulumi customers build secure, scalable platforms and empower their development teams:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tivity Health&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/"&gt;DevSecOps Game-Changer: Security Automation That Delivers Business Results&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BMW Group&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/"&gt;Unified and Programmatic Approach to Infrastructure Management at BMW Using Pulumi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lemonade&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/case-studies/lemonade/"&gt;How the DevOps team supports a much larger group of developers&lt;/a&gt; using by Pulumi to standardize infrastructure components and enforce best practices.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Discover platform engineering best practices in &lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices/"&gt;The Guide to Platform Engineering: 7 Steps to Get It Right&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Build secure, scalable platforms with confidence—get started with the &lt;a href="https://info.pulumi.com/platform-engineering-workshop-series"&gt;Platform Engineering Workshop Series &amp;amp; Course&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;</description><author>Sara Huddleston</author><category>devsecops</category><category>platform-engineering</category><category>developer-experience</category><category>devops</category><category>security</category></item><item><title>Why Every Platform Engineer Should Care About Kubernetes Operators</title><link>https://www.pulumi.com/blog/why-every-platform-engineer-should-care-about-kubernetes-operators/</link><pubDate>Tue, 10 Dec 2024 09:31:38 +0100</pubDate><guid>https://www.pulumi.com/blog/why-every-platform-engineer-should-care-about-kubernetes-operators/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/why-every-platform-engineer-should-care-about-kubernetes-operators/index.png" /&gt;
&lt;p&gt;In one of my recent talks, I mentioned that the foundation of a successful &lt;a href="https://www.pulumi.com/kubernetes"&gt;Kubernetes&lt;/a&gt;-powered platform is the use of &lt;a href="https://kubernetes.io/docs/concepts/extend-kubernetes/operator/"&gt;Kubernetes Operators&lt;/a&gt;, as they are a great way to automate operational tasks and the lifecycle of complex applications and services on Kubernetes.&lt;/p&gt;
&lt;p&gt;In case you missed the talk, here is the link to the recording:&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/vKNsVQjonqM?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;After the talk, I received feedback from the audience that they would like to have more information about Kubernetes operators and some of the advanced operators I would recommend to use in their Kubernetes-powered platforms. And who am I to reject such a great opportunity to share my knowledge with the community?&lt;/p&gt;
&lt;p&gt;As you guess, the base for a Kubernetes Operator is, well, Kubernetes. So, if you are not familiar with Kubernetes, let me give you a brief introduction. Kubernetes, or K8s in short, is by far the most powerful open-source container orchestration platform out there - especially for its capability to maintain a desired state. This means you, as the platform admin, can define how you want your cluster and the workload on top of it to look, and Kubernetes (aka the control plane) executes the necessary steps to ensure the desired state is achieved using a feedback loop.&lt;/p&gt;
&lt;p&gt;And how does Kubernetes achieve this complex operational task management? Kubernetes leverages the concept of controllers and operators. Both ensure that the cluster resources are in the desired state. But why is there a distinction between controllers and operators inside the Kubernetes ecosystem? There is also great confusion when folks talk about controllers and operators, as the differences are in the details and operators are a subcategory of controllers.&lt;/p&gt;
&lt;h2 id="kubernetes-controllers-vs-operators"&gt;Kubernetes Controllers vs. Operators&lt;/h2&gt;
&lt;p&gt;&lt;img src="loop.png" alt="loop.png"&gt;&lt;/p&gt;
&lt;p&gt;K8s controllers are control loops that watch your resources and reconcile the current state with the desired state in a continuous loop. Think about how a thermostat works in your house. The thermostat watches the current temperature and, if it is below the desired temperature, it turns on the heating. If it is above the desired temperature, it turns off the heating. This is how a controller works in Kubernetes - it watches the resources and conditions defined in the desired state and executes the necessary steps to make sure the current state matches the desired state.&lt;/p&gt;
&lt;p&gt;Here are some typical Kubernetes controller key functions as part of the maintain, observe, and enforce loop of the control loop:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rollouts and Rollbacks&lt;/td&gt;
&lt;td&gt;Deployment controller takes care of rolling out new versions of your application and rolling back to the previous version in case of failure.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cluster maintenance&lt;/td&gt;
&lt;td&gt;Node controller watches the nodes in the cluster and makes sure that the nodes are in the desired state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Event handling&lt;/td&gt;
&lt;td&gt;Event controller watches for events and takes action based on the events.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schedule&lt;/td&gt;
&lt;td&gt;Controller to run jobs and cron jobs at a specific time.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource enforcement&lt;/td&gt;
&lt;td&gt;Resource controller watches the resource usage and enforces resource limits in a namespace.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State enforcement&lt;/td&gt;
&lt;td&gt;Different controllers watch the state of the resources and enforce the desired state.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As you can see, controllers automate the routine operational tasks, enforce policies, handle failures and take actions to continuously maintain the desired state of the cluster.&lt;/p&gt;
&lt;p&gt;Some of the typical use cases for controllers are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Limit resource usage&lt;/strong&gt; - Prevent the overload of the cluster by enforcing resource limits with controllers like ResourceQuota.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto-scaling&lt;/strong&gt; - Automatically scales the number of pods based on the different metrics with HorizontalPodAutoscaler.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Task scheduling&lt;/strong&gt; - Run jobs and cron jobs at a specific time with Job and CronJob controllers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Run stateful workloads&lt;/strong&gt; - Deploy and manage stateful workloads like databases with StatefulSet controller, by ensuring that the pods are created in a specific order and have a stable network identity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scaling deployments&lt;/strong&gt; - Deploy and manage stateless workloads like web applications with the Deployment controller, by ensuring that the desired number of pods is running and handling the rolling updates and rollbacks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Controllers, as you see, reduce the manual effort for the platform engineering teams and gives the cluster self-managing
capabilities.&lt;/p&gt;
&lt;p&gt;With all the above points, the benefits of controllers are clear - Let me list some of the main ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automation&lt;/strong&gt; - Controllers automate the routine operational tasks and enforce policies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Availability&lt;/strong&gt; - Controllers ensure that the resources are always available, addressing failures and taking actions to maintain the desired state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Efficiency&lt;/strong&gt; - Controllers provide an efficient way to manage the resources and workloads in the cluster with quota management and auto-scaling.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reliability&lt;/strong&gt; - Controllers help to make workload management more reliable with features like replica management, &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/api-docs/core/v1/pod/"&gt;pod&lt;/a&gt; creation and deletion, and scheduling.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexibility&lt;/strong&gt; - Controllers provide a flexible way to handle a variety of workloads and resources in the cluster, such as &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/api-docs/apps/v1/daemonset/"&gt;DaemonSet&lt;/a&gt;, &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/api-docs/apps/v1/statefulset/"&gt;StatefulSet&lt;/a&gt;, &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/api-docs/batch/v1/job/"&gt;jobs&lt;/a&gt;, &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/api-docs/batch/v1/cronjob/"&gt;cron jobs&lt;/a&gt;, &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/api-docs/apps/v1/deployment/"&gt;deployments&lt;/a&gt;, and &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/api-docs/core/v1/service/"&gt;services&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability&lt;/strong&gt; - Controllers provide a view into the cluster resources and the state of the resources via the &lt;a href="https://www.pulumi.com/blog/yaml-terraform-pulumi-whats-the-smart-choice-for-deployment-automation-with-kubernetes/#kubernetes-components-and-the-kubernetes-api"&gt;Kubernetes API&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With Controllers explained, let&amp;rsquo;s move on to the next level of automation in Kubernetes and talk about Kubernetes Operators.&lt;/p&gt;
&lt;h2 id="kubernetes-operators"&gt;Kubernetes Operators&lt;/h2&gt;
&lt;p&gt;As mentioned before, Kubernetes Operators are a subcategory of controllers that use API extensions (Custom Resource) to complete the automation task. Operators are a set of independent controllers, with each controller responsible for its own task. And while controllers can share similar functions with a controller, it is only focused on one domain and only uses Custom Resources to manage the domain.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Keep in mind that controllers work without the need for custom resources or a link to a specific domain.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Operators are custom-built controllers that focus on the deployment, management, and operation of a specific application or service. Some key functions of operators include:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;Operators integrate security best practices and policies, such as encryption, access control, and &lt;a href="https://www.pulumi.com/what-is/what-is-secrets-management/"&gt;secret management&lt;/a&gt;, to protect the application. You can customize these measures and adjust them to the specific needs of the application.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workload Lifecycle management&lt;/td&gt;
&lt;td&gt;Operators manages the full lifecycle of complex stateful applications through deployment, upgrades, and scaling. It even applies logic to automate operations like backup and restore.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error Handling&lt;/td&gt;
&lt;td&gt;Operators detects and handles errors, such as application crashes, network failures, and resource constraints.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Migration&lt;/td&gt;
&lt;td&gt;Operators help to migrate the application to a new version, a new cluster, or a new cloud provider.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disaster Recovery&lt;/td&gt;
&lt;td&gt;Operators help to recover the application from a disaster, such as data loss, network failure, or hardware failure.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Operators are a great way to encode the operational knowledge of the platform engineering team into automated controllers. This way, the platform engineering team can focus on the strategic tasks and let the operators handle the boring routine operational tasks. This reduces the manual effort and increases the reliability of the platform.&lt;/p&gt;
&lt;p&gt;Some of the typical use cases for operators are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Database management&lt;/strong&gt; - Deploy and manage databases such as MySQL, PostgreSQL, and MongoDB.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage management&lt;/strong&gt; - Deploy and manage storage such as Ceph, GlusterFS, or NFS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logging and monitoring&lt;/strong&gt; - Simplify the deployment and management of logging and monitoring solutions like Prometheus, Grafana, or ELK stack.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI/CD&lt;/strong&gt; - Automate the deployment and management of CI/CD pipelines like Jenkins, GitLab, or Tekton. - Backup and restore - Automate the backup and restore of applications and data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Messaging and event streaming&lt;/strong&gt; - Simplify the deployment and management of messaging and event streaming solutions like Kafka, RabbitMQ, or NATS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Machine learning&lt;/strong&gt; - Automate the deployment and management of machine learning workloads such as TensorFlow, PyTorch, or Kubeflow.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the applications-centric approach provided by operators, the platform engineering team can now enable fully automated operations while enhancing the reliability, efficiency, and observability of the platform and ensuring adherence to best practices and compliance requirements.&lt;/p&gt;
&lt;p&gt;And similar to controllers, operators also have distinct benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Simplification&lt;/strong&gt; - Operators simplify the deployment and management of complex applications and services by providing a declarative way (via Custom Resources).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Higher Productivity&lt;/strong&gt; - Operators increase the productivity of the platform engineering team by automating the routine operational tasks and allowing users to focus on delivering business value.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extensibility&lt;/strong&gt; - Extending the K8s API with Custom Resource Definitions (CRDs) allows administrators to support new applications and services without changing the core Kubernetes code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consistency&lt;/strong&gt; - Operators ensure that they deploy and run the applications and services consistently across different environments, such as on-premises, cloud, or hybrid.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modularity&lt;/strong&gt; - Operators are modular and focused on a specific domain.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Legacy&lt;/strong&gt; Transformation - Operators help to transform legacy applications into cloud-native applications by automating the deployment and management of complex applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is a visual representation of a Kubernetes Operator in action, which I found very nice and helpful:&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/why-every-platform-engineer-should-care-about-kubernetes-operators/operator.png"
alt="Kubernetes Operators: what are they? Some examples Credit: SparkFabrik" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;Kubernetes Operators: what are they? Some examples Credit: SparkFabrik&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="comparison-of-kubernetes-controllers-and-operators"&gt;Comparison of Kubernetes Controllers and Operators&lt;/h2&gt;
&lt;p&gt;Here is a quick summary of the differences between Kubernetes controllers and operators:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Kubernetes Controllers&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Kubernetes Operators&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Definition&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Core control loops within Kubernetes that reconcile the current state with the desired state of resources.&lt;/td&gt;
&lt;td&gt;Custom-built controllers with domain-specific logic, typically extending Kubernetes API with Custom Resource Definitions (CRDs).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;General-purpose automation for cluster-wide resource management and workload operations.&lt;/td&gt;
&lt;td&gt;Focused on application or service-specific lifecycle management and operations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom Resources (CRDs)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not mandatory. Most controllers work with built-in Kubernetes resources like Pods, Deployments, and StatefulSets.&lt;/td&gt;
&lt;td&gt;Mandatory. Operators depend on CRDs to define and manage application-specific resources.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Domain-Specific Logic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited. Primarily focuses on generic Kubernetes operations like scheduling, scaling, and resource enforcement.&lt;/td&gt;
&lt;td&gt;Extensive. Includes application-specific tasks such as backups, upgrades, migrations, and disaster recovery.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Automation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automates operational tasks like resource scheduling, scaling, and maintaining cluster states.&lt;/td&gt;
&lt;td&gt;Automates both operational and domain-specific tasks, often encoding deep operational knowledge of specific applications.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Relatively low complexity as they focus on Kubernetes-native workflows.&lt;/td&gt;
&lt;td&gt;Higher complexity due to domain-specific implementations and integrations with external systems.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provides insight into cluster resource states via Kubernetes API and built-in events.&lt;/td&gt;
&lt;td&gt;Enhances observability with application-specific metrics, logs, and health checks tailored to the managed application.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;- Pod scaling (e.g., HPA) &lt;br&gt; - Resource enforcement (e.g., ResourceQuota) &lt;br&gt; - Rolling updates and rollbacks &lt;br&gt; - Scheduling jobs (e.g., CronJob).&lt;/td&gt;
&lt;td&gt;- Database management (e.g., MySQL Operator) &lt;br&gt; - CI/CD pipelines (e.g., Tekton) &lt;br&gt; - Backup and restore &lt;br&gt; - Monitoring solutions (e.g., Prometheus Operator) &lt;br&gt; - Stateful applications (e.g., Kafka Operator).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Part of Kubernetes core components or extensions like kube-controller-manager.&lt;/td&gt;
&lt;td&gt;External tools developed by vendors, community, or in-house, deployed using Custom Resources.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Benefits&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;- Cluster-wide automation &lt;br&gt; - Ensures resource availability &lt;br&gt; - Efficient and reliable workload management.&lt;/td&gt;
&lt;td&gt;- Simplifies application lifecycle management &lt;br&gt; - Increases productivity with domain-specific automation &lt;br&gt; - Consistent deployments across environments.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Flexible for general Kubernetes operations but limited to built-in resources.&lt;/td&gt;
&lt;td&gt;Highly flexible and extensible for custom applications and domain-specific requirements.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Target Audience&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Platform administrators and Kubernetes users looking to automate Kubernetes-native workflows.&lt;/td&gt;
&lt;td&gt;Developers and platform engineers needing advanced automation and lifecycle management for specific applications or services.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maintenance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed and updated by Kubernetes core or community projects.&lt;/td&gt;
&lt;td&gt;Requires domain-specific knowledge and regular updates to accommodate application changes and best practices.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;With this detailed explanation of Kubernetes controllers and operators, I would like to share some advanced Kubernetes operators that I recommend for use in your Kubernetes-powered platform.&lt;/p&gt;
&lt;h2 id="advanced-kubernetes-operators"&gt;Advanced Kubernetes Operators&lt;/h2&gt;
&lt;p&gt;As we have seen, Kubernetes Operators are the go-to way to automate operational tasks and lifecycle management. I should mention that not all operators are created equal. Some operators are more advanced and provide more features than others. That is why, for example, &lt;a href="https://operatorhub.io/"&gt;OperatorHub.io&lt;/a&gt; categorises operators into &lt;a href="https://sdk.operatorframework.io/docs/overview/operator-capabilities/"&gt;five capability levels&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Basic Install&lt;/strong&gt; - Installs the application on the cluster.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seamless Upgrades&lt;/strong&gt; - Manages Application upgrades.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full Lifecycle Management&lt;/strong&gt; - Manages the full lifecycle of the application.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deep Insights&lt;/strong&gt; - Provides monitoring and metrics.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto Pilot&lt;/strong&gt; - Automatically optimizes and tunes the application.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The more advanced the operator, the more features it provides and the more automation it offers. At its most advanced level, the Auto Pilot, the operator automatically optimizes and tunes the application based on the workload and environment.&lt;/p&gt;
&lt;p&gt;Here is a list of advanced Kubernetes operators that I recommend using in your Kubernetes-powered platform:&lt;/p&gt;
&lt;h3 id="cloudnativepg-operator"&gt;CloudNativePG Operator&lt;/h3&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/why-every-platform-engineer-should-care-about-kubernetes-operators/cloudnativepg.png"
alt="CloudNativePG Operator Credit: cloudnative-pg.io" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;CloudNativePG Operator Credit: cloudnative-pg.io&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href="https://cloudnative-pg.io/"&gt;CloudNativePG Operator&lt;/a&gt; is a PostgreSQL operator that covers the full lifecycle of PostgreSQL databases on Kubernetes. It simplifies the deployment, management, and scaling of PostgreSQL databases by providing a declarative way to define and manage PostgreSQL clusters using custom resources.&lt;/p&gt;
&lt;p&gt;Some of the key features of CloudNativePG Operator are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automated Backups&lt;/strong&gt; - Schedule and manage backups of PostgreSQL databases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High Availability&lt;/strong&gt; - Deploy and manage high-availability PostgreSQL clusters.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scaling&lt;/strong&gt; - Scale the number of PostgreSQL instances based on the workload.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="installation"&gt;Installation&lt;/h4&gt;
&lt;p&gt;Either use the Helm chart or the Kubernetes manifests to deploy the CloudNativePG Operator:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm repo add cloudnative-pg https://cloudnative-pg.io/charts/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm repo update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm upgrade --install cloudnativepg cloudnative-pg/cloudnative-pg --namespace cnpg-system --create-namespace
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or use Pulumi to deploy the CloudNativePG Operator:&lt;/p&gt;
&lt;div&gt;
&lt;pulumi-chooser type="language" options="typescript,javascript,python,go,csharp" mode=""&gt;&lt;/pulumi-chooser&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="typescript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8shelm&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes/helm/v3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cnpg-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;cnpg-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8shelm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cloudnativepg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;oci://ghcr.io/cloudnative-pg/charts/cloudnative-pg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;createNamespace&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="javascript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="python" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;k8s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes.helm.v3&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;k8shelm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes.meta.v1&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;meta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;cnpg-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cnpg-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8shelm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;cloudnativepg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;oci://ghcr.io/cloudnative-pg/charts/cloudnative-pg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;create_namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="go" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apiextensions&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/helm/v3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi/sdk/v3/go/pulumi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewNamespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cnpg-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NamespaceArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cnpg-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewRelease&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cloudnativepg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReleaseArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;oci://ghcr.io/cloudnative-pg/charts/cloudnative-pg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Elem&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CreateNamespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="csharp" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Meta.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyStack&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cnpg-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NamespaceArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;cnpg-system&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cloudnativepg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ReleaseArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Chart&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oci://ghcr.io/cloudnative-pg/charts/cloudnative-pg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;CreateNamespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;h4 id="usage"&gt;Usage&lt;/h4&gt;
&lt;p&gt;Here is a simple example of a PostgreSQL cluster with backup configured on S3 API-compatible storage:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;postgresql.cnpg.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Cluster&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;cluster-example-with-backup&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;primaryUpdateStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;unsupervised&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Persistent storage configuration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;storageClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;standard&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Backup properties&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# This assumes a local minio setup&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;backup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;barmanObjectStore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;destinationPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;s3://backups/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;endpointURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;http://minio:9000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;s3Credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;accessKeyId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;minio&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ACCESS_KEY_ID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;secretAccessKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;minio&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ACCESS_SECRET_KEY&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;wal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;compression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;gzip&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or use Pulumi:&lt;/p&gt;
&lt;div&gt;
&lt;pulumi-chooser type="language" options="typescript,javascript,python,go,csharp" mode=""&gt;&lt;/pulumi-chooser&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="typescript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiextensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cluster-example-with-backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;apiVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;postgresql.cnpg.io/v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;cluster-example-with-backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;instances&lt;/span&gt;: &lt;span class="kt"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;primaryUpdateStrategy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;unsupervised&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Persistent storage configuration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;storageClass&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;standard&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1Gi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Backup properties
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;backup&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;barmanObjectStore&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;destinationPath&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;s3://backups/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;endpointURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://minio:9000&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;s3Credentials&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;accessKeyId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;minio&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ACCESS_KEY_ID&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;secretAccessKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;minio&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ACCESS_SECRET_KEY&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;wal&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;compression&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;gzip&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="javascript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="python" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;apiextensions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;postgresql_cluster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apiextensions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;cluster-example-with-backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;api_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;postgresql.cnpg.io/v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cluster-example-with-backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;instances&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;primaryUpdateStrategy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;unsupervised&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Persistent storage configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;storageClass&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;standard&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1Gi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Backup properties&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;barmanObjectStore&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;destinationPath&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;s3://backups/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;endpointURL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://minio:9000&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;s3Credentials&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;accessKeyId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;minio&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ACCESS_KEY_ID&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;secretAccessKey&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;minio&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ACCESS_SECRET_KEY&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;wal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;compression&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;gzip&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="go" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apiextensions&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/helm/v3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi/sdk/v3/go/pulumi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewCustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cluster-example-with-backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomResourceArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ApiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;postgresql.cnpg.io/v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cluster-example-with-backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OtherFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UntypedArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;instances&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;primaryUpdateStrategy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;unsupervised&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;storageClass&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;standard&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1Gi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;barmanObjectStore&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;destinationPath&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;s3://backups/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;endpointURL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://minio:9000&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;s3Credentials&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accessKeyId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;minio&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ACCESS_KEY_ID&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;secretAccessKey&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;minio&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ACCESS_SECRET_KEY&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;wal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;compression&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;gzip&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="csharp" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Meta.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostGreSQLClusterArgs&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CustomResourceArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [Input(&amp;#34;postgresql.cnpg.io/v1&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ApiVersion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [Input(&amp;#34;Cluster&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Kind&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Others&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [Input(&amp;#34;spec&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;InputMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;PostGreSQLClusterArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyStack&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;postgresqlCluster&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Kubernetes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cluster-example-with-backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;PostGreSQLClusterArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;postgresql.cnpg.io/v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ApiVersion&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;postgresql.cnpg.io/v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Kind&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;cluster-example-with-backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InputMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;instances&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;primaryUpdateStrategy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;unsupervised&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InputMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;storageClass&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;standard&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;1Gi&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;backup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InputMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;barmanObjectStore&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InputMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;destinationPath&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;s3://backups/&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;endpointURL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;http://minio:9000&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;s3Credentials&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InputMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;accessKeyId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InputMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;minio&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;ACCESS_KEY_ID&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;secretAccessKey&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InputMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;minio&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;ACCESS_SECRET_KEY&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;wal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InputMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;compression&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;gzip&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;h4 id="summary"&gt;Summary&lt;/h4&gt;
&lt;p&gt;CloudNativePG Operator is a great way to deploy and manage PostgreSQL databases on Kubernetes. It simplifies a wide range of tasks, including backups, high availability, and scaling, making it a must-have for PostgreSQL users.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;
&lt;p&gt;&lt;strong&gt;You might also like:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/master-kubernetes-secrets-with-pulumi-esc-secrets-store-csi-driver/"&gt;
Master Kubernetes Secrets with Pulumi ESC &amp;#43; Secrets Store CSI Driver
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/aws-eks-auto-mode/"&gt;
Getting Started with Amazon EKS Auto Mode in Pulumi
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/cursed-container-iceberg/"&gt;
105 Ways to Run Containers: The Cloud Container Iceberg
&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="flux-operator"&gt;Flux Operator&lt;/h3&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/why-every-platform-engineer-should-care-about-kubernetes-operators/flux-operator.png"
alt="Flux Operator Credit: fluxcd.control-plane.io/operator" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;Flux Operator Credit: fluxcd.control-plane.io/operator&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The &lt;a href="https://fluxcd.control-plane.io/operator/"&gt;Flux Operator&lt;/a&gt; is a full autopilot solution that provides an alternative to the traditional Flux Bootstrap procedure, removing the operational burden of managing Flux across multiple clusters by automating the installation, configuration, and upgrade of Flux fully.&lt;/p&gt;
&lt;p&gt;Some of the key features of Flux Operator are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GitOps Deployment&lt;/strong&gt; - Automate the deployment of applications and services using GitOps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lifecycle Management&lt;/strong&gt; - Manage the full lifecycle of Flux, including upgrades and rollbacks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deep Insights&lt;/strong&gt; - Provide deep insights into the state of Flux and the applications deployed with Flux.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="installation-1"&gt;Installation&lt;/h4&gt;
&lt;p&gt;Use the Helm chart to deploy the Flux Operator:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm upgrade -i flux-operator oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator --namespace flux-system --create-namespace
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or use Pulumi to deploy the Flux Operator:&lt;/p&gt;
&lt;div&gt;
&lt;pulumi-chooser type="language" options="typescript,javascript,python,go,csharp" mode=""&gt;&lt;/pulumi-chooser&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="typescript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8shelm&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes/helm/v3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;flux-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;flux-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;flux-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;createNamespace&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="javascript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="python" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;k8s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes.helm.v3&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;k8shelm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes.meta.v1&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;meta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;flux_namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;flux-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;flux-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;flux_operator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8shelm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;flux-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;flux_namespace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;create_namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="go" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apiextensions&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/helm/v3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi/sdk/v3/go/pulumi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewNamespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flux-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NamespaceArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flux-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewRelease&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flux-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReleaseArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Elem&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CreateNamespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="csharp" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Meta.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;namespaceFluxSystem&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flux-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NamespaceArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;flux-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fluxOperator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flux-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ReleaseArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Chart&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;namespaceFluxSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;CreateNamespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;h4 id="usage-1"&gt;Usage&lt;/h4&gt;
&lt;p&gt;Here is an example of a FluxInstance Custom Resource that defines a Flux instance:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;fluxcd.controlplane.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;FluxInstance&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;flux&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;flux-system&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;fluxcd.controlplane.io/reconcileEvery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1h&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;fluxcd.controlplane.io/reconcileTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;5m&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2.x&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ghcr.io/fluxcd&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;artifact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;source-controller&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;kustomize-controller&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;helm-controller&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;notification-controller&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;image-reflector-controller&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;image-automation-controller&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubernetes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;multitenant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networkPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cluster.local&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;kustomize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;patches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;(kustomize-controller|helm-controller)&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; - op: add
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; path: /spec/template/spec/containers/0/args/-
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; value: --concurrent=10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; - op: add
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; path: /spec/template/spec/containers/0/args/-
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; value: --requeue-dependency=5s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or use Pulumi:&lt;/p&gt;
&lt;div&gt;
&lt;pulumi-chooser type="language" options="typescript,javascript,python,go,csharp" mode=""&gt;&lt;/pulumi-chooser&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="typescript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiextensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;flux&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;apiVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;fluxcd.controlplane.io/v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;FluxInstance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;flux&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;flux-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;annotations&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;fluxcd.controlplane.io/reconcileEvery&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;fluxcd.controlplane.io/reconcileTimeout&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5m&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;distribution&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2.x&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ghcr.io/fluxcd&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;artifact&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;source-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kustomize-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;helm-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;notification-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;image-reflector-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;image-automation-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;multitenant&lt;/span&gt;: &lt;span class="kt"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;networkPolicy&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;cluster.local&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kustomize&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;patches&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Deployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;(kustomize-controller|helm-controller)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;patch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sb"&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sb"&gt; - op: add
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sb"&gt; path: /spec/template/spec/containers/0/args/-
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sb"&gt; value: --concurrent=10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sb"&gt; - op: add
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sb"&gt; path: /spec/template/spec/containers/0/args/-
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sb"&gt; value: --requeue-dependency=5s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sb"&gt; `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="javascript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="python" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;apiextensions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;flux_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;apiextensions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;flux&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;api_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;fluxcd.controlplane.io/v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;FluxInstance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;flux&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flux_namespace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;annotations&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;fluxcd.controlplane.io/reconcileEvery&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;fluxcd.controlplane.io/reconcileTimeout&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5m&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;distribution&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2.x&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;registry&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ghcr.io/fluxcd&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;artifact&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;components&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;source-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kustomize-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;helm-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;notification-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;image-reflector-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;image-automation-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;multitenant&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;networkPolicy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;domain&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;cluster.local&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kustomize&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;patches&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Deployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;(kustomize-controller|helm-controller)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;patch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;op&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;add&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/spec/template/spec/containers/0/args/-&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;--concurrent=10&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;op&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;add&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/spec/template/spec/containers/0/args/-&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;--requeue-dependency=5s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="go" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apiextensions&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/helm/v3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi/sdk/v3/go/pulumi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewCustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flux&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomResourceArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ApiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fluxcd.controlplane.io/v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;FluxInstance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flux&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flux-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StringMap&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fluxcd.controlplane.io/reconcileEvery&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1h&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fluxcd.controlplane.io/reconcileTimeout&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;5m&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OtherFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UntypedArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;distribution&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;2.x&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;registry&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ghcr.io/fluxcd&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;artifact&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;components&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StringArray&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;source-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kustomize-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;helm-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;notification-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;image-reflector-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;image-automation-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;multitenant&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;networkPolicy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;domain&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cluster.local&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kustomize&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;patches&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Deployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;(kustomize-controller|helm-controller)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;patch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;op&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;add&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/spec/template/spec/containers/0/args/-&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;--concurrent=10&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;op&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;add&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/spec/template/spec/containers/0/args/-&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;--requeue-dependency=5s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="csharp" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Meta.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FluxInstanceArgs&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CustomResourceArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ApiVersion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Kind&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;FluxInstanceArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;flux&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Kubernetes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flux&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;FluxInstanceArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fluxcd.controlplane.io/v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;FluxInstance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ApiVersion&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;fluxcd.controlplane.io/v1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Kind&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;FluxInstance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;flux&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Annotations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;fluxcd.controlplane.io/reconcileEvery&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;1h&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;fluxcd.controlplane.io/reconcileTimeout&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;5m&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;distribution&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;2.x&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;registry&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;ghcr.io/fluxcd&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;artifact&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;components&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;source-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;kustomize-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;helm-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;notification-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;image-reflector-controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;image-automation-controller&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;kubernetes&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;multitenant&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;networkPolicy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;domain&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;cluster.local&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;kustomize&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;patches&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;target&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Deployment&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;(kustomize-controller|helm-controller)&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;patch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;op&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;add&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/spec/template/spec/containers/0/args/-&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;--concurrent=10&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;op&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;add&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/spec/template/spec/containers/0/args/-&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;--requeue-dependency=5s&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;h4 id="summary-1"&gt;Summary&lt;/h4&gt;
&lt;p&gt;The Flux Operator is another excellent example of an advanced Kubernetes operator, providing full lifecycle management with numerous automation features.&lt;/p&gt;
&lt;h3 id="strimzi-operator"&gt;Strimzi Operator&lt;/h3&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/why-every-platform-engineer-should-care-about-kubernetes-operators/strimzi.png"
alt="Strimzi Operator Credit: strimzi.io" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;Strimzi Operator Credit: strimzi.io&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Last but not least, the &lt;a href="https://strimzi.io/"&gt;Strimzi Operator&lt;/a&gt; is a full lifecycle management operator for Apache Kafka on Kubernetes. As event-driven architectures are becoming increasingly popular, Apache Kafka has become the de-facto standard for building scalable and reliable event streaming platforms. The Strimzi Operator makes it easier to deploy, manage, and scale Apache Kafka clusters on Kubernetes.&lt;/p&gt;
&lt;p&gt;Some of the key features of Strimzi Operator are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cluster Management&lt;/strong&gt; - Deploy and manage Apache Kafka clusters.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mirror Clusters&lt;/strong&gt; - Deploy and manage mirror clusters for disaster recovery.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Streaming Capabilities&lt;/strong&gt; - With Kafka Connect you can stream data between Kafka and other systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="installation-2"&gt;Installation&lt;/h4&gt;
&lt;p&gt;Use the Helm chart to deploy the Strimzi Operator:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm repo add strimzi https://strimzi.io/charts/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm repo update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm install strimzi strimzi/strimzi-kafka-operator -n kafka --create-namespace
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or use Pulumi to deploy the Strimzi Operator:&lt;/p&gt;
&lt;div&gt;
&lt;pulumi-chooser type="language" options="typescript,javascript,python,go,csharp" mode=""&gt;&lt;/pulumi-chooser&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="typescript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8shelm&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes/helm/v3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;namespaceKafka&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;strimzi-kafka-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;strimzi-kafka-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;namespaceKafka&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;repositoryOpts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://strimzi.io/charts/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;createNamespace&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="javascript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="python" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;k8s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes.helm.v3&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;k8shelm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes.meta.v1&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;meta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;kafka_namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;strimzi_kafka_operator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8shelm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;strimzi-kafka-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;strimzi-kafka-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;kafka_namespace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;repository_opts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;repo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://strimzi.io/charts/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;create_namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="go" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apiextensions&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/helm/v3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi/sdk/v3/go/pulumi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;namespaceKafka&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewNamespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NamespaceArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewRelease&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;strimzi-kafka-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReleaseArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Chart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;strimzi-kafka-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;namespaceKafka&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;RepositoryOpts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RepositoryOptsArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://strimzi.io/charts/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CreateNamespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="csharp" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Meta.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyStack&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;namespaceKafka&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NamespaceArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;strimziKafkaOperator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;strimzi-kafka-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ReleaseArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Chart&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;strimzi-kafka-operator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;namespaceKafka&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;RepositoryOpts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;RepositoryOptsArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Repo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;https://strimzi.io/charts/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;CreateNamespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;h4 id="usage-2"&gt;Usage&lt;/h4&gt;
&lt;p&gt;Here is an example of a Kafka Custom Resource that defines a Kafka cluster:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka.strimzi.io/v1beta2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;KafkaNodePool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;example-kafka-node-pool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;strimzi.io/cluster&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;example-kafka-cluster&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;controller&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;broker&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ephemeral&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka.strimzi.io/v1beta2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Kafka&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;example-kafka-cluster&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;strimzi.io/kraft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;enabled&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;strimzi.io/node-pools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;enabled&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;kafka&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3.8.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ephemeral&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metadataVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3.8&lt;/span&gt;-&lt;span class="l"&gt;IV0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;plain&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9092&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;tls&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9093&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;offsets.topic.replication.factor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;transaction.state.log.replication.factor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;transaction.state.log.min.isr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;default.replication.factor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;min.insync.replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;entityOperator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topicOperator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;userOperator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This example defines a Kafka cluster with one replica and two listeners, one for plain and one for TLS and uses
ephemeral storage.&lt;/p&gt;
&lt;p&gt;To create a topic, you can use the following KafkaTopic Custom Resource:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka.strimzi.io/v1beta2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;KafkaTopic&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;example-kafka-cluster&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;strimzi.io/cluster&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;partitions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;retention.ms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;7200000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;segment.bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1073741824&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or use Pulumi:&lt;/p&gt;
&lt;div&gt;
&lt;pulumi-chooser type="language" options="typescript,javascript,python,go,csharp" mode=""&gt;&lt;/pulumi-chooser&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="typescript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiextensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;example-kafka-node-pool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;apiVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;KafkaNodePool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-node-pool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;labels&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;strimzi.io/cluster&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;replicas&lt;/span&gt;: &lt;span class="kt"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;broker&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ephemeral&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiextensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;apiVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;annotations&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;strimzi.io/kraft&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;strimzi.io/node-pools&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kafka&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;replicas&lt;/span&gt;: &lt;span class="kt"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;3.8.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ephemeral&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadataVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;3.8-IV0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;listeners&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;plain&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;port&lt;/span&gt;: &lt;span class="kt"&gt;9092&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;tls&lt;/span&gt;: &lt;span class="kt"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tls&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;port&lt;/span&gt;: &lt;span class="kt"&gt;9093&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;tls&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offsets.topic.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;transaction.state.log.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;transaction.state.log.min.isr&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;default.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;min.insync.replicas&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;entityOperator&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;topicOperator&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;userOperator&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiextensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;example-kafka-topic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;apiVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;KafkaTopic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-topic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;labels&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;strimzi.io/cluster&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;partitions&lt;/span&gt;: &lt;span class="kt"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;replicas&lt;/span&gt;: &lt;span class="kt"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;retention.ms&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7200000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;segment.bytes&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1073741824&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="javascript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="python" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;apiextensions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;kafka_node_pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;apiextensions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-node-pool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;api_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;KafkaNodePool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-node-pool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;labels&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;strimzi.io/cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;kafka_namespace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;roles&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;broker&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ephemeral&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;kafka_cluster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;apiextensions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;api_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;annotations&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;strimzi.io/kraft&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;strimzi.io/node-pools&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;kafka_namespace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;3.8.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ephemeral&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;metadataVersion&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;3.8-IV0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;listeners&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;plain&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9092&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;tls&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tls&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9093&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;tls&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;config&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offsets.topic.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;transaction.state.log.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;transaction.state.log.min.isr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;default.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;min.insync.replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;entityOperator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;topicOperator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;userOperator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;kafka_topic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;apiextensions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-topic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;api_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;KafkaTopic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-topic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;labels&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;strimzi.io/cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;kafka_namespace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;partitions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;config&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;retention.ms&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7200000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;segment.bytes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1073741824&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="go" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apiextensions&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;helmv3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/helm/v3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi/sdk/v3/go/pulumi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewCustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;example-kafka-node-pool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomResourceArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ApiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;KafkaNodePool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;example-kafka-node-pool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StringMap&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;strimzi.io/cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OtherFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UntypedArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;roles&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StringArray&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;broker&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ephemeral&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewCustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomResourceArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ApiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StringMap&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;strimzi.io/kraft&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;strimzi.io/node-pools&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OtherFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UntypedArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;3.8.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ephemeral&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;metadataVersion&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;3.8-IV0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;listeners&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;plain&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9092&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tls&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tls&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9093&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tls&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;config&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;offsets.topic.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;transaction.state.log.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;transaction.state.log.min.isr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;default.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;min.insync.replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;entityOperator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;topicOperator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;userOperator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewCustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;example-kafka-topic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;apiv1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CustomResourceArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ApiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;KafkaTopic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;example-kafka-topic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StringMap&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;strimzi.io/cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OtherFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UntypedArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;partitions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;config&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;retention.ms&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7200000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;segment.bytes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1073741824&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="csharp" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Helm.V3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Meta.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KafkaNodePoolArgs&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CustomResourceArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ApiVersion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Kind&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;KafkaNodePoolArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KafkaClusterArgs&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CustomResourceArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ApiVersion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Kind&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;KafkaClusterArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KafkaTopicArgs&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CustomResourceArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ApiVersion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Kind&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;KafkaTopicArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyStack&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;kafkaNodePool&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Kubernetes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;exampleKafkaNodePool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;KafkaNodePoolArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;KafkaNodePool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ApiVersion&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Kind&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;KafkaNodePool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;example-kafka-node-pool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Labels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;strimzi.io/cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;roles&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;controller&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;broker&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;ephemeral&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;kafkaCluster&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Kubernetes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;exampleKafkaCluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;KafkaClusterArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ApiVersion&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Kind&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Annotations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;strimzi.io/kraft&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;strimzi.io/node-pools&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;kafka&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;3.8.0&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;ephemeral&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;metadataVersion&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;3.8-IV0&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;listeners&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;plain&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;9092&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;internal&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;tls&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;tls&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;9093&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;internal&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;tls&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;config&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;offsets.topic.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;transaction.state.log.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;transaction.state.log.min.isr&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;default.replication.factor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;min.insync.replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;entityOperator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;topicOperator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;userOperator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;kafkaTopic&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Kubernetes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApiExtensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;exampleKafkaTopic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;KafkaTopicArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;KafkaTopic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ApiVersion&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;kafka.strimzi.io/v1beta2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Kind&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;KafkaTopic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;example-kafka-topic&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Labels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;strimzi.io/cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;example-kafka-cluster&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;partitions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;config&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;retention.ms&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;7200000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;segment.bytes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1073741824&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;h4 id="summary-2"&gt;Summary&lt;/h4&gt;
&lt;p&gt;The Strimzi Operator demonstrates the power of Kubernetes Operators by providing full lifecycle management for Apache Kafka on Kubernetes. It takes care of the heavy lifting of deploying and managing Kafka clusters, making the Strimzi Operator a valuable tool that should be part of every Kubernetes-powered platform, as it covers a wide range of use cases.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this blog post, I highlighted the importance of Kubernetes Operators for platform engineers and how they can harness the advanced automation capabilities of operators to simplify deploying, managing, and scaling applications and services on Kubernetes.&lt;/p&gt;
&lt;p&gt;I provided some examples of advanced Kubernetes operators that I recommend, but if you want to try using Kubernetes Operators in your Kubernetes-powered platform, here are some great guides to get you started with Pulumi and Kubernetes:&lt;/p&gt;
&lt;section class="my-16"&gt;
&lt;div class="container mx-auto max-w-5xl md:flex my-8 align-top justify-center text-center"&gt;
&lt;div class="md:w3-/12 mr-4"&gt;
&lt;h2 class="no-anchor"&gt;Get Started with Pulumi&lt;/h2&gt;
&lt;p class="text-gray-700 dark:text-gray-300 text-sm"&gt;Use Pulumi's open-source SDK to create, deploy, and manage infrastructure on any cloud.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="mx-auto max-w-4xl"&gt;
&lt;div class="tiles flex-wrap mt-4"&gt;
&lt;div class="pb-4 md:pr-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/aws/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/aws.svg" alt="AWS" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="pb-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/azure/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/azure.svg" alt="Azure" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="pb-4 md:pr-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/gcp/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/gcp.svg" alt="Google Cloud" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="pb-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/kubernetes/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/k8s.svg" alt="Kubernetes" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;</description><author>Engin Diri</author><category>kubernetes</category><category>operators</category><category>devops</category><category>platform-engineering</category></item><item><title>DevSecOps Game-Changer: Security Automation That Delivers Business Results</title><link>https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/</link><pubDate>Thu, 21 Nov 2024 07:16:30 +0000</pubDate><guid>https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/devsecops-strategy-security-automation-tivity-health/index.png" /&gt;
&lt;p&gt;Organizations are under constant pressure to deliver new products and features faster than ever. But speed alone isn’t enough—businesses must also navigate the complex challenges of ensuring security and managing infrastructure costs effectively.&lt;/p&gt;
&lt;p&gt;Enter DevSecOps - the strategic integration of security practices into the DevOps workflow. By automating security processes, organizations can achieve improved speed, scalability, and business impact, all while ensuring security remains a priority.&lt;/p&gt;
&lt;p&gt;Tivity Health, a leading health and fitness solutions provider, has embraced this DevSecOps approach using Pulumi, a modern infrastructure as code (IaC) platform. During PulumiUP 2024, David Giambruno, Tivity Health&amp;rsquo;s VP of Engineering and DevOps, shared how, by leveraging Pulumi, he led the transformation that continuously drives remarkable results in speed, cost savings, and security.&lt;/p&gt;
&lt;h2 id="on-this-article"&gt;On this article:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#the-beginning-from-data-center-to-the-cloud"&gt;The Beginning: From Data Center to the Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#embracing-pulumi-the-power-of-automation-productivity-and-security"&gt;Embracing Pulumi: The Power of Automation, Productivity, and Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#driving-business-impact-through-security-automation"&gt;Driving Business Impact Through Security Automation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#fostering-devops-culture-through-cross-functional-collaboration"&gt;Fostering DevOps Culture Through Cross-Functional Collaboration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#lessons-learned-navigating-the-cultural-shift"&gt;Lessons Learned: Navigating the Cultural Shift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#the-future-of-devsecops-and-pulumi-at-tivity-health"&gt;The Future of DevSecOps and Pulumi at Tivity Health&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-beginning-from-data-center-to-the-cloud"&gt;The Beginning: From Data Center to the Cloud&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.tivityhealth.com/"&gt;Tivity Health&lt;/a&gt;&amp;rsquo;s journey began with a strategic decision to transition from a traditional data center environment to a cloud-native architecture. Rather than opting for a &amp;ldquo;lift and shift&amp;rdquo; approach, they made the bold choice to go directly to a cloud-native model, embracing the principles of DevSecOps along the way.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/35vAiKdDux4?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;The need to &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;automate infrastructure deployment&lt;/a&gt; and management was fundamental. Giambruno explained, &amp;ldquo;&lt;em&gt;If you can&amp;rsquo;t automate it, we don&amp;rsquo;t need it.&lt;/em&gt;&amp;rdquo; This philosophy drove the team to seek out a solution that would not only streamline their operations but also empower their developers to focus on building innovative products for their customers.&lt;/p&gt;
&lt;h2 id="embracing-pulumi-the-power-of-automation-productivity-and-security"&gt;Embracing Pulumi: The Power of Automation, Productivity, and Security&lt;/h2&gt;
&lt;p&gt;Tivity Health&amp;rsquo;s search for the right tool led them to Pulumi, a unified platform for all the infrastructure needs that allows teams to use general programming languages, such as TypeScript, Python, Java, and Go, to define and manage their cloud infrastructure. Giambruno and his team immediately recognized Pulumi&amp;rsquo;s ability to deliver on their key requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automation&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/iac/"&gt;Pulumi&amp;rsquo;s infrastructure as code (IaC)&lt;/a&gt; approach enabled Tivity Health to automate the deployment and management of its cloud environments, reducing the time and effort required for these tasks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Productivity&lt;/strong&gt;: using Pulumi&amp;rsquo;s general-purpose programming languages allowed developers to define, deploy, and manage infrastructure within their existing tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt;: Pulumi&amp;rsquo;s security features allowed Tivity Health to integrate &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/"&gt;security practices&lt;/a&gt; into its infrastructure deployment processes, reducing the risk of security breaches and ensuring compliance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost Optimization&lt;/strong&gt;: Pulumi&amp;rsquo;s ability to automate the spin-up and teardown of cloud environments on demand has led to significant cost reductions for Tivity Health.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Giambruno describes Pulumi as a &amp;ldquo;three-dimensional&amp;rdquo; tool, offering a versatile set of capabilities that have been instrumental in transforming Tivity Health&amp;rsquo;s operations. &amp;ldquo;&lt;em&gt;The ability to use those dimensions in lots of different ways to do the automation is what really makes a difference to the teams&lt;/em&gt;,&amp;rdquo; he says.&lt;/p&gt;
&lt;h2 id="driving-business-impact-through-security-automation"&gt;Driving Business Impact Through Security Automation&lt;/h2&gt;
&lt;p&gt;By adopting Pulumi and DevSecOps automation, Tivity Health realized significant business benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Speed and Agility&lt;/strong&gt;: By automating its infrastructure deployment and management processes, Tivity Health has dramatically &lt;a href="https://www.pulumi.com/case-studies/unity/"&gt;reduced the time&lt;/a&gt; required to spin up new environments or change existing ones. &amp;ldquo;&lt;em&gt;We run it through automation and boom, it&amp;rsquo;s out, it&amp;rsquo;s done&lt;/em&gt;,&amp;rdquo; Giambruno says. This newfound speed and agility have empowered Tivity Health&amp;rsquo;s developers to focus on building products and features rather than getting bogged down in infrastructure-related tasks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost Optimization&lt;/strong&gt;: Tivity Health&amp;rsquo;s cloud-native approach and Pulumi&amp;rsquo;s automation capabilities have resulted in &lt;a href="https://www.pulumi.com/case-studies/lemonade/"&gt;significant cost savings&lt;/a&gt;. The company estimates that its annual cloud spend has decreased from $9.5 million in its data center days to just $2 million—a staggering 79% reduction. These cost savings have allowed Tivity Health to redirect resources towards more strategic initiatives that drive business growth.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved Security and Compliance&lt;/strong&gt;: Tivity Health&amp;rsquo;s DevSecOps strategy, anchored by Pulumi, has strengthened its security posture and &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies/"&gt;compliance efforts&lt;/a&gt;. By integrating security directly into its infrastructure workflows, Tivity Health has improved its security posture. Automation ensures that security measures are enforced consistently across their cloud environments, reducing risks and improving compliance.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="fostering-devops-culture-through-cross-functional-collaboration"&gt;Fostering DevOps Culture Through Cross-Functional Collaboration&lt;/h2&gt;
&lt;p&gt;Using Pulumi provided more than technical benefits. It also enabled better collaboration between the development, security, and operations teams. By providing a common language and framework for infrastructure management, Pulumi has helped break down silos and align these traditionally disparate groups towards a shared goal of delivering secure, high-quality products faster.&lt;/p&gt;
&lt;h2 id="lessons-learned-navigating-the-cultural-shift"&gt;Lessons Learned: Navigating the Cultural Shift&lt;/h2&gt;
&lt;p&gt;Transitioning to DevSecOps and cloud-native practices required a cultural shift at Tivity Health. Giambrono acknowledges that this cultural shift was not without its challenges. He emphasizes the importance of addressing the human element of change, offering the following advice for organizations embarking on a similar journey:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Start with a proof of concepts&lt;/strong&gt;: Giambruno recommends beginning with a small-scale proof of concepts to demonstrate the capabilities and benefits of the new technologies and processes to help alleviate fears and build confidence among team members.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Empower developers and make them feel safe&lt;/strong&gt;: By involving developers in the process and ensuring they feel comfortable with the new tools and workflows, Tivity Health gained user buy-in and overall support for the new DevSecOps approach.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secure buy-in from business and financial stakeholders&lt;/strong&gt;: Address the concerns of business and financial stakeholders early on, such as the impact on costs and the ability to deliver tangible results. This is crucial for securing the necessary support and resources.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Celebrate successes and build momentum&lt;/strong&gt;: Giambruno highlights the importance of celebrating the team&amp;rsquo;s achievements along the way, even when there are bumps on the road, as this helps build enthusiasm and keep the momentum going.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-future-of-devsecops-and-pulumi-at-tivity-health"&gt;The Future of DevSecOps and Pulumi at Tivity Health&lt;/h2&gt;
&lt;p&gt;As Tivity Health continues to refine its DevSecOps strategy, Giambruno is optimistic about the future. He envisions a world where the company&amp;rsquo;s ability to deploy new products and features rapidly will give Tivity Health a significant competitive edge, allowing it to better serve its customers and drive business growth.&lt;/p&gt;
&lt;p&gt;Looking ahead, Giambruno is particularly enthusiastic about the potential of Pulumi&amp;rsquo;s AI-powered capabilities, which he believes will further streamline and optimize the company&amp;rsquo;s infrastructure management processes. &amp;ldquo;&lt;em&gt;I&amp;rsquo;m super looking forward to the tests we&amp;rsquo;re going to do, like when we acquire someone and then taking them in, &amp;lsquo;Borg-ing&amp;rsquo; them into our automation and seeing how much we can take out of their operating cost as fast as possible&lt;/em&gt;,&amp;rdquo; he says.&lt;/p&gt;
&lt;p&gt;Tivity Health&amp;rsquo;s journey with Pulumi is a powerful example of how the right tool, DevSecOps strategy, and automation can drive tangible business results. By focusing on automation, security, and collaboration, organizations can achieve faster, cheaper, and better cloud deployments—putting them on the path to long-term success in an increasingly competitive, cloud-native world.&lt;/p&gt;
&lt;p&gt;To learn more about Pulumi and how it can transform your software development and infrastructure management:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get started with &lt;a href="https://www.pulumi.com/tutorials/"&gt;Pulumi Tutorials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Attend an &lt;a href="https://www.pulumi.com/resources/#upcoming"&gt;upcoming workshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Try out the &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt; code assistant to accelerate your infrastructure as code journey&lt;/li&gt;
&lt;/ul&gt;</description><author>Sara Huddleston</author><category>security</category><category>devsecops</category><category>devops</category><category>infrastructure-as-code</category><category>platform-engineering</category><category>infrastructure-lifecycle-management</category><category>developer-experience</category></item><item><title>YAML, Terraform, Pulumi: What’s the Smart Choice for Deployment Automation with Kubernetes?</title><link>https://www.pulumi.com/blog/yaml-terraform-pulumi-whats-the-smart-choice-for-deployment-automation-with-kubernetes/</link><pubDate>Mon, 18 Nov 2024 08:00:00 +0100</pubDate><guid>https://www.pulumi.com/blog/yaml-terraform-pulumi-whats-the-smart-choice-for-deployment-automation-with-kubernetes/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/yaml-terraform-pulumi-whats-the-smart-choice-for-deployment-automation-with-kubernetes/index.png" /&gt;
&lt;p&gt;YAML and &lt;a href="https://kubernetes.io/"&gt;Kubernetes&lt;/a&gt; go together like peanut butter and jelly. While Kubernetes objects can be defined in JSON, YAML has emerged as the de facto standard.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s often the first tool developers encounter when diving into Kubernetes, and for good reason - its human-readable format makes it the preferred choice in most tutorials, documentation, and even production deployments.&lt;/p&gt;
&lt;div style="display: flex; align-items: center; justify-content: center; height: 600px;"&gt;
&lt;img src="yaml.png" alt="Description of image" style="width: 60%; height: 100%"&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;But is it the best way to manage your Kubernetes resources?&lt;/strong&gt; Let&amp;rsquo;s compare YAML, Terraform, and Pulumi and see which is best for managing your Kubernetes resources.&lt;/p&gt;
&lt;p&gt;I also gave a talk before on &lt;code&gt;No YAML!&lt;/code&gt; and what alternatives you have if you would only stick with the Go language:&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/Q8WKLq-v_6k?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id="kubernetes-components-and-the-kubernetes-api"&gt;Kubernetes Components and the Kubernetes API&lt;/h2&gt;
&lt;p&gt;Before we discuss the ways to manage Kubernetes objects, let&amp;rsquo;s look at the components of a typical Kubernetes cluster and their interactions.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/yaml-terraform-pulumi-whats-the-smart-choice-for-deployment-automation-with-kubernetes/kubernetes-components.png"
alt="Kubernetes Components. Credit: kubernetes.io" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;Kubernetes Components. Credit: kubernetes.io&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;A Kubernetes cluster has two component categories: control plane and node. The control plane components manage the cluster. They consist of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;kube-apiserver&lt;/strong&gt; - The API server is the front end for the Kubernetes control plane. It exposes the Kubernetes API.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;etcd&lt;/strong&gt; - A consistent, highly available key-value store. It is Kubernetes&amp;rsquo; backing store for all API data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;kube-scheduler&lt;/strong&gt; - Watches for newly created Pods with no assigned node and selects a node for them to run on.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;kube-controller-manager&lt;/strong&gt; - Runs a controller to implement the control loop.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;cloud-controller-manager&lt;/strong&gt; - Runs controllers that interact with the underlying cloud providers.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The node components run on every node in the cluster. They provide the runtime environment for the containers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;kubelet&lt;/strong&gt; - An agent that runs on each node in the cluster. It ensures that pods are running.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;kube-proxy&lt;/strong&gt; - Maintains network rules on nodes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Container Runtime&lt;/strong&gt; - Is responsible for running containers.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Kubernetes API is the central component in a Kubernetes cluster. It is the interface to the cluster and the only way to work with Kubernetes objects.&lt;/p&gt;
&lt;p&gt;A Kubernetes object is a &amp;ldquo;record of intent&amp;rdquo;. It represents the desired state of the workload running on the cluster. The whole Kubernetes system will continuously work to ensure that the object exists.&lt;/p&gt;
&lt;h2 id="yaml-manifests"&gt;YAML Manifests&lt;/h2&gt;
&lt;p&gt;If you are long enough exposed to Kubernetes, you will have seen a lot of YAML files. You can define many Kubernetes objects in a YAML file. These include &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/"&gt;&lt;code&gt;Deployments&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/"&gt;&lt;code&gt;Services&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://kubernetes.io/docs/concepts/configuration/configmap/"&gt;&lt;code&gt;ConfigMaps&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/"&gt;&lt;code&gt;Secrets&lt;/code&gt;&lt;/a&gt;, and more.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at an example of a &lt;code&gt;Deployment&lt;/code&gt; object in YAML for an &lt;code&gt;Nginx&lt;/code&gt; web server:&lt;/p&gt;
&lt;h3 id="example"&gt;Example&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;apps/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx-deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;nginx:latest&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="pros-and-cons-of-yaml"&gt;Pros and Cons of YAML&lt;/h3&gt;
&lt;h4 id="pros"&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Simple:&lt;/strong&gt; Kubernetes YAML files are easy to read and write.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The standard:&lt;/strong&gt; YAML is the standard way to define Kubernetes objects. It is a first-class citizen in the &lt;code&gt;kubectl&lt;/code&gt; command-line tool.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="cons"&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multiple environments:&lt;/strong&gt; If you have multiple environments, like development, staging, and production, you need to maintain multiple YAML files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Too manual:&lt;/strong&gt; You must create and update the YAML files by hand. Also, you must track changes across many files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not DRY:&lt;/strong&gt; You cannot use the &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY principle&lt;/a&gt; (Don&amp;rsquo;t Repeat Yourself) in YAML files. If you have the same configuration in many files, you need to update all of them by hand.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No real abstraction:&lt;/strong&gt; The advantage of a static configuration file is also its disadvantage. You cannot use dynamic values in the YAML files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Need for tools from the ecosystem:&lt;/strong&gt; You need to use tools like &lt;code&gt;helm&lt;/code&gt; or &lt;code&gt;kustomize&lt;/code&gt; to manage the complexity of many YAML files, environments, and templating.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To sum it up, YAML is a good choice for simple Kubernetes objects and small projects. But, if you have a complex project, and to be honest, most are, you need a better way to manage your Kubernetes resources.&lt;/p&gt;
&lt;p&gt;Or to rephrase it: Friends don&amp;rsquo;t let friends manage Kubernetes resources with YAML.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/yaml-terraform-pulumi-whats-the-smart-choice-for-deployment-automation-with-kubernetes/drake_no_yaml.png"
alt="Why should you avoid YAML? Credit: No YAML!" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;Why should you avoid YAML? Credit: No YAML!&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="terraform-kubernetes-provider"&gt;Terraform Kubernetes Provider&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.terraform.io/"&gt;Terraform&lt;/a&gt; is an Infrastructure as Code tool. It lets you define and manage your infrastructure in a declarative way. It uses a high-level configuration language called HashiCorp Configuration Language (HCL). To manage Kubernetes objects with Terraform, use the Kubernetes provider. It allows you to define Kubernetes objects in Terraform HCL.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://registry.terraform.io/providers/hashicorp/kubernetes/latest"&gt;Kubernetes provider&lt;/a&gt; allows you to define Kubernetes objects like &lt;code&gt;kubernetes_deployment&lt;/code&gt;, &lt;code&gt;kubernetes_service&lt;/code&gt;, &lt;code&gt;kubernetes_config_map&lt;/code&gt;, &lt;code&gt;kubernetes_secret&lt;/code&gt;, and more in code, leveraging the language features of Terraform. You can use, to a certain extent, loops, conditions, and variables in a way that is not possible with plain YAML files.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at an example of a &lt;code&gt;Deployment&lt;/code&gt; object in Terraform HCL for an &lt;code&gt;Nginx&lt;/code&gt; web server:&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kubernetes_deployment&amp;#34; &amp;#34;nginx&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;metadata&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx-deployment&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;spec&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; replicas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;selector&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; match_labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;template&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;metadata&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;spec&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;container&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx:latest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a very simple example of a &lt;code&gt;Deployment&lt;/code&gt; object in Terraform HCL. Let&amp;rsquo;s add some complexity to the example by adding variables and loops:&lt;/p&gt;
&lt;h3 id="example-with-variables-and-loops"&gt;Example with Variables and Loops&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;The namespace to deploy the resources&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx_image&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;The Nginx image to use&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx:latest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;The number of replicas to deploy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;number_of_deployments&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;The number of deployments to create&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;locals&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; nginx_image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;nginx_image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; replicas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;replicas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;namespace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; number_of_deployments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;number_of_deployments&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kubernetes_deployment&amp;#34; &amp;#34;nginx&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; for_each&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt; {for i in range(local.number_of_deployments) : i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;i&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;metadata&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx-deployment-${each.key}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;namespace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;spec&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; replicas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;replicas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;selector&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; match_labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx-${each.key}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;template&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;metadata&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx-${each.key}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;spec&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;container&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;nginx_image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this example, we can already see the advantage of Terraform over plain YAML files. We can use variables and loops to define multiple &lt;code&gt;kubernetes_deployment&lt;/code&gt; objects in a more dynamic way.&lt;/p&gt;
&lt;h3 id="pros-and-cons-of-terraform"&gt;Pros and Cons of Terraform&lt;/h3&gt;
&lt;h4 id="pros-1"&gt;Pros&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dynamic:&lt;/strong&gt; You can use variables, loops, and conditions in Terraform HCL. This lets you define your Kubernetes objects in a more dynamic way.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; You can apply the DRY principle in Terraform HCL by defining and reusing modules across projects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment management:&lt;/strong&gt; By defining variables, you can manage multiple environments, like development, staging, and production. This is a more structured way to do it, without needing extra tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="cons-1"&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; Terraform is more complex than plain YAML files. You must learn Terraform&amp;rsquo;s HCL to define your Kubernetes objects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DSL:&lt;/strong&gt; Terraform is a Domain-Specific Language (DSL). You need to learn it to define your Kubernetes objects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Testability:&lt;/strong&gt; Testing Terraform code is harder. You need tools like Terratest and Kitchen-Terraform for it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Helm Support:&lt;/strong&gt; Terraform does not support Helm charts out of the box. You need to use the &lt;a href="https://registry.terraform.io/providers/hashicorp/helm/latest"&gt;Helm provider&lt;/a&gt; to manage them with Terraform. This can add complexity to your Terraform code, and you need to keep track of the Helm provider dependency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IDE Support:&lt;/strong&gt; Terraform lacks the same IDE support as YAML files. You need plugins, like the &lt;a href="https://marketplace.visualstudio.com/items?itemName=HashiCorp.terraform"&gt;Terraform Extension for Visual Studio Code&lt;/a&gt;, for syntax highlighting and autocompletion.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Terraform is a good choice for managing your Kubernetes resources if you have a complex project and you do not mind the complexity of the Terraform language. It gives you more flexibility and abstraction than plain YAML files, and you can manage multiple environments in a more structured way.&lt;/p&gt;
&lt;p&gt;But is there a better way to manage your Kubernetes resources? Let&amp;rsquo;s have a look at Pulumi.&lt;/p&gt;
&lt;h2 id="pulumi-and-the-power-of-general-purpose-languages"&gt;Pulumi and the Power of General Purpose Languages&lt;/h2&gt;
&lt;p&gt;Last but not least, let&amp;rsquo;s have a look at Pulumi. Pulumi is an Infrastructure as Code tool. It lets you define and manage your Kubernetes objects using general-purpose programming languages. Pulumi &lt;a href="https://www.pulumi.com/docs/iac/languages-sdks/"&gt;supports multiple languages&lt;/a&gt; like Python, Go, TypeScript, JavaScript, .NET, and JVM-based languages. This gives you all the benefits of a full programming language. It includes native IDE support, code completion, and debugging.&lt;/p&gt;
&lt;p&gt;You need to install the &lt;a href="https://www.pulumi.com/docs/iac/cli/"&gt;Pulumi CLI&lt;/a&gt;. Then, create a &lt;a href="https://www.pulumi.com/docs/iac/cli/commands/pulumi_new/"&gt;new Pulumi project&lt;/a&gt;. Finally, add the &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/"&gt;Kubernetes library&lt;/a&gt; to it. It depends on the language you choose. You could use a package manager, like &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;pip&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at an example of what a &lt;code&gt;Deployment&lt;/code&gt; object would look like in all the supported languages.&lt;/p&gt;
&lt;div&gt;
&lt;pulumi-chooser type="language" options="typescript,javascript,python,go,csharp,java" mode=""&gt;&lt;/pulumi-chooser&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="typescript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nginxDeployment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;nginx-deployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx-deployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;replicas&lt;/span&gt;: &lt;span class="kt"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;matchLabels&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;labels&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;containers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx:latest&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="javascript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="python" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi_kubernetes&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;k8s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;nginx_deployment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;nginx-deployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;nginx-deployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeploymentSpecArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LabelSelectorArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;match_labels&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PodTemplateSpecArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PodSpecArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;containers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;k8s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContainerArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;nginx:latest&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="go" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apps/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/pulumi/pulumi/sdk/v3/go/pulumi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewDeployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginxDeployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DeploymentArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginx-deployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DeploymentSpecArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LabelSelectorArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;MatchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StringMap&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PodTemplateSpecArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;metav1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StringMap&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PodSpecArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ContainerArray&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;corev1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ContainerArgs&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginx:latest&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="csharp" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;﻿&lt;/span&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Core.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Apps.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi.Kubernetes.Types.Inputs.Meta.V1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Deployment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyStack&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;nginxDeployment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Kubernetes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Apps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;V1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginxDeployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DeploymentArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;nginx-deployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DeploymentSpecArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Replicas&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Selector&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;LabelSelectorArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;MatchLabels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Template&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;PodTemplateSpecArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Labels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Spec&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;PodSpecArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Containers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ContainerArgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;nginx:latest&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="java" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;myproject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.Pulumi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.kubernetes.apps.v1.Deployment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.kubernetes.apps.v1.DeploymentArgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.kubernetes.apps.v1.inputs.DeploymentSpecArgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.kubernetes.core.v1.inputs.ContainerArgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.kubernetes.core.v1.inputs.PodSpecArgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.kubernetes.core.v1.inputs.PodTemplateSpecArgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.kubernetes.meta.v1.inputs.LabelSelectorArgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.kubernetes.meta.v1.inputs.ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;java.util.Map&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nginxDeployment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginxDeployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DeploymentArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginx-deployment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeploymentSpecArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LabelSelectorArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PodTemplateSpecArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ObjectMetaArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PodSpecArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ContainerArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;nginx:latest&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;p&gt;Now have a look into the more complex example with variables and loops in Pulumi. I am using &lt;code&gt;TypeScript&lt;/code&gt; as an example,
but you can of course use any of the Pulumi supported languages.&lt;/p&gt;
&lt;h3 id="example-with-variables-and-loops-1"&gt;Example with Variables and Loops&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nginxImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;nginxImage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx:latest&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;replicas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;replicas&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberOfDeployments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;numberOfDeployments&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;numberOfDeployments&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;k8s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Deployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`nginxDeployment-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sb"&gt;`nginx-deployment-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;replicas&lt;/span&gt;: &lt;span class="kt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;matchLabels&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sb"&gt;`nginx-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;labels&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sb"&gt;`nginx-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;containers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nginx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;image&lt;/span&gt;: &lt;span class="kt"&gt;nginxImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this example, you can see how easy it is to define multiple &lt;code&gt;Deployment&lt;/code&gt; objects with variables and loops syntax provided by &lt;code&gt;TypeScript&lt;/code&gt;. This is a big advantage over plain YAML files and Terraform HCL. Blending the full power of a general-purpose programming language with the Kubernetes API is a natural process. Consider the possibilities of creating reusable functions, classes, and modules. You could share them across multiple projects and teams.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;
&lt;p&gt;&lt;strong&gt;You might also like:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/"&gt;
Integrating DevOps and Security in Platform Engineering
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/why-every-platform-engineer-should-care-about-kubernetes-operators/"&gt;
Why Every Platform Engineer Should Care About Kubernetes Operators
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/"&gt;
DevSecOps Game-Changer: Security Automation That Delivers Business Results
&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="pros-and-cons-of-pulumi"&gt;Pros and Cons of Pulumi&lt;/h3&gt;
&lt;h4 id="pros-2"&gt;Pros&lt;/h4&gt;
&lt;p&gt;You can use general-purpose languages to define your Kubernetes objects. These include Python, Go, TypeScript, JavaScript, .NET, and JVM-based languages.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full IDE support:&lt;/strong&gt; You get full IDE support. It includes syntax highlighting, code completion, and debugging.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Testability:&lt;/strong&gt; You can use the full power of your programming language to test your Pulumi code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; You can use the DRY principle in Pulumi. Define reusable functions, classes, and modules in your chosen programming language.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment management:&lt;/strong&gt; You can manage multiple environments, like development, staging, and production, by defining config variables. This is a more structured way, without needing extra tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes Helm Support:&lt;/strong&gt; Pulumi supports &lt;a href="https://www.pulumi.com/registry/packages/kubernetes/api-docs/helm/"&gt;Helm charts&lt;/a&gt; out of the box. You can manage Helm charts with Pulumi without needing extra tools or providers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Programmatic execution of Pulumi:&lt;/strong&gt; You can further blend Pulumi code into your projects using the &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/automation-api/"&gt;Pulumi Automation API&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="cons-2"&gt;Cons&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Runtime dependency:&lt;/strong&gt; You must have the runtime of your chosen programming language installed on your machine, or use a containerised version of it in your CI/CD pipeline.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Follow best practices and compliance:&lt;/strong&gt; Set up a code review process. It should ensure the Pulumi code follows the best practices of your chosen programming language and your organization&amp;rsquo;s additional best practices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No possibility to convert one Pulumi language to another:&lt;/strong&gt; If you start with one language, you can&amp;rsquo;t convert the Pulumi code to another language. You need to rewrite the Pulumi code in the new language.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="yaml-vs-terraform-vs-pulumi---results"&gt;YAML vs. Terraform vs. Pulumi - Results&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;YAML&lt;/th&gt;
&lt;th&gt;Terraform&lt;/th&gt;
&lt;th&gt;Pulumi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Readability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Simple and human-readable&lt;/td&gt;
&lt;td&gt;⚠️ Requires learning HCL&lt;/td&gt;
&lt;td&gt;✅ Uses familiar programming languages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Environment Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Requires manual management of multiple files&lt;/td&gt;
&lt;td&gt;✅ Structured management via variables&lt;/td&gt;
&lt;td&gt;✅ Structured management via config variables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DRY Principle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ No reusability, requires manual updates&lt;/td&gt;
&lt;td&gt;✅ Supports modules and reusable code&lt;/td&gt;
&lt;td&gt;✅ Full support via functions, classes, modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dynamic Configuration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Static configuration only&lt;/td&gt;
&lt;td&gt;✅ Supports loops, conditions, variables&lt;/td&gt;
&lt;td&gt;✅ Full programming language capabilities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IDE Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Good support&lt;/td&gt;
&lt;td&gt;⚠️ Limited, requires plugins&lt;/td&gt;
&lt;td&gt;✅ Full language-native IDE support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Testing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Limited testing options&lt;/td&gt;
&lt;td&gt;⚠️ Requires specialized tools (Terratest)&lt;/td&gt;
&lt;td&gt;✅ Native language testing frameworks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Helm Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Native support&lt;/td&gt;
&lt;td&gt;⚠️ Requires additional provider&lt;/td&gt;
&lt;td&gt;✅ Built-in support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Low&lt;/td&gt;
&lt;td&gt;⚠️ Medium (new DSL)&lt;/td&gt;
&lt;td&gt;⚠️ Varies by language knowledge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dependencies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Minimal&lt;/td&gt;
&lt;td&gt;⚠️ Terraform installation&lt;/td&gt;
&lt;td&gt;❌ Language runtime required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ecosystem Tools&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Requires additional tools (Helm, Kustomize)&lt;/td&gt;
&lt;td&gt;✅ Integrated tooling&lt;/td&gt;
&lt;td&gt;✅ Integrated tooling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Abstraction&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Limited&lt;/td&gt;
&lt;td&gt;✅ Good&lt;/td&gt;
&lt;td&gt;✅ Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Legend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Good/Supported&lt;/li&gt;
&lt;li&gt;⚠️ Partial/With limitations&lt;/li&gt;
&lt;li&gt;❌ Poor/Not supported&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="time-to-say-goodbye-to-yaml"&gt;Time to say Goodbye to YAML?&lt;/h2&gt;
&lt;p&gt;&lt;img src="yaml_simpsons.png" alt="yaml_simpsons.png"&gt;&lt;/p&gt;
&lt;p&gt;So, what&amp;rsquo;s the smart choice for deployment automation with Kubernetes? Is YAML still the best choice for Kubernetes? Or, is there a better way to manage your resources? I understand if you are a YAML fan. Despite complaints, it is still the most popular way to define Kubernetes objects. Many folks feel a sense of accomplishment when their YAML file works on the first try.&lt;/p&gt;
&lt;p&gt;If you have a complex project, you will soon hit the limits of YAML. You want to manage your Kubernetes resources in a more structured, dynamic way while following best practices and compliance. Then, you keep adding more complexity to your YAML files. You do this by using tools like &lt;code&gt;helm&lt;/code&gt; and &lt;code&gt;kustomize&lt;/code&gt; to fix YAML&amp;rsquo;s flaws. Or, you adopt a hybrid approach with &lt;code&gt;jsonnet&lt;/code&gt;, &lt;code&gt;cuelang&lt;/code&gt;, or &lt;code&gt;ytt&lt;/code&gt;. This makes it even more complex.&lt;/p&gt;
&lt;p&gt;Giving up on YAML is not easy, but it does not mean that you have to give up on control. You can still have full control by using Terraform or Pulumi.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Now it&amp;rsquo;s time to make a decision. What&amp;rsquo;s the smart choice for deployment automation with Kubernetes? Is it YAML, Terraform, or Pulumi? For me, the smart choice is Pulumi. It gives you all the benefits of a general-purpose programming language. You gain full control, a more streamlined workflow, and the power to define all your infrastructure needs as code beyond Kubernetes. Especially on complex projects, use Pulumi. It&amp;rsquo;s better than dealing with many YAML files and the complexity of Terraform HCL.&lt;/p&gt;
&lt;p&gt;Next time you start a new project, try Pulumi. See for yourself that it&amp;rsquo;s a smart choice. It&amp;rsquo;s an upgrade to your productivity and happiness.&lt;/p&gt;
&lt;p&gt;But that&amp;rsquo;s my opinion. What&amp;rsquo;s your opinion? What&amp;rsquo;s your smart choice for deployment automation with Kubernetes?&lt;/p&gt;
&lt;p&gt;If you want to try out Pulumi or play around to prove &lt;a href="https://www.pulumi.com/blog/author/engin-diri"&gt;me&lt;/a&gt; wrong, you can start with:&lt;/p&gt;
&lt;section class="my-16"&gt;
&lt;div class="container mx-auto max-w-5xl md:flex my-8 align-top justify-center text-center"&gt;
&lt;div class="md:w3-/12 mr-4"&gt;
&lt;h2 class="no-anchor"&gt;Get Started with Pulumi&lt;/h2&gt;
&lt;p class="text-gray-700 dark:text-gray-300 text-sm"&gt;Use Pulumi's open-source SDK to create, deploy, and manage infrastructure on any cloud.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="mx-auto max-w-4xl"&gt;
&lt;div class="tiles flex-wrap mt-4"&gt;
&lt;div class="pb-4 md:pr-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/aws/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/aws.svg" alt="AWS" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="pb-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/azure/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/azure.svg" alt="Azure" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="pb-4 md:pr-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/gcp/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/gcp.svg" alt="Google Cloud" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;div class="pb-4 md:w-1/2"&gt;
&lt;a class="tile p-8" href="https://www.pulumi.com/docs/iac/get-started/kubernetes/"&gt;
&lt;img class="h-10 mx-auto" src="https://www.pulumi.com/logos/tech/k8s.svg" alt="Kubernetes" /&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;</description><author>Engin Diri</author><category>platform-engineering</category><category>kubernetes</category><category>terraform</category><category>kubecon</category></item><item><title>Pulumi Patterns and Practices Platform (P3): Some Assembly Required</title><link>https://www.pulumi.com/blog/p3-some-assembly-required/</link><pubDate>Mon, 11 Nov 2024 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/p3-some-assembly-required/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/p3-some-assembly-required/index.png" /&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Note: This post discusses Pulumi Copilot, which Pulumi Neo has replaced. &lt;a href="https://www.pulumi.com/docs/ai/"&gt;Learn about Neo →&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Setting up an internal developer platform (IDP) can be a daunting task. There are a lot of tools out there that do some of the work for you, but none of them do all of it. Pulumi P3 is no different. Pulumi Patterns &amp;amp; Practices Platform (P3) is a &lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/"&gt;reference architecture&lt;/a&gt; that we will be describing, and providing code for, through this series of articles.&lt;/p&gt;
&lt;p&gt;We will never try to sell you on the idea that you can simply download a package, click next a few times, and achieve transformative success. That’s because any effective IDP will require some customization and integration to work within your environment.&lt;/p&gt;
&lt;p&gt;Tools that purport to have it all figured out have only figured out how to manipulate you into a false narrative they have constructed in a vacuum, where all your organizational needs fit neatly into a few boxes they’ve decided on for you. And also charge you for. In addition to everything else you’re being charged for. Ultimately you’ll still need to build a lot yourself and these products rarely give guidance on how to do that.&lt;/p&gt;
&lt;p&gt;When we first started hearing about our customers using Pulumi as an internal developer platform (IDP), we were frankly surprised, as our goals were primarily for Pulumi to be the best developer experience in infrastructure. But it makes sense. All the parts are there, some assembly required. Our goal with Pulumi Patterns and Practices Platform (P3) is to help with that assembly process.&lt;/p&gt;
&lt;p&gt;Starting with our &lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/"&gt;previous blog post&lt;/a&gt; on the topic, and continuing here, we are examining this use case, and attempting to formalize that into a collection of reusable components and some guidance on how you can skip the marketing pitches and pricing charts, and get straight to the hard work of building your own highly customized internal developer platform with Pulumi at its core.&lt;/p&gt;
&lt;h2 id="pulumi-p3-bill-of-materials"&gt;Pulumi P3: Bill of Materials&lt;/h2&gt;
&lt;p&gt;Previously we identified the &lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#an-effective-internal-developer-platform"&gt;essential qualities of an effective IDP&lt;/a&gt;. Those were consistency, reproducibility, visibility, security and compliance, auditability, developer experience. In the &lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#a-holistic-view-of-the-patterns-and-practices-platform-reference-architecture"&gt;last half of the post&lt;/a&gt; we discussed which parts of Pulumi could be used to meet those needs. That looks like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consistency&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/learn/abstraction-encapsulation/component-resources/"&gt;component resources&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-portals/templates/"&gt;organization templates&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/drift/"&gt;drift detection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reproducibility&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/learn/building-with-pulumi/understanding-stacks/"&gt;stacks&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;deployments&lt;/a&gt;, &lt;a href="https://www.pulumi.com/registry/packages/snowflake/api-docs/dynamictable/"&gt;versioned data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visibility&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;Pulumi Insights&lt;/a&gt;, &lt;a href="https://www.pulumi.com/product/copilot/"&gt;Pulumi Copilot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security and Compliance&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/"&gt;RBAC&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/#github-based-teams"&gt;GitHub Teams&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/saml/"&gt;SAML-SSO&lt;/a&gt;, &lt;a href="https://www.pulumi.com/product/esc/"&gt;Pulumi ESC&lt;/a&gt;, &lt;a href="https://www.pulumi.com/crossguard/"&gt;Pulumi Crossguard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auditability&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/audit-logs/"&gt;audit logging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developer Experience&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/languages-sdks/"&gt;Python/Go/JavaScript/C#&lt;/a&gt;, &lt;a href="https://www.pulumi.com/blog/next-level-iac-breakpoint-debugging/"&gt;popular IDE support&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/cli/"&gt;command-line tools&lt;/a&gt;, &lt;a href="https://www.pulumi.com/automation/"&gt;deeply hackable&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s all great, and much of that is already built-into Pulumi without the need for you to do anything at all. So, what parts do you actually need to set up and configure? Here’s the bill of materials (BOM) to set up your own instance of Pulumi P3:&lt;/p&gt;
&lt;h3 id="bill-of-materials"&gt;Bill of Materials:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Authentication and Identity Management&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A GitHub organization that matches your Pulumi Cloud organization&lt;/li&gt;
&lt;li&gt;GitHub Teams users and roles that match your organizational structure and security needs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Secrets, Configuration, and Policy&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pulumi ESC environments to manage secrets across clouds&lt;/li&gt;
&lt;li&gt;Pulumi Crossguard policy packs that capture your company policies&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Developer Experience&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A set of reusable multi-language components for cross-cutting concerns/common services&lt;/li&gt;
&lt;li&gt;A set of organization templates that match your common use cases&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s go through each of those and briefly discuss what it looks like to set that up.&lt;/p&gt;
&lt;h2 id="authentication-and-identity-management"&gt;Authentication and identity management&lt;/h2&gt;
&lt;p&gt;We highly recommend using GitHub for code management. So much so that we have deeply integrated GitHub into Pulumi Cloud across a number of features. While we support &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/organizations/#gitlab-identity-provider"&gt;alternatives such as GitLab&lt;/a&gt;, this will be the easiest and more feature-rich way to configure your platform.&lt;/p&gt;
&lt;p&gt;In Pulumi Cloud, you have the ability to create organizations. A &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/organizations/"&gt;Pulumi Cloud organization&lt;/a&gt; can help you manage teams, roles, stacks, settings, and provide a dashboard across the entire organization. Pulumi Cloud also allows you to use a variety of identity providers to log in, including GitHub.&lt;/p&gt;
&lt;p&gt;For simplicity’s sake, we suggest that you start with your GitHub organization. &lt;a href="https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch"&gt;Create the GitHub organization&lt;/a&gt;, &lt;a href="https://docs.github.com/en/organizations/organizing-members-into-teams/about-teams"&gt;set up teams&lt;/a&gt;, and &lt;a href="https://docs.github.com/en/organizations/organizing-members-into-teams/adding-organization-members-to-a-team"&gt;add members&lt;/a&gt; to those teams, assigning either admin or user &lt;a href="https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/using-organization-roles"&gt;roles&lt;/a&gt; to each member.&lt;/p&gt;
&lt;p&gt;Next, in Pulumi Cloud, create an organization &lt;em&gt;&lt;strong&gt;with exactly the same name&lt;/strong&gt;&lt;/em&gt; as your GitHub organization, and choose GitHub as your identity provider. When a Pulumi organization is backed by a GitHub organization, then only members of that GitHub organization may be added to the Pulumi organization. Similarly, as soon as someone loses access to the GitHub organization, they will no longer have access to the Pulumi organization. You will also be able to &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/#github-based-teams"&gt;import your GitHub teams&lt;/a&gt; directly into Pulumi Cloud. Then assign your users to the same roles in Pulumi Cloud teams as they have in the associated GitHub teams.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/p3-some-assembly-required/teams-gh-pulumi.png"
alt="Figure: Mapping GitHub orgs, teams, and roles to Pulumi"&gt;&lt;figcaption&gt;
&lt;p&gt;Figure: Mapping GitHub orgs, teams, and roles to Pulumi&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Finally, you can &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/#granting-access-to-stacks-within-teams"&gt;map teams to stacks&lt;/a&gt; to grant access at specific permission levels. If you’re not familiar with &lt;a href="https://www.pulumi.com/docs/concepts/stack/"&gt;Pulumi Stacks&lt;/a&gt;, a stack is a materialized instance of a specific set of cloud resources, as defined in a Pulumi program.&lt;/p&gt;
&lt;h2 id="pulumi-esc-managing-credentials-configuration-and-other-secrets"&gt;Pulumi ESC: Managing credentials, configuration, and other secrets&lt;/h2&gt;
&lt;p&gt;In order to deploy a stack you will need secrets such as cloud credentials and other configuration values that are provided to the deployment engine. Pulumi ESC is a secure system for managing secrets. They are organized by &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/concepts/environments/"&gt;environments&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;An example set of environments might look something like this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; AWS login/credentials&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# aws-creds ESC environment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;fn::open::aws-login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;oidc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;roleArn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;arn:aws:iam::123456789012:role/pulumi-environments-oidc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;sessionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pulumi-environments-session&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1h&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environmentVariables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${aws.creds.accessKeyId}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${aws.creds.secretAccessKey}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;AWS_SESSION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${aws.creds.sessionToken}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Default production environment to use &lt;code&gt;us-east-1&lt;/code&gt; region&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# aws-production ESC environment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aws-creds&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;us-east-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pulumiConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws:region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${aws.region}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Default staging environment to use &lt;code&gt;us-west-2&lt;/code&gt; region&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# aws-staging ESC environment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aws-creds&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;us-west-2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pulumiConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws:region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${aws.region}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here we define three environments for AWS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aws-creds&lt;/code&gt;: sets up login via OpenID Connect (OIDC) and provides standard environment variables containing AWS credentials to the Pulumi program&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aws-production&lt;/code&gt;: imports everything from &lt;code&gt;aws-creds&lt;/code&gt; then sets the region to &lt;code&gt;us-east-1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aws-staging&lt;/code&gt;: does the same, but sets the region to &lt;code&gt;us-west-2&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using that in a Pulumi program is as simple as adding the following settings to your stack config:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Pulumi.staging.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aws-staging&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this manner, you can configure separate environments for staging and production, with a complex set of configuration values and secrets, using different environments for each one. From the developer’s perspective they would only need to change &lt;code&gt;aws-staging&lt;/code&gt; to &lt;code&gt;aws-production&lt;/code&gt; when they go to deploy their stack.&lt;/p&gt;
&lt;p&gt;Another strong benefit of this approach is that all secrets will be encrypted both in-flight and at-rest. Pulumi waits until the last moment to decrypt secrets at runtime. By default, uses automatic, per-stack encryption keys provided by Pulumi Cloud, but you could use a &lt;a href="https://www.pulumi.com/docs/concepts/secrets/#configuring-secrets-encryption"&gt;provider of your own choosing&lt;/a&gt; instead.&lt;/p&gt;
&lt;h2 id="pulumi-crossguard-policy-as-code"&gt;Pulumi Crossguard: Policy-as-Code&lt;/h2&gt;
&lt;p&gt;Pulumi Crossguard allows you to check and enforce policies on your deployments. Policies are rules, written in code, that run during deployments to check that the resources are conforming to the necessary criteria. You can use off-the-shelf policies like &lt;a href="https://www.pulumi.com/docs/using-pulumi/crossguard/awsguard"&gt;AWSGuard&lt;/a&gt; and &lt;a href="https://github.com/pulumi/compliance-policies/"&gt;Pulumi Compliance-Ready Policies&lt;/a&gt; or write your own.&lt;/p&gt;
&lt;p&gt;Either way you end up with a &lt;em&gt;policy pack&lt;/em&gt; that you can apply to your entire Pulumi organization via Pulumi Cloud.&lt;/p&gt;
&lt;p&gt;Here’s an example policy that checks for the presence of a tag &lt;code&gt;user:Stack&lt;/code&gt; on a S3 bucket:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pulumi_policy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;EnforcementLevel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;PolicyPack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ResourceValidationPolicy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;s3_check_required_tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws:s3/bucket:Bucket&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;user:Stack&amp;#34;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;S3 Bucket is missing required user:Stack tag.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;PolicyPack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;bucket-tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;enforcement_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;EnforcementLevel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MANDATORY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;policies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ResourceValidationPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;s3-tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Ensure required tags are present on S3 buckets.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s3_check_required_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the tag isn&amp;rsquo;t on the resource, it blocks the deployment with an error message. The error message would look something like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Policies:
❌ bucket-tags@v0.0.1
- [mandatory] s3-tags (aws:s3/bucket:Bucket: my-bucket)
Ensure required tags are present on S3 buckets.
S3 Bucket is missing required user:Stack tag.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This allows you to implement company-specific policies that can be as simple or complex as you need them to be.&lt;/p&gt;
&lt;p&gt;To apply this across your entire organization, you can &lt;a href="https://www.pulumi.com/docs/using-pulumi/crossguard/get-started/#enforcing-a-policy-pack"&gt;publish this policy pack to Pulumi Cloud&lt;/a&gt;, with the following commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pulumi policy publish myorg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pulumi policy &lt;span class="nb"&gt;enable&lt;/span&gt; myorg/my-policy-pack latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some other great features of Crossguard are the ability to &lt;a href="https://www.pulumi.com/docs/using-pulumi/crossguard/faq/#how-do-i-version-a-policy-pack"&gt;version policies&lt;/a&gt;, define multiple &lt;a href="https://www.pulumi.com/docs/using-pulumi/crossguard/core-concepts/#policy-groups"&gt;policy groups&lt;/a&gt;, and create &lt;a href="https://www.pulumi.com/blog/remediation-policies/"&gt;remediation policies&lt;/a&gt; that automatically fix policy violations when possible. We will cover these topics in a future post where we go deeper on how to use policies effectively.&lt;/p&gt;
&lt;h2 id="multi-language-components-mlc"&gt;Multi-Language Components (MLC)&lt;/h2&gt;
&lt;p&gt;In Pulumi, a &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/concepts/resources/components/"&gt;component resource&lt;/a&gt;&lt;/em&gt; is something that your developers can import in their Pulumi program, instantiate and modify. These are made available via a &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/concepts/resources/providers/"&gt;provider&lt;/a&gt;&lt;/em&gt;, which is in turn, made available to Pulumi via a &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/using-pulumi/pulumi-packages/"&gt;provider package&lt;/a&gt;&lt;/em&gt;. There are many of these already available in the &lt;a href="https://www.pulumi.com/registry/"&gt;Pulumi Registry&lt;/a&gt;. However, in a custom internal developer platform you can define your own components, and bake appropriate settings/configuration directly into the underlying code.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;multi-language component (MLC)&lt;/em&gt; is even more useful. You can author your component in your language of choice and then generate a SDK that surfaces that component into all of the languages that Pulumi supports. For example, your platform team might be comfortable writing in Python, but the developers that write your microservices might use Go, and the developers who write the front-end apps might use Node.js. Both teams might need to deploy apps and infrastructure into your Kubernetes cluster. With multi-language components you can write a component in Python that abstracts away all the details of your custom Kubernetes cluster, and make that available to both teams, in both Go, Node.js, and any other language that Pulumi supports.&lt;/p&gt;
&lt;p&gt;To build a MLC, you&amp;rsquo;ll follow these basic steps to create the component, provider, provider package, and generate the multi-language SDK:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fork one of the component provider boilerplate repos for &lt;a href="https://github.com/pulumi/pulumi-component-provider-py-boilerplate"&gt;Python&lt;/a&gt;, &lt;a href="https://github.com/pulumi/pulumi-component-provider-ts-boilerplate"&gt;TypeScript&lt;/a&gt;, or &lt;a href="https://github.com/pulumi/pulumi-component-provider-go-boilerplate"&gt;Go&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Update the package and code-generator configuration files, which name your component and package, define the inputs and outputs, and declare the dependencies.&lt;/li&gt;
&lt;li&gt;Implement the component in your preferred language.&lt;/li&gt;
&lt;li&gt;Generate an SDK for the other languages.&lt;/li&gt;
&lt;li&gt;Deploy the package.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here’s a quick example of creating a custom S3 Bucket component in Python, that complies with the tagging policy we built earlier:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pulumi_aws&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TaggedBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ComponentResource&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mycorp:index:TaggedBucket&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Create a bucket and add a custom tag to it.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;-bucket&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;user:Stack&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_stack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ResourceOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_outputs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;bucket&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;websiteUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;website_endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;bucketDnsName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucketDomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This shows the component implementation in isolation from the provider/packaging/SDK boilerplate. In this code sample, we’re creating a component called &lt;code&gt;TaggedBucket&lt;/code&gt; that creates a S3 bucket, and adds a tag &lt;code&gt;user:Stack&lt;/code&gt; with the current stack name as its value. A developer could now use this in a TypeScript Pulumi program as such, and this resource would automatically have the tags added to it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;mycorp&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;mycorp/mycorp-components&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;taggedBucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mycorp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TaggedBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;example&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;taggedBucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;taggedBucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;websiteUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dnsName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;taggedBucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucketDnsName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you want to see how to create MLCs in more detail, check out &lt;a href="https://www.youtube.com/watch?v=_RXvNS5N8A8"&gt;this video&lt;/a&gt; that walks you through the entire process, and &lt;a href="https://github.com/jaxxstorm/pulumi-productionapp"&gt;this repo&lt;/a&gt; for the code shown in the video. In a follow-up post in this series, we will build some reference MLCs that do things like implement a time-to-live (TTL) for stacks in your staging environment, automate drift detection, and automatically instrument your developer’s deployments with observability tools integrated by default.&lt;/p&gt;
&lt;h2 id="organization-templates-and-the-new-project-wizard"&gt;Organization templates and the New Project Wizard&lt;/h2&gt;
&lt;p&gt;The final piece that ties all this together are &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-portals/templates/"&gt;organization templates&lt;/a&gt;&lt;/em&gt;. You may have used some of our &lt;a href="https://www.pulumi.com/templates/"&gt;built-in templates&lt;/a&gt; when you learned how to use Pulumi. These are great for basic use cases, but the real magic happens when you bring together your custom components and custom security environments to create personalized templates which represent the internal use cases for your organization.&lt;/p&gt;
&lt;p&gt;Pulumi’s &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-portals/new-project-wizard/"&gt;New Project Wizard&lt;/a&gt; reads these templates and provides an in-browser way to create a new project and deploy it. Running one of these templates will commit and push code to GitHub, and trigger an initial deployment – all in a few clicks and without leaving the browser.&lt;/p&gt;
&lt;p&gt;Each template needs the following parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;Pulumi.yaml&lt;/code&gt; describing the template and its configuration values&lt;/li&gt;
&lt;li&gt;A GitHub repo (public or private) containing the code for the templated Pulumi program&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s an example of a simple template using the components and environments we described above.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Pulumi.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${PROJECT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${DESCRIPTION}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;python&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;A Python Pulumi program that creates a tagged bucket.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;__main__.py: A minimal Pulumi program&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mycorp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create an AWS resource (S3 Bucket)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tagged_bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mycorp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaggedBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;my-bucket&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Export the name of the bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bucket_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tagged_bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Pulumi.production.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aws-production&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Pulumi.staging.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aws-staging&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;Pulumi.yaml&lt;/code&gt; sets up the template and will populate the name and description from the settings provided during the template dialogue. The custom &lt;code&gt;TaggedBucket&lt;/code&gt; component will create an S3 bucket, which will be tagged with &lt;code&gt;user:Stack&lt;/code&gt; set to the name of the stack. Default stack configurations are provided for the &lt;code&gt;staging&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; environments which map to our two ESC environments, &lt;code&gt;aws-production&lt;/code&gt; and &lt;code&gt;aws-staging&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="how-it-all-works-together"&gt;How it all works together&lt;/h2&gt;
&lt;p&gt;With all of that in place, from the developer’s perspective, all they need to do is create a new project from the template, answering three questions: the stack name, the name of the project, and an optional description.&lt;/p&gt;
&lt;p&gt;If the developer names the stack &lt;code&gt;staging&lt;/code&gt; it will automatically apply the &lt;code&gt;aws-staging&lt;/code&gt; ESC environment, which will include the AWS credentials and set the region to &lt;code&gt;us-west-2&lt;/code&gt;. However, if the developer names the stack &lt;code&gt;production&lt;/code&gt; it will get the &lt;code&gt;aws-production&lt;/code&gt; ESC environment setting it to use the &lt;code&gt;us-east-1&lt;/code&gt; region. The name of the stack will be stored in a tag on the resource.&lt;/p&gt;
&lt;p&gt;Pulumi Crossguard will apply the &lt;code&gt;bucket-tags&lt;/code&gt; policy check to see if the resource has the required &lt;code&gt;user:Stack&lt;/code&gt; tag set and will allow the deployment to proceed only if it has that tag. If a developer created a standard S3 Bucket instead of using our internal &lt;code&gt;TaggedBucket&lt;/code&gt; component, and failed to add the required tag, they will get an error message from our custom policy when they try to deploy.&lt;/p&gt;
&lt;p&gt;Later, we can create additional automation that might do something like delete anything tagged &lt;code&gt;staging&lt;/code&gt; after two weeks, or run drift detection on anything tagged &lt;code&gt;production&lt;/code&gt;. We will be exploring these concepts in more detail in later posts.&lt;/p&gt;
&lt;h3 id="more-to-come"&gt;More to Come&lt;/h3&gt;
&lt;p&gt;While setting up the Pulumi Patterns and Practices Platform (P3) reference architecture is not a simple click-to-deploy, hopefully this high-level tour of the various parts you need to assemble shows that really, it is only a matter of creating a few carefully constructed YAML files and snippets of code, and wiring them together properly. You can start small and build out your platform over time.&lt;/p&gt;
&lt;p&gt;The next few posts in this series will go beyond these simple examples, showing much more complicated implementations of all of these pieces, and recommend some best practices for managing your infrastructure with this platform.&lt;/p&gt;
&lt;p&gt;And if you are already ready to get your hands on Pulumi after this introduction, feel free to &lt;a href="https://www.pulumi.com/signup/"&gt;create an account&lt;/a&gt; and follow some of our &lt;a href="https://www.pulumi.com/docs/get-started/"&gt;Getting Started&lt;/a&gt; guides to see how easy simple use cases are and begin to imagine how that same developer experience will scale up to your entire organization.&lt;/p&gt;
&lt;p&gt;To learn more, you can watch the following video which provides a high level overview of how Pulumi works:&lt;/p&gt;
&lt;div class="rounded-md shadow border border-gray-300 w-3/4 mx-auto my-4" style="position: relative; padding-bottom: 40.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe
src="//www.youtube.com/embed/Q8tw6YTD3ac?rel=0"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;"
allowfullscreen=""
title="Introduction to Pulumi in Three Minutes"
srcdoc="&lt;style&gt;*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img{position:absolute;width:100%;top:0;bottom:0;margin:auto}&lt;/style&gt;&lt;a href=https://www.youtube.com/embed/Q8tw6YTD3ac?autoplay=1&gt;&lt;img src='https://www.pulumi.com/images/home/youtube-getting-started.png' alt='Introduction to Pulumi in Three Minutes'&gt;&lt;/a&gt;"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id="pulumi-cloud"&gt;Pulumi Cloud&lt;/h2&gt;
&lt;p&gt;The Pulumi Cloud is a fully managed service that helps you adopt Pulumi&amp;rsquo;s open source SDK with ease. It provides built-in state and secrets management, integrates with source control and CI/CD, and offers a web console and API that make it easier to visualize and manage infrastructure. It is free for individual use, with features available for teams.&lt;/p&gt;
&lt;p&gt;&lt;a class="btn btn-secondary" href="https://app.pulumi.com/signup" target="_blank"&gt;Create an Account&lt;/a&gt;&lt;/p&gt;</description><author>Troy Howard</author><category>platform-engineering</category><category>patterns-and-practices-platform</category><category>developer-experience</category><category>devsecops</category><category>architecture</category><category>enterprise</category><category>devops</category></item><item><title>The Guide to Platform Engineering: 7 Steps to Get It Right</title><link>https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices/</link><pubDate>Tue, 22 Oct 2024 07:47:03 +0000</pubDate><guid>https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/the-guide-platform-engineering-idp-steps-best-practices/index.png" /&gt;
&lt;p&gt;In today’s fast-paced digital landscape, organizations are increasingly adopting platform engineering to optimize their software delivery and operations. Gartner predicts that by 2026, 80% of large software engineering organizations will have platform engineering teams to provide reusable services, components, and tools for application delivery. Additionally, by 2027, 80% of large enterprises will leverage platform engineering to scale DevOps initiatives in hybrid cloud environments effectively.&lt;/p&gt;
&lt;p&gt;This shift is driven by the rise of cloud adoption, where many enterprises face the challenge of uncoordinated application teams deploying workloads in different ways across various cloud platforms. This siloed approach often results in a lack of standardization, security risks, and operational inefficiencies.&lt;/p&gt;
&lt;p&gt;Platform engineering offers a strategic solution to these issues. This guide provides the essential steps to successfully implement platform engineering, from laying the foundation to scaling internal developer platforms (IDPs) for future growth.&lt;/p&gt;
&lt;h2 id="on-this-article"&gt;On this article:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices#step-1-securing-executive-buy-in"&gt;Step 1: Securing Executive Buy-in&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices#step-2-staffing-the-platform-engineering-team"&gt;Step 2: Staffing the Platform Engineering Team&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices#step-3-defining-the-platform-mandate"&gt;Step 3: Defining the Platform Mandate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices#step-4-implementing-the-pre-production-pipeline"&gt;Step 4: Implementing the Pre-Production Pipeline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices#step-5-embracing-infrastructure-as-code"&gt;Step 5: Embracing Infrastructure as Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices#step-6-implementing-policy-as-code"&gt;Step 6: Implementing Policy as Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices#step-7-evolving-towards-self-service"&gt;Step 7: Evolving Towards Self-Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices#frequently-asked-questions"&gt;Frequently Asked Questions (Platform Engineering Concepts &amp;amp; Definitions)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="step-1-securing-executive-buy-in"&gt;Step 1: Securing Executive Buy-in&lt;/h2&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/t4c3NOiuhXQ?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;The first step in your platform engineering journey is securing executive buy-in. This high-level support is essential, as platform engineering teams must create an organization-wide strategy that integrates internal developer portals (IDPs) and self-service capabilities. Leadership needs to understand how platform engineering can address inefficiencies caused by siloed application teams and uncoordinated cloud deployments.&lt;/p&gt;
&lt;p&gt;To do this, present a clear roadmap with measurable outcomes, such as improved delivery speed and security. Use metrics like &lt;a href="https://en.wikipedia.org/wiki/DevOps_Research_and_Assessment"&gt;DORA&lt;/a&gt; (Deployment Frequency, Lead Time, Mean Time to Recovery) to demonstrate how platform engineering enhances security, standardization, and efficiency. Outline the required resources (headcount, budget, tooling) and align the project with business objectives.&lt;/p&gt;
&lt;h2 id="step-2-staffing-the-platform-engineering-team"&gt;Step 2: Staffing the Platform Engineering Team&lt;/h2&gt;
&lt;p&gt;Once you have executive backing, the next step is to assemble your platform engineering team. This team will &lt;a href="https://www.pulumi.com/blog/developer-portal-platform-teams/"&gt;develop and maintain your internal developer platform (IDP)&lt;/a&gt;, ensuring it offers the organization secure, scalable, and self-service solutions.&lt;/p&gt;
&lt;p&gt;Successful platform engineering teams are characterized by a strong customer focus, empathy for the needs of application teams, and the ability to act as the &amp;ldquo;glue&amp;rdquo; that binds the organization together. Key roles and responsibilities within the platform team include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Customer-facing roles&lt;/strong&gt;: Serve as the primary point of contact for application teams, understanding their needs and advocating for their requirements within the platform.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure expertise&lt;/strong&gt;: Possess deep knowledge of the underlying infrastructure, whether on-premises or in the cloud, to ensure the platform is reliable and scalable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DevOps and automation skills&lt;/strong&gt;: Leverage infrastructure as code (IaC) tools and techniques to automate the provisioning and management of the platform.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/finops-with-pulumi/"&gt;FinOps&lt;/a&gt; and cost optimization expertise&lt;/strong&gt;: Understand the organization&amp;rsquo;s financial systems and processes to ensure the platform is cost-effective and aligned with budgetary constraints.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Software development capabilities&lt;/strong&gt;: Develop the platform&amp;rsquo;s core components, including self-service interfaces and reusable infrastructure modules, using best practices in software engineering.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By assembling a team with this diverse set of skills and a customer-centric mindset, you&amp;rsquo;ll be well-positioned to build a platform that truly meets the needs of your application teams.&lt;/p&gt;
&lt;h2 id="step-3-defining-the-platform-mandate"&gt;Step 3: Defining the Platform Mandate&lt;/h2&gt;
&lt;p&gt;Next, clearly define the platform team’s mandate to set expectations. This document should outline the platform’s purpose, the services it provides, and how it supports &lt;a href="https://www.pulumi.com/blog/building-developer-portals/"&gt;internal developer portals (IDPs)&lt;/a&gt; and self-service capabilities.&lt;/p&gt;
&lt;p&gt;The platform mandate should serve as a central reference point for the platform team and its customers, ensuring everyone is aligned on the team&amp;rsquo;s mission and its value. Key elements to include in the platform mandate include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Introduction&lt;/strong&gt;: A high-level overview of the platform team&amp;rsquo;s purpose and the organizational outcomes it aims to achieve.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Supported systems&lt;/strong&gt;: A list of the infrastructure, services, and tools that the platform team is responsible for managing and supporting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support model&lt;/strong&gt;: Details on how application teams can access platform services, including any self-service capabilities and the team&amp;rsquo;s response times for different types of requests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Team structure&lt;/strong&gt;: An overview of the platform team&amp;rsquo;s members and their areas of expertise, making it easy for application teams to identify the right point of contact.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A well-defined mandate aligns the team and its customers with the platform’s value and purpose.&lt;/p&gt;
&lt;h2 id="step-4-implementing-the-pre-production-pipeline"&gt;Step 4: Implementing the Pre-Production Pipeline&lt;/h2&gt;
&lt;p&gt;With a mandate in place, begin building the core capabilities, starting with a pre-production pipeline. This pipeline standardizes how application code moves from development to deployment, emphasizing security and consistency.&lt;/p&gt;
&lt;p&gt;Key components of the pre-production pipeline include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Version control&lt;/strong&gt;: Implement a centralized version control system to manage application code and infrastructure as code (IaC) configurations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Continuous integration (CI)&lt;/strong&gt;: Automate the build and testing of application artifacts, such as container images or deployment packages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Artifact management&lt;/strong&gt;: Provide a secure and versioned repository for storing and distributing the application artifacts produced by the CI process.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Static analysis&lt;/strong&gt;: Integrate tools that can scan application code and dependencies for security vulnerabilities and other issues.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application delivery&lt;/strong&gt;: Automate the deployment of application artifacts to pre-production environments, such as staging or testing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By establishing a standardized pre-production pipeline, you&amp;rsquo;ll ensure that all application teams follow a consistent, secure, and efficient process for getting their code into a production-ready state.&lt;/p&gt;
&lt;h2 id="step-5-embracing-infrastructure-as-code"&gt;Step 5: Embracing Infrastructure as Code&lt;/h2&gt;
&lt;p&gt;Leveraging infrastructure as code (IaC) is crucial for managing the platform’s infrastructure. It enables consistent, scalable, and secure operations by automating the provisioning of resources, monitoring, and enforcing security policies.&lt;/p&gt;
&lt;p&gt;Key areas where IaC can be applied within the platform include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Foundational infrastructure&lt;/strong&gt;: Provision and manage the underlying cloud resources, such as virtual networks, storage, and compute, that form the platform&amp;rsquo;s foundation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Runtime platforms&lt;/strong&gt;: Deploy and configure the runtime environments where application workloads will be executed, such as Kubernetes clusters or serverless functions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability and monitoring&lt;/strong&gt;: Set up the logging, metrics, and alerting systems that provide visibility into the platform&amp;rsquo;s health and performance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security and compliance&lt;/strong&gt;: Implement security controls, such as &lt;a href="https://www.pulumi.com/docs/esc/"&gt;secrets management&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/get-started/"&gt;access policies&lt;/a&gt;, to ensure the platform meets regulatory and organizational requirements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pipelines and &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/automation-api/"&gt;automation&lt;/a&gt;&lt;/strong&gt;: Use IaC to define and version-control the platform&amp;rsquo;s own deployment and management pipelines, ensuring consistency and repeatability.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/"&gt;infrastructure as code&lt;/a&gt;, the platform engineering team can ensure reliable, scalable, and secure infrastructure across the organization.&lt;/p&gt;
&lt;h2 id="step-6-implementing-policy-as-code"&gt;Step 6: Implementing Policy as Code&lt;/h2&gt;
&lt;p&gt;Alongside your IaC efforts, it&amp;rsquo;s important to set up a robust policy-as-code framework within your platform. Policy-as-code allows you to enforce security, compliance, and operational policies programmatically. This provides governance at scale, ensuring all teams follow the same rules.&lt;/p&gt;
&lt;p&gt;Policy as code can be applied in two key ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Preventative controls&lt;/strong&gt;: Implement policies that proactively validate and reject non-compliant infrastructure changes before they are provisioned, providing fast feedback to application teams.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Detective controls&lt;/strong&gt;: Establish policies that continuously monitor the deployed infrastructure, triggering alerts or remediation actions when deviations from the desired state are detected.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By combining &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/"&gt;IaC and policy as code&lt;/a&gt; with self-service provisioning, you maintain security and compliance while giving teams autonomy.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Build your internal developer platform&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Give developers self-service infrastructure with reusable components, golden paths, and governance built in using Pulumi IDP.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/product/internal-developer-platforms/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Explore Pulumi IDP
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="step-7-evolving-towards-self-service"&gt;Step 7: Evolving Towards Self-Service&lt;/h2&gt;
&lt;p&gt;As your platform matures, the ultimate goal is to empower your application teams with self-service capabilities, allowing them to provision the infrastructure and resources they need quickly and autonomously. This self-service model can take various forms, from pre-defined infrastructure modules to fully automated deployment pipelines.&lt;/p&gt;
&lt;p&gt;When implementing self-service capabilities, keep the following platform engineering best practices in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Start small and iterate&lt;/strong&gt;: Don&amp;rsquo;t try to boil the ocean. Begin with a few well-defined use cases, such as CI/CD pipelines or database provisioning, and gradually expand the self-service offerings as your platform team gains experience and confidence.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/"&gt;Focus on user experience&lt;/a&gt;&lt;/strong&gt;: Ensure that the self-service interfaces, whether web-based or command-line, are intuitive and easy to use. Gather feedback from application teams and continuously refine the user experience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maintain stability and reliability&lt;/strong&gt;: Even with self-service, the platform team is responsible for ensuring the underlying infrastructure and services remain stable and reliable. Implement robust monitoring, alerting, and incident response processes to maintain platform health.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Embrace a product mindset&lt;/strong&gt;: Treat the &lt;a href="https://www.pulumi.com/blog/platform-engineering-cncf-maturity-model/#platforms-as-products-driving-success"&gt;platform as a product&lt;/a&gt;, with the application teams as your customers. Continuously gather feedback, measure key performance indicators, and iterate on the platform&amp;rsquo;s capabilities to meet evolving needs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By gradually transitioning towards a self-service model, you&amp;rsquo;ll empower your application teams to move faster while maintaining the necessary guardrails and controls to ensure the platform&amp;rsquo;s long-term success.&lt;/p&gt;
&lt;h2 id="conclusion-embracing-the-platform-engineering-journey"&gt;Conclusion: Embracing the Platform Engineering Journey&lt;/h2&gt;
&lt;p&gt;Building a successful platform engineering strategy involves following a clear roadmap. But remember, implementing the platform engineering strategy is a journey, not a destination. By following the steps outlined in this guide, you&amp;rsquo;ll be well on your way to building a robust, secure, scalable, and customer-centric internal developer platform (IDP) that empowers your organization to deliver software more efficiently and effectively.&lt;/p&gt;
&lt;p&gt;With the right approach and mindset, your platform engineering efforts will become a strategic enabler for your organization&amp;rsquo;s digital transformation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Build secure, scalable platforms with confidence—&lt;a href="https://info.pulumi.com/platform-engineering-workshop-series"&gt;register for the Platform Engineering Course&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="frequently-asked-questions"&gt;Frequently Asked Questions&lt;/h2&gt;
&lt;h3 id="what-is-platform-engineering"&gt;What is Platform Engineering?&lt;/h3&gt;
&lt;p&gt;There are many definitions for platform engineering, one of which is designing, building, and maintaining internal platforms that streamline software delivery by providing reusable tools, services, and workflows for developers. It focuses on scalability, efficiency, and self-service capabilities for internal teams.&lt;/p&gt;
&lt;p&gt;For a more in-depth explanation of real-world use cases, see &lt;a href="https://www.pulumi.com/what-is/what-is-platform-engineering/"&gt;What is platform engineering&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="who-are-the-platform-customers"&gt;Who are the Platform Customers?&lt;/h3&gt;
&lt;p&gt;The platform customers are the end users, typically internal teams (e.g., application developers and DevOps engineers), who use the platform&amp;rsquo;s tools and services to build, deploy, and manage software.&lt;/p&gt;
&lt;h3 id="what-is-an-internal-developer-platform-idp"&gt;What is an Internal Developer Platform (IDP)?&lt;/h3&gt;
&lt;p&gt;A centralized platform that offers developers the tools and environments they need to build, test, and deploy applications. It abstracts away the complexity of underlying infrastructure, allowing teams to focus on coding and delivery.&lt;/p&gt;
&lt;h3 id="what-is-a-platform-team"&gt;What is a Platform Team?&lt;/h3&gt;
&lt;p&gt;The platform engineering team is a dedicated group of engineers responsible for managing the internal platform. They ensure the platform meets the needs of the organization, providing reliability, security, and scalability.&lt;/p&gt;
&lt;h3 id="what-is-a-self-service-infrastructure"&gt;What is a Self-Service Infrastructure?&lt;/h3&gt;
&lt;p&gt;A platform feature that allows development teams to provision, configure, and manage infrastructure resources on demand without relying on other teams, fostering agility.&lt;/p&gt;
&lt;h3 id="what-is-infrastructure-as-code-iac"&gt;What is Infrastructure as Code (IaC)?&lt;/h3&gt;
&lt;p&gt;The process of managing and provisioning infrastructure through code, allowing infrastructure to be versioned, automated, and managed consistently across environments.&lt;/p&gt;
&lt;p&gt;For a more in-depth explanation, see the &lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;What is Infrastructure as Code? page&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="what-is-policy-as-code-pac"&gt;What is Policy as Code (PaC)?&lt;/h3&gt;
&lt;p&gt;Policy as Code (PaC) defines security, compliance, and &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/core-concepts/"&gt;operational policies&lt;/a&gt; in code to automate their enforcement across infrastructure and application deployments.&lt;/p&gt;
&lt;h3 id="what-is-developer-experience-devex"&gt;What is Developer Experience (DevEx)?&lt;/h3&gt;
&lt;p&gt;The overall experience developers have with using the platform, tools, and workflows provided by platform engineering. Optimizing DevEx ensures that developers can work more efficiently and effectively.&lt;/p&gt;
&lt;p&gt;For a more in-depth explanation, read &lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/"&gt;Beyond Productivity: Developer Experience is Business Critical.&lt;/a&gt;&lt;/p&gt;</description><author>Sara Huddleston</author><author>Josh Kodroff</author><category>platform-engineering</category><category>developer-portals</category><category>policy-as-code</category><category>finops</category><category>cost-efficiency</category></item><item><title>Unified and Programmatic Approach to Infrastructure Management at BMW Using Pulumi</title><link>https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/</link><pubDate>Thu, 03 Oct 2024 09:52:10 +0000</pubDate><guid>https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/index.png" /&gt;
&lt;p&gt;In the ever-evolving world of automotive technology, BMW has been at the forefront of innovation, seamlessly integrating software into the heart of their vehicles. As cars become increasingly complex, with a growing emphasis on connectivity, over-the-air upgrades, and brand-specific user experiences, the need for a robust and scalable software development approach has become paramount.&lt;/p&gt;
&lt;p&gt;Enter the BMW Software Factory, a platform that aims to empower the company&amp;rsquo;s developers and provide them with a superior development experience. At the core of this initiative is the adoption of Pulumi, a modern infrastructure as code (IaC) solution that has transformed the way BMW manages its software ecosystem.&lt;/p&gt;
&lt;h2 id="on-this-article"&gt;On this article:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#the-challenges-of-a-sprawling-software-landscape"&gt;The Challenges of a Sprawling Software Landscape&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#the-evolution-of-bmws-software-development-toolchain"&gt;The Evolution of BMW&amp;rsquo;s Software Development Toolchain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#embracing-pulumi-streamlining-infrastructure-management"&gt;Embracing Pulumi: Streamlining Infrastructure Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#the-benefits-of-pulumi-accelerating-development-and-improving-maintainability"&gt;The Benefits of Pulumi: Accelerating Development and Improving Maintainability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#the-future-of-bmws-software-factory-embracing-the-cloud"&gt;The Future of BMW&amp;rsquo;s Software Factory: Embracing the Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#conclusion-unlocking-the-future-of-automotive-software"&gt;Conclusion: Unlocking the Future of Automotive Software&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-challenges-of-a-sprawling-software-landscape"&gt;The Challenges of a Sprawling Software Landscape&lt;/h2&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/HIliBBo4c-g?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.bmwgroup.com/en/news/general/2023/BMWGroupIT.html"&gt;BMW&amp;rsquo;s software journey&lt;/a&gt; has been a testament to the exponential growth of automotive technology. What started with simple engine controllers has evolved into a complex network of electronic control units (ECUs) scattered throughout the vehicle. As the software footprint continues to expand, BMW recognized the need for a unified and efficient approach to software development and deployment.&lt;/p&gt;
&lt;p&gt;The company&amp;rsquo;s initial efforts involved introducing a platform called &amp;ldquo;Code Craft,&amp;rdquo; which provided a comprehensive stack of services to support the software development lifecycle. This stack included a GitHub Enterprise application for source code management, a Gerrit system for Android-based developments, a continuous integration (CI) pipeline, artifact stores, build caching, and various other tools and services.&lt;/p&gt;
&lt;p&gt;However, as the demand for software-driven features grew, the complexity of managing this sprawling ecosystem became increasingly challenging. BMW found itself grappling with the need to scale its infrastructure, navigate network limitations across multiple data centers, and adapt to the ever-changing landscape of cloud computing.&lt;/p&gt;
&lt;h2 id="the-evolution-of-bmws-software-development-toolchain"&gt;The Evolution of BMW&amp;rsquo;s Software Development Toolchain&lt;/h2&gt;
&lt;p&gt;BMW&amp;rsquo;s journey to streamline its software development process has been gradual and iterative. The company&amp;rsquo;s initial approach involved using &lt;a href="https://www.pulumi.com/docs/iac/comparisons/chef-puppet-etc/"&gt;Ansible&lt;/a&gt; for deployment and a custom-built deployment scripting solution for its OpenShift cluster.&lt;/p&gt;
&lt;p&gt;As the complexity of the platform increased, BMW turned to Helm and Kubernetes to manage its containerized services. However, as the company ventured into the public cloud, the limitations of these tools became apparent. The team recognized the need for a more comprehensive and scalable solution to manage their infrastructure as code.&lt;/p&gt;
&lt;p&gt;At this critical juncture, BMW discovered Pulumi. This modern IaC solution offered a unique advantage – the ability to leverage a full-fledged programming language, Python, to define and manage their infrastructure. This shift proved to be a game-changer, allowing BMW to leverage its expertise in Python and benefit from the rich ecosystem of libraries and tools available in the Python community.&lt;/p&gt;
&lt;h2 id="embracing-pulumi-streamlining-infrastructure-management"&gt;Embracing Pulumi: Streamlining Infrastructure Management&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/case-studies/bmw/"&gt;BMW&amp;rsquo;s adoption of Pulumi&lt;/a&gt; was a strategic move that aimed to address the growing complexity of its software ecosystem. By transitioning from a patchwork of tools to a unified IaC solution, the company was able to streamline its infrastructure management and improve developer productivity.&lt;/p&gt;
&lt;h3 id="shared-modules-promoting-reusability-and-best-practices"&gt;Shared Modules: Promoting Reusability and Best Practices&lt;/h3&gt;
&lt;p&gt;One of BMW&amp;rsquo;s key initiatives was developing a shared modules library, which allowed the team to abstract the complexity of various infrastructure components, such as databases, and provide a consistent and user-friendly interface for their developers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;By leveraging &lt;a href="https://www.pulumi.com/docs/iac/languages-sdks/python/"&gt;Pulumi&amp;rsquo;s Python&lt;/a&gt; bindings, BMW was able to create reusable modules that encapsulated best practices and sensible defaults, making it easier for developers to provision and manage infrastructure resources.
BMW used Pydantic, a data validation library, to define schema-based configurations for its infrastructure. These were then integrated into its IDEs, providing developers with auto-completion and validation support.&lt;/li&gt;
&lt;li&gt;This approach not only accelerated the development process but also ensured that the infrastructure deployed across the organization adhered to consistent security and compliance standards.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="transformation-features-protecting-legacy-services"&gt;Transformation Features: Protecting Legacy Services&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;As part of their software factory, BMW also faced the challenge of integrating legacy services that did not natively support modern authentication and authorization mechanisms, such as &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/oidc/provider/"&gt;OpenID Connect (OIDC)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;To address this, BMW leveraged Pulumi&amp;rsquo;s transformation features to seamlessly inject an &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/oidc/client/#exchanging-oidc-tokens"&gt;OAuth2&lt;/a&gt; proxy into their deployments, providing a secure and consistent way to protect these services without requiring extensive modifications to the underlying applications.&lt;/li&gt;
&lt;li&gt;By encapsulating this functionality within a shared module, BMW was able to apply the OAuth2 proxy to multiple services, ensuring a consistent and secure access control layer across their software ecosystem.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="policy-enforcement-ensuring-compliance-and-security"&gt;Policy Enforcement: Ensuring Compliance and Security&lt;/h3&gt;
&lt;p&gt;One key benefit of &lt;a href="https://www.pulumi.com/product/infrastructure-as-code/"&gt;Pulumi&amp;rsquo;s IaC approach&lt;/a&gt; is the ability to define and enforce policies across the organization, ensuring that infrastructure deployments adhere to security and compliance standards.
BMW has leveraged &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/"&gt;Pulumi&amp;rsquo;s policy-as-code&lt;/a&gt; capabilities to implement mandatory checks, such as ensuring that all S3 buckets are encrypted at rest, preventing the deployment of non-compliant resources.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;By integrating these policy checks into their deployment workflows, BMW has shifted security and compliance concerns to the left, addressing issues early in the development process and reducing the risk of costly post-deployment &lt;a href="https://www.pulumi.com/blog/remediation-policies/"&gt;remediations&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-benefits-of-pulumi-accelerating-development-and-improving-maintainability"&gt;The Benefits of Pulumi: Accelerating Development and Improving Maintainability&lt;/h2&gt;
&lt;p&gt;BMW&amp;rsquo;s adoption of Pulumi has yielded significant benefits, transforming the way the company approaches software development and infrastructure management.&lt;/p&gt;
&lt;h3 id="accelerated-development-with-shared-modules"&gt;Accelerated Development with Shared Modules&lt;/h3&gt;
&lt;p&gt;The implementation of shared modules has been a game-changer for BMW. It allows developers to leverage pre-built and tested infrastructure components without having to reinvent the wheel. This has resulted in a significant acceleration of the development process, as teams can focus on building their applications rather than grappling with the complexities of infrastructure provisioning.&lt;/p&gt;
&lt;h3 id="improved-maintainability-and-consistency"&gt;Improved Maintainability and Consistency&lt;/h3&gt;
&lt;p&gt;By centralizing infrastructure management within the shared modules, BMW has ensured that best practices and security standards are consistently applied across the organization. This has not only improved the overall maintainability of the software ecosystem but has also reduced the risk of security and compliance violations.&lt;/p&gt;
&lt;h3 id="leveraging-pythons-ecosystem"&gt;Leveraging Python&amp;rsquo;s Ecosystem&lt;/h3&gt;
&lt;p&gt;BMW&amp;rsquo;s decision to leverage Pulumi&amp;rsquo;s Python bindings has been a strategic advantage, as the company was able to tap into the rich ecosystem of Python libraries and tools. This has enabled the team to seamlessly integrate Pulumi with their existing Python-based toolchain, including dependency management, testing frameworks, and code quality tools, further enhancing the development experience.&lt;/p&gt;
&lt;h3 id="streamlined-cloud-migration"&gt;Streamlined Cloud Migration&lt;/h3&gt;
&lt;p&gt;As BMW continues to expand its use of public cloud services, Pulumi has played a crucial role in simplifying the &lt;a href="https://www.pulumi.com/migrate/"&gt;migration process&lt;/a&gt;. By providing a consistent IaC approach across on-premises and cloud environments, Pulumi has enabled BMW to manage its infrastructure in a unified manner, reducing the complexity and overhead associated with &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;multi-cloud deployments&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-future-of-bmws-software-factory-embracing-the-cloud"&gt;The Future of BMW&amp;rsquo;s Software Factory: Embracing the Cloud&lt;/h2&gt;
&lt;p&gt;Looking ahead, BMW&amp;rsquo;s Software Factory is poised to take the next step in its evolution, with plans to transition away from the self-hosted backend and embrace cloud-native services. This strategic move aims to further improve &lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/"&gt;developer productivity&lt;/a&gt; and reduce the internal effort required to maintain the underlying infrastructure.&lt;/p&gt;
&lt;p&gt;By leveraging the expertise and reliability of cloud service providers, BMW can focus on delivering innovative software features to their customers while the cloud providers handle the operational aspects of running the necessary services.&lt;/p&gt;
&lt;p&gt;As BMW continues to push the boundaries of automotive software, Pulumi&amp;rsquo;s role in its Software Factory will only become more crucial. By providing a scalable and flexible IaC solution, Pulumi empowers BMW&amp;rsquo;s developers to innovate with confidence and be secure in the knowledge that their infrastructure is managed consistently and in alignment with the company&amp;rsquo;s &lt;a href="https://www.pulumi.com/resources/security-automation-faster-cheaper-better/"&gt;security and compliance standards&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="conclusion-unlocking-the-future-of-automotive-software"&gt;Conclusion: Unlocking the Future of Automotive Software&lt;/h2&gt;
&lt;p&gt;BMW&amp;rsquo;s journey with Pulumi in the Software Factory showcases the power of modern IaC solutions in navigating the complexities of the automotive software landscape. By embracing a unified and programmatic approach to infrastructure management, BMW has accelerated development, improved maintainability, and ensured compliance across its sprawling software ecosystem.&lt;/p&gt;
&lt;p&gt;As the automotive industry continues to evolve, with cars becoming increasingly software-driven, the lessons learned by BMW can serve as a blueprint for other organizations looking to streamline their software development and deployment processes. By leveraging the capabilities of Pulumi and other cutting-edge technologies, the future of automotive software is poised to be more efficient, secure, and responsive to the ever-changing needs of both manufacturers and consumers.&lt;/p&gt;
&lt;p&gt;To learn more about Pulumi and how it can transform your software development and infrastructure management:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get started with &lt;a href="https://www.pulumi.com/tutorials/"&gt;Pulumi Tutorials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Attend an &lt;a href="https://www.pulumi.com/resources/#upcoming"&gt;upcoming workshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Try out the &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt; code assistant to accelerate your infrastructure as code journey&lt;/li&gt;
&lt;/ul&gt;</description><author>Sara Huddleston</author><category>infrastructure-as-code</category><category>cloud-management</category><category>infrastructure-lifecycle-management</category><category>platform-engineering</category><category>developer-experience</category><category>ansible</category><category>containers</category><category>pulumi-deployments</category></item><item><title>Accelerate, Scale and Secure AI Innovation with Pulumi Platform Engineering</title><link>https://www.pulumi.com/blog/scale-ai-innovation-with-platform-engineering/</link><pubDate>Tue, 01 Oct 2024 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/scale-ai-innovation-with-platform-engineering/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/scale-ai-innovation-with-platform-engineering/index.png" /&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Note: This post discusses Pulumi Copilot, which Pulumi Neo has replaced. &lt;a href="https://www.pulumi.com/docs/ai/"&gt;Learn about Neo →&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As leadership teams continue to bet big on AI, the tradeoffs between how much to invest and when to expect a reasonable return are ever-present. While exploring scenarios for accelerating this return on investment, organizations are discovering some unique ways to accelerate their AI payback with Platform Engineering.&lt;/p&gt;
&lt;p&gt;As innovation and ROI pressures mount, how are savvy tech organizations using Platform Engineering to get more competitive advantage - and perhaps a quantum leap - from their AI investments?&lt;/p&gt;
&lt;h2 id="changing-the-rules-of-the-ai-game"&gt;Changing the Rules of the AI Game&lt;/h2&gt;
&lt;p&gt;Platform Engineering is transforming how organizations automate, secure and manage their resources - particularly in AI environments that require substantial compute, memory and cloud infrastructure.&lt;/p&gt;
&lt;h3 id="save-money-on-resources"&gt;Save Money on Resources&lt;/h3&gt;
&lt;p&gt;AI’s wide array of disparate technology resources make it an ideal use case for Platform Engineering. Cloud innovators are unifying AI layers, including web frameworks, LLMs, containers, databases, secrets, policies, and configurations, into streamlined Python libraries. Then they leverage these libraries to efficiently manage infrastructure stacks through code.&lt;/p&gt;
&lt;p&gt;For example, platform teams can now manage Google Dialogflow, LangChain Llama and other stacks using one platform, and then repurpose these unified resources across projects. Plus, they can author infrastructure as code, using programming languages they know and love, and write statements to define infrastructure using their own IDE’s, with autocomplete, type checking, and documentation. These teams deliver higher quality projects with fewer errors (and better testing), and are frequently happier, more productive, and more innovative.&lt;/p&gt;
&lt;p&gt;With this “work smarter, not harder” approach, there’s also less work, as there’s a lot less code required to run infrastructure. In many cases, code can be consolidated by 50% or more, and it can be leveraged across entire organizations without tedious, error-prone copying and pasting.&lt;/p&gt;
&lt;p&gt;All these efficiencies combine to reduce cloud, compute and storage costs, so you can re-invest the savings into more AI innovation and/or more scale across your organization.&lt;/p&gt;
&lt;h3 id="accelerate-time-to-market"&gt;Accelerate Time to Market&lt;/h3&gt;
&lt;p&gt;While speed is a byproduct of these efficiencies, it’s also a key reason to leverage platform engineering for AI. The most recognizable names in the AI industry have many attributes in common, including innovation and speed to market. Many of these leaders leverage Pulumi to achieve this decisive advantage.&lt;/p&gt;
&lt;p&gt;Snowflake is a great example of this approach. “There’s no question that, if we had gone down the traditional infrastructure automation route, it would have taken us a week or a week and a half to do one deployment of the cluster, end to end,” said Raman Hariharan, Director of Cloud Platform Engineering. “Plus, that deployment wouldn’t be repeatable, testable or scalable. It would have been a mad scramble to meet our deadline. When we demonstrated to people that what used to take a week and a half now, with [platform engineering], took under a day, they were shocked.” &lt;a href="https://www.pulumi.com/case-studies/snowflake/"&gt;Read the full Snowflake case study here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pulumi customers regularly rave about their results with platform engineering - many citing 5 to 10X faster time to market. &lt;a href="https://www.pulumi.com/case-studies/"&gt;See more case studies here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="another-benefit-more-freedom-to-innovate-with-more-resources"&gt;Another benefit: more freedom to innovate with more resources&lt;/h3&gt;
&lt;p&gt;This speed and efficiency also frees up valuable time for engineering staff to work on the creative new projects that drive innovation and new revenue generating applications. By combining generative AI with Pulumi’s insights and knowledge of your entire cloud infrastructure, users are solving a wide array of next-generation cloud development challenges.&lt;/p&gt;
&lt;p&gt;Joren McReynolds, VP of Engineering at Panther Labs said, &amp;ldquo;We are now in the best position to deliver new innovative solutions to our customers and to do so quickly, which is huge for a startup such as ours that needs to accelerate our efforts and to do so efficiently and seamlessly.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;To make this process even more efficient, a new AI-driven conversational chat interface called Pulumi Copilot is now integrated throughout Pulumi Cloud, enabling users to quickly accomplish a variety of cloud infrastructure management tasks by leveraging the power of large language models plus the rich capabilities of Pulumi Cloud.&lt;/p&gt;
&lt;p&gt;“At Unity Aura we manage hundreds of infrastructure updates per day,” said Eilon Ashkenazi, DevOps Engineer at Unity Aura. “With Pulumi Copilot we can improve the development process for the team by delivering working reference examples faster and discovery of resources to identify and update infrastructure in production.”&lt;/p&gt;
&lt;h2 id="dramatically-improve-ai-security"&gt;Dramatically Improve AI Security&lt;/h2&gt;
&lt;p&gt;Whether it’s cloud settings, API keys, database credentials or VM passwords, AI environments hold a wide variety of secrets, increasing risk, outages, errors and operational friction. Now you can centralize and secure your secrets management using platform engineering best practices within Pulumi. Easily access, share, and manage environments, secrets, and configurations securely on any cloud using your favorite programming languages. Pull and sync with any secrets store, and consume in any application, tool, or CI/CD platform.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/scale-ai-innovation-with-platform-engineering/diagram.png" alt="A diagram showing third-party integrations with Pulumi ESC"&gt;&lt;/p&gt;
&lt;p&gt;Many industry-leading AI technology providers such as Snowflake have already based some of their competitive differentiation on Pulumi’s unique value. More waves of large organizations are following this example as they navigate their journeys to AI time to market and return on investment.&lt;/p&gt;
&lt;p&gt;Learn more about how Pulumi and Platform Engineering can help your organization in the same way it &lt;a href="https://www.pulumi.com/case-studies/snowflake/"&gt;helped Snowflake speed up its deployment by 10x&lt;/a&gt;. Or take a look at &lt;a href="https://www.pulumi.com/case-studies/aptos/"&gt;how Aptos Labs achieved 10x faster development cycles&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you are ready to talk to an expert about how platform engineering can help your organization, &lt;a href="https://www.pulumi.com/contact/?form=sales"&gt;click here&lt;/a&gt;. For practitioners on your team, here are some &lt;a href="https://www.pulumi.com/events/"&gt;events and learning assets&lt;/a&gt; to get up to speed quickly on platform engineering and infrastructure as code.&lt;/p&gt;</description><author>Marlowe Fenne</author><category>platform-engineering</category></item><item><title>Announcing the New Pulumi Partner Program</title><link>https://www.pulumi.com/blog/pulumi-partner-program/</link><pubDate>Mon, 16 Sep 2024 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/pulumi-partner-program/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/pulumi-partner-program/index.png" /&gt;
&lt;p&gt;We are excited to announce the launch of the &lt;a href="https://www.pulumi.com/partners/"&gt;Pulumi Partner Program&lt;/a&gt;, a strategic initiative designed to empower our partners and their customers to accelerate cloud projects and achieve faster time-to-market. This program is crafted for cloud and SaaS companies who are building, integrating, and going to market with Pulumi.&lt;/p&gt;
&lt;p&gt;Hear from dozens of partners and customers who automate, secure and manage everything in the cloud at PulumiUP on Wednesday, September 18. Register &lt;a href="https://www.pulumi.com/pulumi-up/?utm_source=member_desktop&amp;amp;utm_medium=referral_pulumi&amp;amp;utm_campaign=FY2025Q1_Event_PulumiUP"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="why-the-pulumi-partner-program"&gt;Why the Pulumi Partner Program?&lt;/h2&gt;
&lt;p&gt;Pulumi has always been committed to the open-source community and the vibrant ecosystem that has grown around our products. With nearly &lt;a href="https://www.pulumi.com/registry/"&gt;200 integrations&lt;/a&gt; today, our ecosystem is thriving, supported by a network of service partners focused on helping customers succeed. The Pulumi Partner Program is being developed to formalize and strengthen these relationships, allowing us to scale our ability to deliver seamless integrations, co-developed solutions, and collaborative go-to-market activities. By building this program, we aim to empower partners to better support our mutual customers, accelerate cloud adoption, and provide tailored solutions that meet the unique needs of each organization.&lt;/p&gt;
&lt;p&gt;Customers are choosing Pulumi because it enables them to manage cloud resources and secrets using familiar general-purpose programming languages like Python, TypeScript, .NET, Java and Go. This approach taps into the existing skills of development teams, reducing the learning curve, and also allows for greater flexibility and reuse of code across projects. By utilizing these widely adopted languages, Pulumi increases team productivity, enables more robust automation, and significantly accelerates the path to production compared to tools that require more restrictive, domain-specific languages. With the introduction of &lt;a href="https://www.pulumi.com/blog/any-terraform-provider/"&gt;local packages&lt;/a&gt;, we’re further simplifying the integration process for partners, facilitating seamless adoption and faster delivery of cloud projects.&lt;/p&gt;
&lt;h2 id="key-benefits-of-pulumi-partner-program"&gt;Key Benefits of Pulumi Partner Program&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Empower Your Customers&lt;/strong&gt; to deliver cloud initiatives faster using Pulumi’s Infrastructure as Code (IaC) and Secrets Management capabilities. By partnering with Pulumi, your customers gain access to best automation for their cloud projects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accelerate Adoption&lt;/strong&gt; of your solutions through seamless integration with Pulumi. Leverage Pulumi&amp;rsquo;s support for the world&amp;rsquo;s most popular programming languages and developer tools to streamline integration, making it easier for your customers to use and adopt your products using familiar languages, tools and process.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reach More Developers&lt;/strong&gt; with collaborative documentation, shared examples, and co-marketing initiatives to raise awareness. Participate in joint marketing efforts, including co-branded campaigns and events, to connect with more developers and platform engineers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With 20 inaugural members, our technology partners join an elite community that benefits from Pulumi’s ongoing investment in technical, marketing, training, and business strategy support. We are excited to welcome new members such as &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt;, &lt;a href="https://1password.com/"&gt;1Password&lt;/a&gt;, &lt;a href="https://www.pinecone.io/"&gt;Pinecone&lt;/a&gt;, &lt;a href="https://newrelic.com/"&gt;NewRelic&lt;/a&gt;, &lt;a href="https://tailscale.com/"&gt;Tailscale&lt;/a&gt;, &lt;a href="https://dagger.io/"&gt;Dagger&lt;/a&gt; and many others.&lt;/p&gt;
&lt;h2 id="join-the-pulumi-partner-program"&gt;Join the Pulumi Partner Program&lt;/h2&gt;
&lt;p&gt;We believe that the Pulumi Partner Program will bring together and support the growth of our entire ecosystem, leveraging the strengths of our partners and creating connections for new potential services and technologies. Prospective partners can reach out to us via our &lt;a href="https://www.pulumi.com/partners/"&gt;website&lt;/a&gt;. We look forward to welcoming new partners and driving innovation together.&lt;/p&gt;</description><author>Isaac Harris</author><author>Tejitha Raju</author><category>platform-engineering</category><category>pulumi-community</category><category>enterprise</category></item><item><title>PulumiUP 2024: Dive Into the Future of Cloud, Platform Engineering, and AI/ML</title><link>https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/</link><pubDate>Wed, 11 Sep 2024 07:04:40 +0000</pubDate><guid>https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/index.png" /&gt;
&lt;p&gt;PulumiUP 2024 is just around the corner! It will be held on September 18th, starting at 8 AM PT | 15:00 UTC +0, and with over 5,500 engineers from all over the world already registered, this is shaping up to be the must-attend event for cloud professionals, platform engineers, and AI/ML enthusiasts alike. From entry-level engineers to tech executives, this event brings together professionals from companies of all sizes to explore the latest innovations and best practices in &lt;strong&gt;Cloud and IaC&lt;/strong&gt;, &lt;strong&gt;Platform Engineering &amp;amp; DevOps&lt;/strong&gt;, and &lt;strong&gt;AI/ML&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If you haven’t registered yet, now’s the time! &lt;a href="https://conference.pulumi.com/schedule/?utm_source=PulumiUP&amp;amp;utm_medium=web&amp;amp;utm_campaign=FY2025Q1_Event_PulumiUP"&gt;Start building your schedule today&lt;/a&gt;, select the talks you want to watch live and on-demand and add them to your schedule.&lt;/p&gt;
&lt;h2 id="pulumiup-at-glance"&gt;PulumiUP at Glance&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/#main-track-keynote-cloud-culture-talks-and-more"&gt;Main Track: Keynote, Cloud Culture Talks, and More&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/#aiml-track-highlights"&gt;AI/ML Track Highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/#platform-engineering-and-devops-track-highlights"&gt;Platform Engineering and DevOps Track Highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/#cloud-and-iac-track-highlights"&gt;Cloud and IaC Track Highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/#workshops-and-hands-on-learning"&gt;Workshops and Hands-On Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/#amazing-partners-and-sponsors"&gt;Amazing Partners and Sponsors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/#build-your-schedule-now"&gt;Build Your Schedule Now&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="main-track-keynote-cloud-culture-talks-and-more"&gt;Main Track: Keynote, Cloud Culture Talks, and More&lt;/h2&gt;
&lt;p&gt;In the Main Track, you’ll hear directly from the Pulumi leadership team about exciting product innovations. Don’t miss the Cloud Culture talks focused on the human side of technology and collaboration.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/events/pulumiup-2024-keynote/"&gt;Keynote and New Product Announcements&lt;/a&gt;&lt;/strong&gt; - Joe Duffy (Co-founder and CEO), Luke Hoban (CTO), and other key Pulumi leaders will unveil new products and innovations shaping the next wave of cloud development. Expect to see live demos showcasing how these tools can revolutionize your workflows, from cloud infrastructure to security automation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/9Xf6DJMvQ08"&gt;Why Care About Building a Cloud Center of Excellence?&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Alex Radu (VP Product &amp;amp; Marketing Manager, Public Cloud, J.P. Morgan) discusses why building a Cloud Center of Excellence is essential for long-term cloud strategy success.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/30wTCwfj3cc"&gt;What Is &amp;lsquo;HugOps&amp;rsquo; and Why Is It Important?&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Rees Pozzi (Senior Platform Engineer, Kainos) explores the meaning and importance of &amp;ldquo;HugOps,&amp;rdquo; a practice promoting empathy and collaboration in the tech world but also by all those impacted by it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="aiml-track-highlights"&gt;AI/ML Track Highlights&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://conference.pulumi.com/talks/panel-ai-cloud-development/"&gt;&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/pulumiup_2024-ai-cloud-development.png"
alt="Panelists of AI for Cloud Development" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;Panel: AI for Cloud Development&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;AI is transforming how we approach development and infrastructure, and PulumiUP offers an incredible lineup of talks and panels on the topic.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/4IWGNoNVbiM"&gt;Data Privacy Challenges with Large Language Models&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Aditi Godbole (Data Science, AI &amp;amp; ML Leader, SAP) will address the critical question of managing data privacy, addressing LLM basics, AI data privacy fundamentals, and specific privacy issues in LLMs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/CoZM9BCJcJ4"&gt;Pulumi Powered AI/ML on Kubernetes&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Jason Smith (App Modernization Specialist, Google Cloud) will show you how to serve an open-source LLM with a RAG on Kubernetes and set up a Kubernetes environment for AI/ML workloads with Pulumi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/WoM8Bj76_Fw"&gt;AI Tools for Developers&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Jim Clark (Principal Software Engineer, Docker) will explore how Tools can enhance the capabilities of AI assistants and show how the combination of AI, Tools, and containerized runtimes, can enhance interactions between developers and their tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/2mlb2jEBkoo"&gt;The AI Governance Challenge&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Patty O&amp;rsquo;Callaghan (Technical Director, Charles River) will explore the complexities of AI governance and how to navigate them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/events/panel-ai-in-cloud-development/"&gt;Panel Discussion: &amp;ldquo;AI for Cloud Development&amp;rdquo;&lt;/a&gt;&lt;/strong&gt; - Luke Hoban (CTO, Pulumi), Phillip Carter (Principal Product Manager, Honeycomb), Giri Sreenivas (CPO, Docker), Clare Liguori (Senior Principal Software Engineer, AWS) and Meagan Cojocar (Principal Product Manager, Pulumi) will provide diverse perspectives on how AI is shaping cloud infrastructure.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="platform-engineering-and-devops-track-highlights"&gt;Platform Engineering and DevOps Track Highlights&lt;/h2&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/pulumiup_2024-secrets-policies-automating-cybersecurity.png"
alt="Panelists of Secrets and Policies—Automating Cybersecurity" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;Panel: Secrets and Policies—Automating Cybersecurity&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The Platform Engineering &amp;amp; DevOps track at PulumiUP is perfect for anyone looking to automate infrastructure, secure their systems, and scale their environments with ease. This track features talks and panels on cutting-edge technologies and practices.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/WZD1z2ldweY"&gt;Moving Mountains: How IaC Unlocks Massive Refactoring Possibilities&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Shaun Verch (Infrastructure Engineer, Oso) will show you how infrastructure as code can transform large-scale refactoring projects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/1Q3XPmenthg"&gt;Using Pulumi to Empower Kubernetes Fleet Management&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Blake Romano (Senior Software Engineer, Imagine Learning) will show you how Imagine Learning leverages Pulumi to manage a fleet of Kubernetes clusters and other platform resources quickly and reliably, and how it revolutionized their workflow.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/f2r9rS9U2CA"&gt;Streamline Your Infrastructure Deployment with GitOps and Pulumi Operator&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Sam Cogan (Solutions Architect &amp;amp; Azure MVP, WTW) will highlight how you can define your infrastructure in Git, and have Pulumi automatically reconcile it into deployed infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/EQwpC02CQ9k"&gt;Is This a Platform? Platform Engineering Before PMF&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Jk Jensen (Team Lead, Staff Software Engineer, MystenLabs) will share how they built their service platform around Pulumi to help engineers and researchers move from prototypes to deployed environments, enabling their teams to iterate more quickly and develop an increasing number of systems without additional complexity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://www.pulumi.com/events/security-automation-faster-cheaper-better/"&gt;Security Automation—Faster. Cheaper. Better.&lt;/a&gt;&amp;quot;&lt;/strong&gt; - David Giambruno (VP of Engineering and DevOps, Tivity Health) and Joe Duffy (Founder/CEO, Pulumi) will discuss security automation and how these efforts impacted speed and agility, cost optimization and improved security and compliance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/CGE8VXgkjug"&gt;Meet Devs Where They Are: Why IaC Must Be Real Code&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Jeremy Adams (Head of Ecosystems, Dagger) will present why real code (that teams already use for applications) is essential for both IaC and CI/CD pipelines, and to meet modern DevOps best practices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/2a-wlUnBY1g"&gt;Security of IaC Pipelines and Infrastructure Governance With Policies-As-Code&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Marina Novikova (Senior Partner Solutions Architect, AWS) and Andy Taylor (Senior Networking Specialist/ Solutions Architect, AWS) will explore security best practices for IaC pipelines and infrastructure governance using policies-as-code, cover best practices for handling sensitive information like access keys, tokens and encryption keys, and scaling and automating your DevSecOps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/events/secrets-policies-automating-cybersecurity/"&gt;Panel Discussion: &amp;ldquo;Secrets and Policies—Automating Cybersecurity&amp;rdquo;&lt;/a&gt;&lt;/strong&gt; - Arun Loganathan (Senior Product Manager, Pulumi), Maya Kaczorowski (PM of Security), Jason Meller (VP, Product, 1Password), and Ofir Cohen (CTO, Container Security, Wiz) will explore the intersection of innovation and security, offering insights into how AI is reshaping the threat landscape and how organizations can stay ahead.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cloud-and-iac-track-highlights"&gt;Cloud and IaC Track Highlights&lt;/h2&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/pulumiup-global-cloud-iac-platform-engineering-ai-conference/pulumiup_2024-infrastructure-as-code.png"
alt="Panelists of Infrastructure as Code - Can we do better?" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;Panel: Infrastructure as Code - Can we do better?&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The Cloud and IaC track is ideal for those wanting to deepen their understanding of infrastructure as code and its impact on modern cloud computing. Learn from industry pioneers and see where the future of IaC is headed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://www.pulumi.com/blog/from-cdk-pulumi-evolution-of-sst/"&gt;From CDK to Pulumi: Evolution of SST&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Dax Raad (Founding Engineer, SST) and Jay V (Founder, SST) will share insights into the early development of their product, initially built on AWS Cloud Development Kit (CDK), the challenges they encountered and the groundbreaking decision to transition to Pulumi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/"&gt;Unified Software Development at BMW Software Factory with Pulumi&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Jan-Peter Alten (Expert Software Engineer, DevOps, BMW Group) will showcase how BMW uses Pulumi to unify their software development processes, resulting in an increase in developer productivity, streamlined infrastructure management, and enhanced scalability, security, and compliance across their complex software ecosystem.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/E077QbXPOZE"&gt;Stacking Accounts: Multi-Account Deployments in a Single Stack for Monitoring, Management, and More&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Denis Willett (Software Engineer, North Carolina Institute for Climate Studies) will explain how they use Pulumi for managing 60+PB of environmental data across AWS, GCP, and Azure and leverage multi-account deployments in a single stack via the Pulumi Automation API.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://youtu.be/C5ZuEVXesOk"&gt;Industrialize the Configuration of Your GitHub Repositories With IaC&lt;/a&gt;&amp;quot;&lt;/strong&gt; - Alexandre Nédélec (Software Engineer, Avanade) will live code using the GitHub, Azure native, and Azure AD Pulumi providers to create a GitHub repository and configure its pipeline to deploy to Azure using OpenID Connect.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/events/panel-infrastructure-as-code-can-we-do-better/"&gt;Panel Discussion: &amp;ldquo;Infrastructure as Code — Can We Do Better?&amp;rdquo;&lt;/a&gt;&lt;/strong&gt; - Joe Duffy (Co-Founder and CEO, Pulumi), Brian Grant (CTO, Stealth), Elad Ben-Israel (Co-Founder and CEO, Winglang), Adam Jacob (Co-Founder and CEO, System Initiative), and Luke Hoban (CTO, Pulumi) will discuss the past, the present, and the future of Infrastructure as Code and the overall infrastructure technologies.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="workshops-and-hands-on-learning"&gt;Workshops and Hands-On Learning&lt;/h2&gt;
&lt;p&gt;Want to get hands-on experience? Our live workshops are designed to deepen your understanding of trending topics, Pulumi, and its applications.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://www.pulumi.com/resources/managing-team-secrets-with-1password-pulumi-esc/"&gt;Managing Team Secrets with 1Password &amp;amp; Pulumi ESC&lt;/a&gt;&amp;quot;&lt;/strong&gt; on September 25, led by Phil Johnston (1Password) and Diana Esteves (Pulumi).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://www.pulumi.com/resources/securing-iac-pipelines-in-regulated-industries/"&gt;Securing IaC Pipelines in Regulated Industries&lt;/a&gt;&amp;quot;&lt;/strong&gt; on September 26, led by Josh Kodroff (Pulumi) and Marina Novikova (AWS).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://www.pulumi.com/resources/deploy-tailscale-infrastructure-with-pulumi/"&gt;Deploy Tailscale infrastructure in AWS with Pulumi&lt;/a&gt;&amp;quot;&lt;/strong&gt; on October 15, led by Diana Esteves (Pulumi) and Lee Briggs (Tailscale).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;&lt;a href="https://www.pulumi.com/resources/observability-as-code-for-ai-apps-new-relic/"&gt;Observability as Code for AI Apps with New Relic and Pulumi&lt;/a&gt;&amp;quot;&lt;/strong&gt; on October 30, led by Diana Esteves (Pulumi) and Harry Kimpel (New Relic).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="amazing-partners-and-sponsors"&gt;Amazing Partners and Sponsors&lt;/h2&gt;
&lt;p&gt;Thank you to our amazing customers, sponsors, and partners for supporting PulumiUP!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://aws.amazon.com/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;AWS&lt;/a&gt;&lt;/strong&gt; The world&amp;rsquo;s most comprehensive and broadly adopted cloud, offering over 200 fully featured services from data centers globally.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://cloud.google.com/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;Google Cloud&lt;/a&gt;&lt;/strong&gt; Help developers build quickly, securely, and cost effectively with the next generation of modern infrastructure designed to meet specific workload and industry needs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://newrelic.com/instant-observability/pulumi/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;New Relic&lt;/a&gt;&lt;/strong&gt; Data for engineers to monitor, debug, and improve their entire stack.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://docker.com/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;Docker&lt;/a&gt;&lt;/strong&gt; Accelerate how you build, share, and run applications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://1password.com/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;1Password&lt;/a&gt;&lt;/strong&gt; Streamline how you manage SSH keys, API tokens, and other infrastructure secrets throughout the entire software development life cycle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://tailscale.com/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;Tailscale&lt;/a&gt;&lt;/strong&gt; Make creating software-defined networks easy: securely connecting users, services, and devices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://pinecone.io/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;Pinecone&lt;/a&gt;&lt;/strong&gt; Build remarkable GenAI applications fast, with lower cost, better performance, and greater ease of use at any scale.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://wiz.io/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;Wiz&lt;/a&gt;&lt;/strong&gt; Secure everything you build and run in the cloud.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://honeycomb.io/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;Honeycomb&lt;/a&gt;&lt;/strong&gt; Observability that helps solve problems you couldn’t before.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://mystenlabs.com/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;Mysten Labs&lt;/a&gt;&lt;/strong&gt; Building critical infrastructure to enable a more decentralized internet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://imaginelearning.com/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;Imagine Learning&lt;/a&gt;&lt;/strong&gt; Empowering educators to inspire breakthrough moments in every student’s unique learning journey with digital-first, K–12 education solutions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://dagger.io/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;Dagger&lt;/a&gt;&lt;/strong&gt; Powerful, programmable open source CI/CD engine that runs your pipelines in containers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://osohq.com/?utm_source=Pulumi.com&amp;amp;utm_medium=Website&amp;amp;utm_campaign=PulumiUP"&gt;Oso&lt;/a&gt;&lt;/strong&gt; Authorization as a service.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="build-your-schedule-now"&gt;Build Your Schedule Now&lt;/h2&gt;
&lt;p&gt;With so many compelling topics across AI/ML, Platform Engineering, DevOps, and Cloud and IaC, now is the time to &lt;a href="https://conference.pulumi.com/schedule/?utm_source=PulumiUP&amp;amp;utm_medium=web&amp;amp;utm_campaign=FY2025Q1_Event_PulumiUP"&gt;build your PulumiUP schedule&lt;/a&gt;. Select the sessions that match your goals and interests to maximize your experience. Plus, you&amp;rsquo;ll receive a link to watch your chosen panel discussions and tech talks on-demand!&lt;/p&gt;
&lt;p&gt;Haven’t registered yet? It’s not too late! Join 5,500 engineers worldwide in this groundbreaking event and gain the insights you need to drive innovation at your company. &lt;a href="https://www.pulumi.com/pulumi-up/"&gt;Register now-&amp;gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We can’t wait to see you there!&lt;/p&gt;</description><author>Sara Huddleston</author><category>pulumi-events</category><category>announcements</category><category>platform-engineering</category><category>ai</category><category>cloud-computing</category><category>infrastructure-as-code</category><category>devsecops</category><category>community</category></item></channel></rss>