Spec-Zone.ru › Ansible 2.9

Руководство по облаку CloudStack

Введение

Цель этого раздела — объяснить, как объединить модули Ansible для использования Ansible в контексте CloudStack. Более подробные примеры использования вы найдете в разделе описания каждого модуля.

Ansible содержит ряд дополнительных модулей для взаимодействия с облаками на основе CloudStack. Все модули поддерживают режим проверки, разработаны для идемпотентности, созданы и протестированы, а также поддерживаются сообществом.

Примечание

Некоторые модули потребуют привилегий администратора домена или root-администратора.

Предварительные требования

Предварительные требования для использования модулей CloudStack минимальны. Помимо самого Ansible, все модули требуют библиотеки Python cs https://pypi.org/project/cs/

Этот модуль Python должен быть установлен на хосте выполнения, обычно на вашей рабочей станции.

$ pip install cs

Или, как альтернатива, начиная с Debian 9 и Ubuntu 16.04:

$ sudo apt install python-cs

Примечание

cs также включает командную строку для ад-хок взаимодействия с API CloudStack, например $ cs listVirtualMachines state=Running.

Ограничения и известные проблемы

Поддержка VPC была улучшена с Ansible 2.3, но все еще не полностью реализована. Сообщество работает над интеграцией VPC.

Файл учетных данных

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

Библиотека Python cs ищет файл учетных данных в следующем порядке (последний имеет приоритет):

  • Файл .cloudstack.ini (обратите внимание на точку) в домашнем каталоге.
  • Переменная среды CLOUDSTACK_CONFIG, указывающая на файл .ini.
  • Файл cloudstack.ini (без точки) в текущей рабочей директории, той же директории, что и ваши playbook'ы.

Структура файла ini должна быть следующей:

$ cat $HOME/.cloudstack.ini
[cloudstack]
endpoint = https://cloud.example.com/client/api
key = api key
secret = api secret
timeout = 30

Примечание

Раздел [cloudstack] — это раздел по умолчанию. Переменная среды CLOUDSTACK_REGION может использоваться для определения раздела по умолчанию.

Новое в версии 2.4.

Переменные среды поддерживают CLOUDSTACK_* так, как написано в документации библиотеки cs, например, CLOUDSTACK_TIMEOUT, CLOUDSTACK_METHOD, и т.д. Это было реализовано в Ansible. Даже возможно иметь неполную конфигурацию в cloudstack.ini:

$ cat $HOME/.cloudstack.ini
[cloudstack]
endpoint = https://cloud.example.com/client/api
timeout = 30

и восполнить недостающие данные, установив переменные среды или параметры задач:

---
- name: provision our VMs
  hosts: cloud-vm
  tasks:
    - name: ensure VMs are created and running
      delegate_to: localhost
      cs_instance:
        api_key: your api key
        api_secret: your api secret
        ...

Регионы

Если вы используете более одного региона CloudStack, вы можете определить столько разделов, сколько хотите, и назвать их как вам удобно, например:

$ cat $HOME/.cloudstack.ini
[exoscale]
endpoint = https://api.exoscale.ch/compute
key = api key
secret = api secret

[example_cloud_one]
endpoint = https://cloud-one.example.com/client/api
key = api key
secret = api secret

[example_cloud_two]
endpoint = https://cloud-two.example.com/client/api
key = api key
secret = api secret

Подсказка

Разделы также могут использоваться для входа в один и тот же регион с использованием разных учетных записей.

Передав аргумент api_region с модулями CloudStack, будет выбран нужный регион.

- name: ensure my ssh public key exists on Exoscale
  cs_sshkeypair:
    name: my-ssh-key
    public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
    api_region: exoscale
  delegate_to: localhost

Или, перебирая список регионов, если вы хотите выполнить задачу в каждом из них:

- name: ensure my ssh public key exists in all CloudStack regions
  local_action: cs_sshkeypair
    name: my-ssh-key
    public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
    api_region: "{{ item }}"
    loop:
      - exoscale
      - example_cloud_one
      - example_cloud_two

