エンジニアリングリードとして駆け抜けた2025年:抱え込みを捨てて「決断」を軸にするまで

この記事は 🎄GMOペパボ エンジニア Advent Calendar 2025 - Adventar の21日目です。

前回の記事 エンジニアリングリードになって半年が過ぎました(前編) - rsym’s diary でふりかえりの前編を出してから2ヶ月も経ってしまいました。間をあけすぎですね💦。2025年のエンジニアリングリード(以下EL)としてのふりかえりという形で後編を記載します。この2025年4月〜12月の9ヶ月間は、「リードとしての振る舞い」を模索し、自分の中の責任感の置き所をアジャストし続けた期間でした。

なお、ELとはなにか?具体的に手がけた業務などは前編にて記載しているのでそちらをご覧ください。

「自分が決めないと(でも決められない)」という呪縛

就任してからしばらくの間、私は「ELになったのだから、自分が誰よりも動いてリードしなければならない」という強い思い込みを持っていました。具体的には、以下のようなことまで「自分の手」で完結させようとしていました。

  • スクラムイベント(レトロスペクティブやプランニング)の進行や場作り
  • チームビルディングのための施策立案と実行
  • 進行中のプロジェクトにおける細かな進捗管理や技術的判断

しかし、現実に起きていたのは、責任感ゆえにあらゆるボールを自分一人で抱え込んでしまい、思考や行動が追いつかずに停滞してしまう……という本末転倒な状態でした。

プロジェクトマネジメントにおける試行錯誤

8月からは大規模なパブリッククラウド移行プロジェクトが始まり、プロジェクトマネジメントを担当することになりました。ここでも当初は、管理の軸をどこに置くべきか悩む日々が続きました。

その中で、前述した「抱え込み」から脱却する大きな一歩となったのが、「ミニプロジェクト化」と「権限移譲」の実施です。

これは私一人のアイデアではなく、チームのシニア・ミドルエンジニアから「こう進めてはどうか」という提案をもらったことがきっかけでした。 その提案を受け、私はそれを具体的な形に落とし込み、各メンバーに進行を任せるという意思決定を行いました。

自分ですべてを詳細に管理するのではなく、機能を切り出して任せる。自分は「期限」と「遅延の見極め」、そしてそれをジャッジするための「マイルストーン策定」という、より高い視点での振る舞いにシフトすることを意識しました。

正直なところ、今のプロジェクトが「順調です。楽勝です。」といえるほど、まだ十分な手応えを得るまでには至っていません。しかし、この経験を通じて得た大きな学びがあります。それは、プロジェクトの進め方に限らず、何かを始める時や考える時は、初めから周りの力を借りてアイデアをもらったほうが良いということです。自分は、集まったアイデアをもとに最後の「決断」を下し、その後の「結果」に責任を持てば良い。そう思えるようになったのは大きな変化でした。

ELがすべてを一人で企画し、抱える必要はありません。チームでの議論をしっかりと聴き、時には意見を出し、それらを咀嚼した上で、最終的に「やる・やらない」の旗を振る。自分は、集まったアイデアをもとに 最後に「決断」を下し、その後の「結果」に責任を持つ 。これこそが、今の自分に求められている「マネジメント」としての本当の役割の一つだと気づけました。

ピープルマネジメント:個に向き合うことで見えたもの

こうした組織的な動きの模索と並行して、ピープルマネジメントにおいても新しい試みを始めました。

もともと1on1自体は定期的に実施しており、メンバーの悩みを聞いたり、その場だからこそ話せる本音を引き出したりすることを大切にしていました。ただ、振り返ってみると、どうしても自分も相手も「今起きていること」に意識が向きすぎてしまい、目先の課題解決だけで時間が終わってしまうことも少なくありませんでした。

そこで、下半期からは意識的に「先のこと」にフォーカスする問いかけを増やしました。

特に意識したのは、「曖昧ならそれでもいいし、ふわっとしていてもいい。もしペパボでの現在の業務を一度無視して、自分のキャリアをわがままに決められるとしたらどうしたい?」という聞き方です。

会社や組織の枠組みを一度外し、あえて「わがまま」を許容して対話してみたところ、今まで見えてこなかった意外な発見や、本人が本当に伸ばしたいと思っているスキルが次々と見えてきました。今この瞬間の困りごとを解決するだけでなく、一歩先の未来を一緒に描くことで、メンバーそれぞれの「人となり」をより深く理解する良いきっかけになったと感じています。

最後に

ここまで読んだ方は「ペパボのエンジニアリングリードって、エンジニアリングマネージャとほぼおなじかな?」と感じている方が多いと思います。 はい。その通りです。エンジニアリングマネージャ(以下EM)に近い役割が求められます。といっても事業部によって色があって一概には言えないのですが、EMのようなものと思ってもらえると良いと思います。

