dlaczego używamy Terraform, a nie Chef, Puppet, Ansible, SaltStack lub CloudFormation

aktualizacja, 17 listopada 2016: wzięliśmy tę serię postów na blogu, rozszerzyliśmy ją i przekształciliśmy w książkę o nazwie Terraform: Up & Running!

aktualizacja, 8 lipca 2019: zaktualizowaliśmy tę serię postów na blogu dla Terraform 0.12 i wydaliśmy drugą edycję Terraform: Up & Running!

jest to część 1 obszernego przewodnika po serii Terraform. We wstępie do serii omówiliśmy, dlaczego każda firma powinna używać infrastructure-as-code (IAC). W tym poście omówimy, dlaczego wybraliśmy Terraform jako narzędzie IAC.

Jeśli szukasz w Internecie „Infrastruktura jako kod”, łatwo jest wymyślić listę najpopularniejszych narzędzi:

  • Chef
  • Puppet
  • Ansible
  • SaltStack
  • CloudFormation
  • Terraform

nie jest łatwo znaleźć, którego z nich należy użyć. Wszystkie te narzędzia mogą być używane do zarządzania infrastrukturą jako kod. Wszystkie z nich są open source, wspierane przez duże społeczności współpracowników i współpracują z wieloma różnymi dostawcami chmury (z godnym uwagi wyjątkiem CloudFormation, który jest closed source i tylko AWS). Wszystkie oferują wsparcie dla przedsiębiorstw. Wszystkie z nich są dobrze udokumentowane, zarówno pod względem oficjalnej dokumentacji, jak i zasobów społeczności, takich jak posty na blogu i pytania o StackOverflow. Więc jak decydujesz?

co sprawia, że jest to jeszcze trudniejsze jest to, że większość porównań można znaleźć Online między tymi narzędziami zrobić niewiele więcej niż wymienić ogólne właściwości każdego narzędzia i sprawiają, że brzmi jak można być równie skuteczne z każdym z nich. I chociaż to technicznie prawda, to nie pomaga. To trochę jak powiedzenie początkującemu programiście, że możesz równie skutecznie zbudować stronę internetową za pomocą PHP, C lub Assembly — stwierdzenie, które jest technicznie prawdziwe, ale pomija ogromną ilość informacji, które byłyby niezwykle przydatne w podejmowaniu dobrej decyzji.

w tym poście omówimy kilka bardzo konkretnych powodów, dla których wybraliśmy Terraform zamiast innych narzędzi IAC. Podobnie jak w przypadku wszystkich decyzji technologicznych, jest to kwestia kompromisów i priorytetów, i chociaż twoje szczególne priorytety mogą być inne niż nasze, mamy nadzieję, że dzielenie się naszym procesem myślenia pomoże Ci podjąć własną decyzję. Oto główne kompromisy, które rozważaliśmy:

  • Zarządzanie konfiguracją vs Provisioning
  • Infrastruktura zmienna vs Infrastruktura niezmienna
  • proceduralny vs deklaratywny
  • Master vs Masterless
  • Agent vs Bezagentless
  • duża społeczność vs mała społeczność
  • Dojrzała vs najnowocześniejsza
  • używanie wielu narzędzi razem

Chef, Puppet, Ansible i SaltStack to wszystkie narzędzia do zarządzania konfiguracją, co oznacza, że są one przeznaczone do instalowania i zarządzania oprogramowaniem na istniejących serwerach. CloudFormation i Terraform są narzędziami do udostępniania, co oznacza, że są przeznaczone do dostarczania samych serwerów (a także reszty infrastruktury, takiej jak równoważenie obciążenia, bazy danych, konfiguracja sieci itp.), pozostawiając zadanie konfigurowania tych serwerów innym narzędziom. Te dwie kategorie nie wykluczają się wzajemnie, ponieważ większość narzędzi do zarządzania konfiguracją może w pewnym stopniu zarządzać konfiguracją, a większość narzędzi do zarządzania konfiguracją może w pewnym stopniu zarządzać konfiguracją. Jednak nacisk na zarządzanie konfiguracją lub udostępnianie oznacza, że niektóre narzędzia będą lepiej pasować do niektórych rodzajów zadań.

