I am new to terraform and aws, all I want to do is launch an aws ec2 instance with elastic load balancer with terraform. I get some of the configuration examples from various sites but don't know what is right way to implement those configurations, what should be the folder structure and everything. I had done it using GUI of aws but not getting much help with terraform.
Here the server should be apache2.
Any help is appreciated.
Thanks in advance
As per your requirement of creating Elastic Loadbalancer, using terraform. You will need to create the following resources.
If you already have the EC2 instance created and just want to attach them to ELB.
Create Target Group
Create ELB
Assign the Target Group to your ELB
Register your existing instance to your Target Group
If you don't have any instance created,
Create Target Group
Create ELB
Assign the Target Group to your ELB
Create Launch Template/Configuration
Create ASG, assign the ELB to ASG
The new instance created through ASG will auto-register to the ELB target group.
Terraform Resource example,
Launch Configuration
resource "aws_launch_configuration" "Your_Launch_Configuration" {
name = "launch_conf_name"
instance_type = "Instance_Type"
image_id = "AMI_image_id"
key_name = "Key_Name"
security_groups = "security_groups_id"
user_data = "User Data"
iam_instance_profile = "Instance IAM Role"
}
Auto Scaling Group
resource "aws_autoscaling_group" "Your_ASG" {
name = "ASG Name"
launch_configuration = aws_launch_configuration.Your_Launch_Configuration.id
max_size = "Max size"
min_size = "Min Size"
desired_capacity = "Desired Capacity"
vpc_zone_identifier = "Your Subnet List"
tags = [{
"key" = "Name"
"value" = "ASG Name"
"propagate_at_launch" = true
}]
health_check_grace_period = "300"
target_group_arns = "set of your ELB target Group"
}
Load Balancer Target Group
resource "aws_load_balancer_target_group" "Your_target_group" {
name = "Target_group_name"
port = "80"
protocol = "HTTP"
vpc_id = "Your_vpcid"
tags = {
name = "Target_group_name"
}
health_check {
enabled = true
interval = 300 # health check interval
protocol = "HTTP"
timeout = 300 # timeout seconds
path = "/" # your health check path
}
}
Load Balancer
resource "aws_load_balancer" "your_load_balancer" {
name = load_balancer_name
load_balancer_type = "application"
internal = true # if not internet facing
subnets = ["List of your subnet id"]
security_groups = ["List of your security group id"]
tags = {
"name" = load_balancer_Target_group_name
}
}
Load Balancer Listner
resource "aws_load_balancer_listener" "your_load_balancer_Listner" {
load_balancer_arn = listner_load_balancer_arn #arn of your load balancer
port = "80"
protocol = "http"
default_action {
target_group_arn = listner_Target_group_arn # arn of your target group
type = "forward"
}
}
Related
I am trying to attach Elastic IP to multiple EC2 Instances using terraform. I have been able to create EC2 instances , VPC and Security groups but getting error while attaching Elastic IP's to EC2 instances.
Resource AWS_Instance
resource "aws_instance" "create_instance" {
for_each = toset(var.instance_type)
ami = var.ami
instance_type = each.value
vpc_security_group_ids = [aws_security_group.vpc-ssh.id, aws_security_group.vpc-web.id]
availability_zone = var.availability_zone[index(var.instance_type,each.value)]
tags = {
"key" = each.value
}
}
I am not able to decode how should the instance id be populated inside the elastic IP resource definition.
Create Elastic IP
resource "aws_eip" "my-eip" {
for_each = toset(var.instance_type)
instance = aws_instance.create_instance[???].id // what should be used here
vpc = true
depends_on = [aws_internet_gateway.vpc-dev-igw] }
Since you are looping through the variable instance_type for both resources, you have to put each.value for referencing the EC2 instances:
resource "aws_eip" "my-eip" {
for_each = toset(var.instance_type)
instance = aws_instance.create_instance[each.value].id
vpc = true
depends_on = [aws_internet_gateway.vpc-dev-igw]
}
Having an issue with a Terraform deployment. I have a module that creates a network, and then another module that creates a series of ec2 instances. These servers are required to have specific IP addresses, which are called out in the module (I would rather dynamically set these but for now they are 'hardcoded'). However, I am getting a warning that the IP address I am associating with the ec2 instance 'does not fall within the subnet's address range', but it is. Here is the basic breakdown:
servers
->main.tf
->variables.tf
->outputs.tf
network
->main.tf
->variables.tf
->outputs.tf
main.tf
The relevant bits are as follows:
network main.tf
# Create VPC
resource "aws_vpc" "foo" {
cidr_block = "192.168.1.0/24"
enable_dns_hostnames = "true"
enable_dns_support = "true"
tags = {
Name = "foo"
}
}
# Create a Subnet
resource "aws_subnet" "subnet-1" {
vpc_id = aws_vpc.foo.id
cidr_block = "192.168.1.0/24"
availability_zone = "ca-central-1a"
tags = {
Name = "subnet-1"
}
}
servers main.tf
resource "aws_instance" "bar" {
ami = var.some_ami
instance_type = "t3.medium"
associate_public_ip_address = true
private_ip = "192.168.1.15"
# root disk
root_block_device {
volume_size = "60"
volume_type = "gp3"
encrypted = true
delete_on_termination = true
}
tags = {
Name = "bar"
}
}
main.tf
module "network" {
source = "./network"
}
module "servers" {
source = "./servers"
subnet_id = module.network.aws_subnet
}
Everything works correctly, and I verified in AWS that the VPC is created, and the subnet is created, but for some reason when the server is getting created I get the following error:
│ Error: creating EC2 Instance: InvalidParameterValue: Address 192.168.1.15 does not fall within the subnet's address range status code: 400
I left out some of the irrelevant bits of the tfs but everything else works as expected except this one thing. Anyone know whats going on?
Your aws_instance resource does not have subnet_id attribute. So instances are being launched in default subnet.
Add subnet_id attribute as below
resource "aws_instance" "bar" {
ami = var.some_ami
instance_type = "t3.medium"
associate_public_ip_address = true
subnet_id = "your_subnet_id"
private_ip = "192.168.1.15"
# root disk
root_block_device {
volume_size = "60"
volume_type = "gp3"
encrypted = true
delete_on_termination = true
}
tags = {
Name = "bar"
}
}
You could also use data resource to get the subnet id.
data "aws_subnet" "selected" {
filter {
name = "tag:Name"
values = ["myawesomesubnet"]
}
}
I'm aware that there already exists several posts similar to this one - I've went through them and adapted my Terraform configuration file, but it makes no difference.
Therefore, I'd like to publish my configuration file and my use case: I'd like to provision a (Windows) Virtual Machine on AWS, using Terraform. It works without the File Provisioning part - including them, the provisioning results in a timeout.
This includes adaptations from previous posts:
SSH connection restriction
SSH isnt working in Windows with Terraform provisioner connection type
Usage of a Security group
Terraform File provisioner can't connect ec2 over ssh. timeout - last error: dial tcp 92.242.xxx.xx:22: i/o timeout
I also get a timeout when using "winrm" instead of "ssh".
I'd be happy if you could provide any hint for following config file:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
# Configure the AWS Provider
provider "aws" {
access_key = "<my access key>"
secret_key = "<my secret key>"
region = "eu-central-1"
}
resource "aws_instance" "webserver" {
ami = "ami-07dfec7a6d529b77a"
instance_type = "t2.micro"
security_groups = [aws_security_group.sgwebserver.name]
key_name = aws_key_pair.pubkey.key_name
tags = {
"Name" = "WebServer-Win"
}
}
resource "null_resource" "deployBundle" {
connection {
type = "ssh"
user = "Administrator"
private_key = "${file("C:/Users/<my user name>/aws_keypair/aws_instance.pem")}"
host = aws_instance.webserver.public_ip
}
provisioner "file" {
source = "files/test.txt"
destination = "C:/test.txt"
}
depends_on = [ aws_instance.webserver ]
}
resource "aws_security_group" "sgwebserver" {
name = "sgwebserver"
description = "Allow ssh inbound traffic"
ingress {
from_port = 0
to_port = 6556
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "sgwebserver"
}
}
resource "aws_key_pair" "pubkey" {
key_name = "aws-cloud"
public_key = file("key/aws_instance.pub")
}
resource "aws_eip" "elasticip" {
instance = aws_instance.webserver.id
}
output "eip" {
value = aws_eip.elasticip.public_ip
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["eu-central-1a", "eu-central-1b", "eu-central-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = true
tags = {
Terraform = "true"
Environment = "dev"
}
}
Thanks a lot in advance!
Windows EC2 instances don't support SSH, they support RDP. You would have to install SSH server software on the instance before you could SSH into it.
I suggest doing something like placing the file in S3, and using a user data script to trigger the Windows EC2 instance to download the file on startup.
I am trying to create multiple ec2 instance with this script
resource "aws_instance" "my-instance" {
count = 3
ami = ...
instance_type = ...
key_name = ...
security_groups = ...
tags = {
Name = "my-instance - ${count.index + 1}"
}
}
This creates 3 instances. But all three are in same availability zones. I want to create one instance in each availability zone or one in each of the availability zone that I provide. How can I do it?
I read that I can use
subnet_id = ...
option to specify the availability zone where the instance should be created. But I am not able to figure out how to loop through instance creation (which is currently being handled by count parameter) and specifiy different subnet_id
Can someone help please.
There are several ways of accomplishing this. What I would recommend is to create a VPC with 3 subnets and place an instance in each subnet:
# Specify the region in which we would want to deploy our stack
variable "region" {
default = "us-east-1"
}
# Specify 3 availability zones from the region
variable "availability_zones" {
default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
# Configure the AWS Provider
provider "aws" {
region = var.region
}
# Create a VPC
resource "aws_vpc" "my_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "my_vpc"
}
}
# Create a subnet in each availability zone in the VPC. Keep in mind that at this point these subnets are private without internet access. They would need other networking resources for making them accesible
resource "aws_subnet" "my_subnet" {
count = length(var.availability_zones)
vpc_id = aws_vpc.my_vpc.id
cidr_block = cidrsubnet("10.0.0.0/16", 8, count.index)
availability_zone = var.availability_zones[count.index]
tags = {
Name = "my-subnet-${count.index}"
}
}
# Put an instance in each subnet
resource "aws_instance" "foo" {
count = length(var.availability_zones)
ami = ...
instance_type = "t2.micro"
subnet_id = aws_subnet.my_subnet[count.index].id
tags = {
Name = "my-instance-${count.index}"
}
}
I am writing a TF script to launch an EC2 instance into an existing VPC. I have seen some examples where the script assigns the subnet id using a variable from another part of the script where the VPC and subnet was created.
Instead of using subnet_id = "${aws_subnet.main-public-1.id}" as was shown in that example, I tried putting the actual subnet id from an existing subnet in an existing vpn, both of which were made using the console, like this:
subnet_id = "subnet-xxxxx"
and applied the security group the same way. But when the EC instance got stood up, it was in the default VPC with the default security group. Why did this happen? How do I launch the EC2 into an existing VPC and subnet with existing security groups?
Here is the full script
EC2.tf
provider "aws" {
profile = "default"
region = var.region
}
resource "aws_instance" "WindowsBox" {
ami = "ami-xxxxx"
instance_type = "t2.medium"
key_name = aws_key_pair.keypair.key_name
subnet_id = "subnet-xxxxx"
vpc_security_group_ids = ["sg-xxxxx"]
tags = {
Name ="WindowsBox"
}
}
resource "aws_eip" "ip" {
vpc = true
instance = aws_instance.WindowsBox.id
}
resource "aws_key_pair" "keypair" {
key_name = "WindowsBox-keypair"
public_key = file("./kp/WindowsBox-keypair.pub")
}
Variables.tf
variable "region" {
default = "us-east-2"
}
The security group that you are using to create the instance should also exist inside the VPC. I think that's not the case here.
I would check the VPC id of the security group is matching with the VPC id of the subnet.
Hope this helps