EMに求められる意思決定とそこに至るまでの解像度が少しだけ鮮明になった。そんな2025年だったと思います。といっても「一人前のEMになれましたか?」と聞かれると答えは「No」となります。来年は「Yes」と答えられるようになりたいです。 そのためには「もっと人を動かす力」を身につける必要があると考えています。たとえばパブリッククラウドの移設プロジェクトにおいて、期限までに完遂させるために対象の機能がまだ多いこと、移設にあたってのコスト管理(プライベートクラウドより高価なので与実管理がより重要になる)などの課題があります。この課題をチームメンバーと常に議論し、アクションを決めて、実行を促す。以前の自分だったら「アクションの中身まで自分がすべて決めよう」として、結果として何も進まない……というオチになっていたはずです。

2026年の末に「一人前のEMになれましたか?」と聞かれたら、自信を持って「Yes」と答えられるように。この新しい軸を武器に、また一年向き合っていこうと思います。

エンジニアリングリードになって半年が過ぎました(前編)

2025年4月1日に、GMOペパボ株式会社技術部のエンジニアリングリードに就任しました。 気が付いたら10月に入っておりもう半年が過ぎました(早いですね💨)。 せっかくなので半年間の振り返りをしようかと思います。

半年間の取り組みをいろいろ書いていたら文章量が多くなってしまったので、前編・後編に分けることにしました。 前編は半年間で取り組んだことを中心に、後編ではふりかえりと今後のやっていきについて書きたいと思います。

エンジニアリングリードとは?

弊社のエンジニア職は、4等級以上の職位になるとプロフェッショナルとマネジメントに分かれます。 エンジニアリングリードはマネジメントの4等級に該当します。 マネジメントの職務は「部門方針・目標および全社技術方針に基づき、部門全体の技術選択および技術者組織について方針を決定し、実行します。」と定められています。 事業部CTO・シニアエンジニアリングリードと協力してこの職務を果たしていくことになります。

詳細は過去に書いたブログをご参照ください。

エンジニアリングリードに就任しました - rsym’s diary

この半年間でやったこと

1. 組織体制の変更に伴うスクラムのリブート

エンジニアリングリードに就任する前もスクラムに取り組むための体制の整備には取り組んできましたが、チームの人数・メンバーが大きく変わりました。 技術部 技術基盤グループは、旧「技術基盤グループ」と「プラットフォームグループ」が統合され、ひとつのチームとして再始動しました。 統合に伴いミッションもリブートされたため、スクラムも新体制に合わせて再構築する必要がありました。

具体的には、スプリント内で全員がタスクについて協議しあい、それをふりかえる仕組みの整備を進めました。 旧体制で実施していたスクラムの仕組みをベースにしつつ、直近で力を入れているプロジェクトに軸足を置いた運用へと移行しました。 ちなみに弊社のテックブログで「絶対倒すタスク」通称「ZETTAO」が登場したのも、このスクラムの振り返りイベントであるスプリントレトロスペクティブで生まれたものです。 tech.pepabo.com

2. 1on1

1on1は就任前から継続していましたが、就任後は技術部を横断した1on1にも取り組むようになりました。 技術部には私が主に関わっている「技術基盤グループ」のほかに「ホスティングインフラグループ」というホスティングに関する事業のインフラを担うチームがあります。 このチームで求められる技術スタックにはオンプレミスの要素やメールホスティングの要素があり、私が取り組んできた業務と通ずる部分があります。 このような背景から、後述の「5. エンジニアの評価」にてホスティングインフラグループの一部メンバーの評価を担当することになりました。 一方で通ずる領域があるとはいえ、その方たちの業務を詳しく把握しているわけではありませんし、普段から一緒に業務しているわけではありません。 そこで、お互いの普段どんな仕事をしているのか・興味のある技術領域は何か・今後頑張りたいことはなにかといったことを1on1を通じて話していくことにしました。 頻度は月一を目安に実施していますが、メンバーを観察してスポットで実施した方が良さそうと判断した時は都度声をかけて1on1することもあります。

自分の場合、1on1はキャッチアップ型で進めることが多いです。キャッチアップ型とは枠組みは特に持たず「メンバーが話し合いたい事柄を告げてもらい、自分は耳を傾けることに徹する方式」です。 この方式は「創造的な議論」をしやすいメリットがある代わりに、「心理療法」「不満を吐き出す場」で終わってしまう場合もあるというデメリットがあります。 もちろん理想は常にオープンな場での話し合いができることですが、現実としてそうはいかないことがあると思います。 例えば、チーム全体に対してだとどうしても話しにくいこと、その場ではうまく表現できず消化不良に終わってしまうことなどです。 これを野放しにすると、その方にとってはフラストレーションになり、お互い不幸になってしまいます。 そういったことに対してアンテナを張れるようにキャッチアップ型を採用しています。 また、ホスティングインフラグループのメンバーとの会話においても、取り組んでいる業務やチャレンジしていることなどについて話す目的でも、このキャッチアップ型はとてもマッチしていると考えています。

3. 登壇

2025/5/9に開催された「Road To SRE NEXT@福岡」にてLTをしてきました。 2024年の下半期くらいからメールのスパム対策ソフトウェア「rspamd」を扱う場面が増えてきて、これを通じてスパム対策にあたってログから収集された情報に基づきデータドリブンで対策を強化できないか?という取り組みをしていました。 それを発表させていただきました。 昨今、メールホスティングを扱うサービスは決して多くはないと思います。 不安もありましたが、実際には予想以上の反響があり、懇親会でも多くの方が興味を持ってくださいました。発表してよかったと思える経験でした。

