Рубрики
Uncategorized

Что я узнал, изучая Terraform: часть 5

Серия Terraform Часть 1: Введение Часть 2: Создание сервера Часть 3: обеспечение … Tagged IAC, Terraform, DevOps, Tuperial.

Серия терраформ

  • Часть 1: Введение
  • Часть 2: Создание сервера
  • Часть 3: обеспечение сервера
  • Часть 4: Управление государством Terraform
  • Часть 5: Чистый код с модулями Terraform
  • Часть 6: петли с терраформой
  • Часть 7: условные с терраформи
  • Часть 8: тестирование кода Terraform

До сих пор мы сосредоточились на предоставленной функциональности Terraform. Создание серверов, настройка настройки сети, настройка доменных имен, удаленно запустить сценарии Bash, создание единиц хранения и перемещение состояния Terraform в общее пространство.

В этом посте мы собираемся сделать перерыв и посмотреть, как мы можем написать чище, СУХОЙ Er, и многоразовый код Terraform. Основным ключевым словом здесь является «многоразовое», потому что этот пост в основном о модулях Terraform.

Модули являются ключевым ингредиентом для написания повторного использования, поддержания и проверки кода Terraform. [1]

Наличие модуля в Terraform Легко, потому что любой код Terraform, хранящийся в каталоге, рассматривается в одном и том же модуле. По тем же причинам мы также можем сказать, что модули в Terraform неявные, и именно поэтому создание модуля — это немного волшебство.

Давайте посмотрим на наши файлы Terraform, которые мы создали до сих пор:

  • Provider.tf : Определяет переменные SSH, используя Terraform для подключения к нашей капельке. Кстати, Provider.tf это довольно паршивое имя для этого файла.:-) Мы рефактируем это.
  • Domain.tf : Указывает наш домен на нашу каплю и определяет его запись CNAME.
  • Space.tf : Объявляет нашу хранение. Это ведро в AWS и пространство в цифро -точке Lingo.
  • main.tf : Настраивается в значительной степени то, что осталось, включая версию провайдера, удаленный бэкэнд и нашу любимую каплю.

Мы создали все эти файлы в одном и том же каталоге. Вот почему они все принадлежат к одному и тому же модулю Terraform. Теперь давайте разберем его, чтобы мы могли повторно использовать наш код, чтобы создать несколько капель, доступных к разным доменным именам. Таким образом, мы можем иметь инфраструктуру, поддерживающую как производственную, так и промежуточную среду. Мы собираемся оставить ведра и файлы отдаленного состояния из этой статьи, чтобы сделать вещи простыми.

Мы стремимся создать инфраструктуру как в производственной, так и в постановке. Мы собираемся создать их с помощью многоразовых модулей Terraform. После того, как мы преобразуем нашу кодовую базу, наша структура каталогов будет выглядеть следующим образом:

Позвольте мне сначала убрать одну вещь: Versions.tf Анкет Я использую Terraform v0.13, и вам нужно определить свой Требования поставщика Начиная с этой версии. Итак, все мои Versions.tf Файлы одинаковы:

terraform {
  required_providers {
    digitalocean = {
      source = "terraform-providers/digitalocean"
    }
  }
  required_version = ">= 0.13"
}

Структура каталога с модулями

Как я упоминал ранее, каждый каталог ведет себя как отдельный модуль. Я решил разделить свою инфраструктуру на два модуля: домен и сервер . Каждая из моих средств будет иметь свой сервер и другой домен, указывающий на этот сервер. Вот почему я создал каталог для каждого модуля под модули Анкет

Начнем с домен модуль. Я скопировал код из Domain.tf в модули/домен/main.tf :

resource "digitalocean_domain" "domain" {
  name       = var.domain_name
  ip_address = var.server_ipv4
}

resource "digitalocean_record" "cname_www" {
  domain = digitalocean_domain.domain.name
  type   = "CNAME"
  name   = "www"
  value  = "@"
}

Вы должны заметить изменение внутри Digitalocean_domain Ресурс: значения имя и ip_address больше не кодированы.

Модульные входы

Итак, я создал vars.tf Файл для определения переменных моего модуля:

variable "domain_name" {
  description = "Domain name like yourdomain.com"
  type        = string
}

variable "server_ipv4" {
  description = "Server's IP address where the domain should point to"
  type        = string
}

Теперь я могу использовать эти переменные в качестве входных данных в моем домен модуль. Всякий раз, когда мы используем домен Модуль, нам придется предоставить обе переменные для создания этого ресурса. Вот как мы сможем определить домен с разными доменными именами и отдельными IP -адресами, указывающими на разные серверы.

Теперь давайте перейдем к сервер модуль. Я снова скопировал свой код из моего старого main.tf Файл здесь:

