Infrastructure as Code

Zarządzanie serwerami - Infrastructure as Code

W agencji drupalowej, jaką jest Droptica, bardzo ważną rolę odgrywają serwery, na których hostujemy tworzone przez nas serwisy. Wdrażając w firmie Infrastructure as Code, udało nam się zwiększyć stabilność i dostępność usług oraz zoptymalizować czas niezbędny na wprowadzanie zmian w infrastrukturze. Automatyczne zarządzanie serwerami zdecydowanie uprościło kilka naszych procesów.

Infrastructure as Code - o co chodzi?

Jeszcze do niedawna większość firm działających w sektorze IT i świadczących usługi związane z WWW musiała dysponować zapleczem serwerów, które wymagały sporej ilości przygotowań - między innymi instalacji w centrach danych, konfiguracji systemu operacyjnego, sieci, ustawienia mechanizmów zabezpieczeń i przygotowania do świadczenia usługi.

Jednak od paru lat ten trend się zmienia. Wszyscy jesteśmy obecnie świadkami rewolucji Cloud - rozwiązań gdzie potężni gracze na rynku przetwarzania danych oferują swoje niewykorzystane zasoby, najczęściej w postaci wirtualnych maszyn, które można przygotować za pomocą kilku kliknięć. W takim wypadku odchodzi cały proces przygotowania środowiska opartego o hardware, co samo w sobie już redukuje koszty. Jednak największą zaletą tego rozwiązania jest szybkość i łatwość przygotowania, którą dodatkowo można zautomatyzować przy pomocy udostępnianych przez dostawców API.

I tutaj właśnie pojawia się pojęcie Infrastructure as Code - paradygmatu, którego założeniem jest zdefiniowanie całego środowiska w postaci kodu, który poddany odpowiedniemu procesowi spowoduje przygotowanie opisanej nim infrastruktury. Takiego właśnie rozwiązania używamy na naszych platformach hostingowych Drupala.

Odpowiadając na pytanie “dlaczego wdrożyliśmy IaC w Droptica” - powodów jest wiele, ale najważniejsze z nich to:

  • przechowywanie stanu serwerów w repozytorium - to, co jest w kodzie, odzwierciedla stan faktyczny i w dodatku jest czytelne nie tylko dla administratorów;
  • możliwość powrotu do dowolnego momentu w historii - jeżeli kod przechowywany jest w repozytorium, to znamy całą historię zmian i możemy się pomiędzy nimi płynnie przełączać;
  • taką reprezentację można w łatwy sposób poddać walidacji i przetestować - technologie, z których korzystamy, dostarczają nam takie mechanizmy;
  • automatyzacja deploymentu, która jeszcze bardziej przyśpiesza przygotowanie i wdrożenie serwerów w środowisku produkcyjnym.

Jak się do tego zabrać?

Wdrożenie Infrastructure as Code w naszym przypadku sprowadziliśmy do dwóch kroków - znalezienia oprogramowania, które spełni założenia oraz przygotowanie kodu, który odzwierciedla środowisko.

W przypadku kroku pierwszego zdefiniowaliśmy dwa podstawowe warunki:

  • obsługa wielu platform Cloud - w Droptice nie ograniczamy się do jednego, konkretnego rozwiązania. Wciąż testujemy nowości na rynku, by oferować naszym klientom coraz ciekawsze i stabilniejsze rozwiązania (obecnie korzystamy z usług m.in. AWS, Digital Ocean oraz Linode).
  • niezmienność infrastruktury (ang. immutable infrastructure) - naszym celem jest przechowywanie faktycznego stanu środowiska w repozytorium, tak aby móc je odtworzyć w dowolnym momencie. Nie możemy zatem doprowadzić do sytuacji, gdzie do stanu infrastruktury wprowadzane są zmiany, które nie znalazły się wcześniej w kodzie - co jest praktyczną definicją paradygmatu immutable infrastructure. 

Wybór narzędzia

Na rynku dostępnych jest wiele narzędzi, które pozwalają wdrożyć Infrastructure as Code. W naszych rozważaniach braliśmy pod uwagę m.in. Ansible, Cloud Formation oraz Terraform, który ostatecznie zdecydowaliśmy się wykorzystać.

Wprawdzie głównym zadaniem Ansible nie jest orkiestracja środowiska, lecz zarządzanie konfiguracją, to posiada on moduły pozwalające na współpracę z usługami cloud computing. Takie rozwiązanie wydaje się bardzo praktyczne. W jednym repozytorium można utrzymywać zarówno kod odpowiedzialny za docelowy wygląd infrastruktury, jak i jej późniejszej konfiguracji. Jednak Ansible, w odróżnieniu od dwóch pozostałych, wykorzystuje proceduralny styl kodu, w którym krok po kroku określamy zadania do wykonania. W pewnych sytuacjach może to prowadzić do nieintuicyjnych zmian w kodzie, co pokazaliśmy to na poniższym przykładzie.

Uproszczony kod w Ansible, który stworzy 10 maszyn, wygląda tak:

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

I to samo, lesz napisane w Terraformie:

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


