start

certbot renewでApacheがCPU 100%に張り付くでござるの巻き

SSL証明書の期限が切れた状態でcertbot renewを行うと、ApacheプロセスのCPU利用率が100%となりハング状態になるっぽい。apachectlで止めようとしても(弊鯖はご存じのとおりFreeBSDなのでservice apache24 stopだが)、応答が返ってこずkillせざるを得ないという状況。環境は以下のとおり。

  • FreeBSD 13.0-RELEASE-p4
  • Apache 2.4.51
  • certbot 1.21.0
  • certbot-apache 1.21.0
  • Python 3.8.12
  • webrootモードで運用

weekly_certbot_enableでもって週次で証明書の確認&更新が行われるはずなのに、なんで切れてるの?そもそも期限切れになったからと言って、なんでhttpdがハング状態になるの?と疑問は尽きないのだが、ひとまず脇に置いといて、この状況に陥ったらcertbot certonlyを使って手動で証明書を更新してやる。

# certbot certonly --webroot -w /path/to/document_root -d example.com

証明書更新後、certbot renewでhttpdが暴走しないことを確認する(renewが正常に終われば暴走はしてない。)

それにしても原因は何なんだろうなー。以前、同様の状況が発生した時は、apacheやモジュールの更新を行っていたのでバイナリ間の何らかの不整合くらいで流したが、たぶん今回と同じ原因だったんだろう。さらにその以前は正しく動いていたような気がしなくもない(結構期限切れをやらかしていたので確証が持てない)ので、よくわかりません。

詳しい方教えてください。


(2021-12-24 追記)

確証はないけど、証明書更新後にapache reloadをしておらず、新しい証明書がapacheに認識されてないのが原因な気がする。

FreeBSDフォーラムの投稿のように、証明書更新後のフックスクリプトでリロードしてやれば解決しそうな気がする。

/usr/local/etc/letsencrypt/renewal-hooks/deploy/reload_apache24.sh
#!/bin/sh
service `echo $0|sed -e 's/.*\/\(.*\)_\(.*\).sh/\2 \1/'`

FreeBSDのSambaのビルドでncurses not availableが出てた

家鯖のFreeBSDのnet/samba413をビルドしようとすると、configureでncursesが見つからんと言われてコケるようになっていた。

ncurses not available, cannot build regedit
ncurses not available, but --with-regedit was specified

ncursesってbaseに含まれてたような…なんでエラーになんの?と思いつつ、念のためdevel/ncursesを入れても効果なし。Sambaの依存パッケージじゃないし、そりゃそうだ。

portsのバグを疑いしばらく放置&再試行してみたものの、一向に直る気配がない。そもそもエラーでググってもそれらしい結果が出てこないので、自分の環境の問題なのだろう。

では、どうやってシステムのncursesを直すか?

base.txzあたりでシステムを上書きすれば良さそうではあるものの、ncursesがどのtarballに含まれているのかが分からない。かといって、なんも考えずにtxz一式を展開した結果、設定ファイルなどがデフォルトに戻るのは避けたい。

そんな感じでモニョってたんだけど、たまたま目にしたFreeBSD-SA-00:68.ncursesに解決策があった。/usr/src/lib/libncursesでmake installするだけで良かったのだ。

# cd /usr/src/lib/libncurses
# make && make install

そしてSamba 4.13が無事ビルドできて一件落着。

# portmaster net/samba413

システムを飛ばしたときの復旧が不十分だったんだろうなぁ、たぶん。近いうちにbuildworldしとくか…

OpenZFSにRAIDZ Expansionのプルリクができてた

今まで気づかなかったが、2か月ほど前の6/11に、待望のRAIDZ ExpansionのプルリクがOpenZFSに立てられていた!!2018年のプリアルファコード以来目立った動きがなく、どうなっとんじゃーいって感じだったが、June 2021 FreeBSD Developer Summitでの報告の翌日、PRが作られた模様。

コードレビューは始まったばかり、というかまだ進んでない?ようでリリースはまだまだ先っぽい。OpenZFSプロジェクトの状況としては、現在は2.1リリース作業の真っただ中で、取り込まれるのはどんなに早くとも来年リリースのOpenZFS 2.2あたりと見込まれている。まぁ、かなり大きい変更なのでレビューもテストも時間がかかるだろうしね、仕方ないね。

PRの議論を見るに、拡張時の挙動である「既存データのストライプサイズは変更しない=データ/パリティ比率は変わらない」という点が、結構引っかかってるっぽい雰囲気。

