連載
» 2020年03月17日 05時00分 公開

特集:マイクロサービス入門(終):マイクロサービス移行後のテスト、CI/CD、運用監視で現場が疲弊しないためのポイント

マイクロサービスアーキテクチャへの移行を進める上で生まれた課題にどう取り組んだのか。オイシックス・ラ・大地の川上徹氏がOisixのマイクロサービス移行後のテスト、CI/CD、運用監視を紹介します。

[川上徹,オイシックス・ラ・大地]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

 これまでの連載では、ECサイトであるOisixをマイクロサービスアーキテクチャへ移行させていくアプローチについて解説してきたが、今回は移行させた後の開発・運用について解説する。

 併せて前回まで触れてこなかった開発時に留意しておいた方がいい継続的なメンテナンスや運用に関する内容についても解説する。

CI/CDパイプラインを生かした機動力のある開発

 本連載の第5回でも「パイプラインファースト」という言葉について説明したが、開発当初からCI/CD(継続的インテグレーション/継続的デプロイ)パイプラインを整備し、品質保証に十分な量のテストコードをコード変更の都度実行し、実績のある自動デプロイを行える環境が整っていることのメリットは非常に大きいと筆者は考えている。

テストコードの充足による心理的安全性

 マイクロサービスを導入するメリットである「変更に強い」システムを目指すのであれば、テストコードを充足させることは必須だろう。

 テストコードといえばいわゆるクラスやモジュールをターゲットにした「単体テスト」「ユニットテスト」と呼ばれる領域のテストをカバーするものというイメージがあるかもしれないが、もう少し広範囲の領域をテストコードでカバーすることも可能だ。

 Oisixではマイクロサービス開発のフレームワークとして「Spring Boot」を採用しているが、このフレームワークにはテストに関する機能も豊富にそろっている。

 Spring Bootを用いて開発したアプリケーションはビルドしたアーカイブ(jar)を直接Webアプリケーションとして起動することが可能だが、それをテストコードの中で行い、HTTPリクエストを送信するテストも可能だ。

 つまり、RESTful APIとして開発したマイクロサービス単体の振る舞いであれば、テストコードの中で品質を保証できるということであり、コードの変更をGitリポジトリにPushする都度テストを実行し、問題がないことを確認できる安心感は大きい。

 もちろん重厚なテストを実装するとテストの実行時間は比例して長くなるため、CIパイプラインの並列化や、Webアプリケーションとして起動するテストはある程度集約してWebコンテナの起動回数を減らすなどの工夫も必要になる。

 また、各マイクロサービスが利用するデータベースやインメモリデータストアなどのマネージドリソースをDockerコンテナとして用意し、テスト実行の都度環境を構築して使い捨てるといったアプローチも有効だ。

 特にデータベースについてはアプリケーションのGitリポジトリ内にDDL(Data Definition Language)を保持し、それをテスト実行時に起動したDockerコンテナに対して適用する。テストコードからはそのDockerコンテナに対してアクセスさせるという方法だ。アプリケーションリポジトリ内で原本管理されているDDLを用いることで本番環境と確実に同等であることが保証されたテーブル構成の環境に対してテストが行えるので、品質の確認精度を向上することにつながる。

 テスト実行時に指定したDockerコンテナを立ち上げる機能は多くのCIツールが提供しており、JVM言語を利用した開発を行っているのであれば、「Testcontainers」のようなテストコードからDockerコンテナを起動するテストフレームワークを利用することも可能だ。都度クリーンな環境を構築することで冪等(べきとう)なテストコードを実装しやすくなり、CIの安定性も向上するだろう。

 変更に強く、スピーディーな開発を行っていくためには自動テストによる品質保証は重要なポイントであり、強く意識すべきだろう。

安全なリリース

 「変更に強い」システムを目指すのだから、1日に何度もリリースを行ったり、ユーザーのアクセスが頻繁に行われている中でのリリースを行ったりするなどの要件も出てくるはずだ。そのためには、安全なリリースへの配慮が必要になる。

 意識すべきキーワードとしては、下記などになるだろう。

  • Graceful Shutdown
  • ヘルスチェック
  • ローリングアップデート
  • カナリアリリース

 Oisixのマイクロサービス開発ではプラットフォームとして「Kubernetes」を採用しているため、Kubernetesを例に説明するが、マイクロサービスアーキテクチャを用いた開発であれば、考え方としては近しいものが必要となるはずだ。

 まずGraceful Shutdownだ。これはアプリケーションが処理中のリクエストを完了してから停止するというものだ。あらかじめGraceful Shutdownの仕組みを導入しておくことで、稼働中のアプリケーションを入れ替える際にエラーとなってしまうリクエストの発生を防ぐことができる。

 Kubernetesを使用している場合は、アプリケーションにリクエストの完了を確認するエンドポイントを用意しておき、PreStopイベント(コンテナの終了時にフックできるライフサイクルイベント)において、そのエンドポイントを実行するなどで実現可能だ。

 続いてヘルスチェック。これはアプリケーションが正常に稼働しているかどうかをチェックするインジケーターである。リリース時に限らず、ロードバランサーがそのアプリケーションに対してリクエストを割り振っていいかどうかをチェックするための機構だ。

 OisixではKubernetesの「LivenessProbe/ReadinessProbeの仕組み」を用いて「Spring Boot Actuator」のhealthエンドポイントを実行させている。これにより、アプリケーションがデータベースなどのマネージドリソースに対して接続できているかどうかを含めてヘルスチェックを行い、Kubernetesがコンテナに対してリクエストを割り振ってよいかどうか、あるいはコンテナを再起動すべきかどうかを自動的に判断できる。

 Graceful Shutdownとヘルスチェックの考え方を踏まえて、ローリングアップデートの仕組みを実現する。大まかな流れは下記のようなものである。

  1. 新しいバージョンのアプリケーションを通常時のコンテナ起動数に対して一定割合で起動し、ヘルスチェックの仕組みを用いてリクエストを割り振っていい状態かどうかを確認する
  2. 古いバージョンのアプリケーションのうち、一定割合をGraceful Shutdownによって停止する
  3. 新しいバージョンのアプリケーションを通常時のコンテナ起動数まで起動する
  4. 残りの古いバージョンのアプリケーションをGraceful Shutdownによって停止する

 Kubernetesを使用している場合、これらの振る舞いを「Manifest」と呼ばれるYAMLファイルに記述することで制御できる。ローリングアップデート時のコンテナ数(割合)なども柔軟に設定可能だ。

 最後はカナリアリリースだ。これは新しいバージョンと古いバージョンのアプリケーションを一定期間混在して稼働させ、新しいバージョンのアプリケーションに問題がないことを本番の運用状態で確認するものだ。

 プラットフォームとしてKubernetesを使用している場合は、「Istio」などを使用して構築可能である。これは、アプリケーションのシステム的な問題を確認しながらリリースすることの他に、一部のユーザーに対して先行して機能提供を行い、フィードバックを取り込んだ上で本格的なリリースを行うといったアプローチとしても有効な手法だ。

 本連載の第6回でも解説した通り、OisixではIstioを用いて実現可能なリクエストを割合ベースで振り分けるカナリアリリースよりも細かい制御を必要としたため、「Feature Toggle」を活用したカナリアリリースを実現している。

マイクロサービスアーキテクチャへ移行後の運用

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。