<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0"><channel><title>Pulumi Blog: Patterns and practices platform</title><link>https://www.pulumi.com/blog/tag/patterns-and-practices-platform/</link><description>Pulumi blog posts: Patterns and practices platform.</description><language>en-us</language><pubDate>Mon, 11 Nov 2024 00:00:00 +0000</pubDate><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.74fadd1b94bae866bccf29a780f184a71c5cfc34c8677be70da8fe2ab0309b9e.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>Pulumi Patterns and Practices Platform (P3): A reference architecture for large-scale organizations</title><link>https://www.pulumi.com/blog/pulumi-patterns-and-practices/</link><pubDate>Mon, 05 Aug 2024 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/pulumi-patterns-and-practices/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/pulumi-patterns-and-practices/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.74fadd1b94bae866bccf29a780f184a71c5cfc34c8677be70da8fe2ab0309b9e.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;Infrastructure management is all fun and games until you find yourself scrolling through 1000+ resources in your AWS console. Worse, when one rogue product team wants to use Azure and your data team wants to be on GCP, you&amp;rsquo;re ARM wrestling in Azure and watching your economies of scale tip the wrong direction as you&amp;rsquo;re copy-pasting CloudFormation templates into yet another git repo. This. Needs. To. Be. A. Platform!&lt;/p&gt;
&lt;p&gt;And in that moment of overwhelm, you will be sold to, nurture-emailed every week, and told all your problems will be solved by implementing an IDP (internal developer platform, as if you&amp;rsquo;ve never seen this acronym before). An IDP that costs a lot of money and a lot of time to implement beyond default settings. An IDP that really only solves half of your problems. Your internal team offers to build something that feels more like welding together random pieces of code into an abstract found-art sculpture built from junkyard refuse, already 5 years out of date. How long will this investment be useful before you have to start over?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s exhausting. If there was a good solution on the market, you wouldn&amp;rsquo;t be reading this article. So let&amp;rsquo;s talk about what you really need, and how Pulumi can help.&lt;/p&gt;
&lt;h2 id="an-effective-internal-developer-platform"&gt;An effective internal developer platform&lt;/h2&gt;
&lt;p&gt;There are quite a few &lt;a href="https://en.wikipedia.org/wiki/Listicle"&gt;listicles&lt;/a&gt; out there professing to authoritatively tell you the 5, or 7, or 11 essential components of an internal developer platform. Personally, I trust our customers to tell us, and here&amp;rsquo;s what they have said they need:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#consistency"&gt;Consistency:&lt;/a&gt;&lt;/strong&gt; Bring some order to the chaos. As your company and your infrastructure grows, it gets more and more complicated to maintain consistency. You might already have established design patterns that you want to replicate, but don&amp;rsquo;t have any way to encode those practices in your current tools. There&amp;rsquo;s a lot of copy/paste of reusable blocks, but no way to apply &lt;a href="https://www.youtube.com/watch?v=5xw04T20lto&amp;amp;t=7s"&gt;DRY principles&lt;/a&gt; or to modularize/templatize the important parts (hint: all the parts are important!).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#reproducibility"&gt;Reproducibility:&lt;/a&gt;&lt;/strong&gt; Repeatable behaviors, who dat? If you run your deploy twice do you get the same results each time? What if you replicate your production environment to create a test environment, are they actually identical? How much more work does it take to get them to be? Will you get the same version of the training dataset every time you run your AI workloads? It&amp;rsquo;s anyone&amp;rsquo;s guess. A lack of reproducibility slows down development, makes debugging more difficult, and makes that reuse we just talked about harder to achieve.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#visibility"&gt;Visibility:&lt;/a&gt;&lt;/strong&gt; When your node count, and user count starts to go beyond about 50-100 resources (computing or human) you quickly run into a problem of visibility. It can be very difficult to get a handle on what&amp;rsquo;s happening, how many resources you have, where they are, and how much they cost. Any system that purports to be able to manage 1000 nodes or more must have deeply integrated analytics, dashboards, charts, and be searchable, across all your clouds, all your users, and every kind of resource.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#security-and-compliance"&gt;Security and Compliance:&lt;/a&gt;&lt;/strong&gt; Good fences make good neighbors. RBAC, policy-as-code, excellent secrets management, integration with your existing identity providers. These are the things you need to build security and policy guardrails you can rely on. Without them? It&amp;rsquo;s just a powder keg of liability waiting to catch a spark.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#auditability"&gt;Auditability:&lt;/a&gt;&lt;/strong&gt; What happened and who did it? This is like a high-stakes game of &lt;a href="https://en.wikipedia.org/wiki/Cluedo"&gt;Clue&lt;/a&gt;. How quickly can you figure out who ran that bad deployment? Was it &lt;em&gt;Colonel Mustard&lt;/em&gt; in the &lt;em&gt;library&lt;/em&gt; with the &lt;em&gt;candlestick&lt;/em&gt;? Or Blake the new Front-End Developer with overly-broad permissions in AWS? Being able to answer these questions needs to happen quickly. Quickly, like minutes, not hours or days. And it might have happened 6 months ago. Oof.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#auditability"&gt;Developer Experience:&lt;/a&gt;&lt;/strong&gt; In the ideal world, developers drive their own DevOps. The platform team provides self-service tools and streamlined workflows that allow your engineers to provision new resources, so your team doesn&amp;rsquo;t have to. And you know, if the developers don&amp;rsquo;t like the user experience, they won&amp;rsquo;t use it at all, and will invent their own tools. You will have ROGUE SYSTEMS to hunt down and argue against in tedious overly-technical meetings. This is not what you want. We need to keep the developers happy to prevent this.&lt;/p&gt;
&lt;h2 id="a-holistic-view-of-the-patterns-and-practices-platform-reference-architecture"&gt;A holistic view of the Patterns and Practices Platform reference architecture&lt;/h2&gt;
&lt;p&gt;Pulumi has a broad surface area of &lt;a href="https://www.pulumi.com/product/"&gt;products and features&lt;/a&gt; that address these needs. Designed with integration in mind from the beginning, our tools orchestrate well, presenting a smooth and streamlined workflow for both operations teams and developer teams.&lt;/p&gt;
&lt;p&gt;We have an idea of how you can use all the Pulumi products together to deliver a comprehensive internal platform for security, infrastructure management, and deployments. Call it an &lt;a href="https://www.pulumi.com/what-is/what-is-platform-engineering/"&gt;internal platform for developer platform engineers&lt;/a&gt; (IPfDPE), if you want. We call it the realization of a vision we&amp;rsquo;ve been working hard to build for many years.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pulumi Patterns and Practices Platform (P3)&lt;/strong&gt; is a reference architecture that we will be describing, and providing code for, through this series of articles. We&amp;rsquo;ll be diving deep into not just what you can do with our tools, but how to do it, and provide code for a reference implementation that you can use to jump start the process.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a quick overview to give you an idea of how we&amp;rsquo;ll be addressing those needs in Pulumi Patterns and Practices Platform (P3).&lt;/p&gt;
&lt;h3 id="consistency"&gt;Consistency&lt;/h3&gt;
&lt;p&gt;Pulumi can help bring consistency to your software catalog by encoding design patterns into reusable &lt;em&gt;&lt;a href="https://www.pulumi.com/learn/abstraction-encapsulation/component-resources/"&gt;component resources&lt;/a&gt;&lt;/em&gt; and by building custom &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; that provide a no-code or low-code way to start a new project. Templates help get projects off the ground faster and ensure consistent code structure, policy compliance, and best practices.&lt;/p&gt;
&lt;figure&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded w-full" title="The New Project Wizard in Pulumi Cloud"
autoplay muted playsinline
loop &gt;
&lt;source src="npw-720p.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;figcaption&gt;&lt;p&gt;Figure: An internal developer portal using custom templates in Pulumi Cloud&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Beyond that, because Pulumi is &lt;a href="https://www.pulumi.com/blog/deploy-to-multiple-regions/"&gt;multi-cloud&lt;/a&gt; (AWS, Azure, Google Cloud, and more) and &lt;a href="https://www.pulumi.com/blog/pulumiup-pulumi-packages-multi-language-components/"&gt;multi-language&lt;/a&gt; (JavaScript, Python, Go, C#, Java) you can enjoy the same consistency across all your environments and all your developer teams, regardless of the languages they prefer, or cloud tooling they need.&lt;/p&gt;
&lt;p&gt;Another core aspect of consistency is &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/drift/"&gt;drift detection&lt;/a&gt;&lt;/em&gt;. Pulumi automatically detects and remediates cloud resources that have deviated from the expected state stored in Pulumi Cloud. This tech is better than ibuprofen at getting rid of developer-created headaches.&lt;/p&gt;
&lt;h3 id="reproducibility"&gt;Reproducibility&lt;/h3&gt;
&lt;p&gt;Since 2010, scientists have felt that we are in a crisis – a &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Replication_crisis"&gt;reproducibility crisis&lt;/a&gt;&lt;/em&gt; – wherein we cannot easily reproduce an experiment in order to verify published results. Similarly, the software industry is entering into a reproducibility crisis of its own, especially around AI training workflows, where it is increasingly difficult to recreate crucial build and prod environments. &lt;a href="https://www.pulumi.com/learn/building-with-pulumi/understanding-stacks/"&gt;Pulumi Stacks&lt;/a&gt; make it very easy to manage both configuration and state across multiple environments, and make &lt;a href="https://www.pulumi.com/blog/simple-reproducible-kubernetes-deployments/"&gt;reproducing a deployment&lt;/a&gt; within Pulumi a matter of a few basic operations.&lt;/p&gt;
&lt;p&gt;You can use Pulumi programs to capture &lt;em&gt;&lt;strong&gt;all&lt;/strong&gt;&lt;/em&gt; of the necessary resources for an AI training workload, including things like versioned data using &lt;a href="https://www.pulumi.com/registry/packages/snowflake/api-docs/dynamictable/"&gt;dynamic tables&lt;/a&gt; with time-travel functionality in &lt;a href="https://www.pulumi.com/case-studies/snowflake/"&gt;Snowflake&lt;/a&gt;. That means you can be sure that not only will your deployment be on the infrastructure you need, it will also have the exact version of data, every time, which is essential to A/B testing and debugging your models.&lt;/p&gt;
&lt;h3 id="visibility"&gt;Visibility&lt;/h3&gt;
&lt;p&gt;Every resource under management by Pulumi is visible within &lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;Pulumi Insights&lt;/a&gt;. From this single-pane-of-glass interface, you can search for resources across all cloud environments. &lt;a href="https://www.pulumi.com/product/copilot/"&gt;Pulumi Copilot&lt;/a&gt; provides a state-of-the-art AI chat interface to ask complex questions and get immediate results. Pulumi Insight&amp;rsquo;s analytics gives you the ability to identify anomalies or trends in resource usage and dig into cost, security, and compliance concerns.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/uploads/pulumi-insights-search.gif"
alt="Figure: Search for any resource with Pulumi Insights"&gt;&lt;figcaption&gt;
&lt;p&gt;Figure: Search for any resource with Pulumi Insights&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="security-and-compliance"&gt;Security and Compliance&lt;/h3&gt;
&lt;p&gt;In the modern parlance, when you say DevOps, you mean DevSecOps. Pulumi is designed to be secure by default. Pulumi Cloud offers full &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/"&gt;role-based access control (RBAC) functionality&lt;/a&gt; including deep integration with &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/#github-based-teams"&gt;GitHub teams&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/saml/"&gt;SAML-based SSO&lt;/a&gt;, managed secrets and flexibly-defined secure environments with &lt;a href="https://www.pulumi.com/product/esc/"&gt;Pulumi ESC&lt;/a&gt;, and policy-as-code provided by &lt;a href="https://www.pulumi.com/crossguard/"&gt;Pulumi Crossguard&lt;/a&gt;. Most importantly all of these features are deeply integrated across the platform, creating an air-tight system with all the guardrails you need for managing security and access.&lt;/p&gt;
&lt;h3 id="auditability"&gt;Auditability&lt;/h3&gt;
&lt;p&gt;Every action a user takes in Pulumi can be tracked via the &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/audit-logs/"&gt;audit log&lt;/a&gt; which is searchable in two clicks from the Pulumi Cloud homepage dashboard. Audit logs can be filtered by user with one more click. Creating automated backups of your audit logs is a &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/audit-logs/#automated-export"&gt;first-class feature&lt;/a&gt;. You will never have to worry about responding quickly when someone asks about an event that happened in your system. Also, each deployment and update has logs directly visible from the Pulumi Cloud app, regardless of how it was initiated.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/images/docs/guides/self-hosted/auditlogs.png"
alt="Figure: Viewing the audit log in Pulumi Cloud"&gt;&lt;figcaption&gt;
&lt;p&gt;Figure: Viewing the audit log in Pulumi Cloud&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="developer-experience"&gt;Developer Experience&lt;/h3&gt;
&lt;p&gt;Probably the most compelling aspect of Pulumi is the developer experience. &lt;a href="https://www.pulumi.com/testimonials/"&gt;Developers love Pulumi&lt;/a&gt;, because they get to use their preferred tools. General purpose programming languages, visual IDEs, command-line tools, and products with an API-driven architecture are what developers want, and it&amp;rsquo;s what Pulumi delivers in spades.&lt;/p&gt;
&lt;p&gt;With Pulumi templates and custom internal component resources in place, &lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#how-does-devex-intersect-with-devops"&gt;developers can drive their own DevOps&lt;/a&gt;, provisioning their own infrastructure resources and managing their own deployments directly, reducing bottlenecks in platform teams. Product engineering teams can self-service with a stream-lined workflow that stays compliant with company policy by default. Deep in the code of their favorite programming languages, your developers will never even know they are following the company rules.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/pulumi-patterns-and-practices/pulumi-ide.png"
alt="Figure: Using C# to write a Pulumi program in VS Code"&gt;&lt;figcaption&gt;
&lt;p&gt;Figure: Using C# to write a Pulumi program in VS Code&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="more-to-come"&gt;More to Come&lt;/h3&gt;
&lt;p&gt;So now that we&amp;rsquo;ve made a case for how Pulumi can be applied to meet the most pressing needs of a larger organization, hopefully you will realize that the Pulumi Patterns and Practices Platform (P3) reference architecture we are presenting here is more than just infrastructure-as-code. P3 is a Pulumi-powered platform for teams, where your developer portal is not just a catalog of software, but a fully functional control-plane across all your cloud environments.&lt;/p&gt;
&lt;p&gt;Stay tuned for the following series of posts where we will use Pulumi to implement the P3 reference architecture for a fully-featured internal developer platform (IDP, or IPfDPE if you prefer). That said, you may already have invested in some popular in cloud-native tools like &lt;a href="https://www.pulumi.com/blog/pulumi-in-a-cloud-native-world/#the-kebap-stack-reference-architecture"&gt;Backstage&lt;/a&gt; or &lt;a href="https://www.pulumi.com/blog/kubernetes-4-0-even-more-kubernetes-native/"&gt;Kubernetes&lt;/a&gt;. Pulumi plays well with others, and you will be delighted to see &lt;a href="https://www.pulumi.com/blog/pulumi-in-a-cloud-native-world"&gt;how you can use Pulumi to cover the gaps&lt;/a&gt; in the &lt;a href="https://www.cncf.io/"&gt;CNCF&lt;/a&gt; ecosystem.&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></channel></rss>