Whenever I add key_name to my amazon resource, I can never actually connect to the resulting instance:
provider "aws" {
"region" = "us-east-1"
"access_key" = "**"
"secret_key" = "****"
}
resource "aws_instance" "api_server" {
ami = "ami-013f1e6b"
instance_type = "t2.micro"
"key_name" = "po"
tags {
Name = "API_Server"
}
}
output "API IP" {
value = "${aws_instance.api_server.public_ip}"
}
When I do
ssh -i ~/Downloads/po.pem bitnami#IP
I just a blank line in my terminal, as if I was putting in a wrong IP. However, checking the Amazon console, I can see the instance is running. I'm not getting any errors on my Terraform either.
By default all network access is not allowed. You need to explicitly allow network access by setting a security group.
provider "aws" {
"region" = "us-east-1"
"access_key" = "**"
"secret_key" = "****"
}
resource "aws_instance" "api_server" {
ami = "ami-013f1e6b"
instance_type = "t2.micro"
key_name = "po"
security_groups = ["${aws_security_group.api_server.id}"]
tags {
Name = "API_Server"
}
}
resource "aws_security_group" "api_server" {
name = "api_server"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["XXX.XXX.XXX.XXX/32"] // Allow SSH from your global IP
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
output "API IP" {
value = "${aws_instance.api_server.public_ip}"
}
Related
I am trying to get the following Terraform script to run:-
provider "aws" {
region = "us-west-2"
}
provider "random" {}
resource "random_pet" "name" {}
resource "aws_instance" "web" {
ami = "ami-a0cfeed8"
instance_type = "t2.micro"
user_data = file("init-script.sh")
subnet_id = "subnet-0422e48590002d10d"
vpc_security_group_ids = [aws_security_group.web-sg.id]
tags = {
Name = random_pet.name.id
}
}
resource "aws_security_group" "web-sg" {
name = "${random_pet.name.id}-sg"
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"]
}
}
output "domain-name" {
value = aws_instance.web.public_dns
}
output "application-url" {
value = "${aws_instance.web.public_dns}/index.php"
}
However it errors with the following:-
Error: Error authorizing security group egress rules: InvalidGroup.NotFound: The security group 'sg-0c181b93d98173b0f' does not exist status code: 400, request id: 6cd8681b-ee70-4ec0-8509-6239c56169a1
The SG gets created with the correct name, but it claims it does not exist.
I am am unsure how to resolve this.
Typically I worked it out straight after posting. I had neglected to add the vpc_id property to the aws_security_group which meant it was an EC2 Classic SG which cannot have egress rules.
Is it possible to create an EC2 instance while reusing already existing VPC?
Running the following code yields Error launching source instance: VPCIdNotSpecified: No default VPC for this user. GroupName is only supported for EC2-Classic and default VPC. (status code: 400):
data "aws_security_groups" "my_tib_sg" {
tags = {
Name = "my-security-group"
}
}
resource "aws_instance" "nginx" {
ami = data.aws_ami.aws-linux.id
instance_type = "t2.micro"
key_name = var.key_name
vpc_security_group_ids = [data.aws_security_groups.my_tib_sg.id]
# more, irrelevant stuff...
}
FWIU from the error, the aws_instance block requires a reference to my VPC, which basically exists in my security group. Besides, I can't find a way to refer a VPC in an aws_instance block.
Updating code per answers:
I updated the code per answers below:
data "aws_security_groups" "my_tib_sg" {
tags = {
Name = "my-tib-sg"
}
}
data "aws_subnet" "my_subnet" {
tags = {
Name = "my-tib-subnet-1"
}
}
resource "aws_network_interface" "my_ani" {
subnet_id = data.aws_subnet.my_subnet.id
private_ips = ["10.0.0.10"]
tags = {
Name = "my-tib-ani"
by = "TF_TF"
}
}
resource "aws_instance" "nginx" {
ami = data.aws_ami.aws-linux.id
instance_type = "t2.micro"
key_name = var.key_name
vpc_security_group_ids = [data.aws_security_groups.my_tib_sg.id]
network_interface {
network_interface_id = aws_network_interface.my_ani.id
device_index = 0
}
connection {
type = "ssh"
host = self.public_ip
user = "ec2-user"
private_key = file(var.private_key_path)
}
provisioner "remote-exec" {
inline = [
"sudo yum install nginx -y",
"sudo service nginx start"
]
}
}
But the error changes to "network_interface": conflicts with vpc_security_group_ids.
(needless to mention: both my_subnet and my_tib_sg use same VPC)
I typically use the subnet_id parameter, directly on the aws_instance resource:
data "aws_security_groups" "my_tib_sg" {
tags = {
Name = "my-tib-sg"
}
}
data "aws_subnet" "my_subnet" {
tags = {
Name = "my-tib-subnet-1"
}
}
resource "aws_instance" "nginx" {
ami = data.aws_ami.aws-linux.id
instance_type = "t2.micro"
key_name = var.key_name
vpc_security_group_ids = [data.aws_security_groups.my_tib_sg.ids[0]]
# specify the subnet_id here
subnet_id = data.aws_subnet.my_subnet.id
# more, irrelevant stuff...
}
Yes, you can add a new EC2 instance to an existing VPC.
You should provide the subnet_id to aws_instance. You would typically pass that into Terraform as a parameter, rather than hard-coding its value into your template.
Note: the subnet ID implicitly indicates the actual VPC (because a subnet only exists in one VPC).
Is it possible to create an EC2 instance while reusing already existing VPC?
yes you can create an ec2 instance with an existing VPC. You can use a Data Source: aws_vpc to query existing VPC and then further reference the same in your resource like Resource: aws_instance below:
variable "vpc_id" {}
data "aws_vpc" "selected" {
id = var.vpc_id
}
resource "aws_subnet" "example" {
vpc_id = data.aws_vpc.selected.id
availability_zone = "us-west-2a"
cidr_block = cidrsubnet(data.aws_vpc.selected.cidr_block, 4, 1)
}
resource "aws_security_group" "allow_tls" {
name = "allow_tls"
description = "Allow TLS inbound traffic"
vpc_id = data.aws_vpc.selected.id
ingress {
description = "TLS from VPC"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [aws_vpc.main.cidr_block]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "allow_tls"
}
}
resource "aws_network_interface" "foo" {
subnet_id = aws_subnet.example.id
private_ips = ["172.16.10.100"]
security_groups = [aws_security_group.allow_tls.id]
tags = {
Name = "primary_network_interface"
}
}
resource "aws_instance" "foo" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
network_interface {
network_interface_id = aws_network_interface.foo.id
device_index = 0
}
credit_specification {
cpu_credits = "unlimited"
}
}
I'm running the below terraform code to deploy an ec2 instance inside a VPC to work as web server but for some reason I cant reach the website and cant shh to it, I have set the ingress and egress rules properly I believe:
########Provider########
provider "aws" {
region = "us-west-2"
access_key = "[redacted]"
secret_key = "[redacted]"
}
########VPC########
resource "aws_vpc" "vpc1" {
cidr_block = "10.1.0.0/16"
tags = {
Name = "Production"
}
}
########Internet GW########
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.vpc1.id
}
########Route table########
resource "aws_route_table" "rt" {
vpc_id = aws_vpc.vpc1.id
route {
cidr_block = "0.0.0.0/24"
gateway_id = aws_internet_gateway.gw.id
}
route {
ipv6_cidr_block = "::/0"
gateway_id = aws_internet_gateway.gw.id
}
}
########Sub Net########
resource "aws_subnet" "subnet1" {
vpc_id = aws_vpc.vpc1.id
cidr_block = "10.1.0.0/24"
availability_zone = "us-west-2a"
map_public_ip_on_launch = "true"
tags = {
Name = "prod-subnet-1"
}
}
########RT assosiation########
resource "aws_route_table_association" "a" {
subnet_id = aws_subnet.subnet1.id
route_table_id = aws_route_table.rt.id
}
########Security Group########
resource "aws_security_group" "sec1" {
name = "allow_web"
description = "Allow web inbound traffic"
vpc_id = aws_vpc.vpc1.id
ingress {
description = "HTTP from VPC"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.1.0.0/16"]
}
#SSH access from anywhere
ingress {
description = "SSH from VPC"
from_port = 22
to_port = 22
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 = "allow_web"
}
}
########Net Interface for the Instance########
#resource "aws_network_interface" "wsn" {
# subnet_id = aws_subnet.subnet1.id
# private_ips = ["10.0.1.50"]
# security_groups = [aws_security_group.sec1.id]
#}
########Load Balancer########
resource "aws_elb" "elb" {
name = "lb"
subnets = [aws_subnet.subnet1.id]
security_groups = [aws_security_group.sec1.id]
instances = [aws_instance.web1.id]
listener {
instance_port = 80
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
}
########EC2 Instance########
resource "aws_instance" "web1" {
ami = "ami-003634241a8fcdec0" #ubuntu 18.4
instance_type = "t2.micro"
availability_zone = "us-west-2a"
key_name = "main-key"
subnet_id = aws_subnet.subnet1.id
#network_interface {
# device_index = 0
# network_interface_id = aws_network_interface.wsn.id
#}
user_data = <<-EOF
#!/bin/bash
sudo apt update -y
sudo apt install apache2 -y
sudo systemctl start apache2
sudo bash -c 'echo Hello world!!! > /var/www/html/index.html'
EOF
tags = {
Name = "HelloWorld"
}
}
output "aws_elb_public_dns" {
value = aws_elb.elb.dns_name
}
The plan and the apply runs all fine but in the loadbalancer the instance is "outofservice"
what could be wrong here??
You are missing security group to your instance: vpc_security_group_ids.
Subsequently, you won't be able to ssh to it nor the http traffic will be allowed from the outside.
Also your route to IGW is incorrect. It should be:
cidr_block = "0.0.0.0/0"
Same for SG for your ELB to allow traffic from the internet. It should be:
cidr_blocks = ["0.0.0.0/0"]
I am trying to launch an EFS file system in my default VPC. I am able to create the EFS but not able to mount the target in all subnets. In subnet_id I not sure how to pass the value of all the subnet ids of default VPC. Below is my Terraform code:
$ cat ec2.tf
provider "aws" {
[enter image description here][1]region = "ap-south-1"
profile = "saumikhp"
}
data "aws_vpc" "default" {
default = true
}
data "aws_subnet_ids" "example" {
vpc_id = var.vpc_id
}
data "aws_subnet" "example" {
for_each = data.aws_subnet_ids.example.ids
id = each.value
}
resource "aws_key_pair" "key" {
key_name = "mykey12345"
public_key = file("mykey12345.pub")
}
resource "aws_security_group" "web-sg" {
name = "web-sg"
description = "Allow port 22 and 80"
vpc_id = "vpc-18819d70"
ingress {
from_port = 22
to_port = 22
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"]
}
ingress {
from_port = 2049
to_port = 2049
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "web-sg"
}
}
resource "aws_instance" "myinstance" {
ami = "ami-0447a12f28fddb066"
instance_type = "t2.micro"
key_name = "mykey12345"
security_groups = ["web-sg"]
connection {
type = "ssh"
user = "ec2-user"
private_key = file("mykey12345")
host = aws_instance.myinstance.public_ip
}
provisioner "remote-exec" {
inline = [
"sudo yum install httpd php git -y",
"sudo systemctl restart httpd",
"sudo systemctl enable httpd",
]
}
tags = {
Name = "SaumikOS"
}
}
resource "aws_efs_file_system" "efs" {
creation_token = "efs"
performance_mode = "generalPurpose"
throughput_mode = "bursting"
encrypted = "true"
tags = {
Name = "EfsExample"
}
}
resource "aws_efs_mount_target" "efs-mt" {
depends_on = [
aws_instance.myinstance,
]
for_each = data.aws_subnet_ids.example.ids
subnet_id = each.value
file_system_id = "aws_efs_file_system.efs.id"
security_groups = ["aws_security_group.web-sg.id"]
}
Error after running terraform apply
You can get the subnets from the default VPC by using a combination of the aws_vpc and aws_subnet_ids data sources.
data "aws_vpc" "default" {
default = true
}
data "aws_subnet_ids" "example" {
vpc_id = var.vpc_id
}
You can then create an EFS mount target in each of the subnets by looping over these (each mount target only takes a single subnet_id):
resource "aws_efs_mount_target" "efs-mt" {
for_each = data.aws_subnet_ids.example.ids
file_system_id = aws_efs_file_system.efs.id
subnet_id = each.value
security_groups = [aws_security_group.web-sg.id]
}
I have a below terraform script which works fine when use it on terminal.
provider "aws" {
region = "${var.aws_region}"
}
resource "aws_instance" "jenkins-poc" {
count = "2"
ami = "${var.aws_ami}"
instance_type = "${var.instance_type}"
key_name = "${var.key_name}"
availability_zone = "${var.aws_region}${element(split(",",var.zones),count.index)}"
vpc_security_group_ids = ["${aws_security_group.jenkins-poc.id}"]
subnet_id = "${element(split(",",var.subnet_id),count.index)}"
user_data = "${file("userdata.sh")}"
tags {
Name = "jenkins-poc${count.index + 1}"
Owner = "Shailesh"
}
}
resource "aws_security_group" "jenkins-poc" {
vpc_id = "${var.vpc_id}"
name = "${var.security_group_name}"
description = "Allow http,httpd and SSH"
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
egress {
from_port = "0"
to_port = "0"
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_elb" "jenkins-poc-elb" {
name = "jenkins-poc-elb"
subnets = ["subnet-","subnet-"]
listener {
instance_port = 80
instance_protocol = "http"
lb_port = "80"
lb_protocol = "http"
}
health_check {
healthy_threshold = "2"
unhealthy_threshold = "3"
timeout = "3"
target = "tcp:80"
interval = 30
}
instances = ["${aws_instance.jenkins-poc.*.id}"]
}
and variables file is as given below.
variable "aws_ami" {
default = "ami-"
}
variable "zones"{
default = "a,b"
}
variable "aws_region" {
default = "us-east-1"
}
variable "key_name" {
default = "test-key"
}
variable "instance_type" {
default = "t2.micro"
}
variable "count" {
default = "2"
}
variable "security_group_name" {
default = "jenkins-poc"
}
variable "vpc_id" {
default = "vpc-"
}
variable "subnet_id" {
default = "subnet-,subnet"
}
Everything works fine when I run through terminal using terraform apply. But same code gives me below error when I run it through jenkins.
aws_security_group.jenkins-poc: Error creating Security Group: UnauthorizedOperation: You are not authorized to perform this operation
Note :: This is a non-default vpc in which I am performing this operation.
I would highly appreciate any comments. I didn't mention sensitive values.
Just make sure if you are in the right aws profile and the default aws profile could restrict you from creating the instance
provider "aws" {
region = "${var.aws_region}"
shared_credentials_file = "~/.aws/credentials"
profile = "xxxxxxx"
}