AWS ELB e AutoScaling con Terraform

In questo post, fornirò una rapida introduzione a Terraform, uno strumento utilizzato per il provisioning e la configurazione dell’infrastruttura. Terraform consente di definire le configurazioni dell’infrastruttura e quindi implementare / creare automaticamente tali configurazioni da Terraform. A questo proposito, puoi confrontare Terraform con soluzioni simili come OpenStack Heat, AWS CloudFormation e altri.

Terraform è uno strumento per la costruzione, modifica e controllo delle versioni dell’infrastruttura in modo sicuro ed efficiente. Terraform può gestire fornitori di servizi esistenti e popolari, nonché soluzioni interne personalizzate. Le distribuzioni multi-cloud possono essere molto impegnative poiché molti strumenti esistenti per la gestione dell’infrastruttura sono specifici del cloud. Terraform è indipendente dal cloud e consente di utilizzare un’unica configurazione per gestire più provider e persino gestire dipendenze tra cloud. Ciò semplifica la gestione e l’orchestrazione, aiutando gli operatori a costruire infrastrutture multi-cloud su larga scala.

La documentazione ufficiale di Terraform per iniziare fa un buon lavoro nell’introdurre i singoli elementi di Terraform (ovvero risorse, variabili di input, variabili di output, ecc.), Quindi in questa guida ci concentreremo su come mettere insieme quegli elementi per creare un esempio abbastanza reale. In particolare, forniremo diversi server su AWS in un cluster e implementeremo un bilanciamento del carico per distribuire il carico su quel cluster. L’infrastruttura che creerai in questo esempio è un punto di partenza di base per l’esecuzione di servizi Web e microservizi scalabili e ad alta disponibilità. Le caratteristiche principali sono:

Infrastruttura come codice

L’infrastruttura è descritta usando una sintassi di configurazione di alto livello. Ciò consente a un progetto del tuo datacenter di essere aggiornato e trattato come faresti con qualsiasi altro codice. Inoltre, l’infrastruttura può essere condivisa e riutilizzata.

Piani di esecuzione

Terraform ha una fase di “pianificazione” in cui genera un piano di esecuzione . Il piano di esecuzione mostra cosa farà Terraform quando si chiama applica. Ciò consente di evitare sorprese quando Terraform manipola l’infrastruttura.

Grafico delle risorse

Terraform crea un grafico di tutte le risorse e parallelizza la creazione e la modifica di qualsiasi risorsa non dipendente. Per questo motivo, Terraform costruisce l’infrastruttura nel modo più efficiente possibile e gli operatori ottengono informazioni sulle dipendenze nella propria infrastruttura.

Automazione del cambiamento

Modifiche complesse possono essere applicate alla tua infrastruttura con una minima interazione umana. Con il piano di esecuzione e il grafico delle risorse menzionati in precedenza, sai esattamente quale Terraform cambierà e in quale ordine, evitando molti possibili errori umani.

Scarica terraform in base al tuo sistema. L’installazione è molto semplice. Scarica l’archivio zip di Terraform e decomprimilo in una posizione adatta. Dopo aver decompresso la terraform, aggiornare la variabile di ambiente PATH che punta a terraform. Poiché la cartella / usr / local / bin è già impostata sulla variabile di ambiente PATH, non è necessario impostarla di nuovo. Se si sta utilizzando un’altra posizione, specificarla nella variabile d’ambiente PATH in .bash_profile o in / etc / profile.

$ wget https://releases.hashicorp.com/terraform/0.10.7/terraform_0.10.7_linux_386.zip
$ decomprimere
terraform_0.10.7_linux_386.zip
$ mv terraform / usr / local / bin /
$ export PATH = $ PATH: / usr / local / bin /
Verifica l’installazione:
$ terraform -v

Terraform può eseguire il provisioning dell’infrastruttura attraverso diversi tipi di provider cloud, tra cui AWS, Azure, Google Cloud, DigitalOcean e molti altri.

Devi creare un utente IAM. Per creare un account utente più limitato, vai alla console Gestione identità e accesso (IAM), fai clic su “Utenti” e fai clic sul pulsante blu “Crea nuovi utenti”.

Fare clic su Avanti e in Aggiungi utente al permesso di gruppo selezionare ec2fullaccess. Quindi è necessario copiare l’ID chiave di accesso e l’ID chiave di accesso segreta.

Creare una directory per isolare i file terraform.
$ mkdir ~ / terraform && cd ~ / terraform