RAIDZ ExpansionでRAIDZ vdevにストレージを追加した場合、vdevの物理ストライプ幅は拡張後のサイズとなる。対する論理ストライプ幅については、既存のデータは拡張前の幅、再書き込みを含む新規データは拡張後の幅となる。具体的な数値を当てはめると、HDD 5本のRAIDZ2プールをHDD 6本に拡張した場合、既存データは論理5ストライプ(データ/パリティ比=3:2)のままで、新規データは論理6ストライプ(データ/パリティ比=4:2)で記録される。データによってストライプ幅が異なること自体は、RAIDZの元からの仕様なので問題ないらしい。

一方で、この仕様のため既存RAIDZプールの使用率が高いほど、RAIDZ Expansionでのプール拡張後の実効空き容量は増えにくくなる。例えば、1TB×4のRAIDZ1プールに1TB書き込むとプール使用率は33%なのに対し、1TB×3のRAIDZ1プールに1TB書き込んだあと(この時点での使用率は66%)で1TBのHDDを追加しても使用率は66%のままとなる。既存データのデータ/パリティ比が変わらない以上、この容量オーバーヘッドは避けられない。

RAIDZ ExpansionでRAIDZプールは何度でも拡張可能だが、こんな感じゆえに、最小構成で始めて必要に応じて後からディスクを追加する、という戦略は取りにくいのは否めない。

使っていく中で既存データも新しいストライプ幅に置き換わり、このオーバーヘッドは徐々に解消されていく。このあたりの挙動は他のプロパティと一緒で、ZFSの思想っぽいというかなんというか。可及的速やかにプール容量を最大効率で増やしたい!という場合には厳しいだろうが、現実的にそんなケースがどれだけあるのだろうか?そもそもZFS的にはそんなカツカツ運用するなよって感じ?

拡張時に全データの再配置を行ってるにもかかわらず、既存データの論理ストライプ幅を変えないは、実装の簡便さと拡張中のRAIDZ1/2/3の冗長性担保が理由とのこと。

このまま無事マージされて欲しい。

certbotでthe following renewal configurations were invalidが出た

吹き飛んだ家鯖の環境再構築の一環でcertbotを再設定し、証明書の更新テストを行ったところ「the following renewal configurations were invalid」なるエラーが発生した。

