はてなブログPerl 5.28.1化への道

こんにちは, はてなブログの開発に携わっているエンジニアの id:papix です. この記事は, 「Perl Advent Calendar 2018」の22日目の記事です.

qiita.com

昨日は, @mp0liiu さんの「PerlのDIコンテナ, Bread::Boardの紹介」でした.

qiita.com

はてなブログPerl 5.28.1化への道

はてなブログ(今皆さんが見ているこのブログもはてなブログです!)は, Perlで実装されています. Perlは年に1回, 新しいバージョンがリリースされていて(Perl 5.28.0は2018年6月23日にリリースされました), 2018年12月現在の最新安定版はPerl 5.28.1です.

先日, はてなブログで利用しているPerlのバージョンを現時点の最新版(= Perl 5.28.1)にバージョンアップするという機会がありました. 自分が入社した2017年2月以降, チームでタスクの順序を考慮するにあたって, 限られたリソースの中, どうしてもPerlのバージョンアップを後回しにせざるを得なかった状況が続いていました. その結果として, 入社後初めて担当することになった今回のバージョンアップは, それなりに「ビックバンアップデート」と言えるものになりました. 自分にとっても得難い経験だったので, その時の様子をご紹介したいと思います.

コードの修正

...さて, Perlのバージョンアップを実現するにあたって, まず着手しないといけないのはコードの修正です. Perlは後方互換性を重視している言語... と言われていますが, それでもバージョンが上がるごとに少しずつ挙動が変わったり, これまで使えた機能が非推奨になったりします.

有名なものでいえば, Perl 5.18.0から導入されたHash Randomization(ハッシュのキーをkeysなどで取得した時の順番が不定になる), 同じタイミングで実施されたスマートマッチ(~~)の非推奨化(それに伴うgiven/whenの非推奨化), 或いはPerl 5.26.0で実施された@INCから.が取り除かれる修正などが挙げられるでしょう. 機能の非推奨化については, 非推奨になってもそのまま使い続けることは出来ますが, とは言え将来的に廃止される見込みがあるからこそ非推奨化されている訳ですし, 加えて非推奨化が成された旨の警告も表示されるようになるので, 丁寧に対処する必要があります.

実際に, 今回はてなブログをPerl 5.28.1にアップデートするために実施した作業としては, 前述した@INCへの対応がありました. これまではてなブログでは@INC.があることを想定して, 例えばt/lib以下にテストのためのライブラリを設置したりしていたのです. そのためPerl 5.28.1化を実現するにあたり, CI環境も含めてうまく動作する必要がありました.

...この辺りは, 「難易度が高い」というよりは, 「地道に1つずつ潰さないといけない」という, 地味な作業が続きます. 今回Perl 5.28.1化を進めるにあたっては, Perl 5.28.1で問題なく動作するように修正を加えつつ, 現在動いているPerlのバージョンでも動作するようにして, 少しずつ修正をマージ/リリースしていく方針で進めました. この進め方だと, 成果物が少しづつリリースされるので, その都度成功体験(?)を得ることができ, 地味な作業が続く中でモチベーションを維持する... という観点で非常に良い進め方だったと思います.

手順書の構築

...さて, コードの修正が終わり, はてなブログのコードがPerl 5.28.1でも動作するようになった所で, いよいよリリースに向けた準備を始めます. はてなブログはAWSで構築されていて, そこにはMackerelで管理されているbackend, worker, batchといったロールのEC2インスタンスがいて, そのそれぞれでPerlが動いています. これらをユーザーの皆様へ影響なく, 安全にPerl 5.28.1に置き換えるために, 今回は「Perl 5.28.1で動くEC2インスタンスを新たに構築して, それに入れ替えていく」というアプローチを採用しました.

具体的には,

  • Perl 5.28.1で動くbackend, worker, batchのEC2インスタンスを構築
  • Perl 5.28.1が動くbackendを1台だけproxyのupstreamに追加
    • アクセスログ, エラーログなどをチェックして, Perl 5.28.1にアップグレードすることで異常が発生していないかチェック
  • backendの全台をPerl 5.28.1が動くEC2インスタンスに交換
  • 同様に, worker, batchもPerl 5.28.1が動くEC2インスタンスに交換
  • 数日様子を見て, 古いバージョンのPerlで動作しているEC2インスタンスを退役