Il codice Terraform è scritto in una lingua chiamata HCL in file con estensione “.tf”. È un linguaggio dichiarativo. Il primo passo per utilizzare Terraform è in genere quello di configurare il provider che si desidera utilizzare. Crea un file chiamato “esempio.tf” e inserisci il seguente codice:

  provider "aws" { 
access_key = "aws_access_key_id"
secret_key = “aws_secret_access_key_id”
regione = "ap-sud-1"
}

Qui utilizzeremo il provider AWS e desideri implementare la tua infrastruttura nella regione “ap-sud-1”. Per ciascun provider, è possibile creare diversi tipi di “risorse”, ad esempio server, database e sistemi di bilanciamento del carico.

  risorsa "aws_instance" "web" { 
ami = “$ {lookup (var.amis, var.region)}”
count = "$ {var.count}"
key_name = “$ {var.key_name}”
vpc_security_group_ids = [“$ {aws_security_group.instance.id}”]
source_dest_check = false
instance_type = “t2.micro”
tag {
Nome = "$ {format (" web-% 03d ", count.index + 1)}"
}
}

Crea un altro file chiamato “variabili.tf”

  variabile "count" { 
default = 1
}
variabile "regione" {
description = "Regione AWS per l'hosting della nostra rete"
default = "ap-sud-1"
}
variabile "public_key_path" {
description = "Inserisci il percorso della chiave pubblica SSH da aggiungere ad AWS."
default = "/path_to_keyfile/keypair_name.pem"
}
variabile "key_name" {
description = "Nome chiave per SSHing in EC2"
default = "kaypair_name"
}
variabile "amis" {
description = "Base AMI per avviare le istanze"
default = {
ap-south-1 = “ami-8da8d2e2”
}
}

NOTA: è necessario creare e scaricare la coppia di chiavi utilizzando la console di gestione

In un terminale, vai nella cartella in cui hai creato esempio.tf ed esegui il comando “piano terraform”:

  $ piano terraform 
Stato di Terraform rinfrescante in memoria prima del piano ...
(...) + aws_instance.example
ami: "ami-2d39803a"
disponibilità_zona: ""
ebs_block_device. #: ""
ephemeral_block_device. #: ""
instance_state: ""
tipo_istanza: "t2.micro"
key_name: ""
network_interface_id: ""
placement_group: ""
private_dns: ""
private_ip: ""
public_dns: ""
public_ip: ""
root_block_device. #: ""
security_groups. #: ""
source_dest_check: "true"
subnet_id: ""
locazione: ">"
vpc_security_group_ids. #: ""
Piano: 1 da aggiungere, 0 da modificare, 0 da distruggere.

Per creare effettivamente l’istanza, esegui il comando “terraform apply”:

  $ terraform si applica 
aws_instance.example: creazione in corso ...
............
.......... . . .
Candidatura completa! Risorse: 1 aggiunto, 0 modificato, 0 distrutti.

Puoi vedere l’istanza creata nella console di gestione di aws attiva e in esecuzione.

L’esecuzione di un singolo server è un buon inizio, ma nel mondo reale, un singolo server è un singolo punto di errore. Se il server si arresta in modo anomalo o viene sovraccaricato da troppo traffico, gli utenti non possono più accedere al tuo sito. La soluzione consiste nell’eseguire un cluster di server, instradare i server che non funzionano e regolare le dimensioni del cluster su o giù in base al traffico.
Il
il primo passo è la creazione di un ASG è la creazione di una configurazione di avvio, che specifica come configurare ciascuna istanza EC2 nell’ASG. Dalla distribuzione della singola istanza EC2 in precedenza, sai già esattamente come configurarla.
Il secondo passo è la creazione di un bilanciamento del carico altamente disponibile e scalabile che richiede molto lavoro.

