2016-05-03 20 views
16

Ho usato Terraform per creare il mio stack AWS e mi sono divertito. Se doveva essere utilizzato in un ambiente commerciale, la configurazione avrebbe dovuto essere riutilizzata per diversi ambienti (ad esempio QA, STAGING, PROD).Ambienti diversi per Terraform (Hashicorp)

Come potrei essere in grado di raggiungere questo obiettivo? Dovrei creare uno script wrapper che faccia chiamate al cli di terraform mentre passi in file di stato diversi per ambiente come di seguito? Mi chiedo se ci sia una soluzione più nativa fornita da Terraform.

terraform apply -state=qa.tfstate 

risposta

12

Suggerisco di dare un'occhiata allo hashicorp best-practices repo, che ha una configurazione abbastanza buona per gestire ambienti diversi (simile a quello suggerito da James Woolfenden).

Stiamo usando una configurazione simile, e funziona abbastanza bene. Tuttavia, questo repository delle best practice presume che tu stia utilizzando Atlas, cosa che non lo siamo. Abbiamo creato un Rakefile piuttosto elaborato, che fondamentalmente (passando di nuovo dal repository best-practice) ottiene tutte le sottocartelle di/terraform/providers/aws e le espone come build differenti usando i namespace. Così il nostro rake -T uscita sarebbe elencare i seguenti compiti:

us_east_1_prod:init 
us_east_1_prod:plan 
us_east_1_prod:apply 

us_east_1_staging:init 
us_east_1_staging:plan 
us_east_1_staging:apply 

Questa separazione impedisce le modifiche che potrebbero essere esclusivo di dev per influenzare accidentalmente (o peggio, distruggere) qualcosa in prod, come si tratta di un file di stato diverso. Permette anche di testare un cambiamento in dev/staging prima di applicarlo effettivamente a prod.

Inoltre, recentemente ho incappato in questo piccolo write up, che mostra in pratica ciò che potrebbe accadere se si tiene tutto insieme: https://charity.wtf/2016/03/30/terraform-vpc-and-why-you-want-a-tfstate-file-per-env/

+0

mi sembra che questa sia probabilmente una risposta migliore per molte persone. – the0ther

+1

