Terraform i vCloud Director

Nasze przygody z vCD prowadzą nas w różne ścieżki. Ostatnia zawiodła nas w gęstwiny Terraform i współpracy tegoż kodera API z produktami VMware. Skoro to czytasz to wydaje mi się, że nie trzeba ci wyjaśniać czym Terraform jest. Jednakże dla porządku, coś tam trzeba o nim napomknąć. W żołnierskich słowach: Terraform jest platformą do automatycznego powoływania infrastruktury poprzez kod. Jest to przydatne narzędzie gdy od klikacza w GUI chcemy się rozwinąć do pisarza w CLI.

Pozwolę sobie na standardową dygresję, bo czymże byłaby opowieść bez klasycznej dygresji. Wahadło – bo ono przeszło mi przez głowę, reprezentuje w zasadzie nieskończony ruch z jednej strony na drugą. Wehikuł ten stanął mi przed oczami gdy pisząc powyższy akapit pomyślałem o tym, że dawno, dawno temu koszerne było łupanie wszystkiego w konsoli. Wiecie lata 90 – Slackware, Gentoo, PLD. Tam w zasadzie nic się nie dało zrobić via GUI, lub proces dotarcia do tego GUI był tak żmudny, że tylko nieliczni mogli się grzać w blasku KDE czy Gnome. Później wahadło wychyliło się w drugą stronę – autorskie, wyklepane skrypty stały się passse, a świat poszedł w stronę okienek, standaryzacji itp. Następnie nieskończony ruch znów uderzył na inną stronę. I nastąpił wielki powrót do kodu… bo okazało się, że klikanie jak małpa po GUI tysiąc razy tego samego nie ma większego sensu z perspektywy zachowania energii. Oczywiście każdy kolejny wychył wahadła nie wciągał nas w piekło poprzedniego cyklu, a jedynie w jego kolejną odsłonę, zazwyczaj lepszą i bogatszą o doświadczenia z poprzednich iteracji. Zatem kod teraz, a kod 20 lat temu to trochę inne rzeczy. Tak samo narzędzia – kiedyś toporne i trudne do opanowania, teraz jakby złagodniały, dojrzały i pozwalają, co bywa zaskakujące, czerpać niezwykłą przyjemność z pisania.

Tak jak wspominałem, nie będę przepisywał poradnika ze strony Terraform wyjaśniającego co jest czym, a skupię się na prostym przykładzie użycia. Generalnie co tu dużo gadać – coś tam napisaliśmy, znajdziecie nasze wytwory tutaj – https://github.com/inleo-pl/Terraform-vCloud-Director. Jest to kilka przydatnych i w pełni działających skryptów, dzięki którym możemy powołać:

  1.  Organizację
  2. vDC w modelu Allocation
  3.  vDC w modelu Pay as you go
  4. NSX Edge organizacji wraz z dopięciem do standardowej sieci external
  5. Oraz kombos tych 4 powyższych robiący 1 organizację, 2 vDC i jednego Edge

Trzeba przyjąć, że skrypty te są bazą i można je różnorako rozbudowywać/przerabiać, aby osiągnąć konkretny cel. Aby zobrazować Wam jak działa Terraform z vCD, zrealizujemy scenariusz w którym założymy Organizację klienta, a w niej dwa vDC (jedno typu Allocation, drugie PaYG) oraz jeden Edge podpięty do External Network. Zakładamy oczywiście, że Twoje środowisko vCloud Director jest w pełni skonfigurowane (wraz z NSX) oraz masz uprawnienia administratora na poziomie Provider.

Zacznijmy od pobrania skryptów bazowych:

git clone https://github.com/inleo-pl/Terraform-vCloud-Director.git

Teraz przejdźmy do katalogu ze skryptem:

cd Terraform-vCloud-Director/1org-2vdc-1edge/

Znajdują się tutaj 3 pliki:

main.tf variables.tf terraform.tfvars

Pierwszy zawiera wszelkie funkcje, które będą odpowiedzialne za tworzenie naszej infrastruktury. Drugi opisuje zmienne, które użyte są w pliku main.tf. Trzeci określa wartości tych zmiennych. Na początku skupmy się na pierwszym pliku, który rozpoczyna się od:

provider "vcd" { user = var.vcd_user password = var.vcd_pass org = var.vcd_org url = var.vcd_url max_retry_timeout = var.vcd_max_retry_timeout allow_unverified_ssl = var.vcd_allow_unverified_ssl }

