Руководство по облаку CloudStack
Введение
Цель этого раздела — объяснить, как объединить модули Ansible для использования Ansible в контексте CloudStack. Вы найдете больше примеров использования в разделе «Подробности» каждого модуля.
Ansible содержит ряд дополнительных модулей для взаимодействия с облаками на базе CloudStack. Все модули поддерживают режим проверки, разработаны для идемпотентности, были созданы и протестированы и поддерживаются сообществом.
Примечание
Некоторые модули потребуют привилегий администратора домена или администратора корня.
Предварительные условия
Предварительные условия для использования модулей 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
В вышеприведенном воспроизведении мы определили 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
В первом воспроизведении мы настраиваем группы безопасности, во втором воспроизведении виртуальные машины будут созданы и назначены этим группам. Кроме того, вы видите, что мы назначаем общедоступный IP-адрес, возвращаемый модулями, инвентарю хостов. Это необходимо, так как мы не знаем заранее полученные IP-адреса. На следующем этапе вы настроите DNS-серверы с этими IP-адресами для доступа к виртуальным машинам по их имени DNS.
В последней задаче мы ожидаем, что SSH будет доступен, поэтому любые последующие воспроизведения смогут получить доступ к виртуальной машине по SSH без сбоев.
© 2012–2018 Michael DeHaan
© 2018–2021 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.11/scenario_guides/guide_cloudstack.html