Terraform - I can not create EC2 instance using SG module - amazon-web-services

Could u please let me know why I'm not able to create a EC2 using a SG module that I built?
I'm getting the following error
Error: creating EC2 Instance: VPCIdNotSpecified: No default VPC for this user. GroupName is only supported for EC2-Classic and default VPC.
│ status code: 400, request id: e91aa79f-0d8f-44ec-84df-ba22cd3307d8
Indeed I don't wanna use a default VPC, follow below my main code:
module "vpc" {
source = "../modules/vpc/"
region = var.region
awsprofile = var.awsprofile
vpcname = var.vpcname
subnetaz1 = var.subnetaz1
subnetaz2 = var.subnetaz2
subnetaz3 = var.subnetaz3
private1_cidr = var.private1_cidr
private2_cidr = var.private2_cidr
private3_cidr = var.private3_cidr
public1_cidr = var.public1_cidr
public2_cidr = var.public2_cidr
public3_cidr = var.public3_cidr
vpc_cidr = var.vpc_cidr
}
module "security" {
source = "../modules/security/"
public_sg_name = var.public_sg_name
ingress_ports = var.ingress_ports
internet_access = var.internet_access
vpc_id = module.vpc.aws_vpc_id
}
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
resource "aws_instance" "web" {
count = var.instance_count
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_size
associate_public_ip_address = "true"
key_name = var.key_name
security_groups = [module.security.sg_name]
tags = {
Name = "${var.instance_name}-1"
}
}
In the "security_groups" I'm trying to get the output from security group module however unsucessfully.
output "sg_id" {
value = aws_security_group.PublicSG.id
}
output "sg_name" {
value = aws_security_group.PublicSG.name
}
Does anyone has any idea why it is not working?

Instead of security_groups you should be using vpc_security_group_ids:
resource "aws_instance" "web" {
count = var.instance_count
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_size
associate_public_ip_address = "true"
key_name = var.key_name
vpc_security_group_ids = [module.security.sg_id]
tags = {
Name = "${var.instance_name}-1"
}
}

Related

Creating multiple ec2 aws instances and attaching multiple networking interfaces with specific IP using (count, for_each) Terraform

