システム全体のコスト構造の変化
インフラやサーバー管理のコストの変化
本節では、インフラにフォーカスを当てて見積りの変化を見てみましょう。
サーバーをオンプレミス環境、サーバーホスティング環境もしくはクラウド環境のいずれで構築するかは、システムが要求するサーバースペックや管理コストの面から検討する必要があります。
オンプレミス環境は、サーバーを設置する場所を自前で用意し、そこに調達したサーバーを設置して運用します。既にサーバールームがある場合には問題ありませんが、そうでない場合には初期費用がとてもかかります。けれども、ハードウェアも、その中のソフトウェアもすべて自社内にあるので、どのようなスペックのサーバーを設置するかなどを含めて、すべてを自分たちでコントロールできます。逆にいうと、すべてをコントロールしないといけないので、ハードウェア障害の監視と障害対応を含むすべてを自分たちで行う必要があります。
サーバーホスティング環境は、サーバーをレンタルし、そこにソフトウェアを導入して利用します。ハードウェアとサーバーの設置場所はホスティング会社が用意するので、オンプレミス環境のようなサーバールームの準備やハードウェアの設置は不要になります。ホスティング会社がハードウェアの監視を行い、障害が発生した際には対応をしてくれるので、そういった監視と障害対応の費用は不要になります。しかしながら、サーバーを他の利用者と共有するケースもあるので、その他の利用者がサーバーに負荷をかけた場合に、自身のサービスも影響を受けてしまう場合があります(影響を受けないために専用サーバーをホスティングするオプションもあります)。
クラウド環境は、サーバーをレンタルするという意味ではサーバーホスティング環境と変わりませんが、どちらかというとリソースをレンタルするイメージです。サーバーホスティングは1台いくらという契約ですが、クラウドは台数に依存しません。また、利用できるサーバーのスペックも種類が豊富です。料金はどのスペックのサーバーを、どれぐらいの時間起動しているかの従量課金となるため、料金が読みにくい場合があります。
開発を行おうとしているシステムが1拠点で使用する社内Webシステム、たとえば人事部で使用する社員管理システムだったとしたら、サーバーを手配する際のスペックの見積りは比較的容易だと思います。なぜなら、利用は平日の日中だけで、同時接続数は人事部の人数に限られ、データ量も見積りしやすいからです。このような場合は自前でサーバーを用意し運用するオンプレミス環境もしくはサーバーホスティング環境で調達するほうがサーバースペックも費用の見積りも容易でしょう。
一方、インターネットで公開する24時間利用可能なサービスで同時接続数は世界中からという場合、接続数やデータ量が予測できないため、オンプレミス環境もしくはサーバーホスティング環境は向いていません。この場合、クラウド環境のほうが、急なアクセス数の増加や利用者の増加にもスケールアップ・スケールアウトともにしやすいことから適しています。
オンプレミス環境やサーバーホスティング環境は、導入初期にシステムのスペックと費用の見積りができる場合には有利ですが、一方で導入後にシステムをスケールアップ・スケールアウトするのは難しくなります。
クラウド環境は、導入初期にシステムのスペックの見積りが難しい場合に有利です。なぜなら導入後のスケールアップ・スケールアウトが容易なので、まず小さな構成でサービスを開始し、利用者が増えてきたらスケールアップやスケールアウトすることができるからです。ただし、初期導入コストが低い反面、従量制の料金体制のため、利用していないサーバーインスタンスはシャットダウンする、不要なファイルはストレージから削除する、といったことをしないとムダな料金がかかります。従量課金を避けたいのなら、他のオンプレミス環境にするか、クラウド環境にするかを検討する必要があります。
開発環境とステージング、そして本番へ
今までのリリース作業は、ソース管理システムからソースコード一式を払い出し→設定ファイルの更新→1つのファイルに圧縮→サーバーに転送→解凍という作業を手作業で行っていました。
しかし、前述したCIツールを用いることで、リリース作業は自動化でき、リリース作業自体の時間を大幅に短縮できるようになります。
毎週のようにリリースがある場合、年間に50回近いリリースを行う必要があります。1回のリリース作業に動作確認も含めて2時間かかっていたとすると、50回リリースするのに2時間×50回=100時間=14人日が必要となります。けれども、CIツールを用いて自動化すると、この2時間が短縮できるため、リリース作業にかかる時間は大幅に削減できます(CIツールは自動化ツールなので、人の手を介していないという意味では0時間と解釈できるかもしれません)。
開発を行い、それが本番環境にリリースされるまでには、大まかに3つの環境を経由します。はじめに開発者が開発を行うための「開発環境」、次に各開発者が開発した成果物を1つにまとめリリース前のテストを行う「ステージング環境」、ステージング環境でのテストが完了したら最後に「本番環境」(プロダクション環境と呼ぶこともあります)にリリースし、実際に利用者が利用できるようにします。
このように開発したプログラムを開発環境から本番環境に移すまでにはタイムラグがあります。開発するものにもよりますが、このタイムラグは1週間のときもあれば数カ月のときもあります。
タイムラグが大きいということは、本番環境にリリースしてから行った開発の規模が大きいということです。開発の規模が大きいものをリリースする場合、リリースのリスクが高くなります。たとえばプログラム改修だけをリリースより、プログラム改修に加えてデータベースのテーブル拡張や新たなミドルウェアの導入を同時に行うリリースはリスクが高いです。また、その間に本番環境での不具合対応を行った場合、その不具合対応を開発環境に施さなければならないため、対応漏れのリスクも高くなります。
この隔たりが大きいものをビッグジャンプと呼び、隔たりが小さいものをスモールジャンプと呼ぶとすると、リリースのリスクを小さくするためにはスモールジャンプを繰り返すことが重要です。たとえば、何らかの機能改修を行う場合、開発環境と本番環境の隔たりが大きいままリリースを一度で行うのはビッグジャンプです。リリースを複数に分けて行い、なるべく開発環境と本番環境の隔たりを小さくしてリリースを行うのはスモールジャンプです。
スモールジャンプはリリースリスクを小さくするだけではなく、開発者に安心を与えます。たとえば、ある一覧を表示する機能のSQLをリファクタリングすることを想像してください。リファクタリングは、テーブルにインデックスを追加することと、そのインデックスを使うようにSQLを修正することとします。リファクタリングなので、修正の前後でSQLの結果に違いがあってはいけません。
ビッグジャンプのリリースの場合、データベースにインデックスを追加し、改修したSQLを使用するように変更したプログラムをリリースします。
スモールジャンプのリリースの場合、これをいくつかのステップに分けてリリースします。まずリファクタリング前後でSQLの結果に違いがないことを確認するため、リファクタリング対象のSQLが呼ばれるたびに実行結果をログ出力 するよう改修しリリースします。続いてデータベースにインデックスを追加して、現行のSQLを実行すると同時に改修したSQLを実行し、結果をログ出力するよう改修したプログラムをリリースします(パフォーマンスに影響しないよう、並列化など工夫がいるかもしれません)。これで現行のSQL結果と改修後のSQL結果が取得できるようになったので、結果に差異が発生することなく運用できているかを監視します。結果に差異がなく、かつパフォーマンスの向上が確認できたら、現行のSQLから改修後のSQLに切り替えます。
明らかにスモールジャンプのほうが工程も工数も多くかかりますが、それでもスモールジャンプを採用するのは、開発環境と本番環境の隔たりを小さく保つことができる方法だからです。隔たりを小さく保てば、もしリリースしたものに不具合が起きた場合も、小さい変更を元に戻すだけでリリース前の状態に戻すことができます。
1回のビッグジャンプでリリースを行う工数と複数のスモールジャンプを行う工数を比較し、どちらがプロジェクトに適しているか、リスクも加味した比較検討を行いましょう。
DevOpsによる組織の変化
自社でサービス開発を行い、自社でそのサービスを運用する場合、サービスの開発を専門に行う「開発チーム」とサービスの運用を専門に行う「運用チーム」に分けて組織することがあります。
一見するとそれぞれのチームは独立して機能するように思えますが、実はそうではないのが実情です。この「開発チーム」と「運用チーム」を効率的に機能させ、プロジェクト計画や見積りに影響を与えるような予期しない突発作業や衝突を防ぐ仕組みがDevOpsです。
開発チームはシステムの新規開発や機能の追加開発、バグ修正などを担当します。一方、運用チームは開発チームが手掛けたシステムをデプロイし、障害などが起きていないかを監視します。その結果、もし問題が発生した場合は開発チームに連絡し対処を仰ぎます。
そして悲しいことに、開発チームと運用チームは利益相反しがちです。開発チームはより良いシステムを目指すためシステムを更改しようとします。一方運用チームは、システムを安定稼働させることを目指すため、できる限りシステム更改を避けようとします。この方向性の違いが利益相反の構造を生みます。
とはいえ、1つのシステムをより良いものにしていくという目的は一緒ですので、本来は利益相反するものではありません。この共通の目的を達成するための仕組みがDevOpsの基礎となります。
DevOpsで重要な要素はいくつかありますが、特に自動化されたインフラストラクチャとバージョン管理システムの利用が重要です。この2つについて詳しく見てみましょう。
自動化されたインフラストラクチャ
インフラストラクチャ、つまり開発したアプリケーションの実行環境は、開発チームと運用チームで共有する情報が多いです。OSは何を使うか、ミドルウェアは何を使うか、ミドルウェアの設定はどのようにするか、アプリケーションが接続するデータベースに関する設定はどのようなものか、などです。
この情報を共有する方法として、手順書や定義書などのドキュメントを用いるのが一般的です。このドキュメントはアプリケーションを開発した開発チームが作成し、実行環境を管理する運用チームに構築を依頼します。
実行環境構築は、設定内容は開発チームが熟知しているので、本来開発チームが構築したほうがスムーズにいきますが、実行環境の管理は運用チームの業務のため、構築の主担当は運用チームとなります。しかしながら、運用チームは設定内容を熟知していないのでスムーズには構築できません。
この環境構築の「ひずみ」を解消する方法のひとつがDockerの利用です。Dockerは仮想環境を提供するコンテナ技術で、Dockerを使ってインフラストラクチャを構築することができます。
仮想環境は昔から存在する技術で、ホストOS上でゲストOSを起動する手法は現在でも使われています。これを完全仮想化と呼びますが、Dockerは完全仮想化ではなく、コンテナ型の仮想環境と呼ばれます。
コンテナ型の仮想環境は完全仮想化とは異なり、ホストOSは隔離された実行環境の上で動作するひとつのプロセスとして起動するため、完全仮想化に比べて軽量でオーバーヘッドが少ないという特徴があります。
Dockerの中核を成すのはDockerfileとDockerイメージです。
Dockerfileは仮想環境を構築する手順をまとめた設定ファイルで、OSのイメージからミドルウェアをインストールし、アプリケーション設定までの手順を記述します。
DockerイメージはDockerfileを基に作成した仮想環境のイメージです。Dockerイメージを用いることで、同じ仮想環境を複数起動することも可能となります。
アプリケーションを動かすには、このDockerイメージを起動した後、アプリケーションモジュールをインストールしサービスを開始します。
再びアプリケーションをデプロイするときは、今まで起動していたサーバーは破棄し、基となるDockerイメージからモジュールを再度インストールし起動します。
起動後は設定を変更せず運用するインフラストラクチャなので、イミュータブル(不変)インフラストラクチャといいます。
話を開発チームと運用チームの「ひずみ」に戻します。
Dockerを用いることで、Dockerを中心にして開発チームはDevOpsのDevに集中し、運用チームはDevOpsのOpsに集中できるようになります。具体的にはOSやミドルウェアの設定とアプリケーションのインストールまでを開発チームが用意したDockerfileが担います。運用チームは開発チームが用意したDockerfileでDockerイメージを作成し、そのDockerイメージで起動したアプリケーションの運用に集中することができるようになります。これにより「ひずみ」が解消します。
DevOpsにおけるバージョン管理システムの利用
バージョン管理システムにGitHubを利用すると、Issue機能(課題管理機能)を使うことができます。
この機能は開発チームの閉じた範囲だけで利用するのではなく、運用チームからの課題管理にも使います。たとえば、ログ出力が一部おかしく修正してほしいなどの課題を運用チームが投稿し、開発チームがそれに対応するなどのケースです。
バージョン管理システム内で課題管理をするので、その課題に対するfeatureブランチをプルリクエストし、マージされると課題管理もクローズするなどの運用が行えます。このように課題管理とバージョン管理を一緒に行うシームレスな運用を行うことがDevOpsのポイントです。
また、先に述べたDockerfileはテキストファイルなので、バージョン管理に適しています。Dockerfileをバージョン管理することで、開発チームと運用チームがメンテナンスを行えるようになり、開発チームが追加したミドルウェアの設定変更は運用チームに伝わり、運用チームが追加したログ出力先の変更もまた開発チームに伝わります。
自動化されたインフラストラクチャとバージョン管理システムを組み合わせることで、開発チームと運用チームがともに協力し合い、システムをより良いものにしていくという目的に向き合えるようになるでしょう。
そのような仕組み作りが好循環を生み、生産性の高い組織となります。そして、不確定だった工数が明確になり、多くの工数がかかっている作業のコストを削減でき、結果的に見積りの明確化へとつながります。
続きは本書で
本書『システム開発のための見積りのすべてがわかる本』ではこの他、初めて見積りに取りかかる方のために、見積りの根幹から要件や要望の可視化、チーム作業の見積り、従来の見積りとクラウド時代の見積りの違いなどを解説しています。
改めて見積りについて学びたい方にもお勧めの1冊、ぜひ手に取ってみてください。