Terraforming my world

@nathandench

https://ndench.github.io

#BrisPHP

From "interested but scared" to never manually provisioning infrastructure again

Who am I?

  • Co-founder of ProcurePro.co
  • Fullstack Symfony + Aurelia engineer
  • Begrudging DevOps engineer
  • Absolutely hate manual repetitive tasks

In the beginning

  • Handcrafted snowflake servers
  • Confluence page documentation
  • No CI pipeline
  • Manual deploys with SSH + git pull
  • Weekly downtime with manual fixes
  • Shared Virtualbox images for dev
  • High bus factor

Is there a better way?

  • Improve developer experience
  • Improve development speed
  • Autoscaling/autohealing infrastructure
  • Less bugs/errors in production
  • Infrastructure shouldn't need constant maintenance
  • Smaller bus factor

Step 1

  1. Series of bash scripts to create a server
  2. Make an AMI
    • Packer = bonus points
  3. One "special" server for cron jobs, etc
  4. Other servers can be duplicated for scale
  5. Dev box built from same script + extras
    • Packer = bonus points

Step 2

  1. Create CI build servers
    • Use existing scripts
    • Containers or dedicated server
  2. CI build tasks
    • Automated tests
    • Database fixtures = bonus points
    • Static analysis
  3. Deployment
    • Can script ssh deploys
    • Or use CodeDeploy, Deployer, etc
  4. Migrations = bonus points

Step 3

  • VPC
  • Subnets
  • CIDR blocks
  • DHCP options
  • Internet gateway
  • NAT gateways/instances
  • Route tables
  • Subnet groups
    • Database
    • Elasticache
    • Redshift
  • Security groups
  • IAM roles
  • Network ACLs
  • Customer gateways
  • VPN gateways

Terraform the hard parts

Step 3

Terraform the hard parts

Step 3

Terraform the hard parts

$ cd terraform

$ terraform import aws_vpc.this vpc-a01106c2
Successfully imported!

$ terraform import aws_internet_gateway.this igw-c0a643a9
Successfully imported!

$ terraform import aws_subnet.public subnet-9d4a7b6c
Successfully imported!

$ terraform import aws_subnet.private subnet-9d4a7b6c
Successfully imported!

$ terraform import aws_nat_gateway.this nat-05dba92075d71c408
Successfully imported!
terraform/
├─ main.tf

Step 4

Custom modules

Step 4

$ terraform state aws_vpc.this module.infra.aws_vpc.this
Successfully moved!

$ terraform state mv aws_internet_gateway.this module.infra.aws_internet_gateway.this
Successfully moved!

$ terraform state mv aws_subnet.public module.infra.aws_subnet.public
Successfully moved!

$ terraform state mv aws_subnet.private module.infra.aws_subnet.private
Successfully moved!

$ terraform state mv aws_nat_gateway.this module.infra.aws_nat_gateway.this
Successfully moved!

Custom modules

terraform/
├─ modules/
│  ├─ main.tf
├─ staging/
│  ├─ main.tf
├─ producton/
│  ├─ main.tf

Step 5

Third party modules

Pros

  • Easily use more features
  • Use better more well maintained code

Cons

  • Need to ensure module is maintained
  • Might not have the options you need

Step 5

Third party modules

What did all this get me?

  • Create separate environments easily
  • Completely ignore infrastructure
  • Easier to re-learn after a break
  • Easier to teach to others (bus factor)
  • Create an entirely separate app in a few days
    • 80+ resources per environment
    • 70+ resources in CI pipeline

Question time!

@nathandench

https://ndench.github.io

#BrisPHP

Terraforming my world

By Nathan Dench

Terraforming my world

  • 346