ステージング環境とは結局なんなのか。

# tl;dr
できればちゃんと本番環境と同じ構成にしようね。

# はじめに
エンジニアのみなさんならほぼ日常的に耳にする言葉である「ステージング環境」。
そのほかにも「開発環境」「本番（プロダクション）環境」と言った環境が一般的に耳にするところだと思います。

当然それぞれには役割があり、開発の工程に応じて必要になってくるものです。
では、それぞれの環境の特徴をざっと確認してみましょう。

# 開発環境の役割
「開発環境」は、エンジニアがコーディングしたプログラムが動作するかを確認する、まさしく開発するための環境です。
個人のPCに仮想環境を立ち上げるだけだったり、クラウド上に共有のPaaSを一つ置くだけだったり、「動けば良い」というようなイメージです。
言語やミドルウェアのバージョンを本番環境と合わせておけば、最低限開発環境としての要件を満たせていると思います。（現場によってはバージョンが違うところもあるけどね！！）
つまり、「開発環境」は開発ができれば良い環境。という認識です。

# 本番環境の役割
「本番環境」は、サービスを一般公開するなど、実際に利用し、常に動かすための環境です。
かっこよくいうとプロダクション環境です。
要件定義の段階で環境構成案を検討し、その際に冗長化やバックアップの方針など、運用面をしっかりと意識して構成を決定する必要があります。
オンプレであれば機体の購入などが必要になるため、クラウドより慎重に行われます。（クラウドだから適当でいいという意味ではないです。）
つまり、「本番環境」はちゃんと動作すれば良い環境。という認識です。

# ステージング環境の役割
上の二つは「開発」「本番」という日本語の意味から役割をイメージしやすいものだと思います。
ではステージング環境とは？日本語でいうと「検証環境」です。
検証という日本語と、他の環境の役割から改めて考え、

「検証環境」は
> 「本番環境」はちゃんと動作すれば良い環境。

という部分が「検証」できれば良さそうですね。

この「ちゃんと動作する」というのを確認するのが、一般的には「試験（テスト）」と言われるものです。
つまり「ステージング環境」とは「試験を実施するための環境」だと考えられます。

では次に考えるのは、「試験を実施するための環境」に必要な要件はなんでしょうか？ということです。

ここで、今までに私が関わったプロジェクトの「ステージング環境」と呼ばれていた環境を振り返りながら考えてみたいと思います。


## プロジェクト事例
### プロジェクト１ - 本番環境相乗り型
***

読んで字のごとく、本番環境のサーバにステージングの資材を相乗りさせています。
apacheのconfでパスを切って、URLを`http://xxx.com/staging/~~`とするとステージング環境に繋がる、というものです。

HAHAHAHAHA... 

いや、これには訳があってですね。社内専用の一部の部署が使うだけのシステムであり、費用が全く確保できず、お客様が保有するオンプレ一台で全てを完結させてくれと言われたのです。
WebサーバだけでなくmysqlやMemcachedなども全て相乗りしていました。
まともなエンジニアがみたら「そりゃないよ」と言われるかもしれません。私も引き継ぐ時に後任のエンジニアの方に失笑された思い出があります。

しかし試験はできていた気がします。
本番環境と同じサーバですので勿論ミドルウェアなんかも各種同じバージョンで動作します。
リストア試験も、むしろ本番と一体だからこそ、より高い信頼性で実施できていたような気さえします。
これは検証できている環境だと言えるのではないでしょうか？


### プロジェクト２ - 可用性排除型
***

こちらは以下のような環境です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/185345/21d554a8-2365-3333-b4f2-7693d91fb65e.png)


本番環境では可用性の観点から必要なLBがステージング環境にはありません。
ステージング環境は常時動くものではないため、可用性など必要ない、という観点から構成された環境です。

勿論Webサーバの中身は本番と同等のものを用意しています。
LBの設置なども無料ではないので、こちらもリーズナブルな環境であると言えます。

非機能における負荷試験やスケールの試験は、リリース前に本番環境で行っておけば良いので、
機能試験や外部連携試験を行う環境として構築した「ステージング環境」となっています。


### プロジェクト３ - 本番模倣型
***

本番環境と全く同じ構成を取っています。
LBにぶら下がるサーバの台数は、クラウドのため自由に変更可能なので、普段は２台のみにして節約を計っています。
試験状況に応じてスケールアウトをして行きます。

本番環境と同じ構成であるため、どのような試験も本番環境と同じであるという信頼性が持てます。
しかし費用がかさみます。


### プロジェクト４ - 開発用ステージング環境 + 本番維持環境型
***

上記の３つと少し毛色が違いますので、並列で紹介するのはちょっとナンセンスかもしれません。。
「開発用ステージング環境」というのがいわゆる「ステージング環境」のことで、それとは別に「本番維持環境」というものがあります。

これは、「一度リリースしてお終い」のサービスなら不要ですが（あまりそのようなサービスは少ないかと思いますが）、
継続的な機能追加などのリリースが必要な場合、「次期リリースに向けてステージング環境の資材を更新し、試験実施の最中」という状況だと、
ステージングと本番の動作が当然異なってしまうため、「ステージング環境では本番で発生した不具合の原因調査を行うことができない」ということを避けるために構築された環境です。

運用面まで加味した「検証」を行うため、「本番維持環境」も広義の「ステージング環境」と言えるのではないでしょうか。
しかしインフラ面ではプロジェクト３の1.5倍の費用がかさみます。


### プロジェクト５ - 開発とステージングの差が名前の差だけならば、ステージングの存在など不要だ！型
***

