top of page

Śledź nasze wpisy w social media

  • Instagram
  • Facebook
  • Twitter
  • LinkedIn
  • YouTube
  • Zdjęcie autoraPiotr Kośka

Infrastruktura w Kodzie (IaaC) - Trochę o zmiennych i elastyczność naszego modułu - część 5

Za nami już cztery cześci o terraform mojego autorstwa o których przeczytasz tu:

A w tym artykule spotykamy się po raz piąty - i porozmawiamy sobie o zmiennych i zobaczymy jak dobre zaplanowanie naszego modułu pozwoli nam skonfigurować nasze środowisko developerskie i produkcyjne na podstawie tego samego modułu. Poprzez nadpisywanie zmiennych. Zatem zapraszam materiał do poczytania i obejrzenia.



Małe zmiany by uzyskać elastyczność


Finalna konfiguracja z części czwartej pozwala nam utworzyć projekt w DigitalOcean (taki byt w DigitalOcean według, którego można organizować "grupować" swoje zasoby) do tego projektu podpinamy strefe DNS. Tworzymy też VPC - czyli naszą sieć poprzez deklaracje adresu sieciowego dla regionów dostępnych w digitalocean - obecnie jest ich czternaście na czas pisania tego artykułu. Koncepcyjnie dla projektu przyjąłem sieć 10.X.0.0/16 i podzieliłem ją na pod sieć 10.X.0.0/20. Pozwoliło mi to pokryć każdy region i pozostawiło mi jeszcze dodatkowe dwa adresy sieci dla moich podsieci jako rezerwowe.


Gdybym chciał bazując na tej konfiguracji stworzyc nowy projekt - czyli wykorzystać utworzony moduł. Byłoby to problematyczne ponieważ dużo wartości konfiguracyjnych zdefiniowałem jako stałe wpisy. Postarajmy się przerobić naszą konfiguracje tak by udało się elastycznie tworzyć drugie środowisko w naszym terraform na DigitalOcean.


Zacznijmy od zasobu projekt w naszej konfiguracji. Plik procject.tf prezentuje się następująco:



Będziemy musieli dodać tak jak to jest w polu name odwołanie do naszej zmiennej która, będzie wstawiać właściwą wartość w odpowiednim polu. Dodajmy zatem naszą odpowiednią zmienną:


variable "digitalocean_project" {
    description = ""
    type = object({
        name = string
        description = string
        purpose = string
        environment = string
    })
    default = {
      description = "Project for YouTube Channel"
      environment = "development"
      name = "YoutubeProject"
      purpose = "Learning"
    }
}

Zmienna już dekralowaliśmy więc nie jest to dla nas jakaś nowość. Nowością może być fakt że nasze wartości które opisują projekt są w jednej zmiennej obiektowej z odpowiednimi własnościami. Deklarując taką zmienną w:


  • type - wpisujemy rodzaj naszej zmiennej, tym razem będzie ona typu obiektowego co pozwoli nam zdefiniować dodatkowe pola i określić typ tych pól. I mamy tu name, description, purpose, environment typu string.

  • default - tu możemy jak poprzednio zdefiniować wartości domyślne dla naszych zmiennych, tak by zabezpieczyć się przed tym jakby, ktoś podczas importowania/używania naszego modułu nie wskazał wartości dla tych zmiennych.

Odwołanie teraz do tych zmiennych też już znamy. Dochodzi tutaj tylko aspekt jak odwołać się do poszczególnych wartości w tym obiekcie. Możemy to zrobić za pomocą kropki - czyli:


  • var.digitalocean_project.name

Po wprowadzeniu zmiany nasz zasób będzie wyglądał następująco:


resource "digitalocean_project" "youtube-project" {
  name = var.digitalocean_project.name
  description = var.digitalocean_project.description
  purpose = var.digitalocean_project.purpose
  environment = var.digitalocean_project.environment
}

Możemy już teraz sprawdzić poprzez polecenie terraform plan czy nasza modyfikacja nie wprowadza żadnych zmian w stanie naszego terraforma. Pamiętamy że, w stanie terraform nie są przechowywane zmienne tylko juz wartości tych zmiennych, zatem terraform plan powinien pokazać że nie ma żadnych zmian:



Teraz możemy te zmienne użyć w naszym module - a dokładnie w jego deklaracji w pliku main.tf - może to wygladać tak:


module "digitalocean-youtube" {
  source = "./modules/digitalocean/youtube-do"
  providers = {
    digitalocean = digitalocean.youtube-do
  }
  
  digitalocean_project = {
    name = "YoutubeProject"
    description = "Project for YouTube Channel"
    purpose = "Learning"
    environment = "development"
  }
}