w szczególności odkryliśmy, że jeśli używasz Dockera lub Packera, zdecydowana większość Twoich potrzeb w zakresie zarządzania konfiguracją jest już załatwiona. Za pomocą Dockera i Packera można tworzyć obrazy (takie jak kontenery lub obrazy maszyn wirtualnych), które mają zainstalowane i skonfigurowane całe oprogramowanie potrzebne serwerowi. Gdy już masz taki obraz, wszystko, czego potrzebujesz, to serwer, aby go uruchomić. A jeśli wszystko, co musisz zrobić, to aprowizować kilka serwerów, To narzędzie do aprowizacji, takie jak Terraform, Zazwyczaj będzie lepszym rozwiązaniem niż narzędzie do zarządzania konfiguracją (oto przykład użycia Terraform do wdrożenia Docker w AWS).

Infrastruktura zmienna vs Infrastruktura niezmienna

narzędzia do zarządzania konfiguracją, takie jak Chef, Puppet, Ansible i SaltStack, zazwyczaj domyślnie paradygmat infrastruktury zmiennej. Na przykład, jeśli powiesz Chef ’ owi, aby zainstalował nową wersję OpenSSL, uruchomi on aktualizację oprogramowania na istniejących serwerach, a zmiany zostaną wprowadzone. Z biegiem czasu, gdy wprowadzasz coraz więcej aktualizacji, każdy serwer tworzy unikalną historię zmian. Często prowadzi to do zjawiska znanego jako configuration drift, gdzie każdy serwer staje się nieco inny niż wszystkie inne, co prowadzi do subtelnych błędów konfiguracyjnych, które są trudne do zdiagnozowania i prawie niemożliwe do odtworzenia.

Jeśli używasz narzędzia do obsługi, takiego jak Terraform, do wdrażania obrazów maszyn utworzonych przez Docker lub Packer, każda „zmiana” jest w rzeczywistości wdrożeniem nowego serwera (tak jak każda „zmiana” na zmienną w programowaniu funkcyjnym faktycznie zwraca nową zmienną). Na przykład, aby wdrożyć nową wersję OpenSSL, należy utworzyć nowy obraz za pomocą Packera lub Dockera z już zainstalowaną nową wersją OpenSSL, wdrożyć ten obraz na zestawie całkowicie nowych serwerów, a następnie odłączyć stare serwery. Takie podejście zmniejsza prawdopodobieństwo błędów w konfiguracji, ułatwia dokładne poznanie, jakie oprogramowanie działa na serwerze, i pozwala trywialnie wdrożyć dowolną poprzednią wersję oprogramowania w dowolnym momencie. Oczywiście można zmusić narzędzia do zarządzania konfiguracją do niezmiennych wdrożeń, ale nie jest to idiomatyczne podejście do tych narzędzi, podczas gdy jest to naturalny sposób korzystania z narzędzi do udostępniania.

proceduralny vs deklaratywny

styl proceduralny, w którym piszesz kod określający krok po kroku, jak osiągnąć pożądany stan końcowy. Terraform, CloudFormation, SaltStack i Puppet zachęcają do bardziej deklaratywnego stylu, w którym piszesz kod określający pożądany stan końcowy, a samo narzędzie IAC jest odpowiedzialne za znalezienie sposobu osiągnięcia tego stanu.

na przykład, załóżmy, że chcesz wdrożyć 10 serwerów („instancje EC2” w żargonie AWS), aby uruchomić v1 aplikacji. Oto uproszczony przykład szablonu Ansible, który robi to za pomocą podejścia proceduralnego:

- ec2:
count: 10
image: ami-v1
instance_type: t2.micro

a oto uproszczony przykład szablonu Terraform, który robi to samo za pomocą podejścia deklaratywnego:

resource "aws_instance" "example" {
count = 10
ami = "ami-v1"
instance_type = "t2.micro"
}

teraz na powierzchni te dwa podejścia mogą wyglądać podobnie, a kiedy początkowo wykonasz je za pomocą Ansible lub Terraform, przyniosą one podobne rezultaty. Interesujące jest to, co się dzieje, gdy chcesz coś zmienić.

na przykład wyobraź sobie, że ruch wzrósł i chcesz zwiększyć liczbę serwerów do 15. W przypadku Ansible kod proceduralny, który napisałeś wcześniej, nie jest już przydatny;jeśli tylko zaktualizujesz liczbę serwerów do 15 i ponownie przeskanujesz ten kod, wdroży on 15 nowych serwerów, co daje łącznie 25! Więc zamiast tego, musisz być świadomy tego, co jest już wdrożone i napisać zupełnie nowy skrypt proceduralny, aby dodać 5 nowych serwerów:

- ec2:
count: 5
image: ami-v1
instance_type: t2.micro

