Back to Blog
Lesson 4 of the AWS: AWS Core Services for Developers course
Cloud NativeJuly 3, 20264 min read

Introduction to Infrastructure as Code with AWS CloudFormation

Learn why IaC is essential for modern cloud engineering. Master your first CloudFormation template in YAML and deploy it to AWS using the CLI.

AWSCloudFormationIaCYAMLDevOpsInfrastructure as Code

Previously in this course, we set up our environment by configuring the AWS CLI and establishing IAM users and policies. Up until now, if you've interacted with AWS, you've likely done it manually through the Web Console. While the console is great for learning, it’s a recipe for disaster in production.

In this lesson, we shift from manual configuration to Infrastructure as Code (IaC). We will stop "clicking" and start "coding" our infrastructure, ensuring our deployments are consistent, repeatable, and versionable.

Why Infrastructure as Code?

If you build a server by clicking through the AWS console, you are creating "snowflake" infrastructure—a unique, undocumented, and difficult-to-replicate resource. If that server dies, you have to remember every single setting you changed to rebuild it.

IaC solves this by treating infrastructure definitions like application code. The benefits include:

  • Reproducibility: You can spin up identical environments (Dev, Staging, Prod) with one command.
  • Version Control: Since your infrastructure is in a file, you can track changes in Git.
  • Auditability: You know exactly what changed, when, and by whom.
  • Automation: You can integrate infrastructure changes into your CI/CD pipelines (something we'll explore later in the course).

Understanding CloudFormation

AWS CloudFormation is the native IaC service for AWS. You provide a text file—a template—written in YAML or JSON, and CloudFormation handles the heavy lifting of provisioning the resources in the correct order.

A CloudFormation template is declarative. You don't tell AWS how to build the resource; you tell AWS what the end state should look like.

Your First Template: Creating an S3 Bucket

Let’s define a simple S3 bucket. Create a file named my-first-stack.yaml:

YAML
AWSTemplateFormatVersion: '2010-09-09'
Description: A simple template to create an S3 bucket.

Resources:
  MyS3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Sub 'my-unique-bucket-name-${AWS::AccountId}'

Breaking down the YAML:

  • AWSTemplateFormatVersion: Required for compatibility.
  • Resources: The heart of the template. This is where you declare your AWS components.
  • Type: Defines the AWS service (e.g., AWS::S3::Bucket).
  • !Sub: An intrinsic function that lets you inject the AWS Account ID into the bucket name, ensuring it's unique.

Deploying Your Stack via the CLI

Now that we have our template, let's deploy it. Open your terminal in the directory where you saved the file.

  1. Create the stack:

    Bash
    aws cloudformation create-stack \
      --stack-name my-dev-stack \
      --template-body file://my-first-stack.yaml
  2. Verify the status: The command returns a Stack ID. You can track progress in the console, or check via CLI:

    Bash
    aws cloudformation describe-stacks --stack-name my-dev-stack

When the status reaches CREATE_COMPLETE, your bucket is live. Because you used IaC, you can delete the entire stack—and everything inside it—with one command: aws cloudformation delete-stack --stack-name my-dev-stack.

Hands-on Exercise

  1. Modify your my-first-stack.yaml to include a second resource. Add a Type: 'AWS::SNS::Topic' to your Resources section.
  2. Deploy the updated template using aws cloudformation update-stack.
  3. Observe how CloudFormation calculates the "diff" and only adds the new resource without destroying your bucket.

Common Pitfalls

  • Hardcoding Names: Avoid hardcoding resource names. If you delete a stack and try to recreate it, AWS might prevent you from using the same name if the resource hasn't fully propagated through the global namespace (especially with S3). Use !Sub or !Ref to generate dynamic names.
  • Drift: If you manually change a setting in the console after deploying via CloudFormation, your template and the actual infrastructure will go out of sync. This is called "configuration drift." Always make changes to the code, then update the stack.
  • IAM Permissions: Ensure your IAM user has cloudformation:* permissions to execute these commands.

FAQ

Q: Is CloudFormation better than Terraform? A: Both are excellent. CloudFormation is native to AWS and requires no external state file management, making it easier for beginners. Terraform is cloud-agnostic. For this course, we stick to AWS-native tools.

Q: Can I use JSON instead of YAML? A: Yes, but YAML is generally preferred for its readability and ability to include comments.

Q: What happens if I make a typo in the YAML? A: CloudFormation performs a validation check before starting the deployment. If the syntax is invalid, the stack creation will fail immediately before any resources are touched.

Recap

We’ve moved from manual management to declarative IaC. By defining our infrastructure in YAML, we ensure that our "serverless web app" project remains consistent and easy to manage as it grows in complexity. We’ve learned that CloudFormation manages the lifecycle of our resources, and the AWS CLI provides the interface to control that lifecycle.

Up next: We will level up our automation and move away from raw YAML templates by using the AWS Cloud Development Kit (CDK) to define infrastructure using actual programming languages.

Similar Posts