余談ですが、福岡の飯は美味しい😋

speakerdeck.com

4. エンジニアの評価

エンジニアリングリードに就任して初めて取り組んだことその1です。 ペパボでは半年に一回(4等級以上は年に一回)エンジニアを評価する制度があります。 各エンジニアに専門職上長と所属上長がついて、半年ごとに各エンジニアのチャレンジや実績について話し合い評価を決めています。 視点は多々ありますがたとえば以下のような視点でエンジニアを評価します。

  • 事業目標を達成するためにどのように技術的な課題を解決してきたのか
  • 事業を支えるための理想像としてどのようなエンジニアリングをしていくべきか、理想像の達成を阻害する課題をどのように解決し、改善に結びつけているか
  • ペパボのプレゼンスに寄与するような活動を組織内外問わずに取り組んできたのか

ここで注意すべき点として、評価者はただ淡々と点数をつける立場ではないということです。 評価者は、被評価者となるエンジニアに等級要件について正しく理解してもらうために支援・目線合わせをしたり、 より高い点数を得るためにどのような取り組みをすべきか、あるいは実績がすでにあるならどのようにアピールすべきか、 継続的に支援していく使命も課せられています。

以下に弊社のエンジニア組織と制度について書かれているので参考にどうぞ。 弊社ではエンジニア職・マネジメント職が等級で分けられており、等級ごとに職能要件が設けられています。 それに相当する実績を残したかが評価の軸となります。 また弊社ではいわば追認で新たな職位に着くことができる制度となっており、 現在の等級よりさらに上を目指す場合、「上の等級に相当するだけの実績をすでに残しているか?」という視点が求められます。 このような視点を身につけてもらうために支援するのも評価者の役割となります。

tech.pepabo.com

ここからは私個人が評価者として意識していることを書きます。 評価者になるにあたり、エンジニアリングリードに就任する前、つまり3等級エンジニアだった時代に私の評価者であった @hiboma さんからの教えを大切にすることを意識しています。 詳細は割愛しますが端的には以下の5つです。 先述した内容と通ずる部分もあります。

  • 評価者 is not 採点官
  • 評価プロセス is not プロジェクトマネジメント
  • 評価者 is not 指導者
  • 評価者は傭兵として支援
  • 評価者はセコンドとして支援

実際 @hiboma さんにはたくさんのことを支援していただきました。 当時、被評価者であった私目線では「点数を付けられているという感覚はほとんどなく、気づいたらいろんなことに取り組んでおり、気づいたら相応の点数をつけられるだけの実績を積んでいた」そんな感覚でした。 この教えは、個人的には評価者の理想像の姿だと思っており、私もそうなるべく評価者としてのスキルを磨かねばという今日この頃です。

5. 採用活動

エンジニアリングリードに就任して初めて取り組んだことその2です。 以下に取り組むようになりました。

  • カジュアル面談(これは就任以前も実施したことあり)
  • 中途採用の書類選考
  • 中途採用の一次面接官
  • 採用のための定例・キープへの参加

また、採用というよりはペパボのファンを増やすことが主目的ですが、7/17に開催された「ペパボおごりナイト」にも参加し、来場いただいた様々な方と交流しました。 クリエイターの方はもちろん、エンジニアの方も来ていただいており、そのエンジニアの方が普段やっていることや私が普段やっていることなど、いろいろお話できました。

このイベントに参加いただいている時点で、その方たちはすでにペパボのファンである、あるいはペパボにちょっと興味を持っている、というような方々だと思います。 すでにファンである方にはもっとペパボを好きになってもらい、ちょっと興味を持っている方はペパボのファンになってもらう、そんなきっかけが生まれる楽しいイベントでした。

また、「3. 登壇」で記載した「Road To SRE NEXT@福岡」でも、発表後の懇親会を通じてペパボのメールホスティングの運用に興味を持っていただきました。 この活動も広義にはファンを獲得する活動であり、話を聞いたエンジニアが将来転職を考える時に「ペパボ」が選択肢になってくれたらいいなという種まきの意味合いも込められています。

6. エンジニアリング

さてここまではマネジメントや採用に関わる活動について書きました。 でもエンジニアであることを忘れてはいけません。 エンジニアリングリードはエンジニアリングでも結果を出すことが求められます。 現在私が特に関わっているサービスとしてカラーミーショップとSUZURIアルバム(旧30days Album)があります(それ以外に関わることもあります)。 大まかには以下のような取り組みをしてきました。

  • カラーミーショップのメールホスティングの運用
    • スパム対策ソフトウェアの導入を通じたメールのセキュリティ対策の強化
    • 詳細は先述の「3. 登壇」の資料をご参考にしてください
  • カラーミーショップの特定機能のパブリッククラウドへの移設(主にプロジェクトマネジメント)
    • プライベートクラウドで運用していた機能について、サービスのスケーリングや信頼性に重きを置いたアーキテクチャを実現するための移設に取り組みました
    • 自分はデータ移行に関する部分を担当しつつ、プロジェクト全体のマネジメントを実施しました
  • カラーミーショップのセキュリティ対策
    • 弊社では各商材で毎年セキュリティに関する施策を事前に宣言しそれを年内に着実に完遂するための取り組みを実施しています
    • 技術基盤グループはカラーミーショップのプラットフォームに関するセキュリティ施策を担っており、私はそれを達成するために技術基盤グループのメンバーを巻き込んで遂行しています
  • SUZURIアルバムのオンプレミス環境の継続的なリプレース運用と各種ソフトウェアのアップデート対応(主にプロジェクトマネジメント)
  • SUZURIアルバムのセキュリティ対策
    • 「カラーミーショップのセキュリティ対策」と同様のことをSUZURIアルバムでも実施しています
  • そのほかにも各サービスの障害対応なども実施しています