za pomocą kodu deklaratywnego, ponieważ wszystko, co robisz, to deklarujesz żądany stan końcowy, a Terraform domyśla się, jak dostać się do tego stanu końcowego, Terraform będzie również wiedział o każdym stanie utworzonym w przeszłości. Dlatego, aby wdrożyć więcej 5 serwerów, wystarczy wrócić do tego samego szablonu Terraform i zaktualizować liczbę z 10 do 15:

resource "aws_instance" "example" {
count = 15
ami = "ami-v1"
instance_type = "t2.micro"
}

jeśli wykonasz ten szablon, Terraform zda sobie sprawę, że stworzył już 10 serwerów i dlatego jedyne, co musiał zrobić, to stworzyć 5 nowych serwerów. W rzeczywistości, przed uruchomieniem tego szablonu, możesz użyć polecenia Terraform plan, aby wyświetlić podgląd zmian, które wprowadzi:

$ terraform plan+ aws_instance.example.11
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.12
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.13
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.14
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.15
ami: "ami-v1"
instance_type: "t2.micro"Plan: 5 to add, 0 to change, 0 to destroy.

Co się stanie, gdy chcesz wdrożyć usługę v2? Przy podejściu proceduralnym oba poprzednie szablony Ansible ponownie nie są użyteczne, więc musisz napisać kolejny szablon, aby wyśledzić 10 serwerów, które wcześniej wdrożyłeś (a może było to 15 teraz?) i ostrożnie aktualizować każdy z nich do nowej wersji. Dzięki deklaratywnemu podejściu Terraform, wracasz do dokładnie tego samego szablonu i po prostu zmieniasz numer wersji ami na v2:

resource "aws_instance" "example" {
count = 15
ami = "ami-v2"
instance_type = "t2.micro"
}

oczywiście powyższe przykłady są uproszczone. Ansible pozwala na użycie tagów do wyszukiwania istniejących instancji EC2 przed wdrożeniem nowych (np. za pomocą instance_tags I count_tag), ale ręczne obliczanie tego rodzaju logiki dla każdego Zasobu, którym zarządzasz za pomocą Ansible, na podstawie historii każdego zasobu, może być zaskakująco skomplikowane (np. znajdowanie istniejących instancji nie tylko za pomocą znacznika, ale także wersji obrazu, strefy dostępności itp.). Wskazuje to na dwa główne problemy związane z narzędziami proceduralnymi IAC:

  1. w przypadku postępowania z kodeksem proceduralnym stan infrastruktury nie jest w pełni ujęty w Kodeksie. Przeczytanie trzech szablonów Ansible, które stworzyliśmy powyżej, nie wystarczy, aby wiedzieć, co zostało wdrożone. Musisz też znać kolejność, w jakiej zastosowaliśmy te szablony. Gdybyśmy zastosowali je w innej kolejności, moglibyśmy skończyć z inną infrastrukturą, a tego nie widać w samej bazie kodu. Innymi słowy, aby rozumować o kodzie Ansible lub Chef, musisz znać pełną historię każdej zmiany, która kiedykolwiek miała miejsce.
  2. możliwość ponownego użycia kodu proceduralnego jest z natury ograniczona, ponieważ musisz ręcznie wziąć pod uwagę aktualny stan bazy kodu. Ponieważ ten stan stale się zmienia, kod użyty tydzień temu może nie być już użyteczny, ponieważ został zaprojektowany w celu modyfikacji stanu infrastruktury, która już nie istnieje. W rezultacie podstawy Kodeksu proceduralnego z czasem stają się coraz większe i bardziej skomplikowane.

z drugiej strony, przy rodzaju deklaratywnego podejścia stosowanego w Terraform, kod zawsze reprezentuje najnowszy stan Twojej infrastruktury. Na pierwszy rzut oka możesz określić, co jest obecnie wdrożone i jak jest skonfigurowane, bez konieczności martwienia się o historię lub czas. Ułatwia to również tworzenie kodu wielokrotnego użytku, ponieważ nie musisz ręcznie uwzględniać aktualnego stanu świata. Zamiast tego skupiasz się na opisaniu pożądanego stanu, a Terraform wymyśla, jak automatycznie przejść z jednego stanu do drugiego. W rezultacie bazy kodów Terraform pozostają małe i łatwe do zrozumienia.

