This module itends to deploy some base infrasctructure to AWS.
module "aws_base_infra" {
source = "github.com/dyegoe/terraform-aws-base-infra?ref=main"
project = "example-project"
key_name = "default"
zone_domain = "example.com"
vpc = {
cidr = "192.168.56.0/24"
azs = ["a", "b", "c"]
public_subnets = [
"192.168.56.0/26",
"192.168.56.64/26",
"192.168.56.128/26"
]
}
default_ingress_sg_rules = {
internal = {
from_port = -1,
to_port = -1,
ip_protocol = "-1",
cidr_ipv4 = ["0.0.0.0/0"],
description = "Allow any from anywhere"
}
}
instances = {
sample-node0001 = {
ami_id = "al2023"
instance_type = "t3.nano"
availability_zone = "a"
disk_size = 8
}
}
}
Name | Version |
---|---|
terraform | ~> 1.6.0 |
aws | ~> 5.19.0 |
cloudinit | ~> 2.3.2 |
random | ~> 3.5.1 |
Name | Version |
---|---|
aws | ~> 5.19.0 |
cloudinit | ~> 2.3.2 |
random | ~> 3.5.1 |
Name | Source | Version |
---|---|---|
vpc | terraform-aws-modules/vpc/aws | ~> 5.1.2 |
Name | Description | Type | Default | Required |
---|---|---|---|---|
assign_public_ip | Assign public IP to instances. You can override this value for each instance. | bool |
true |
no |
default_egress_sg_rules | Default egress rules that could be added to instances security groups when add_default_egress_sg_rules is set to true for each instance. |
map( |
{ |
no |
default_ingress_sg_rules | Default ingress rules that could be added to instances security groups when add_default_ingress_sg_rules is set to true for each instance. |
map( |
{} |
no |
instances | Map of objects to describe instances. Map key is used as a name for the instance and must be unique. Project name will be used as a prefix for the instance name. The ami_id accepts some pre-defined AMI names: amzn2 , al2023 , ubuntu2204 .The pre-defined AMI will always get the latest AMI ID for the selected region." The additional_disks is a map of objects to describe additional disks to create/attach to the instance. The key must be a device name.The additional_security_groups is a list of security groups to add to the instance. It must be a key from the security_groups variable.To add the default sg rules to the instance security group, set add_default_egress_sg_rules and/or add_default_ingress_sg_rules to true . |
map(object({ |
n/a | yes |
key_name | Pre-existent key name created on the same region and AWS account that you are creating the resources. It should match availabilty zones. |
string |
n/a | yes |
project | Project name. It will be used as a prefix for all resources. | string |
n/a | yes |
security_groups | Map of objects to describe security groups and its rules. | map(object({ |
n/a | yes |
ssh_port | SSH port. | number |
22 |
no |
volume_type | EBS Volume Type. | string |
"gp3" |
no |
vpc | A object containing VPC information. AZs must be a letter that represents the AZ. For example: ["a", "b", "c"]. Number of public subnets must match the number of availability zones. Tags are applied to all resources for the VPC. |
object({ |
n/a | yes |
zone_domain | A already hosted Route53 domain under the same AWS account that you are creating the resource. | string |
n/a | yes |
Name | Description |
---|---|
instances | It returns an object of all instances created by the module. |
instances_security_group_egress_rules | It returns an object of instances security group egress rules. |
instances_security_group_ingress_rules | It returns an object of instances security group ingress rules. |
shared_security_group_egress_rules | It returns an object of shared security group egress rules. |
shared_security_group_ingress_rules | It returns an object of shared security group ingress rules. |
shared_security_groups_id | It returns an object of shared security groups id. |
All componentes names are prefixed with the project name. For example: example-project-vpc
.
It uses terraform-aws-modules/vpc/aws to create a VPC with the following characteristics:
- No IPV6 support.
- No NAT gateway.
- No public subnets.
- No public IP is mapped on launch.
- Full DNS support.
- CIDR block is defined by VPC CIDR.
- AZs are defined by VPC AZs.
- Public subnets (CIDRs) are defined by VPC public subnets.
- Additional tags to the VPC and public subnets using VPC tags and VPC public subnet tags.
The AZs must be a letter that represents the AZ. For example: ["a", "b", "c"]. It will be concatenated with the (aws_region.current) region name to create the AZ name. The number of AZs must match the number of public subnets
Shared security groups are created iterating over the security group variable. The security group name is the project name concatenated with the security group name. For example: example-project-sample-sg
.
The map keys are the security group names and must be unique. Each security group has two lists: egress/ingress rules.
The egress/ingress rules are defined by the following syntax:
{
from_port = number
to_port = number
ip_protocol = string
cidr_ipv4 = optional(list(string), null)
self = optional(bool, false)
description = string
}
- The
cidr_ipv4
andself
are optional. - If
self
is set totrue
the security group id will be used as source or destination. Thencidr_ipv4
is not required and will be ignored. - If
self
is set tofalse
thecidr_ipv4
is required and the security group id will be ignored.
Each instace gets a security group. The security group name is the project name concatenated with the instance name and a random string. For example: example-project-sample-node0001-5f3a
. The random string is used to avoid security group name conflicts.
The egress/ingress rules are defined by the following variables:
var.default_egress_sg_rules
var.default_ingress_sg_rules
var.instances.egress_sg_rules
var.instances.ingress_sg_rules
var.instances.add_default_ingress_sg_rules
var.instances.add_default_egress_sg_rules
Security group rules have the following syntax:
{
from_port = number
to_port = number
ip_protocol = string
cidr_ipv4 = list(string)
description = string
}
The default egress/ingress rules could be included to the instances security group if var.instances.add_default_ingress_sg_rules
and/or var.instances.add_default_egress_sg_rules
is/are set to true
.
Because of a limitation of the aws_instance resource, the network interfaces don't get tags. The workaround is to use the aws_network_interface resource to create the network interfaces and then attach them to the instances. The network interface name is the project name concatenated with the instance name. For example: example-project-sample-node0001
.
There is a possibility to define the default behaviour of assigning EIPs to the instances by setting the assign_public_ip variable. If not provided, it will be set to true
by default. But you can override it specifying the assign_public_ip
attribute in the instances variable.
The EIP name is the project name concatenated with the instance name. For example: example-project-sample-node0001
.
This componente expects a hosted zone under the same AWS account that you are creating the resource. The hosted zone name must match the zone domain. For example: example.com
.
Additionaly, the project name is used as subdomain. For example: example-project.example.com
.
A internal zone (aws_route53_record.internal) is created following the same subdomain pattern (example-project.example.com
) and it is attached to the VPC.
By design, two records are created for each instance:
sample-node0001.example-project.example.com
on the public zone (aws_route53_record.public) pointing to the EIP.sample-node0001.example-project.example.com
on the internal zone (aws_route53_record.internal) pointing to the network interface private ip.
Each instance gets a root EBS volume when creating the instance. However, additional EBS volumes can be created and attached to the instance using the additional disks variable.
variable "instances" {
...
additional_disks = optional(map(object({
size = number
mount_point = string
volume_id = optional(string, "")
prevent_destroy = optional(bool, false)
})), {})
...
}
The variable above is iterated in different local variables to create the EBS volumes and attach them to the instance.
local.additional_disks_to_create_prevent_destroy
is a map of objects to create the EBS volumes with theprevent_destroy
attribute set totrue
andvolume_id
is not provided.local.additional_disks_to_create
is a map of objects to create the EBS volumes with theprevent_destroy
attribute set tofalse
andvolume_id
is not provided.local.additional_disks_to_attach
is a map of objects to attach the EBS volumes to the instance. It attaches all volumes created bylocal.additional_disks_to_create_prevent_destroy
andlocal.additional_disks_to_create
and also the volumes that already exists (volume_id
is provided).
NB: The prevent_destroy
attribute is used to avoid destroying the EBS volume when running terraform destroy
.
You must remove the resource manually:
terraform state list
terraform state show 'module.aws_base_infra.aws_ebs_volume.create["sample-master01_sdb"]'
terraform state rm 'module.aws_base_infra.aws_ebs_volume.create["sample-master01_sdb"]'
terraform destroy
Then, you can use this EBS volume later by providing the volume_id
attribute that matches id
from the terraform state show
command above.
variable "instances" {
...
additional_disks = {
sdb = {
size = 8
mount_point = "/data"
volume_id = "vol-0a1b2c3d4e5f6g7h8"
}
}
...
}
The resource aws_instance.this is used to create the instances. The instance name is the project name concatenated with the instance name. For example: example-project-sample-node0001
.
The resource iterates the map of objects provided by the instances variable to create the instances. Each map key represents the instance name and must be unique.
{
ami_id = string
instance_type = string
key_name = optional(string, "")
availability_zone = string
disk_size = optional(number, 8)
additional_disks = optional(map(object({
size = number
mount_point = string
volume_id = optional(string, "")
prevent_destroy = optional(bool, false)
})), {})
additional_security_groups = optional(list(string), [])
add_default_egress_sg_rules = optional(bool, true)
add_default_ingress_sg_rules = optional(bool, false)
egress_sg_rules = optional(map(object({
from_port = number
to_port = number
ip_protocol = string
cidr_ipv4 = list(string)
description = string
})), {})
ingress_sg_rules = optional(map(object({
from_port = number
to_port = number
ip_protocol = string
cidr_ipv4 = list(string)
description = string
})), {})
tags = optional(map(string), {})
}
ami_id
accepts some pre-defined AMI names:amzn2
,al2023
,ubuntu2204
. The pre-defined AMI will always get the latest AMI ID for the selected region.key_name
is the name of a pre-existent key created on the same region and AWS account that you are creating the resources. If not provided here, it uses the key_name variable.availability_zone
must be a letter that represents the AZ. For example: "a". It will be concatenated with the (aws_region.current) region name to create the AZ name.disk_size
is the root EBS volume size in GB. Default is 8.additional_disks
is a map of objects to describe additional disks to create/attach to the instance. The key must be a device name. See EBS Volumes for more details.additional_security_groups
is a list of additional security groups to attach to the instance. It must be a key from thesecurity_groups
map. See Security Groups for more details.add_default_egress_sg_rules
andadd_default_ingress_sg_rules
are used to add the default sg rules to the instance security group. Default istrue
foradd_default_egress_sg_rules
andfalse
foradd_default_ingress_sg_rules
.egress_sg_rules
andingress_sg_rules
are used to add additional sg rules to the instance security group. See Security Groups for more details.
The cloudinit_config.instance data source is used to create the cloud-init configuration. The cloud-init configuration is used to:
- Change the SSH port.
- Disable SELinux.
- Change hostname.
- Set search domain.
You can find an example here of how to use this module.
- Terraform
~> 1.4.0
- Although it may work with previous versions, it has not been tested.
- I recommend using tfenv to manage Terraform versions.
- pre-commit
== 3.3.2
- This repository uses pre-commit hooks to run some validations before committing new changes. You must install it in order to run the hooks.
- You can install it using pip:
pip install -r requirements.txt
- Then, install the git hook scripts:
pre-commit install
- terraform-docs
== v0.16.0
- tflint
== v0.47.0
- AWS Credentials
- You must have AWS credentials configured in order to run
terraform plan
andterraform apply
. - You can configure it using AWS CLI
- You must have AWS credentials configured in order to run
Module is maintained by Dyego Alexandre Eugenio
Apache 2 Licensed. See LICENSE for full details.