エンジニアリングを担いつつ、プロジェクトマネジメントに近いこともやってきました。 お恥ずかしい話、後述する新規に取り組んだことをはじめ苦戦した部分があり、プロジェクトマネジメントもうまくコントロールできないことが多々あったと思います。 それでもプロジェクトに関わっていただいたメンバーが、皆優秀な方で皆様のおかげでプロジェクトを完遂できたと思います。 かかわっていただいた皆さん、本当にありがとうございました。

前編はここまで

これだけで長くなってしまったので一旦ここまで🙏 この半年間で取り組んだことを書きました。 後編では「ふりかえり」「今後どうしていくか」を中心に書こうと思います。

エンジニアリングリードに就任しました

わたくし rsym1290 は2025年4月1日より、GMOペパボ株式会社 技術部技術基盤グループのエンジニアリングリードに就任しました。

※エイプリルフールではありません。本当です。

エンジニアリングリードとは?

弊社のエンジニア職位制度はこちらに記載されています。 合わせてご参照ください。

ref:エンジニア組織と制度 - Pepabo Tech Portal

エンジニア職は4等級以上の職位に就任する場合、プロフェッショナルとマネジメントに分かれており、エンジニアリングリードはマネジメントの4等級に該当します。

マネジメントの職務は以下のように定義されています。 エンジニアリングリードはこれをシニアエンジニアリングリード・事業部CTOと協力してこの職務を果たしていくことになります。

部門方針・目標および全社技術方針に基づき、部門全体の技術選択および技術者組織について方針を決定し、実行します。

エンジニアリングリードとマネージャ

上述の説明を聞いて、いわゆる管理職としての「マネージャ」を想像した人もいるのではないでしょうか? 実際マネージャに求められる要件と類似している部分があります。 ですが、弊社ではマネージャ・サブマネージャは別の職位として存在します。

目標管理・ピープルマネジメント・採用活動・チームビルディングといった活動はエンジニアリングリードもマネージャも一緒に遂行していきます。大きな違いとして、マネージャ・サブマネージャは勤怠管理やペパボの文化遵守などを通じて組織を作ることに貢献することが求められるのに対し、エンジニアリングリードは担当領域の技術選定や意思決定を通じて、チームを牽引して技術的な課題を解決していくことが求められます。

就任のきっかけ

私は2023年の上半期あたりから、エンジニアリングリードというキャリアを意識するようになりました。 詳しい経緯は以下の記事に記載しているのでそちらも参照ください。

リーダー職に就任しました - rsym’s diary

要約すると、これまで携わった大規模プロジェクトにて他事業部のエンジニアやGMOグループのエンジニアと協力してプロジェクトを遂行してきた実績より、マネジメントで力を発揮できそうというアドバイスを受けたことをきっかけに、このエンジニアリングリードという職種を意識し始めました。

また、私の所属する部署は2025年1月に組織編成がありました。 組織編成に伴い、新しい部署のメンバー同士の結束を高めるために1月末にLT会を企画しました。 そのLT会で、2025年の目標として「エンジニアリングリードになる」という宣言をしました。 詳細は、後日弊社のテックブログで公開します。

就任にあたって評価されたポイント

エンジニアリングリードの打診があったのは2025年2月末で、LT会での宣言からわずか1ヶ月後のことでした。 打診そのものは非常に嬉しいことなのですが、まさかこんなに早く就任の話がくるとは思ってもいませんでした。

ペパボではエンジニアリングリードは任命制となっており、これまでの実績・評価に基づいて任命されます。 30days Albumのデータセンター移設プロジェクトをはじめとした長期にわたる様々なプロジェクトを牽引し完遂させた実績(いわばプロジェクトマネジメント力)が評価されたと理解しています。 また、リーダーになった後も1on1を通じたチームの心理的安全性を確保するための活動や、カラーミーショップのプラットフォームのセキュリティ対応に関するプロジェクトを完遂させた実績を残し、これらの活動も評価されたと思います。

エンジニアリングリードとして目指していくこと

エンジニアリングリードがやることは先述した通りです。 その上で私が所属する技術基盤グループのエンジニアリングリードならでは、もっというと今エンジニアリングリードになったことを受けての責務もあると考えています。それは「新体制でスタートしたチームを牽引し、ペパボのサービスのためのよりよいプラットフォームを提供できるチームを作り上げること」ではないかと私は考えています。 このように考えたのは主に以下2点からです。