Zatem widzimy i wcześniej już to pokazywałem przez deklaracje naszego modułu możemy nadpisywać zadeklarowane zmienne - lub podawac ich wartości jeżeli nasze zmienne były by bez wartości default. Znów uruchomienie terraform plan nic nie zmieni - bo stan zgadza się z tym co jest w naszym backend ze stanem terraform.



Możemy też gdybyśmy chcieli zmienić te wartości sprawdzic jak sie zachowa nasz terraform plan gdy taka zamianę testowo wprowadzimy do naszego pliku konfiguracyjnego.



Terraform wykrywa zmiany i jak widzimy modyfikuje te wartości które zmieniamy - reszta pozostaje bez zmian i po stronie digitalocean odbywa to się w formie modyfikacji zasobu nie jego usunięcia. Bo i takie modyfikacje sie zdarzają by coś zmienić trzeba zasób najpierw usunąć a potem go dodać na nowo. Oczywiście terraform to robi automatycznie i nasz w podsumowaniu planu o tym informuje.


Poprawiamy VPC


Zmiana ta będzie zmiana dająca nam elastyczność również w przypadku tworzenia sieci. Obecnie tego nie mamy bo wartość adresu sieciowego tworzonego dla naszego regionu i danego VPC jest podawana na stałe.



Musimy zmodyfikować naszą wartość dla pola ip_range na taką by była generowana dynamicznie. Możemy się wzorować na tym co mamy w polu name dla tego zasobu - resource "digitalocean_vpc" "sfo1" {}.


Tu będziemy potrzebować dodatkowej zmiennej i musimy ją zadeklarować:


variable "secound_octet_number" {
    description = "value"
    type = string
    default = "0"
}

Po deklaracji jej w naszym pliku vars.tf - mozemy ja wykorzystać w naszej konfiguracji i pliku vpc.tf.

Przykład dla jednego regionu:



A tu dla kompletnego pokrycia wszystkich regionów:


resource "digitalocean_vpc" "nyc1" {
    name = "terraform-${var.type_env}-${var.name_env}-northamerica-nyc1-vpc"
    region = "nyc1"
    ip_range = "10.${var.secound_octet_number}.0.0/20"
}

resource "digitalocean_vpc" "nyc2" {
    name = "terraform-${var.type_env}-${var.name_env}-northamerica-nyc2-vpc"
    region = "nyc2"
    ip_range = "10.${var.secound_octet_number}.16.0/20"
}

resource "digitalocean_vpc" "nyc3" {
    name = "terraform-${var.type_env}-${var.name_env}-northamerica-nyc3-vpc"
    region = "nyc3"
    ip_range = "10.${var.secound_octet_number}.32.0/20"
}

resource "digitalocean_vpc" "sfo1" {
    name = "terraform-${var.type_env}-${var.name_env}-northamerica-sfo1-vpc"
    region = "sfo1"
    ip_range = "10.${var.secound_octet_number}.48.0/20"
}

resource "digitalocean_vpc" "sfo2" {
    name = "terraform-${var.type_env}-${var.name_env}-northamerica-sfo2-vpc"
    region = "sfo2"
    ip_range = "10.${var.secound_octet_number}.64.0/20"
}

resource "digitalocean_vpc" "sfo3" {
    name = "terraform-${var.type_env}-${var.name_env}-northamerica-sfo3-vpc"
    region = "sfo3"
    ip_range = "10.${var.secound_octet_number}.80.0/20"
}

resource "digitalocean_vpc" "tor1" {
    name = "terraform-${var.type_env}-${var.name_env}-northamerica-tor1-vpc"
    region = "tor1"
    ip_range = "10.${var.secound_octet_number}.96.0/20"
}

resource "digitalocean_vpc" "lon1" {
    name = "terraform-${var.type_env}-${var.name_env}-europe-lon1-vpc"
    region = "lon1"
    ip_range = "10.${var.secound_octet_number}.112.0/20"
}

resource "digitalocean_vpc" "ams2" {
    name = "terraform-${var.type_env}-${var.name_env}-europe-ams2-vpc"
    region = "ams2"
    ip_range = "10.${var.secound_octet_number}.128.0/20"
}

resource "digitalocean_vpc" "ams3" {
    name = "terraform-${var.type_env}-${var.name_env}-europe-ams3-vpc"
    region = "ams3"
    ip_range = "10.${var.secound_octet_number}.144.0/20"
}

resource "digitalocean_vpc" "fra1" {
    name = "terraform-${var.type_env}-${var.name_env}-europe-fra1-vpc"
    region = "fra1"
    ip_range = "10.${var.secound_octet_number}.160.0/20"
}

