目的
2022年頃勉強会用に作った原稿があるので、メンテナンスして公開します。
Spring Bootの頻繁なフレームワークのバージョンアップに追従できず手間を掛けている事態を見かけますが、『Spring Bootバージョンアップ案件』のようにまとめてバージョンアップするのは手間です。
ここでは定期的なSpring Bootのバージョンアップに必要なことを説明します。
前提条件
- この話は作者の経験則と一般的なプラクティスのまとめです。完璧ではないので建設的なフィードバックが欲しいです
- 開発環境や本番で利用するプラットフォームには依存しない話をします
- 商用サービスでのSpring Bootバージョンアップを想定します
- 計画とテストを重点的に必要な場合の話をします
- 個人利用であればもっと気軽にやればいいです
この話で考慮しないこと
- JDKのメジャーバージョンアップに伴う対応が別に必要な場合
- 極端に実装依存、プラットフォーム依存なこと
- 開発プロセスはアジャイルかウォーターフォールかは考慮しません
何故Spring Bootのバージョンアップをしないのか
Spring Bootのバージョンアップに限った話ではありませんが、Spring Bootはアップデートが定期的に行われるためバージョンアップ対応に手が回りにくく、負の循環になりやすいです。
理由は色々あります。
よくある理由1 計画と運用設計がない
- バージョンアップの必要性が設計されていないので、一度開発したらアップデート作業が行われない
- バージョンアップ作業の時間がない、予算がない
- バージョンアップ作業中に最新版が発表されてしまい、影響範囲が増えるのでバージョンアップが終われない
よくある理由2 テストもCI/CDもない
- CI/CDが整備されておらずテストが全て人力なのでミスに気がつかない
- テストケースがないのでバージョンアップ時の検証に労力がかかる
- バージョンアップ作業のたび、ほぼ同じテスト設計とテストケースの作成をやり直すことになるので手間
- バージョンアップ作業のたび、テスト実施を繰り返すことになるので手間
- バージョンアップ作業での不具合に気が付かず障害を起こすので、バージョンアップが禁止になる
- CI/CDが整備されておらずリリースが人力なので、頻繁にリリースできない
以降ではこうならないため、Spring Bootのバージョンアップで必要なことを紹介します。
バージョンアップ前に知っておくこと
- Springのエコシステム
- Springのサポートポリシー
- OSSの知識
Springのエコシステム
正しい情報収集と継続的な学習のため、Springのエコシステムを把握する必要があります。
makingさんの『今こそ知りたいSpringエコシステム』(Spring Fest 2020)にまとまっています。
https://www.youtube.com/watch?v=Q8dLlWirFNo
JSUG(Japan Spring Users Group)に参加すると、定期的な勉強会の場が持てます。
詳しい方々に質問できるので活用しましょう。
Springのサポートポリシー
サポートポリシーは公式ページを確認しましょう。
リリース周期、EOLの考え方も掲載されています。
https://spring.io/projects/spring-boot#support
https://github.com/spring-projects/spring-boot/wiki/Supported-Versions
OSSの知識
最低限JavaとSpring自体の知識が必要です。
Java 11以降JDKのリリース周期が変わるなど変化が大きい分野です。
未だにJava 6の頃の知識のまま止まっている組織もあるので、まずは最新情報をおさえましょう。
Springの勉強方法
Springは認定研修や書籍で勉強できます。
書籍だと プロになるためのSpring入門 ――ゼロからの開発力養成講座 などがあります。
バージョンアップの事前準備
- 利用ライブラリ、利用機能の把握
- リリースノートの確認と影響範囲の調査
- バージョンアップ計画の作成
- バージョンアップ完了条件の定義
- CI/CDの整備
- 運用設計
- 監視設計
- テスト設計
- テストケースの作成
- 並行稼働の検討
事前準備 - 利用ライブラリ、利用機能の把握
Spring Bootが提供している機能は多岐にわたります。
Spring Initializrでプロジェクトを作成してから、どのような方式設計、基本設計、実装をしたかを事前に把握してドキュメント化しておくと、リリースノートを読んだときに自分たちのプロダクションコードへの影響の有無がわかりやすいです。
把握することの例
- Spring Actuatorを使っていない
- Spring BootのAutoConfigurationを使っている、使っていない
- Single Page Applicationなので、Javaのテンプレートエンジンは一切使っていない
- Spring SecurityでCoreモジュールを使っているが、OIDC, OAuth, LDAPモジュールは使っていない
- データベースアクセスは3rd partyを使っている
- Spring Cloud AWSを使わず、AWS SDKを使ってConfigurationを書いている
チームが理解しやすい項目を考えて整理してみてください。
事前準備 - リリースノートの確認と影響範囲の調査
作業量と難易度を把握するため、事前に出来るだけリリースノートの確認と影響範囲の調査を済ませましょう。
pom.xmlまたはbuild.gradleのSpring Bootのバージョンを書き換え、ローカルで動作確認するとわかりやすいです。
Spring Bootのバージョンを書き換えて起動しない場合、JavaConfigの修正など大掛かりになることがあります。
Spring Bootのバージョンを書き換えて動く場合は、テストをすれば十分かもしれません。
事前準備 - バージョンアップ計画の作成
公式のロードマップを見ながら計画をたてます
https://spring.io/projects/spring-boot#support
計画の例
- 現在利用しているバージョンから、最新バージョンへのマイナーバージョンアップ
- 定期的なマイナーバージョンアップ
の2段階が必要です。
影響範囲が少なかったり、チームがSpringに詳しかったりする場合、あまり気にせず最新版に一発でバージョンアップデートしても良いでしょう。
計画の分け方
この記事を書きはじめた時点(2022/01/16)でのSpring Bootの最新版は2.6.2です。
現時点でSpring Boot 2.2.x (xは任意)を利用している場合は、下記のような分割が考えられます。
- Spring Boot 2.2からSpring Boot 2.6.2にバージョンアップする
- 段階的にやるか一発でSpring Boot 2.6.2にバージョンアップするか考えます
- Spring Boot 2.2.x -> 2.3 -> 2.4.11 -> 2.5 -> 2.6.2
- Spring Boot 2.2.x -> 2.6.2
- 出来るだけ次期バージョンのSpring Boot 2.6.3のリリースまでに間に合うように日程を立てます
- 段階的にやるか一発でSpring Boot 2.6.2にバージョンアップするか考えます
Spring Boot 3へのメジャーバージョンアップが必要な場合は、この後にJDK 17へのバージョンアップが必要です。
計画の例
- Spring Boot 2.6を随時バージョンアップする
- Spring Boot 2.6.3がリリースされたら、Spring Boot 2.6.2をSpring Boot 2.6.3に
- Spring Boot 2.6.4がリリースされたら、Spring Boot 2.6.3をSpring Boot 2.6.4に
- (以下同様)
- Spring Boot 2.7がリリースされたら、適宜Spring Boot 2.6.nからSpring Boot 2.7にバージョンアップする
- 『適宜』と書いた部分の検討が必要です
- Spring Boot 2.7の初回リリースは2022/05/19, Spring Boot 2.6のサポート終了が2022/11/24なので、2022/05中旬から2022/11中旬までの間、Spring Boot 2.7にバージョンアップすると良いでしょう
事前準備 - バージョンアップ完了条件の定義
Spring Bootの新機能をどこまで適用するかは意見や実現可能性で議論が割れがちです。
バージョンアップと直接関係ない既知のバグを見つけたなど、不測の事態も発生する可能性があります。
何をもって完了するかがブレるので、Spring Bootのバージョンアップの完了条件を定義しておきましょう。
Spring Bootのバージョンアップをしたことで業務的にできることは変わらない(基本的には変えたらいけない)のですが、受託開発のエンドユーザや、アジャイル開発のProduct Ownerのために、Spring Bootバージョンアップの受入条件の定義も必要かもしれません。
※これを書いていて、受入条件と完了条件の違いを考えてなかったことに気がついた。適当です
完了条件の例
- ローカル環境でSpring Bootアプリケーションを起動できること
- CI環境で全件テストが通っていること
- CIでビルド、デプロイできること
- ステージング環境にデプロイできること
- 環境にデプロイしたSpring Bootアプリケーションが起動すること
- ステージング環境でシステムテストが全件OKになること
- バージョンアップ起因の不具合は全て修正したこと
- ヘルスチェックが正常に行えること
- 監視メトリクスがAPMに連携されていること
- 負荷試験の結果、所定のレスポンスタイムを満たせること
完了条件のポイント
- 条件を全てを満たすことを目的にしない
- Spring Bootのバージョンアップ作業中にSpring Bootのバグを見つけた場合など、完了できなくなります
- 完了条件の例にタスクが全て完了したことを含めなかったのは、色々な理由で完遂できない問題が出るからです
- 機能要件を満たすこと以外にも考慮が必要です
- ヘルスチェックが正常に行えることなど
- Spring Actuatorを使っている場合特に
事前準備 - CI/CDの整備
Spring Bootは定期的にバージョンアップされますので、その度にテストとリリース作業を手動でやるのは大変です。
CI/CDを整備して、テストの実行、ビルド、リリース作業を自動で定期的にできるようにしておきましょう。
事前準備 - 運用設計
Spring Bootのバージョンアップは定期的に行われるため、バージョンアップを運用設計に組み込んでおきましょう。
dependabotやrenovatebotを使うと更新が自動で受け取れます。
ただし、botに頼るとバージョンアップ対応の動きが計画に組み込まれませんので、運用設計と計画を組みましょう。
Xではこのような声もあり、作者に響くものがありました。
運用例
- 定期的にバージョンアップ期間を取り、バージョンアップ
- dependabotで更新を定期的に検知、CIが通ればマージしてリリース
監視設計
Spring Bootバージョンアップの本番リリース後、バージョンアップの影響がないことを確認するためにも、プロダクトの監視設計をしておきましょう
テスト設計, テストケースの作成
テスト設計を行いテストケースを作成します。
- Spring Bootバージョンアップ後もプログラムが動作すること
- Spring Bootバージョンアップ後も機能動作が全て満たせること
を確認する必要があります。
JUnitでのユニットテスト、シナリオテスト、回帰テストなどが考えられます。
Spring Bootのバージョンアップは毎月あります。その度に全て手動でのテストをするのは現実的ではありません。
必ずユニットテストを書きましょう。
バージョンアップ時にやること
- バージョンアップ作業
- テスト
- 並行稼働の検討
- リリース・監視
バージョンアップ作業
- GitHubのリリースページを確認する
- build.gradle または pom.xml のSpring Bootのバージョンを書き換える
- 必要があれば関連する依存性もバージョンアップする
- Wikiを確認し、必要な箇所を修正する
- https://github.com/spring-projects/spring-boot/wiki#release-notes
- GitHubのリリースページより細かく、コードレベルの変更が書いてあります
- Spring Bootのマイグレーションガイドを確認し、変更点を修正する
- バージョンによってはマイグレーションガイドがあります
- その他、動かなくなった箇所を修正する
- 現状の実装とSpring Bootの変更点によるので、決まった修正はありません
- 必要に応じて新機能を採用する
変更点の確認
公式は必ず確認しましょう。JSUG勉強会も参考になります。
小技
利用ライブラリのバージョンの組み合わせで迷ったら、Spring Initializrで作成したプロジェクトと見比べてみましょう
テスト
バージョンアップ作業中は逐次ユニットテストを実行し、バージョンアップ作業中に作った不具合を見つけられるようにします
要件によりますが性能試験なども必要かもしれません。重要なのはバージョンアップ後もプロダクトを提供できることだと思います。
並行稼働の検討
Spring Bootバージョンアップの本番リリース時、いきなり全システムを新しいバージョンに変えるとリスクがあるかもしれません。
並行稼働の必要があるか検討しましょう。
コンテナならロールバックは簡単なので、並行稼働は不要かもしれません。
過去に作者がハマったこと
2024年は特に大きな問題には遭遇していません。実装やSpring Bootのバージョンでも変わるのであくまで参考です。
Spring Boot 2.2.5にバージョンアップできない
Spring Boot 2.2.4から2.2.5へバージョンアップを試みました。
ローカル環境では動きましたが、Cloud Foundry環境ではTomcatが起動できずエラーになりました。
原因はSpring Bootのバグです。
Credentials of cloudfoundry service cannot be resolved after upgrading to 2.2.5
https://github.com/spring-projects/spring-boot/issues/20343
このバグはSpring Boot 2.2.6で修正されたので、Spring Boot 2.2.4からSpring Boot 2.2.6にバージョンアップしました。
https://github.com/spring-projects/spring-boot/releases/tag/v2.2.6.RELEASE
教訓
- Spring Bootバージョンアップは、ローカル環境の動作だけでなく、必ず試験環境にデプロイして確認しましょう
- Spring Bootのバージョンアップでバグを踏む可能性があります
- Spring BootのバージョンアップではGitHubでの不具合報告も視野に入れる必要があります
Spring Boot 2.3へのバージョンアップ
運用、インフラよりの新機能の適用に考慮点があります。
バリデーションを使う場合spring-boot-starter-validationを依存性に追加する必要がありますが、wikiに書いてある通りなのでそのほかはあまり難しくなかったです
- Spring Actuatorのlivenessで外部サービスを含めない判定をするのに注意
- TomcatのGraceful shutdown
- Graceful shutdownするのはいいけど、Gracefulに止まらない場合どうするんだっけ?という問題があり採用せず
- Docker Image support
- 新機能を無理に適用する必要がなかったため、使いませんでした
Spring Frameworkのバージョンアップで非推奨メソッドが出来た
Spring Bootのバージョンアップ作業中に気が付きませんでしたが、VSCodeで見ていたら非推奨メソッドを利用していることに気がつきました。
削除されないうちにメソッドを移行します。
まとめ
Spring Bootバージョンアップ時に必要なこと
- OSSエコシステムやJava, Springの知識
- バージョンアップの計画、運用設計
- Springの方式
- Spring Bootバージョンアップの影響範囲の調査
- CI/CDの整備
- テストの整備
- 監視設計、並行稼働の検討など
他にもあればぜひ伺いたいです。
ここまで読んでいただきありがとうございました。happy holidays!