$ sudo certbot --dry-run renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /usr/local/etc/letsencrypt/renewal/hoge.example.com-0001.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not due for renewal, but simulating renewal for dry run
(略)
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed without reload, fullchain is
/usr/local/etc/letsencrypt/live/hoge.example.com-0001/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /usr/local/etc/letsencrypt/renewal/hoge.example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/certbot/_internal/renewal.py", line 70, in _reconstitute
    renewal_candidate = storage.RenewableCert(full_path, config)
  File "/usr/local/lib/python3.8/site-packages/certbot/_internal/storage.py", line 468, in __init__
    self._check_symlinks()
  File "/usr/local/lib/python3.8/site-packages/certbot/_internal/storage.py", line 538, in _check_symlinks
    raise errors.CertStorageError(
certbot.errors.CertStorageError: expected /usr/local/etc/letsencrypt/live/hoge.example.com/cert.pem to be a symlink
Renewal configuration file /usr/local/etc/letsencrypt/renewal/hoge.example.com.conf is broken. Skipping.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
  /usr/local/etc/letsencrypt/live/hoge.example.com-0001/fullchain.pem (success)

Additionally, the following renewal configurations were invalid:
  /usr/local/etc/letsencrypt/renewal/hoge.example.com.conf (parsefail)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0 renew failure(s), 1 parse failure(s)

んん-?confファイルのパースエラー?というのは早計で、実際のエラーはその上に書いてある「certbot.errors.CertStorageError: expected /usr/local/etc/letsencrypt/live/hoge.example.com/cert.pem to be a symlink」というやつ。

要は/usr/local/etc/letsencrypt/live/ドメイン/以下のpemファイルは、/usr/local/etc/letsencrypt/archive/ドメイン/のpemファイルへのシンボリックリンクじゃないとダメらしい。liveの方を確認してみたら、確かにシンボリックリンクではなく実ファイルになっていた。

root@example:/usr/local/etc/letsencrypt/live/hoge.example.com # ls -al
total 32
drwxr-xr-x  2 root  wheel     7 Dec 21 08:06 .
drwx------  4 root  wheel     5 May  4 10:36 ..
-rw-r--r--  1 root  wheel   692 Aug 17  2019 README
-rw-r--r--  1 root  wheel  1834 Dec 21 08:06 cert.pem
-rw-r--r--  1 root  wheel  1586 Dec 21 08:06 chain.pem
-rw-r--r--  1 root  wheel  3420 Dec 21 08:06 fullchain.pem
-rw-------  1 root  wheel  1704 Dec 21 08:06 privkey.pem

確かな原因は分からないけど、Boot Environment環境への移行作業でやらかした線が濃厚。

となれば、シンボリックリンクにすれば解決するハズなんだけど、これまた「OpenSSL.crypto.Error」とかいうエラーが発生してダメだった。

そもそも同一ドメインに対して、何で「hoge.example.com.conf」と「hoge.example.com-0001.conf」の2つの設定があるんだ?というか、どちらのconfファイルも作った覚えはない。

色々試してみるとcertbot certonlyコマンドで証明書を取得すると、対応するconfファイルが自動で作られるっぽい。で、同名ファイル(同名ドメイン)が存在する場合、連番付きのconfになる模様。

それならばconfファイルと証明書を全部消し、証明書取得からやり直したところ、無事更新まで通った。confファイル置き場は/usr/local/etc/letsencrypt/renewal/ね。

VMのFreeBSD 13.0Rのrand_harvestqのCPU負荷が高い件

家鯖の消費電力がとある時点から急に増えた。その差は実に30Wで明らかに誤差ではない。

FreeBSDな仮想マシンを起動すると増えるのは明白だったが、原因として思い当たることはなかった。が、ふとProxmox VEのCPU使用率グラフを見たら、FreeBSD 13.0-RELEASEに更新したタイミングでCPU利用率が大幅に上がっているのに気付いた。

FreeBSD内でtopしても特段高負荷なプロセスはなかったものの、よーく見てみるとSystemが4~5%となっており、何かがCPUを使ってるのは間違いない。そこでtop -SPでシステムの個別の状態を見てみると、rand_harvestqが定常的に1CPUの40~80%を食っていた。

プロセス名から察するに、乱数のエントロピー収穫用のプロセスである。エントロピー収穫の詳細は、手前みそながらこちら

関連するシステム変数を見ても、特に変な個所はなさげ。しいて言えば、乱数源としてVirtIO Entropy Adapter (VirtIO RNG)とIntel Secure Key RNG (RDRAND)の2種類が使われてる点が仮想マシン特有ってところかな。

$ sysctl kern.random
kern.random.fortuna.concurrent_read: 1
kern.random.fortuna.minpoolsize: 64
kern.random.rdrand.rdrand_independent_seed: 0
kern.random.use_chacha20_cipher: 1
kern.random.block_seeded_status: 0
kern.random.random_sources: 'VirtIO Entropy Adapter','Intel Secure Key RNG'
kern.random.harvest.mask_symbolic: VMGENID,PURE_VIRTIO,PURE_RDRAND,[UMA],[FS_ATIME],SWI,INTERRUPT,NET_NG,[NET_ETHER],NET_TUN,MOUSE,KEYBOARD,ATTACH,CACHED
kern.random.harvest.mask_bin: 100001001000000111011111
kern.random.harvest.mask: 8683999
kern.random.initial_seeding.disable_bypass_warnings: 0
kern.random.initial_seeding.arc4random_bypassed_before_seeding: 0
kern.random.initial_seeding.read_random_bypassed_before_seeding: 0
kern.random.initial_seeding.bypass_before_seeding: 1

で、まぁ、色々と試してみたら、VirtIO Entropy Adapterが高負荷の原因だった。

その名の通り、VMでホスト側の乱数デバイスを使うための準仮想化デバイスなんだけど、ふつーに考えたら負荷は低くなるハズ。VirtIO RNGの乱数源は/dev/urandomにしてあるので、ブロックすることもないハズだし…。この辺、特にいじってはないんだけどなー、謎。

準仮想化で負荷が高くなっては本末転倒なので、VMからVirtIO RNGを取り除いて運用することにした。FreeBSD側ではIntel Secure Key RNGが動いてるので問題はないでしょう。

これで消費電力は無事元の水準に戻り、お財布の平和は保たれたのであった。

  • start.txt
  • 最終更新: 2019-08-19 11:45
  • by Decomo