Zabbix5.0 のDB移行（MariaDB→TimescaleDB）

## はじめに

Zabbix のデータベースを MariaDB で運用していたところ、history syncer internal processes 等の値が定期的に高騰するようになったため、時系列データベースである TimescaleDB に移行することにしました。本記事は、検証環境での検証結果のまとめです。

## 環境

１年ほど前に構築した検証環境があったので、Zabbixのバージョンを最新化（5.0.15）した上で検証しました。
PostgreSQL, TimescaleDB はコミュニティ版のものを使用しました。

| 項目 | 移行前 | 移行後 |
|------|--------|--------|
| OS   | CentOS 8.2 | 同左 |
| PHP | php-7.2.24-1 | 同左 |
| Web | httpd-2.4.37-21 | 同左 |
| DB | mariadb-10.3.17-1 | postgresql12-12.8-1PGDG + timescaledb_12-2.4.2-1 |
| Zabbix Server | zabbix-server-mysql-5.0.15-1 | zabbix-server-pgsql-5.0.15-1 |

## 移行の流れ

以下のような流れで移行します。

1. Zabbix Server の停止
2. Zabbix 関連パッケージのアンインストール・インストール
3. PostgreSQL のインストールと設定
4. pgloader によるマイグレーション
5. TimescaleDB のインストールと適用
6. MariaDB の停止
7. Zabbix Server の設定と起動
8. SELinux モジュールの生成とインストール

## 1. Zabbix Server の停止

データベースに値が更新されないように、Zabbix Server を停止します。

```
sudo systemctl stop zabbix-server
```

## 2. Zabbix 関連パッケージのアンインストール・インストール

MySQL 接続用の Zabbix 関連パッケージをアンインストールし、 PostgreSQL 接続用の Zabbix 関連パッケージをインストールします。

```
sudo dnf remove -y zabbix-server-mysql
sudo dnf install -y zabbix-server-pgsql
sudo dnf remove -y zabbix-web-mysql
sudo dnf install -y zabbix-web-pgsql zabbix-apache-conf
```

## 3. PostgreSQL のインストールと設定

