Ruby のフルタイムコミッタとして最初の1ヶ月でやったこと

Ruby の フルタイムコミッタとして最初の1ヶ月でやったこと|ANDPAD Advent Calendar 2022 この記事は ANDPAD Advent Calendar 2022 の 9日目の記事です。

こんにちは柴田です。

Ruby のフルタイムコミッタとして活動を開始した 11/7 から 12/1 までに行った Ruby の開発についてご紹介します。

毎日多くの時間を Ruby に費やす事ができるようになり、最初に手をつけたのはつぎはぎの時間では集中して解決まで持っていく事が難しかった ruby-lang.org の裏側にあるサーバー群のリプレイスです。

今回は複数のサーバーのうち、neon と呼ばれる debian で稼働し続けていたメールサーバーを別の何かしらの SaaS またはクラウド環境へ同等の機能を有したまま移設を行う部分を担当しました。この neon というサーバーは私が Ruby コミッタになった10年ほど前から NaCl の shugo さんが管理する Xen 環境で稼働を続けていましたが、2022 年内には廃棄を行いたいという事で11月にアンドパッドに入社するタイミングでデッドラインを 11 月末に設定して9月ごろから少しずつ準備を行なっていました。

まずはこの neon が有する機能をご紹介します。

neon の初期構成図

  • dovecot で稼働している IMAP サーバー
  • mailman で稼働しているメーリングリスト
  • postfix で稼働している ruby-lang.org の SMTP サーバー

これらを可能な限りダウンタイムなく別の何かへ移行するというのが今回のゴールです。当初はサーバーを AWS の EC2 のインスタンスへ持っていくことも考えましたが、昨今はクラウド環境においてもメールサーバー、特に送信サーバーを構築することは制限が多く、ふとしたタイミングで spam 判定などを行われた結果 ruby-lang.org のメール機能、例えば matz@ruby-lang.org へメールが到達しないというような状況は避けたいのでサーバーをそのまま構築するということは最初の選択肢から外しました。

また、AWS の SES を用いることも考えましたが、mailman を AWS SES と連携させることは簡単ではなさそうということがわかり、この選択肢も一旦外しました。

上記の3つの機能はメールの送受信という関係にあり、いずれも密結合している機能群でしたがサーバー内の設定や用途を改めて確認していくと以下の2点に気がつきました

  • IMAP サーバーは bugs.ruby-lang.org で使用するメールデータの吸い出しにしか使っていない
  • postfix は Ruby コミッタないし、aliases で定義される複数のグループ向けのメールリレーとしてしか使っていない

mailman はメーリングリストという都合上、送信サーバーの postfix は必要となるため、まず上記の2つの機能をサーバーから分離していく戦略を取りました。具体的には

  • Google Domains へ ruby-lang.org を移管し、google domains が提供する email の転送機能を使って Ruby コミッタ宛の alias を実現する
  • Google Workspace を契約して Google Groups を用いて mailman 以外のグループ向けのメーリングリストを実現する
  • Google Workspace にbotアカウントを作成し、そこに送信したメールを IMAP アクセスを開放して bugs.ruby-lang.org から取得する

という置き換えを順次行なっていきました。1行でサラッと書いてはいますが、実際には shugo さんによる各種サービスの契約と、私が管理画面から設定をぽちぽちと設定しては動作チェック、というのをそれぞれ1日くらいずつ費やしています。特に IMAP を使う連携を担うコードは、mock を使ってテストを行なっても全く意味がなく、botアカウントでログインしてテストを実行しては GMail の IMAP の挙動を確認しながらデバッグ、という繰り返しでした。

ここで Google Domains と Google Workspace が提供する MX レコードへと設定を変更したところ、Ruby コミッタのメールアドレスである hsbt@ruby-lang.org を別の転送先へ転送する、ということはできるようになりましたが、メーリングリストのアドレスは ruby-core@lists.ruby-lang.org ではなく、ruby-core@ruby-lang.org という個人のアドレスと同じドメインでも届くようにしてあり、そのアドレスが広く使われている、ということに気がつきました。

これは完全に自分の計画ミスでしたが、Google Domains の転送を使って ruby-core@ruby-lang.org 宛のメールを ruby-core@neon.ruby-lang.org へ転送することで、メーリングリストとしてのおおよその機能は引き継げることに気がつき当面はこれで乗り切ることにしました。

dovecot をなくした構成