...という手順になります. このように進めると, Perlのバージョンアップ作業の途中でもし問題が発生しても, 古いバージョンのPerlで動作しているEC2インスタンスが待機しているので, すぐさま切り替えて復旧出来る点が嬉しいです.

続いて, リリースの大まかな方針が決まったので, これを手順書に落とし込んでいきます. 手順書を用意するにあたっては, 以下のポイントに気をつけました:

  • 必要な連絡/周知も網羅する
  • 実際に入力するコマンドまで丁寧に書く
  • 中止基準や切り戻し方法も定めておく

詳しくは自分の個人ブログにまとめたので, そちらを読んでみてください:

papix.hatenablog.com

完成した手順書は, GitHub EnterpriseのIssueで管理しました. 作業が終わった後にチェックボックスをクリックすると, Onの状態に出来るので, これで進捗管理をするようにしました.

f:id:papix:20181221173708p:plain
backendのうち, 1台を実際に投入してログを調査してみるときの手順が書かれている

ところで, はてなでは「プロダクトオーナーシップ」を合言葉に, プロダクト全体について開発チームが責任を持てる体制づくりを進めています. その一環として, これまでインフラ部署やSREに頼っていたサービスのインフラの保守管理, そして信頼性への責任を, これまで以上に開発チームが持てるようにする「インフラオーナーシップ」の獲得を目指しています. 今回のPerlのバージョンアップとそれに伴う手順書の構築では, 「インフラオーナーシップ」の観点でも非常に良い影響がありました.

開発チームがサービスの信頼性に責任を持つためには, 当然のことながら, 開発チームのエンジニアが自分たちが開発し保守するサービスが稼働するインフラについて, より深く知る必要があります. 今回手順書を構築する中で, SREのレビューやチームメンバーのアドバイスを通して, はてなブログのインフラに関する暗黙の知識が少しずつ文章化され, インフラを構築したり保守するための知見がチームにしっかり展開される, という効果がありました. 更には, 今後はてなブログの開発チームにJoinするエンジニアに, 今回構築した手順書を元にPerlのバージョンアップを担当してもらう事で, そこで得た経験を, はてなブログを構成するインフラやそこで必要となるオペレーションについて把握する橋頭堡にしてもらう... といったこともできそうです.

そしてリリース作業へ

リリースにあたって, 問題に至る種をなるべく減らしたいので, そのリリース作業を実施する数日間, リリースを止めるという判断をしました. プロデューサーやディレクターと調整し, リリース停止の決定をして, 実施日程を決め, ...いよいよリリース作業へ突入です.

結果としては, 少し手間取ってしまった部分があったものの, Perl 5.28.1にアップグレードすることで問題が発生した! ...ということもなく, 当初構築した手順書通りに作業を進めることができました. 今回は, 実際に入力するコマンドまで丁寧に用意しておいたので, 途中でコマンドをtypoして, オペレーションミスしたり焦ったり... という事を防ぎましたし, 事前に中止基準も定めておいたので, 途中で「リリースを続けるか, 中止するか...」といった判断で悩むこともなく, 平穏にリリースを終えることができました.

...というわけで, 今みなさんがご覧になっているはてなブログは, 現在Perl 5.28.1で動作しています. 恐らく来年には, Perl 5.30.xがリリースされるはずです. このバージョンアップもしっかり対応して, サービスの信頼性に責任を持つという意味でも, 常に最新のPerlで動作し続ける状態を維持していきたいと思っています.

まとめ

Perlで動くはてなブログを, Perl 5.28.1化するために取り組んだことをご紹介しました. 今回は, 自分にとっては初めての実稼働中サービスのPerlバージョンアップだったので, ちょっと丁寧めに進めましたが, とはいえそのお陰で特段の問題なく, 無事にバージョンアップを完遂することが出来たので良かったです.

明日は...

明日の「Perl Advent Calendar 2018」は, はてなブログチームのテックリード, id:aereal さんの担当です.