oczywiście są też wady języków deklaratywnych. Bez dostępu do pełnego języka programowania twoja siła ekspresji jest ograniczona. Na przykład niektóre rodzaje zmian w infrastrukturze, takie jak stopniowe wdrażanie bez przestojów, są trudne do wyrażenia w kategoriach czysto deklaratywnych. Podobnie, bez możliwości robienia „logiki” (np. if-statements, loops), tworzenie ogólnego kodu wielokrotnego użytku może być trudne (szczególnie w CloudFormation). Na szczęście Terraform dostarcza wiele potężnych elementów podstawowych, takich jak zmienne wejściowe, zmienne wyjściowe, Moduły, create_before_destroy I count, które umożliwiają tworzenie czystego, konfigurowalnego, modułowego kodu nawet w języku deklaratywnym. Omówimy te narzędzia bardziej w części 4, Jak tworzyć infrastrukturę wielokrotnego użytku z modułami Terraform i części 5, Wskazówki Terraform & tricks: loops, if-statements, and pitfalls.

Master kontra Masterless

domyślnie Chef, Puppet i SaltStack wymagają uruchomienia głównego serwera do przechowywania stanu infrastruktury i dystrybucji aktualizacji. Za każdym razem, gdy chcesz zaktualizować coś w swojej infrastrukturze, używasz klienta (np. narzędzia wiersza poleceń) do wydawania nowych poleceń do serwera głównego, a serwer główny albo wypycha aktualizacje na wszystkie inne serwery, albo te serwery regularnie pobierają najnowsze aktualizacje z serwera głównego.

serwer główny oferuje kilka zalet. Po pierwsze, jest to pojedyncze, centralne miejsce, w którym można zobaczyć i zarządzać statusem infrastruktury. Wiele narzędzi do zarządzania konfiguracją zapewnia nawet interfejs internetowy (np. konsola Chef, konsola Puppet Enterprise) dla głównego serwera, aby łatwiej było zobaczyć, co się dzieje. Po drugie, niektóre serwery główne mogą działać nieprzerwanie w tle i wymuszać konfigurację. W ten sposób, jeśli ktoś dokona ręcznej zmiany na serwerze, serwer główny może przywrócić tę zmianę, aby zapobiec dryfowi konfiguracji.

jednak konieczność uruchomienia serwera głównego ma poważne wady:

  • dodatkowa Infrastruktura: musisz wdrożyć dodatkowy serwer, a nawet klaster dodatkowych serwerów (dla wysokiej dostępności i skalowalności), aby uruchomić master.
  • Konserwacja: musisz utrzymywać, aktualizować, tworzyć kopie zapasowe, monitorować i skalować główny (- e) serwer (- y).
  • Bezpieczeństwo: musisz zapewnić klientowi sposób komunikowania się z serwerami głównymi i sposób komunikowania się z innymi serwerami, co zazwyczaj oznacza otwarcie dodatkowych portów i skonfigurowanie dodatkowych systemów uwierzytelniania, z których wszystkie zwiększają powierzchnię dla atakujących.

Chef, Puppet i SaltStack mają różne poziomy wsparcia dla trybów masterless, w których po prostu uruchamiasz ich oprogramowanie agenta na każdym z serwerów, zazwyczaj zgodnie z okresowym harmonogramem (np. zadanie cron, które działa co 5 minut) i używaj go do ściągania najnowszych aktualizacji z kontroli wersji (zamiast z głównego serwera). To znacznie zmniejsza liczbę ruchomych części, ale, jak omówiono w następnej sekcji, nadal pozostawia wiele pytań bez odpowiedzi, szczególnie o tym, jak zapewnić serwery i zainstalować na nich oprogramowanie agenta.