開発環境で機能試験をすればプログラムとしての動きを担保できているので、改めてステージング環境なんて立てる必要はありません。
あとは本番環境にリリースあるのみ。

ｲｸｿﾞｰ! (ﾃﾞ ﾃﾞ ﾃﾞﾃﾞﾃﾞﾃﾞﾝ　ｶｰﾝ!)

ステージングの構成でもなんでもないですが、システムがすごい小さく、ほぼ外部連携のみのシステムであり、
連携先にステージング環境がなかったのでこうなったそうです。
なぜ連携先にステージング環境がなかったのか。ｺﾚｶﾞﾜｶﾗﾅｲ


## で、結局どうなのか
上記のプロジェクト事例の紹介の中で、「機能試験」「負荷試験」「リストア試験」「外部連携試験」など、様々な試験の単語出てきました。
「試験」と一口に言っても、多くの種類の試験が存在します。
これら全ての「試験」を**正確**にこなせる環境である、というのが「ステージング環境」の要件ではないでしょうか。

この考えのもと、改めてプロジェクト１〜５を評価してみましょう。

 + プロジェクト１ - 本番環境相乗り型
  これは一見残念な環境ですが、ある意味で本番と検証が一致している環境であると言えるため、試験を正確にこなせる気がします。
  が、同じ環境であるがゆえにサーバの中に資材を格納するパスが一致しません。
  外部のファイルを相対パスで参照するようなプログラムがあった場合、本番環境での正当性は疑わしいものになってしまいます。
  また、負荷試験を実施した際、本番稼働前なら良いですが、本番稼働後は、ステージングへの負荷が本番環境を圧迫してしまい、目も当てられません。
  よってステージング環境としては微妙です。
　

 + プロジェクト２ - 可用性排除型
  この環境が実は今まで経験したなかで一番多いステージング環境でした。が、私に言わせればプロジェクト１より悪い気がします。
  そもそも本番環境と構成のレベルで異なっているのであれば試験になりません。
  例えばLBが付与するHTTPヘッダの情報などがありますが、これをステージング環境で確認できなくなり、「ログにクライアントIPアドレスを出していたが、本番になったら出なくなった」などの珍事が起こりえます。
  また、一番酷かったのは「セッション情報をファイル出力にしていたため、冗長化したらセッションが切れた」というプロジェクトもありました。
  さらに、この環境も負荷試験を正確に行えません。Webサーバが1台しか存在しない場合のスループットしか測定できないため、Webサーバをスケールアウトすることで期待通りに性能が上がって行くのかが計測できないためです。
  （Webサーバを2台にした時点でDBがボトルネックとなってしまい、3台以降増やしても十分な効果を得られない、と言った状況を観測できません。）
  よってこれはステージング環境失格です。微妙じゃなくて失格です。（私怨）
　

 + プロジェクト３ - 本番模倣型
  Webサービスである場合、ドメインはステージング用に別途取得することが多いと思うので、そこだけは設定が変わってしまうと思います。
  （クライアントのhostsを書き換えたりDNSを切り替えたりすることで対応も可能だが、どちらが良いかはちょっと判断が難しい気もする。）
  が、クラウドであればスケールの試験も容易に行えますし、この環境は非常に理想的です。
　ただし、LBの下には最低でも2台のサーバは必須です。1台のみだと、結局冗長構成にした時の動作を担保できません。（先のセッションの件など）
  構成は似ているが本番はAWS、ステージングはHeroku、みたいなサービスの話を聞いたことがありますがこれは避けましょう。結局構成が違うことには変わりません。パブリッククラウドにはそれぞれ特性というか癖もあります。
　
 + プロジェクト４ - 開発用ステージング環境 + 本番維持環境型
  プロジェクト３ + 本番維持環境の状況です。問い合わせ等が多いサービスであればこの構成が一番望ましいのではないかと思います。
  本番環境で障害が発生した際、本番環境のログなどはもちろん参照しますが、再現性があるか、どのように修正可能か、と言ったことは本番環境で試すのはナンセンスです。（それがサービス全体に影響を与える可能性があるため）
  そのため、別件の開発スケジュールにも影響を受けない「本番維持環境」というのは意外と重要になってくるのではないかと思います。
　
 + プロジェクト５ - 開発とステーj（ry
  ﾅﾆﾓｲｳｺﾄﾊﾅｲ


つまり３（および４）の構成が正しいステージング環境ではないか、ということですね。
ただ、外部連携がある場合、「その連携先がステージング環境を提供しているのか」「ステージング環境の連携先から期待するレスポンスを取得することができるか」はこちらの構成とは別問題なので事前に確認しておきましょう。
できなければ別途スタブなどを検討する必要があります。

# まとめ
結論は前述の通り、ステージングは本番環境と同等の構成でなければならない、ということが言いたかっただけです。ネジの一本まで同じに揃えましょう。

しかし、「プロジェクト１」の事例のように、そもそものコストやサーバリソースの面でそのような構成は不可能、ということが往々にしてあるとは思います。
（特にSIerなら検証環境の大切さをお客様にご理解いただかなければならないですし。）

「ステージングは本番環境と同等の構成でなければならない」というのは理想論であるため、不可能な場合に現状で取れる最善策は何かというのを考えることも大切だと思います。
またその際に、「検証環境と本番環境のどこが異なることでどのような問題を孕む可能性があるのか」というのをしっかりと明確にできるようにしておきたいですね。
これがわかることで、お客様（自社サービスなら上司とか）にも環境差異によって担保できなくなる状況を説明できるようになるので、悲劇を未然に防止することができるのではないかとおもいます。

環境差異から生まれる悲しい休日のアラートが一件でも減ることを私は祈っております。。。