Konfiguracja względem środowiska

0

Ostatnio poróżniłem się z konfiguracją clouda aws poprzez AWS CloudFormation i przechodzę na Terraform. Ale mam pytanie. Mając kilka środowisk uruchomieniowych często się spotykamy ze scenariuszem, że kaźda z nich może mieć inną konfiguracje. Jak w takich przypadkach obsługujecie swoje terraformy aby w zależności od środowiska wgrywały do clouda inną konfiguracje? W tej chwili rozważam dwie opcje:

  1. Terraform workspaces
  2. Podzielenie struktury katalogów na różne foldery typu dev/stg/prod i w każdej z nich oddzielna konfiguracja a jakieś wspólne resource w oddzielnym module

Macie jakieś dobre pomysły i sugestie na co uważać przy późniejszym rozwoju clouda z uzyciem terraforma?

2

Ja stosowałem drugie podejście - główny moduł Terraforma parametryzowany przez różne pliki .tfvars na potrzeby różnych środowisk. Zazwyczaj to powinno wystarczać.

Credentiale i konfiguracja backendu wstrzykiwana przez zmienne środowiskowe przez pipeline CI/CD.

Z workspace nie korzystałem, chociaż wiem że niektórzy tak robią. Nie wiem nawet jak dokładnie to działa pod spodem, ale w dokumentacji jest jedna niepokojąca wzmianka:

Workspaces are not appropriate for system decomposition or deployments requiring separate credentials and access controls.

0
Klaun napisał(a):

Ja stosowałem drugie podejście - główny moduł Terraforma parametryzowany przez różne pliki .tfvars na potrzeby różnych środowisk. Zazwyczaj to powinno wystarczać.

Credentiale i konfiguracja backendu wstrzykiwana przez zmienne środowiskowe przez pipeline CI/CD.

Z workspace nie korzystałem, chociaż wiem że niektórzy tak robią. Nie wiem nawet jak dokładnie to działa pod spodem, ale w dokumentacji jest jedna niepokojąca wzmianka:

Workspaces are not appropriate for system decomposition or deployments requiring separate credentials and access controls.

Zrobiłem podobnie, wykorzystałem moduły i oddzilne katalogi dla kazdego srodowiska, wiec skonczylo sie na czyms takim:

- terraform
-- environments
--- dev
---- main.tf
---- vars.tf
---- outputs.tf
--- stg
--- prod
-- modules
--- aws-s3
---- main.tf
---- vars.tf
---- outputs.tf

Korzystałeś może z terraform backend? Chciałem przetrzymywać tam moje tfstate (w buckecie i dynamodb) ale mam problem z podłączeniem go do AWS SSO, bo mi krzyczy "Error: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds" mimo, że jestem zalogowany do swojego profilu :/

0

Spoko, to wyglada na rozwiazanie posrednie, ale znowu wiem ze niektorzy je stosuja, chociaz przyznam szczerze wywodzac sie ze srodowiska Azure, gdzie korzystalem z natywnych tooli do IaC jak ARM/Bicep nigdy na oczy takiego setupu nie widzialem i troche go osobiscie nie rozumiem.

Jak ja zazwyczaj robie w przypadku Terraforma na Azure (jak robie definicje infry pod konkretny projekt, jak to ma byc wspoldzielone repo z bazowymi modulami do uzytku w organizacji, albo jakis service catalog to bedzie pewnie inaczej):

/
└── terraform
    │   └── environments
    │       ├── dev.tfvars
    │       └── prod.tfvars
    ├── main.tf
    ├── variables.tf
    ├── outputs.tf
    ├── storage.tf
    ├── keyvault.tf
    ├── database.tf
    └── appservice.tf

Czyli dokladnie jeden modul glowny (nie mam main.tf per srodowisko) po prostu w rozny sposob parametryzowany pomiedzy srodowiskami.

Korzystałeś może z terraform backend?

Korzystalem, bo chyba nie da sie korzystac z TF bez backendu :D
Ale tylko z Azurowego Blob Storage.

0
Klaun napisał(a):

Spoko, to wyglada na rozwiazanie posrednie, ale znowu wiem ze niektorzy je stosuja, chociaz przyznam szczerze wywodzac sie ze srodowiska Azure, gdzie korzystalem z natywnych tooli do IaC jak ARM/Bicep nigdy na oczy takiego setupu nie widzialem i troche go osobiscie nie rozumiem.

Jak ja zazwyczaj robie w przypadku Terraforma na Azure (jak robie definicje infry pod konkretny projekt, jak to ma byc wspoldzielone repo z bazowymi modulami do uzytku w organizacji, albo jakis service catalog to bedzie pewnie inaczej):

/
└── terraform
    │   └── environments
    │       ├── dev.tfvars
    │       └── prod.tfvars
    ├── main.tf
    ├── variables.tf
    ├── outputs.tf
    ├── storage.tf
    ├── keyvault.tf
    ├── database.tf
    └── appservice.tf

Czyli dokladnie jeden modul glowny (nie mam main.tf per srodowisko) po prostu w rozny sposob parametryzowany pomiedzy srodowiskami.

Korzystałeś może z terraform backend?

Korzystalem, bo chyba nie da sie korzystac z TF bez backendu :D
Ale tylko z Azurowego Blob Storage.

Da się korzystać bez backendu, bo wtedy Ci state trzyma lokalnie, ale jest to troche śliskie mimo wszystko.

To co mam teraz to działa praktycznie tak samo jak twoje, tylko, że w .tfvars trzymam głównie jakieś secrety czy inne rzeczy które są z natury zmienne albo prywatne a w main.tf (tym dla konkretnego środowiska) już są bardziej statycznie zdefiniowane wartości które lecą do konkretnego modułu, jak np:

module "aws-lambda-export" {
  source = "../../modules/aws-lambda/aws-lambda-export"

  node_env    = "dev"
  lambda_name = "jakas_nazwa"
  runtime     = "nodejs18.x"

  iam_role      = module.aws-iam.lambda_iam_role
  lambda_bucket = module.aws-s3.lambda_bucket

  mongodb_name = var.mongodb_name
  mongodb_url  = var.mongodb_url

  memory_size = 2048
  timeout     = 600
}
0
Escanor16 napisał(a):

Da się korzystać bez backendu, bo wtedy Ci state trzyma lokalnie, ale jest to troche śliskie mimo wszystko.

To sie nazywa backend lokalny :P

To co mam teraz to działa praktycznie tak samo jak twoje, tylko, że w .tfvars trzymam głównie jakieś secrety czy inne rzeczy które są z natury zmienne albo prywatne a w main.tf (tym dla konkretnego środowiska) już są bardziej statycznie zdefiniowane wartości które lecą do konkretnego modułu, jak np:

module "aws-lambda-export" {
  source = "../../modules/aws-lambda/aws-lambda-export"

  node_env    = "dev"
  lambda_name = "jakas_nazwa"
  runtime     = "nodejs18.x"

  iam_role      = module.aws-iam.lambda_iam_role
  lambda_bucket = module.aws-s3.lambda_bucket

  mongodb_name = var.mongodb_name
  mongodb_url  = var.mongodb_url

  memory_size = 2048
  timeout     = 600
}

No tylko jak rozumiem dla kazdego srodowiska masz oddzielny composition root w ktorym skladasz te wszystkie moduly. Czy w takim razie zakladasz ze srodowiska dev/test/prod beda sie roznic pod katem kompozycji modulow i tworzonych zasobow? Zazwyczaj raczej dazymy do tego zeby srodowiska byly do siebie jak najbardziej zblizone, a roznily sie tylko sizingiem/konfiguracja.

Jak nie chcesz miec za duzo parametrow w .tfvars (co znowu w przypadku tworzenia infry pod konkretny projekt jest dobrym pomyslem) to przeciez mozesz w main.tf zdefiniowac lokala ktory przechowuje konfiguracje per srodowisko i wtedy przez tfvarsy wstrzykujesz dalej rzeczywiscie tylko to co moze byc bardziej zmienne niz reszta.

0
Klaun napisał(a):

No tylko jak rozumiem dla kazdego srodowiska masz oddzielny composition root w ktorym skladasz te wszystkie moduly. Czy w takim razie zakladasz ze srodowiska dev/test/prod beda sie roznic pod katem kompozycji modulow i tworzonych zasobow? Zazwyczaj raczej dazymy do tego zeby srodowiska byly do siebie jak najbardziej zblizone, a roznily sie tylko sizingiem/konfiguracja.

Jak nie chcesz miec za duzo parametrow w .tfvars (co znowu w przypadku tworzenia infry pod konkretny projekt jest dobrym pomyslem) to przeciez mozesz w main.tf zdefiniowac lokala ktory przechowuje konfiguracje per srodowisko i wtedy przez tfvarsy wstrzykujesz dalej rzeczywiscie tylko to co moze byc bardziej zmienne niz reszta.

Tak, dla każdego środowiska jest oddzielny main.tf z konfiguracją modułów.
Raczej nie będzie żadnych większych różnic oprócz sizingu/konfiguracji ale taki podział na środowiska jaki mam teraz i dekompozycja resource na oddzielne moduły stwarza, że jak na to patrze to wydaje się to jakieś bardziej solidne aniżeli wstrzykiwanie wszystkiego przez zmienne/locals. Ale wiadomo, kwestia doświadczenia i pewnie za jakiś czas okaże się czy to był dobry pomysł.

2

Zainteresuj się terragruntem. Bardzo ułatwia.
https://terragrunt.gruntwork.io/

1 użytkowników online, w tym zalogowanych: 0, gości: 1