Частное облако OVH и HashiCorp Terraform - Часть 1

При обсуждении концепций DevOps и Infrastructure-as-a-Code быстро всплывают инструменты, разработанные HashiCorp. С Terraform HashiCorp предлагает простой способ автоматизации подготовки инфраструктуры как в общедоступных облаках, так и в локальной среде. Terraform имеет долгую историю развертывания и управления ресурсами публичного облака OVH. Например, вы можете найти полное руководство на GitHub. В этой статье мы сосредоточимся на использовании Terraform для взаимодействия с другим решением OVH: частным облаком.



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

Установка

Terraform доступен на веб-сайте HashiCorp практически для всех ОС в виде простого двоичного файла. Просто загрузите его и скопируйте в каталог в PATH вашей операционной системы. Чтобы проверить, что все работает правильно, запустите команду terraform.

$ terraform
Usage: terraform [-version] [-help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure


Папки и файлы

Как и другие инструменты «Инфраструктура как код», Terraform использует простые файлы для определения целевой конфигурации. Для начала мы создадим каталог и поместим файл с именем main.tf. По умолчанию Terraform будет читать все файлы в рабочем каталоге с .tfрасширением, но для упрощения мы начнем с одного файла. В следующей статье мы увидим, как организовать данные в несколько файлов.

Точно так же, чтобы было легче понять операции Terraform, мы укажем всю необходимую информацию прямо в файлах. Сюда входят имена пользователей, пароли и имена различных ресурсов (vCenter, кластер и т. Д.). Совершенно очевидно, что делать это не рекомендуется для использования Terraform в производстве. Вторая статья также даст возможность улучшить эту часть кода. Но пока давайте будем простыми!

Провайдеры

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

provider "vsphere" {
    user = "admin"
    password = "MyAwesomePassword"
    vsphere_server = "pcc-XXX-XXX-XXX-XXX.ovh.com"
}


Здесь мы видим, что Terraform использует свой собственный способ структурирования данных (также можно записать все в JSON, чтобы облегчить автоматическое создание файлов! ). Данные сгруппированы в блоки (здесь блок с именем vsphere, который относится к типу провайдера ), а данные, относящиеся к блоку, представлены в форме ключей / значений.

Данные

Теперь, когда Terraform может подключаться к vCenter, нам нужно получить информацию об инфраструктуре vSphere. Поскольку мы хотим развернуть виртуальную машину, нам нужно знать центр обработки данных, кластер, шаблон и т. Д. И где мы собираемся его создать. Для этого мы будем использовать блоки типа данных:

data "vsphere_datacenter" "dc" {
  name = "pcc-XXX-XXX-XXX-XXX_datacenter3113"
}

data "vsphere_datastore" "datastore" {
  name          = "pcc-001234"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_virtual_machine" "template" {
  name          = "UBUNTU"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}


В приведенном выше примере, мы пытаемся получить информацию о центре обработки данных с именем pcc-XXX-XXX-XXX-XXX_datacenter3113и получить информацию из хранилища данных с именем pcc-001234и шаблона, имя которого является UBUNTU. Здесь мы видим, что мы используем идентификатор центра обработки данных, чтобы получить информацию об объекте, связанном с ним.

Ресурсы

Ресурсы будут использоваться для создания и / или управления элементами инфраструктуры. В нашем примере мы будем использовать ресурс типа virtual_machine, который, как следует из названия, поможет нам создать виртуальную машину.

resource "vsphere_virtual_machine" "vm" {
  name             = "vm01"
  resource_pool_id = "${data.vsphere_compute_cluster.cluster.resource_pool_id}"
  datastore_id     = "${data.vsphere_datastore.datastore.id}"
  guest_id         = "${data.vsphere_virtual_machine.template.guest_id}"
  scsi_type        = "${data.vsphere_virtual_machine.template.scsi_type}"

  network_interface {
    network_id = "${data.vsphere_network.network.id}"
  }

  disk {
    label = "disk0"
    size  = "${data.vsphere_virtual_machine.template.disks.0.size}"
  }

  clone {
    template_uuid = "${data.vsphere_virtual_machine.template.id}"

    customize {
      linux_options {
        host_name = "vm01"
        domain     = "example.com"
      }

      network_interface {
        ipv4_address = "192.168.1.2"
        ipv4_netmask = 24
      }

      ipv4_gateway    = "192.168.1.254"
      dns_suffix_list = ["example.com"]
      dns_server_list = ["192.168.1.1"]
    }
  }
}


Структура этого ресурса немного сложнее, потому что она состоит из нескольких подблоков. Мы видим, что сначала мы определим имя виртуальной машины. Затем мы предоставляем информацию о его конфигурации (пул ресурсов, хранилище данных и т. Д.). И блоки используются, чтобы определить конфигурацию своих виртуальных устройств. Субблок позволит вам указать, какой шаблон вы хотите использовать для создания виртуальной машины, а также указать информацию о конфигурации операционной системы, установленной на виртуальной машине. Субблок является специфическим для типа ОС, которую вы хотите клонировать. На всех уровнях мы используем информацию, полученную ранее в блоках.network_interfacedisk clone customize data

Полный пример

provider "vsphere" {
    user = "admin"
    password = "MyAwesomePassword"
    vsphere_server = "pcc-XXX-XXX-XXX-XXX.ovh.com"
}

data "vsphere_datacenter" "dc" {
  name = "pcc-XXX-XXX-XXX-XXX_datacenter3113"
}

data "vsphere_datastore" "datastore" {
  name          = "pcc-001234"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_compute_cluster" "cluster" {
  name          = "Cluster1"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_network" "network" {
  name          = "vxw-dvs-57-virtualwire-2-sid-5001-Dc3113_5001"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_virtual_machine" "template" {
  name          = "UBUNTU"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

resource "vsphere_virtual_machine" "vm" {
  name             = "vm01"
  resource_pool_id = "${data.vsphere_compute_cluster.cluster.resource_pool_id}"
  datastore_id     = "${data.vsphere_datastore.datastore.id}"
  guest_id         = "${data.vsphere_virtual_machine.template.guest_id}"
  scsi_type        = "${data.vsphere_virtual_machine.template.scsi_type}"

  network_interface {
    network_id = "${data.vsphere_network.network.id}"
  }

  disk {
    label = "disk0"
    size  = "${data.vsphere_virtual_machine.template.disks.0.size}"
  }

  clone {
    template_uuid = "${data.vsphere_virtual_machine.template.id}"

    customize {
      linux_options {
        host_name = "vm01"
        domain     = "example.com"
      }

      network_interface {
        ipv4_address = "192.168.1.2"
        ipv4_netmask = 24
      }

      ipv4_gateway    = "192.168.1.254"
      dns_suffix_list = ["example.com"]
      dns_server_list = ["192.168.1.1"]
    }
  }
}


3… 2… 1… Зажигание

Давайте посмотрим, как использовать наш новый файл конфигурации с Terraform…



Инициализация

Теперь, когда наш файл конфигурации готов, мы сможем использовать его для создания нашей виртуальной машины. Начнем с инициализации рабочей среды с помощью terraform initкоманды. Это позаботится о загрузке поставщика vSphere и создании различных файлов, необходимых Terraform для работы.

$ terraform init

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "vsphere" (1.10.0)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

...

* provider.vsphere: version = "~> 1.10"

Terraform has been successfully initialized!
...


Строить планы

Следующим шагом является выполнение terraform planкоманды, чтобы убедиться, что наш файл конфигурации не содержит ошибок, и визуализировать все действия, которые будет выполнять Terraform.

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

data.vsphere_datacenter.dc: Refreshing state...
data.vsphere_compute_cluster.cluster: Refreshing state...
data.vsphere_network.network: Refreshing state...
data.vsphere_datastore.datastore: Refreshing state...
data.vsphere_virtual_machine.template: Refreshing state...

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + vsphere_virtual_machine.vm
      id:                                                   <computed>
      boot_retry_delay:                                     "10000"
      change_version:                                       <computed>
      clone.#:                                              "1"
      clone.0.customize.#:                                  "1"
      clone.0.customize.0.dns_server_list.#:                "1"
      clone.0.customize.0.dns_server_list.0:                "192.168.1.1"
      clone.0.customize.0.dns_suffix_list.#:                "1"
      clone.0.customize.0.dns_suffix_list.0:                "example.com"
      clone.0.customize.0.ipv4_gateway:                     "172.16.0.1"
      clone.0.customize.0.linux_options.#:                  "1"
      clone.0.customize.0.linux_options.0.domain:           "example.com"
      clone.0.customize.0.linux_options.0.host_name:        "vm01"
      clone.0.customize.0.linux_options.0.hw_clock_utc:     "true"
      clone.0.customize.0.network_interface.#:              "1"
      clone.0.customize.0.network_interface.0.ipv4_address: "192.168.1.2"
      clone.0.customize.0.network_interface.0.ipv4_netmask: "16"
      clone.0.customize.0.timeout:                          "10"
      clone.0.template_uuid:                                "42061bc5-fdec-03f3-67fd-b709ec06c7f2"
      clone.0.timeout:                                      "30"
      cpu_limit:                                            "-1"
      cpu_share_count:                                      <computed>
      cpu_share_level:                                      "normal"
      datastore_id:                                         "datastore-93"
      default_ip_address:                                   <computed>
      disk.#:                                               "1"
      disk.0.attach:                                        "false"
      disk.0.datastore_id:                                  "<computed>"
      disk.0.device_address:                                <computed>
      ...

Plan: 1 to add, 0 to change, 0 to destroy.


Перед продолжением важно уделить время проверке всей информации, возвращаемой командой. Было бы беспорядком удалять виртуальные машины в производственной среде из-за ошибки в файле конфигурации… В приведенном ниже примере мы видим, что Terraform создаст новый ресурс (здесь виртуальная машина), а не изменит и не удалит ничего, что в точности Цель!

Применять

На последнем этапе terraform applyкоманда фактически настроит инфраструктуру в соответствии с информацией, содержащейся в файле конфигурации. В качестве первого шага planкоманда будет выполнена, и Terraform попросит вас подтвердить ее, набрав yes.

$ terraform apply
...

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

vsphere_virtual_machine.vm: Creating...
  boot_retry_delay:                                     "" => "10000"
  change_version:                                       "" => "<computed>"
  clone.#:                                              "" => "1"
  clone.0.customize.#:                                  "" => "1"
  clone.0.customize.0.dns_server_list.#:                "" => "1"
  clone.0.customize.0.dns_server_list.0:                "" => "192.168.1.1"
  clone.0.customize.0.dns_suffix_list.#:                "" => "1"
  clone.0.customize.0.dns_suffix_list.0:                "" => "example.com"
  clone.0.customize.0.ipv4_gateway:                     "" => "192.168.1.254"
  clone.0.customize.0.linux_options.#:                  "" => "1"
  clone.0.customize.0.linux_options.0.domain:           "" => "example.com"
  clone.0.customize.0.linux_options.0.host_name:        "" => "terraform-test"
  clone.0.customize.0.linux_options.0.hw_clock_utc:     "" => "true"
  clone.0.customize.0.network_interface.#:              "" => "1"
  clone.0.customize.0.network_interface.0.ipv4_address: "" => "192.168.1.2"
  clone.0.customize.0.network_interface.0.ipv4_netmask: "" => "16"
  clone.0.customize.0.timeout:                          "" => "10"
  clone.0.template_uuid:                                "" => "42061bc5-fdec-03f3-67fd-b709ec06c7f2"
  clone.0.timeout:                                      "" => "30"
  cpu_limit:                                            "" => "-1"
  cpu_share_count:                                      "" => "<computed>"
  cpu_share_level:                                      "" => "normal"
  datastore_id:                                         "" => "datastore-93"
  default_ip_address:                                   "" => "<computed>"
  disk.#:                                               "" => "1"
...
vsphere_virtual_machine.vm: Still creating... (10s elapsed)
vsphere_virtual_machine.vm: Still creating... (20s elapsed)
vsphere_virtual_machine.vm: Still creating... (30s elapsed)
...
vsphere_virtual_machine.vm: Still creating... (1m50s elapsed)
vsphere_virtual_machine.vm: Creation complete after 1m55s (ID: 42068313-d169-03ff-9c55-a23e66a44b48)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.


Когда вы подключаетесь к vCenter вашего частного облака, вы должны увидеть новую виртуальную машину в инвентаре!

Следующие шаги

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

disk {
  label = "disk0"
  size  = "${data.vsphere_virtual_machine.template.disks.0.size}"
}

disk {
  label = "disk1"
  size  = "${data.vsphere_virtual_machine.template.disks.0.size}"
  unit_number = 1
}


Затем запустите, terraform planчтобы увидеть, что Terraform собирается сделать, чтобы согласовать состояние инфраструктуры с вашим файлом конфигурации.

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

data.vsphere_datacenter.dc: Refreshing state...
data.vsphere_datastore.datastore: Refreshing state...
data.vsphere_network.network: Refreshing state...
data.vsphere_compute_cluster.cluster: Refreshing state...
data.vsphere_virtual_machine.template: Refreshing state...
vsphere_virtual_machine.vm: Refreshing state... (ID: 4206be6f-f462-c424-d386-7bd0a0d2cfae)

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  ~ vsphere_virtual_machine.vm
      disk.#:                  "1" => "2"
      disk.1.attach:           "" => "false"
      disk.1.datastore_id:     "" => "<computed>"
      ...


Plan: 0 to add, 1 to change, 0 to destroy.


Если вы согласны с предложением действия terraform, вы можете запустить его повторно terraform apply, чтобы добавить новый виртуальный диск к вашей виртуальной машине.

Приберись

Когда вы закончили свои тесты, и вы больше не требуется полезность инфраструктуры, у НУ можете просто запустить terraform destroyкоманду, чтобы удалить все ранее созданные ресурсы. Будьте осторожны с этой командой, так как после этого нет возможности вернуть ваши данные!

$ terraform destroy

data.vsphere_datacenter.dc: Refreshing state...
data.vsphere_compute_cluster.cluster: Refreshing state...
data.vsphere_datastore.datastore: Refreshing state...
data.vsphere_network.network: Refreshing state...
data.vsphere_virtual_machine.template: Refreshing state...
vsphere_virtual_machine.vm: Refreshing state... (ID: 42068313-d169-03ff-9c55-a23e66a44b48)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - vsphere_virtual_machine.vm


Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

vsphere_virtual_machine.vm: Destroying... (ID: 42068313-d169-03ff-9c55-a23e66a44b48)
vsphere_virtual_machine.vm: Destruction complete after 3s

Destroy complete! Resources: 1 destroyed.


В этой статье мы увидели, как развернуть виртуальную машину с файлом конфигурации Terraform. Это позволило нам узнать основные команды plan, applyи destroy, а также понятия provider, dataи resource. В следующей статье мы разработаем этот пример, изменив его, чтобы сделать его более адаптируемым и универсальным.