Ansible, CloudFormation, Heat i Terraform są domyślnie pozbawione masterless. Aby być dokładniejszym, niektóre z nich mogą polegać na serwerze głównym, ale jest to już część używanej infrastruktury, a nie dodatkowy element, którym musisz zarządzać. Na przykład Terraform komunikuje się z dostawcami chmury za pomocą interfejsów API dostawcy chmury, więc w pewnym sensie serwery API są serwerami głównymi, z tym że nie wymagają żadnej dodatkowej infrastruktury ani dodatkowych mechanizmów uwierzytelniania (tj. po prostu użyj kluczy API). Ansible działa poprzez bezpośrednie połączenie z każdym serwerem przez SSH, więc ponownie nie musisz uruchamiać żadnej dodatkowej infrastruktury ani zarządzać dodatkowymi mechanizmami uwierzytelniania (np.

Agent kontra Bezagentowy

Chef, Puppet i SaltStack wymagają zainstalowania oprogramowania agenta (np. Agent zazwyczaj działa w tle na każdym serwerze i jest odpowiedzialny za
instalowanie najnowszych aktualizacji zarządzania konfiguracją.

ma to kilka wad:

  • Bootstrapping: Jak zaopatrzyć swoje serwery i zainstalować na nich oprogramowanie agenta? Niektóre narzędzia do zarządzania konfiguracją kopią puszkę w dół drogi, zakładając, że jakiś zewnętrzny proces zajmie się tym za nich (np. najpierw używasz Terraform do wdrażania kilku serwerów z obrazem maszyny Wirtualnej, który ma już zainstalowany agent); Inne narzędzia do zarządzania konfiguracją mają specjalny proces rozruchowy, w którym uruchamiasz jednorazowe polecenia, aby udostępnić serwery za pomocą interfejsów API dostawcy chmury i zainstalować oprogramowanie agenta na tych serwerach przez SSH.
  • Konserwacja: Musisz okresowo aktualizować oprogramowanie agenta, uważając, aby było zsynchronizowane z serwerem głównym, jeśli taki istnieje. Musisz także monitorować oprogramowanie agenta i ponownie go uruchomić, jeśli ulegnie awarii.
  • bezpieczeństwo: Jeśli oprogramowanie agenta usunie konfigurację z serwera głównego (lub innego serwera, jeśli nie używasz serwera głównego), musisz otworzyć porty wychodzące na każdym serwerze. Jeśli serwer główny wypycha konfigurację do agenta, musisz otworzyć porty przychodzące na każdym serwerze. W obu przypadkach musisz dowiedzieć się, jak uwierzytelnić agenta na serwerze, z którym rozmawia. Wszystko to zwiększa powierzchnię do napastników.

Po raz kolejny Chef, Puppet i SaltStack mają różne poziomy wsparcia dla trybów bezagentowych (np. salt-ssh), ale często czują się one tak, jakby były podłączone jako afterthought i nie zawsze obsługują pełny zestaw funkcji narzędzia do zarządzania konfiguracją. Dlatego w środowisku naturalnym domyślna lub idiomatyczna konfiguracja kucharza, pacynki i saletry prawie zawsze zawiera agenta, a zazwyczaj także mistrza.

wszystkie te dodatkowe ruchome części wprowadzają wiele nowych trybów awarii do Twojej infrastruktury. Za każdym razem, gdy otrzymasz raport o błędzie o 3 nad ranem, będziesz musiał dowiedzieć się, czy jest to błąd w kodzie aplikacji, kodzie IAC, kliencie zarządzania konfiguracją, serwerze głównym lub sposobie, w jaki klient rozmawia z serwerem głównym lub sposobem, w jaki Inne Serwery rozmawiają z serwerem głównym lub…

Ansible, CloudFormation, Heat i Terraform nie wymagają instalacji żadnych dodatkowych agentów. Aby być dokładniejszym, niektóre z nich wymagają agentów, ale zazwyczaj są one już zainstalowane jako część używanej infrastruktury. Na przykład AWS, Azure, Google Cloud i wszyscy inni dostawcy chmury zajmują się instalowaniem, zarządzaniem i uwierzytelnianiem oprogramowania agenta na każdym ze swoich serwerów fizycznych. Jako użytkownik Terraform nie musisz się tym martwić: po prostu wydajesz polecenia, a agenci dostawcy chmury wykonują je za ciebie na wszystkich Twoich serwerach. Z Ansible, twoje serwery muszą uruchamiać
demona SSH, który i tak jest często uruchamiany na większości serwerów.

duża społeczność vs mała społeczność

ilekroć wybierzesz technologię, wybierasz również społeczność. W wielu przypadkach ekosystem wokół projektu może mieć większy wpływ na Twoje doświadczenia niż nieodłączna jakość samej technologii. Społeczność określa, ile osób przyczynia się do projektu, ile wtyczek,
integracji i rozszerzeń jest dostępnych, jak łatwo jest znaleźć pomoc online (np. posty na blogu, pytania na temat StackOverflow) i jak łatwo jest zatrudnić kogoś, kto ci pomoże (np. pracownika, konsultanta lub firmę wsparcia).

trudno jest dokonać dokładnego porównania między społecznościami, ale można zauważyć pewne trendy, wyszukując w Internecie. Poniższa tabela pokazuje porównanie popularnych narzędzi IAC z danymi zebranymi w maju 2019 r., w tym czy narzędzie IAC jest open source czy closed source, jakich dostawców chmury obsługuje, całkowitą liczbę współpracowników i gwiazdek na GitHub, liczbę commitów i aktywnych spraw w ciągu jednego miesiąca od połowy kwietnia do połowy maja, liczbę bibliotek open source dostępnych dla tego narzędzia, liczbę pytań wymienionych dla tego narzędzia na StackOverflow oraz liczbę zadań, które wspominają o narzędziu na GitHub. Indeed.com.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *