こんにちは。クルーズ株式会社CTOの鈴木です。
以前の「SHOPLISTのシステムをモダンなアーキテクチャに変えようとしたら予想以上に闇が深かった話 」でも書いたのですが、現行のSHOPLISTにおけるOSやミドルウェアがとにかく古い状態でした。
今回はOSミドルウェアをバージョンアップした話について共有していこうと思います。
OS/ミドルウェアのバージョンアップはインフラ的な山場の一つです。
CentOSの6.4は2020年の11月でサポート終了、PHP5.4は2015年に終了しておりセキュリティ面、生産性面で大きな課題がある状況でした。セキュリティ面は当然のこととして、AWS SDK for PHPやgoogle-api-php-clientなど主要ライブラリがPHPのバージョンが古すぎて使えないこと、Web APIを呼び出して使うにしてもlibcurlの問題でSSL connect errorが発生して呼び出せない、その他文献がない、調べようにもネット上の文献少なくなっている、しまいには新規に参画したメンバから「SHOPLISTのこのシステム、化石ですね」と言われてしまう、笑うに笑えない状況でした。
今回どこまでバージョンアップするか?
計画時点のStable 最新版を選定しました。
■OS CnetOS 6.4 ⇒ Amazon Linux release 2 (Karoo)
■Web Apache2.2 ⇒ Apache 2.4.43
■PHP PHP5.4 ⇒ PHP7.4
■DB MariaDB10.0.3 ⇒ MariaDb10.5.5
■redis redis2.8.3-1 ⇒ redis4.0.10
構築を行う際に議論となったこと
ソフトウェアパッケージを管理するリポジトリについて
今回OSがAmazonLinuxで、amazon-linux-extrasライブラリを正としようとすべきなのですが、以下2点の問題があり、以下の方針としました。
1.amazon-linux-extrasのphpのバージョンタグにphp7.4のバージョンタグがstableとなっていてリビジョンがない問題
⇒stableで代用。なのでリビジョン単位で見ると環境差異が生まれる可能性はあるが受容する。
2.必要なすべてのライブラリがamazon-linux-extras内に存在しない問題
⇒やむを得ないのでそのようなものはpecl、pearを使うけど、amazon-linux-extrasにあるものはそこからインストールする。
今後のバージョンアップの頻度、その時のバージョンの選定ルールについて
議論の発端としては各ミドルウェアごとにEOLが異なることです。
例えば2年おきに最新安定版にアップデートを行うという決めごとにした場合、PHPのアクティブサポートは2011年の11月に終了となり、サポート切れ状態となりますが、EOLの長いもの、例えばMariaDBなどについてはサポート範囲内なので今のままでも特段追加したい機能や、今使っているバージョンで問題が無ければ無理にバージョン上げる必要ないのではないかという話です。
この件については結論があいまいな部分はあるのですが以下の方針でよいのではないかと考えています。
1.PHPおよびPHPライブラリは2年ごとに最新安定版に
2年おきにバージョンを安定最新版にあげる。理由としてはPHPのアクティブサポートが2年、セキュリティサポートが3年なので、2年おきにやる計画を立てておけば仮にトラブって多少足が出たとしてもセキュリティサポート終了までにはアップデートが完了できる。またバージョンアップに伴い非推奨関数の書き直しなど、ソース上の回収箇所も一定数あるものなので、定期的にバージョンアップを計画し、それに向けて通常業務においても非推奨関数の書き換えを行う運用を作るなど、定常業務化した方がバージョンアップ前に苦労することが減るので、機械的に2年で最新安定版にあげることを計画しそのために日々準備しておく方が適切と判断。
2.それ以外は必要な場合は2年おきに
追加機能要望のあるもの、もしくはサポートが切れることが見込まれるものについては2年おきのPHPバージョンアップの際に同時に行い、それ以外においてはバージョンアップは行わない。
3.重大な脆弱性が見つかり、システム全体で見てもリスクヘッジの手段がないものは即時。
CVN、NVDは日次確認しており、その中でその脆弱性がミドルウェア単体の設定変更や、WAFやALBなどその他サービスの組み合わせでも防げないものについては即時バージョンアップ。
バージョンアップの進め方
実施のスケジュール一気に進めてしまうと問題が発生した際に原因の切り分けできなくなるので以下の段取りで進めました。
1.ローカル環境及び開発環境のOS/PHPを含むミドルウェアをバージョンアップしてEC2インスタンスをそれぞれ作成する。
2.Git上でPHP7動作確認用のブランチを定義しておき、そのブランチにソースコードがデプロイされて場合に、新バージョンに対応したEC2インスタンスにデプロイし、PHP7による影響範囲の洗い出しとプログラムの回収を個なっていく。releaseブランチからPHP7動作確認用のブランチには定期的にpullして機能差分を埋めていく。
3.まず先に本番環境のDBインスタンスのバージョンアップから先に行い、その後にWebとバッチインスタンスサーバのバージョンアップを行う。ただその前に不要なテーブル・データで削除できるものは消す。(事前にバックアップDBインスタンスでテーブルおよびデータ削除にかかる時間を計測したところ数時間規模だったので、データ削除のために計画メンテナンスを一度行う。
4.計画メンテナンスを行い本番環境のDBインスタンスのバージョンアップを先に行う。この時点でWebインスタンスがCentOS6.4/PHP5.4環境、DBインスタンスがAmazonLinux2/MariaDB10.5.5環境に置き換わっている。
5.PHP7対応のソースとreleaseブランチのマージのため、新規機能リリースを一定期間停止し、releaseブランチ = php7.4対応の状態に整理していく。
6.計画メンテナンスを行い、Web とバッチインスタンスをPHP7.4に対応したインスタンスに切り替えていく。この時点でWebとバッチインスタンスもAmazonLinux2/PHP7.4環境に置き換わっている。
7.ここで何も問題が発生しなければ旧バージョンのインスタンスをTerminateして終了。
ちなみに上記の2までは比較的順調に進みました。3以降は何かしらの問題が発生し難儀しました。
結構長くなってしまいました。
次回以降の記事で、発生した問題と解決方法を書いていきたいと思います。
-------------------------------------------------------------------------------------------------
※2020年の内容を記事にしており、2020年11月以降PHP7サポート切れをはじめとした脆弱性リスクへの対処は完了しております。