LINUX

Cómo instalar Terraform y aprovisionar la instancia en la nube AWS EC2

Las primitivas de terraform utilizadas para definir la infraestructura como código (IaaC). Puede construir, cambiar y versionar su infraestructura en AWS, Digital Ocean, Google Cloud, Heroku, Microsoft Azure, etc. usando la misma herramienta. Describa los componentes de su aplicación única o del centro de datos completo utilizando terraform. En este tutorial, crearemos una infraestructura utilizando terraform y aprovisionaremos la instancia AWS EC2.

1. Instale Terraform

Descargar terraform dependiendo de su sistema. La instalación es muy sencilla. Descargue el archivo zip terraform y descomprímalo en una ubicación adecuada. Una vez que hayamos descomprimido terraform, actualizaremos la variable de entorno PATH apuntando a terraform. Dado que la carpeta / usr / local / bin ya está configurada en la variable de entorno PATH, no es necesario volver a configurarla. Si está utilizando cualquier otra ubicación, especifíquela en la variable de entorno PATH en .bash_profile o en / etc / profile.

[thegeek@mysandbox ~]$ cd /usr/local/src
[root@mysandbox src]# wget https://releases.hashicorp.com/terraform/0.8.5/terraform_0.8.5_linux_386.zip
[root@mysandbox src]# unzip terraform_0.8.5_linux_386.zip
[root@mysandbox src]# mv terraform /usr/local/bin/

Ahora agregue la siguiente línea para agregar terraform en la ubicación PATH.

export PATH=$PATH:/terraform-path/

Verifique la instalación de terraform con el siguiente comando

