How to create aws_instance without ebs_block_device? - amazon-ec2

Im trying to create an EC2 instance without any additional ebs_block_device. I just need a root_block_device. It would appear the default behavior for ebs_block_device when no config is provided, is to create a 2048 GB volume. Is there any way to prevent this from happening?
Below is the aws_instance resource for your reference. I have tried setting volume_size to 0 which didn't trigger any errors but still created the default 2048 GB volume.
resource "aws_instance" "ec2_instance" {
ami = data.my_ami.id
instance_type = "t3.small"
root_block_device {
volume_size = 20
}
tags = {
Name = "my-ec2-host"
}
}
Update: I have understood that the additional 2048 ebs_block_device is default due to the AMI I am using. However is there any way to override this default (like I can from the UI)?

Related

Terraform create multiple ec2 instances in multiple subnets

I am trying to create multiple ec2 instances with access to multiple subnets.
I've found questions and answers on doing these things individually, but not combined.
First, I create a private and a public subnet, then I setup a local to store the IDs once they are created:
locals {
subnets = [ aws_subnet.public_subnet.id, aws_subnet.private_subnet.id ]
}
Next, I can create a variable number of servers in the private_subnet using for_each and the below:
servers = [ "s1", "s2" ]
resource "aws_instance" "system" {
for_each = var.servers
ami = var.aws_ami
instance_type = var.instance_type
#subnet_id = aws_subnet.private_subnet.id
count = 2
subnet_id = element(local.subs, count.index)
}
What I want to have, is that the server can access both subnets (it doesn't exist as far as I can tell, but the equivalent of subnet_ids = [aws_subnet.public_subnet.id, aws_subnet.private_subnet.id]).
I found a nice answer which works for a specific instance by creating two NICs (Terraform one EC2 instance with two subnets), however I need to do this var.servers times so it's difficult to hardcode the var.servers * 2 NICs with my current aws_instance setup (and I trip up when combining for_each and count).
Can someone please point me in the right direction?
Two create multiple servers (in your case 4 in total) in private (two servers) and public (two servers) subnets you can use count:
resource "aws_instance" "system" {
count = length(var.servers) * length(local.subnets)
ami = var.aws_ami
instance_type = var.instance_type
subnet_id = element(local.subnets, count.index)
}
For those looking to have a similar setup there are a few steps (assuming subnets and route tables already exist):
Create a machine on a single subnet
Create an additional network interface
Attach the network interface to the 'other' subnet (for the existing machine)
Create a variable for machines to create:
domains = [
"asd.com",
"asd2.com"
]
Create the machines on a single subnet:
resource "aws_instance" "domain" {
for_each = var.domains
ami = var.aws_ami
subnet_id = aws_subnet.public_subnet.id
associate_public_ip_address = true
tags = {
Name = "Instance - ${each.key}"
}
}
Create the additional interfaces for the 'other' subnet:
resource "aws_network_interface" "nics" {
for_each = var.domains
subnet_id = aws_subnet.private_subnet.id
tags = {
Name = "NIC - ${each.key}"
}
}
Attach the network interfaces to the 'other' subnet (for the existing machine):
resource "aws_network_interface_attachment" "attach_nics" {
for_each = var.domains
instance_id = aws_instance.domain[each.key].id
network_interface_id = aws_network_interface.nics[each.key].id
device_index = 1 # public_subnet = 0
}
The 'trick' here (that I didn't know) is understanding that you can access data from created resources based on their names in the existing script (which is used in the aws_network_interface_attachment component).

provisioning an EC2 instance with terraform InvalidKeyPair.NotFound

I've created a key pair for EC2 called terraform, downloaded the pem file to the same directory where my terraform files live, I issue a terraform apply and I get:
aws_instance.windows: Creating...
Error: Error launching source instance: InvalidKeyPair.NotFound: The key pair 'terraform' does not exist
status code: 400, request id: 1ac563d4-244a-4371-bde7-ee9bcf048830
I'm specifying the name of the key-value pair via an envrionment variable. This is the start of the block I'm using to create the Windows virtual machine:
resource "aws_instance" "windows" {
ami = data.aws_ami.Windows_2019.image_id
instance_type = var.windows_instance_types
key_name = var.key_name
vpc_security_group_ids = [aws_security_group.allow_rdp_winrm.id]
associate_public_ip_address = true
subnet_id = aws_subnet.subnet1.id
get_password_data = "true"
user_data = file("scripts/user_data.txt")
There is obviously something I'm doing wrong, do I need to tell terraform which aws region then key pair resides in ?
The key pairs are regional, so if you created them in one region, they aren't available in the other.
Terraform will always try to find and use the key in the region that you tell it to run in and if the key is not present, AWS will complain about this error.
Terraform also doesn't like it when things are created out of band and you might run into complications. It's also much cleaner to create the keypair using terraform and you can reference it as Atul has posted in his answer.
You could also import the key into Terraform or use Terraform's data sources to search and find the key as alternatives but these are a bit advanced, especially if you're getting started with Terraform.
You need to create a key pair first before consuming it.
resource "aws_key_pair" "my_key_pair" {
key_name = var.key_name
public_key = file("${abspath(path.cwd)}/my-key.pub")
}
Now use the key as
resource "aws_instance" "windows" {
ami = data.aws_ami.Windows_2019.image_id
instance_type = var.windows_instance_types
key_name = aws_key_pair.my_key_pair.key_name
I'll only provide an answer that pertains to your error message directly, as this question came up first on a Bing search.
The Data Source documentation doesn't make mention of Keypair. It might be presumed from the Instances Availability Zone.
data "aws_key_pair" "example" {
key_name = "terraform"
filter {
name = "tag:Component"
values = ["web"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
key_name = data.aws_key_pair.example.key_name
instance_type = "t3.micro"
tags = {
Name = "HelloWorld"
}
}
Instance resource declaration: https://registry.terraform.io/providers/hashicorp%20%20/aws/latest/docs/resources/instance
AWS Keypair Data Source: https://registry.terraform.io/providers/hashicorp%20%20/aws/latest/docs/data-sources/key_pair

How can I pass aws ec2 private ips to template file Using terraform

I am fairly new to terraform. I am trying to create number of ec2 instances and want to run bootstrap script once instance is ready, and in bootstrap script I need to pass private ips of instance created ( part of terraform script).
After so much of googling I came to know that I have to use terraform_file but, not able to use it correctly.
Terraform version: 0.11.13
/* Security group for the instances */
resource "aws_security_group" "test-reporting-sg"
{
name = "${var.environment}-test-reporting-sg"
vpc_id = "${var.vpc_id}"
}
data "template_file" "init"
{
count = "${var.instance_count}"
template = "${file("${path.module}/wrapperscript.sh")}"
vars = {
ip_addresses= "${aws_instance.dev-testreporting.*.private_ip}"
}
}
resource "aws_instance" "dev-testreporting"
{
count = "${var.instance_count}"
ami="${var.ami_id}"
instance_type ="${var.instance_type}"
key_name ="${var.key_name}"
security_groups = [ "${aws_security_group.test-reporting-sg.id}" ]
subnet_id = "${var.subnet_ids}"
user_data = "${data.template_file.init.*.rendered.[count.index]}"
}
Thanks
In resource module you can add private_ip like below
private_ip = "${lookup(var.private_ips,count.index)}"
and add private_ip values to variable file

Terraform: Cannot create spot instance. Error: MaxSpotInstanceCountExceeded

I am trying to create a spot instance in Terraform and the terraform code appears to be fine but I keep getting an error back saying MaxSpotInstanceCountExceeded.
NOTE: Right now this is just a test hence I am not including security groups, IPs, etc etc.
Steps I have taken:
Checked that I have 0 spot instance requests created in console.
Tried logging in to the console and creating a spot instance request. It works just fine.
Cancelled the spot instance request to ensure that I now have 0 spot instance requests.
Now I try and create virtually the same spot instance with the terraform script below, but I get the error: MaxSpotInstanceCountExceeded
Does anyone know why Terraform (or maybe AWS?) is not allowing me to create the spot instance using the terraform script, but it works just fine from the console?
Thanks!
provider "aws" {
profile = "terraform_enterprise_user"
region = "us-east-2"
}
resource "aws_spot_instance_request" "MySpotInstance" {
# Spot Request Settings
wait_for_fulfillment = "true"
spot_type = "persistent"
instance_interruption_behaviour = "stop"
# Instance Settings
ami = "ami-0520e698dd500b1d1"
instance_type = "c4.large"
associate_public_ip_address = "1"
root_block_device {
volume_size = "10"
volume_type = "standard"
}
ebs_block_device {
device_name = "/dev/sdb"
volume_size = "50"
volume_type = "standard"
delete_on_termination = "true"
}
tags = {
Name = "MySpotInstance"
Application = "MyApp"
Environment = "TEST"
}
}

How do I launch an EC2 instance into an existing VPC using Terraform?

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

Resources