Mantenere un rapporto separato per ambiente è sicuramente una buona pratica: poiché Terraform 0.10, la funzione [Workspaces] (https://www.terraform.io/docs/state/workspaces.html) fa esattamente questo per 'spazio di lavoro' (es.ambiente) – RichVel

3

Non è necessario creare uno script wrapper. Quello che facciamo è dividere il nostro env in un modulo e quindi avere un file terraformato di primo livello in cui importiamo quel modulo per ogni ambiente. Finché hai il tuo setup del modulo per prendere abbastanza variabili, generalmente env_name e pochi altri, sei bravo. A titolo di esempio

# project/main.tf 
module "dev" { 
    source "./env" 

    env = "dev" 
    aws_ssh_keyname = "dev_ssh" 
} 

module "stage" { 
    source "./env" 

    env = "stage" 
    aws_ssh_keyname = "stage_ssh" 
} 

# Then in project/env/main.tf 
# All the resources would be defined in here 
# along with variables for env and aws_ssh_keyname, etc. 
+0

Interessante. Come fai a tenere separati i file .tfstate? Mantieni i moduli specifici dell'ambiente in cartelle separate e mantieni i file .tfstate associati? – n00b

+0

Non è necessario, un file tfstate per l'intero account aws :) se si controlla il modulo in git, è possibile impostare versioni e diramazioni per gli envs. Devi solo assicurarti di ottenere una terraforma prima di ogni schieramento per i non dev envs. – Paul

+0

Intendi un 'terraform refresh '? – n00b

5

Come si scala il vostro utilizzo Terraform, è necessario condividere lo stato (tra sviluppatori, costruire processi e progetti diversi), supportare più ambienti e regioni. Per questo è necessario utilizzare lo stato remoto. Prima di eseguire il tuo terraform è necessario impostare il tuo stato. (Im usando PowerShell)

$environment="devtestexample" 
$region  ="eu-west-1" 
$remote_state_bucket = "${environment}-terraform-state" 
$bucket_key = "yoursharedobject.$region.tfstate" 

aws s3 ls "s3://$remote_state_bucket"|out-null 
if ($lastexitcode) 
{ 
    aws s3 mb "s3://$remote_state_bucket" 
} 

terraform remote config -backend S3 -backend-config="bucket=$remote_state_bucket" -backend-config="key=$bucket_key" -backend-config="region=$region" 
#(see here: https://www.terraform.io/docs/commands/remote-config.html) 

terraform apply -var='environment=$environment' -var='region=$region' 

Il tuo stato è ora memorizzata nella S3, per regione, per l'ambiente, e quindi è possibile accedere a questo stato in altri progetti TF.

7

soluzione di Paolo con i moduli è l'idea giusta. Tuttavia, raccomando vivamente lo di fronte allo definendo tutti gli ambienti (ad es. QA, staging, produzione) nello stesso file Terraform. Se lo fai, allora ogni volta che stai apportando una modifica alla messa in scena, rischi di rompere accidentalmente anche la produzione, che in parte sconfigge il punto di mantenere quegli ambienti isolati in primo luogo! Vedi Terraform, VPC, and why you want a tfstate file per env per una discussione colorata su cosa può andare storto.

Consiglio sempre di memorizzare il codice Terraform per ogni ambiente in una cartella separata. In effetti, potresti persino voler memorizzare il codice Terraform per ogni "componente" (ad esempio un database, un VPC, una singola app) in cartelle separate. Di nuovo, la ragione è l'isolamento: quando apporti modifiche a una singola app (che potresti fare 10 volte al giorno), non vuoi mettere a rischio l'intero VPC (che probabilmente non cambierai mai).

Pertanto, il mio layout tipico file è qualcosa di simile:

stage 
    └ vpc 
    └ main.tf 
    └ vars.tf 
    └ outputs.tf 
    └ app 
    └ db 
prod 
    └ vpc 
    └ app 
    └ db 
global 
    └ s3 
    └ iam 

Tutto il codice Terraform per l'ambiente di staging va nella cartella stage, tutto il codice per l'ambiente prod va nella cartella prod, e tutto il codice che vive al di fuori di un ambiente (ad es. utenti IAM, bucket S3) va nella cartella global.

Per ulteriori informazioni, consultare How to manage Terraform state. Per uno sguardo più approfondito alle migliori pratiche di Terraform, consulta il libro Terraform: Up & Running.

+0

Hai provato ad incantare questa solutina con l'uso di un modulo per sbarazzarti di una cartella separata - problema di stato separato? – aholbreich

+0

@aholbreich Sì, per evitare di copiare/incollare lo stesso codice tra ogni ambiente, utilizziamo i moduli come descritto qui: [Come creare un'infrastruttura riutilizzabile con i moduli Terraform] (https://blog.gruntwork.io/how-to -creare riutilizzabili-infrastrutture-con-Terraform-moduli-25526d65f73d). –

+0

@YevgeniyBrikman eventuali raccomandazioni per la rimozione della duplicazione del 90% del codice da ciascun ambiente? Ognuno dei miei è molto simile e cambiare tutto è soggetto a errori. Grazie in anticipo. –

3

Si noti che dalla versione 0.10.0 ora Terraform supporta il concetto di aree di lavoro (ambienti in 0.9.x).

Uno spazio di lavoro è un contenitore denominato per lo stato Terraform. Con più spazi di lavoro, è possibile utilizzare un'unica directory di configurazione di Terraform per gestire più insiemi distinti di risorse dell'infrastruttura.

Vedi maggiori informazioni qui: https://www.terraform.io/docs/state/workspaces.html