Руководство по облаку Rackspace
Введение
Примечание
Этот раздел документации находится в стадии разработки. Мы в процессе добавления дополнительных примеров использования модулей Rackspace и способов их совместной работы. По завершении, появятся примеры для Rackspace Cloud в ansible-examples.
Ansible содержит ряд основных модулей для взаимодействия с облаком Rackspace Cloud.
Цель этого раздела — объяснить, как объединить модули Ansible (и использовать скрипты инвентаризации) для использования Ansible в контексте Rackspace Cloud.
Предварительные условия для использования модулей rax минимальны. Помимо самого Ansible, все модули требуют и протестированы с pyrax 1.5 или выше. Вам понадобится этот Python-модуль, установленный на хосте выполнения.
pyrax в настоящее время недоступен во многих репозиториях пакетов операционных систем, поэтому вам, вероятно, нужно будет установить его через pip:
$ pip install pyrax
Следующие шаги часто выполняются с управляющей машины по отношению к API Rackspace Cloud, поэтому имеет смысл добавить localhost в файл инвентаризации. (Ansible, возможно, в будущем не потребует этого ручного шага):
[localhost] localhost ansible_connection=local
В шагах плейбука мы будем обычно использовать следующую структуру:
- hosts: localhost connection: local gather_facts: False tasks:
Файл учетных данных
Скрипт инвентаризации rax.py и все модули rax поддерживают стандартный файл учетных данных pyrax, который выглядит следующим образом:
[rackspace_cloud] username = myraxusername api_key = d41d8cd98f00b204e9800998ecf8427e
Установка параметра среды RAX_CREDS_FILE с путем к этому файлу поможет Ansible найти способ загрузки этой информации.
Дополнительную информацию об этом файле учетных данных можно найти по адресу https://github.com/rackspace/pyrax/blob/master/docs/getting_started.md#authenticating
Запуск из виртуальной среды Python (необязательно)
Большинство пользователей не будут использовать virtualenv, но некоторые пользователи, особенно разработчики Python, иногда это делают.
Существуют особые моменты, когда Ansible установлен в виртуальную среду Python virtualenv, а не по умолчанию, при установке в глобальной области. Ansible предполагает, если не указано иное, что бинарный файл Python будет находиться по адресу /usr/bin/python. Это делается через строку интерпретатора в модулях, однако, при указании переменной инвентаризации ‘ansible_python_interpreter’, Ansible будет использовать этот указанный путь вместо этого, чтобы найти Python. Это может вызвать путаницу, так как можно предположить, что модули, выполняющиеся на ‘localhost’, или, возможно, выполняющиеся через ‘local_action’, используют интерпретатор Python virtualenv. Установив эту строку в инвентаризации, модули будут выполняться в интерпретаторе virtualenv и будут иметь доступ к пакетам virtualenv, в частности, 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" -c local
Вот как это будет выглядеть в плейбуке, предполагая, что параметры были определены в переменных:
tasks:
- name: Provision a set of instances
local_action:
module: rax
name: "{{ rax_name }}"
flavor: "{{ rax_flavor }}"
image: "{{ rax_image }}"
count: "{{ rax_count }}"
group: "{{ group }}"
wait: yes
register: rax
Модуль rax возвращает данные о созданных узлах, такие как IP-адреса, имена хостов и пароли входа. Регистрируя возвращаемое значение шага, можно использовать эти данные для динамического добавления получившихся хостов в инвентаризацию (временно, в памяти). Это облегчает выполнение конфигурационных действий на хостах в последующей задаче. В следующем примере серверы, которые были успешно созданы с использованием вышеуказанной задачи, динамически добавляются в группу с именем «raxhosts», при этом имя хоста, IP-адрес и корневой пароль каждого узла добавляются в инвентаризацию.
- name: Add the instances we created (by public IP) to the group 'raxhosts'
local_action:
module: add_host
hostname: "{{ item.name }}"
ansible_host: "{{ item.rax_accessipv4 }}"
ansible_ssh_pass: "{{ 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 установлен глобально. Если Ansible установлен в virtualenv, скрипты инвентаризации устанавливаются в $VIRTUALENV/share/inventory.
Примечание
Пользователи 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 (вместо плагина инвентаризации), может быть полезно извлечь данные о хостах из Rackspace API.
Это можно сделать с помощью модуля 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
local_action:
module: rax_facts
credentials: ~/.raxpub
name: "{{ inventory_hostname }}"
region: "{{ rax_region }}"
- 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
connection: local
gather_facts: False
tasks:
- name: Network create request
local_action:
module: rax_network
credentials: ~/.raxpub
label: my-net
cidr: 192.168.3.0/24
region: IAD
state: present
- name: Server create request
local_action:
module: 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
Полная среда
Построение полной среды веб-сервера с серверами, настраиваемыми сетями и балансировщиками нагрузки, установкой nginx и созданием настраиваемого index.html
---
- name: Build environment
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Load Balancer create request
local_action:
module: 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
local_action:
module: rax_network
credentials: ~/.raxpub
label: my-net
cidr: 192.168.3.0/24
state: present
region: IAD
register: network
- name: Server create request
local_action:
module: 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
local_action:
module: add_host
hostname: "{{ item.name }}"
ansible_host: "{{ item.rax_accessipv4 }}"
ansible_ssh_pass: "{{ item.rax_adminpass }}"
ansible_user: root
groups: web
loop: "{{ rax.success }}"
when: rax.action == 'create'
- name: Add servers to Load balancer
local_action:
module: 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 существуют задачи автоматизации Rackspace, которые выполняются на серверах после их успешного создания. Если ваша автоматизация выполняется до автоматизации RackConnect или Managed Cloud, вы можете вызвать ошибки и нерабочие серверы.
Эти примеры показывают создание серверов и обеспечение завершения автоматизации Rackspace до продолжения работы Ansible.
Для простоты эти примеры объединены, но оба необходимы только при использовании RackConnect. При использовании только управляемого облака, часть RackConnect можно игнорировать.
Часть RackConnect относится только к RackConnect версии 2.
Использование управляющей машины
- name: Create an exact count of servers
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Server build requests
local_action:
module: 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
local_action:
module: add_host
hostname: "{{ item.name }}"
ansible_host: "{{ item.rax_accessipv4 }}"
ansible_ssh_pass: "{{ 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: Wait for rackconnnect automation to complete
local_action:
module: 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
local_action:
module: 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
local_action:
module: rax_facts
name: "{{ inventory_hostname }}"
region: DFW
- 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
connection: local
tasks:
- 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
connection: local
roles:
- role: users
- role: openssh
opensshd_PermitRootLogin: "no"
- role: ntp
Использование Ansible Pull с XenStore
---
- name: Ensure Rackconnect and Managed Cloud Automation is complete
hosts: all
connection: local
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
connection: local
roles:
- role: users
- role: openssh
opensshd_PermitRootLogin: "no"
- role: ntp
Расширенное использование
Автомасштабирование с Tower
Ansible Tower также содержит очень полезную функцию для примеров автоматического масштабирования. В этом режиме простой скрипт curl может вызывать определённый URL, и сервер будет «звонить» отправителю и настраивать запускаемую виртуальную машину. Это может быть отличный способ перенастроить временные узлы. Подробности см. в документации Tower.
Преимущество использования обратного вызова в Tower по сравнению с режимом pull заключается в том, что результаты работы сохраняются централизованно, и меньше информации нужно передавать удалённым узлам.
Оптимизация в облаке Rackspace
Ansible — мощный инструмент оркестрации, и модули rax позволяют вам оркестрировать сложные задачи, развертывания и конфигурации. Ключевым моментом является автоматизация развертывания инфраструктуры, как любого другого программного обеспечения в среде. Сложные развертывания ранее могли потребовать ручного управления балансировщиками нагрузки или ручного развертывания серверов. Используя модули rax, включённые в Ansible, можно сделать развертывание дополнительных узлов зависящим от текущего количества работающих узлов или конфигурацию кластерного приложения — от количества узлов с общими метаданными. Например, можно автоматизировать следующие сценарии:
- Серверы, удаляемые из балансировщика нагрузки облака по одному, обновляются, проверяются и возвращаются в пул балансировщика нагрузки
- Расширение уже работающей среды, где узлы развертываются, настраиваются, конфигурируются и устанавливается программное обеспечение
- Процедура, при которой журналы приложений загружаются в централизованное место, например, в Cloud Files, перед выводом узла из эксплуатации
- Серверы и балансировщики нагрузки, у которых записи 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.6/scenario_guides/guide_rax.html