UMGUM.COM (лучше) 

Zabbix server upgrade 1.6 => 1.8 ( Обновление сервера системы мониторинга с версии 1.6.2 до 1.8.3. )

26 сентября 2010  (обновлено 29 декабря 2014)

Эта публикация отнесена в архив. Она неактуальна.
Ресурс по следующей ссылке является преемником: Обновление сервера системы мониторинга с версии 1.8.3 до 2.0.5.

OS: Debian Lenny.

Обновление с 1.6 до 1.8 должно пройти достаточно гладко. Обновление исполняемых файлов и компонентов "web"-интерфейса производится путём простого замещения и отдельному рассматриванию не подлежит. Самое интересное - обновление структуры и содержимого СУБД, в моём случае ещё и совмещённое с переносом данных с одной физической машины на другую.

Сразу предупреждаю, переносить на новый сервер старую базу и обновлять её до требований новой версии Zabbix дело не одного часа. У меня на перенос и обновление базы наработанной в течении года на мониторинге порядка сотни единиц оборудования по ряду параметров ушло около трёх часов чистого рабочего времени без учёта экспериментальных попыток. Так что, заранее пишем служебную записку на выход в выходной день или просто выводим сервис из работы на денёк - другой.


В связи с затяжным характером процедур рекомендую запускать их в сеансах "screen", а то, обидно будет утерять связь с хостом после трёх часов ожидания, очень обидно.

# aptitude install screen

Создание сеанса:

# screen -S screen.postgres

Подключение к сеансу:

# screen -r screen.postgres

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

# /etc/init.d/zabbix-server stop

