Original author: Alexander Savchuk

Terraform-vs-Cloudformation

The question comes up occasionally — why might we still choose to use third-party tools when AWS already offers essentially the same service?

CloudFormation has improved dramatically over the past few years, and there are certainly more compelling reasons to use Terraform than there were at the time. However, given the choice again, I would prefer To use Terraform. Here are a few reasons why I chose to do so.

language

Terraform uses HCL (HashiCorp Configuration Language), which was developed to balance human readability with machine-friendly recognition.

CloudFormation uses JSON or YAML.

Generally speaking, relative to JSON, YAML is more easy to read and write, but like JSON, YAML will force you to use multiple nested domains, if somewhere do not pay attention to the wrong use of indentation, so your code might make you want to vomiting blood (translator: now the majority of the idea have code formatting features, so…). . In contrast, HCL typically has only one or two layers of nested fields and performs some basic Go-inspired formatting hygiene, which makes code more comfortable to read.

Terraform has a rich set of character interpolation and built-in functions, including conditional and cloud native support, which allows fairly complex logical models to be built in DSLS without having to resort to a fully fledged programming language (although this can be done through external data sources). CloudFormation’s built-in functions are obviously limited.

Another reason to favor Terraform is that it makes code reuse easier through the use of modules and gives you a lot of flexibility in building projects in the way that makes the most sense to you. CloudFormation supports nested stacks, but generally you have to keep all your infrastructure code in one (or more) large files in a project repository, whereas with Terraform you can split it up at will. It’s usually much easier for the average person to work with multiple 100-line files than a single 5000-plus line file. Modules can be stored on GitHub or a public Terraform module repository, and are easily versioned and shared across multiple projects.

state

Terraform stores its status in a file that can be stored on your computer’s hard drive, submitted to your code management repository, and saved to S3 or other configuration management systems. No matter how you choose to save it, you need to make sure that you don’t lose or destroy your status files, and you also need to make sure that you don’t accidentally apply your production status files to your test environment. In any case, we’ve had enough holes in our history with Terraform status files, and now that Terraform has introduced workspaces (formerly called “environments”), it’s probably hard to shoot ourselves in the foot again.

CloudFormation, by contrast, runs on an AWS infrastructure and manages state for you, so you don’t need to care how it does it. , unlike Terraform CloudFormation application will also try to roll back cannot change (unless it is in a state UPDATE_ROLLBACK_FAILED) (aws.amazon.com/blogs/mt/re…). . In addition, the CloudFormation back end can receive signals from your resources, which makes configuring automatic scaling and rolling updates a very useful option. CloudFormation is also not afraid of sudden machine outages (which can happen with replaceable CI/CD servers), while Terraform needs to recover from partial updates.

At present, on the face of it, CloudFormation seems to have the upper hand. If we take a closer look at Terraform’s status file, it’s a very powerful presence, and this is Terraform’s main selling point. It allows us to import, apply, or transfer resources, which means we can refactor our infrastructure at will without destroying and rebuilding it.

Another thing that is possible in Terraform is managing Configuration Drift. Each time terraForm Plan is run, it takes the latest “actual” state of the infrastructure and compares it to the “target” and “current” states defined in the configuration file, which reflect the actual state when TerraForm Apply was last run and are stored in the status file. If our infrastructure no longer matches the “target” state (usually due to some external change), Terraform calculates the difference and recommends manual changes to restore it to the state described in our configuration. As long as we keep idempotent deployment and periodically run Terraform plans, this will make it easy for us to detect and recover configuration drift changes. In fact, these things can be set up as scheduled tasks in our infrastructure supply pipeline.

CloudFormation, meanwhile, is stupidly unaware of any changes beyond its state. You can simply try the following experiment.

First, we deploy a new CloudFormation to create a new VPC and a security group with no entry rules:

AWSTemplateFormatVersion: '2010-09-09'

Resources:
  VPC:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: 10.0. 0. 0/ 16

  SecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupName: TestSG
      GroupDescription: Test security group
      VpcId: ! Ref VPC
Copy the code

Then, go to the Aws console and manually add a new Ingress rule. For example, let’s open the SSH port for some quick debugging.

Next, update your CloudFormation and you will get the following error:

Running CloudFormation again at this time will not detect manual changes, and in the case of CloudFormation, we have not made any changes to the infrastructure.

configuration

Parameters make it possible to reuse the same template in a variety of environments. For example, you might want to use a cheaper EC2 instance in your test environment and a more powerful one in your production environment.

CloudFormation supports up to 60 parameters that must be provided at run time. There are several ways to do this.

  • Pass the arguments one by one and default them to reasonable values;
  • You supply parameters in bulk from a file (you need to make sure you pass the correct file);
  • Import parameter values from the output of another CloudFormation;
  • Storing or reading from parameters;
  • Use the Mapping section and look up parameters by some key (for example, by environment).