resource "digitalocean_droplet" "server" {
  image  = "ubuntu-20-04-x64"
  name   = var.server_name
  region = "ams3"
  size   = var.server_size
  ssh_keys = [
    var.ssh_fingerprint
  ]

  connection {
    host        = self.ipv4_address
    user        = "root"
    type        = "ssh"
    private_key = file(var.ssh_private_key)
    timeout     = "2m"
  }

  provisioner "remote-exec" {
    inline = [
      "export PATH=$PATH:/usr/bin",
      # install nginx
      "sudo apt-get update",
      "sudo apt-get -y install nginx"
    ]
  }
}

Я создал vars.tf Файл для моего сервер Модуль также:

variable "server_name" {
  description = "The name of the server"
  type        = string
}

variable "server_size" {
  description = "The size of the server"
  type        = string
}

variable "ssh_fingerprint" {
  description = "Fingerprint of the SSH key that is allowed to connect to the server"
  type = string
}

variable "ssh_private_key" {
  description = "Private key of the SSH key that is allowed to connect to the server"
  type = string
}

Если мы передаем переменные SSH, вы увидите, что теперь мы сможем настроить имя сервера и размер сервера в этом модуле. Вот как мы сможем создать производственный сервер с большим размером, сохраняя при этом проставочный сервер в меньшем размере.

Теперь у нас есть оба домен и сервер модули, чтобы создать себя в среде. Начнем с производство . Вот как это выглядит, чтобы создать среду с нашими модулями в Производство/main.tf :

module "server" {
  source = "../modules/server"

  server_name     = "terraform-sandbox"
  server_size     = "s-1vcpu-1gb"
  ssh_fingerprint = var.ssh_fingerprint
  ssh_private_key = var.ssh_private_key
}

module "domain" {
  source = "../modules/domain"

  domain_name = "productiondomain.com"
  server_ipv4 = module.server.server_ipv4
}

Я собираюсь передать здесь переменные SSH, так как мы собираемся предоставить их в качестве аргументов командной строки. Как видите, мы объявляем имя и размер для сервер модуль. Точно так же мы даем имя для нашего домен модуль. Все в твердом кодировании сейчас. Однако server_ipv4 Аргумент для домен Модуль выглядит немного странно, не так ли?:-)

Выходы модуля

Что вы видите как module.server.server_ipv4 это использование выходов модуля. Мы изолировали наш домен и сервер модули, но домен Конфигурация требует сервер S IP -адрес. Мы можем получить доступ к значениям модуля, определив вывод в этом модуле. Вот содержание модули/сервер/outs.tf :

output "server_ipv4" {
  value = digitalocean_droplet.server.ipv4_address
}

Определяя server_ipv4 Вывод, мы предоставляем модуль пользовательский доступ к Digitalocean_droplet Ресурс ipv4_address Аргумент внутри сервер пример. Точно так же мы получаем доступ к выводу, следуя этой структуре:

module.MODULE_NAME.OUTPUT_NAME

В нашем случае это становится:

module.server.server_ipv4

Таким образом, Terraform сначала создаст сервер, а затем использует его IP -адрес для настройки нашего домена.

Модуль местные жители

Помимо входов и выходов, Terraform предоставляет другую структуру данных, чтобы сделать нашу кодовую базу сухой. Вместо входов и выходов мы не используем местных жителей между модулями. Их использование ограничено инкапсуляциями локальных значений, так же, как константы в языках программирования, но только в одном и том же модуле.

Например, вместо жесткого кодирования изображения и региона нашего сервера давайте инкапсулируем их в модули/сервер/vars.tf :

locals {
  server_image = "ubuntu-20-04-x64"
  server_region = "ams3"
}

Тогда мы можем пойти дальше и использовать их в нашем модули/сервер/main.tf файл:

resource "digitalocean_droplet" "server" {
  image  = local.server_image
  name   = var.server_name
  region = local.server_region
  size   = var.server_size
  ssh_keys = [
    var.ssh_fingerprint
  ]

# ...

Я просто хотел сделать небольшую записку здесь и сказать, что все три структуры не являются уникальными для модулей. Как вы можете себе представить, модули являются неявными структурами. В теоретическом смысле это было бы правдой, если бы мы сказали, что мы также можем использовать входные данные, выходы и местных жителей за пределами контекста модуля. Хотя каждое из использования практически подпадает под использование модуля, поскольку каждый каталог в Terraform является модулем.

[1]: Terraform Up & Running: написание инфраструктуры как код Евгения Брикмана (2 -е издание)

Фотография обложки от Андрей Лишаков

Часть 4 …………………………………………………………………………………………….. Часть 6

Оригинал: «https://dev.to/gzg/what-i-ve-learned-learning-terraform-part-5-j4b»