I am unable to implement the creation of multiple instances with a attached multiple network interface. I have a code where three instances are created and 3 network interfaces are attached. I would like to do this using count, for_each. I could no5 find implemented methods on the Internet. I ask you to help me how to implement the code using count
resource "aws_network_interface" "private_elasticsearch" {
subnet_id = aws_subnet.private_subnets.id
private_ips = ["10.245.10.6"]
security_groups = [aws_security_group.elastic_traffic.id,
aws_security_group.general.id]
tags = {
Environment = "Test"
Project = "test"
Name = "elasticsearch-interface"
}
}
resource "aws_network_interface" "private_elasticsearch2" {
subnet_id = aws_subnet.private_subnets.id
private_ips = ["10.245.10.7"]
security_groups = [aws_security_group.elastic_traffic.id, aws_security_group.general.id]
tags = {
Environment = "Test"
Project = "test"
Name = "elasticsearch-interface2"
}
}
resource "aws_network_interface" "private_elasticsearch3" {
subnet_id = aws_subnet.private_subnets.id
private_ips = ["10.245.10.8"]
security_groups = [aws_security_group.elastic_traffic.id, aws_security_group.general.id]
tags = {
Environment = "Test"
Project = "test"
Name = "elasticsearch-interface3"
}
}
resource "aws_instance" "dev-elasticsearch" {
ami = "ami-08bdc08970fcbd34a"
availability_zone = "eu-north-1a"
instance_type = "t3.micro"
network_interface {
device_index=0
network_interface_id = aws_network_interface.private_elasticsearch.id
}
tags = {
Environment = "Test"
Project = "test"
Name = "elasticsearch-instance-dev"
}
}
resource "aws_instance" "dev-elasticsearch-2" {
ami = "ami-08bdc08970fcbd34a"
availability_zone = "eu-north-1a"
instance_type = "t3.micro"
network_interface {
device_index=0
network_interface_id = aws_network_interface.private_elasticsearch2.id
}
tags = {
Environment = "Test"
Project = "test"
Name = "elasticsearch-instance-dev-2"
}
}
resource "aws_instance" "dev-elasticsearch-3" {
ami = "ami-08bdc08970fcbd34a"
availability_zone = "eu-north-1a"
instance_type = "t3.micro"
network_interface {
device_index=0
network_interface_id = aws_network_interface.private_elasticsearch3.id
}
tags = {
Environment = "Test"
Project = "test"
Name = "elasticsearch-instance-dev-3"
}
You can do it with count (for_each also possible):
locals {
ips = ["10.245.10.6", "10.245.10.7", "10.245.10.8"]
}
resource "aws_network_interface" "private_elasticsearch" {
count = length(local.ips)
subnet_id = aws_subnet.private_subnets.id
private_ips = [local.ips[count.index]]
security_groups = [aws_security_group.elastic_traffic.id,
aws_security_group.general.id]
tags = {
Environment = "Test"
Project = "test"
Name = "elasticsearch-interface${count.index}"
}
}
resource "aws_instance" "dev-elasticsearch" {
count = length(local.ips)
ami = "ami-08bdc08970fcbd34a"
availability_zone = "eu-north-1a"
instance_type = "t3.micro"
network_interface {
device_index=0
network_interface_id = aws_network_interface.private_elasticsearch[count.index].id
}
tags = {
Environment = "Test"
Project = "test"
Name = "elasticsearch-instance-dev${count.index}"
}
}

EC2 instance creation

I'm trying to create multiple EC2 instance but they have different AMIs, instance types and should be in different availability zones as shown below. I've tried a few different ways but can't make it work.
locals {
az_ami = [
{Name = "host1", type = "t3a.medium", az = "eu_west_2a", ami_id = "ami-01234abc"},
{Name = "host2", type = "t3a.micro", az = "eu_west_2b", ami_id = "ami-01234def"},
{Name = "host3", type = "t3a.medium", az = "eu_west_2b", ami_id = "ami-01234gef"},
{Name = "host4", type = "t3a.medium", az = "eu_west_2a", ami_id = "ami-01234hty"}
]
}
#variable "ami_id" {}
resource "aws_instance" "myinstance" {
count = length(local.az_ami)
for_each = [{ for i in local.az_ami: }]
dynamic "ec2_instance"{
for_each = local.az_ami[count.index]
content {
instance_type = "ec2_instance.value.Name"
availability_zone = "ec2_instance.value.az"
ami = "ec2_instance.value.ami_id"
}
}
}
If you want to use count, then it should be:
resource "aws_instance" "myinstance" {
count = length(local.az_ami)
instance_type = local.az_ami[count.index].type
availability_zone = local.az_ami[count.index].az
ami = local.az_ami[count.index].ami_id
tags = {
Name = local.az_ami[count.index].Name
}
}
But with for_each it could be:
resource "aws_instance" "myinstance2" {
for_each = {for idx, val in local.az_ami: idx => val}
instance_type = each.value.type
availability_zone = each.value.az
ami = each.value.ami_id
tags = {
Name = each.value.Name
}
}

Terraform 0.12.13 - Not able to spin AWS instance

AWS EC2 instance creation is failing while creating a network interface in the aws_instance section. The configuration is following configuration as defined in Terraform Network Interfaces
Configuration.
On removing the network block the configuration works seamlessly. With network block the following error was logged
"Error: Error launching source instance: Unsupported: The requested configuration is currently not supported. Please check the documentation for supported configurations."
variable "aws_region" {}
variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "vpc_cidr_block" {}
variable "environment" {}
variable "applicationtype" {}
variable "subnet_cidr_block" {}
variable "amiid" {}
variable "instancetype" {}
variable "bucketname" {}
variable "publickey-fe" {}
variable "publickey-be" {}
provider "aws" {
profile = "default"
region = "${var.aws_region}"
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
}
data "aws_availability_zones" "availability" {
state = "available"
}
resource "aws_vpc" "sitespeed_vpc" {
cidr_block = "${var.vpc_cidr_block}"
instance_tenancy = "dedicated"
tags = {
env = "${var.environment}"
application = "${var.applicationtype}"
Name = "site-speed-VPC"
}
}
resource "aws_subnet" "sitespeed_subnet" {
vpc_id = "${aws_vpc.sitespeed_vpc.id}"
cidr_block = "${var.subnet_cidr_block}"
availability_zone = "${data.aws_availability_zones.availability.names[0]}"
tags = {
env = "${var.environment}"
application = "${var.applicationtype}"
Name = "site-speed-Subnet"
}
}
resource "aws_network_interface" "sitespeed_frontend_NIC" {
subnet_id = "${aws_subnet.sitespeed_subnet.id}"
private_ips = ["192.168.10.100"]
tags = {
env = "${var.environment}"
application = "${var.applicationtype}"
Name = "site-speed-frontend-nic"
}
}
resource "aws_network_interface" "sitespeed_backend_NIC" {
subnet_id = "${aws_subnet.sitespeed_subnet.id}"
private_ips = ["192.168.10.110"]
tags = {
env = "${var.environment}"
application = "${var.applicationtype}"
Name = "site-speed-backend-nic"
}
}
resource "aws_key_pair" "sitespeed_front_key" {
key_name = "site_speed_front_key"
public_key = "${var.publickey-fe}"
}
resource "aws_key_pair" "sitespeed_back_key" {
key_name = "site_speed_back_key"
public_key = "${var.publickey-be}"
}
resource "aws_instance" "sitespeed_front" {
ami = "ami-00942d7cd4f3ca5c0"
instance_type = "t2.micro"
key_name = "site_speed_front_key"
availability_zone = "${data.aws_availability_zones.availability.names[0]}"
network_interface {
network_interface_id = "${aws_network_interface.sitespeed_frontend_NIC.id}"
device_index = 0
}
tags = {
env = "${var.environment}"
application = "${var.applicationtype}"
Name = "site-speed-frontend-server"
public = "yes"
}
}
resource "aws_instance" "sitespeed_backend" {
ami = "ami-00942d7cd4f3ca5c0"
instance_type = "t2.micro"
key_name = "site_speed_back_key"
network_interface {
network_interface_id = "${aws_network_interface.sitespeed_backend_NIC.id}"
device_index = 0
}
tags = {
env = "${var.environment}"
application = "${var.applicationtype}"
Name = "site-speed-backend-server"
public = "No"
}
}
resource "aws_s3_bucket" "b" {
bucket = "${var.bucketname}"
acl = "private"
tags = {
env = "${var.environment}"
application = "${var.applicationtype}"
}
}
The issue was due to the Terraform Version. Following is the updated script that supports Terraform V.0.12.16 to create an EC2 Instance on AWS.
// Variable Definition
variable "aws_region" {}
variable "aws_vpc_cidr_block" {}
variable "aws_subnet_cidr_block" {}
variable "aws_private_ip_fe" {}
variable "aws_Name" {}
variable "aws_Application" {}
variable "aws_ami" {}
variable "aws_instance_type" {}
// Provider Definition
provider "aws" {
version = "~> 2.40"
region = var.aws_region
}
// Adds a VPC
resource "aws_vpc" "aws_ec2_deployment_test-vpc" {
cidr_block = var.aws_vpc_cidr_block
tags = {
Name = join("-", [var.aws_Name, "vpc"])
Application = var.aws_Application
}
}
//Adds a subnet
resource "aws_subnet" "aws_ec2_deployment_test-subnet" {
vpc_id = aws_vpc.aws_ec2_deployment_test-vpc.id
cidr_block = var.aws_subnet_cidr_block
availability_zone = join("", [var.aws_region, "a"])
tags = {
Name = join("-", [var.aws_Name, "subnet"])
Application = var.aws_Application
}
}
//Adds a Network Interface
resource "aws_network_interface" "aws_ec2_deployment_test-fe" {
subnet_id = aws_subnet.aws_ec2_deployment_test-subnet.id
private_ips = [ var.aws_private_ip_fe ]
tags = {
Name = join("-", [var.aws_Name, "network-interface-fe"])
Application = var.aws_Application
}
}
//Adds an EC2 Instance
resource "aws_instance" "aws_ec2_deployment_test-fe"{
ami = var.aws_ami
instance_type = var.aws_instance_type
network_interface {
network_interface_id = aws_network_interface.aws_ec2_deployment_test-fe.id
device_index = 0
}
tags = {
Name = join("-", [var.aws_Name, "fe-ec2"])
Application = var.aws_Application
}
}
// Print Output Values
output "aws_ec2_deployment_test-vpc" {
description = "CIDR Block for the VPC: "
value = aws_vpc.aws_ec2_deployment_test-vpc.cidr_block
}
output "aws_ec2_deployment_test-subnet" {
description = "Subnet Block: "
value = aws_subnet.aws_ec2_deployment_test-subnet.cidr_block
}
output "aws_ec2_deployment_test-private-ip" {
description = "System Private IP: "
value = aws_network_interface.aws_ec2_deployment_test-fe.private_ip
}
output "aws_ec2_deployment_test-EC2-Details" {
description = "EC2 Details: "
value = aws_instance.aws_ec2_deployment_test-fe.public_ip
}
Gist link to the solution

Terraform aws_spot_fleet_request iam_instance_profile

I read the Terraform spot fleet example usages from here.
What is the significance of "iam_instance_profile_arn" and what does it do in Example 1?
I'm getting the error "launch_specification.0: invalid or unknown key: tags" in some cases, while not in others so I thought maybe it is related to the iam_profile.
iam_instance_profile_arn = "${aws_iam_instance_profile.example.arn}"
Example 1:
# Request a Spot fleet
resource "aws_spot_fleet_request" "cheap_compute" {
iam_fleet_role = "arn:aws:iam::12345678:role/spot-fleet"
spot_price = "0.03"
allocation_strategy = "diversified"
target_capacity = 6
valid_until = "2019-11-04T20:44:20Z"
launch_specification {
instance_type = "m4.10xlarge"
ami = "ami-1234"
spot_price = "2.793"
placement_tenancy = "dedicated"
iam_instance_profile_arn = "${aws_iam_instance_profile.example.arn}"
}
launch_specification {
instance_type = "m4.4xlarge"
ami = "ami-5678"
key_name = "my-key"
spot_price = "1.117"
iam_instance_profile_arn = "${aws_iam_instance_profile.example.arn}"
availability_zone = "us-west-1a"
subnet_id = "subnet-1234"
weighted_capacity = 35
root_block_device {
volume_size = "300"
volume_type = "gp2"
}
tags {
Name = "spot-fleet-example"
}
}
}
Example 2:
resource "aws_spot_fleet_request" "foo" {
iam_fleet_role = "arn:aws:iam::12345678:role/spot-fleet"
spot_price = "0.005"
target_capacity = 2
valid_until = "2019-11-04T20:44:20Z"
launch_specification {
instance_type = "m1.small"
ami = "ami-d06a90b0"
key_name = "my-key"
availability_zone = "us-west-2a"
}
launch_specification {
instance_type = "m3.large"
ami = "ami-d06a90b0"
key_name = "my-key"
availability_zone = "us-west-2a"
}
depends_on = ["aws_iam_policy_attachment.test-attach"]
}
The instance profile is unrelated to the error. The error is saying this:
tags {
Name = "spot-fleet-example"
}
Part of the first example isnt recognized. You can read about what instance profiles are here:
An instance profile is a container for an IAM role that you can use to
pass role information to an EC2 instance when the instance starts.

How to correctly use Count and pick multiple az subnets in Terraform

I am trying to implement a module where i am trying to spin a number of instance in already created subnets (by terraform) , but i am not sure how to actually use count in modules and also how to pick values from s3 bucket datasource to spin instance in multi-az , here is what my resource in module dir looks like
resource "aws_instance" "ec2-instances" {
count = "${var.count_num }"
ami = "${data.aws_ami.ubuntu.id}"
instance_type = "${var.machine_type}"
key_name = "${var.key_name}"
#vpc_security_group_ids = ["${aws_security_group.jumpbox-sec-group.id}"]
vpc_security_group_ids = ["${var.sec-group}"]
disable_api_termination = "${var.is_production ? true : false}"
subnet_id = "${element(var.es_stg_subnets, count.index)}" <--- This won't work , i need to use data-source as s3
tags {
#Name = "${var.master_name}-${count.index+1}"
Name = "${var.instance-tag}-${count.index+1}"
Type = "${var.instance-type-tag}"
}
root_block_device {
volume_size = "${var.instance-vol-size}"
volume_type = "gp2"
}
}
And here is the actual module :
module "grafana-stg" {
source = "../../modules/services/gen-ec2"
#ami_id = "${data.aws_ami.ubuntu.id}"
instance_type = "${var.grafana_machine_type}"
key_name = "jumpbox"
vpc_security_group_ids = ["${aws_security_group.grafana-sec-group.id}"]
#subnets = "${data.terraform_remote_state.s3_bucket_state.subnet-public-prod-1a}"
subnet_id = ??????????????????
disable_api_termination = "${var.is_production ? true : false}"
}
I would look at retrieving your subnets utilising a data source.
Utilising Data Sources
Terraform has the concept of data sources. You can pull information from AWS that you require for resources. In your gen-ec2.tf file -
// In order to get subnets, you need the VPC they belong to.
// Note you can filter on a variety of different tags.
data "aws_vpc" "selected" {
tags {
Name = "NameOfVPC"
}
}
// This will then retrieve all subnet ids based on filter
data "aws_subnet_ids" "private" {
vpc_id = "${data.aws_vpc.selected.id}"
tags {
Tier = "private*"
}
}
resource "aws_instance" "ec2-instances" {
count = "${length(data.aws_subnet_ids.private.ids)}"
ami = "${data.aws_ami.ubuntu.id}"
instance_type = "${var.machine_type}"
key_name = "${var.key_name}"
vpc_security_group_ids = ["${var.sec-group}"]
disable_api_termination = "${var.is_production ? true : false}"
subnet_id = "${element(data.aws_subnet_ids.private.*.ids, count.index)}"
tags {
Name = "${var.instance-tag}-${count.index+1}"
Type = "${var.instance-type-tag}"
}
root_block_device {
volume_size = "${var.instance-vol-size}"
volume_type = "gp2"
}
}
Your module now looks like so -
module "grafana-stg" {
source = "../../modules/services/gen-ec2"
#ami_id = "${data.aws_ami.ubuntu.id}"
instance_type = "${var.grafana_machine_type}"
key_name = "jumpbox"
vpc_security_group_ids = ["${aws_security_group.grafana-sec-group.id}"]
disable_api_termination = "${var.is_production ? true : false}"
}
For me as I am using Terraform v0.12.5, the bellow snippet worked fine
data "aws_subnet_ids" "public_subnet_list" {
vpc_id = "${var.vpc_id}"
tags = {
Tier = "Public"
}
}
resource "aws_instance" "example" {
count = 2
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = tolist(data.aws_subnet_ids.public_subnet_list.ids)[count.index]
}