概要
Postfix で3000人規模の利用者がいるメールサーバを運用しています。利用者の登録情報(誰が登録されているか、転送先アドレスは何処か、など)は、別サーバで稼働している LDAP サーバに格納されています。
メールサーバ管理者と LDAP サーバ管理者が別人の場合、連絡不行届などが理由で、LDAP サーバは停止しているのに、メールサーバを起動してしまうことが有り得ます。このような事故が発生すると、Postfix は接続元に対して一時的エラーを通知してメールを受け取らないという挙動をするはずですが、そもそも Postfix を止めてしまった方が良いという場合もあります。筆者の場合は、停電からの復電作業手順書に、メールサーバと LDAP サーバの電源投入順序に制約を追加し、作業時間を増やしたくないという動機です。
本稿では、そのような LDAP サーバに対するヘルスチェック付きのメールサーバを構築する方法を述べます。
設定手順
ヘルスチェックスクリプトのインストール
ldap-health-check スクリプトを /usr/local/bin/
に置いて下さい。
そのスクリプトの引数として、Postfix の LDAP 設定ファイルを指定する --conffile
オプションと --debug
オプションの2つを指定して実行し、LDAP サーバと通信できていることを確認してください。
$ /usr/local/bin/ldap-health-check --conffile /etc/postfix/your-using-ldap-config --debug
DEBUG: LDAP search success: dn=ou=users,dc=example,dc=net
^C
ヘルスチェックサービスの作成
以下のようなサービス定義ファイル /etc/systemd/system/ldap-health-check.service
を用意します。
[Unit]
Description = ldap-health-check daemon
[Service]
ExecStart = /usr/local/bin/ldap-health-check --conffile your-using-ldap-configuration-file
Type = simple
Restart = always
StartLimitBurst = 1
[Install]
RequiredBy = postfix.service
この設定では、Restart = always
と指定して「常に再起動を試みる」、かつ StartLimitBurst = 1
と指定して「1回再起動を試みて失敗したら、そこで諦める」という指定をしています。ここで、「諦める」という指定になっているのが重要です。本稿の目的として、このヘルスチェックサービスが停止したら、その時点で Postfix も停止したいわけですが、うっかり StartLimitBurst = 0
と設定して、無期限に再起動を試みるという指定をすると Postfix は停止してくれません。ヘルスチェックサービスの再起動を試行している間は、RequiredBy
によって指定した依存関係が満たされていると見なされて、Postfix は停止されないようです。ですから、StartLimitBurst
を適当に指定して、ヘルスチェックサービスを明示的に 失敗 させる必要があります。
作成した定義ファイルを systemd に読み込ませます。
$ sudo systemctl enable ldap-health-check.service
$ sudo systemctl start ldap-health-check.service
この状態で、以下のようなメッセージが表示されるはずです。
$ systemctl status ldap-health-check.service
● ldap-health-check.service - ldap-health-check daemon
Loaded: loaded (/etc/systemd/system/ldap-health-check.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2020-03-19 22:03:25 JST; 32min ago
Main PID: 23220 (ldap-health-che)
Tasks: 1 (limit: 4698)
Memory: 11.8M
CGroup: /system.slice/ldap-health-check.service
└─23220 /usr/bin/perl /usr/local/bin/ldap-health-check
LDAP サーバが応答していない時、Postfix が停止することを動作確認
LDAP サーバの IP アドレスが、198.51.100.8 であるとします。メールサーバから LDAP サーバへの通信を禁止するには、メールサーバ上で、以下のようにダミーの経路を設定することがもっとも簡単です。
$ sudo ip route add blackhole 198.51.100.8
ダミーの経路が設定されると、ldap-health-check
スクリプトが、以下のようにエラーで異常終了するようになります。
$ systemctl status ldap-health-check.service
● ldap-health-check.service - ldap-health-check daemon
Loaded: loaded (/etc/systemd/system/ldap-health-check.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Thu 2020-03-19 22:46:15 JST; 9s ago
Process: 36413 ExecStart=/usr/local/bin/ldap-health-check (code=exited, status=1/FAILURE)
Main PID: 36413 (code=exited, status=1/FAILURE)
すると、Postfix も以下のように異常終了しているはずです。
$ systemctl status postfix.service
● postfix.service - Postfix Mail Transport Agent
Loaded: loaded (/lib/systemd/system/postfix.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Thu 2020-03-19 22:46:15 JST; 3min 53s ago
Main PID: 31077 (code=exited, status=0/SUCCESS)
Mar 19 22:21:14 mx1.example.net systemd[1]: Starting Postfix Mail Transport Agent...
Mar 19 22:21:14 mx1.example.net systemd[1]: Started Postfix Mail Transport Agent.
Mar 19 22:46:15 mx1.example.net systemd[1]: postfix.service: Succeeded.
Mar 19 22:46:15 mx1.example.net systemd[1]: Stopped Postfix Mail Transport Agent.
Mar 19 22:46:15 mx1.example.net systemd[1]: Stopping Postfix Mail Transport Agent...
Mar 19 22:46:15 mx1.example.net systemd[1]: Dependency failed for Postfix Mail Transport Agent.
Mar 19 22:46:15 mx1.example.net systemd[1]: postfix.service: Job postfix.service/start failed with result 'dependency'.
末尾から2行目に Dependency failed
と出力されていることがポイントで、ヘルスチェックサービスが停止しているために Postfix サービスを開始できないことが分かります。
LDAP サーバが復活した時、Postfix が再開することを動作確認
以下のような cron を設定して、10分に少なくとも1回は、Postfix の起動を試みるようにします。
3,13,23,33,43,53 * * * * root /usr/bin/systemctl status postfix >/dev/null || /usr/bin/systemctl start postfix
LDAP サーバへのダミーの通信経路を削除して、正常に通信できるようにします。
$ sudo ip route del blackhole 198.51.100.8
すると、10分以内に cron により Postfix の起動が試行されます。
先ほどのヘルスチェックサービスの設定で、StartLimitBurst = 1
と指定して、「再起動に1回失敗したら諦める」と設定してありますが、systemctl start postfix
コマンドが実行されると、その時点で、Postfix サービスが依存している別サービスの失敗回数カウンタもリセットされるので、少なくとも1回はヘルスチェックサービスの再起動が試行されます。したがって、この時点でヘルスチェックが成功すれば、Postfix も無事に起動されます。