Terraform is much more flexible than that. It has the concept of a data source that provides a read-only representation of some resource, allowing you to access its properties without affecting its state. The data source provides a wide range of options to easily integrate Stacks and avoid hard-coding the required parameters. For example, you can access properties of external managed resources (such as finding the latest AMI), get output from CloudFormation Stack, reuse properties that are output by other Terraform stacks (such as a database Endpoint or DNS record), and if that’s not enough, Run some custom scripts that provide the required values. There is only one truth, and that truth is the current state of the infrastructure, not a recent snapshot, as is often the case with configuration files. During the next Terraform run, all changes to a resource are propagated to all other resources that depend on it, without worrying that somewhere has been forgotten to replicate, while maintaining a clear separation of concerns. Another benefit is that you can use the same CI/CD pipeline to manage all Terraform projects without having to worry about passing the correct set of parameters to each resource.

Because Terraform is cross-cloud, you can combine infrastructure from different cloud providers with resources from third-party services such as PagerDuty or New Relic. In essence, Terraform gives you a convenient way to manage all of your infrastructure as code without having to learn the separate tools and configuration syntax for each platform and service.

other

Terraform validates the configuration file before running the update. Not only does it check that all files are using the correct syntax (CloudFormation has similar validation), but it also checks that all parameters are accessible and the entire configuration is valid.

In Terraform, you can (and should) run a “Terraform Plan” step before applying any changes. This step will tell you exactly what will change and why.

When Terraform PALn runs, it shows that Terraform must destroy and recreate two ECR repositories because their names have changed.

CloudFormation supports change sets, which are very unfriendly and difficult to understand.

Terraform automatically formats code to help maintain a consistent code style and make pull requests easier to read. JSON(or now YAML) is a pain that afflicts CloudFormation developers in ways that developers using Terraform can hardly imagine.

Both Terraform and CloudFormation cover 100% of available AWS resources, but Terraform generally supports new available resources several months before CloudFormation does. All new AWS features must be released with REST API and SDK support for the primary language. CloudFormation support, on the other hand, is optional. But Terraform developers are eager to jump in and add features they want to use, so open source software stands out in this situation.

conclusion

So does this mean that Terraform is always better than CloudFormation? No, there are plenty of reasons to choose CloudFormation.

For example, when managing S3 buckets to store Terraform State files, it is best not to create them manually, because in this case one of the most important buckets in your infrastructure will become unmanageable and unauditable. Of course, you could provide it as a Terraform, but it seems to immediately become a chicken-and-egg question — where do you store the status file of the bucket used to store the status file? One option is to commit it to a source control system, which may work if you don’t modify the resource often, but this is usually not the best option. CloudFormation might be an attractive option for managing this bucket because you don’t have to worry about status files at all. Alternatively, you can first create it in Terraform using local state, and then add the S3 back end to the bucket you just created. After reinitializing the project by running “Terraform Init,” Terraform migrates the status file to S3.

Another example is automatic zooming and scrolling for updates. Unfortunately, it is only available as part of the CloudFormation API, so there is no choice but to manage it using CloudFormation. As a workaround, you can have the best of both worlds by packaging this CloudFormation Stack resource as a Terraform.

resource "aws_cloudformation_stack" "autoscaling_group" {
  name = "${var.cfn_stack_name}"
 
  template_body = <<EOF
Description: "${var.cfn_stack_description}"
Resources:
  ASG:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      VPCZoneIdentifier: ["${join("\", \", var. Subnets)} ${join("\", \", var. Subnets)}"]
      AvailabilityZones: ["${join("\", \", var. Availability_zones)}"]
      LaunchConfigurationName: "${aws_launch_configuration.ecs.name}"
      MinSize: "${var.asg_min_size}"
      MaxSize: "${var.asg_max_size}"
      DesiredCapacity: "${var.asg_desired_capacity}"
      HealthCheckType: EC2
 
    CreationPolicy:
      AutoScalingCreationPolicy:
        MinSuccessfulInstancesPercent: 80
      ResourceSignal:
        Count: "${var.cfn_signal_count}"
        Timeout: PT10M
    UpdatePolicy:
    # Ignore differences in group size properties caused by scheduled actions
      AutoScalingScheduledAction:
        IgnoreUnmodifiedGroupSizeProperties: true
      AutoScalingRollingUpdate:
        MaxBatchSize: "${var.asg_max_size}"
        MinInstancesInService: "${var.asg_min_size}"
        MinSuccessfulInstancesPercent: 80
        PauseTime: PT10M
        SuspendProcesses:
          - HealthCheck
          - ReplaceUnhealthy
          - AZRebalance
          - AlarmNotification
          - ScheduledActions
        WaitOnResourceSignals: true
    DeletionPolicy: Retain
  EOF
}
Copy the code

Language translator

I intended to use it for skill learning + English training, but I didn’t expect the translation process to be so painful, and the translation is also very bad (may be a face of confusion), but I still want to thank Youdao Dictionary.

My colleagues wrote Terraform articles. If you are interested, you can go to see them and send them: