Multi-environment configuration for development, staging, and production
TypeScriptTo achieve a multi-environment setup using Pulumi, we need to use a Pulumi project with a stack for each environment (development, staging, and production). A stack in Pulumi is a deployment target that contains a collection of cloud resources, and having separate stacks for each environment allows you to isolate configurations, resources, and secrets.
Here's a high-level overview of the steps we will follow:
- Organize our Pulumi project into separate directories or use inline configurations for different environments.
- Define the resources required for our application, such as compute instances, databases, networking, etc.
- Parameterize our Pulumi code to accept configuration variables so that each environment can have different settings.
- Create three Pulumi stacks (
dev
,staging
, andprod
), each representing one of our environments. - Apply the appropriate configuration settings to each stack.
- Run
pulumi up
on each stack to deploy our multi-environment setup.
Now, let's look at a program that creates a simple AWS S3 bucket for each environment with different names. We will use TypeScript for this, as it provides type safety and full IDE support which will be beneficial for building and maintaining our infrastructure as code.
Notice how the bucket names change with the stack, allowing the same code to create differently named resources based on the environment.
import * as pulumi from "@pulumi/pulumi"; import * as aws from "@pulumi/aws"; // We retrieve the current stack which represents our current environment const stack = pulumi.getStack(); const bucketNameSuffix = stack === "prod" ? "prd" : stack; // A configuration object that allows us to parameterize our stack const config = new pulumi.Config(); // We create a new S3 bucket with a name based on the current environment const bucket = new aws.s3.Bucket(`${bucketNameSuffix}-bucket`, { bucket: `my-app-${bucketNameSuffix}`, acl: "private", tags: { Environment: stack, }, }); // Exporting the bucket name so we can easily retrieve this information later export const bucketName = bucket.id;
To deploy this to
dev
,staging
, andprod
, you would run the Pulumi CLI'spulumi up
command for each separate stack:pulumi stack select dev
and thenpulumi up
to deploy to development.pulumi stack select staging
and thenpulumi up
to deploy to staging.pulumi stack select prod
and thenpulumi up
to deploy to production.
You can customize the configuration for each stack by using the
pulumi config set
command. For instance, if you have different tags or bucket policies for each stack, you can set them in the respective stack configuration:pulumi config set aws:region us-west-2 --stack dev pulumi config set aws:region us-east-1 --stack staging pulumi config set aws:region eu-central-1 --stack prod
This way, you can have different regions for your AWS resources in different stacks. Remember, each stack can have its own set of configurations in
Pulumi.<stack-name>.yaml
.Deploying separate stacks for development, staging, and production allows you to manage and scale each environment independently, providing a well-structured CI/CD pipeline and following best practices for software development and deployment.