Definiujemy tutaj providera, czyli blok kodu mówiący dla Terraform co będziemy wykorzystywać do tworzenia infrastruktury. W naszym przypadku jest to oczywiście vCD. Dalej sprawa wydaje się naturalna – użytkownik, hasło, url itd. Wszystkie niezbędne szczegóły znajdziecie tutaj https://www.terraform.io/docs/providers/vcd/index.html. Każde z pól opisywane jest zmienną zdefiniowaną w pliku variables.tf, a później określonej wartością w pliku terraform.tfvars. O tym jednak za chwilę, na razie zauważcie jak się odnosimy do tych zmiennych – przed nazwą zmiennej należy wstawić var np.: var.vcd_org.

Przejdźmy dalej:

resource "vcd_org" "my-vcd-org" { name = var.vcd_org_name full_name = var.vcd_org_full_name can_publish_catalogs = "false" is_enabled = "true" delete_force = "true" delete_recursive = "true" }

Powyższy fragment odpowiada za zdefiniowanie organizacji klienta w vCD (https://www.terraform.io/docs/providers/vcd/r/org.html). Sprawa ma się podobnie jak z połączeniem – mamy wartości, które są samo wyjaśniające się, oraz zmienne. Różnica tutaj na pewno jest zauważalna przy np. is_enabled = “true”, gdzie is_enable przyjmuje wartość bool. Należy zatem nadać jej wartość albo true albo false. Trzeba ją podawać małymi literami w cudzysłowach. Kolejnym etapem jest zdefiniowane vDC w stworzonej właśnie organizacji (https://www.terraform.io/docs/providers/vcd/r/org_vdc.html).  Na początek organizacji typu Allocation:

resource "vcd_org_vdc" "my-vdc-alloc" { name = var.vcd_org_vdc_alloc_name description = var.vcd_org_vdc_alloc_description org = var.vcd_org_name allocation_model = "AllocationPool" network_pool_name = var.vcd_org_vdc_alloc_network_pool_name provider_vdc_name = var.vcd_org_vdc_alloc_provider_vdc_name compute_capacity { cpu { allocated = var.vcd_org_vdc_alloc_compute_capacity_cpu } memory { allocated = var.vcd_org_vdc_alloc_compute_capacity_memory } } storage_profile { name = var.vcd_org_vdc_alloc_storage_profile_name limit = var.vcd_org_vdc_alloc_storage_profile_limit default = true } metadata = { metatag-01 = "Value of Metatag 01." metatag-02 = "Value of Metatag 02." } enabled = true enable_thin_provisioning = true enable_fast_provisioning = false delete_force = true delete_recursive = true }

Jadąc od góry – nazwa, opis są w miarę oczywiste. Następnie mamy vcd_org_name, które pozwala na zdefiniowanie w której organizacji będzie stworzone vDC. Kolejnym elementem jest Allocation Model, tutaj mamy do wyboru:

  • AllocationVApp zwane również Pay as you go
  • AllocationPool
  • ReservationPool

Po wyborze rodzaju vDC następuję cześć dot. ustawienia alokacji i limitów itp. dla CPU i Pamięci. Należy ustawiać w MB i MHz. Kolejnym etapem jest ustawienie Storage Profile, z tego co udało mi się zrobić, można niestety ustawić tylko jeden SP podczas uruchamiania. Parametr name musi mieć dokładnie taką samą nazwę co zdefiniowany w vCD. Limit podaje się w Mb. Dalej ustawiamy metatagi o ile są potrzebne i inne ustawienia, które mogą być przydatne np. wyłączenie fast provisioning. Analogicznie działamy z PaYG:

resource "vcd_org_vdc" "my-vdc-payg" { name = var.vcd_org_vdc_payg_name description = var.vcd_org_vdc_payg_description org = var.vcd_org_name allocation_model = "AllocationVApp" network_pool_name = var.vcd_org_vdc_payg_network_pool_name provider_vdc_name = var.vcd_org_vdc_payg_provider_vdc_name compute_capacity { cpu { limit = 0 } memory { limit = 0 } } storage_profile { name = var.vcd_org_vdc_payg_storage_profile_name limit = var.vcd_org_vdc_payg_storage_profile_limit default = true } metadata = { metatag-01 = "Value of Metatag 01." metatag-02 = "Value of Metatag 02." } enabled = true enable_thin_provisioning = true enable_fast_provisioning = false delete_force = true delete_recursive = true }

Zasadniczą różnicą jest wybrany inny model oraz definicja zasobów jako unlimited. Reszta w zasadzie pozostaje taka sama. Ostatnim krokiem jest stworzenie Edge:

resource "vcd_edgegateway" "org-edge" { org = var.vcd_org_name vdc = var.vcd_org_vdc_alloc_name name = var.vcd_edgegateway_name description = var.vcd_edgegateway_description configuration = var.vcd_edgegateway_configuration advanced = true external_network { name = "Internet" subnet { ip_address = var.vcd_edgegateway_ip gateway = var.vcd_edgegateway_gateway_ip netmask = var.vcd_edgegateway_netmask_ip use_for_default_route = true } } }

Podajmy organizację do jakiej ma należeć serwer Edge, a później vDC. Edge jest maszyną wirtualną, więc z perspektywy vCD musi działać w kontekście jakiegoś vDC. Wybrałem vDC Allocation, ale można to ustawić również na PaYG. Później ustawiamy nazwę Edge, opis i konfigurację jedną z 4 poniższych:

  • Compact
  • Full
  • X-large
  • Full4

Następnie aby mieć funkcję np. Load balancera, Mikrosegemntacji itp. uruchamiamy go w trybie advanced, oraz dopinamy do External Network o nazwie „Internet” gdzie ustawiamy niezbędne adresacje IP.

Plik variables.tf zawiera definicje zmiennych, przyjrzyjmy się jednej z nich:

variable "vcd_user" { description = "Username of admin account." default = "administrator" }

Podczas jej definiowania ustawimy nazwę, opis oraz ewentualnie wartość domyślną. Generalnie jest tutaj kilka zmiennych, które definiują, że dostajemy się na poziomie administratora. Pierwsza to ta przedstawiona w bloku kodu powyżej, druga to vcd_org, która musi mieć wartość „System” aby dostać się do providera. Reszta zdefiniowana jest już w pliku terrafrom.tfvars:

vcd_pass="CemeteryPolk@" vcd_url="https://your.vcd.com/api" vcd_org_name="Cemetery Polka" vcd_org_full_name="Uncle Vernon, Uncle Vernon, independent as a hog on ice." vcd_org_vdc_alloc_name="vDC-Alloc" vcd_org_vdc_alloc_description="vDC-Alloc for Cemetery Polka" vcd_org_vdc_alloc_compute_capacity_cpu="1000" vcd_org_vdc_alloc_compute_capacity_memory="1000" vcd_org_vdc_alloc_network_pool_name="" vcd_org_vdc_alloc_provider_vdc_name="Provider-vDC" vcd_org_vdc_alloc_storage_profile_name="SSD" vcd_org_vdc_alloc_storage_profile_limit="1024" vcd_org_vdc_payg_name="vDC-PaYG" vcd_org_vdc_payg_description="vDC-PaYG for Cemetery Polka" vcd_org_vdc_payg_network_pool_name="" vcd_org_vdc_payg_provider_vdc_name="Provider-vDC" vcd_org_vdc_payg_storage_profile_name="SSD" vcd_org_vdc_payg_storage_profile_limit="1024" vcd_edgegateway_name="Org-Edge" vcd_edgegateway_description="The org edge." vcd_edgegateway_configuration="compact" vcd_edgegateway_ip="192.168.1.2" vcd_edgegateway_gateway_ip="192.168.1.1" vcd_edgegateway_netmask_ip="255.255.255.0"

Myślę, że nie trzeba zbyt mocno go tłumaczyć, zdaje się być w miarę oczywisty. Mamy nazwę zmiennej i jej wartość. Co ważne, jak nie wpiszemy w ten plik wartości zmiennej, to Terraform poprosi nas o nią podczas uruchamiania deploy.

Nie ma co rozprawiać – czas uruchamiać. Na początku zainicjujmy TF komendą:

terraform init

Komenda ta zassie i zainstaluje niezbędne moduły do obsługi zdefiniowanego w main.tf providera. Następnie aby uruchomić nasz skrypt wpisujemy:

terraform plan

Który przetestuje nam pliki na sucho i na końcu:

terraform apply

Teraz dzieje się magia. Jak wszystko się powiedzie, to powinniście zobaczyć po stronie vCD nową organizację a w niej dwa vDC wraz z NSX Edge. Może się zdarzyć, że skrypt się wywali z informacją, że nie znalazł organizacji aby powołać vDC, lub nie ma jeszcze vDC w którym ma być Edge. Dzieje się tak ponieważ Terraform powołuje zdefiniowane zasoby i nie sprawdza zależności. Można oczywiście te zależności poustawiać, ale do testów wystarczy skrypt uruchomić jeszcze raz – kiedy już wymagane zasoby się pojawią. Aby zwinąć infrastrukturę można użyć komendy:

terraform destroy

Terraform wywali wszystko… więc to dzięki stworzonemu plikowi terraform.tfstate. Zatem aby mieć możliwość rollback nie należy go usuwać.

Na ten moment to tyle. Terraform ma bardzo duże możliwości, a dzisiejszy przykład dotyka czubka góry lodowej. Tymczasem miłego deployowania, a ja myślę, że na pewno się ono pojawi na łamach naszego bloga.