Ранее мы сравнивали «NFS и CEPH», в той заметке мы говорили об узких местах технологии NFS и как можно их решить путем использования в инфраструктуре распределенного файлового хранилища от компании Red Hat — Ceph.
Сегодня предлагаем рассмотреть вариант как быстро и с наименьшим кол-вом ошибок развернуть кластер CEPH используя систему управления конфигурациями — Ansible.
Почему стоит использовать данный вариант установки и кому он может не подойти. Касательно второго вопроса, данный вариант установки подходит специалистам, которые имеют достаточный опыт работы с Ansible и Ceph, понимают терминологии обоих систем, смогут выполнить дебаг ошибок в случаи наличие их при использовании Ansible ролей. Почему стоит использовать данное решение, т.к. оба продукта принадлежат компании Red Hat и продукт ceph-ansible является официальным продуктом данной компании, при установке используются лучший практики лучшие практики (best practice), что в свою очередь минимизирует кол-во ошибок при достижении конечного результата.
Прежде чем приступить к практической части, как использовать решение ceph-ansible, предлагаем рассмотреть вариант где в целом мы можем использовать Ceph.
Современные архитектуры, построенные на базе железа (bare metal), а также частично использующие облачные решения (AWS, Google Cloud), которые использую в своей архитектуре Docker и такие оркестраторы как Docker swarm, Kubernetes, Rancher — часто сталкиваются с проблемой: где хранить данные приложения, которые должны быть доступны из любой точки инфраструктуры независимо от расположения Docker контейнера с приложением. Данную проблему и помогает решить Ceph, c учетом того, что система распределенного хранения, с высокой доступностью, а также масштабируемостью. К примеру в архитектурах на базе Kubernetes Ceph имеет провиженер (provisioner) для k8s PersistentVolume — CephFS и k8s PersistentVolumeClaims — RBD (Ceph Block Device). Также Ceph часто используется в решениях обработки и хранения BigData из-за прекрасного свойства — горизонтальной масштабируемости.
Однако не стоит забывать, что все архитектуры с использование Ceph предпологает высокую избыточность использования серверов и/или виртуальных машин. К сожалению Ceph не предлагает дешевых и простых решений, т.к. он сразу становится уязвимым и хранения данных в такой архитектуре будет не гарантированным.
Рассмотрим как развернуть Ceph с помощью ceph-ansible для будующего использования в Kubernetes в качестве блочных устройств (PersistentVolumeClaims — RBD).
Для нашего тестового стенда будем использовать:
1x виртуальный сервер с ansible
IP — 192.168.1.2 — для внешнего трафика
IP — 10.0.1.4 — для внутреннего трафика
3x сервера для ceph + на каждом из серверов по 3 свободных HDD для OSD
IP — 192.168.2.1 192.168.2.2 192.168.2.3 — для внешнего трафика
IP — 10.0.1.1 10.0.1.2 10.0.1.3 — для внутреннего трафика
Также мы установим Grafana и Dashboard для наглядной визуализации работы с Ceph.
Для наших 4-х серверов настроена внутрення сеть 10.0.1.0/24, которую мы будем использовать для внутреннего трафика Ceph
Подготовка сервера с ansible.
Необходимо сгенерировать ssh ключи и разложить их на все сервера.
Скачать репозиторий:
1 |
git clone https://github.com/ceph/ceph-ansible |
и переключится на нужную нам версию в соответствии со следующей структурой, также стоит обратить, что для разных версии разные требования к версии ansible
Бранчи stable- * были проверены QE и к ним редко выходят исправления во время их жизненного цикла:
1 2 3 4 |
stable-3.0 поддержка Ceph версий jewel и luminous. Необходим Ansible версии 2.4. stable-3.1 поддержка Ceph версий luminous и mimic. Необходим Ansible версии 2.4. stable-3.2 поддержка Ceph версий luminous и mimic. Необходим Ansible версии 2.6. stable-4.0 поддержка Ceph версии nautilus. Необходим Ansible версии 2.8. |
Мы будем использовать в примере версию nautilus
1 |
git checkout stable-4.0 |
Установим все необходимые зависимости
1 |
pip install -r requirements.txt |
Переименовываем примеры конфиг файлов:
1 2 3 4 |
cp site.yml.sample site.yml cp group_vars/all.yml.sample group_vars/all.yml cp group_vars/mons.yml.sample group_vars/mons.yml cp group_vars/osds.yml.sample group_vars/osds.yml |
Создаем inventory файл с описанием всех наших серверов
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[mons] 192.168.2.1 192.168.2.2 192.168.2.3 [osds] 192.168.2.1 192.168.2.2 192.168.2.3 [mgrs] 192.168.2.1 [grafana-server] 192.168.2.1 |
Приводим основной файл site.yml к следующему виду:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
--- # Defines deployment design and assigns role to server groups - hosts: - mons - osds gather_facts: false any_errors_fatal: true become: true tags: always vars: delegate_facts_host: True pre_tasks: # If we can't get python2 installed before any module is used we will fail # so just try what we can to get it installed - import_tasks: raw_install_python.yml - name: gather facts setup: when: not delegate_facts_host | bool - name: gather and delegate facts setup: delegate_to: "{{ item }}" delegate_facts: True with_items: "{{ groups['all'] }}" run_once: true when: delegate_facts_host | bool - name: install required packages for fedora > 23 raw: sudo dnf -y install python2-dnf libselinux-python ntp register: result when: - ansible_distribution == 'Fedora' - ansible_distribution_major_version|int >= 23 until: result is succeeded - name: check if it is atomic host stat: path: /run/ostree-booted register: stat_ostree tags: always - name: set_fact is_atomic set_fact: is_atomic: '{{ stat_ostree.stat.exists }}' tags: always tasks: - import_role: name: ceph-defaults - import_role: name: ceph-facts - import_role: name: ceph-validate - import_role: name: ceph-infra - hosts: mons gather_facts: false become: True any_errors_fatal: true pre_tasks: - name: set ceph monitor install 'In Progress' run_once: true set_stats: data: installer_phase_ceph_mon: status: "In Progress" start: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}" tasks: - import_role: name: ceph-defaults tags: ['ceph_update_config'] - import_role: name: ceph-facts tags: ['ceph_update_config'] - import_role: name: ceph-handler - import_role: name: ceph-common - import_role: name: ceph-config tags: ['ceph_update_config'] - import_role: name: ceph-mon - import_role: name: ceph-mgr when: groups.get(mgr_group_name, []) | length == 0 post_tasks: - name: set ceph monitor install 'Complete' run_once: true set_stats: data: installer_phase_ceph_mon: status: "Complete" end: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}" - hosts: mgrs gather_facts: false become: True any_errors_fatal: true pre_tasks: - name: set ceph manager install 'In Progress' run_once: true set_stats: data: installer_phase_ceph_mgr: status: "In Progress" start: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}" tasks: - import_role: name: ceph-defaults tags: ['ceph_update_config'] - import_role: name: ceph-facts tags: ['ceph_update_config'] - import_role: name: ceph-handler - import_role: name: ceph-common - import_role: name: ceph-config tags: ['ceph_update_config'] - import_role: name: ceph-mgr post_tasks: - name: set ceph manager install 'Complete' run_once: true set_stats: data: installer_phase_ceph_mgr: status: "Complete" end: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}" - hosts: osds gather_facts: false become: True any_errors_fatal: true pre_tasks: - name: set ceph osd install 'In Progress' run_once: true set_stats: data: installer_phase_ceph_osd: status: "In Progress" start: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}" tasks: - import_role: name: ceph-defaults tags: ['ceph_update_config'] - import_role: name: ceph-facts tags: ['ceph_update_config'] - import_role: name: ceph-handler - import_role: name: ceph-common - import_role: name: ceph-config tags: ['ceph_update_config'] - import_role: name: ceph-osd post_tasks: - name: set ceph osd install 'Complete' run_once: true set_stats: data: installer_phase_ceph_osd: status: "Complete" end: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}" - hosts: mons gather_facts: false become: True any_errors_fatal: true tasks: - import_role: name: ceph-defaults - name: get ceph status from the first monitor command: ceph --cluster {{ cluster }} -s register: ceph_status changed_when: false delegate_to: "{{ groups[mon_group_name][0] }}" run_once: true - name: "show ceph status for cluster {{ cluster }}" debug: msg: "{{ ceph_status.stdout_lines }}" delegate_to: "{{ groups[mon_group_name][0] }}" run_once: true when: not ceph_status.failed - import_playbook: infrastructure-playbooks/dashboard.yml when: - dashboard_enabled | bool - groups.get(grafana_server_group_name, []) | length > 0 - ansible_os_family in ['RedHat', 'Suse'] |
Редактируем файл group_vars/all.yml в нем мы задаем такие важные параметры как версия будущего кластера, указываем внутреннюю подсеть, интерфейсы, размер журнала и многое другое. Для нашего примера конфигурация переменных будет следующая:
1 2 3 4 5 6 7 |
ceph_origin: repository ceph_repository: community ceph_stable_release: nautilus monitor_interface: eth0 journal_size: 5120 #public_network: 0.0.0.0/0 - оставляем закоментированным cluster_network: 10.0.1.0/24 - указываем сеть для внутреннего трафика |
Далее редактируем файл переменных отвечающих за настройку OSD group_vars/osds.yml
Можно выполнить полностью автоматическую настройку поиска и установки OSD на сервере указав переменную:
1 |
osd_auto_discovery: true |
Однако мы указываем в явном виде диски наших серверов:
1 2 3 4 |
devices: - /dev/sdb - /dev/sdc - /dev/sdd |
Подготовка завершена, теперь необходимо проиграть ansible
1 |
ansible-playbook site.yml -i inventory_hosts |
Примерное время разворачивания 10 минут, результат успешного выполнения в консоли будет следующий вывод:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
INSTALLER STATUS ********************************************************* Install Ceph Monitor : Complete (0:02:48) Install Ceph Manager : Complete (0:01:14) Install Ceph OSD : Complete (0:01:29) Install Ceph Dashboard : Complete (0:00:38) Install Ceph Grafana : Complete (0:01:08) Install Ceph Node Exporter : Complete (0:01:31) Thursday 22 August 2019 10:20:20 +0200 (0:00:00.064) 0:09:50.539 ** ========================================================================== ceph-common : install redhat ceph packages ------------------------------- 79.72s ceph-container-engine : install container package ------------------------ 37.51s ceph-mgr : install ceph-mgr packages on RedHat or SUSE ------------------- 35.18s ceph-osd : use ceph-volume lvm batch to create bluestore osds ------------ 29.40s ceph-grafana : wait for grafana to start --------------------------------- 19.38s ceph-config : generate ceph configuration file: ceph.conf ---------------- 12.03s ceph-grafana : install ceph-grafana-dashboards package on RedHat or SUSE -- 9.11s ceph-common : install centos dependencies --------------------------------- 8.23s ceph-validate : validate provided configuration --------------------------- 7.23s ceph-mgr : wait for all mgr to be up -------------------------------------- 6.72s ceph-mon : fetch ceph initial keys ---------------------------------------- 5.33s ceph-dashboard : set or update dashboard admin username and password ------ 5.25s ceph-facts : set_fact fsid from ceph_current_status ----------------------- 4.30s check for python ---------------------------------------------------------- 4.02s ceph-mon : waiting for the monitor(s) to form the quorum... --------------- 3.94s ceph-facts : create a local fetch directory if it does not exist ---------- 3.75s ceph-facts : set_fact devices generate device list when osd_auto_discovery- 3.41s gather and delegate facts ------------------------------------------------- 3.37s ceph-osd : apply operating system tuning ---------------------------------- 2.91s ceph-container-engine : start container service --------------------------- 2.89s |
У нас установились успешно следующие компоненты:
1 2 3 4 5 6 |
Install Ceph Monitor Install Ceph Manager Install Ceph OSD Install Ceph Dashboard Install Ceph Grafana Install Ceph Node Exporter |
Для доступа в dashboard используем ссылку:
1 2 |
Dashboard web UI http://192.168.2.1:8443/ логин и пароль - admin / admin |
Мы успешно произвели базовую настройку распределенной системы хранения данных Ceph, для будущих задач расширения кластера достаточно добавить новый сервер в инвентаризацию
**********************************************************************
ошибка — insecure global_id reclaim
Available Fixes:
- Ceph Octopus: 15.2.11
- Ceph Nautlis: 14.2.20
1 |
ceph config <span class="prism-token prism-builtin prism-class-name">set</span> mon auth_allow_insecure_global_id_reclaim <span class="prism-token prism-boolean">false</span> |
Спасибо за статью! Пытаюсь воспроизвести с максимально похожими настройками и каждый раз все отваливается на TASK [ceph-mgr : add modules to ceph-mgr]Ж
Error ENOENT: module »dashboard» reports that it cannot run on the active manager daemon: cannot import name UnrewindableBodyError (pass —force to force enablement)’
Может быть знаете как это обойти?
К сожалению с такой ошибкой не сталкивался. По ошибке, вроде как ему имя не нравится, может что-то специфическое указали в качестве имени в ceph-mgr?
на гите майнтенейр ответил. Это проблема urlib и requests. Они уже стояли на нодах через пип, а цеф хочет их через рпм. Спасибо за быстрый ответ!