1
votes

I am trying to install packages after provisioning an ec2 instance with terraform, but I am unable to gain access via ssh. Here is my config below if anyone can spot what I am doing wrong. I have tried many ways of doing this but I have been unsuccessful in all my attempts. however, I got it to provision the ec2 instance set up all the networking stuff, security group, and load balancer. What I am attempting to do is to create 2 ec2 instances and install Nginx on both of them then, load-balance them both with elb.

    provider "aws" {
      region = "${var.aws_region}"
    }
    
    # OS image
    data "aws_ami" "ubuntu-18_04" {
      most_recent = true
      owners = ["${var.ubuntu_account_number}"]
    
      filter {
        name   = "name"
        values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
      }
    }
    
    # Create a VPC to launch our instances into
    resource "aws_vpc" "default" {
      cidr_block = "10.0.0.0/16"
    }
    
    # Create an internet gateway to give our subnet access to the outside world
    resource "aws_internet_gateway" "default" {
      vpc_id = "${aws_vpc.default.id}"
    }
    
    # Grant the VPC internet access on its main route table
    resource "aws_route" "internet_access" {
      route_table_id         = "${aws_vpc.default.main_route_table_id}"
      destination_cidr_block = "0.0.0.0/0"
      gateway_id             = "${aws_internet_gateway.default.id}"
    }
    
    # Create a subnet to launch our instances into
    resource "aws_subnet" "default" {
      vpc_id                  = "${aws_vpc.default.id}"
      cidr_block              = "10.0.1.0/24"
      map_public_ip_on_launch = true
    }
    
    # A security group for the ELB so it is accessible via the web
    resource "aws_security_group" "elb" {
      name        = "my_elb"
      description = "Used in the terraform"
      vpc_id      = "${aws_vpc.default.id}"
    
      # HTTP access from anywhere
      ingress {
        from_port   = 80
        to_port     = 80
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    
      # outbound internet access
      egress {
        from_port   = 0
        to_port     = 0
        protocol    = "-1"
        cidr_blocks = ["0.0.0.0/0"]
      }
    }
    
    # Our default security group to access
    # the instances over SSH and HTTP
    resource "aws_security_group" "default" {
      name        = "my_test"
      description = "Used in the terraform"
      vpc_id      = "${aws_vpc.default.id}"
    
      # SSH access from anywhere
      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/16"]
      }
    
      egress {
        from_port   = 0
        to_port     = 0
        protocol    = "-1"
        cidr_blocks = ["0.0.0.0/0"]
      }
    }
    
    resource "aws_elb" "web" {
      name = "terraform-example-elb"
      subnets         = ["${aws_subnet.default.id}"]
      security_groups = ["${aws_security_group.elb.id}"]
      instances       = ["${aws_instance.web.id}"]
    
      listener {
        instance_port     = 80
        instance_protocol = "http"
        lb_port           = 80
        lb_protocol       = "http"
      }
    }
    
    resource "aws_instance" "web" {
      connection {
        # The default username for our AMI
        user = "ubuntu"
        host = "${self.public_ip}"
        type     = "ssh"
        private_key = "${file("/Users/me/Downloads/my-test-key.pem")}"
      }
    
      instance_type = "t2.nano"
      ami = data.aws_ami.ubuntu-18_04.id
      vpc_security_group_ids = [aws_security_group.default.id,]
      subnet_id = aws_subnet.default.id
      provisioner "remote-exec" {
        inline = [
          "sudo apt-get -y update",
          "sudo apt-get -y install nginx",
          "sudo service nginx start",
        ]
      }
    }
1
You now need to provide a connection block for provisioners in Terraform: terraform.io/docs/provisioners/connection.htmlMatt Schuchard
... or instead of remote-exec you can use user_data to install all that: terraform.io/docs/providers/aws/r/instance.html#user_dataHelder Sepulveda

1 Answers

0
votes

Here is what you have on your instance:

    resource "aws_instance" "web" {
      connection {
        # The default username for our AMI
        user = "ubuntu"
        host = "${self.public_ip}"
        type     = "ssh"
        private_key = "${file("/Users/me/Downloads/my-test-key.pem")}"
      }
    
      instance_type = "t2.nano"
      ami = data.aws_ami.ubuntu-18_04.id
      vpc_security_group_ids = [aws_security_group.default.id,]
      subnet_id = aws_subnet.default.id

      provisioner "remote-exec" {
        inline = [
          "sudo apt-get -y update",
          "sudo apt-get -y install nginx",
          "sudo service nginx start",
        ]
      }
    }

Here how that should look like

    resource "aws_instance" "web" {    
      instance_type = "t2.nano"
      ami = data.aws_ami.ubuntu-18_04.id
      vpc_security_group_ids = [aws_security_group.default.id,]
      subnet_id = aws_subnet.default.id

      provisioner "remote-exec" {
        connection {
          # The default username for our AMI
          user = "ubuntu"
          host = "${self.public_ip}"
          type     = "ssh"
          private_key = "${file("/Users/me/Downloads/my-test-key.pem")}"
        }

        inline = [
          "sudo apt-get -y update",
          "sudo apt-get -y install nginx",
          "sudo service nginx start",
        ]
      }
    }

As you can see the connection is nested on the provisioner.
I have some examples here:
https://github.com/heldersepu/hs-scripts/blob/master/TerraForm/ec2_ubuntu.tf


Something else you can do is use user_data:
https://www.terraform.io/docs/providers/aws/r/instance.html#user_data

I have an example here:
https://github.com/heldersepu/hs-scripts/blob/master/TerraForm/ec2_ubuntu.tf#L8