[root@mysandbox src]# terraform
Usage: terraform [--version] [--help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
apply               Builds or changes infrastructure
console            Interactive console for Terraform interpolations
destroy            Destroy Terraform-managed infrastructure
fmt                  Rewrites config files to canonical format
get                  Download and install modules for the configuration
graph              Create a visual graph of Terraform resources
import             Import existing infrastructure into Terraform
init                  Initializes Terraform configuration from a module
output             Read an output from a state file
plan                Generate and show an execution plan
push               Upload this Terraform module to Atlas to run
refresh            Update local state file against real resources
remote            Configure remote state storage
show               Inspect Terraform state or plan
taint                Manually mark a resource for recreation
untaint             Manually unmark a resource as tainted
validate           Validates the Terraform files
version            Prints the Terraform version

All other commands:
debug              Debug output management (experimental)
state                Advanced state management

2. Cree un usuario de EC2

Cuando crea una cuenta en AWS por primera vez, se le proporciona un inicio de sesión de root que accede a todos los servicios / funciones en AWS. Para conocer las mejores prácticas de seguridad de AWS, utilice una cuenta raíz y cree cuentas de usuario con acceso limitado a los servicios de AWS. Dado que crearemos una infraestructura en AWS utilizando la API de terraform que interactuará con los servicios EC2, crearemos un usuario con acceso a todos los servicios EC2 únicamente.

Inicie sesión en AWS consola usando la cuenta root. Seleccione servicios-> AZ-> IAM

Seleccione el servicio IAM

Haga clic en Usuarios en el panel de IAM.

Seleccionar usuario de la barra lateral izquierda en el panel de IAM

Haga clic en «Agregar usuario»

Haga clic en agregar usuario en IAM

Proporcione un nombre de usuario y haga clic solo en «Acceso programático». Hemos proporcionado el nombre de usuario como «terraformuser». Haga clic en «Siguiente: Permiso»

Nombre de usuario de IAM y tipo de acceso

A continuación, haga clic en «Crear grupo». Proporcione un nombre de grupo y en el tipo de política, filtre por AmazonEC2. Seleccione la primera fila que le da acceso completo a Amazon EC2.

Otorgar acceso completo a EC2

Haga clic en «Siguiente: Revisar»

Revisión de usuario de IAM

Haga clic en «Crear usuario».

Crear usuario de IAM

Descargue el ID de la clave de acceso y la clave secreta de los usuarios recién creados haciendo clic en «Descargar .csv». Estas credenciales son necesarias para conectarse al servicio Amazon EC2 a través de terraform

Descargue la clave de usuario y el ID de AWS terraform

3. Archivo Terraform

Como ya sabemos que terraform es una herramienta de línea de comandos para crear, actualizar y versionar la infraestructura en la nube, obviamente queremos saber cómo lo hace. Terraform describe la infraestructura en un archivo usando el lenguaje llamado Hashicorp Configuration Language (HCL) con la extensión .tf Es un lenguaje declarativo que describe la infraestructura en la nube. Cuando escribimos nuestra infraestructura usando HCL en un archivo .tf, terraform genera un plan de ejecución que describe lo que hará para alcanzar el estado deseado. Una vez que el plan de ejecución está listo, terraform ejecuta el plan y genera un archivo de estado con el nombre terraform.tfstate por defecto. Este archivo asigna metadatos de recursos a la ID de recurso real y permite que terraform sepa qué está administrando en la nube.

4. Terraform y aprovisionamiento de AWS

Para implementar una instancia EC2 a través de terraform, cree un archivo con extensión .tf Este archivo contiene dos secciones. La primera sección declara el proveedor (en nuestro caso es AWS). En la sección de proveedor especificaremos la clave de acceso y la clave secreta que está escrita en el archivo CSV que hemos descargado anteriormente al crear el usuario EC2. También elija la región de su elección. El bloque de recursos define qué recursos queremos crear. Como queremos crear una instancia EC2, lo especificamos con «aws_instance» y los atributos de la instancia dentro de ella como ami, instance_type y etiquetas. Para encontrar las imágenes de EC2, navegue por ubuntu imagen de la nube.

[root@mysandbox src]# cd
[root@mysandbox ~]# mkdir terraform
[root@mysandbox ~]# cd terraform/
[root@mysandbox terraform]# vi aws.tf

provider "aws" {
access_key = "ZKIAITH7YUGAZZIYYSZA"
secret_key = "UlNapYqUCg2m4MDPT9Tlq+64BWnITspR93fMNc0Y"
region = "ap-southeast-1"
}

resource "aws_instance" "example" {
ami = "ami-83a713e0"
instance_type = "t2.micro"
tags {
Name = "your-instance"
}
}

Primero aplique terraform plan para averiguar qué hará terraform. El plan terraform nos permitirá saber qué cambios, adiciones y eliminaciones se realizarán en la infraestructura antes de aplicarla. Se van a crear los recursos con el signo ‘+’, se van a eliminar los recursos con el signo ‘-‘ y se van a modificar los recursos con el signo ‘~’.

[root@mysandbox terraform]# terraform plan

Ahora para crear la instancia, ejecute terraform apply

[root@mysandbox terraform]# terraform apply

aws_instance.example: Creating...
ami:                                                   "" => "ami-83a713e0"
associate_public_ip_address:             "" => "<computed>"
availability_zone:                                "" => "<computed>"
ebs_block_device.#:                          "" => "<computed>"
ephemeral_block_device.#:                "" => "<computed>"
instance_state:                                    "" => "<computed>"
instance_type:                                     "" => "t2.micro"
key_name:                                          "" => "<computed>"
network_interface_id:                         "" => "<computed>"
placement_group:                               "" => "<computed>"
private_dns:                                        "" => "<computed>"
private_ip:                                          "" => "<computed>"
public_dns:                                         "" => "<computed>"
public_ip:                                           "" => "<computed>"
root_block_device.#:                          "" => "<computed>"
security_groups.#:                              "" => "<computed>"
source_dest_check:                           "" => "true"
subnet_id:                                          "" => "<computed>"
tags.%:                                              "" => "1"
tags.Name:                                        "" => "your-instance"
tenancy:                                             "" => "<computed>"
vpc_security_group_ids.#:                 "" => "<computed>"
aws_instance.example: Still creating... (10s elapsed)
aws_instance.example: Still creating... (20s elapsed)
aws_instance.example: Creation complete

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

A continuación, nos dirigimos al panel de EC2, encontraremos que la nueva instancia se está inicializando.

Inicialización de la instancia EC2

5. Un ejemplo de terraforma más complejo

Ahora que hemos entendido cómo crear una instancia EC2 usando terraform, creemos una infraestructura un poco más avanzada usando terraform. Nuestro objetivo de infraestructura incluye-

→ Crear una VPC con CIDR 10.0.0.0/16

→ Una subred pública dentro de VPC con CIDR 10.0.1.0/24

→ Una subred privada dentro de VPC con CIDR 10.0.2.0/24

→ Grupos de seguridad para instancias públicas y privadas

→ Tres instancias EC2: servidor web, servidor de base de datos e instancia NAT

Primero, creamos un par de claves con el nombre linoxide-deployer.pem a través de la consola de AWS. Para hacer eso, haga clic en «Pares de claves» en el panel de EC2 seguido de «Crear par de claves» y guárdelo en un directorio recién creado dentro de la carpeta terraform que hemos creado en el paso 4.

Crear par de claves

[root@mysandbox ]# cd ~/terraform
[root@mysandbox ]# mkdir ssh

Descargue y copie linoxide-deployer.pem dentro del directorio ~ / terraform / ssh.

Ahora, comenzamos a crear recursos uno por uno a partir de VPC. Además, dividiremos la configuración en varios archivos .tf en función de lo que hacen. Por ejemplo, para crear un recurso VPC, crearemos un archivo con el nombre vpc.tf para que podamos realizar un seguimiento de lo que hace cada archivo. Antes de crear recursos, declaremos todas las variables en el archivo variables.tf.

variables.tf

variable "access_key" {
description = "AWS access key"
default = "ZKIAITH7YUGAZZIYYSZA"
}

variable "secret_key" {
description = "AWS secret key"
default = "UlNapYqUCg2m4MDPT9Tlq+64BWnITspR93fMNc0Y"
}

variable "region" {
description = "AWS region for hosting our your network"
default = "ap-southeast-1"
}

variable "key_path" {
description = "Key path for SSHing into EC2"
default  = "./ssh/linoxide-deployer.pem"
}

variable "key_name" {
description = "Key name for SSHing into EC2"
default = "linoxide-deployer"
}

variable "vpc_cidr" {
description = "CIDR for VPC"
default     = "10.0.0.0/16"
}

variable "public_subnet_cidr" {
description = "CIDR for public subnet"
default     = "10.0.1.0/24"
}

variable "private_subnet_cidr" {
description = "CIDR for private subnet"
default     = "10.0.2.0/24"
}

variable "amis" {
description = "Base AMI to launch the instances"
default = {
ap-southeast-1 = "ami-83a713e0"
ap-southeast-2 = "ami-83a713e0"
}
}

Definamos VPC con el bloque CIDR de 10.0.0.0/16

vpc.tf

resource "aws_vpc" "default" {
cidr_block = "${var.vpc_cidr}"
enable_dns_hostnames = true
tags {
Name = "terraform-aws-vpc"
}
}

Definir la puerta de enlace

gateway.tf

resource "aws_internet_gateway" "default" {
vpc_id = "${aws_vpc.default.id}"                                                                                                                                       tags {
Name = "linoxide gw"
}
}

Definir subred pública con CIDR 10.0.1.0/24

public.tf

resource "aws_subnet" "public-subnet-in-ap-southeast-1" {
vpc_id = "${aws_vpc.default.id}"

cidr_block = "${var.public_subnet_cidr}"
availability_zone = "ap-southeast-1a"

tags {
Name = "Linoxide Public Subnet"
}
}

Definir subred privada con CIDR 10.0.2.0/24

private.tf

resource "aws_subnet" "private-subnet-ap-southeast-1" {
vpc_id = "${aws_vpc.default.id}"

cidr_block = "${var.private_subnet_cidr}"
availability_zone = "ap-southeast-1a"

tags {
Name = "Linoxide Private Subnet"
}
}

Tabla de ruta para subred pública / privada

route.tf

resource "aws_route_table" "public-subnet-in-ap-southeast-1" {
vpc_id = "${aws_vpc.default.id}"

route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.default.id}"
}