resource "digitalocean_vpc" "sgp1" {
    name = "terraform-${var.type_env}-${var.name_env}-asia-sgp1-vpc"
    region = "sgp1"
    ip_range = "10.${var.secound_octet_number}.176.0/20"
}

resource "digitalocean_vpc" "blr1" {
    name = "terraform-${var.type_env}-${var.name_env}-asia-blr1-vpc"
    region = "blr1"
    ip_range = "10.${var.secound_octet_number}.192.0/20"
}

resource "digitalocean_vpc" "syd1" {
    name = "terraform-${var.type_env}-${var.name_env}-australia-syd1-vpc"
    region = "syd1"
    ip_range = "10.${var.secound_octet_number}.208.0/20"
}

Mamy nasze VPC obsłużone - zostało nam jeszcze do modyfikacji lekkiej plik domain.tf tak by odwołać się do właściwej nazwy projektu w naszym data - będzie to dokładnie:


data "digitalocean_project" "youtube-project" {
    name = var.digitalocean_project.name
}

a całość prezentuje się w następujący sposób:


data "digitalocean_project" "youtube-project" {
    name = var.digitalocean_project.name
}

resource "digitalocean_project_resources" "domain" {
    project = data.digitalocean_project.youtube-project.id
    resources = [
        digitalocean_domain.dev-technicznie-nietechnicznie-cloud.urn
    ]
}

resource "digitalocean_domain" "dev-technicznie-nietechnicznie-cloud" {
    name = "${var.app_env}.technicznie-nietechnicznie.cloud"
}

I teraz kompletny plik main.tf


module "digitalocean-youtube" {
  source = "./modules/digitalocean/youtube-do"
  providers = {
    digitalocean = digitalocean.youtube-do
  }
  
  digitalocean_project = {
    name = "YoutubeProject"
    description = "Project for YouTube Channel"
    purpose = "Learning"
    environment = "development"
  }

  type_env = "development"
  secound_octet_number = "1"
  name_env = "youtube"
  app_env = "dev"
}

Sprawdzamy i znów terraform plan nie pokazuje żadnych zmian. Czas zatem je wprowadzić w postaci uruchomienia nowego projektu na podstawie naszego moduły. Plik main.tf bedzie wyglądał nastepująco:


module "myovh" {
    source = "./modules/myovh"
}

module "digitalocean-youtube" {
  source = "./modules/digitalocean/youtube-do"
  providers = {
    digitalocean = digitalocean.youtube-do
  }
  
  digitalocean_project = {
    name = "YoutubeProject"
    description = "Project for YouTube Channel"
    purpose = "Learning"
    environment = "development"
  }

  type_env = "development"
  secound_octet_number = "1"
  name_env = "youtube"
  app_env = "dev"
}

module "digitalocean-youtube2" {
  source = "./modules/digitalocean/youtube-do"
  providers = {
    digitalocean = digitalocean.youtube-do
  }
  
  digitalocean_project = {
    name = "ProdYoutubeProject"
    description = "Project for YouTube Channel"
    purpose = "Learning"
    environment = "production"
  }

  type_env = "production"
  secound_octet_number = "2"
  name_env = "newyoutube"
  app_env = "prod"
}

Sprawdźmy zatem ile i jakie zmiany dokonają się w naszym stanie i na naszym DigitalOcean. wydajemy polecenie terraform init i potem terraform plan


Jak widzimy w podsumowaniu zostanie dodanych siedemnaście zasobów w digitalocean jako nowe - czyli nasz poprzedni moduł i utworzone zasoby nie zostaną w żaden sposób zmodyfikowane. Możemy teraz to zweryfikować po stronie DigitalOcean i pokaże nam się nowy projekt:



W projekcie nowo utworzonym widzimy że, nasza domena została prawidłowo podpieta



I sieci zostały po tworzone dla naszych regionów - vpc nie mozna przypisac do projektu dlatego widoczne są też te wcześniej tworzone dla poprzedniego modułu w terraform.



Jak widać wszystko działa i zachowuje się według ustalonej konfiguracji. W tym artykule to wszystko. Daj znać czy taka seria Ci się podoba. Pozdrawiam.

121 wyświetleń0 komentarzy

Śledź nasze wpisy w social media

  • Instagram
  • Facebook
  • Twitter
  • LinkedIn
  • YouTube

Poznaj terraform jedno z najepszych narzedzi do zarządzania infrastrukturą w kodzie (IaC) - w kursie tym przeprowadzam Cię przez proces instalacji i konfiguracji tego narzędzia.

bottom of page