新年明けましておめでとうございます。バスクリンです。今年もみんなの気になる技術や最新の情報をテンション上げて書いていきたいと思います。
昨年はハードウェアネタやパフォーマンスの技術的な話、集合知やAIの流行りの技術、依存性やシステム開発などSEとして必要になる考え方などの記事を書いてきましたが、今年はもっと具体的にこれからの技術者として求められる考え方や技術を中心にブログを書いていこうと思います。
では、今日はシステム設計におけるソフトウェア品質の中で注目されている「冪等性(べきとうせい)」について考えてみます。
ソフトウェア品質
設計、開発、インフラなど、全てのタスクに共通していることは「ソフトウェアを作っている」ということです。Web開発も例外ではありません。大きな視点で見れば全てソフトウェアです。インフラもハードやネットワークを設定して基盤を作るということはソフトウェア基盤を作っていることになります。
このソフトウェアに必要な品質のことを「ソフトウェア品質」といい、開発者側や運用側、エンドユーザ側など様々な観点から図ることができるための指標があります。
ソフトウェアの要求には機能要求(仕様書などで明確に定義されている要求)と、非機能要求(明確に定義されていない要求)があり、エンジニアの評価は非機能要求の品質で大きく変わります。
ソフトウェア品質 (wikipedia)
ソフトウェア品質の評価に関する国際規格ISO/IEC 9126には以下の6つ品質特性と品質副特性が定義されており、非機能要求の計測に利用されています。
- 機能性(ユーザ要求に対して満足させる機能が提供されているか。暗黙の要求も含む)
副特性:合目的性、正確性、相互運用性、気密性、標準適合性 - 信頼性(一定の条件下・期間において、安定して期待される役割を果たすことができるか)
副特性:成熟性、障害許容性、回復性、標準適合性 - 使用性(ユーザにとって使いやすいか)
副特性:理解性、習得性、運用性、注目性、標準適合性 - 効率性(CPUやメモリ、ストレージ等のリソースを無駄に消費していないか)
副特性:時間効率性、資源効率性、標準適合性 - 保守性(手順、資源を活用して要求の保持・修復・修正ができるか)
副特性:解析性、変更性、安定性、試験性、標準適合性 - 移植性(異なるコンピュータ構成にソフトウェアを移行しやすいか)
副特性:環境適応性、設置性、共存性、置換性、標準適合性
ISO/IEC 9126 (wikipedia)
いっぱいありすぎて困りますね。全てを完全に満たすシステムを作ろうとなるとかなりのコストがかかってしまいます。良いエンジニアはこのソフトウェア品質をプロジェクトの性質(ライフサイクル、開発期間、予算、メンバーのレベル)に合わせて、取捨選択しながら品質の良いシステムを構築することができます。特にPMやSEにはこのソフトウェア品質を構築・維持できる力が求められます。
冪等性とは何か?
上記で記述されているソフトウェア品質に「冪等性」という性質は含まれていません。冪等性ってなんなんでしょう?
冪等 (wikipedia)
冪等性とは数学で使われる単語で、ざっくりいうと「ある操作を1回やってもN回やっても必ず結果が同じである」という概念です。数学で使用される冪等と詳細は少し異なりますが、概念的な部分では同じです。例を上げると
1 2 3 4 5 |
// 初期化(代入)は何度実行しても結果は同じなので冪等 int i = 0; // インクリメントは実行される度に結果が変わるので冪等ではない for ( ; ; ++i) |
こんな経験はないでしょうか?
- プログラム作ってテストもしていたが、本番環境に入れたら動かない
- 指示された手順書に従って開発環境を構築しようとしたらエラーが出て構築できない
- 同じプログラムをAとBの端末に入れたが、端末によって挙動が異なる
- Aというサーバだけがネットワークトラフィックがものすごく多い
- 1回目と2回目で実行結果がことなる
これらは全て「冪等ではない」のです。
もっとレアなケースで言えば、開発端末では正常にコンパイルできていて期待する動作をしていたが、ビルド端末でコンパイルをすると挙動が異なる。なんていうものもあります。C++で最適化を有効にしてコンパイルすると、ビルド端末のCPUや空きメモリによって最適化のスコープやレジスタ割当、CPU固有の命令セットなどによって生成される結果が異なる場合があります。
コンパイラ最適化 (wikipedia)
なぜ冪等ではなくなるのか?
ソフトウェアの設計方法としての冪等性もありますが、今回はインフラ関連の冪等性について考えてみましょう。
ソフトウェアは人間が作ります。エンジニアのスキルには差異があります。また人間なので間違いもあります。また、今の時代はOSやミドルウェアが頻繁にアップデートされる時代です。使用していたライブラリをアップデートしたら動かなくなったとかはよく聞く話です。
また、ソフトウェアの構造上の問題点も大きく関係しています。
- ソフトウェアはOSに依存しています
- ソフトウェアはミドルウェア(DB接続ライブラリや各種ツールなど)に依存しています
- ミドルウェアはOSに依存しています
- OSはハードウェアに依存しています
- OSはデバイスドライバ(外部装置など)に依存しています
- デバイスドライバはハードウェアに依存しています
このように、ソフトウェアを構成する要素には依存関係が多く存在します。
さらに開発環境と本番環境(プロジェクトによってはテスト環境やステージ環境も)の開発スタイルにも関係があります。開発環境と本番環境は異なることが多く、ソフトウェアが同じでもOSやハードウェア、ミドルウェアの差異があり、冪等ではありません。
また、通常は1台のPCやサーバで稼働するシステムは少なく、クライアント・サーバ形式で複数台のサーバが協調してシステムを構成しています。これら全ての依存関係を把握するだけでも大変な作業で、精神衛生上もよろしくありません。
そこで登場した考え方が、Immutable Infrastructureという考え方です。
Immutable Infrastructureという考え方
一言でいうと「安定している本番環境に手を加えない」という考え方です。しかし手を加えないと機能改修や機能追加はできません。ミドルウェアやOSに脆弱性が発見されればパッチも適用しなければなりません。
機能追加やパッチ適用に失敗すると多大なコストが発生します。システム停止の時間や原因解明のための調査、復旧までのリソースコスト。システム管理者であれば考えたくない状況です。障害発生時は復旧を最優先に行うので、後日調査しようとしたときにログをかき集めて解析しますが、再現性がない場合もあり、仮説を立ててみても検証する環境がなく、原因が不明のまま終わることも多々あります。多くのパッチや変更を加えている環境は同じものを作ろうにも作れないことがよくあります。
Immutable Infrastructureでは本番環境には手を加えず、別の環境を1から構築します。構築が完了すれば本番環境と差し替えて継続して運用していきます。つまり「使い捨て」にしていきます。
- データは使い捨てにはできないので、小さなコンテナに切り離して独自に管理します。
- ミドルウェア群も小さなコンテナに切り離して、お互いが協調しあいながらサービスを提供します。
- 本番環境も開発環境もOSより上のレイヤーは同じ構成で環境を構築します。
こうすることにより、切り替えで障害が発生した場合は、安定稼働していた環境へ切り戻しするだけで旧環境へ戻すことができます。障害が発生した環境をいつでも作ることができるため調査の工数も大幅に削減できます。
Immutable Infrastructure (wikipedia)
Infrastructure as code
上記のImmutable Infrastructureを実現するためにInfrastructure as code(IaC)という手法が確立されました。インフラ周りの構築・設定をすべてコードで管理するという考え方です。コードで管理するため、人為的なミスも少なく、ミスがあった場合も差分で比較することができます。
また、環境構築は同じコードで構築されるため環境による差異を無くすことができます。クラウド環境においてスケールアップやスケールダウンなどの構成変更も人間でやるより遥かに安定して即座に変更ができます。
またプロジェクトメンバーが追加になった場合も端末の構成をコード化しておけば、実行するだけで開発環境が構築できて、すぐ作業に取り掛かれます。
Infrastructure as Codeを実現するツールには、Ansible, Chef, Puppet等がありますが、最近ではDockerとKubernetesが多く利用されてきています。
また、このIaCはクラウドサービスのIaaSとも相性がよく、AWSやGCP、Azureも積極的にサポートしています。
Infrastructure as Code (wikipedia)
まとめ
いかがだったでしょうか?ソフトウェア開発における品質管理と冪等性、冪等性をインフラ視点から確保するImmutable InfrastructureとInfrastructure as code。
次回はDockerを使って実際に環境を構築してみたいと思います(‘ω’)ノ
Photo by https://allthefreestock.com