一つは新しいチームを作り上げていく責務があることです。技術部技術基盤グループは実は組織編成によって2025年1月に発足しました。チームメンバー自体は編成前のメンバーを中心に構成されていますが、グループとして新しいスタートを切ったことになります。新しいチームをビルディングしていくこと、チームメンバーを育てていくこと、採用を通じてチームに新しい風を呼び込むこと、チームを作り上げるためにやることはたくさんあると思います。

もう一つは意思決定する責務がより大きくなったことです。リーダーの時もこの責務は決してなかったわけではありませんが、エンジニアリングリードとしてこの責務はより大きくなったと思います。私は、技術部技術基盤グループというペパボが提供する様々なサービスのプラットフォームを横断的に支えるチームに所属しています。いわゆる商材を持ったチームではありませんが、意思決定すべきことはたくさんあると思います。様々なサービスを提供するペパボにとって、プラットフォームの理想的な姿は何か?サービスを利用していただいているユーザの皆様にとっての利用体験の向上につながるプラットフォームとは何か?さらには開発者にとっての開発体験・生産性の向上につながるプラットフォームとは何か?決定すべきことは多々あります。もちろんこれを私一人で決めるわけではないですし、もっというと一人で決められるものではないと思います。

最後に

就任は4月1日からですが、それ以前からエンジニアリングリードとしての振る舞いを少しずつ意識してきたつもりです。責務の多さ・大きさに驚いており、考えることも一気に増えて混乱しているのが正直なところです。またエンジニアリングリードを名乗るに相応しい振る舞いができているかと言われると、まだまだ道は長いと思っています。 それでも、自分がエンジニアリングリードに任命されたのは、この新しい技術基盤グループを牽引してほしいという期待があるからこそだと思っています。技術基盤グループが良くなっていくかは私にかかっている。。。というと思い上がりが過ぎるかもしれませんが、片棒は担いでいると思います。 「技術基盤グループのおかげでペパボのサービスがよくなった!」そう言ってもらえるように頑張っていきたいと思います!

AstroNvimのyankにおけるクリップボードへのコピーを無効にする

少し前から AstroNvim を使うようになった。 導入するだけで洗練されたUIですぐにnvimを使えるしプラグインもまとまっていてとても良い。

ただ個人的に馴染まなかったのがyankした時にクリップボードにもコピーされること。 yankでクリップボードにコピーされることで、想定してなかったペーストが起きたりでちょいストレスになってた。 AstroNvimのデフォルトに適用しようと頑張ったけど、どうしても手癖を矯正できなかったので、クリップボードへのコピーを無効にした。

デフォルトでクリップボードが有効になっている

vimのオプションに opt.clipboardというのがある。 これに unnamedplus が入っているとyankした時にクリップボードにもコピーされる。 luaのコメント通りSSHセッションではこれは無効化されて、ローカルでの操作のときに unnamedplus が有効になる。

github.com

    if not vim.env.SSH_TTY then -- only set `clipboard` if in SSH session and in neovim 0.10+
      opt.clipboard = "unnamedplus" -- connection to the system clipboard
    end

無効にする

~/.config/nvim/lua/plugins/astrocore.luaをいかのように修正すればよい。

  • 行頭の if true then return {} end を削除するかコメントアウト
  • vim.opt.clipboardを空にする設定を入れる
❯ cat ~/.config/nvim/lua/plugins/astrocore.lua
⭐️↓を削除 or コメントアウト
-- if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE

-- AstroCore provides a central place to modify mappings, vim options, autocommands, and more!
-- Configuration documentation can be found with `:h astrocore`
-- NOTE: We highly recommend setting up the Lua Language Server (`:LspInstall lua_ls`)
--       as this provides autocomplete and documentation while editing

