Обнаружить Ansible изменения в Terraform и выполнить их - PullRequest
0 голосов
/ 03 июня 2019

Я хочу объединить Ansible с Terraform, чтобы Terraform создавала машины, а Ansible предоставит их. Используя terraform-provisioner-ansible , можно объединить их без проблем. Но я обнаружил отсутствие обнаружения изменений, которое не происходит, когда Ansible работает автономно.

TL; DR : Как применить изменения, внесенные в Ansible, в плагин Terraform Ansible? Или, по крайней мере, запускать плагин ansible при каждом обновлении, чтобы Ansible мог сам справиться с этим?

Пример использования

Рассмотрим эту пьесу, которая устанавливает несколько пакетов

- name: Ansible install package test
  hosts: all
  tasks: 
  - name: Install cli tools
    become: yes
    apt:
      name: "{{ tools }}"
      update_cache: yes
    vars:
      tools:
        - nnn
        - htop

, который интегрирован в Terraform с помощью плагина

resource "libvirt_domain" "ubuntu18" {
  # ...
  connection {
    type = "ssh"
    host = "192.168.2.2"
    user = "ubuntu"
    private_key = "${file("~/.ssh/id_rsa")}"
  }
  provisioner "ansible" {
    plays {
      enabled = true
      become_method = "sudo"

      playbook = {
        file_path = "ansible-test.yml" 
      }
    }
  }
}

будет отлично работать при первом запуске. Но позже я заметил, что какой-то пакет пропал

- name: Ansible install package test
  hosts: all
  tasks: 
  - name: Install cli tools
    become: yes
    apt:
      name: "{{ tools }}"
      update_cache: yes
    vars:
      tools:
        - nnn
        - htop
        - vim # This is a new package

При запуске terraform plan Я получу No changes. Infrastructure is up-to-date. Мой новый пакет vim никогда не будет установлен! Таким образом, Ansible не запустился, потому что, если Ansible запустится, он установит новый пакет.

Кажется, проблема в самом провайдере :

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

Но как правильно применять обновления? Я попытался null_ressource со ссылкой depends_on на мой ресурс vm, но Terraform также не обнаруживает изменений в части Ansible. Кажется, отсутствие обнаружения изменений из плагина Terraform.

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

Разве нельзя сделать что-то подобное с Terraform?

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

source_code_hash может быть вариантом, но негибким: при наличии нескольких пьес / ролей мне нужно делать это вручную для каждого отдельного файла, который легко подвержен ошибкам.

Ответы [ 2 ]

0 голосов
/ 04 июня 2019

Использование null_ressource с псевдо-триггером

Идея из tedsmitt использует метку времени в качестве триггера, который, по-видимому, является единственным способом принудительной инициализации.Однако запуск ansible-playbook plain из CLI может привести к дополнительным расходам на обслуживание инвентаря вручную.Вы не можете вызвать скрипт динамической инвентаризации Python отсюда, поскольку terraform apply необходимо завершить до

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

resource "null_resource" "ansible-provisioner" {
  triggers {
      build_number = "${timestamp()}"
  }
  depends_on = ["libvirt_domain.ubuntu18"]

  connection {
    type = "ssh"
    host = "192.168.2.2"
    user = "ubuntu"
    private_key = "${file("~/.ssh/id_rsa")}"
  }
  provisioner "ansible" {
    plays {
      enabled = true
      become_method = "sudo"

      playbook = {
        file_path = "ansible-test.yml" 
      }
    }
  }
}

Единственная сумочка здесь: Terraform будет распознавать псевдо-изменения каждый раз

Terraform will perform the following actions:

-/+ null_resource.ansible-provisioner (new resource required)
      id:                    "3365240528326363062" => <computed> (forces new resource)
      triggers.%:            "1" => "1"
      triggers.build_number: "2019-06-04T09:32:27Z" => "2019-06-04T09:34:17Z" (forces new resource)


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

Это кажется лучшим компромиссом для меня, согласно другим доступным временным решениям.

Запуск Ansible вручную с динамическим инвентарем

Другой способ, который я нашел, - это плагин динамического инвентаризации , подробное описание которого можно найти в этой записи блога .Он интегрируется в Terraform и позволяет вам указать ресурсы в качестве хоста инвентаря, например:

resource "ansible_host" "k8s" {
  inventory_hostname = "192.168.2.2"
  groups             = ["test"]
  vars = {
    ansible_user = "ubuntu"
    ansible_ssh_private_key_file = "~/.ssh/id_rsa"
  }
}

Сценарий Python использует эту информацию для создания динамического инвентаря, который можно использовать так:

ansible-playbook -i /etc/ansible/terraform.py ansible-test.yml

Большое преимущество: оно сохраняет вашу конфигурацию СУХОЙ.Terraform имеет ведущий файл конфигурации, нет необходимости также поддерживать отдельные файлы Ansible.А также возможность использования переменных (например, имя хоста инвентаризации не должно быть жестко задано для производственного использования, как в моем примере).

В моем случае использования (тест-кластер Provision Rancher) подход null_ressource выглядит лучше, поскольку ВСЁ строится с помощью одной команды Terraform.Не нужно дополнительно выполнять Ansible.Но в зависимости от требований, может быть лучше оставить Ansible отдельным шагом, поэтому я разместил это как альтернативу.

Установка плагина

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

version=0.0.4
wget https://github.com/nbering/terraform-provider-ansible/releases/download/v${version}/terraform-provider-ansible-linux_amd64.zip -O terraform-provisioner-ansible.zip
unzip terraform-provisioner-ansible.zip
chmod +x linux_amd64/*
mv linux_amd64 ~/.terraform.d/plugins

А такжеобратите внимание, что автоматизированный поставщик из решения выше должен быть сначала удален, так как он имеет то же имя (может конфликтовать).

0 голосов
/ 04 июня 2019

Как вы упомянули в своем вопросе, в плагине нет обнаружения изменений.Вы можете реализовать триггер для null_resource, чтобы он работал при каждом применении.

resource "null_resource" "ansible-provisioner" {
  triggers {
      build_number = "${timestamp()}"
  }
  provisioner "local-exec" {
    command = "ansible-playbook ansible-test.yml"
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...