tags {
Name = "Linoxide Public Subnet"
}
}

resource "aws_route_table_association" "public-subnet-in-ap-southeast-1-association" {
subnet_id = "${aws_subnet.public-subnet-in-ap-southeast-1.id}"
route_table_id = "${aws_route_table.public-subnet-in-ap-southeast-1.id}"
}

resource "aws_route_table" "private-subnet-in-ap-southeast-1" {
vpc_id = "${aws_vpc.default.id}"

route {
cidr_block = "0.0.0.0/0"
instance_id = "${aws_instance.nat.id}"
}

tags {
Name = "Linoxide Private Subnet"
}
}

resource "aws_route_table_association" "private-subnet-in-ap-southeast-1-association" {
subnet_id = "${aws_subnet.private-subnet-in-ap-southeast-1.id}"
route_table_id = "${aws_route_table.private-subnet-in-ap-southeast-1.id}"
}

Definir grupo de seguridad NAT

natsg.tf

resource "aws_security_group" "nat" {
name = "vpc_nat"
description = "NAT security group"

ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["${var.private_subnet_cidr}"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["${var.private_subnet_cidr}"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}

egress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["${var.vpc_cidr}"]
}
egress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}

vpc_id = "${aws_vpc.default.id}"

tags {
Name = "NATSG"
}
}

Definir grupo de seguridad para Web

websg.tf

resource "aws_security_group" "web" {
name = "vpc_web"
description = "Accept incoming connections."

ingress {
from_port = 80
to_port = 80
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"]
}
ingress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}

egress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["${var.private_subnet_cidr}"]
}

vpc_id = "${aws_vpc.default.id}"

tags {
Name = "WebServerSG"
}
}

Definir grupo de seguridad para la base de datos en la subred privada

dbsg.tf

resource "aws_security_group" "db" {
name = "vpc_db"
description = "Accept incoming database connections."

ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
security_groups = ["${aws_security_group.web.id}"]
}

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["${var.vpc_cidr}"]
}
ingress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["${var.vpc_cidr}"]
}

egress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

vpc_id = "${aws_vpc.default.id}"

tags {
Name = "DBServerSG"
}
}

Definir instancia de servidor web

