アプリ開発やサイト制作のスマホ端末実機検証・テスト-Remote TestKit

継続的デリバリーへ

継続的インテグレーションをさらに発展させ、顧客に対する最終リリースまでを見据えた継続的デリバリーを目指す取り組み方について学習します。

リリースの問題点

ソフトウエア開発は何のために行うのでしょうか? 開発することが目的ですか? お客様に価値を提供する作業の一つが開発ですが、それだけでお客様に価値を提供できますか?

当然のことですが、開発したシステムは、本番環境にリリースして、運用ができるようになって、お客様に実際に使っていただいて、はじめて価値を生みます。

ところが、開発サイドと運用サイドが別であり、その間の連携が密になっていない状況が、比較的よくあるのではないでしょうか? 場合によっては、両者が単一の会社あるいは同一グループ会社ですらない、完全に別の会社がそれぞれを担当していることもあるのではないでしょうか?

つまりそのような場合、開発サイドと運用サイドの間には、ギャップが存在している可能性が高く、そのギャップを橋渡しするものの一つが、リリース作業になります。ギャップがある以上、その間の橋渡しであるリリース作業には問題が発生することが多いのではないでしょうか? ところが、最近までリリース作業の改善に関する話題は、開発の方法の改善の話題や、運用のための監視ツールの改善の話題ほど語られてこなかったのではないでしょうか?

開発サイドと運用サイドのギャップ

では、このギャップを埋めるはずのリリース作業において良くある問題とはなんでしょう? 今まで当然と思っていたことでも、よく考えると、もっと良い方法があるのではないでしょうか?

リリース作業について、よくある問題点を挙げてみましょう。

  • 手作業でリリースをする。
  • 開発環境と疑似本番環境以降で設定が違う。
  • 本番環境の設定が管理されていない。

まず、一番よくみられるのが、リリース作業を手作業で行っていることではないでしょうか?

一般的に、開発チームが開発を行い試験環境で十分にテストして問題がないと判断したプログラム群を、最後の作業の一つとして、疑似本番環境にリリースを行うことが多いと思います。これは、開発チームにとっては自分たちの成果を、運用チームに引き渡すための作業であり、多くの場合、完成したものを渡すために一回だけ行われる作業です。何度も行うことが想定されていれば自動化を行おうとする場合もあるでしょうが、一回限りの作業と想定している場合には、どうしても手作業となるはずです。

とはいえ、手作業でリリースを間違いなく行うために、あらかじめ手順書を作り、チェックリストを作成する場合が多いでしょう。もちろん、手順書にバグがあってはいけないので、手順書のテスト用の環境をつくって、手順書の通りにリリースできることを確認することもあります。

ですが、手作業で作成される以上、手順書に何らかのヒューマンエラーが混在する可能性があり、さらに手順書を元に行うリリース作業自体にもヒューマンエラーの可能性があります。つまり、手作業で行うリリースには、失敗の可能性が付きまとうのです。

また、リリース作業自体は、ダブルチェックやトリプルチェックといった何重ものチェックを行うことによって、あらかじめ想定した通りリリースができたはずなのに、正常に動作しなかった、という経験はないでしょうか。

開発環境や、試験環境では正常に動作していたものが、疑似本番環境にリリースした途端に動作しなくなるのはなぜでしょう? 多くの場合は、何らかの環境条件の違いが元になってトラブルを起こすと考えられています。例えば、サーバー名が違うとか、フォルダ構成や、フォルダ、ファイルのアクセス権の問題で正常に機能しなかった例や、開発やテスト時にドライバーにパッチを当てないと正常に動作しないとわかっていて、運用チームに連絡はしてあったのに、その情報が正しく疑似本番環境に適用されていなかった。また、最終的な本番環境についての初期設定情報はドキュメント化されているが、運用にともなって変更されていったチューニングやパラメータの結果が残っていなかった。さらには、システムが安定して動作している時はいいが、機器にトラブルが発生して、再構築するときに、最新の設定情報が残っておらず、復旧に時間がかかる場合や、トラブル発生前と同様のパフォーマンスを発揮できなかった、などの例が挙げられます。

他にも、開発チームと運用チームの間での情報共有が上手くできていないといった問題が発生することはないでしょうか。同じ会社ですら、開発部門と運用部門が異なる場合はよくありますし、開発会社と運用会社が別というのも珍しくないでしょう。そのような場合に、情報共有の問題が多く発生するとみてもよいでしょう。

リリース作業というのは、開発したシステムを実際に使えるように設置するという意味では、重要な作業だと認識しているにも関わらず、同じようなトラブルを起こしていることはないでしょうか。

では、これらの問題を解決する方法を学んで行きましょう。

継続的インテグレーションの次のステップ

継続的インテグレーションをすでに実践している方もいると思いますが、再度おさらいをしてみましょう。

