Руководство по Rackspace Cloud
Введение
Примечание
Этот раздел документации находится в стадии разработки. Мы работаем над добавлением больше примеров работы модулей Rackspace и их взаимодействия. После завершения будут также примеры для Rackspace Cloud в ansible-examples.
Ansible содержит ряд основных модулей для взаимодействия с Rackspace Cloud.
Цель этого раздела — объяснить, как объединить модули Ansible (и использовать скрипты инвентаризации) для использования Ansible в контексте Rackspace Cloud.
Предварительные условия для использования модулей rax минимальны. Помимо самого ansible, все модули требуют и тестируются с pyrax 1.5 или выше. Вам понадобится этот Python-модуль, установленный на хосте выполнения.
pyrax в настоящее время недоступен во многих репозиториях пакетов операционных систем, поэтому вам, вероятно, потребуется установить его через pip:
$ pip install pyrax
Ansible создает неявный localhost, который выполняется в том же контексте, что и ansible-playbook и другие инструменты командной строки. Если по какой-либо причине вам нужно или вы хотите иметь его в своей инвентаризации, вы должны сделать что-то вроде следующего:
[localhost] localhost ansible_connection=local ansible_python_interpreter=/usr/local/bin/python2
Дополнительную информацию см. в Неявный Localhost
В шагах книги задач мы обычно будем использовать следующий шаблон:
- hosts: localhost gather_facts: False tasks:
Файл учетных данных
Скрипт инвентаризации rax.py и все модули rax поддерживают стандартный файл учетных данных pyrax, который выглядит так:
[rackspace_cloud] username = myraxusername api_key = d41d8cd98f00b204e9800998ecf8427e
Указание параметра среды RAX_CREDS_FILE на путь к этому файлу поможет Ansible определить, как загрузить эту информацию.
Дополнительную информацию об этом файле учетных данных можно найти по адресу https://github.com/pycontribs/pyrax/blob/master/docs/getting_started.md#authenticating
Запуск из виртуальной среды Python (необязательно)
Большинство пользователей не будут использовать virtualenv, но некоторые пользователи, особенно разработчики Python, иногда это делают.
Существуют особые соображения, когда Ansible установлен в виртуальной среде Python, а не по умолчанию, когда установлено в глобальной области. Ansible предполагает, что бинарник python будет находиться в /usr/bin/python, если не указано иное. Это делается через строку интерпретатора в модулях, однако, при указании переменной инвентаризации «ansible_python_interpreter», Ansible будет использовать этот указанный путь вместо этого для поиска Python. Это может вызвать путаницу, так как можно предположить, что модули, выполняемые на «localhost», или, возможно, выполняемые через «local_action», используют интерпретатор Python виртуальной среды. Установив эту строку в инвентаризации, модули будут выполняться в интерпретаторе виртуальной среды и будут доступны пакеты виртуальной среды, в частности pyrax. При использовании virtualenv вы можете изменить определение инвентаризации localhost для поиска этого местоположения следующим образом:
[localhost] localhost ansible_connection=local ansible_python_interpreter=/path/to/ansible_venv/bin/python
Примечание
pyrax может быть установлен в глобальной области пакетов Python или в виртуальной среде. Нет особых соображений, которые нужно учитывать при установке pyrax.
Развертывание
Теперь к самому интересному.
Модуль «rax» предоставляет возможность развертывания экземпляров в Rackspace Cloud. Обычно задача развертывания выполняется с сервера управления Ansible (в нашем примере, localhost) по отношению к API Rackspace cloud. Это делается по нескольким причинам:
- Избегание установки библиотеки pyrax на удаленных узлах
- Нет необходимости шифровать и распространять учетные данные на удаленные узлы
- Скорость и простота
Примечание
Авторизация с модулями, связанными с Rackspace, обрабатывается либо путем указания вашего имени пользователя и API-ключа в качестве переменных среды, либо путем передачи их в качестве аргументов модуля, либо путем указания расположения файла учетных данных.
Вот базовый пример развертывания экземпляра в режиме ad-hoc:
$ ansible localhost -m rax -a "name=awx flavor=4 image=ubuntu-1204-lts-precise-pangolin wait=yes"
Вот как это будет выглядеть в книге задач, предполагая, что параметры были определены в переменных:
tasks:
- name: Provision a set of instances
rax:
name: "{{ rax_name }}"
flavor: "{{ rax_flavor }}"
image: "{{ rax_image }}"
count: "{{ rax_count }}"
group: "{{ group }}"
wait: yes
register: rax
delegate_to: localhost
Модуль rax возвращает данные об узлах, которые он создает, такие как IP-адреса, имена хостов и пароли для входа. Регистрируя возвращаемое значение шага, можно использовать эти данные для динамического добавления полученных хостов в инвентаризацию (временно, в памяти). Это способствует выполнению действий конфигурации на узлах в последующей задаче. В следующем примере серверы, которые были успешно созданы с помощью вышеупомянутой задачи, динамически добавляются в группу с именем «raxhosts», причем имя хоста, IP-адрес и пароль root каждого узла добавляются в инвентаризацию.
- name: Add the instances we created (by public IP) to the group 'raxhosts'
add_host:
hostname: "{{ item.name }}"
ansible_host: "{{ item.rax_accessipv4 }}"
ansible_password: "{{ item.rax_adminpass }}"
groups: raxhosts
loop: "{{ rax.success }}"
when: rax.action == 'create'
После создания группы хостов следующая задача в этой книге задач теперь может настроить серверы, принадлежащие группе raxhosts.
- name: Configuration play
hosts: raxhosts
user: root
roles:
- ntp
- webserver
Вышеупомянутый метод связывает конфигурацию хоста с шагом развертывания. Это не всегда то, что вы хотите, и это приводит нас к следующему разделу.
Инвентаризация хостов
После запуска ваших узлов вы, вероятно, захотите снова с ними взаимодействовать. Лучший способ справиться с этим — использовать плагин инвентаризации «rax», который динамически запрашивает Rackspace Cloud и сообщает Ansible, какие узлы вам нужно управлять. Вы можете использовать этот плагин даже в том случае, если вы запускаете облачные экземпляры с помощью других инструментов, включая интерфейс пользователя Rackspace Cloud. Плагин инвентаризации может использоваться для группирования ресурсов по метаданным, региону, ОС и т. д. Использование метаданных настоятельно рекомендуется в «rax» и может предоставить простой способ сортировки между группами хостов и ролями. Если вы не хотите использовать скрипт динамической инвентаризации rax.py, вы также можете выбрать ручное управление своим файлом инвентаризации INI, хотя это менее рекомендуется.
В Ansible вполне возможно использовать несколько динамических плагинов инвентаризации вместе с данными файла INI. Просто поместите их в общую директорию и убедитесь, что скрипты имеют разрешение chmod +x, а скрипты INI-формата не имеют.
rax.py
Для использования скрипта динамической инвентаризации Rackspace скопируйте rax.py в свою директорию инвентаризации и сделайте его исполняемым. Вы можете указать файл учетных данных для rax.py с помощью переменной среды RAX_CREDS_FILE.
Примечание
Динамические скрипты инвентаризации (например, rax.py) сохраняются в /usr/share/ansible/inventory, если Ansible установлен глобально. Если установлен в виртуальной среде, скрипты инвентаризации устанавливаются в $VIRTUALENV/share/inventory.
Примечание
Пользователи Red Hat Ansible Tower заметят, что динамическая инвентаризация поддерживается в Tower по умолчанию, и вам нужно только связать группу с вашими учетными данными Rackspace Cloud, и он будет легко синхронизироваться без этих шагов:
$ RAX_CREDS_FILE=~/.raxpub ansible all -i rax.py -m setup
rax.py также принимает переменную среды RAX_REGION, которая может содержать отдельный регион или список регионов, разделенных запятыми.
При использовании rax.py, в инвентаризации не будет определен ‘localhost’.
Как упоминалось ранее, вы часто будете выполнять большинство этих модулей вне цикла хоста и вам потребуется определить ‘localhost’. Рекомендуемый способ сделать это — создать директорию inventory, и поместить в нее как скрипт rax.py, так и файл с localhost.
Выполнение ansible или ansible-playbook и указание директории inventory вместо отдельного файла, заставит ansible оценить каждый файл в этой директории для инвентаризации.
Давайте протестируем наш скрипт инвентаризации, чтобы увидеть, может ли он взаимодействовать с Rackspace Cloud.
$ RAX_CREDS_FILE=~/.raxpub ansible all -i inventory/ -m setup
Предполагая, что все настроено правильно, скрипт инвентаризации rax.py выведет информацию, аналогичную следующей информации, которая будет использоваться для инвентаризации и переменных.
{
"ORD": [
"test"
],
"_meta": {
"hostvars": {
"test": {
"ansible_host": "198.51.100.1",
"rax_accessipv4": "198.51.100.1",
"rax_accessipv6": "2001:DB8::2342",
"rax_addresses": {
"private": [
{
"addr": "192.0.2.2",
"version": 4
}
],
"public": [
{
"addr": "198.51.100.1",
"version": 4
},
{
"addr": "2001:DB8::2342",
"version": 6
}
]
},
"rax_config_drive": "",
"rax_created": "2013-11-14T20:48:22Z",
"rax_flavor": {
"id": "performance1-1",
"links": [
{
"href": "https://ord.servers.api.rackspacecloud.com/111111/flavors/performance1-1",
"rel": "bookmark"
}
]
},
"rax_hostid": "e7b6961a9bd943ee82b13816426f1563bfda6846aad84d52af45a4904660cde0",
"rax_human_id": "test",
"rax_id": "099a447b-a644-471f-87b9-a7f580eb0c2a",
"rax_image": {
"id": "b211c7bf-b5b4-4ede-a8de-a4368750c653",
"links": [
{
"href": "https://ord.servers.api.rackspacecloud.com/111111/images/b211c7bf-b5b4-4ede-a8de-a4368750c653",
"rel": "bookmark"
}
]
},
"rax_key_name": null,
"rax_links": [
{
"href": "https://ord.servers.api.rackspacecloud.com/v2/111111/servers/099a447b-a644-471f-87b9-a7f580eb0c2a",
"rel": "self"
},
{
"href": "https://ord.servers.api.rackspacecloud.com/111111/servers/099a447b-a644-471f-87b9-a7f580eb0c2a",
"rel": "bookmark"
}
],
"rax_metadata": {
"foo": "bar"
},
"rax_name": "test",
"rax_name_attr": "name",
"rax_networks": {
"private": [
"192.0.2.2"
],
"public": [
"198.51.100.1",
"2001:DB8::2342"
]
},
"rax_os-dcf_diskconfig": "AUTO",
"rax_os-ext-sts_power_state": 1,
"rax_os-ext-sts_task_state": null,
"rax_os-ext-sts_vm_state": "active",
"rax_progress": 100,
"rax_status": "ACTIVE",
"rax_tenant_id": "111111",
"rax_updated": "2013-11-14T20:49:27Z",
"rax_user_id": "22222"
}
}
}
}
Стандартная инвентаризация
При использовании стандартного файла инвентаризации в формате ini (в отличие от плагина инвентаризации), может быть целесообразно извлечь обнаруживаемую информацию о hostvar из API Rackspace.
Это можно сделать с помощью модуля rax_facts и файла инвентаризации, подобного следующему:
[test_servers] hostname1 rax_region=ORD hostname2 rax_region=ORD
- name: Gather info about servers
hosts: test_servers
gather_facts: False
tasks:
- name: Get facts about servers
rax_facts:
credentials: ~/.raxpub
name: "{{ inventory_hostname }}"
region: "{{ rax_region }}"
delegate_to: localhost
- name: Map some facts
set_fact:
ansible_host: "{{ rax_accessipv4 }}"
Хотя вам не нужно знать, как это работает, может быть интересно узнать, какие переменные возвращаются.
Модуль rax_facts предоставляет факты, которые соответствуют скрипту инвентаризации rax.py.
{
"ansible_facts": {
"rax_accessipv4": "198.51.100.1",
"rax_accessipv6": "2001:DB8::2342",
"rax_addresses": {
"private": [
{
"addr": "192.0.2.2",
"version": 4
}
],
"public": [
{
"addr": "198.51.100.1",
"version": 4
},
{
"addr": "2001:DB8::2342",
"version": 6
}
]
},
"rax_config_drive": "",
"rax_created": "2013-11-14T20:48:22Z",
"rax_flavor": {
"id": "performance1-1",
"links": [
{
"href": "https://ord.servers.api.rackspacecloud.com/111111/flavors/performance1-1",
"rel": "bookmark"
}
]
},
"rax_hostid": "e7b6961a9bd943ee82b13816426f1563bfda6846aad84d52af45a4904660cde0",
"rax_human_id": "test",
"rax_id": "099a447b-a644-471f-87b9-a7f580eb0c2a",
"rax_image": {
"id": "b211c7bf-b5b4-4ede-a8de-a4368750c653",
"links": [
{
"href": "https://ord.servers.api.rackspacecloud.com/111111/images/b211c7bf-b5b4-4ede-a8de-a4368750c653",
"rel": "bookmark"
}
]
},
"rax_key_name": null,
"rax_links": [
{
"href": "https://ord.servers.api.rackspacecloud.com/v2/111111/servers/099a447b-a644-471f-87b9-a7f580eb0c2a",
"rel": "self"
},
{
"href": "https://ord.servers.api.rackspacecloud.com/111111/servers/099a447b-a644-471f-87b9-a7f580eb0c2a",
"rel": "bookmark"
}
],
"rax_metadata": {
"foo": "bar"
},
"rax_name": "test",
"rax_name_attr": "name",
"rax_networks": {
"private": [
"192.0.2.2"
],
"public": [
"198.51.100.1",
"2001:DB8::2342"
]
},
"rax_os-dcf_diskconfig": "AUTO",
"rax_os-ext-sts_power_state": 1,
"rax_os-ext-sts_task_state": null,
"rax_os-ext-sts_vm_state": "active",
"rax_progress": 100,
"rax_status": "ACTIVE",
"rax_tenant_id": "111111",
"rax_updated": "2013-11-14T20:49:27Z",
"rax_user_id": "22222"
},
"changed": false
}
Примеры использования
Этот раздел содержит дополнительные примеры использования, основанные на конкретном случае использования.
Сеть и сервер
Создание изолированной облачной сети и создание сервера
- name: Build Servers on an Isolated Network
hosts: localhost
gather_facts: False
tasks:
- name: Network create request
rax_network:
credentials: ~/.raxpub
label: my-net
cidr: 192.168.3.0/24
region: IAD
state: present
delegate_to: localhost
- name: Server create request
rax:
credentials: ~/.raxpub
name: web%04d.example.org
flavor: 2
image: ubuntu-1204-lts-precise-pangolin
disk_config: manual
networks:
- public
- my-net
region: IAD
state: present
count: 5
exact_count: yes
group: web
wait: yes
wait_timeout: 360
register: rax
delegate_to: localhost
Полная среда
Создание полной среды веб-сервера с серверами, настраиваемыми сетями и балансировщиками нагрузки, установкой nginx и созданием пользовательского index.html
---
- name: Build environment
hosts: localhost
gather_facts: False
tasks:
- name: Load Balancer create request
rax_clb:
credentials: ~/.raxpub
name: my-lb
port: 80
protocol: HTTP
algorithm: ROUND_ROBIN
type: PUBLIC
timeout: 30
region: IAD
wait: yes
state: present
meta:
app: my-cool-app
register: clb
- name: Network create request
rax_network:
credentials: ~/.raxpub
label: my-net
cidr: 192.168.3.0/24
state: present
region: IAD
register: network
- name: Server create request
rax:
credentials: ~/.raxpub
name: web%04d.example.org
flavor: performance1-1
image: ubuntu-1204-lts-precise-pangolin
disk_config: manual
networks:
- public
- private
- my-net
region: IAD
state: present
count: 5
exact_count: yes
group: web
wait: yes
register: rax
- name: Add servers to web host group
add_host:
hostname: "{{ item.name }}"
ansible_host: "{{ item.rax_accessipv4 }}"
ansible_password: "{{ item.rax_adminpass }}"
ansible_user: root
groups: web
loop: "{{ rax.success }}"
when: rax.action == 'create'
- name: Add servers to Load balancer
rax_clb_nodes:
credentials: ~/.raxpub
load_balancer_id: "{{ clb.balancer.id }}"
address: "{{ item.rax_networks.private|first }}"
port: 80
condition: enabled
type: primary
wait: yes
region: IAD
loop: "{{ rax.success }}"
when: rax.action == 'create'
- name: Configure servers
hosts: web
handlers:
- name: restart nginx
service: name=nginx state=restarted
tasks:
- name: Install nginx
apt: pkg=nginx state=latest update_cache=yes cache_valid_time=86400
notify:
- restart nginx
- name: Ensure nginx starts on boot
service: name=nginx state=started enabled=yes
- name: Create custom index.html
copy: content="{{ inventory_hostname }}" dest=/usr/share/nginx/www/index.html
owner=root group=root mode=0644
RackConnect и Управляемое облако
При использовании RackConnect версии 2 или Rackspace Managed Cloud существуют задачи автоматизации Rackspace, которые выполняются на серверах, созданных после их успешного развертывания. Если ваша автоматизация выполняется до автоматизации RackConnect или Managed Cloud, вы можете вызвать ошибки и сделать серверы непригодными для использования.
Эти примеры показывают создание серверов и обеспечение того, что автоматизация Rackspace завершилась до продолжения Ansible.
Для простоты эти примеры объединены, однако оба необходимы только при использовании RackConnect. При использовании только Managed Cloud часть RackConnect можно пропустить.
Часть RackConnect относится только к версии 2 RackConnect.
Использование управляющего компьютера
- name: Create an exact count of servers
hosts: localhost
gather_facts: False
tasks:
- name: Server build requests
rax:
credentials: ~/.raxpub
name: web%03d.example.org
flavor: performance1-1
image: ubuntu-1204-lts-precise-pangolin
disk_config: manual
region: DFW
state: present
count: 1
exact_count: yes
group: web
wait: yes
register: rax
- name: Add servers to in memory groups
add_host:
hostname: "{{ item.name }}"
ansible_host: "{{ item.rax_accessipv4 }}"
ansible_password: "{{ item.rax_adminpass }}"
ansible_user: root
rax_id: "{{ item.rax_id }}"
groups: web,new_web
loop: "{{ rax.success }}"
when: rax.action == 'create'
- name: Wait for rackconnect and managed cloud automation to complete
hosts: new_web
gather_facts: false
tasks:
- name: ensure we run all tasks from localhost
delegate_to: localhost
block:
- name: Wait for rackconnnect automation to complete
rax_facts:
credentials: ~/.raxpub
id: "{{ rax_id }}"
region: DFW
register: rax_facts
until: rax_facts.ansible_facts['rax_metadata']['rackconnect_automation_status']|default('') == 'DEPLOYED'
retries: 30
delay: 10
- name: Wait for managed cloud automation to complete
rax_facts:
credentials: ~/.raxpub
id: "{{ rax_id }}"
region: DFW
register: rax_facts
until: rax_facts.ansible_facts['rax_metadata']['rax_service_level_automation']|default('') == 'Complete'
retries: 30
delay: 10
- name: Update new_web hosts with IP that RackConnect assigns
hosts: new_web
gather_facts: false
tasks:
- name: Get facts about servers
rax_facts:
name: "{{ inventory_hostname }}"
region: DFW
delegate_to: localhost
- name: Map some facts
set_fact:
ansible_host: "{{ rax_accessipv4 }}"
- name: Base Configure Servers
hosts: web
roles:
- role: users
- role: openssh
opensshd_PermitRootLogin: "no"
- role: ntp
Использование Ansible Pull
---
- name: Ensure Rackconnect and Managed Cloud Automation is complete
hosts: all
tasks:
- name: ensure we run all tasks from localhost
delegate_to: localhost
block:
- name: Check for completed bootstrap
stat:
path: /etc/bootstrap_complete
register: bootstrap
- name: Get region
command: xenstore-read vm-data/provider_data/region
register: rax_region
when: bootstrap.stat.exists != True
- name: Wait for rackconnect automation to complete
uri:
url: "https://{{ rax_region.stdout|trim }}.api.rackconnect.rackspace.com/v1/automation_status?format=json"
return_content: yes
register: automation_status
when: bootstrap.stat.exists != True
until: automation_status['automation_status']|default('') == 'DEPLOYED'
retries: 30
delay: 10
- name: Wait for managed cloud automation to complete
wait_for:
path: /tmp/rs_managed_cloud_automation_complete
delay: 10
when: bootstrap.stat.exists != True
- name: Set bootstrap completed
file:
path: /etc/bootstrap_complete
state: touch
owner: root
group: root
mode: 0400
- name: Base Configure Servers
hosts: all
roles:
- role: users
- role: openssh
opensshd_PermitRootLogin: "no"
- role: ntp
Использование Ansible Pull с XenStore
---
- name: Ensure Rackconnect and Managed Cloud Automation is complete
hosts: all
tasks:
- name: Check for completed bootstrap
stat:
path: /etc/bootstrap_complete
register: bootstrap
- name: Wait for rackconnect_automation_status xenstore key to exist
command: xenstore-exists vm-data/user-metadata/rackconnect_automation_status
register: rcas_exists
when: bootstrap.stat.exists != True
failed_when: rcas_exists.rc|int > 1
until: rcas_exists.rc|int == 0
retries: 30
delay: 10
- name: Wait for rackconnect automation to complete
command: xenstore-read vm-data/user-metadata/rackconnect_automation_status
register: rcas
when: bootstrap.stat.exists != True
until: rcas.stdout|replace('"', '') == 'DEPLOYED'
retries: 30
delay: 10
- name: Wait for rax_service_level_automation xenstore key to exist
command: xenstore-exists vm-data/user-metadata/rax_service_level_automation
register: rsla_exists
when: bootstrap.stat.exists != True
failed_when: rsla_exists.rc|int > 1
until: rsla_exists.rc|int == 0
retries: 30
delay: 10
- name: Wait for managed cloud automation to complete
command: xenstore-read vm-data/user-metadata/rackconnect_automation_status
register: rsla
when: bootstrap.stat.exists != True
until: rsla.stdout|replace('"', '') == 'DEPLOYED'
retries: 30
delay: 10
- name: Set bootstrap completed
file:
path: /etc/bootstrap_complete
state: touch
owner: root
group: root
mode: 0400
- name: Base Configure Servers
hosts: all
roles:
- role: users
- role: openssh
opensshd_PermitRootLogin: "no"
- role: ntp
Расширенное использование
Автомасштабирование с Tower
Red Hat Ansible Tower также содержит очень удобную функцию для случаев использования автомасштабирования. В этом режиме простой скрипт curl может вызывать определенный URL-адрес, и сервер «выполнит звонок» до запрашивающего и сконфигурирует экземпляр, который запускается. Это может быть отличный способ переконфигурации временных узлов. Дополнительную информацию см. в документации по Tower.
Преимущество использования обратного вызова в Tower по сравнению с режимом pull заключается в том, что результаты задач по-прежнему записываются централизованно, и с удалёнными хостами необходимо передавать меньше информации.
Оптимизация в облаке Rackspace
Ansible — это мощный инструмент оркестрации, а модули rax предоставляют возможность автоматизировать сложные задачи, развертывания и конфигурации. Ключевой момент здесь — автоматизация подготовки инфраструктуры, как и любого другого программного обеспечения в среде. Сложные развертывания ранее могли потребовать ручного вмешательства в балансировщики нагрузки или ручного развёртывания серверов. Используя модули rax, включённые в Ansible, можно сделать развертывание дополнительных узлов зависящим от текущего количества работающих узлов или конфигурацию кластеризованного приложения — от количества узлов с общей метаданными. Например, можно автоматизировать следующие сценарии:
- Поочерёдное удаление серверов из балансировщика нагрузки в облаке, обновление, проверка и возвращение в пул балансировщиков
- Расширение уже работающей среды, где узлы подготавливаются, инициализируются, настраиваются и на них устанавливается программное обеспечение
- Процедура загрузки журналов приложений в центральное расположение, например, в облачные файлы, перед выводом узла из эксплуатации
- Создание и уничтожение записей DNS для серверов и балансировщиков нагрузки соответственно при их создании и выводе из эксплуатации
© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.10/scenario_guides/guide_rax.html