Po wykonaniu obu fragmentów osiągniemy ten sam rezultat - wygenerowane zostanie 10 wirtualnych serwerów w AWS. Co się jednak stanie, gdy zdecydujemy się zwiększyć ich liczbę do 15?

W przypadku Ansible nie mamy zapamiętanego stanu, więc zwiększenie liczby serwerów w kodzie do 15 spowoduje wygenerowanie dokładnie takiej ilości. Finalnie otrzymamy ich 25, dlatego ostatecznie w kodzie umieścić należy liczbę pięciu nowych maszyn:

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

CloudFormation i Terraform przechowują informację o obecnym stanie infrastruktury, tak więc zmiana jest kosmetyczna i o wiele bardziej intuicyjna:

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

Z tego też powodu nie zdecydowaliśmy się na użycie Ansibla. Cloud Formation odpadło z o wiele prostszego powodu - jest to narzędzie dedykowane dla AWS, nie spełnia zatem naszego pierwszego warunku - współpracy z wieloma dostawcami. 

Jak działa Terraform?

W tej części artykułu przedstawimy krótki poradnik praktyczny, który pozwala postawić pierwsze kroki w automatyzacji i wdrożeniu IaC. Skupimy się tutaj na Ubuntu, ponieważ z takiego środowiska korzystamy na co dzień w Droptica.

Instalacja

Na dziś Terraform nie znajduje się w oficjalnych repozytoriach Ubuntu / Debian, ale producent dostarcza gotowe paczki, które wystarczy wypakować i zainstalować.

wget https://releases.hashicorp.com/terraform/0.11.2/terraform_0.11.2_linux_amd64.zip
unzip terraform_0.11.2_linux_amd64.zip
cp terraform /usr/local/bin

Instalacja pluginów

Nie wszyscy dostawcy usług cloud są wspierani natywnie, m.in. w przypadku Linode i OVH niezbędne jest zainstalowanie pluginów. W większości przypadków procedury te są dobrze opisane w repozytoriach, podobnie jak w poniższych dwóch przypadkach:

Skompilowane pluginy wgrywa się do katalogu ~/.terraform.d/plugins.

Opisujemy pierwszy serwer

Używanie Terraforma jest naprawdę proste! Kod, który był pokazany wyżej, w pełni wystarczy,  żeby stworzyć pierwszą wirtualną maszynę w AWS, ale zajmijmy się nieco bardziej skomplikowanym zagadnieniem.

resource "aws_instance" "server-01" {
  ami               = "ami-0d77397e"
  availability_zone = "eu-west-1a"
  instance_type     = "t2.large"

  root_block_device {
    volume_type = "gp2"
    volume_size = "120"
    delete_on_termination = "true"
  }

  tags {
    Name = "server-01"
    Org  = "droptica"
  }
}

Powyższy przykład również doprowadzi do utworzenia nowego wirtualnego serwera o nazwie server-01 w AWS, precyzuje to rodzaj zasobu aws_instance. Następnie uzupełniamy niezbędne parametry (zdefiniowane w dokumentacji AWS):

  • ami - identyfikator obrazu (w tym przypadku Ubuntu Server 16.04);
  • availability_zone - region i strefa, w których serwer będzie utworzony;
  • Instance_type - typ i wielkość instancji.

W sekcji root_block_device specyfikujemy parametry dysku, który będzie związany z tą instancją - w tym przypadku jest to podstawowy typ - gp2, o rozmiarze 120 GB.

Uruchomienie kodu

Tak przygotowany kod jest gotowy do uruchomienia. Zanim jednak wdrożymy zmiany w środowisku docelowym, warto zapoznać się z listą kroków, które zostaną wykonane. Pozwoli to wykryć ewentualne błędy w kodzie, w tym celu wystarczy uruchomić polecenie:

$ terraform plan

w wyniku którego otrzymamy szczegółowe informacje na temat planowanych zmian w infrastrukturze:

> terraform plan
aws_instance.example: Refreshing state... (ID: i-6a7c545b)
(...)
~ aws_instance.example
   tags.%:    "0" => "2"
   tags.Name: "" => "server-01"
   tags.Org: "" => "droptica"
Plan: 1 to add, 0 to change, 0 to destroy.

Jeżeli wszystko się zgadza, nie pozostaje nic innego jak uruchomić wdrożenie i zatwierdzić zmiany:

terraform apply

Co dalej?

Sam opis maszyn to dopiero początek, usługi cloud computing są w tej chwili tak rozbudowane, że pozwalają na tworzenie dużo bardziej skomplikowanej architektury. W Droptice zdefiniowaliśmy m.in. sieć (zarówno publiczną, jak i prywatną), serwery utrzymujące nasze serwisy, bazy danych oraz load balancery - skrótowo ujmując stworzyliśmy platformę niezawodnego hostingu w oparciu o AWS.

Dla tych, którzy chcą zapoznać się ze wszystkimi możliwościami Terraforma, polecam dokumentację, a jeśli chcecie spróbować z nim swoich sił - oficjalny poradnik będzie idealnym punktem zaczepienia.
 

3. Najlepsze praktyki zespołów programistycznych