Obiecałem w poprzednich rozdziałach, że zadbamy o lekkie usprawnienia security. Lokalny stan w terraform, nie stanowi najlepszego rozwiązania wystarczy, że podejrzymy wygenerowane pliki .tfstate i niezależnie od sposobu przekazania sekretów – lądują one tam czystym tekstem. Dodatkowo jeśli więcej niż jedna osoba pracuje nad zmianami infrastruktury – stan byłby ciągle trzymany niezależnie na różnych systemach. Potencjalnymi rozwiązaniami tego problemu mógłby być wspóldzielony dysk lub nawet lepiej inny rodzaj bezpiecznego składowiska.
Składowanie stanu w Azure
W tym artykule omówimy sobie podejście wykorzystujące Azure Storage. Zaczynamy od przygotowanie dedykowanej grupy zasobów, jak i konta magazynu (Storage account).
% az group create --name terraform-state --location westeurope
% az storage account create --resource-group terraform-state --name tstatesgdevpl --sku Standard_LRS --encryption-services blob
Przygotowane w ten sposób konto magazynu da nam dostęp do stanu z każdego miejsca na świecie. Klucze dostępowe uzyskamy poprzez polecenie:
% az storage account keys list --resource-group terraform-state --account-name tstatesgdevpl
[
{
"keyName": "key1",
"permissions": "Full",
"value": "xxxxxxxx"
},
{
"keyName": "key2",
"permissions": "Full",
"value": "yyyyyyyyyy"
}
]
Nieco interesującym może wydać się fakt, że w wyniku zostały zwrócone od razu dwa klucze (key1 i key2). Którego z nich powinniśmy zatem używać? Czy różnią się one zakresem uprawnień?
Otóż… możemy korzystać z obu. Istnienie dwóch kluczy drastycznie ułatwia ich emigrowanie w razie skompromitowania jednego z nich. W przypadku, gdy jeden z nich wyciekł powinniśmy zadziałać w następujący sposób. W każdej aplikacji korzystającej z naszego konta magazynu, podmieniamy klucz na drugi z dostępnych. Następnie rotujemy pierwszy z nich. Istnienie dwóch aktywnych kluczy umożliwia rotację w banalny sposób chroniący nas przed jakimkolwiek downtime’m aplikacji.
Pozyskany w ten sposób klucz dla potrzeb Terraform powinniśmy umieścić w zmiennej środowiskowej:
export ARM_ACCESS_KEY=xxxxxxxx
Następnie przygotowujemy magazyn pod nasz stan termaformowy.
% az storage container create --name tstate-marvel-aggregator --account-name tstatesgdevpl --account-key $ARM_ACCESS_KEY
{
"created": true
}
Jeśli chcemy obejrzeć efekt powyższych działań możemy zajrzeć np. na Portal Azure. Warto dodać, że jeżeli pominiemy wstrzyknięcie klucza do konta magazynu, a jesteśmy zalogowani z poziomu AzureCLI, polecenie i tak wykona się poprawnie po wyświetleniu nieprzyjemnego ostrzeżenia.
Pozostał nam do ułożenia ostatni klocek naszej układanki. Powinniśmy przestawić domyślne zachowanie Terraform, aby potrafił skorzystać z przygotowanego składowiska.
Mechanizmy obsługujące zarządzanie stanem nazywane są „backendami” i są one w pełni konfigurowalne i podmienialne. Domyślne zachowanie i jego wady poznaliśmy w poprzednich artykułach, jednak ich podmiana okazuje się banalną sprawą – wykorzystuje się do tego specjalną sekcję na początku pliku (dodajmy ją do naszego config.tf):
terraform {
backend "azurerm" {
resource_group_name = "terraform-state"
storage_account_name = "tstatesgdevpl"
container_name = "tstate-marvel-aggregator"
key = "terraform.tfstate"
}
}
Jako, że mamy przygotowaną już całą konfigurację możemy wykonać zestaw poleceń init (reinicjalizacja), a następnie plan i apply, a jako efekt ich wykonania powinniśmy zobaczyć, że stan wylądował w naszym magazynie.
Podsumowanie
W tym artykule przenieśliśmy zarządzanie stanem do chmury, od tego momentu w wygodny sposób i niewielkim kosztem możemy pracować infrastrukturą naszego projektu. Oczywiście planując wdrażanie większych rozwiązań warto rozważyć inne sposoby zarządzania stanem.