Compare commits

...

10 Commits

6 changed files with 265 additions and 48 deletions

0
.gitignore vendored Normal file → Executable file
View File

0
.terraform.lock.hcl generated Normal file → Executable file
View File

221
README.md Normal file → Executable file
View File

@ -1,42 +1,193 @@
# Terraform Base Infra Modules # Terraform AWS Base Infrastructure Module
By using this module you can quickly configure a new account and deploy the basic infrastructure into it making adding accounts and configuring them a relative breeze ## Overview
* This module consists only of other modules, no actual end resources like EC2 hosts or security groups are defined here, only references to these resources are defined here. All modules that make up this base_infra module are all individualy versioned to make sure that environments are all configured alike without losing the ability to make changes to the individual accounts. This comprehensive Terraform module provisions a complete AWS infrastructure foundation including VPC, subnets, EKS cluster, node groups, bastion host, and VPC flow logs. It provides a production-ready, scalable base infrastructure for running containerized workloads on Amazon EKS.
Currently this modules is consuming several other modules, below a list of all these modules; ## Features
- label module (simplifies the labeling and naming of resources)
- vpc module (Creates the VPC's and related resources like internet gateways, nat gateways, route tables, routes, peerings etc)
- bastion module (Creates a bastion host and the required security groups)
- subnets module (Creates the public and private subnets in the availability zones you specified)
- eks_cluster module (Creates all resources to get an EKS cluster backend up and running)
- eks_node_group module (Creates and configures the eks workernodes that will run the workloads )
- flow_logs module (Enables all the network resources in the account to enable flowlogs)
-
Using this module is actualy very simple and consists only of adding the following piece of code to a file with the .tf extension and define the variables in one of the following files; terraform.tfvars or variables.tf
``` - Complete VPC setup with configurable CIDR blocks
module "base_infra" { - Dynamic subnet creation across multiple availability zones
source = "../../platform" - Public and private subnet configuration with NAT gateways
# Variables go beneath this line - VPC Flow Logs for network monitoring
name = var.name - EC2 Bastion host for secure SSH access
vpc_cidr_block = var.vpc_cidr_block - Amazon EKS cluster with configurable Kubernetes version
stage = var.stage - EKS Node Groups with auto-scaling capabilities
prefix = var.prefix - OIDC provider integration for IAM roles for service accounts
availability_zones = var.availability_zones - Security groups and IAM roles properly configured
keyname = var.keyname - CloudPosse naming conventions for consistent resource naming
public_keyname = var.public_keyname
region = var.region ## Resources Created
instance_types = var.instance_types
bastion_instance_type = var.bastion_instance_type ### Networking
bastion_ami = var.bastion_ami - AWS VPC
disk_size = var.disk_size - Internet Gateway
max_size = var.max_size - NAT Gateways (one per AZ)
min_size = var.min_size - Public and Private Subnets (dynamic across AZs)
kubernetes_labels = var.kubernetes_labels - Route Tables
kubeconfig_path = var.kubeconfig_path - VPC Flow Logs (CloudWatch Logs integration)
desired_size = var.desired_size
aws_eks_update_kubeconfig_additional_arguments = var.aws_eks_update_kubeconfig_additional_arguments ### Compute
- EC2 Bastion Server with Elastic IP
- EKS Cluster
- EKS Node Group with Auto Scaling
### Security
- Security Groups for bastion and EKS cluster
- IAM Roles and Policies for EKS cluster and worker nodes
- OIDC Identity Provider (optional)
### Monitoring
- VPC Flow Logs with CloudWatch Log Group
## Usage
```hcl
module "base_infrastructure" {
source = "git@github.com:webuildyourcloud/terraform-aws-base_infra.git"
# Required Variables
region = "us-east-1"
availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"]
vpc_cidr_block = "10.0.0.0/16"
# Naming Convention
prefix = "myorg"
stage = "prod"
name = "app"
delimiter = "-"
attributes = []
# Bastion Configuration
bastion_instance_type = "t3.micro"
bastion_ami = "ami-0c55b159cbfafe1f0"
keyname = "my-ssh-key"
security_groups = []
# EKS Configuration
kubernetes_version = "1.21"
instance_types = ["t3.medium"]
desired_size = 3
min_size = 2
max_size = 5
disk_size = 20
kubeconfig_path = "./kubeconfig"
oidc_provider_enabled = true
# Kubernetes Labels
kubernetes_labels = {
Environment = "production"
Team = "platform"
}
# Tags
tags = {
Environment = "production"
ManagedBy = "terraform"
}
} }
``` ```
## Variables
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|----------|
| region | AWS Region | `string` | n/a | yes |
| availability_zones | List of availability zones | `list(string)` | n/a | yes |
| vpc_cidr_block | VPC CIDR block | `string` | n/a | yes |
| prefix | Namespace for the organization | `string` | n/a | yes |
| stage | Stage (e.g., 'prod', 'staging', 'dev') | `string` | n/a | yes |
| name | Solution name | `string` | n/a | yes |
| delimiter | Delimiter between name components | `string` | `"-"` | no |
| attributes | Additional attributes | `list(string)` | `[]` | no |
| tags | Additional tags | `map(string)` | `{}` | no |
| bastion_instance_type | EC2 instance type for bastion | `string` | n/a | yes |
| bastion_ami | AMI ID for bastion host | `string` | n/a | yes |
| keyname | SSH key name | `string` | `""` | no |
| security_groups | Security groups allowed to connect to bastion | `list(string)` | n/a | yes |
| user_data | User data content for bastion | `list(string)` | `[]` | no |
| root_block_device_encrypted | Encrypt root block device | `bool` | `false` | no |
| root_block_device_volume_size | Root block device volume size (GiB) | `number` | `8` | no |
| metadata_http_endpoint_enabled | Enable metadata service | `bool` | `true` | no |
| metadata_http_put_response_hop_limit | HTTP PUT response hop limit | `number` | `1` | no |
| metadata_http_tokens_required | Require metadata session tokens | `bool` | `false` | no |
| associate_public_ip_address | Associate public IP to bastion | `bool` | `true` | no |
| kubernetes_version | Kubernetes version | `string` | `null` | no |
| desired_size | Desired number of worker nodes | `number` | n/a | yes |
| max_size | Maximum number of worker nodes | `number` | n/a | yes |
| min_size | Minimum number of worker nodes | `number` | n/a | yes |
| oidc_provider_enabled | Create IAM OIDC provider | `bool` | `true` | no |
| kubeconfig_path | Path to kubeconfig file | `string` | n/a | yes |
| disk_size | Disk size in GiB for worker nodes | `number` | n/a | yes |
| instance_types | Instance types for EKS nodes | `list(string)` | n/a | yes |
| kubernetes_labels | Kubernetes labels for node group | `map(string)` | n/a | yes |
| kubernetes_namespace | Kubernetes namespace for Fargate | `string` | `"kube-apps"` | no |
| aws_eks_update_kubeconfig_additional_arguments | Additional arguments for kubeconfig update | `string` | `null` | no |
## Outputs
| Name | Description |
|------|-------------|
| public_subnet_cidrs | Public subnet CIDRs |
| private_subnet_cidrs | Private subnet CIDRs |
| public_subnet_ids | Public subnet IDs |
| private_subnet_ids | Private subnet IDs |
| vpc_cidr_block | VPC CIDR block |
| vpc_id | VPC ID |
| security_groups | Security Group IDs of bastion |
| eks_cluster_id | EKS cluster name |
| eks_cluster_arn | EKS cluster ARN |
| eks_cluster_endpoint | Kubernetes API server endpoint |
| eks_cluster_version | Kubernetes server version |
| eks_cluster_identity_oidc_issuer | OIDC Identity issuer |
| eks_cluster_certificate_authority_data | EKS cluster CA certificate |
| eks_cluster_auth_token | Cluster authentication token |
| workers_security_group_ids | Worker nodes security group |
| eks_node_group_role_arn | Worker nodes IAM role ARN |
| eks_node_group_role_name | Worker nodes IAM role name |
| eks_node_group_id | EKS Node Group ID |
| eks_node_group_arn | EKS Node Group ARN |
| eks_node_group_resources | Node Group underlying resources |
| eks_node_group_status | Node Group status |
## Requirements
| Name | Version |
|------|---------|
| terraform | >= 0.13 |
| aws | ~> 3.27 |
## Dependencies
This module uses the following external modules:
- [cloudposse/terraform-null-label](https://github.com/cloudposse/terraform-null-label) - Resource naming
- [cloudposse/vpc/aws](https://registry.terraform.io/modules/cloudposse/vpc/aws) - VPC creation
- [umotif-public/vpc-flow-logs/aws](https://registry.terraform.io/modules/umotif-public/vpc-flow-logs/aws) - VPC Flow Logs
- [cloudposse/dynamic-subnets/aws](https://registry.terraform.io/modules/cloudposse/dynamic-subnets/aws) - Dynamic subnet creation
- [cloudposse/ec2-bastion-server/aws](https://registry.terraform.io/modules/cloudposse/ec2-bastion-server/aws) - Bastion host
- Custom modules:
- terraform-aws-eks-cluster
- terraform-aws-eks_node_group
## Important Notes
1. **SSH Key**: Ensure the SSH key specified in `keyname` exists in the target region before applying
2. **VPC CIDR**: Choose a CIDR block that doesn't conflict with other VPCs in your environment
3. **NAT Gateways**: This module creates NAT gateways which incur hourly charges
4. **EKS Cluster**: Initial cluster creation takes approximately 10-15 minutes
5. **OIDC Provider**: Enable OIDC provider for using IAM roles for Kubernetes service accounts
6. **Kubeconfig**: The module expects a path where it can write the kubeconfig file
7. **Security Groups**: Additional security groups can be attached to the bastion host via the `security_groups` variable
## Security Considerations
- VPC Flow Logs are enabled by default for network monitoring
- Bastion host is configured in public subnets with restricted security groups
- EKS cluster and worker nodes are deployed in private subnets
- IMDSv2 can be enforced via `metadata_http_tokens_required`
- Root volume encryption can be enabled via `root_block_device_encrypted`
## License
This module is provided as-is for use within your organization.

41
main.tf Normal file → Executable file
View File

@ -81,22 +81,37 @@ module "subnets" {
# #tags = local.tags # #tags = local.tags
#} #}
module "bastion" {
source = "git@github.com:webuildyourcloud/terraform-aws-bastion.git?ref=tags/0.0.1"
enable_bastion = true
environment = var.stage
project = var.prefix
aws_region = var.region
key_name = var.keyname
instance_type = var.bastion_instance_type
subnet_id = element(module.subnets.public_subnet_ids, 0)
vpc_id = module.vpc.vpc_id
tags = {
Name = "${var.prefix}-${var.stage}-bastion" module "ec2-bastion-server" {
} source = "cloudposse/ec2-bastion-server/aws"
version = "0.28.0"
instance_type = var.bastion_instance_type
security_groups = compact(concat([module.vpc.vpc_default_security_group_id], var.security_groups))
subnets = module.subnets.public_subnet_ids
key_name = var.keyname
user_data = var.user_data
vpc_id = module.vpc.vpc_id
associate_public_ip_address = true
} }
#module "bastion" {
# source = "git@github.com:webuildyourcloud/terraform-aws-bastion.git?ref=tags/0.0.7"
# enable_bastion = true
# environment = var.stage
# project = var.prefix
# aws_region = var.region
# key_name = var.keyname
# instance_type = var.bastion_instance_type
# subnet_id = element(module.subnets.public_subnet_ids, 0)
# vpc_id = module.vpc.vpc_id
#
# tags = {
# Name = "${var.prefix}-${var.stage}-bastion"
# }
#}
module "eks_cluster" { module "eks_cluster" {
source = "git@github.com:webuildyourcloud/terraform-aws-eks-cluster.git?ref=tags/0.0.3" source = "git@github.com:webuildyourcloud/terraform-aws-eks-cluster.git?ref=tags/0.0.3"
stage = var.stage stage = var.stage

5
outputs.tf Normal file → Executable file
View File

@ -28,6 +28,11 @@ output "vpc_id" {
description = "VPC ID Main VPC" description = "VPC ID Main VPC"
} }
output "security_groups" {
value = module.ec2_bastion.security_group_ids
description = "Security Group Id of Default VPC"
}
#### eks_cluster outputs #### #### eks_cluster outputs ####
output "eks_cluster_id" { output "eks_cluster_id" {
description = "The name of the cluster" description = "The name of the cluster"

46
variables.tf Normal file → Executable file
View File

@ -64,6 +64,52 @@ variable "public_keyname" {
default = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDboPfi18b0We79c6mqQui+iPPL0KqUWIdm02hb6RyQ67buYPik6KRAin8hiwvgVHyBF3sdnDsaP9snSFq2QQXUtdB5MxHplIJSbdd/oREtTXHCc9OfhGEuJDqQ8ViHj1ApYlLNIohHAhJkVywkpMhLUHqLZ2DXhwVjM9XDHx0aoImwcyczzU9e4T8jtvLB+PlDRNxvCrKuf6Ir6sd1u9vHWQYR4kV61T3Z/VaeRPSF5Y50IF5ECTrNoQeR0NSRIrY6g4/hZzMisLxpybtO44jkZ7OPVwhAjfZgTTZYnrrSkdoL8HYbaEuKZC/WPvoCOfq5eF4ydpwUQomzeCD9pnOX pderuiter@MacBook-Pro-van-Patrick.local" default = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDboPfi18b0We79c6mqQui+iPPL0KqUWIdm02hb6RyQ67buYPik6KRAin8hiwvgVHyBF3sdnDsaP9snSFq2QQXUtdB5MxHplIJSbdd/oREtTXHCc9OfhGEuJDqQ8ViHj1ApYlLNIohHAhJkVywkpMhLUHqLZ2DXhwVjM9XDHx0aoImwcyczzU9e4T8jtvLB+PlDRNxvCrKuf6Ir6sd1u9vHWQYR4kV61T3Z/VaeRPSF5Y50IF5ECTrNoQeR0NSRIrY6g4/hZzMisLxpybtO44jkZ7OPVwhAjfZgTTZYnrrSkdoL8HYbaEuKZC/WPvoCOfq5eF4ydpwUQomzeCD9pnOX pderuiter@MacBook-Pro-van-Patrick.local"
} }
variable "security_groups" {
type = list(string)
description = "List of Security Group IDs allowed to connect to the bastion host"
}
variable "user_data" {
type = list(string)
default = []
description = "User data content"
}
variable "root_block_device_encrypted" {
type = bool
default = false
description = "Whether to encrypt the root block device"
}
variable "root_block_device_volume_size" {
type = number
default = 8
description = "The volume size (in GiB) to provision for the root block device. It cannot be smaller than the AMI it refers to."
}
variable "metadata_http_endpoint_enabled" {
type = bool
default = true
description = "Whether the metadata service is available"
}
variable "metadata_http_put_response_hop_limit" {
type = number
default = 1
description = "The desired HTTP PUT response hop limit (between 1 and 64) for instance metadata requests."
}
variable "metadata_http_tokens_required" {
type = bool
default = false
description = "Whether or not the metadata service requires session tokens, also referred to as Instance Metadata Service Version 2."
}
variable "associate_public_ip_address" {
type = bool
default = true
description = "Whether to associate public IP to the instance."
}
### Kubernetes Settings ### ### Kubernetes Settings ###
variable "kubernetes_version" { variable "kubernetes_version" {
type = string type = string