I'm quite busy with trying to learn more about Terraform but I'm having one problem that I have no clue on how to work-around/fix.
The problem is as follows, in my script I am generating an ec2 instance (AWS) with a couple of side things like en EIP and a security group from a module, which is all working fine. But I cannot figure out how to attach the security group to the machine, now it's being created and that's it.
The code is as follows:
data "aws_ami" "latest" {
most_recent = true
owners = [ "self"]
filter {
name = "name"
values = [ lookup(var.default_ami, var.ami) ]
}
}
module "aws_security_group" {
source = "./modules/services/Security groups/"
server_port = 443
}
resource "aws_instance" "test-ec2deployment" {
ami = data.aws_ami.latest.id
instance_type = var.instance_type
subnet_id = var.subnet_id
availability_zone = var.availability_zone
associate_public_ip_address = var.public_ip
root_block_device {
volume_type = "gp2"
volume_size = 60
delete_on_termination = true
}
tags = {
Name = "Testserver2viaTerraform"
}
}
resource "aws_eip" "ip" {
instance = aws_instance.test-ec2deployment.id
}
resource "aws_eip" "example" {
vpc = true
}
Above is the main file and i'm loading the following module:
resource "aws_security_group" "my-webserver" {
name = "webserver"
description = "Allow HTTP from Anywhere"
vpc_id = "vpc-"
ingress {
from_port = 80
to_port = 80
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 = "my-webserver"
Site = "my-web-site"
}
}
The last step is attaching the security group to the machine but again, no clue on how to do that. I've been reading several docs and tried to google but I cannot seem to find the answer or the answer does not work for me. So hopefully you guys can help me further.
Thanks for your time, much appreciated!
In aws_security_group module you need to output security group id by add the following in ./modules/services/Security groups//main.tf
output "securitygroup_id" {
value = aws_security_group.my-webserver.id
}
then in your main tf file attach security group to your instance like this:
resource "aws_network_interface_sg_attachment" "sg_attachment" {
security_group_id = module.aws_security_group.securitygroup_id
network_interface_id = aws_instance.test-ec2deployment.primary_network_interface_id
}
Related
i'm new to terraform.
i try to make simple terraform code with aws.
it works well. i can see ec2 and security group, eip.
i want to access instance but i don't have .pem file.
so it make me hard to connect ec2.
how to get .pem file?
can anyone let me know please?
resource "aws_key_pair" "alone_ec2" {
key_name = "alone_ec2"
public_key = file("~/.ssh/id_rsa.pub")
}
resource "aws_security_group" "alone_web" {
name = "Alone EC2 Security Group"
description = "Alone EC2 Security Group"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["${chomp(data.http.myip.body)}/32"]
}
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
# EC2
resource "aws_instance" "web" {
ami = "ami-02de72c5dc79358c9"
instance_type = "t2.micro"
key_name = aws_key_pair.alone_ec2.key_name
vpc_security_group_ids = [
aws_security_group.alone_web.id
]
tags = {
Name = "example-webservice"
}
root_block_device {
volume_size = 30
}
}
# EIP
resource "aws_eip" "elasticip" {
instance = aws_instance.web.id
}
output "EIP" {
value = aws_eip.elasticip.public_ip
}
You can use "tls_private_key" to create the key pair, save it to your machine using a provisioner when uploading it to aws.
resource "tls_private_key" "this" {
algorithm = "RSA"
rsa_bits = 4096
}
resource "aws_key_pair" "this" {
key_name = "my-key"
public_key = tls_private_key.this.public_key_openssh
provisioner "local-exec" {
command = <<-EOT
echo "${tls_private_key.this.private_key_pem}" > my-key.pem
EOT
}
}
I have a slight issue. I have 3 subnet cidr blocks with 3 different az groups. I am passing a list of static Ip address for these instance to get assigned in order. My code however is throwing "ip address is out of range for the subnet" which makes sense because it's just going from ip 0 to the N instance how can i properly make sure the instance gets placed in the proper subnet. I hope my question makes sense and is clear please see the code below thank you all for the help! The code belows creates the instance
### Start of Radient FID Server ###
resource "aws_instance" "FID" {
depends_on = [aws_kms_key.aws-wm-wmad-prod]
disable_api_termination = false
count = var.How_many_FID
ami = var.windows_dc_ami_2016
availability_zone = element(var.availability_zones, count.index)
ebs_optimized = var.windows_dc_ebs_optimized
instance_type = var.windows_dc_instance_type_FID
key_name = var.Key_Pair_Ec2
monitoring = true
vpc_security_group_ids = [aws_security_group.Private01.id]
subnet_id = element(aws_subnet.private_subnet_cidr_blocks_Apps, count.index).id
private_ip = "${lookup(var.ips,count.index)}"
associate_public_ip_address = false
tags = merge(
{
Name = element(var.Radiant_FID_Server_Tags, count.index)
Project = var.project,
Environment = var.environment
},
var.tags
)
I have a variables file which i'm passing the private Ip addresses:
variable "ips" {
default = {
"0" = "10.7.90.79"
"1" = "10.7.90.80"
"2" = "10.7.90.81"
"3" = "10.7.90.82"
"4" = "10.7.90.90"
"5" = "10.7.90.84"
"6" = "10.7.90.85"
"7" = "10.7.90.86"
"8" = "10.7.90.87"
"9" = "10.7.90.88"
}
}
##how i create my subnets
resource "aws_subnet" "private_subnet_cidr_blocks_AD" {
count = length(var.private_subnet_cidr_blocks_AD) # count = 3
vpc_id = aws_vpc.default.id #id34odfjdf
cidr_block = var.private_subnet_cidr_blocks_AD[count.index]
availability_zone = var.availability_zones[count.index]
tags = merge(
{
Name = element(var.private_subnet_cidr_blocks_AD_NameTag, count.index),
Project = var.project,
Environment = var.environment
},
var.tags
)
}
So let's say you have the following CIDR block list defined:
private_subnet_cidr_blocks_AD = ["10.7.90.64/27", "10.7.90.96/27","10.7.90.160/27"]
Then you could define your IP list like this:
variable "ips" {
default = [
{ subnet=0, ip="10.7.90.79" },
{ subnet=0, ip="10.7.90.80" },
{ subnet=0, ip="10.7.90.81" },
# etc...
{ subnet=1, ip="10.7.90.100" },
{ subnet=1, ip="10.7.90.101" },
# etc...
{ subnet=2, ip="10.7.90.170" },
{ subnet=2, ip="10.7.90.171" },
]
}
Each subnet number being the index in the private_subnet_cidr_blocks_AD list that corresponds to the CIDR block that the IP belongs to.
Then your instance definition could look like this:
resource "aws_instance" "FID" {
for_each = toset( var.ips )
subnet_id = aws_subnet.private_subnet_cidr_blocks_Apps[each.value.subnet].id
private_ip = each.value.ip
I am trying to create a simple infrastructure which includes EC2, VPC and internet connectivity with Internet Gateway, but while the infrastructure is being created through terraform apply the terminal output gets stuck in creating mode for approximately 5-6 minutes for route table association using subnet id and then finally throws error that vpc-id, routetableid, subnet id does not exist and not found.
Sharing some specific code below :
resource "aws_route_table" "dev-public-crt" {
vpc_id = "aws_vpc.main-vpc.id"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "aws_internet_gateway.dev-igw.id"
}
tags = {
Name = "dev-public-crt"
}
}
resource "aws_route_table_association" "dev-crta-public-subnet-1"{
subnet_id = "aws_subnet.dev-subnet-public-1.id"
route_table_id = "aws_route_table.dev-public-crt.id"
}
resource "aws_vpc" "dev-vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "dev-vpc"
}
}
resource "aws_subnet" "dev-subnet-public-1" {
vpc_id = "aws_vpc.dev-vpc.id"
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = "true"
tags = {
Name = "dev-subnet-public-1"
}
}
You need to remove the " around all the reference values you have there: vpc_id = "aws_vpc.main-vpc.id" should be vpc_id = aws_vpc.main-vpc.id, etc. Otherwise you try to create a aws_route_table in the vpc with the literal id "aws_vpc.main-vpc.id".
Whenever you want to reference variables or resources or data sources either do not wrap in " at all, or interpolate using "something ${aws_vpc.main-vpc.id} ..."
The result should probably look like:
resource "aws_route_table" "dev-public-crt" {
vpc_id = aws_vpc.main-vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.dev-igw.id
}
tags = {
Name = "dev-public-crt"
}
}
resource "aws_route_table_association" "dev-crta-public-subnet-1"{
subnet_id = aws_subnet.dev-subnet-public-1.id
route_table_id = aws_route_table.dev-public-crt.id
}
resource "aws_vpc" "dev-vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "dev-vpc"
}
}
resource "aws_subnet" "dev-subnet-public-1" {
vpc_id = aws_vpc.dev-vpc.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = "true"
tags = {
Name = "dev-subnet-public-1"
}
}
No guarantee that this works because now there could be invalid references, but those need to cleaned up by you
I want to create windows azure VM, copy some file and run some simple command on that VM using terraform script.
Problem is : I am able to create VM but not able to connect via winrm.
provider "azurerm" {
subscription_id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
tenant_id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
resource "azurerm_virtual_network" "vnet" {
name = "cmTFVnet"
address_space = ["10.0.0.0/16"]
location = "South India"
resource_group_name = "cservice"
}
resource "azurerm_subnet" "subnet" {
name = "cmTFSubnet"
resource_group_name = "cservice"
virtual_network_name = "${azurerm_virtual_network.vnet.name}"
address_prefix = "10.0.2.0/24"
}
resource "azurerm_public_ip" "publicip" {
name = "cmTFPublicIP"
location = "South India"
resource_group_name = "cservice"
public_ip_address_allocation = "dynamic"
}
resource "azurerm_network_security_group" "nsg" {
name = "cmTFNSG"
location = "South India"
resource_group_name = "cservice"
security_rule {
name = "SSH"
priority = 340
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
security_rule {
name = "winrm"
priority = 1010
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "5985"
source_address_prefix = "*"
destination_address_prefix = "*"
}
security_rule {
name = "winrm-out"
priority = 100
direction = "Outbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "5985"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_network_interface" "nic" {
name = "cmNIC"
location = "South India"
resource_group_name = "cservice"
network_security_group_id = "${azurerm_network_security_group.nsg.id}"
ip_configuration {
name = "compilerNICConfg"
subnet_id = "${azurerm_subnet.subnet.id}"
private_ip_address_allocation = "dynamic"
public_ip_address_id = "${azurerm_public_ip.publicip.id}"
}
}
resource "azurerm_virtual_machine" "vm" {
name = "cmTFVM"
location = "South India"
resource_group_name = "cservice"
network_interface_ids = ["${azurerm_network_interface.nic.id}"]
vm_size = "Standard_D2s_v3"
storage_image_reference
{
id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
storage_os_disk {
name = "cmOsDisk"
managed_disk_type = "Premium_LRS"
create_option = "FromImage"
}
os_profile {
computer_name = "hostname"
admin_username = "test"
admin_password = "test#123"
}
os_profile_windows_config {
enable_automatic_upgrades = "true"
provision_vm_agent ="true"
winrm = {
protocol = "http"
}
}
provisioner "remote-exec" {
connection = {
type = "winrm"
user = "test"
password = "test#123"
agent = "false"
https = false
insecure = true
}
inline = [
"cd..",
"cd..",
"cd docker",
"mkdir test"
]
}
}
VM is created successfully but not able to connect by WINRM
but I am getting following error in "remote-exec":
azurerm_virtual_machine.vm: timeout - last error: unknown error Post
http://:5985/wsman: dial tcp :5985: connectex: A connection attempt
failed because the connected party did not properly respond after a
period of time, or established connection failed because connected
host has failed to respond.
or http response error: 401 - invalid content type
When you create the Windows Azure VM, the WINRM is not configured by default. So if you want to connect the VM through the WINRM, you should configure the WINRM after the VM creation time, or in the creation time.
You can follow the steps in Configure WinRM after virtual machine creation. And you can also configure it in the creation time. There is an example shows that through Azure template. It will also provide a little help. See Deploys a Windows VM and Configures a WinRM Https listener.
Trying to attach a shared volume to my auto-scaling group. Not sure how to get that done in terraform, or even if that is possible?
The aws_volume_attachment takes on one instance id, but I am expecting to put this in launch config somehow. Can someone please help.
resource "aws_ebs_volume" "shared_volume" {
availability_zone = "us-east-1"
size = 2
}
resource "aws_volume_attachment" "volume_attachment" {
device_name = "/dev/xvdb"
instance_id = "????"
volume_id = "${aws_ebs_volume.shared_volume.id}"
skip_destroy = true
}
resource "aws_launch_configuration" "flume-conf" {
image_id = "${var.app_ami_id}"
instance_type = "${var.app_instance_type}"
key_name = "${var.ssh_key_name}"
security_groups = ["${var.app_security_group_id}"]
user_data = "${data.template_file.config.rendered}"
iam_instance_profile = "${var.app_iam_role}"
root_block_device {
volume_size = 50
volume_type = "gp2"
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_autoscaling_group" "ec2_asg" {
name = "${format("%s", var.app_name)}"
launch_configuration = "${aws_launch_configuration.flume-conf.name}"
min_size = "${var.asg_min_size}"
max_size = "${var.asg_max_size}"
vpc_zone_identifier = ["${element(data.aws_subnet_ids.private.ids, 0)}", "${element(data.aws_subnet_ids.private.ids, 1)}"]
availability_zones = "${var.availability_zones}"
depends_on = []
lifecycle {
create_before_destroy = false
}
}
EBS Volumes cannot be mounted to multiple hosts. If you are looking for this functionality, consider EFS.