Wstęp

Dostęp do aktualnego stanu systemu wcześniej, w którym wdrożona jest automatyzacja zadań jest niezbędny do jego poprawnego utrzymania i dalszego konfigurowania. Wiele programów, które stosujemy, aby wdrożyć automatyzację zadań ma wbudowane mechanizmy przechowywania stanu, inne sprawdzają ten stan przed wykonaniem każdego z zaplanowanych zadań lub nie mają takiego mechanizmu wcale. W tym ostatnim przypadku to programiści muszą stworzyć odpowiednie mechanizmy, aby stan infrastruktury przechowywać i móc z niego korzystać. Także w większości przypadków jest to konieczne, jeżeli samodzielnie tworzymy mechanizmy, w których wykorzystujemy wiele aplikacji do wykonania poszczególnych czynności. W takim wypadku to my musimy przechowywać aktualny stan infrastruktury i przekazywać go jako parametry pomiędzy aplikacjami.

Terraform

Terraform to popularne narzędzie do zarządzania infrastrukturą. Niewątpliwie należy do moich ulubionych ze względu na swoją elastyczność oraz stosunkowo prosty język programowania HCL, jak i wbudowane mechanizmy przechowywania stanu infrastruktury. Dzięki temu, mogę budować skrypty dodając do nich kolejne kroki powoływania infrastruktury, a co najważniejsze w prosty sposób skalować rozwiązania, które zaprojektuję. Przykładowo, jeżeli stworzę skrypt do powoływania maszyn wirtualnych z zadanego szablonu, to w prosty sposób mogę uruchomić cztery takie wirtualne serwery, a następnie korzystając z tego samego przepisu zwiększyć ich liczbę do ośmiu. Niezależnie od tego czy maszyny wirtualne zostaną w mojej infrastrukturze zaprogramowane do umieszczenia jednej podsieci, czy każda z maszyn będzie umieszczona w osobnej, mechanizmy przechowywania stanu i skalowania rozwiązania zapewniają, że jedynie muszę zmienić parametr wskazujący na liczbę maszyn wirtualnych, które chce uruchomić. Gdy pierwszy raz wdrażam zaprogramowaną infrastrukturę, Terraform tworzy specjalny plik o nazwie terraform.tfstate, w którym przechowuje aktualny stan powołanej infrastruktury. Jest on następnie wykorzystywany do przygotowania planu zmian, jeżeli dokonujemy modyfikacji parametrów naszego skryptu. Stan ten jest automatycznie odświeżany przed każdą operacją. Głównym celem utrzymywania pliku stanu jest przechowywanie powiązań między obiektami w systemie zdalnym a wystąpieniami zasobów zadeklarowanymi w konfiguracji. Gdy Terraform utworzy obiekt zdalny w odpowiedzi na zmianę konfiguracji, zarejestruje on identyfikator tego obiektu względem określonego wystąpienia zasobu, a następnie potencjalnie zaktualizuje lub usunie ten obiekt w odpowiedzi na przyszłe zmiany konfiguracji. Oznacza to, że w pliku zapisane jest powiązanie – na przykład między obiektem wskazującym na publiczny adres IP a maszyną wirtualną i jej interfejsem, do którego adres ten jest przypisany. Jest to takie samo powiązanie jakie jest zapisane w zarządzanej infrastrukturze.

Ansible

W Terraformie określamy, jaki stan chcemy osiągnąć. Następnie już sama aplikacja upewnia się, że jesteśmy w tym stanie, tworząc, modyfikując lub niszcząc potrzebne zasoby. Ansible dla odmiany nie zarządza żadnym stanem. Musimy zatem sami zdefiniować, w jaki sposób chcemy śledzić utworzone zasoby za pomocą tagów lub innych właściwości, podczas gdy Terraform utrzymuje stan infrastruktury, więc nie musimy się martwić o tworzenie duplikatów zasobów. Jest to jeden z powodów, dlaczego polecam Terraform do budowania infrastruktury, a Ansible do konfigurowania oprogramowania. Nie oznacza to jednak, że Ansible w żaden sposób nie zbiera informacji o urządzeniach. Aby móc wprowadzić zaprogramowany w zadaniu przez nas docelowy stan, konieczne jest najpierw pobranie aktualnego stanu urządzenia. Na tej podstawie programiści danego modułu określają zestaw i kolejność czynności, które muszą zostać wykonane. Czynności niezbędne do wykonania są zaprogramowane w logice modułu. Dodatkowo, dzięki kolekcji ansible.utils uzyskaliśmy możliwość formatowania odczytanego stanu i zapisywania go w postaci struktury JSON, którą łatwo potem przekazać i analizować za pomocą zewnętrznych narzędzi. I chociaż biblioteka ta musi wpisywać się w logikę działania Ansible – co powoduje, że ma pewne ograniczenia i nie do końca intuicyjnie się jej używa – jest wygodnym narzędziem zbierania informacji nie tylko z serwerów, ale choćby z urządzeń sieciowych. Zebrane w ten sposób dane możemy przetwarzać w kolejnych zadaniach i wykorzystywać do podjęcia decyzji związanych z rekonfiguracją systemu.

Gdzie przechowywać informacje o stanie?

Proste systemy automatyzacji często odpalamy bezpośrednio na swoich komputerach. W takim przypadku jakiekolwiek informacje o stanie systemu także przechowujemy na swoim lokalnym komputerze. W przypadku systemów bardziej rozległych, a w szczególności takich, w których konfiguracji dokonuje więcej niż jedna osoba, a najczęściej całe zespoły, takie rozwiązanie z oczywistych powodów się nie sprawdza. Dostęp do zawartości pliku stanu muszą mieć wszystkie osoby biorące udział w procesie automatyzacji. Zazwyczaj zadania te wykonywane są przy użyciu centralnych systemów lub innych narzędzi spinających cały proces ze sobą. Wybór miejsca przechowywania informacji o stanie zależy zatem od wielu czynników. Moim zdaniem trzy główne czynniki to:

  • informacja, jakich narzędzi używamy,
  • zależności pomiędzy narzędziami, w szczególności czy odczytany, bądź skonfigurowany stan przez jedno narzędzie będzie służył do wyzwolenia scenariusza wykonywanego w innym narzędziu
  • polityki wewnętrzne przedsiębiorstwa, a w szczególności polityki związane z bezpieczeństwem i ochroną informacji

Terraform sam w sobie obsługuje kilka zdalnych lokalizacji do przechowywania pliku terraform.tfstate. Między innymi może to być usługa Amazon S3, Azure Blob Storage, Google Cloud Storage, Consul czy usługa Terraform Cloud. Dzięki podziałowi kompetencji, praca może zostać rozdzielona pomiędzy niezależne zespoły, które przekazują między sobą określone informacje. Przykładowo – zespół zajmujący się infrastrukturą może zająć się budowaniem podstawowych maszyn wirtualnych oraz usług sieciowych. Następnie udostępni niektóre informacje, takie jak identyfikatory VPC, podsieci, identyfikatory instancji NAT, a inne zespoły wykorzystują je, w celu prowadzenia konfiguracji systemu operacyjnego i aplikacji.