2. In the begging
resource "aws_instance" "web" {
ami = "ami-00162fa"
instance_type = "t2.micro"
}
3. Just plan!
$ terraform plan
# aws_instance.web must be replaced
-/+ resource "aws_instance" "web" {
~ ami = "ami-00162fa" -> "ami-00162fb" # forces replacement
}
Plan: 1 to add, 0 to change, 1 to destroy.
4. But even successful plans fail!
$ terraform apply
aws_instance.web: Destroying... [id=i-067578c3e140d38e5]
aws_instance.web: Destruction complete after 30s
aws_instance.web: Creating...
Error: Error launching source instance: InvalidAMIID.Malformed:
Invalid id: "ami-00162fb"
on main.tf line 1, in resource "aws_instance" "web":
1: resource "aws_instance" "web" {
15. Avoid using a single large terraform stack
● Reduce blast radius
● If possible break it up to independent stacks
● Use remote state data source provider for dependencies
● Smaller plan output
● Less changes
● Faster to plan and apply
17. Lint your code
$ tflint --deep
1 issue(s) found:
Error: "ami-00162fa" is invalid AMI ID. (aws_instance_invalid_ami)
on a.tf line 3:
3: ami = "ami-00162fa"
18. ● Monitoring
● Open Source Modules
● Test Environment
● Multiple stacks
● Linting
19. Run Terraform in your CI tool
● Automation Reduces Mistakes
● You can review the code before it gets applied!
● Less latency so more efficient
● Will not get interrupted by leaving for lunch!
● Developers can deploy without admin access
26. Terratest
terraformOptions := &terraform.Options {
// The path to where your Terraform code is located
TerraformDir: "../examples/terraform-basic-example",
}
// At the end of the test, run `terraform destroy` to clean up any resources
that were created
defer terraform.Destroy(t, terraformOptions)
// This will run `terraform init` and `terraform apply` and fail the test if
there are any errors
terraform.InitAndApply(t, terraformOptions)
// Validate your code works as expected
validateServerIsWorking(t, terraformOptions)
27. Tips
● Test various configurations that your module will be used
● Be aware of unique constraints
● Parallelism can speed things up
● Don’t pack too many things in the module
I started with terraform in 2017 when I join Olindata. I have a development background and before that when I heard infrastructure I walked in the opposite direction. Well now things are a bit changed. when It comes to infra as a code, I see things with my software engineering background. This talk is a little bit oriented towards AWS, since that’s what I have been working mostly.
With simple code there’s not much to go wrong.
Plan is basically like compiling. If it’s successful, your code has passed some linting and validation done by terraform and AWS provider. If you apply it should work. That’s what I was led to believe when i started with terraform
Now you have a half formed infrastructure! Other examples are startup scripts silently failing, s3 bucket creation failing because the bucket name is used somewhere else
First thing first, A failed infrastructure should make alarms go off, make graphs in your dashboard go abnormal, you want to catch silent failures. If you test something manually after deployment that should have been part of monitoring
Vpc is great example of module that people commonly don’t use and waste time trying to get AWS networking working! Public cloud is not easy! Best code is no code. Modules glue things together
Developing the same logic wrapped by modules, means time spent writing code and deploying it to see it works!
Test all changes on the test environment. It could be partially suspended when not in use depending on the size. You can potentially use terraform workspaces as well.
Tflint has 700 rules for AWS!
You can periodically run plan as well. Also now your audit records(cloudtrail) . terraform cloud.
You probably have organizational policies. For example No unencrypted EBS volumes. You can apply those policies to your code, store them in one place and test everything! First two only test the code. Terraform_validate uses python, conftest, Sentinel and terraform-compliance have their own languages.
With sentinel you can actually test depending on the contents of plan, for example you can only allow 1 change in a plan for a certain user or no resource could be deleted by certain user groups.
depending on how static or flexible your module is, you may not need this! But if your module is used in many stacks, you better make sure it has proper tests!