ここまではトラブルはあったものの最終的には解決できたため順調でしたが最後の mailman を移行する部分で想像以上に時間を使ってしまいました。当初、外部ユーザーへ開放した Google Workspace の Google Groups へ移管すれば良いと計画を立て、mailman のメンバーリストをインポートする作業を行なっていましたが、ここで Google Groups のメンバーインポートには以下のような制限があることを発見しました(具体的な制限を示すドキュメントは見つかりませんでした...)

  • Google Groups の UI からは csv などを使ったメンバー追加ができず、さらに数千のメンバーをアドレスの列挙で追加する事ができない
  • Google Workspace の admin 画面より、グループメンバーの追加から csv インポートを実行すると 5000-8000 くらいインポートを行った後に全て失敗する

Google の公式ドキュメントを読むと 1日に追加できるメンバーには制限があるらしい、という記述から上記の二つ目の失敗はこの制限に引っかかったと考え、全てのメーリングリストのアドレスの総数2万程度をインポートしては成功したアドレスだけを除外し、後日再びインポートという作業を繰り返していました。

最終的に Google Groups へメンバーの登録は行う事ができましたが、実際にテストを行なってみるといくつかのグループのみ送信したメールが全て google によって spam と判定されて reject されるという事態が生じました。グループの設定を変更してみたり、バウンスしてしまう送信先アドレスを全て削除(これも画面から目視)してみたりしたものの効果がなく、Google のサポートに相談して提案された Google の IP レンジを GMail のホワイトリストに追加する、という手段も効果がなく手詰まりとなりました。辛い。

もうメーリングリストの移設は諦めるか、または最初に選択肢として入れた AWS での自前構築、ということも考えましたが、shugo さんが MailmanLists というマネージドの mailman を提供するサービスを発見し、こちらのサービスを契約しメーリングリストとしての機能をテストしたところ行けそうだ、という感触を得たため Google Groups に移行できないメーリングリストはこのサービスを使うことにしました。なお、この時点で 11/24 となっており、サーバー廃棄まで1週間を切っていました。

指定したリストへメールさえ正しく配信してくれるのであれば、あとはサービスが提供する機能と私たちがやりたいことのすり合わせを行うだけなので、いくつかテストを行なったところ

  • neon の中で自分たちで拡張を行っていた python のプラグインに依存した部分が動かない
  • shugo さんが mailman3 を契約してきた(!)ので、neon で使っていた mailman2 ではみた事がない設定があった

という事がわかったため、存在しうるメールヘッダを用いて従来利用していた機能が動くように以下のような変更を加えました。

https://github.com/ruby/b.r-l.o/compare/a1fae7203cd6db10c3ba1986897f6346a07bb5d1...b676c20b2921e37f1ca77c826f96d212dfeb0af0

これも IMAP のデータのため、いきなり本番ないし staging でテストを行うしかなく、多くの人にテストメールが送信されてしまいましたが、なんとか redmine と mailman3 で新規稼働予定のメーリングリストの連携の目処を立てました。その後は Google Groups へ移行する事ができなかったメーリングリストについて、Mailmanlists へ移行することを決め、既存の mailman2 のデータをサポートと連携して全てインポートすることに成功しました。

最終的な構成

こうして、無事 neon が提供していた機能を Google Domains, Google Groups, Mailmanlists へと移行を行うことに成功し、12月1日に neon をシャットダウンし、長きにわたって ruby-lang.org と Ruby 開発者を支えてきたサーバーを退役する事ができました。お疲れ様でした。図を見ても分かる通り、Mailmanlists の部分を Google Groups に置き換えることができればメールのリレーの数も少なく複雑性を下げることができるので、Google Groups への移行は引き続き挑戦していこうと思います。

今回はフルタイムの Ruby 開発者として行ったメールサーバーの移設についてご紹介しました。メールサービスはクラウド事業者が提供するマネージドサービスを使う事がもはや定番のため、個々の技術要素には目新しい点はありませんが、インフラ環境の移行や技術選定、複雑な状況と解法の考え方などが皆さんの参考になれば幸いです。

おわりに

現在、アンドパッドでは一緒に働く仲間を大募集しています。
ご興味を持たれた方はカジュアル面談や情報交換のご連絡をお待ちしております。

engineer.andpad.co.jp

hrmos.co

明日は、データグループのエンジニアの森さんがデータエンジニアの認定資格試験を受験した際の受験記を公開してくれる予定です!お楽しみに!