---@type LazySpec
return {
  "AstroNvim/astrocore",
  ---@type AstroCoreOpts
  opts = {
    -- Configure core features of AstroNvim

...

    -- vim options can be configured here
    options = {
      opt = { -- vim.opt.<key>
        relativenumber = true, -- sets vim.opt.relativenumber
        number = true, -- sets vim.opt.number
        spell = false, -- sets vim.opt.spell
        signcolumn = "yes", -- sets vim.opt.signcolumn to yes
        wrap = false, -- sets vim.opt.wrap
        ⭐️↓追記
        clipboard = "", -- sets vim.opt.clipboard
      },

...

    },

...

自分は先頭行を思いっきり見落としてて clipboard = "" だけを入れた状態で、なんでクリップボード無効にならないんだ?となって危うくハマるところだった。 先頭行に if true then return {} end と書かれていて強制的にreturnしてこのファイルにある設定を一切取り込まないようになってた。 WARN: REMOVE THIS LINE TO ACTIVATE THIS FILEというコメントが書かれているのに😅

rspamdのRatelimitモジュールにおけるレートリミットの振る舞い

自分の業務でrspamdを使う場面が増えてる。 rspamdはメールのスパム検知などをになってくれるソフトウェアで、postfixなどからmilterとして利用することができる。 最近だとRatelimitモジュールを使ってるのだが、レートリミットの振る舞いについて理解が浅かったので整理した。

rspamdのRatelimitモジュールとは

rspamdではさまざまなモジュール提供しており、Ratelimitモジュールもその一つ。 文字通りレートリミットをかけられる。

ref:https://rspamd.com/doc/modules/ratelimit.html

設定例

この記事では以下のような設定を考える。 rspamd触りたての自分は、この設定は以下のような意味だろうと考えていた。

  • <制限したいドメイン>について1時間あたり60通送信したらレートリミットがかかる
  • ただし、5通だけは超過を許容している

この考え方は合っているようで合ってない。 以下もう少し詳しく触れていく。

$ sudo cat /etc/rspamd/local.d/ratelimit.conf

rates {
  sample = {
    selector = 'rcpts';
    key = '<制限したいドメイン>';
    bucket = [
      {
        burst = 5;
        rate = "60 / 1h"; 
      },
    ];
  }

Token Bucket Algorithm

前提として Token Bucket Algorithm というものを理解する必要がある。 Ratelimitモジュールでもこのアルゴリズムが採用されており、上記パラメータはこのアルゴリズムで利用されるからである。

Token Bucket Algorithmとはデータの流量を制御する時に採用されるアルゴリズムの一種で、メールに限らずあらゆる帯域制御やレートリミットで採用されている。 大まかなコンセプトとしては「一定時間のデータ転送に制限をかけつつある程度のバースト性を許容する」というもの。 データの送信がある度に消費されるトークンと、トークンを蓄えるバケットを利用して流量を制御する。

具体的には以下のようにして流量制御される。

  • 一定時間おきにバケットトークンが追加される
  • ただしバケットが満杯の時は新しいトークンは破棄される
  • メッセージが到達すると、バケット内に十分なトークンが残っているかチェック
    • ある場合は、その分だけトークンを消費してメッセージが送信される
    • 足りない場合は、そのメッセージはsoft rejectされる(振る舞いの変更は可能っぽい)
  • バースト分についてはバケット内のトークン数をマイナスにする形で許容されるが、その後はトークンが補充されるまでレートリミットがかけられる

今回の設定だとどうなるか

ここでもう一回設定例をみてみる。

    selector = 'rcpts';
    key = '<制限したいドメイン>';
    bucket = [
      {
        burst = 5;
        rate = "60 / 1h"; 
      },

burstrateはどちらもToken Bucket Algorithmで使うパラメータである。 このアルゴリズムに当てはめると以下のようになる。

  • アルゴリズムの適用対象は宛先が<制限したいドメイン>の場合とする(それ以外のメールには影響しない)
  • 1時間で60個のトークンを継続的に補充する(60秒で1トークン)
  • バケットの容量は60
  • バーストは5なので、一時であればバケット内のトークン数-5にして送信できるが、その後レートリミットがかかる
  • レートリミットがかかったらバケット内のトークン数が0以上になるまで解除されない

タイムラインでイメージしてみる

0:00〜1:00の間で考えてみる。 簡略化のためにタイムラインは10分刻みとしている。

10分刻みで考えているのでトークンの補充頻度は10分で10トークンとなる。 この補充頻度に対して、送信量が超過してバケット内のトークン数が0下回った場合、0以上までトークンが補充されるまではレートリミットがかかったままになる。 以下の表だと0:40にburstしたので、0:40〜0:50の間はレートリミットがかかる。 これが解除されるのはトークンが補充されて0以上になる0:50である(0でもバーストはできるので送信可能らしい)。

時刻 送信されたメール数 補充 or 消費されるトークン数 バケット内のトークン数 備考
00:00 0 10 補充 / 0 消費 60.0
00:10 40 10 補充 / 40 消費 30.0
00:20 10 10 補充 / 10 消費 30.0
00:30 15 10 補充 / 15 消費 25.0
00:40 45 10 補充 / 45 消費 -10.0 burst
- / - -10.0 から徐々に補充 ratelimit exceeded
00:50 0 10 補充 / 0消費 0.0 ratelimit lifted
01:00 0 10 補充 / 0 消費 10.0

go-milterで遊ぶ

この記事は 🎄GMOペパボ エンジニア Advent Calendar 2024 - Adventar の21日目の記事です。

最近業務でメールサーバを扱っており、Milterを触る場面が増えてきた。 メールサーバはPostfixを使っておりsmtpd_miltersを利用してMilterと連携するわけだが、そんな時にチームメンバーからMilter連携ができてるかどうかを検証する手段として、go-milterを利用したダミーのMilterを実装しPostfixのMilter連携をデバッグする方法を教えてもらった。

というわけでgo-milterを実際に使ってみた。 早速go-milterの使い方から。。。と行きたいところだが、go-milterを使うにはMilterの仕組みを理解していることが大前提になるので、まずはMilterの説明から。

Milterとは

Mail filterの略で、MTAに対してメールフィルタリングの機能を提供する仕組みおよびそれを提供するAPIである。 Milterによって、MTAで処理するメールに対してスパムメールやウイルスが添付されたメールを検出したり、必要に応じて駆除することができる。元々はSendmail用に開発されたものだが、後にPostfixなどの他のMTAでも採用されるようになった。 スパム対策ソフトとして有名なRspamdや、ウイルス駆除ソフトとして有名なClamAVも、Milterとして利用するための機能を提供している。

Milterの仕組み

MTAが受信処理する際のSMTPセッション内で実行される各種ハンドシェイクそれぞれについてcallback関数を定義し、各ハンドシェイクの段階で対応するcallback関数が実行される仕組みになっている。 全体図を書くと以下の通り。 以下は各callback関数での結果がOKである前提で書いているが、どこかのcallback関数でRejectなどの結果だった場合は、そこでAbortされる。

sequenceDiagram
    participant MUA as MUA (ex. OutLook)
    participant MTA as MTA (ex. Postfix)
    participant Milter as Milter (ex. Rspamd/ClamAV)

    MUA->>MTA: CONNECT
    MTA->>Milter: CONNECT情報を送信
    Note over Milter: CONNECT callback関数
    Milter->>MTA: フィルタリング結果 (ex. OK, Reject)
    MTA->>MUA: 220

    MUA->>MTA: HELO example.com
    MTA->>Milter: HELO情報を送信
    Note over Milter: HELO callback関数
    Milter->>MTA: フィルタリング結果 (ex. OK, Reject)
    MTA->>MUA: 250 Hello example.com

    MUA->>MTA: MAIL FROM:<user@example.com>
    MTA->>Milter: MAIL FROM情報を送信
    Note over Milter: MAIL FROM callback関数
    Milter->>MTA: フィルタリング結果 (ex. OK, Reject)
    MTA->>MUA: 250 OK

    MUA->>MTA: RCPT TO:<recipient@example.com>
    MTA->>Milter: RCPT TO情報を送信
    Note over Milter: RCPT TO callback関数
    Milter->>MTA: フィルタリング結果 (ex. OK, Reject)
    MTA->>MUA: 250 OK

    MUA->>MTA: DATA
    MTA->>MUA: 354 Start mail input
    MUA->>MTA: メールヘッダーを送信
    MTA->>Milter: メールヘッダーを送信
    Note over Milter: HEADER callback関数
    Milter->>MTA: フィルタリング結果 (ex. OK)
    MUA->>MTA: メール本文を送信
    MTA->>Milter: メール本文を送信
    Note over Milter: BODY callback関数
    Milter->>MTA: フィルタリング結果 (ex. OK, Reject, Virus Detected)
    MTA->>MUA: 250 OK

    MUA->>MTA: QUIT
    MTA->>Milter: セッション終了情報を送信
    Note over Milter: CLOSE callback関数
    Milter->>MTA: 応答
    MTA->>MUA: 221 Goodbye

go-milterとは?

ここでようやく本題。 go-milterとは、名前通りMilterを実装できるgolangのパッケージである。

pkg.go.dev

https://pkg.go.dev/github.com/emersion/go-milter#Milter の通り、各コマンドに対するcallback関数のインターフェースが定義されている。 このインターフェースを満たす実装をすればよい。

例えば以下はCONNに対するcallback関数のインターフェースである。 引数は、ホスト名・プロトコルファミリ・ポート・IPアドレス・Modifier構造体となっている。

     // Connect is called to provide SMTP connection data for incoming message.
    // Suppress with OptNoConnect.
    Connect(host string, family string, port uint16, addr net.IP, m *Modifier) (Response, error)

ちなみにModifier構造体はこのようになっている。 Macros(MTAからMilterへ渡される付加情報)とヘッダ情報からなっている。 Modifier構造体は、全てのcallback関数の実装で引数として必要となる。

type Modifier struct {
    Macros  map[string]string
    Headers textproto.MIMEHeader
    // contains filtered or unexported fields
}

戻り値はResponse構造体とエラーの二つである。 Response構造体は以下の通り。 callback関数での処理結果と、後続のコマンドの受付を継続するか中止するかを表すbool値で構成される。 Response構造体はAbort以外のcallback関数の実装で戻り値として必要になる。

type Response interface {
    Response() *Message
    Continue() bool
}

サンプルコード

こちらをどうぞ。 やっていることはとても簡単で、各コマンドでMUAから送信された情報をslogを使用してログに出力しているだけ。

github.com

実行例

このようにコマンドごとにログが出ていることがわかる。 最後はCloseではなくAbortになってしまう点だけは原因が掴めておらず。 おそらくだがQUITコマンドが送信されずにコネクションが切断されたときにこうなるのだろう。

$ sudo ./dummy-milter
2024/12/19 13:46:30 INFO Connect from  host=localhost :="port=58866"
2024/12/19 13:46:30 INFO HELO  name=mail-server
2024/12/19 13:46:30 INFO MAIL FROM:  from=user@example.com
2024/12/19 13:46:30 INFO RCPT TO:  rcpt=recipient@example.com
2024/12/19 13:46:30 INFO Header:  name=From ": "="value=user@example.com"
2024/12/19 13:46:30 INFO Header:  name=To ": "="value=recipient@example.com"
2024/12/19 13:46:30 INFO Header:  name=Subject ": "="value=test"
2024/12/19 13:46:30 INFO Header:  name=Message-Id ": "="value=<20241219044630.1DBEA809AE2@mail-server>"
2024/12/19 13:46:30 INFO Header:  name=Date ": "="value=Thu, 19 Dec 2024 13:46:30 +0900 (JST)"
2024/12/19 13:46:30 INFO Header:  name=X-Virus-Scanned ": "="value=clamav-milter 0.103.12 at milter-server"
2024/12/19 13:46:30 INFO Header:  name=X-Virus-Status ": "="value=Clean"
2024/12/19 13:46:30 INFO Headers:  headers="map[Date:[Thu, 19 Dec 2024 13:46:30 +0900 (JST)] From:[user@example.com] Message-Id:[<20241219044630.1DBEA809AE2@mail-server>] Subject:[test] To:[recipient@example.com]"
2024/12/19 13:46:30 INFO Body chunk:  chunk="This is a test email\r\n\r\n"
2024/12/19 13:46:30 INFO Body
2024/12/19 13:46:30 INFO Abort
2024/12/19 13:46:30 INFO Abort

ちなみに

go-milterでは各コマンド以外にもいろんな関数を提供している。 例えば、処理中のメールに新しいヘッダーを付与するAddHeader関数や、処理中のメールを隔離するQuarantine関数などがある。 これらの関数を組み合わせれば、独自のスパム検知ソフトウェアを実装することができそうだ。

リーダー職に就任しました

2024/3/1より、私はGMOペパボ株式会社の技術部プラットフォームグループのリーダー職に就任しました。 リーダー職についたきっかけ、どんなことをやっていくのか、決意表明を書こうと思います。

きっかけ

私は、長らく弊社が提供するサービスの一つである30days AlbumやBaytと呼ばれるペパボの各サービスが利用するプライベートなオブジェクトストレージを中心に、オンプレミスのレイヤからアプリケーション(バックエンド)のレイヤまで横断してエンジニアリングを手掛け、サービスを支える取り組みをしてきました(各サービスの説明については割愛します。 気になる方は弊社のテックブログをご覧ください)。 同時に、2022年〜2023年にわたって30days AlbumやBaytに関連する大規模なプロジェクトに取り組んでいました。これらのプロジェクトは30days Albumの関係者だけでなく、他事業部のエンジニアやGMOグループのエンジニアと協力して取り組む場面が多々あり、その当時からプロジェクトの進捗を管理したり、チームメンバーから課題をヒアリングして課題解決のための手法を一緒に考えたりということをしていました。 当時からすでにリーダーっぽい動きをしていたこともあってか、 @hiboma から「エンジニアリングリードやチームマネジメントで力を発揮できそう」という助言をいただきました。 今後のキャリアをどうしていくか、当時の選択肢では「シニアエンジニア or マネージャ」の2択になっていましたが、ここに「エンジニアリングリード」という選択肢が私の中で生まれました(どのキャリアに進むのかまだ決めたわけではありません。あくまで選択肢が増えただけです)。 その後、マネージャの@ginbearと話し合いながら今後のキャリアについて考えた結果、リーダーをやってみることになりました。

どんなことをやっていくの?

プラットフォームグループのリーダーには以下のミッションが与えられます。

「メンバーの能力が十分に発揮され、チームの成果を最大化すること」

勤怠や安全衛生といったいわゆる労務管理はしません。これはマネージャ職が行います。 具体的には以下のミッションに取り組んできます。

主要ミッション(チームビルディングと目標管理)

私の場合、主なミッションとして以下が与えられています。

  • チームビルディング
    • チームの生産性の向上のために、生産性を阻害する課題を発見し解決していくこと目指す
    • MTGなどのファシリテート、他事業部との仲介、チームメンバーとの1on1、チームの課題提起 
  • 目標管理
    • 技術方針に則り、事業部ごとの課題に基づいてチームの目標を設定し、目標達成に向けて管理します
    • アクションアイテムの設定、スケジューリング・期限設定、コスト管理、その他フォロー

サブミッション(成長支援と採用)

原則は主要ミッションに注力して取り組みますが、もし余裕があったらチャレンジする要素として以下の二つがあります。 あくまでサブミッションであり、マネージャからもまずは先述した主要ミッションを遂行することを求められています。

  • 成長支援
    • パートナーが成長・上位の等級へ昇格できるようにサポートする体制を作る
  • 採用
    • 面談などを通じて、スキルマッチや文化へのマッチを評価する

決意表明

リーダーとしてチームを引っ張る以上、私がボトルネックになることはチーム全体の大幅なボトルネックになるためこれまで以上に責務が大きくなります。 既にリーダーっぽい動きをしていたからといって「これまでみたいなことをしてれば良いでしょう」という考えでいたら間違いなくチームは鈍化します。 特に最近30days Album以外にもEC支援のサービス(カラーミーショップなど)のインフラを担うチームにもジョインしており、こちらでもリーダーとしての役割が求められます。 サービスが変われば事業の方針・技術スタック・文化も大きく変わります(既にギャップを受けています💦)。 逆にいえば、両者のいいところ・課題と言えるところを俯瞰して改善していくことでチームをブーストできるのではないかと思います。

@rsym1290 がリーダーになったことで、チームが良くなった!」そう言ってもらえるようなリーダを目指して頑張ります。

最後に

この本を買ったので勉強します!

www.oreilly.co.jp