Skip to content

Latest commit

 

History

History
267 lines (206 loc) · 7.46 KB

LAB07-Provisioners-Null-Resources.md

File metadata and controls

267 lines (206 loc) · 7.46 KB

LAB-07: Provisioners (file, remote-exec), Null Resources (local-exec) => Provision Key-Pair, SSH Connection

This scenario shows:

  • how to create file, run command using "remote-exec" provisioners on remote instance,
  • how to create file using provisioner "file" on remote instance,
  • how to create file, run command using "local-exec" on local pc,
  • how to create key-pairs for SSH connection.

Code: https://github.com/omerbsezer/Fast-Terraform/blob/main/labs/provisioners-nullresources/main.tf

Prerequisite

Steps

  • SSH key-pairs (public and private key) are used to connect remote server. Public key (xx.pub) is on the remote server, with private key, user can connect using SSH.

  • There are 2 ways of creating key-pairs (public and private key):

    • Creating them on cloud (AWS)
      • EC2 > Key-pairs > Create Key-Pair
    • Creating them on on-premise
      • "ssh-keygen -t rsa -b 2048"
  • Creating key-pairs on AWS: Go to EC2 > Key-pairs

image

  • After creating key-pairs, public key is listed on AWS:

image

  • Private key (testkey.pem) is downloaded on your PC:

image

  • Copy this testkey.pem into your directory on which main.tf exists.

image

  • With provisioner "file", on the remote instance, new file can be created
  • With provisioner "remote-exec", on the remote instance, any command can be run
  • With provisioner "local-exec", on the local PC, any command can be run on any shell (bash, powershell)
  • With "null_resource", without creating any resource, any command can be run.
  • Provisioners in the resource only runs once while creating resource on remote instance
  • Provisioners in the "null_resource" run multiple times and it doesn't depend on the resource.
...
resource "aws_instance" "ubuntu2204" {

  ...
  provisioner "file" {
    source      = "test-file.txt" 
    destination = "/home/ubuntu/test-file.txt"
  }

  provisioner "file" {
    content     = "I want to copy this string to the destination file => server.txt (using provisioner file content)"
    destination = "/home/ubuntu/server.txt"
  }
  
  provisioner "remote-exec" {
    inline = [
      "touch hello.txt",
      "echo helloworld remote-exec provisioner >> hello.txt",
    ]
  }

  connection {
      type        = "ssh"
      host        = self.public_ip
      user        = "ubuntu"
      private_key = file("testkey.pem")
      timeout     = "4m"
   }
}

resource "null_resource" "example" {
  provisioner "local-exec" {
    command = "'This is test file for null resource local-exec' >>  nullresource-generated.txt"
    interpreter = ["PowerShell", "-Command"]
  }
}
...

image

  • Create main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }
  required_version = ">= 1.2.0"
}

provider "aws" {
	region = "eu-central-1"
}

resource "aws_vpc" "my_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  tags = {
    Name = "My VPC"
  }
}

resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.my_vpc.id
  cidr_block        = "10.0.0.0/24"
  availability_zone = "eu-central-1c"
  tags = {
    Name = "Public Subnet"
  }
}

resource "aws_internet_gateway" "my_vpc_igw" {
  vpc_id = aws_vpc.my_vpc.id
  tags = {
    Name = "My VPC - Internet Gateway"
  }
}

resource "aws_route_table" "my_vpc_eu_central_1c_public" {
    vpc_id = aws_vpc.my_vpc.id
    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = aws_internet_gateway.my_vpc_igw.id
    }
    tags = {
        Name = "Public Subnet Route Table"
    }
}
resource "aws_route_table_association" "my_vpc_eu_central_1c_public" {
    subnet_id      = aws_subnet.public.id
    route_table_id = aws_route_table.my_vpc_eu_central_1c_public.id
}

resource "aws_security_group" "allow_ssh" {
  name        = "allow_ssh_sg"
  description = "Allow SSH inbound connections"
  vpc_id      = aws_vpc.my_vpc.id
  # for SSH
  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"]
  }
  tags = {
    Name = "allow_ssh_sg"
  }
}

resource "aws_instance" "ubuntu2204" {

  ami                         = "ami-0d1ddd83282187d18" # Ubuntu 22.04 eu-central-1 Frankfurt
  instance_type               = "t2.nano" 
  key_name                    = "testkey"
  vpc_security_group_ids      = [aws_security_group.allow_ssh.id]
  subnet_id                   = aws_subnet.public.id
  associate_public_ip_address = true

  tags = {
    Name = "Ubuntu 22.04"
  }

  provisioner "file" {
    source      = "test-file.txt" 
    destination = "/home/ubuntu/test-file.txt"
  }

  provisioner "file" {
    content     = "I want to copy this string to the destination file => server.txt (using provisioner file content)"
    destination = "/home/ubuntu/server.txt"
  }
  
  provisioner "remote-exec" {
    inline = [
      "touch hello.txt",
      "echo helloworld remote-exec provisioner >> hello.txt",
    ]
  }

  connection {
      type        = "ssh"
      host        = self.public_ip
      user        = "ubuntu"
      private_key = file("testkey.pem")
      timeout     = "4m"
   }
}

resource "null_resource" "example" {
  provisioner "local-exec" {
    command = "'This is test file for null resource local-exec' >>  nullresource-generated.txt"
    interpreter = ["PowerShell", "-Command"]
  }
}

Code: https://github.com/omerbsezer/Fast-Terraform/blob/main/labs/provisioners-nullresources/main.tf

  • Run init, validate command:
terraform init
terraform validate
  • Run plan, apply command:
terraform plan
terraform apply

image

image

  • On AWS EC2 Instance:

image

  • Make SSH connection:
ssh -i testkey.pem ubuntu@<PublicIP>
  • Provisioners run and files were created on remote instance:

image

  • On local PC, local provisioner also created file:

image

  • Destroy infrastructure:
terraform destroy 

image

image

  • On AWS EC2 Instance:

image