継続的インテグレーションでは、

  • 常にビルドが通る状態
  • 自動テストが成功する状態

を維持することが重要であると記述いたしました。
そして、継続的インテグレーションを実現するにはCIツールと呼ばれるツールの導入が必要とも書きました。

たとえば、アジャイル手法を用いた開発の場合を考えてみましょう。

通常のアジャイル手法の現場では、CIツールを用いて継続的インテグレーションを実行するための環境ができていると考えられます。

一つのサイクルが終わった段階で、お客様に成果をお見せする際、本番環境を使うことはないでしょう。一般的には、実装された機能をお客様が使えるような、本番環境をスケールダウンしたデモ用の環境を用意するはずです。

では、そのデモ用の環境へのリリースはどうしていますか?

以前、筆者が従事していた開発現場では、CIツールを入れて定期的にビルドと自動テストを実行する環境ができていました。しかしながら、デモ用環境のリリース作業はお客様にお見せする当日の午前中に、リリース担当者一人がバタバタとリリース作業を手作業で行っていました。

開発の初期には手順書すらなく、試行錯誤でリリースを行っていました。もちろん、少しずつは、手順書らしきものは存在しましたが、依然として手作業で行っていたため、ミスの発生をゼロにすることはできませんでした。このため、リリース担当者は、デモの時間に間に合うよう、時計を見ながら必死にリリース作業を繰り返していました。また、かろうじて存在していたリリース手順は属人化していたため、リリース担当者がいないとデモ用環境が構築できない、といった問題もありました。ところが、ある時からこのような必死のリリース作業がなくなったのです。

CIツールを導入して、定期的にビルドや、自動テストを実行することができているのですから、それを拡張することで、自動的にデモ用環境にリリースできるのではないかということに気がついたのです。

試行錯誤はありましたが、最終的には、デモ用環境へのリリースは、ボタンひとつで行えるものとなりました。デモの当日になって、プログラムの問題があっても、誰かがボタンをクリックするだけでデモ用環境が再構築されるようになったのです。また、毎日夜中に自動的にデモ用環境への自動リリースもできるようになりました。

これは、デモ用環境の例でしかありませんが、当然、これを拡張していけば、本番環境までボタンひとつでリリースできようになることでしょう。また、この方式の利点も明らかだと思います。

  • 自動化によるヒューマンエラーの排除
  • リリース作業の属人化の排除
  • 常に動作が確認された安全なリリース作業

つまり、CIツールによる継続的インテグレーションを拡張することで、リリース作業の大幅な改善を図ることができるのです。

継続的デリバリーに向けて

継続的インテグレーションでは、開発チーム内部で常にテストが通る状態を保てるようになったため、不具合の発生から検出と修正のサイクルを短くすることができました。同時にお客様の求める機能を悪影響なく効率的に開発することができました。しかし、いくら素早くお客様の求める機能を実装しても、それが、本番環境にリリースされなければ、お客様にとっての価値には結び付きません。

つまり、次のステップは、開発された機能を、いかにして素早く本番環境にリリースするかです。

アジャイル手法や継続的インテグレーションの活用が広がっているのであれば、リリースもサイクルを合わせる必要があります。2週間から4週間程度のサイクルで新機能が実装されているならば、すぐにリリースすべきです。半年、一年待って全機能ができあがるのを待ってリリースしていたら、その間に状況が変化し実装された機能は使えなくなる、あるいは要求が変わる可能性もあります。短いサイクルで実装できた機能からリリースを繰り返すことが、お客様にとっての真の価値を生むことになります。

お客様といっても、実際に開発の現場、運用の現場でお話できているのは、一部の方でしかありません。直接見えているお客様の後ろに、より多くのシステムの利用者の方がいらっしゃいます。そして、実際にそれらの多くの方が使ってみて気がつく発見もあるでしょう。デモ環境での確認では想定もしていなかったような使い方をされて、トラブルとなる場合もあるでしょう。その場合には、次のサイクルでそれを改善し、すぐにリリースすることが重要です。

常にリリースを繰り返すことで、絶えずお客様にとっての価値を提供し続けるのが、継続的デリバリーです。

継続的デリバリー

ただし、継続的デリバリーを実践するためには、開発側だけではできません。

本番システムへのリリースが必要となるため運用側とも密接に連携する必要があります。一般的に、開発側は新しいことや、常に変化を求めます。それに対して今までの運用側では、一度動き出したものを簡単には変えようとはしませんでした。変化することがシステム停止のリスクになる可能性があったからです。

しかし、お客様を取り巻く環境が急速に変化し続けている昨今では、変化をしないことがお客様にとってのビジネス機会の損失となる可能性が大きくなってきました。今までの変化を拒絶することで安定稼働を目指す運用から、変化を受け入れながらリスクを低減する運用に変わる必要があるのです。

