<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0"><channel><title>Pulumi Blog: Fundamentals</title><link>https://www.pulumi.com/blog/tag/fundamentals/</link><description>Pulumi blog posts: Fundamentals.</description><language>en-us</language><pubDate>Tue, 21 Nov 2023 03:53:33 +0000</pubDate><item><title>Going Beyond With Advanced Infrastructure as Code Use Cases</title><link>https://www.pulumi.com/blog/going-beyond-with-advanced-infrastructure-as-code-use-cases/</link><pubDate>Tue, 21 Nov 2023 03:53:33 +0000</pubDate><guid>https://www.pulumi.com/blog/going-beyond-with-advanced-infrastructure-as-code-use-cases/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/going-beyond-with-advanced-infrastructure-as-code-use-cases/index.png" /&gt;
&lt;p&gt;&lt;em&gt;This is the third of a three-part series originally published on The New Stack. Read &lt;a href="https://www.pulumi.com/blog/infrastructure-as-code-in-any-programming-language/"&gt;Part 1&lt;/a&gt; and &lt;a href="https://www.pulumi.com/blog/walkthrough-of-adopting-infrastructure-as-code/"&gt;Part 2&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Engineers who modernize their &lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;Infrastructure as Code&lt;/a&gt; with Pulumi get two classes of benefits:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Infrastructure as Code to develop cloud infrastructure with code.&lt;/li&gt;
&lt;li&gt;Pulumi Cloud, which tames cloud infrastructure management at &lt;a href="https://roadmap.sh/videos/scaling-the-unscalable"&gt;scale&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We’ve covered a fair bit of the first above, but have yet to scratch the surface for the second.&lt;/p&gt;
&lt;p&gt;Many Infrastructure as Code solutions require that you explicitly manage something typically referred to as “state.” This state is an artifact produced that keeps track of what you think your infrastructure looks like, as defined by your Infrastructure as Code, so that it can be easily compared to what your actual infrastructure looks like. This is how diffs and updates can be done. Every Infrastructure as Code tool stores this infrastructure state, which is really just metadata about all the cloud resources, properties and dependencies. However, how much the tool exposes you to it varies.&lt;/p&gt;
&lt;p&gt;Managed services like AWS CloudFormation and Azure Resource Manager (ARM) abstract this state away behind a service. Other tools like Terraform require you to explicitly manage that state by hand, often storing it in an S3 bucket or equivalent on your chosen cloud. The managed service approach tends to be easier to use and also avoids common pitfalls including security ones (&lt;a href="https://sysdig.com/blog/cloud-breach-terraform-data-theft/"&gt;like accidentally committing secrets to your Terraform state file in plain text&lt;/a&gt;) as well as reliability ones (&lt;a href="https://www.youtube.com/watch?v=ix0Tw8uinWs"&gt;like a code merge gone wrong that takes out your infrastructure&lt;/a&gt;). Pulumi Cloud offers both options, but the default is to use it like a managed service.&lt;/p&gt;
&lt;p&gt;Pulumi Cloud is available for unlimited free usage, has a free tier for teams and offers advanced editions for larger teams and enterprises. Pulumi’s SDK is fully open source and can be used without the service, but the cloud service is the easiest, most secure and most reliable way to use Pulumi Cloud.&lt;/p&gt;
&lt;p&gt;Pulumi Cloud’s architecture allows your cloud credentials to remain on your client. This when combined with features like identity integration and secrets management, addresses many pressing security concerns, and can mean that using the service is even more secure than managing Infrastructure as Code state on your own.&lt;/p&gt;
&lt;p&gt;The service enables integration with your chosen identity provider — such as GitHub, GitLab, Atlassian, Okta, Azure ActiveDirectory or &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/saml/"&gt;any SAML/SSO provider&lt;/a&gt; — and provides a complete visual history of who changed what infrastructure and when, very similar to what GitHub offers for code commits. It also makes it easier to see and control what’s going on in your team with organizations, role-based access controls and policy enforcement. It enables rich workflows via webhooks and gives users the ability to deploy either with the click of a button or straight out of a git repo.&lt;/p&gt;
&lt;p&gt;You can get a better sense of what functionality is available in the Pulumi Cloud by &lt;a href="https://www.pulumi.com/product/"&gt;reading this overview page&lt;/a&gt;. Although the Pulumi Cloud is trusted by many Global 2000 companies, is regularly audited by outside firms for well-architected and security best practices, and is SOC 2 Type II compliant, there is also a &lt;a href="https://www.pulumi.com/product/self-hosted/"&gt;self-hosted edition available that can be run anywhere&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="testing-your-infrastructure-as-code"&gt;Testing Your Infrastructure as Code&lt;/h2&gt;
&lt;p&gt;A benefit of using general-purpose languages is that we get to test our code. Most of us wouldn’t think of writing application code without testing it, and Infrastructure as Code is no different. It’s not just that we can test it, but we can use standard tools and practices.&lt;/p&gt;
&lt;p&gt;Testing can come in many different forms, including unit tests, property tests and integration tests. The following table summarizes the differences between the three approaches:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/unit"&gt;&lt;strong&gt;Unit Tests&lt;/strong&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/property-testing"&gt;&lt;strong&gt;Property Tests&lt;/strong&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/integration"&gt;&lt;strong&gt;Integration Tests&lt;/strong&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Provision real infrastructure&lt;/td&gt;
&lt;td&gt;No&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;Require the Pulumi CLI&lt;/td&gt;
&lt;td&gt;No&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;Time to execute&lt;/td&gt;
&lt;td&gt;Milliseconds&lt;/td&gt;
&lt;td&gt;Seconds&lt;/td&gt;
&lt;td&gt;Minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;Same as Pulumi program&lt;/td&gt;
&lt;td&gt;Node.js or Python&lt;/td&gt;
&lt;td&gt;Any language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation target&lt;/td&gt;
&lt;td&gt;Resource inputs&lt;/td&gt;
&lt;td&gt;Resource inputs and outputs&lt;/td&gt;
&lt;td&gt;External endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;First is basic unit testing which, thanks to using regular programming languages, can be done in the usual way. For instance, the built-in Python and Go test frameworks “just work,” and as do popular third-party frameworks like Mocha (for JavaScript), NUnit (for .NET), JUnit (for Java), and so on. This can be good at ensuring a function that computes CIDR blocks, for instance, is correct. Testing infrastructure itself is a bit more involved, simply because many properties for resources aren’t known a priori until a deployment is done. But when combined with Pulumi Cloud’s infrastructure mocking framework, it’s possible to test infrastructure topologies and properties too. &lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/unit/"&gt;Read more about testing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next are assertions. The idea behind this is to embed assertions within your actual program, so that unexpected situations are caught immediately. This can be associated with any program state, including the resources themselves. &lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/property-testing/"&gt;Read more about assertions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next up is integration testing. For Infrastructure as Code, the typical meaning of an integration test is to spin up a dedicated stack solely for purposes of testing, often referred to as an “ephemeral stack.” Because Pulumi Cloud makes it easy to create independent, isolated copies of your infrastructure, thanks to the projects and stack model, these workflows are surprisingly easy to achieve. This can then be integrated into your typical testing processes, whether those are run by hand or automated as part of your CI/CD process. It’s common to spin up an ephemeral stack whose lifetime is tied to a single pull request, for instance, to validate that the changes being proposed are correct: It is created (and tested) when the pull request is opened, updated (and tested) anytime a new push to it is made and destroyed when it’s closed. &lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/integration/"&gt;Read more about integration testing and ephemeral stack techniques&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, lots of more exotic tests are possible. For instance, you can fuzz-test your Infrastructure as Code by adding randomization to ensure the infrastructure behaves correctly in the face of strange inputs. You can chaos test your infrastructure by disabling instances or scaling key services below their typical thresholds to understand how your application behaves. You can stress test your infrastructure by placing unreasonable demands and seeing what breaks. The possibilities here are endless, but by using Infrastructure as Code in a general-purpose language, you have a lot more tools than is typically available to you.&lt;/p&gt;
&lt;p&gt;To learn more about testing Infrastructure as Code more generally, with specific code examples, please see the &lt;a href="https://www.pulumi.com/docs/iac/concepts/testing/"&gt;Automated Testing of Pulumi Programs&lt;/a&gt; user guide.&lt;/p&gt;
&lt;h2 id="enforcing-security-compliance-cost-and-more-with-policy-as-code"&gt;Enforcing Security, Compliance, Cost and More with Policy as Code&lt;/h2&gt;
&lt;p&gt;An adjacent approach to both Infrastructure as Code and testing is something called policy as code. Just like Infrastructure as Code, the idea is to encode definitions in a real code artifact. The difference is that those are policies that analyze and flag problems with your infrastructure. The benefits of expressing these in code, however, are very similar to Infrastructure as Code: You can version policies as your requirements change over time, it’s reviewable by the team, and it’s just more expressive.&lt;/p&gt;
&lt;p&gt;These policies can cover literally anything that can be analyzed and checked. This commonly includes security (such as ensuring databases aren’t open to the internet), compliance (that only FIPS endpoints are used for government-critical infrastructure), cost (that a deployment about to be done doesn’t exceed a team’s budget), and best practices (that all resources are tagged according to the team’s conventions). The idea is similar to linters and static analysis, both of which just work with Infrastructure as Code written in general-purpose languages, just purpose-built for infrastructure analysis.&lt;/p&gt;
&lt;p&gt;Just as Pulumi Cloud lets you use general-purpose languages for your Infrastructure as Code, it lets you use general-purpose languages for policy as code too. This benefits from the richness of those languages and enables advanced use cases like integrating with cost management or ticketing systems like ServiceNow to enforce IT policies. Pulumi Cloud also supports the Open Policy Agent (OPA) language Rego to make it easier to leverage existing policies.&lt;/p&gt;
&lt;p&gt;If we violate a policy, we get an error (for mandatory checks) or warning (for advisory ones) before the mistake even makes its way into production:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/going-beyond-with-advanced-infrastructure-as-code-use-cases/policy-error.png" alt="Policy Error"&gt;&lt;/p&gt;
&lt;p&gt;This might be “boring” from an engineer’s point of view but tends to be very important for an organization, especially for folks who are building out a platform team.&lt;/p&gt;
&lt;p&gt;A benefit of using the Pulumi Cloud is that you can manage and enforce policies across the entire organization without individual engineers needing to even know how to run them. To learn more about policy as code, &lt;a href="https://www.pulumi.com/docs/using-pulumi/crossguard/"&gt;refer to the user guide for CrossGuard&lt;/a&gt;, Pulumi’s policy as code.&lt;/p&gt;
&lt;h2 id="deploying-your-infrastructure-as-code-continuously"&gt;Deploying Your Infrastructure as Code Continuously&lt;/h2&gt;
&lt;p&gt;Most engineering teams ship their applications continuously thanks to CI/CD systems like GitHub Actions, Atlassian BitBucket, GitLab Pipelines, CircleCI, Travis, TeamCity, Spinnaker, or one of the built-in cloud CI/CD services like AWS CodePipeline, Azure DevOps or Google CloudBuild. This unlocks powerful git-driven workflows to push code out into production without needing to deploy things manually. But many teams don’t yet do that for infrastructure.&lt;/p&gt;
&lt;p&gt;Adopting Infrastructure as Code helps you to do two things. First, you can verify and ship infrastructure changes the same way you ship application changes, by pushing and reviewing code, a practice we’ve already reviewed as being a core strength of Infrastructure as Code. Second, you can harmonize your application and infrastructure delivery pipelines, so they aren’t as disparate and disconnected. This helps to ship faster while scaling up to many more complex environments as your software sees more success.&lt;/p&gt;
&lt;p&gt;The shift to containers, serverless and managed services has blurred the line between “application code” and “infrastructure code.” Is a serverless function on the infrastructure side of the line or application? What about a container registry? A pub/sub-topic? By using entirely different tools and delivery pipelines for applications versus infrastructure, which has historically been true of most infrastructure tools, we introduce a false dichotomy that slows down the team.&lt;/p&gt;
&lt;p&gt;Pulumi Cloud offers two solutions for automating infrastructure delivery: First, any of the above CI/CD systems can be used to not just deliver application code, but also your Infrastructure as Code too. Second, Pulumi Cloud offers a built-in system called “Pulumi Deployments” to get up and running and trigger deployments based on git workflows. Read more in the &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;Pulumi Deployments&lt;/a&gt; and/or &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/continuous-delivery/"&gt;Continuous Delivery&lt;/a&gt; user guides.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/images/product/pulumi-deployments-graphic.png" alt="Pulumi Deployments"&gt;&lt;/p&gt;
&lt;h2 id="advanced-iac-automation-with-automation-api"&gt;Advanced IaC Automation with Automation API&lt;/h2&gt;
&lt;p&gt;What if Infrastructure as Code were a normal library, in your language of choice, rather than a CLI? That was the question we asked before creating the automation API. Why is that an interesting question? It’s interesting because it elevates Infrastructure as Code to a core capability of any larger piece of software, which can be automated, rather than just a tool that needs to be run by hand by humans. We saw above that a small step toward this is to put Pulumi Cloud into your CI/CD, but the automation API takes it to a whole new level.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/images/home/automation-api-diagram.svg" alt="Automation API"&gt;&lt;/p&gt;
&lt;p&gt;The scenarios this unlocks are mentioned earlier — custom tools and libraries, internal infrastructure provisioning portals, and even entire SaaS products — all of which need Infrastructure as Code as a central capability. Indeed, some of your favorite SaaS products, and even those that can be managed with Pulumi, use Pulumi on the backend to provision and manage infrastructure across clouds and across clusters.&lt;/p&gt;
&lt;p&gt;Interestingly, we have found that, on average, those who leverage the automation API versus traditional Infrastructure as Code use cases are able to manage more than 10 times the infrastructure per engineer. That’s a big deal and the goal of automation: Doing more with less, experiencing less manual toil and just shipping faster with confidence.&lt;/p&gt;
&lt;p&gt;Pulumi’s approach of using general-purpose languages made automation API a natural and unique extension of Infrastructure as Code into new realms. To learn more about Automation API, &lt;a href="https://www.pulumi.com/automation/"&gt;check out this page&lt;/a&gt;, which describes some common scenarios with complete examples.&lt;/p&gt;
&lt;h2 id="detecting-iac-drift-and-doing-something-about-it"&gt;Detecting IaC Drift and Doing Something about It&lt;/h2&gt;
&lt;p&gt;A problematic scenario with any Infrastructure as Code tool is something called “drift”: this happens when someone manually changes your infrastructure outside of the Infrastructure as Code tool. In that case, the actual infrastructure has “drifted” from what it was supposed to be, given your Infrastructure as Code definitions. Detecting drift is one thing, remediating it is another.&lt;/p&gt;
&lt;p&gt;As a concrete example, imagine an engineer on the team is debugging an issue in production. To do so, they crack open port 22 so they can SSH into a Bastion host. (There are probably better approaches but as we know, when there’s a live incident, speed matters and sometimes shortcuts are taken.) Unfortunately, after resolving the incident, the engineer has forgotten to remove port 22 access. This is a potential security risk that we want to catch and resolve.&lt;/p&gt;
&lt;p&gt;The two potential remediations to drift are typically:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Reapply the Infrastructure as Code, thereby eliminating the drift, and in this case, closing port 22 access&lt;/li&gt;
&lt;li&gt;Incorporate the infrastructure changes into our program, so that the drifted state becomes our last-known-good on a go-forward basis. It’s also sometimes interesting to compare different environments to see if the infrastructure within them has drifted, although thanks to the Pulumi model of projects and stacks, this is uncommon in practice. It’s more of a concern with per-stack configuration, for which the Pulumi Cloud offers features to detect and resolve.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The Pulumi Cloud &lt;code&gt;refresh&lt;/code&gt; command can be used to detect drift and then you can decide how to remediate it. All of the building blocks are there to either reapply changes, ingest them back into the program or some combination thereof. The combination of refresh, plus automation API, as well as the Pulumi Deployments capability, enables you to detect and remediate drift on demand or on a scheduled basis. &lt;a href="https://www.pulumi.com/blog/patterns-drift-detection/"&gt;Read more about drift detection and remediation&lt;/a&gt; or &lt;a href="https://www.youtube.com/watch?v=-K90I1F6tfs"&gt;watch the video&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="learn-more-about-infrastructure-as-code"&gt;Learn More about Infrastructure as Code&lt;/h2&gt;
&lt;p&gt;The Pulumi &lt;a href="https://www.pulumi.com/docs/get-started/"&gt;Getting Started guide&lt;/a&gt; is the easiest way to get up and running with Infrastructure as Code. In addition to that, plus exploring the Pulumi Templates and Examples, we recommend some additional resources:&lt;/p&gt;
&lt;p&gt;The tutorial series, &lt;a href="https://www.pulumi.com/blog/iac-recommended-practices-code-organization-and-stacks/"&gt;Infrastructure as Code Recommended Practices&lt;/a&gt;, is a great overview of many concerns you will encounter along your Infrastructure as Code journey. This ranges from how to organize your project code and stacks, how to do local development and testing of your code, how to evolve these structures as your needs change, automation scenarios and more.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://www.pulumi.com/docs/iac/guides/"&gt;Using Pulumi&lt;/a&gt; page is a collection of tutorials and getting started guides on specific infrastructure as code topics, such as deeper dives into fundamental concepts, how to simplify your infrastructure projects, and more.&lt;/p&gt;
&lt;p&gt;We hope this article has given you a good grasp of the core Infrastructure as Code concepts you’re likely to encounter, no matter the tool you choose, as well as demonstrated some of the unique benefits Pulumi Cloud offers by using general-purpose and popular programming languages.&lt;/p&gt;</description><author>Joe Duffy</author><category>infrastructure-as-code</category><category>fundamentals</category></item><item><title>A Walkthrough of Adopting Infrastructure as Code</title><link>https://www.pulumi.com/blog/walkthrough-of-adopting-infrastructure-as-code/</link><pubDate>Tue, 14 Nov 2023 19:54:55 +0000</pubDate><guid>https://www.pulumi.com/blog/walkthrough-of-adopting-infrastructure-as-code/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/walkthrough-of-adopting-infrastructure-as-code/index.png" /&gt;
&lt;p&gt;&lt;em&gt;This is the second of a three-part series originally published on The New Stack.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Following the first piece in this series, &lt;a href="https://www.pulumi.com/blog/infrastructure-as-code-in-any-programming-language/"&gt;Infrastructure as Code in Any Programming Language&lt;/a&gt;, this walkthrough will show what it takes to get up and running with Infrastructure as Code. Everything we show will be done with Pulumi’s &lt;a href="https://www.pulumi.com/docs/install/"&gt;free and open source Infrastructure as Code SDK&lt;/a&gt;. You can also sign up for &lt;a href="https://app.pulumi.com/signup"&gt;Pulumi Cloud&lt;/a&gt;. After discussing the basics of how to get going, we’ll then dive into some advanced use cases to show what you can do from there.&lt;/p&gt;
&lt;h2 id="migrating-to-infrastructure-as-code"&gt;Migrating to Infrastructure as Code&lt;/h2&gt;
&lt;p&gt;When you pick an Infrastructure as Code tool, there is a major decision up front: Is this going to be net new infrastructure, or are you adopting existing infrastructure? In the latter case, maybe you clicked to experiment in the AWS console but are now ready to use Infrastructure as Code. Or maybe you started with Terraform and now want to migrate to Pulumi. In either case, there’s no getting around it. This is a trickier situation.&lt;/p&gt;
&lt;p&gt;In some cases, it’s better to just toss that infrastructure and start over from scratch. Or perhaps you can focus on succeeding first with a “new” part of the system and integrate with the existing infrastructure until you’re convinced it’s time to migrate. In many cases, however, that’s infeasible: Maybe you actually have a mission-critical service already that you need to bring under the management of &lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;Infrastructure as Code&lt;/a&gt;. The good news is that Pulumi offers &lt;a href="https://www.pulumi.com/migrate/"&gt;tools to migrate&lt;/a&gt; from existing tools like Terraform, AWS CloudFormation/CDK, Azure Resource Manager (ARM), Kubernetes YAML and more, bringing existing infrastructure under the management of Pulumi without any disruption. The user guides in the &lt;a href="https://www.pulumi.com/migrate/"&gt;Migration Hub&lt;/a&gt; walk through this process.&lt;/p&gt;
&lt;h2 id="getting-started-with-infrastructure-as-code"&gt;Getting Started with Infrastructure as Code&lt;/h2&gt;
&lt;p&gt;Let’s assume we are starting out with new infrastructure, even though most concepts are relevant even if you’re starting with a migration.&lt;/p&gt;
&lt;h3 id="cloud-infrastructure-resources-architectures-and-topologies"&gt;Cloud Infrastructure Resources: Architectures and Topologies&lt;/h3&gt;
&lt;p&gt;We usually start by provisioning a certain cloud architecture given our unique scenario. Maybe we’re creating a containerized application, a machine learning pipeline, or spinning up a Kubernetes cluster. In all of these cases, it begins by understanding the cloud resources that make up our architecture. In Pulumi, these are the programmable objects you’ll write code against.&lt;/p&gt;
&lt;p&gt;The world of cloud infrastructure is a bit daunting. Pulumi supports over 100 clouds. AWS has over 200 services with over 1,000 individual resources and over 300,000 configurable properties across all of them. Pulumi is a multicloud tool, but “multicloud” does not mean “lowest common denominator.” Instead, Pulumi exposes all those individual clouds, resources and properties in their raw, unadulterated form. The benefit of this is that you have the entire capabilities of all of these clouds right at your fingertips. The downside is that to use them you need to understand these clouds and how to use them properly. As a result, you’ll probably quickly find that you want a starting point, rather than a blank page.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/templates/"&gt;Pulumi Templates&lt;/a&gt; are a good way to get started. They represent over a dozen of the most common application and infrastructure architectures on the most popular clouds. They were built to be simple enough to be understandable at a glance but complete enough to be useful in practice. That includes containerized services, serverless applications, static websites, virtual machines and Kubernetes clusters across AWS, Azure, and Google Cloud, in addition to common Kubernetes workloads. Each template generates a fully working project that you can kick the tires with or even use as a starting point for your own customized architecture.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pulumi/examples"&gt;Pulumi Examples&lt;/a&gt; is an open source collection of over 300 fully working examples covering more clouds and more services. If you didn’t find a good starting point with the templates, there is a good chance you’ll find an approximation of your desired architecture here. If not, there are over 100,000 individual API examples in the &lt;a href="https://www.pulumi.com/registry/"&gt;Pulumi Registry&lt;/a&gt;, such as &lt;a href="https://www.pulumi.com/registry/packages/snowflake/api-docs/database/#example-usage"&gt;this one, which demonstrates provisioning a new Snowflake database with replication&lt;/a&gt;. Although these aren’t always as complete as examples and templates, they can also provide a great jumping-off point, in addition to serving as great reference material as you create additional code.&lt;/p&gt;
&lt;p&gt;Let’s take a quick look at several examples that represent common application architectures.&lt;/p&gt;
&lt;h3 id="architecture-1-containerized-service"&gt;Architecture 1: Containerized Service&lt;/h3&gt;
&lt;p&gt;In this example, we build and publish a Docker image running an NGINX web server to a private container registry, and then run that image in a load-balanced service. The load balancer ensures that we can easily scale up the number of replicas on the backend as our workload increases without fundamentally changing how clients can access it. There are many ways to accomplish this depending on the cloud we choose, and the detailed resources will differ.&lt;/p&gt;
&lt;p&gt;If our chosen cloud is AWS, we will need an Elastic Container Service (ECS) cluster and registry, with a Fargate service and application load balancer in front of it. This enables our service to be accessed over the internet:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/templates/container-service/aws/architecture.png" alt="AWS Containers Template"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;See the template for AWS &lt;a href="https://www.pulumi.com/templates/container-service/aws/"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If we choose Google Cloud, on the other hand, we can either use Google Kubernetes Engine (GKE) or Google Cloud Run. In this example, we use Cloud Run and the built-in artifact repository, since these services are generally easier to use when just getting started:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/templates/container-service/gcp/architecture.png" alt="Google Cloud Containers Template"&gt;&lt;/p&gt;
&lt;p&gt;In both cases, after deploying the infrastructure, we will have a fully functioning microservice environment with one load-balanced service running the NGINX web server. The Infrastructure as Code tool will give us a URL for the internet-accessible load balancer so we can browse to it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;See the template for GCP &lt;a href="https://www.pulumi.com/templates/container-service/gcp/"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id="architecture-2-serverless-application"&gt;Architecture 2: Serverless Application&lt;/h3&gt;
&lt;p&gt;In this example, we will create a serverless application. Unlike containers, which are fairly consistent across clouds (largely thanks to technologies like Docker and Kubernetes), the way serverless works varies greatly across clouds.&lt;/p&gt;
&lt;p&gt;For Azure, we’ll need to create an Azure Blob Storage container to host our code, upload the serverless function bundle, and then configure an Azure Function app that will make our function available over HTTPS:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/templates/serverless-application/azure/architecture.png" alt="Azure Serverless Template"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;See the template for Azure &lt;a href="https://www.pulumi.com/templates/serverless-application/azure/"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For AWS, although the architecture is in spirit very similar, the details differ greatly. We will use Amazon API Gateway and Lambda together to allow our function to be accessed over HTTPS:&lt;/p&gt;
&lt;p&gt;In both cases, after deploying the infrastructure, we get back a web URL to access it. This example is a good reminder that each of the clouds is very different in its details. Infrastructure as Code doesn’t necessarily shield you from those details, although it is possible to build abstractions that do, which is both a strength but also something you’ll need to navigate.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/templates/serverless-application/aws/architecture.png" alt="AWS Serverless Template"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;See the template for AWS &lt;a href="https://www.pulumi.com/templates/serverless-application/aws/"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id="architecture-3-kubernetes-cluster"&gt;Architecture 3: Kubernetes Cluster&lt;/h3&gt;
&lt;p&gt;For the final example, let’s switch gears and focus on more “foundational” infrastructure than the applications themselves. This is the sort of thing a platform engineer might care more about than, say, a backend systems engineer who is focused mostly on building and shipping services. In this specific case, we’ll spin up a managed Kubernetes cluster in AWS and Azure.&lt;/p&gt;
&lt;p&gt;In the case of Azure’s Kubernetes Service (AKS), the design of the service is fairly chunky. So we can simply spin up a managed cluster with the associated networking infrastructure:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/templates/kubernetes/azure/architecture.png" alt="Azure Kubernetes Template"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;See the template for Azure &lt;a href="https://www.pulumi.com/templates/kubernetes/azure/"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In the case of AWS’s Elastic Kubernetes Service (EKS), on the other hand, the service itself is rather complex to set up, involving many moving parts. That includes the control plane itself, the worker node groups, an autoscaling group, the AWS container network interface plugin to manage pod networking and more:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/templates/kubernetes/aws/architecture.png" alt="AWS Kubernetes Template"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;See the template for AWS &lt;a href="https://www.pulumi.com/templates/kubernetes/aws/"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You can see here even greater differences between the equivalent cloud services on different cloud providers and AWS’s more “building blocks” style of approach in action. This is also a great example of Infrastructure as Code’s ability to bundle best practices so that they can be reused. This uses the &lt;a href="https://www.pulumi.com/registry/packages/eks/"&gt;Pulumi EKS Package&lt;/a&gt;, which configures all of the above in the standard way so that you don’t need to figure out every little detail when you’re just getting started.&lt;/p&gt;
&lt;p&gt;In both cases, we end up with a fully managed Kubernetes cluster that is ready to use. The tool spits out a kubeconfig file so we can immediately deploy into or inspect it.&lt;/p&gt;
&lt;h2 id="infrastructure-projects-and-stacks"&gt;Infrastructure Projects and Stacks&lt;/h2&gt;
&lt;p&gt;All of these examples had one thing in common: The Infrastructure as Code program’s job is to declare individual resource objects, their properties and how they relate to each other. That was true no matter the scenario, the cloud or the language we have chosen. Once the program has done that, the Infrastructure as Code tool takes care of the rest.&lt;/p&gt;
&lt;p&gt;Pulumi uses the term &lt;strong&gt;project&lt;/strong&gt; to refer to the code that declares all of this, and each instance of said project that is configured and ready to deploy — each “environment,” if you will — is called a &lt;strong&gt;stack&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/images/docs/pulumi-programming-model-diagram.svg" alt="Pulumi Stacks"&gt;&lt;/p&gt;
&lt;p&gt;Each project can have many running stacks. That is useful for managing developer stacks (perhaps one per teammate) in addition to staging and production environments. It’s common to have many production environments when scaling a worldwide service. It’s also increasingly common to use short-lived stacks, for example, by creating a temporary stack for the duration of a pull request so pre-commit tests can be run against the hypothetical deployment.&lt;/p&gt;
&lt;p&gt;The Pulumi CLI makes it easy to create both. The &lt;code&gt;pulumi new&lt;/code&gt; command creates a new project:&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
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It will prompt you for the project layout, name and other related settings. A project is just a name, program and associated metadata, and a parent for subsequent stacks.&lt;/p&gt;
&lt;p&gt;The new command creates a starter stack, too, often called dev, for early-development purposes when getting going with a new project. However, additional ones can be created and managed using the &lt;code&gt;pulumi stack&lt;/code&gt; command:&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 stack init &lt;span class="c1"&gt;# create a new stack for this project&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pulumi stack ls &lt;span class="c1"&gt;# list stacks in this project&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pulumi stack &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="c1"&gt;# switch the current stack we&amp;#39;re using&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pulumi stack rm &lt;span class="c1"&gt;# delete a stack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Everything defined at the project level is shared among all stacks, including the code itself. This is nice because usually we want to keep all of the environments consistent with one another. But clearly sometimes we’ll want certain elements to intentionally diverge. Perhaps we want to deploy different stacks to different regions, use smaller or fewer VMs in our development stack than in production to keep cloud costs down and so on.&lt;/p&gt;
&lt;p&gt;This is where Pulumi &lt;strong&gt;configuration&lt;/strong&gt; enters the picture. Using configuration, you can easily set different values for specific settings in one stack versus another, and then the program can change its behavior accordingly. This allows you to keep most of your project’s declared infrastructure consistent across stacks by default but explicitly alter it when needed.&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 config &lt;span class="nb"&gt;set&lt;/span&gt; aws:region us-west-2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That’s not where configuration ends, however. Some of our configuration may entail using sensitive information, like Stripe access keys, database passwords or other kinds of secret tokens. Although Pulumi treats all state securely with in-transit and at-rest encryption, we never want settings like these to show up in plaintext anywhere. That’s where the Pulumi &lt;strong&gt;secrets&lt;/strong&gt; system comes in handy by providing built-in encryption and secure storage of these settings.&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 config &lt;span class="nb"&gt;set&lt;/span&gt; dbPassword --secret &lt;span class="o"&gt;[&lt;/span&gt;redacted&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, Pulumi gives you tools to manage your projects and stacks according to your own requirements, similar to how git can be used for many different source control philosophies such as monorepos. For a description of the tradeoffs involved, see the &lt;a href="https://www.pulumi.com/docs/guides/organizing-projects-stacks/"&gt;“Organizing Projects and Stacks” user guide&lt;/a&gt; or the &lt;a href="https://www.pulumi.com/blog/iac-recommended-practices-structuring-pulumi-projects/"&gt;IaC Recommended Best Practices blog series&lt;/a&gt;. For complex systems, we will likely want a separation of concerns between pieces of our infrastructure, which means it is possible for one stack to depend on another.&lt;/p&gt;
&lt;p&gt;For example, there could be a base networking and security layer, a data stack and a Kubernetes cluster that consume information from a lower-level layer but are provisioned separately, with applications above that depending on different assortments of all of the above.&lt;/p&gt;
&lt;p&gt;Each stack is a unit of security and deployment concurrency. By layering stacks in this manner, we can let different teammates work in isolation from one another, ensure that the most secure and robust parts of our infrastructure are under lock and key, and just generally let different parts of the team go faster without affecting one another. The feature that enables this is called “Stack References,” and you can &lt;a href="https://www.pulumi.com/docs/intro/concepts/stack/#stackreferences/"&gt;read more about how to use them in the documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="doing-a-deployment"&gt;Doing a Deployment&lt;/h2&gt;
&lt;p&gt;After we’ve got everything wired up — a project, its code containing the declaration of a desired cloud resource topology, and at least one stack — it’s time to actually get something up and running. Since our code is written in an ordinary language, it’s tempting to think we would just run it outright. (Indeed, we will see later on that with the Automation API, we can do just that.) Infrastructure as Code is special, though; because of its declarative nature, we will run it using the Pulumi CLI, which ensures a declarative Infrastructure as Code workflow.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;pulumi up&lt;/code&gt; command is the key behind that workflow in action:&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 up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;pulumi up&lt;/code&gt; command evaluates our program, generates a desired state resource graph and gives us a preview of what will occur should we proceed with our deployment. (We can run the &lt;code&gt;pulumi preview&lt;/code&gt; command explicitly if we want to run that as an independent step.) That preview will show any creates, updates or deletes, as well as interesting metadata about our deployment. The first time we ever deploy to a stack, there will be only creates, but after that we will see things like detailed diffs down to the property level for everything that has changed from one up to the next. These changes may arise due to code changes or even configuration updates.&lt;/p&gt;
&lt;p&gt;Let’s take a look at all of this in action. First, we’ll create a new stack to run a load-balanced service in AWS (although it’s AWS, the same workflow applies no matter our choice of cloud):&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 container-aws-typescript
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let’s inspect the code that got generated:&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 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;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;containerPort&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;containerPort&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;80&lt;/span&gt;&lt;span class="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;cpu&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;cpu&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;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;memory&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;memory&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;128&lt;/span&gt;&lt;span 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;// An ECS cluster to deploy into
&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="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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// An ALB to serve the container endpoint to the internet
&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="s2"&gt;&amp;#34;loadbalancer&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="c1"&gt;// An ECR repository to store our application&amp;#39;s container 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;repo&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="s2"&gt;&amp;#34;repo&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;forceDelete&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Build and publish our application&amp;#39;s container image from ./app to the ECR repository
&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="s2"&gt;&amp;#34;image&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;repositoryUrl&lt;/span&gt;: &lt;span class="kt"&gt;repo.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;path&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="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;// Deploy an ECS Service on Fargate to host the application container
&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="s2"&gt;&amp;#34;service&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;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;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="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="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;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;containerPort&lt;/span&gt;&lt;span class="p"&gt;,&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="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;// The URL at which the container&amp;#39;s HTTP endpoint will be available
&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;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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we deploy this, we will see the full resource graph and the load-balanced service at the end:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/walkthrough-of-adopting-infrastructure-as-code/pulumiup-base.jpg" alt="Pulumi Resource Graph"&gt;&lt;/p&gt;
&lt;p&gt;That’s what the initial deployment looks like. Now let’s create a database for our application. We’ll first add these code changes:&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;basic_dynamodb_table&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;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ddb-table&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;attributes&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;UserId&amp;#34;&lt;/span&gt;&lt;span class="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;S&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&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;GameTitle&amp;#34;&lt;/span&gt;&lt;span class="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;S&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&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;TopScore&amp;#34;&lt;/span&gt;&lt;span class="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;N&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;billingMode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;PROVISIONED&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;globalSecondaryIndexes&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;hashKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;GameTitle&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&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;GameTitleIndex&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;nonKeyAttributes&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;UserId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;projectionType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;INCLUDE&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;rangeKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;TopScore&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;readCapacity&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;writeCapacity&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="p"&gt;}],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;hashKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;UserId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;rangeKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;GameTitle&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;readCapacity&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;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="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 class="p"&gt;,&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;dynamodb-table-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="nx"&gt;ttl&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;attributeName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;TimeToExist&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&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;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="nx"&gt;writeCapacity&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="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then run &lt;code&gt;pulumi up&lt;/code&gt; again. Notice that it shows us the diffs this time, down to individual properties that have changed in addition to what is new:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/walkthrough-of-adopting-infrastructure-as-code/pulumiup-ddb.jpg" alt="Pulumi Diff"&gt;&lt;/p&gt;
&lt;p&gt;Note that, thanks to understanding of dependencies between resources, Infrastructure as Code tools will run many operations in parallel. You’ll see that timings are displayed as things are updated. Provisioning cloud infrastructure can be a slow process, but because of parallelism, Pulumi not only knows in what order to run various operations, it can do so as fast as possible.&lt;/p&gt;
&lt;p&gt;After all is said and done, we can &lt;code&gt;pulumi destroy&lt;/code&gt; our stack, which deletes all infrastructure within it:&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 destroy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is clearly a dangerous but necessary operation. Pulumi has two features to help avoid mistakes. First, &lt;a href="https://www.pulumi.com/docs/intro/concepts/resources/options/protect/"&gt;protecting a resource&lt;/a&gt; ensures extra steps are required to delete it, and second, &lt;a href="https://www.pulumi.com/docs/intro/concepts/resources/options/retainondelete/"&gt;the retain-on-delete option&lt;/a&gt; keeps the physical resource around even when the logical resource has been removed from your Pulumi stack. These are good to use with critical and precious resources whose destruction might be catastrophic, like databases — better safe than sorry!&lt;/p&gt;
&lt;p&gt;In Part 3 of our series, the final installation, we will discuss advanced IaC use cases and how you can use Pulumi Cloud to develop cloud infrastructure with code and tame cloud infrastructure management at scale. We will be using Pulumi Cloud, which is available &lt;a href="https://app.pulumi.com/signup"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><author>Joe Duffy</author><category>infrastructure-as-code</category><category>fundamentals</category></item><item><title>Infrastructure as Code in Any Programming Language</title><link>https://www.pulumi.com/blog/infrastructure-as-code-in-any-programming-language/</link><pubDate>Tue, 31 Oct 2023 22:36:29 +0000</pubDate><guid>https://www.pulumi.com/blog/infrastructure-as-code-in-any-programming-language/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/infrastructure-as-code-in-any-programming-language/index.png" /&gt;
&lt;p&gt;&lt;em&gt;This is the first of a three-part series originally published on The New Stack.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;Infrastructure as Code&lt;/a&gt; is a technology for automating the infrastructure for your cloud applications. If you’re an engineer, whether that’s developing a backend service or within a central platform team, it’s not just about writing application code. You’ll need to provision, update and perform other tasks associated with its supporting infrastructure, and that’s where Infrastructure as Code can help. Instead of manually pointing-and-clicking in the cloud console, which is unrepeatable and error-prone, or writing ad-hoc scripts, which can be tedious and hard to scale, Infrastructure as Code lets us, as engineers, use familiar techniques by just writing code.&lt;/p&gt;
&lt;p&gt;Not every engineer has a deep infrastructure background and yet needs to get more hands-on with infrastructure these days, which is OK: This three-part series was written from an engineer’s point of view. In it, we will demystify Infrastructure as Code — the why, what, and how — through the lens of Pulumi, a popular Infrastructure as Code tool among engineers.&lt;/p&gt;
&lt;h2 id="why-we-need-infrastructure-as-code"&gt;Why We Need Infrastructure as Code&lt;/h2&gt;
&lt;p&gt;Modern applications need cloud infrastructure to run. That is equally true for simple monolithic applications running on virtual machines as it is for exotic distributed serverless applications that are fully elastic in scale. The applications themselves need infrastructure that they directly use, like whatever they run within (such as virtual machine, containerized service, serverless function, static website) in addition to any other resources they consume (databases, pub/sub topics, queues, AI/ML services, observability metrics and dashboards), but also depend on more primitive infrastructure to run atop (Kubernetes clusters, security roles and permissions, private networks, load balancers, encryption keys and more).&lt;/p&gt;
&lt;p&gt;The phrase “cloud infrastructure” is also broader than it may seem. This phrase evokes immediate thoughts of popular clouds like Amazon Web Services (AWS) , Microsoft Azure, and Google Cloud, as well as more specialized or regional ones like Alibaba Cloud, DigitalOcean and Oracle Cloud. It also quickly leads to cloud native infrastructure like Docker, Kubernetes and Helm. But this phrase also perhaps not obviously applies to modern software-as-a-service (SaaS) infrastructure companies who increasingly are supplying critical pieces of cloud infrastructure, including Confluent, Cloudflare, Databricks, DataDog, Elastic, MongoDB, New Relic and Snowflake.&lt;/p&gt;
&lt;p&gt;These companies are essentially specialized clouds providing more specialized services but are increasingly expanding to become clouds of their own. It also applies to private cloud technologies like F5, VMware vSphere and related technologies. Finally, also not obviously, there are SaaS tools that have configurable state that we use every day and may want repeatable management of just like our other cloud assets, including Auth0, GitHub, GitLab and PagerDuty.&lt;/p&gt;
&lt;p&gt;Cloud infrastructure’s reach is far and wide! But it also means that there are many complex moving pieces to manage and tame. And with so much innovation happening in cloud capabilities, that complexity is just growing with time. This begs questions like the following:&lt;/p&gt;
&lt;p&gt;Where does the infrastructure come from? How do we change it as our requirements evolve? How do we scale it as our needs grow, whether that’s increasing the compute and memory available to our workloads, scaling to many new instances, increasing our availability and reducing latency by deploying to new regions and environments worldwide… or, as is usually the case, a combination of all of these?&lt;/p&gt;
&lt;p&gt;How do we ensure our infrastructure practices are repeatable in the event something fails or a mistake is made? How do we capture and reuse best practices? Do the answers to these questions differ across clouds? How do we ensure collaboration can take place safely and our deployments aren’t flaky and prone to colliding? And how do we secure all of it and ensure best practices and policies are enforced at all times?&lt;/p&gt;
&lt;p&gt;These are all things that Infrastructure as Code solves, and it starts with code.&lt;/p&gt;
&lt;h2 id="benefits-of-infrastructure-as-code"&gt;Benefits of Infrastructure as Code&lt;/h2&gt;
&lt;p&gt;The Infrastructure as Code approach provides many benefits, but they fall into two primary categories:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using code to declare infrastructure&lt;/li&gt;
&lt;li&gt;Using a declarative engine to orchestrate infrastructure changes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It is the combination of these two things that leads to the magic of “Infrastructure as Code.”&lt;/p&gt;
&lt;h2 id="the-benefits-of-code"&gt;The Benefits of Code&lt;/h2&gt;
&lt;p&gt;Encoding your cloud application infrastructure in code results in a durable artifact representing your desired architecture. This can be code-reviewed, committed to source control and versioned in the usual ways. Infrastructure as Code tools not only know how to stand up the initial version of your infrastructure, but can replicate it across many environments (like dev, staging, prod and multiple regions), in addition to upgrading individual environments as your requirements evolve.&lt;/p&gt;
&lt;p&gt;In terms of the “code” aspect, the expression of your code varies across the Infrastructure as Code landscape. Some tools support markup languages like JSON or YAML, while others support domain-specific languages (DSLs) that are specific to that tool. In this article, we will use Pulumi, which takes a unique approach to Infrastructure as Code that is well-suited for engineers: namely you use industry-standard general-purpose languages, including C#, Go, Java, JavaScript, Python or TypeScript, to express your code. This approach is great for engineers because it makes infrastructure more accessible and lets you use standard engineering tools and practices that you’re already using to build other software in your team.&lt;/p&gt;
&lt;p&gt;Examples of these benefits include having rich constructs like simple if-statements and for-loops, which help avoid repetition and model complex infrastructure needs. Since all of these languages are broadly supported throughout the industry, virtually any editor you pick up will have great support, such as Visual Studio Code, PyCharm, Sublime Text, IntelliJ or even vim or emacs. That means you’ll get interactive statement completion, red squiggles if you make a typo or have a type-checking error, documentation as you hover, right-click to go to definition or refactor, and so much more. It’s easy to take these things for granted, but they are essential for software engineering productivity.&lt;/p&gt;
&lt;p&gt;There are other benefits still such as linters, testing tools, the ability to share and reuse with package managers rather than copy-and-pasting and more. Lastly, each of these languages has enormous communities that add up to more than 20 million engineers, which means there’s a wealth of knowledge and support available.&lt;/p&gt;
&lt;p&gt;It turns out &lt;a href="https://www.pulumi.com/blog/pulumi-yaml/"&gt;Pulumi supports YAML&lt;/a&gt; too — the L in YAML stands for language, after all — which is a fine choice for simple scenarios, those where you want to machine-generate your Infrastructure as Code, or when engineers want to enable their sysadmins to do Infrastructure as Code too.&lt;/p&gt;
&lt;h2 id="the-benefits-of-declarative"&gt;The Benefits of Declarative&lt;/h2&gt;
&lt;p&gt;Code is one major benefit. But in addition to the benefits of code, Infrastructure as Code has another significant advantage: It is “declarative,” even if you’ve chosen an imperative language like Go to express your code.&lt;/p&gt;
&lt;p&gt;Infrastructure as Code tools generally work using a concept called “desired state.” The code, when run, produces a picture of the infrastructure your application requires. The Infrastructure as Code tool then understands how to compare the desired state with reality, and plan a course of action based on that information.&lt;/p&gt;
&lt;p&gt;If it’s your first time creating a certain environment, something Pulumi calls a stack, then of course all the declared infrastructure will need to be created from scratch. Upon subsequent evaluations, however, that same infrastructure may need to be updated, deleted or even re-created, in addition to new infrastructure that may get spun up when it’s the first time it has been declared. This plan is presented ahead of performing any actions, so you and your team can review it, and if the course of action is wrong, you can correct it first.&lt;/p&gt;
&lt;p&gt;One example of this process would be to first create a microservice environment that includes a Layer 4 network load balancer, a containerized cluster and a replicated, containerized service. You could subsequently add a private container registry, switch to a Layer 7 application load balancer, and scale up the service from one to three replicas.&lt;/p&gt;
&lt;p&gt;This declarative approach ensures we can preview changes before they are made so we don’t have any unpleasant deployment surprises, gives us a full audit history of exactly what has changed in our actual infrastructure and when, similar to what source control does for our code artifacts, allows us to gate deployments on verification checks such as testing and policy enforcement, and makes it easier to integrate with various automation workflows.&lt;/p&gt;
&lt;p&gt;It’s the codification of infrastructure and repeatability of the declarative approach that lets us use Infrastructure as Code in many kinds of automated workflows. That includes running a command-line interface (CLI) manually or as part of a script. Although “manual” may sound bad, the actual deployment is done with all of the above safeguards, so it’s fairly common for an Infrastructure as Code tool to be run this way.&lt;/p&gt;
&lt;p&gt;However, most teams will adopt a CI/CD model for their most important environments, like production, which will trigger the actual deployment of code changes off a code commit. This ensures that all changes have been reviewed in the usual ways and go through a standard CI/CD pipeline. That pipeline may also include continuous verification (CV) such as running tests.&lt;/p&gt;
&lt;p&gt;Some Infrastructure as Code tools support just one cloud, but our chosen tool, Pulumi, supports many, &lt;a href="https://www.pulumi.com/registry"&gt;including all of those mentioned above&lt;/a&gt;, so all of these workflows can be standardized across all of the clouds and service providers. It can even track dependencies between cloud services — for example, it would not be strange to provision an Elastic Kubernetes Service cluster in AWS, install Datadog agents on its nodes, deploy some Kubernetes workloads, and place a Cloudflare content delivery network in front of that application, all using a single Infrastructure as Code program.&lt;/p&gt;
&lt;p&gt;Pulumi’s unique approach unlocks an even more sophisticated workflow for running your code, using its so-called “&lt;a href="https://www.pulumi.com/automation/"&gt;Automation API&lt;/a&gt;.” This approach embeds Infrastructure as Code workflows right into larger pieces of software so that it can be programmed for highly dynamic scenarios.&lt;/p&gt;
&lt;p&gt;This unlocks scenarios like building custom tools and libraries that build on top of and extend Infrastructure as Code, &lt;a href="https://www.pulumi.com/product/internal-developer-platforms/"&gt;internal infrastructure provisioning portals&lt;/a&gt; and even entire SaaS products that need to provision or manage infrastructure as part of delivering their capabilities to their own end users.&lt;/p&gt;
&lt;p&gt;In Part 2 of our series, we will take you through the steps needed to set up Infrastructure as Code. In doing so, we will be using Pulumi’s free and open source SDK, which is available &lt;a href="https://www.pulumi.com/docs/install/"&gt;here&lt;/a&gt;. It’s easy to get started, but you may want to take time now to explore the platform. You might also like to sign up for Pulumi Cloud, which can be done &lt;a href="https://app.pulumi.com/signup"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><author>Joe Duffy</author><category>infrastructure-as-code</category><category>fundamentals</category></item></channel></rss>