Ora riapri il tuo file example.tf e copia quanto segue

  provider "aws" { 
access_key = "aws_access_key_id"
secret_key = “aws_secret_access_key_id”
regione = "ap-sud-1"
}
data "aws_availability_zones" "all" {} ### Creazione dell'istanza EC2
risorsa "aws_instance" "web" {
ami = "$ {lookup (var.amis, var.region)}"
count = "$ {var.count}"
key_name = "$ {var.key_name}"
vpc_security_group_ids = ["$ {aws_security_group.instance.id}"]
source_dest_check = false
instance_type = "t2.micro"
tag {
Nome = "$ {format (" web-% 03d ", count.index + 1)}"
}
}
### Creazione di un gruppo di sicurezza per EC2
risorsa "aws_security_group" "istanza" {
name = "terraform-esempio-istanza"
ingresso {
from_port = 8080
to_port = 8080
protocollo = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingresso {
from_port = 22
to_port = 22
protocollo = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
## Creazione della configurazione di avvio
risorsa "aws_launch_configuration" "esempio" {
image_id = "$ {lookup (var.amis, var.region)}"
instance_type = "t2.micro"
security_groups = ["$ {aws_security_group.instance.id}"]
key_name = "$ {var.key_name}"
user_data = << - EOF
#! / Bin / bash
echo "Ciao, Mondo"> index.html
nohup busybox httpd -f -p 8080 e
EOF
ciclo vitale {
create_before_destroy = true
}
}
## Creazione del gruppo di AutoScaling
risorsa "aws_autoscaling_group" "esempio" {
launch_configuration = "$ {aws_launch_configuration.example.id}"
availability_zones = ["$ {data.aws_availability_zones.all.names}"]
min_size = 2
max_size = 10
load_balancers = ["$ {aws_elb.example.name}"]
health_check_type = "ELB"
tag {
chiave = "Nome"
value = "terraform-asg-example"
propagate_at_launch = true
}
}
## Gruppo di sicurezza per ELB
risorsa "aws_security_group" "elb" {
name = "terraform-example-elb"
uscita {
from_port = 0
to_port = 0
protocollo = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
ingresso {
from_port = 80
to_port = 80
protocollo = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
### Creazione di ELB
risorsa "aws_elb" "esempio" {
name = "terraform-asg-example"
security_groups = ["$ {aws_security_group.elb.id}"]
availability_zones = ["$ {data.aws_availability_zones.all.names}"]
Controllo della salute {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
intervallo = 30
target = "HTTP: 8080 /"
}
ascoltatore {
lb_port = 80
lb_protocol = "http"
instance_port = "8080"
instance_protocol = "http"
}
}

Nel file variabile.tf

  variabile "count" { 
default = 1
}
variabile "regione" {
description = "Regione AWS per l'hosting della nostra rete"
default = "ap-south-1"
}
variabile "public_key_path" {
description = "Inserisci il percorso della chiave pubblica SSH da aggiungere ad AWS."
default = "/home/ratul/developments/devops/keyfile/ec2-core-app.pem"
}
variabile "key_name" {
description = "Nome chiave per SSHing in EC2"
default = "ec2-core-app"
}
variabile "amis" {
description = "Base AMI per avviare le istanze"
default = {
ap-south-1 = "ami-8da8d2e2"
}
}

Crea anche un file chiamato output.tf e copia quanto segue

  output "instance_ids" { 
value = ["$ {aws_instance.web. *. public_ip}"]
}
output "elb_dns_name" {
value = "$ {aws_elb.example.dns_name}"
}

Ora esegui il piano terraform

  $ piano terraform Aggiornamento stato Terraform in memoria prima del piano ... 
Lo stato aggiornato verrà utilizzato per calcolare questo piano, ma non lo sarà
persistente nella memoria di stato locale o remota.
aws_security_group.instance: stato di aggiornamento ... (ID: sg-54ed813c)
aws_security_group.elb: stato di aggiornamento ... (ID: sg-09ef8361)
data.aws_availability_zones.all: stato di aggiornamento ...
aws_launch_configuration.example: stato di aggiornamento ... (ID: terraform-20171010122248311700000001)
aws_instance.web: stato di aggiornamento ... (ID: i-0c4d35b212b045d78)
aws_elb.example: stato di aggiornamento ... (ID: terraform-asg-example)
aws_autoscaling_group.example: stato di aggiornamento ... (ID: tf-asg-20171010122315457300000002)
Il piano di esecuzione Terraform è stato generato ed è mostrato di seguito.
Le risorse sono visualizzate in ordine alfabetico per una rapida scansione. Risorse verdi
verrà creato (o distrutto e quindi creato se una risorsa esistente
esiste), le risorse gialle vengono modificate sul posto e le risorse rosse
sarà distrutto. Le voci ciano sono fonti di dati da leggere.
Nota: non è stato specificato un parametro "-out" per salvare questo piano, quindi quando
"si applica" si chiama, Terraform non può garantire questo è ciò che verrà eseguito.
- / + aws_instance.web (nuova risorsa richiesta)
ami: "ami-8da8d2e2" => "ami-8da8d2e2"
associate_public_ip_address: "true" => ""
availability_zone: "ap-south-1a" => ""
ebs_block_device. #: "0" => ""
ephemeral_block_device. #: "0" => ""
instance_state: "running" => ""
tipo_istanza: "t2.micro" => "t2.micro"
ipv6_address_count: "" => ""
ipv6_addresses. #: "0" => ""
key_name: "ec2-core-app" => "ec2-core-app"
network_interface. #: "0" => ""
network_interface_id: "eni-b523daea" => ""
placement_group: "" => ""
primary_network_interface_id: "eni-b523daea" => ""
private_dns: "ip-172-31-24-44.ap-south-1.compute.internal" => ""
private_ip: "172.31.24.44" => ""
public_dns: "ec2-13-126-108-226.ap-south-1.compute.amazonaws.com" => ""
public_ip: "13.126.108.226" => ""
root_block_device. #: "1" => ""
security_groups. #: "1" => ""
source_dest_check: "false" => "false"
subnet_id: "subnet-16814c7f" => ""
tag.%: "1" => "1"
tags.Name: "web-001" => "web-001"
tenancy: "default" => ""
user_data: "c765373c563b260626d113c4a56a46e8a8c5ca33" => "" (forza una nuova risorsa)
volume_tags.%: "0" => ""
vpc_security_group_ids. #: "0" => "1"
vpc_security_group_ids.3652085476: "" => "sg-54ed813c"
Piano: 1 da aggiungere, 0 da modificare, 1 da distruggere.

Esegui il piano terraform

  $ piano terraform 
aws_security_group.instance: stato di aggiornamento ... (ID: sg-54ed813c)
aws_security_group.elb: stato di aggiornamento ... (ID: sg-09ef8361)
data.aws_availability_zones.all: stato di aggiornamento ...
aws_launch_configuration.example: stato di aggiornamento ... (ID: terraform-20171010122248311700000001)
aws_instance.web: stato di aggiornamento ... (ID: i-0c4d35b212b045d78)
aws_elb.example: stato di aggiornamento ... (ID: terraform-asg-example)
aws_autoscaling_group.example: stato di aggiornamento ... (ID: tf-asg-20171010122315457300000002)
aws_instance.web: Destroying ... (ID: i-0c4d35b212b045d78)
aws_instance.web: sta ancora distruggendo ... (ID: i-0c4d35b212b045d78, 10s trascorso)
aws_instance.web: sta ancora distruggendo ... (ID: i-0c4d35b212b045d78, 20s trascorsi)
aws_instance.web: sta ancora distruggendo ... (ID: i-0c4d35b212b045d78, 30s trascorso)
aws_instance.web: sta ancora distruggendo ... (ID: i-0c4d35b212b045d78, 40s trascorso)
aws_instance.web: distruzione completata dopo 47 secondi
aws_instance.web: creazione in corso ...
ami: "" => "ami-8da8d2e2"
associate_public_ip_address: "" => ""
availability_zone: "" => ""
ebs_block_device. #: "" => ""
ephemeral_block_device. #: "" => ""
instance_state: "" => ""
tipo_istanza: "" => "t2.micro"
ipv6_address_count: "" => ""
ipv6_addresses. #: "" => ""
key_name: "" => "ec2-core-app"
network_interface. #: "" => ""
network_interface_id: "" => ""
placement_group: "" => ""
primary_network_interface_id: "" => ""
private_dns: "" => ""
private_ip: "" => ""
public_dns: "" => ""
public_ip: "" => ""
root_block_device. #: "" => ""
security_groups. #: "" => ""
source_dest_check: "" => "false"
subnet_id: "" => ""
tag.%: "" => "1"
tags.Name: "" => "web-001"
tenancy: "" => ">"
volume_tags.%: "" => ""
vpc_security_group_ids. #: "" => "1"
vpc_security_group_ids.3652085476: "" => "sg-54ed813c"
aws_instance.web: Sto ancora creando ... (10s trascorsi)
aws_instance.web: Sto ancora creando ... (20s trascorsi)
aws_instance.web: Sto ancora creando ... (30s trascorsi)
aws_instance.web: creazione completata dopo 32 secondi (ID: i-019e9bf03a9d3de32)
Candidatura completa! Risorse: 1 aggiunto, 0 modificato, 1 distrutto. Output : elb_dns_name = terraform-asg-example-2472445669.ap-south-1.elb.amazonaws.com
instance_ids = [
52.66.14.13
]

ELB sta indirizzando il traffico verso le tue istanze EC2. Ogni volta che premi l’URL, sceglierà un’istanza diversa per gestire la richiesta. Ora hai un cluster completamente funzionante di web server!

Copia elb_dns_name e incollalo nel tuo browser

Esegui terraform distruggere

  $ terraform distruggere 
Vuoi davvero distruggere?
Terraform eliminerà tutta la tua infrastruttura gestita.
Non è possibile annullare. Solo 'sì' sarà accettato per confermare.
Inserisci un valore:

Dopo aver digitato “yes” e premuto invio, Terraform costruirà il grafico delle dipendenze ed eliminerà tutte le risorse nel giusto ordine, usando il maggior parallelismo possibile. Tra circa un minuto, il tuo account AWS dovrebbe essere nuovamente pulito.