※この記事は、個人技術ブログ CodeArchPedia.com の技術メモ(要約)です。
Spring Boot 2.7をKubernetes上で動かす際、複数Pod環境での定期実行タスクの重複に悩まされました。Spring Cloud Kubernetesのリーダー選出機能を使ってもなぜか機能せず、全Podでタスクが暴発する事態に陥った経験から、確実な解決策をまとめました。
何が起きたか(課題)
・Spring Cloud Kubernetesでリーダー選出を実装したが、Pod間で排他制御が効かない。
・ConfigMapやLeaseリソースが更新されず、全Podでスケジュールタスクが同時に実行される。
・特にJDK 8という環境制約があり、ライブラリのバージョン不整合による不可解な挙動が発生。
どう解決したか(概要)
高レベルな抽象化に頼るのをやめ、Kubernetesのデファクトスタンダードである fabric8 kubernetes-client を直接利用するアプローチへ切り替えました。JDK 8環境でも動作する安定バージョン「6.13.5」を特定し、LeaseLockを用いた直接的なリーダー選出ロジックを実装することで解決しました。
実装の手順は以下の通りです。
- pom.xmlにfabric8のクライアントライブラリを追加。
- サービス起動時にLeaderElectorを初期化し、Leaseリソースを監視対象として登録。
- リーダーシップ獲得・剥奪時のコールバックを定義し、isLeader()フラグを管理。
- スケジュールタスクの実行条件にisLeader()のチェックを挿入。
効果(Before/After)
Beforeは複数Podが同時にDB更新や外部API呼び出しを行い、ログが重複してタスクの整合性が取れない状態でした。Afterでは、常に選出された単一のリーダーPodのみが確実にタスクを実行するようになり、システム全体の冪等性が担保されました。
🚀 詳細な設定とコードはこちら
具体的な実装コードや、JDK 8環境でハマるポイントの詳細な設定は元のブログで公開しています。
