A Terraform Module Managing EC2 Instances
Go to file
Matt Trachier fd6ed078e1
fix: this trigger is undertermined at plan time (#61)
Signed-off-by: Matt Trachier <matt.trachier@suse.com>
2024-03-14 16:27:51 -05:00
.github fix: make sure default ip is always available, send owners from aws to image outputs, validate image names (#57) 2024-03-13 16:31:24 -05:00
examples fix: make sure default ip is always available, send owners from aws to image outputs, validate image names (#57) 2024-03-13 16:31:24 -05:00
modules fix: this trigger is undertermined at plan time (#61) 2024-03-14 16:27:51 -05:00
tests fix: make sure default ip is always available, send owners from aws to image outputs, validate image names (#57) 2024-03-13 16:31:24 -05:00
.aliases feat: added more official cloud init support, added cloud init debugging logs, added a default private ip selection, updated dev functions (#54) 2024-03-12 00:33:23 -05:00
.envrc fix: attach security group as a separate resource than the server (#37) 2024-01-29 11:51:45 -06:00
.functions feat: added more official cloud init support, added cloud init debugging logs, added a default private ip selection, updated dev functions (#54) 2024-03-12 00:33:23 -05:00
.gitignore fix: add cloud-init timeout, update dev env, update workflows (#28) 2023-12-04 16:49:19 -06:00
.rcs feat: added more official cloud init support, added cloud init debugging logs, added a default private ip selection, updated dev functions (#54) 2024-03-12 00:33:23 -05:00
.variables fix: eip needs to be created to pass it (#56) 2024-03-12 00:52:03 -05:00
CHANGELOG.md chore(main): release 0.4.0 (#55) 2024-03-13 17:18:27 -05:00
README.md fix: update all tests to stop using the default vpc and subnet (#50) 2024-03-08 12:37:18 -06:00
flake.lock fix: attach security group as a separate resource than the server (#37) 2024-01-29 11:51:45 -06:00
flake.nix fix: make sure default ip is always available, send owners from aws to image outputs, validate image names (#57) 2024-03-13 16:31:24 -05:00
main.tf feat: add eip and handle cloud-init scripts better (#48) 2024-02-12 10:33:00 -06:00
outputs.tf add workfolder to outputs 2023-10-06 14:04:23 -05:00
terraform.md fix: add cloud-init timeout, update dev env, update workflows (#28) 2023-12-04 16:49:19 -06:00
validate-image.sh fix: make sure default ip is always available, send owners from aws to image outputs, validate image names (#57) 2024-03-13 16:31:24 -05:00
variables.tf feat: add eip and handle cloud-init scripts better (#48) 2024-02-12 10:33:00 -06:00
versions.tf fix: update required version of tf to the latest open source version (#46) 2024-02-09 12:09:18 -06:00

README.md

Terraform AWS Server

This module deploys infrastructure in AWS.

Recent Changes

  1. Servers will no longer deploy a public ip by default. You can override this by setting up a subnet that automatically deploys public ips. You can select to have a public IP added to your server with the 'add_public_ip' boolean variable. - this IP will be an elastic ip so it will cost a little bit extra, but will persist between server rebuilds
  2. This module has a lean towards enabling the provisioning of kubernetes clusters, so it has some additional requirements
    • the primary network interface's ip should not change even when the server is rebuilt
      • this allows us to have a more stable config and easier data recovery options

AWS Access

The first step to using the AWS modules is having an AWS account, here is a document describing this process. You will need an API access key id and API secret key, you can get the API keys following this tutorial. The Terraform AWS provider uses the AWS Go SDK, which allows the use of either environment variables or config files for authentication.

You do not need the AWS cli to generate the files, just place them in the proper place and Terraform will find and read them.

Server Types

This module provides a pre-chosen set of "types" of servers in order to reduce choice fatigue for the user and streamline testing. The choices are detailed in the server module and below:

# storage sizes in GB, using gp3 storage type
locals {
  types = {
    small = { # minimum required for rke2 control plane node, handles 0-225 agents
      id      = "t3.medium",
      cpu     = "2",
      ram     = "4",
      storage = "20",
    },
    medium = { # agent node, fits requirements for a database server or a small gaming server
      id      = "m5.large",
      cpu     = "2",
      ram     = "8",
      storage = "200",
    },
    large = { # control plane handling 226-450 agents, also fits requirements for a git server
      id      = "c5.xlarge",
      cpu     = "4",
      ram     = "8",
      storage = "500",
    },
    xl = { # control plane handling 451-1300 agents, also fits requirements for a large database server, gaming server, or a distributed storage solution
      id      = "t3.xlarge",
      cpu     = "4",
      ram     = "16",
      storage = "1000",
    }
    xxl = { # control plane handling 1300+ agents, also fits requirements for a large gaming server, a large database server, or a distributed storage solution
      id      = "m5.2xlarge",
      cpu     = "8",
      ram     = "32",
      storage = "2000",
    }
  }
}

Image types

This module provides a pre-chosen set of "types" of images in order to reduce choice fatigue for the user and streamline testing. The choices are detailed in the image module and below:

locals {
  types = {
    sles-15 = {
      user         = "ec2-user",
      group        = "wheel",
      name         = "suse-sles-15-sp5-v*-hvm-*",
      owner        = "amazon",
      architecture = "x86_64",
      workfolder   = "~"
    },
    sles-15-cis = { # WARNING! this AMI requires subscription to a service, it is not free
      user         = "ec2-user",
      group        = "wheel",
      name         = "CIS SUSE Linux Enterprise 15*",
      owner        = "aws-marketplace",
      architecture = "x86_64",
      workfolder   = "~"
    },
    rhel-8-cis = { # WARNING! this AMI requires subscription to a service, it is not free https://aws.amazon.com/marketplace/server/procurement?productId=ca1fe94d-9237-41c7-8fc8-78b6b0658c9f
      user         = "ec2-user",
      group        = "wheel",
      name         = "CIS Red Hat Enterprise Linux 8 STIG Benchmark*",
      owner        = "aws-marketplace",
      architecture = "x86_64",
      workfolder   = "/var/tmp"
    },
    ubuntu-20 = { # WARNING! you must subscribe and accept the terms to use this image
      user         = "ubuntu",
      group        = "admin",
      name         = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-*",
      owner        = "aws-marketplace",
      architecture = "x86_64",
      workfolder   = "~"
    },
    ubuntu-22 = { # WARNING! you must subscribe and accept the terms to use this image
      user         = "ubuntu",
      group        = "admin",
      name         = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-*",
      owner        = "aws-marketplace",
      architecture = "x86_64",
      workfolder   = "~"
    },
    rocky-8 = { # WARNING! you must subscribe and accept the terms to use this image
      user         = "ec2-user",
      group        = "wheel",
      name         = "Rocky-8-EC2-Base-8*",
      owner        = "aws-marketplace",
      architecture = "x86_64",
      workfolder   = "~"
    },
    # the goal for these search strings is to keep them as stable as possible without specifying a version that is EOL
    # our users often rely on extended support from RHEL, so we don't consider odd numbered minors which are inelegible for that
    # https://access.redhat.com/support/policy/updates/errata
    # therefore the search found here is the most recent even minor that has been released
    # expect RHEL 9.4 in June 2024
    rhel-9 = {
      user         = "ec2-user",
      group        = "wheel",
      name         = "RHEL-9.2.*_HVM-*-x86_64-*-Hourly2-GP3",
      owner        = "amazon",
      architecture = "x86_64",
      workfolder   = "~"
    },
    # following the same lines as rhel-9 this will be the most recent even minor that has been released
    # expect RHEL 8.10 in June 2024
    rhel-8 = {
      user         = "ec2-user",
      group        = "wheel",
      name         = "RHEL-8.8.*_HVM-*-x86_64-*-Hourly2-GP3",
      owner        = "amazon",
      architecture = "x86_64",
      workfolder   = "~"
    },
  }
}

Examples

Local State

The specific use case for the example modules is temporary infrastructure for testing purposes. With that in mind, it is not expected that we manage the resources as a team, therefore the state files are all stored locally. If you would like to store the state files remotely, add a terraform backend file (*.name.tfbackend) to your root module. https://www.terraform.io/language/settings/backends/configuration#file

Development and Testing

Paradigms and Expectations

Please make sure to read terraform.md to understand the paradigms and expectations that this module has for development.

Environment

It is important to us that all collaborators have the ability to develop in similar environments, so we use tools which enable this as much as possible. These tools are not necessary, but they can make it much simpler to collaborate.

  • I use nix that I have installed using their recommended script
  • I use direnv that I have installed using brew.
  • I simply use direnv allow to enter the environment
  • I navigate to the tests directory and run go test -v -timeout=40m -parallel=10
    • It is important to note that the test files do not stand alone, they expect to run as a package.
    • This means that specifying the file to test (as follows) will fail: go test -v -timeout 40m -parallel 10 basic_test.go
  • To run an individual test I navigate to the tests directory and run go test -v -timeout 40m -parallel 10 -run <test function name>
    • eg. go test -v -timeout 40m -parallel 10 -run TestBasic

Our continuous integration tests in the GitHub ubuntu-latest runner. It is free for public repositories, we use Nix to add dependencies to it for building and testing.