By: Alex English
Here at ELVT, we run many projects in the cloud each with many environments, which requires a great deal of infrastructure. In order to manage this in a sane way, we use automated infrastructure provisioning. Without it, we’d have to manually configure each project in the cloud for our client’s use. Environments for our projects typically involve many components, like Kubernetes clusters, databases, cache servers, monitoring and logging infrastructure, and more. Configuring every project and every environment manually can be an arduous and error-prone process. There are many ways of doing this, such as Terraform, Ansible, Chef, etc. At ELVT, we partner with Pulumi, as well as use it for our own projects.
What is Pulumi?
Pulumi is a platform that manages infrastructure. At its core, Pulumi stores state, and exposes an API that allows us to manipulate that state. When we run pulumi up, it executes our code, compares the new state to the existing state, and manages any changes. For example, our state can be a set of s3 buckets in AWS, a load balancer in azure, a Kubernetes cluster running on bare metal, a database, etc. Here’s a simple typescript example of Pulumi code that configures an S3 bucket in AWS:
In Pulumi, these states are isolated into independent stacks. Each stack is isolated from other stacks, and when we execute our Pulumi program, it runs against a particular stack. Typically, a stack is an environment (staging, production, qa, etc), but as we’ll see later, we can also use them for local development environments.
Why Infrastructure as Code?
Manual configuration is error prone. For example, when setting up an Application Load Balancer in AWS, there are many screens (networking, rules, target groups, etc) that all have to be configured correctly for an ALB to work properly. We’ve set up a great deal of these at ELVT, and while ALBs are extremely powerful and versatile, every part of these has to be set up correctly to work. If a health check is set to the wrong port, EC2 instances will be removed from target groups and we won’t see requests go through. It often takes a few iterations of configuration to make the stars line up. Although it doesn’t take much time, it can cause frustration and lead to problems that might not be apparent until a project is further down the road.
Infrastructure as Code (IaC) removes those roadblocks. Once a block of code is verified to be working as intended, we can use it over and over again with predictable results. IaC is repeatable. With Pulumi, we can run this code again in a given environment without making any changes. In this sense, Pulumi code is idempotent.
Typically in an organization there are one or more test environments. There may be a development environment, a staging environment, and then ultimately a production environment. Say we’ve got a new feature that requires not only code, but a set of s3 buckets hosted behind CloudFront. In development, we can work out the relationships between those moving parts of the infrastructure in our Pulumi code. We can verify that buckets are created, Cloudfront is configured correctly, certificates are generated correctly, and even the dreaded IAM. Because Pulumi is written in the language of our choosing, we can design modules that take configuration parameters (names or prefixes) that separate one environment from another.
Once we’ve successfully worked this out in development, we can simply switch the stack to the next environment and then run pulumi up against that environment. This avoids us having to go through the whole configuration process again, manually copying configuration from one browser window to another. We can then test and make adjustments as needed
Pulumi is one of a few commonly available IaC platforms. However, Pulumi allows us to write code in languages we’re familiar with. In the above example we chose to use TypeScript. This allows developers to work in a language they’re comfortable with, instead of having to learn a complicated proprietary language such as Terraform, which is notorious for its steep learning curve. In our case, TypeScript’s powerful typing mechanism gives us some added benefits in the IDE, checking the types in our code and giving us strong API documentation in the editor.
Additionally, using Pulumi in our native programming language (whichever that may be) allows us to reason about infrastructure on our own terms. We can create components that share configuration and structure that configuration in ways that we’re used to. For example, when we write an application we can create config objects and serialize them as we want. And with Pulumi, we can use that same approach in our infrastructure.
Pulumi at ELVT Consulting
At ELVT, one of our clients is a successful fintech company that deals with large amounts of financial documents. Many case studies with Pulumi deal with successfully managing production and staging environments, and we’ve done that here as well. However, we’d like to go over one way that we’ve used Pulumi successfully to help manage a growing team.
The infrastructure for this client was set up in AWS EKS, the Elastic Kubernetes Service. The main application used about six different Kubernetes pods along with an ingress, storage, and other kubernetes components. Because of cost, it was uneconomical to host twenty or thirty different development environments in the AWS staging cluster, but to cover testing for some functionality, developers had to reproduce the Kubernetes infrastructure either locally or in a shared development server.
This company started small, and as all successful companies do, hit a period of rapid growth in the engineering staff. Pulumi handled production, staging, and other lower environments. However, we needed a way to set up development in either Minikube on someone’s local machine or on a shared development server in AWS.
Here’s where Pulumi really shined for us. The Pulumi Kubernetes Provider works anywhere that kubectl works, either against AWS, a shared bare-metal development server, or minikube on a local machine. We’d onboard a new developer, create a pulumi stack for them on a shared server, and they’d be off with a minimum of working through configuration.
Let's Wrap it Up!
AWS infrastructure can be very complicated, especially for our larger projects. We have to support developer environments, cloud environments, and sometimes bare-metal or hybrid cloud environments. In addition to saving time and sanity, Pulumi makes this much simpler and more portable.
Interested to hear more or just want to discuss what we can do with your specific needs? You can ping us directly at firstname.lastname@example.org or go straight to our calendar.
You must belogged in to post a comment.