このため、言われ始めた言葉として、DevOpsがあります。これは、開発(Development) と運用(Operations)を結びつけた言葉です。つまり両者が密接に結びついて、お客様にとっての価値を最大化するために努力しつづけるように変化するということです。この状態になっている場合には、必然的に、継続的デリバリーが実践できているでしょう。

以下に、DevOpsの原点と言われている資料「10 deploys per day: Dev&Ops cooperation at
Flickr(http://www.slideshare.net/jallspaw/10-deploys-per-day-dev-and-ops-cooperation-at-flickr)」にあるスライドを紹介します。

  1. Automated Infrastructure(自動化された環境)
  2. Shard version control(共有のバージョン管理)
  3. One step build and deploy(ビルドとデプロイの自動化)
  4. Feature flags(機能一覧)
  5. Shared metrics(メトリクスの共有)
  6. IRC and IM robots(IRCやインスタントメッセンジャー)
  7. Respect(尊重、尊敬)
  8. Trust(信頼)
  9. Healthy attitude about failure(障害に対して向き合う)
  10. Avoiding Blame(非難を行わない)

これからわかるように、自動化するためのツール群、そして、開発と運用がお互いに助け合うことが重要です。

最初に挙げた問題点にもあるように、リリース作業で一番怖いのが、環境の違いによるトラブルです。確かに開発サイドは、動作するプログラムを開発したかもしれませんが、そのプログラムが正常動作するための前提となる設定を、運用サイドが正しく本番環境で設定しなければ、システムとして正しく動作はしません。

このような問題を、開発側と運用側が密接に連携し乗り越えることで、継続的デリバリーは実現されるのです。

先の事例で行ったものは、デモ用環境という開発者がメンテナンスをすることが可能な環境における自動リリースであり、本番環境の運用担当との連携ができているわけではありませんでした。DevOpsという言葉に照らし合わせるとOpsのない状態であり、本当の意味での継続的デリバリーと言えるほどのものではありませんでした。

しかしながら、その環境では、データベースのテーブル構成やマスターデータも、構成管理サーバーに登録されていて、自動リリースによって、常に最新のデータベースとプログラムを使ってデモ用環境は構築され続けていたのです。ビルドやテストのエラーなどのステータスも、各自に対して、インスタントメッセンジャーで配信されるようにしていました。

また、開発者が機能追加のために行ったデータベースの変更も、すべて自動的にデモ用環境にはリリースされて、プログラムとデータベースの同期は常に保たれる仕組みが構築されていました。つまり、限定的ではありますが、プログラムだけのリリースではなく、システムの基本的な構成要素の一つであるデータベースの中身まで、常に最新化され続けていたのです。あとは、リリーススクリプトにフォルダ構成を適切に設定する機能を追加していくことで、開発者によるフォルダの事前設定すら不要にすることができたと考えられます。

継続的デリバリーは、この事例の延長にあります。

この事例ではできませんでしたが、運用サイドを巻き込み、これらの仕組みをさらに発展させていくことで、ビルドからリリースまでを自動化し、リスクに対して強いシステムを構築することは可能でしょう。変更を加えてリリースしたシステムでトラブルが発生しても、ひとつ前の動作していたバージョンにシステムを戻す作業を、ボタンひとつでできるような環境を作ることが可能となるのです。

これによって、リスクを軽減して、確実なリリースを実行できるようになります。

その結果、お客様が望んだ機能をすばやく開発しリリースすることが可能になります。

お客様にとって価値のあるシステムを提供し続けることを第一に考えた時に、開発サイドや運用サイドといった個別で最適化するのではなく、アプリケーションライフサイクルの中での全体最適を突き詰めることで、継続的デリバリーが実現できるのです。

そのためには、技術的なチャレンジも必要でしょうが、それ以上に、組織の壁を壊すことや、企業文化を変えることも必要になってくる場合もあるでしょう。

ですが、ビジネス状況の変化の激しい現在において、それらの壁を乗り越えられないということは、お客様とっての価値を提供し続けることができなくなるということであり、自らの競争力の低下を意味するのではないでしょうか。

全てを一度に実現することは難しいと思いますが、継続的デリバリーを念頭に、開発サイドと運用サイドで協力して、お客様にとって最適な価値の提供方法を検討してみてはいかがでしょうか。それが、自らの競争力を向上させることにつなるはずです。

執筆者プロフィール  吉村 好廣

外資系コンピュータメーカーに入社し、ハードウエアからソフトウエアまで幅広く開発の経験を積む。その中で様々なレベルのテストを経験する。独立後、テストをキーワードにプロジェクトを渡り歩くフリーランスのエンジニア。Androidテスト部、自動化テスト研究会等の活動の中でさらに切磋琢磨し腕を磨き続ける。