[PostgreSQL公式サイトのマニュアル](https://www.postgresql.org/download/linux/redhat/) を参考に、PostgreSQL のインストールを設定をします。

リポジトリをインストールします。

```
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
```

OS同梱の PostgreSQL モジュールを無効化します。

```
sudo dnf -qy module disable postgresql
```

コミュニティ版 PostgreSQL をインストールします。

```
sudo dnf install -y postgresql12-server
```

データベースを初期化します。

```
sudo /usr/pgsql-12/bin/postgresql-12-setup initdb
```

接続設定を変更します。

```
sudo cp -p /var/lib/pgsql/12/data/pg_hba.conf{,.default}
sudo vi /var/lib/pgsql/12/data/pg_hba.conf
sudo diff -u /var/lib/pgsql/12/data/pg_hba.conf{.default,}
```
```
--- /var/lib/pgsql/12/data/pg_hba.conf.default  2021-09-26 16:42:06.589004356 +0900
+++ /var/lib/pgsql/12/data/pg_hba.conf  2021-09-26 16:46:38.837010714 +0900
@@ -83,9 +83,9 @@
 # "local" is for Unix domain socket connections only
 local   all             all                                     peer
 # IPv4 local connections:
-host    all             all             127.0.0.1/32            ident
+host    all             all             127.0.0.1/32            md5
 # IPv6 local connections:
-host    all             all             ::1/128                 ident
+host    all             all             ::1/128                 md5
 # Allow replication connections from localhost, by a user with the
 # replication privilege.
 local   replication     all                                     peer
```

PostgreSQL の起動と自動起動設定をします。

```
sudo systemctl start postgresql-12
sudo systemctl status postgresql-12
sudo systemctl enable postgresql-12
```

ユーザーとデータベースを作成します。

```
cd /var/tmp
sudo -u postgres createuser --pwprompt zabbix
sudo -u postgres createdb -O zabbix zabbix
```

## 4. pgloader によるマイグレーション

pgloader をインストールし、MariaDB から PostgreSQL にマイグレーションします。
なお、pgloader は epel や PostgreSQL のリポジトリにはパッケージがありませんでした。検証用途かつ単発実行のため、サードパーティーのパッケージをインストールしましたが、 [pgloaderのソース](https://github.com/dimitri/pgloader) を make してもよいでしよう。

インストールします。

```
sudo dnf install -y https://pkgs.dyn.su/el8/base/x86_64/pgloader-3.6.2-1.el8.x86_64.rpm
```

スキーマ登録用SQLと pgloader に流し込むコマンドを用意します。

```
mkdir /var/tmp/pgzabbix
cd /var/tmp/pgzabbix
gzip -d -c /usr/share/doc/zabbix-server-pgsql/create.sql.gz > schema.sql
sed '/INSERT.*/,$d' schema.sql > create.sql
grep ^ALTER schema.sql > alter.sql
vi commands.load
```
```
LOAD DATABASE FROM mysql://zabbix:PASSWORD@localhost/zabbix INTO postgresql://zabbix:PASSWORD@localhost/zabbix 
    WITH include no drop, truncate, create no tables, create no indexes, no foreign keys, reset sequences, 
        data only SET maintenance_work_mem TO '1024MB', work_mem to '256MB'
    ALTER SCHEMA 'zabbix' RENAME TO 'public' 
    BEFORE LOAD EXECUTE create.sql 
    AFTER LOAD EXECUTE alter.sql;
```

マイグレーションします。

```
pgloader mysql://zabbix:PASSWORD@localhost/zabbix postgresql://zabbix:PASSWORD@localhost/zabbix
pgloader commands.load
```

動作確認として、まずログを確認します。

```
less /tmp/pgloader/pgloader.log
```

Encoding が UTF-8 であることを確認します。

```
mysql -u zabbix -p -e "SHOW CREATE DATABASE zabbix;"
sudo -u postgres psql -U postgres -l
```

テーブルを確認します。

```
mysql -u zabbix -p -e "SHOW TABLES FROM zabbix;"
psql -U zabbix -d zabbix -c "\dt" -h localhost
```

PostgreSQL のスキーマは public であることを想定していましたが、zabbix となっていました。
public というスキーマは既に存在するため、名前変更できなかったのかもしれません。
変更できなくても参照設定で対処できるので、このまま進めることにします。

## 5. TimescaleDB のインストールと適用

TimescaleDB をインストールします。

```
sudo dnf -y install timescaledb_12
```

TimescaleDB 用の設定（postgresql.conf の編集）は、 timescaledb-tune というツールが提供されているので、これを利用します。

```
sudo cp -p /var/lib/pgsql/12/data/postgresql.conf{,.default}
sudo dnf install -y https://packagecloud.io/timescale/timescaledb/el/8/x86_64/timescaledb-tools-0.11.0-0.el8.x86_64.rpm
sudo timescaledb-tune -pg-config /usr/pgsql-12/bin/pg_config
sudo diff -u /var/lib/pgsql/12/data/postgresql.conf{.default,}
```

最低限、以下の行が追加されていることを確認します。

```
+shared_preload_libraries = 'timescaledb'       # (change requires restart)
```

PostgreSQL を再起動します。

```
sudo systemctl restart postgresql-12
```

Zabbix データベースに TimescaleDB を適用します。

```
echo "CREATE EXTENSION IF NOT EXISTS timescaledb SCHEMA zabbix CASCADE;" | sudo -u postgres psql -U postgres zabbix
gzip -d -c /usr/share/doc/zabbix-server-pgsql/timescaledb.sql.gz > timescaledb.sql
cat timescaledb.sql | psql -U zabbix zabbix -h localhost
```

動作確認として、 history テーブルの状態を確認します。

```
psql -U zabbix -d zabbix -c "\d+ history;" -h localhost
                                          テーブル"zabbix.history"
   列   |        型        | 照合順序 | Null 値を許容 |      デフォルト       | ストレージ | 統計目標 | 説明
--------+------------------+----------+---------------+-----------------------+------------+----------+------
 itemid | numeric          |          | not null      |                       | main       |          |
 clock  | bigint           |          | not null      | '0'::bigint           | plain      |          |
 value  | double precision |          | not null      | '0'::double precision | plain      |          |
 ns     | bigint           |          | not null      | '0'::bigint           | plain      |          |
インデックス:
    "history_clock_idx" btree (clock DESC)
    "idx_16883_history_1" btree (itemid, clock)
トリガー:
    ts_insert_blocker BEFORE INSERT ON history FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
子テーブル: _timescaledb_internal._hyper_1_1_chunk,
            _timescaledb_internal._hyper_1_2_chunk
アクセスメソッド: heap
```

パーティション用の BEFORE INSERT トリガが作成され、子テーブルが存在することが確認できます。

## 6. MariaDB の停止

MariaDB は不要になったので、停止します。

```
sudo systemctl stop mariadb
sudo systemctl disable mariadb
```

## 7. Zabbix Server の設定と起動

PostgreSQL 接続用の設定をします。

```
cd /etc/zabbix
sudo cp -p zabbix_server.conf{,.default}
sudo vi zabbix_server.conf
sudo diff -u zabbix_server.conf{.default,}
```
```
--- zabbix_server.conf.default  2021-08-30 18:32:00.000000000 +0900
+++ zabbix_server.conf  2021-09-26 17:50:32.458100230 +0900
@@ -105,6 +105,7 @@
 # Mandatory: no
 # Default:
 # DBSchema=
+DBSchema=zabbix

 ### Option: DBUser
 #      Database user.
@@ -122,6 +123,7 @@
 # Mandatory: no
 # Default:
 # DBPassword=
+DBPassword=PASSWORD

 ### Option: DBSocket
 #      Path to MySQL socket.
```

いよいよ Zabbix Server を起動しますが、その前に、SELinux が有効になっている場合はいったん停止します。

```
sudo setenforce 0
sudo systemctl restart zabbix-server
```

管理画面からアクセスする場合の PostgreSQL 接続用の設定をします。

```
cd /etc/zabbix/web
sudo cp -p zabbix.conf.php{,.default}
sudo vi zabbix.conf.php
diff -u zabbix.conf.php{.default,}
```
```
--- zabbix.conf.php.default     2020-10-27 17:03:50.308617898 +0900
+++ zabbix.conf.php     2021-09-26 17:55:05.496106605 +0900
@@ -1,7 +1,7 @@
 <?php
 // Zabbix GUI configuration file.

-$DB['TYPE']                            = 'MYSQL';
+$DB['TYPE']                            = 'POSTGRESQL';
 $DB['SERVER']                  = 'localhost';
 $DB['PORT']                            = '0';
 $DB['DATABASE']                        = 'zabbix';
@@ -9,7 +9,7 @@
 $DB['PASSWORD']                        = 'PASSWORD';

 // Schema name. Used for PostgreSQL.
-$DB['SCHEMA']                  = '';
+$DB['SCHEMA']                  = 'zabbix';

 // Used for TLS connection.
 $DB['ENCRYPTION']              = false;
```

zabbix-web-deps が再インストールされたので、PHP のタイムゾーンを設定し直します。

```
cd /etc/php-fpm.d
sudo vi zabbix.conf
```
```
php_value[date.timezone] = Asia/Tokyo
```

変更を適用します。

```
sudo systemctl restart httpd
```

## 8. SELinux モジュールの生成とインストール

audit.log に denied ログが出力されていますので、audit.log からモジュールを生成し、インストールします。
ここでは大雑把にすべてのログから zabbix-server というモジュールを生成しています。

```
cd /var/tmp
sudo ausearch -m AVC | audit2allow -M zabbix-server
sudo semodule -i zabbix-server.pp
```

インストールできたので、 SELinux を有効に戻し、 Zabbix Server を再起動し、正常に起動できることを確認します。

```
sudo setenforce 1
sudo systemctl restart zabbix-server
sudo systemctl status zabbix-server
```

以上で作業は終了です。

## トラブルシューティング

検証中に遭遇したトラブルについて触れます。

### could not access file "$libdir/timescaledb-1.4.0": No such file or directory

* https://github.com/timescale/timescaledb/issues/1425

TimescaleDB を入れなおしたら直りました。

```
sudo -u postgres psql -U postgres zabbix

DROP EXTENSION timescaledb CASCADE;
CREATE EXTENSION IF NOT EXISTS timescaledb SCHEMA zabbix CASCADE;
```

### HINT:  Upgrade your license to 'timescale' to use this free community feature.

/var/log/zabbix/zabbix_server.log に出力されました。

* https://github.com/timescale/timescaledb/issues/2901

zabbix ユーザーに superuser 権限を付与しても解消されませんでした。
TimescaleDB を入れ直したら、直りました。


## 参考

* [How to deploy Zabbix on PostgreSQL with Timescale DB plugin - Zabbix Blog](https://blog.zabbix.com/how-to-deploy-zabbix-on-postgresql-with-timescale-db-plugin/13668/)
* [Second Zabbix Meetup Online 2020 in Russian](https://www.youtube.com/watch?v=soXukhwC-wQ) ※ロシア語です
* [MySQLからPostgreSQLへの移行](https://tech-ja.netlify.app/articles/ja518546/index.html)
* [pgloaderでMySQL→Postgresへの移行を行う](https://qiita.com/11ohina017/items/4a808e4fc03e1ac890ba)
* [PostgreSQL: Linux downloads (Red Hat family)](https://www.postgresql.org/download/linux/redhat/)