webserver.tf

resource "aws_instance" "web-1" {
ami = "${lookup(var.amis, var.region)}"
availability_zone = "ap-southeast-1a"
instance_type = "t2.micro"
key_name = "${var.key_name}"
vpc_security_group_ids = ["${aws_security_group.web.id}"]
subnet_id = "${aws_subnet.public-subnet-in-ap-southeast-1.id}"
associate_public_ip_address = true
source_dest_check = false

tags {
Name = "Web Server LAMP"
}
}

Definir instancia de base de datos

dbinstance.tf

resource "aws_instance" "db-1" {
ami = "${lookup(var.amis, var.region)}"
availability_zone = "ap-southeast-1a"
instance_type = "t2.micro"
key_name = "${var.key_name}"
vpc_security_group_ids = ["${aws_security_group.db.id}"]
subnet_id = "${aws_subnet.private-subnet-in-ap-southeast-1.id}"
source_dest_check = false

tags {
Name = "Database Server"
}
}

Definir instancia NAT

natinstance.tf

resource "aws_instance" "nat" {
ami = "ami-1a9dac48" # this is a special ami preconfigured to do NAT
availability_zone = "ap-southeast-1a"
instance_type = "t2.micro"
key_name = "${var.key_name}"
vpc_security_group_ids = ["${aws_security_group.nat.id}"]
subnet_id = "${aws_subnet.public-subnet-in-ap-southeast-1.id}"
associate_public_ip_address = true
source_dest_check = false

tags {
Name = "NAT instance"
}
}

Asignar EIP para NAT e instancia web

eip.tf

resource "aws_eip" "nat" {
instance = "${aws_instance.nat.id}"
vpc = true
}
resource "aws_eip" "web-1" {
instance = "${aws_instance.web-1.id}"
vpc = true
}

Ejecute primero el plan terraform para averiguar qué hará terraform. También puede realizar una revisión final de su infraestructura antes de ejecutar terraform apply

[root@mysandbox terraform]# terraform plan
----------------------------
----------------------------
Plan: 16 to add, 0 to change, 0 to destroy.

Hay un total de 16 planes para agregar, nada que cambiar o destruir

Ahora ejecute terraform apply

[root@mysandbox terraform]# terraform apply

Una vez completada la ejecución del comando anterior, nuestra infraestructura cobrará vida con una VPC, dos subredes, puerta de enlace, tablas de enrutamiento, grupos de seguridad, asociación EIP, las tres instancias EC2, etc. Puede crear el gráfico de infraestructura con el siguiente comando.

[root@mysandbox terraform]# terraform graph | dot -Tpng > infrastructure_graph.png

terraform y aprovisionar AWS

Ahora conéctese a la instancia NAT desde su estación de trabajo local, estará dentro de la instancia NAT. La IP privada asignada a la instancia NAT en nuestra infraestructura es 10.0.1.220. Acceda a la instancia dentro de la subred privada, es decir, la instancia de base de datos a través de la instancia NAT, así como la instancia ‘Web Server LAMP’. La IP privada asignada a las instancias de servidor web y de base de datos son 10.0.2.220 y 10.0.1.207 respectivamente. Explore el panel de EC2 para encontrar la IP privada asignada a sus instancias.

[root@mysandbox terraform]# ssh -i "./ssh/linoxide-deployer.pem" ec2-user@ec2-52-220-223-173.ap-southeast-1.compute.amazonaws.com

Hacer ping a la instancia de base de datos desde NAT

[ec2-user@ip-10-0-1-220 ~]$ ping 10.0.2.220
PING 10.0.2.220 (10.0.2.220) 56(84) bytes of data.
64 bytes from 10.0.2.220: icmp_seq=1 ttl=64 time=0.321 ms
64 bytes from 10.0.2.220: icmp_seq=2 ttl=64 time=0.452 ms
64 bytes from 10.0.2.220: icmp_seq=3 ttl=64 time=0.393 ms

Hacer ping a la instancia del servidor web desde NAT

[ec2-user@ip-10-0-1-220 ~]$ ping 10.0.1.207
PING 10.0.1.207 (10.0.1.207) 56(84) bytes of data.
64 bytes from 10.0.1.207: icmp_seq=1 ttl=64 time=0.747 ms
64 bytes from 10.0.1.207: icmp_seq=2 ttl=64 time=0.517 ms

Hemos instalado terraform y aprovisionamos AWS. Ahora puede usar el código para actualizar fácilmente su infraestructura e incluso implementarlo en otra región con modificaciones menores.

Conclusión:

¡Eso es todo por terraform! Hemos definido el estado de la infraestructura en archivos terraform e implementamos la infraestructura con un solo comando. Examinar la documentación para obtener más información sobre los detalles del proveedor de terraform / AWS. Gracias por leer este artículo.

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba
Cerrar