Дожидаемся, пока Postgres успокоится и приведёт в порядок свои внутренности после отрыва главного главного возмущателя - Zabbix`а. В моём случае Postgres после отключения Zabbix ещё минут пять что-то там делал от имени пользователя сервиса мониторинга.

Для полного спокойствия перезапустим Postgres, если на нём не висит более важных сервисов, разумеется:

# /etc/init.d/postgres-8.3 restart

Для PostgreSQL резервное копирование и применение данных стандартно осуществляется утилитами создания "дампа", например, входящей в состав комплекта программного обеспечения сервера PostgreSQL утилитой pg_dump. Необходимо оперировать от имени пользователя, который имеет право чтения необходимых таблиц на сервере, в нашем случае это postgres.

Я предпочитаю вначале создавать резервную копию структуры базы, а потом уже сохранять сами данные. Такой подход позволяет произвести какие нибудь необходимые изменения в структуре прежде, чем располагать в ней данные. Особенно удобно это в случае, когда объём резервируемых данных измеряется в гигабайтах.

Сохраняем структуру базы данных:

# pg_dump --verbose --clean --schema-only --format=p --file="./file.name.structure.sql" --username="postgres" --password zabbix

Где:

"--clean"          - указываем применять команды удаления всех объектов перед их восстановлением;
"--schema-only"    - указываем сохранять только структуру объектов;
"--format {с|t|p}" - указываем на формат выходного файла, соответственно "gzip", "tar" или "plain text".

Сохраняем данные как таковые:

# pg_dump --verbose --blobs --data-only --format=c --compress=4 --file="./file.name.data.sql.gz" --username="postgres" --password zabbix

Где:

"--blobs"          - указываем сохранять большие двоичные объекты наряду с обычными данными. В связи с использованием этого параметра необходимо так же применить архивирование данных в формат "tar" или "gzip";
"--data-only"      - указываем сохранять только данные;
"--inserts"        - применяем для восстановления записей команды INSERT вместо используемых по умолчанию команд COPY. Этот вариант безопаснее, так как одна поврежденная запись приводит к сбою всей команды COPY, хотя процесс восстановления и занимает больше времени;
"--format {с|t|p}" - указываем на формат выходного файла, соответственно "gzip", "tar" или "plain text" (для того, чтобы pg_dump смог архивировать данные соответствующие утилиты должны иметься в системе);
"--compress {0-9}" - указываем уровень сжатия (0 — минимальный, 9 — максимальный) при архивировании.

В режиме по умолчанию данные в резервной копии сохраняются для отрабатывания с помощью инструкции "COPY". Это гораздо быстрее, чем использование "INSERT", хотя и чревато полным сбоем восстановления таблицы в случае малейшей ошибки в теле файла резервной копии. Ситуация с выбором между инструкциями интересная: с одной стороны, при восстановлении много-гигабайтного файла применение инструкции "COPY" сэкономит часы, даже не минуты, а с другой стороны - очень обидно будет из-за мелкой ошибки в одной ячейке таблицы огрести проблемы со всей базой. Думаю, что до объёмов базы в два-три гигабайта можно побаловаться "COPY", потом придёт время думать о надёжности, пусть и в ущерб времени, а после того, как размер базы зашкалит за сотню гигабайт, банальное восстановление из резервной копии вообще уже не будет рассматриваться как вариант.

Процедура создания резервной копии данных может быть долгой и зависит, в основном, от уровня производительности дисковой подсистемы; пока СУБД прочитает записи по запросу с диска, пока отдаст их утилите, да пока та их запишет снова на диск. На моей практике резервирование базы объёмом в пару гигабайт на машине с процессором "Pentium 4" и IDE дисками заняло порядка двадцати минут. При этом загрузка процессора в среднем составляла 70-80%, расход оперативной памяти не поражал воображение.

Передаем файлы на удалённый сервер, хотя бы с использованием SCP:

# scp "./file.name.data.sql.gz" user@remote_host:/directory.on.remote.host/

file.name.data.sql.gz        23%  180MB  11.6MB/s   00:51 ETA

На время восстановления базы меняем для пользователя СУБД "postgres" метод аутентификации на "trust" в файле конфигурации "/etc/postgres/8.3/main/pg_hba.conf". После этого пользователь "postgres" сможет войти без пароля. Перезапускаем СУБД:

# /etc/init.d/postgres-8.3 restart

На самом деле, думаю, что для локального администратора СУБД в одно-пользовательском сервере особого смысла городить парольную защиту нет, если злоумышленник проник в среду исполнения суперпользователя системы, то он всё равно изменит способ аутентификации так, как ему удобно; потому можно так и оставить пользователя "postgres" доверенным и разрешить ему подключение к СУБД без пароля.

Сейчас самое время принять меры к тому, чтобы срок восстановления данных не стал исчисляется в сутках - временно откажемся от создания индексов к таблицам; иначе пересчёт таковых при каждой вставке порции данных превратит наш процесс в оч-ч-чень затяжной процесс.

Вырежем из файла резервной копии структуры базы "file.name.structure.sql" инструкции создающие индексы и вынесем их в отдельный файл "file.name.structure.indexes.sql", который исполним после восстановления данных. В итоге файл для восстановления индексов будет выглядеть примерно таким образом:

# cat ./file.name.structure.indexes.sql

--
-- PostgreSQL database custom dump
--

SET client_encoding = 'UTF8';
SET standard_conforming_strings = off;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET escape_string_warning = off;

SET search_path = public, pg_catalog;
....
--
-- TOC entry 2635 (class 1259 OID 16779)
-- Dependencies: 1668
-- Name: acknowledges_1; Type: INDEX; Schema: public; Owner: zabbix; Tablespace:
--

CREATE INDEX acknowledges_1 ON acknowledges USING btree (userid);
....
--
-- TOC entry 2773 (class 1259 OID 17483)
-- Dependencies: 1712
-- Name: valuemaps_1; Type: INDEX; Schema: public; Owner: zabbix; Tablespace:
--

CREATE INDEX valuemaps_1 ON valuemaps USING btree (name);
....
--
-- PostgreSQL database custom dump complete
--

Восстанавливаем структуру базы данных:

# cat "./file.name.structure.sql" | psql --username zabbix zabbix 2> "./file.name.structure.error.log" 1> "./file.name.structure.access.log"

Теперь внесём данные. Учитывая то, что при создании резервной копии данных мы использовали архивирование, просто передать файл в качестве потока команд клиенту Postgres не выйдет, проще воспользоваться утилитой "pg_resore":

# pg_restore --verbose --exit-on-error --data-only --dbname="zabbix" --username="postgres" ./file.name.data.sql.gz

Примерный вид журнала событий утилиты восстановления pg_restore:

pg_restore: connecting to database for restore
pg_restore: executing SEQUENCE SET history_str_sync_id_seq
pg_restore: executing SEQUENCE SET history_sync_id_seq
pg_restore: executing SEQUENCE SET history_uint_sync_id_seq
pg_restore: executing SEQUENCE SET proxy_dhistory_id_seq
pg_restore: executing SEQUENCE SET proxy_history_id_seq
pg_restore: restoring data for table "acknowledges"
pg_restore: restoring data for table "actions"
pg_restore: restoring data for table "alerts"
pg_restore: restoring data for table "applications"
pg_restore: restoring data for table "auditlog"
pg_restore: restoring data for table "conditions"
pg_restore: restoring data for table "config"
....

Процедура восстановления базы более длительная, чем создание резервной копии. Если резервирование двух-гигабайтной базы прошло за двадцать минут, то на восстановление таковой было затрачено порядка одного часа.

После размещения данных восстановим заданные разработчиками индексы с помощью подготовленного нами набора SQL инструкций:

# cat "./file.name.structure.indexes.sql" | psql --username zabbix zabbix 2> "./file.name.structure.indexes.error.log" 1> "./file.name.structure.indexes.access.log"

Создание индексов к данным большого объёма - операция весьма активного характера. И диски пошумят и процессор при этом погреется.

Убедимся в том, что клавиши нажимались не зря и строчки на экране не просто так мелькали, проверим, восстановились ли данные базы:

# psql -U zabbix

zabbix=> \dt

Schema |      Name     | Type  | Owner
--------+---------------+-------+--------
public | acknowledges  | table | zabbix
public | actions       | table | zabbix
public | alerts        | table | zabbix
public | applications  | table | zabbix
....
public | triggers      | table | zabbix
public | users         | table | zabbix
public | users_groups  | table | zabbix
public | usrgrp        | table | zabbix
public | valuemaps     | table | zabbix
(73 rows)

zabbix=> \q

Теперь необходимо обновить её структуру до уровня, поддерживаемого более новой версией сервера мониторинга Zabbix. В соответствии с рекомендациями разработчиков необходимо удалить часть существующих индексов данных затрагиваемых скриптом обновления, для последующего изменения структуры (иначе процедура обновления будет ну оч-ч-чень сильно замедлена перерасчётом индекса при изменении каждой ячейки обрабатываемых таблиц):

# psql -U postgres

postgres=# \connect zabbix zabbix
Password for user zabbix:
You are now connected to database "zabbix" as user "zabbix".
zabbix=>
....
drop index dhosts_1;
drop index dservices_1;
drop index httptest_2;
drop index httptest_3;
drop index history_log_2;
drop index history_text_2;
drop index actions_1;
drop index escalations_2;
drop index graphs_items_1;
drop index graphs_items_2;
drop index services_1;
....
zabbix=> \q

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

Теперь применим набор SQL запросов от разработчиков, что изменят структуру и данные нашей базы до вида применимого в новой версии Zabbix. "Патч" мы получили с набором исходных кодов сервера Zabbix. Просто применим его:

# cat "/usr/src/zabbix-1.8.3/upgrades/dbpatches/1.8/postgresql/patch.sql" | psql --username zabbix zabbix 2> "./patch.error.log" 1> "./patch.access.log"

PostgreSQL будет гудеть, создавая, перемещая, удаляя таблицы, пересчитывая индексы. Обновление базы данных размером около двух гигабайт заняло примерно тридцать минут. Разработчики предупреждают, что база в кодировке UTF-8 конвертируется особенно долго, но я думаю, что это актуально для содержащих не латинский контент.

Вот, собственно, и всё. Можно запустить Zabbix сервер, зайти на "web"-панель управления и получить обновлённую систему мониторинга.

Если бы мы не переносили базу с её содержимым, то индивидуальные шаблоны и конфигурации можно было бы экспортировать со старого сервера с помощью "web"-инструмента в панели управления Zabbix сервера:

"Configuration" => "Export/Import" => "Export" => "All"

Отмечаем все объекты, что хотели бы экспортировать и делаем это.

На новом сервере в панели управления можно импортировать полученные XML файлы.