Переменные окружения

Новое в версии 2.3.

Начиная с Ansible 2.3, можно использовать переменные среды для домена (CLOUDSTACK_DOMAIN), учетной записи (CLOUDSTACK_ACCOUNT), проекта (CLOUDSTACK_PROJECT), VPC (CLOUDSTACK_VPC) и зоны (CLOUDSTACK_ZONE). Это упрощает задачи, так как не нужно повторять аргументы для каждой задачи.

Ниже приведен пример того, как это можно использовать в сочетании с функцией блоков Ansible:

- hosts: cloud-vm
  tasks:
    - block:
        - name: ensure my ssh public key
          cs_sshkeypair:
            name: my-ssh-key
            public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"

        - name: ensure my ssh public key
          cs_instance:
              display_name: "{{ inventory_hostname_short }}"
              template: Linux Debian 7 64-bit 20GB Disk
              service_offering: "{{ cs_offering }}"
              ssh_key: my-ssh-key
              state: running

      delegate_to: localhost
      environment:
        CLOUDSTACK_DOMAIN: root/customers
        CLOUDSTACK_PROJECT: web-app
        CLOUDSTACK_ZONE: sf-1

Примечание

Вы по-прежнему можете перезаписать переменные среды, используя аргументы модуля, например, zone: sf-2

Примечание

В отличие от CLOUDSTACK_REGION, эти дополнительные переменные среды игнорируются в командной строке cs.

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

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

Пример использования: Развертывание в облаке CloudStack с расширенной сетью

Наше облако CloudStack имеет расширенную настройку сети. Мы хотели бы развернуть веб-серверы, которые получают статический NAT и открытые порты 80 и 443 для брандмауэра. Кроме того, мы развертываем серверы базы данных, к которым не предоставляется доступ. Для доступа к виртуальным машинам по SSH мы используем SSH-шлюз.

Вот как выглядит наш инвентарь:

[cloud-vm:children]
webserver
db-server
jumphost

[webserver]
web-01.example.com  public_ip=198.51.100.20
web-02.example.com  public_ip=198.51.100.21

[db-server]
db-01.example.com
db-02.example.com

[jumphost]
jump.example.com  public_ip=198.51.100.22

Как вы видите, общедоступные IP-адреса для наших веб-серверов и шлюза присвоены в качестве переменной public_ip непосредственно в инвентаре.

Для настройки шлюза, веб-серверов и серверов базы данных мы используем group_vars. Директория group_vars содержит 4 файла для конфигурации групп: cloud-vm, jumphost, webserver и db-server. cloud-vm предназначен для определения параметров нашей облачной инфраструктуры.

# file: group_vars/cloud-vm
---
cs_offering: Small
cs_firewall: []

Наши серверы базы данных должны получить больше ЦП и оперативной памяти, поэтому мы определили использовать предложение Large для них.

# file: group_vars/db-server
---
cs_offering: Large

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

# file: group_vars/webserver
---
cs_firewall:
  - { port: 80 }
  - { port: 443 }

Кроме того, мы развертываем шлюз, который имеет открыт только порт 22 для доступа к виртуальным машинам из нашей офисной IPv4-сети.

# file: group_vars/jumphost
---
cs_firewall:
  - { port: 22, cidr: "17.17.17.0/24" }

Теперь к интересному. Мы создаем playbook для создания нашей инфраструктуры, который мы называем infra.yml:

# file: infra.yaml
---
- name: provision our VMs
  hosts: cloud-vm
  tasks:
    - name: run all enclosed tasks from localhost
      delegate_to: localhost
      block:
        - name: ensure VMs are created and running
          cs_instance:
            name: "{{ inventory_hostname_short }}"
            template: Linux Debian 7 64-bit 20GB Disk
            service_offering: "{{ cs_offering }}"
            state: running

        - name: ensure firewall ports opened
          cs_firewall:
            ip_address: "{{ public_ip }}"
            port: "{{ item.port }}"
            cidr: "{{ item.cidr | default('0.0.0.0/0') }}"
          loop: "{{ cs_firewall }}"
          when: public_ip is defined

        - name: ensure static NATs
          cs_staticnat: vm="{{ inventory_hostname_short }}" ip_address="{{ public_ip }}"
          when: public_ip is defined

В этом playbook'е мы определили 3 задачи и используем группу cloud-vm в качестве цели для обработки всех виртуальных машин в облаке, но вместо SSH к этим виртуальным машинам мы используем delegate_to: localhost для выполнения вызовов API локально со своей рабочей станции.

В первой задаче мы убеждаемся, что создана запущенная виртуальная машина с шаблоном Debian. Если виртуальная машина уже создана, но остановлена, она просто запустится. Если вы хотите изменить предложение на существующей виртуальной машине, вы должны добавить force: yes в задачу, которая остановит виртуальную машину, изменит предложение и запустит её снова.

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

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

Примечание

Общедоступные IP-адреса должны быть получены заранее, см. также cs_ip_address

Примечание

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

Пример использования: Развертывание в облаке CloudStack с базовой сетью

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

Вот как выглядит наш инвентарь:

[cloud-vm:children]
webserver

[webserver]
web-01.example.com
web-02.example.com

Настройки по умолчанию для ваших виртуальных машин выглядят так:

# file: group_vars/cloud-vm
---
cs_offering: Small
cs_securitygroups: [ 'default']

Наш веб-сервер также будет в группе безопасности web:

# file: group_vars/webserver
---
cs_securitygroups: [ 'default', 'web' ]

Playbook выглядит следующим образом:

# file: infra.yaml
---
- name: cloud base setup
  hosts: localhost
  tasks:
  - name: upload ssh public key
    cs_sshkeypair:
      name: defaultkey
      public_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"

  - name: ensure security groups exist
    cs_securitygroup:
      name: "{{ item }}"
    loop:
      - default
      - web

  - name: add inbound SSH to security group default
    cs_securitygroup_rule:
      security_group: default
      start_port: "{{ item }}"
      end_port: "{{ item }}"
    loop:
      - 22

  - name: add inbound TCP rules to security group web
    cs_securitygroup_rule:
      security_group: web
      start_port: "{{ item }}"
      end_port: "{{ item }}"
    loop:
      - 80
      - 443

- name: install VMs in the cloud
  hosts: cloud-vm
  tasks:
  - delegate_to: localhost
    block:
    - name: create and run VMs on CloudStack
      cs_instance:
        name: "{{ inventory_hostname_short }}"
        template: Linux Debian 7 64-bit 20GB Disk
        service_offering: "{{ cs_offering }}"
        security_groups: "{{ cs_securitygroups }}"
        ssh_key: defaultkey
        state: Running
      register: vm

    - name: show VM IP
      debug: msg="VM {{ inventory_hostname }} {{ vm.default_ip }}"

    - name: assign IP to the inventory
      set_fact: ansible_ssh_host={{ vm.default_ip }}

    - name: waiting for SSH to come up
      wait_for: port=22 host={{ vm.default_ip }} delay=5

В первом playbook'е мы настраиваем группы безопасности, во втором playbook'е виртуальные машины будут назначены этим группам. Кроме того, вы видите, что мы назначаем общедоступный IP-адрес, возвращаемый модулями, в инвентарь хостов. Это необходимо, так как мы не знаем заранее полученные IP-адреса. На следующем шаге вы настроите DNS-серверы с этими IP-адресами для доступа к виртуальным машинам по их имени DNS.

В последней задаче мы ждем, пока SSH станет доступным, чтобы любой последующий playbook мог получить доступ к виртуальной машине по SSH без ошибок.

© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.9/scenario_guides/guide_cloudstack.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API