Operating Continuously

『Operating Continuously』は継続的〇〇の運用バージョンです。

<a href="https://www.amazon.co.jp/Operating-Continuously-Practices-Accelerating-Software/dp/1098117298"><img src="https://m.media-amazon.com/images/I/81mZljiX4SL._SL1500_.jpg" alt="Operating Continuously" width="200"/></a>

そもそも運用はもとより継続的なのでは?　と思いますが、DevOpsのインフィニティループの図では、一応フェーズが区切られていて、特にDev側のパッケージとOps側のデプロイ&リリースが分かれています。これを指して、ここにハンドオフ(受け渡し)が存在するから、改善の余地があるという論理展開になっています。

![DevOpsのInfinity Loop](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8475/df2370c4-f59a-f95c-0332-5f9b5e088e81.png)


## リリースとデプロイの逆転

本書のメインの主張は現代DevOpsでは「リリースとデプロイは逆にできる」というものです。

そもそもリリースとデプロイの定義からですが、DevOps文脈では以下のような解釈が一般的のようです。

* リリース
    * リリースは、ソフトウェア製品や機能が完成し、利用可能な状態になることを指す。
    * 製品や機能が品質保証（QA）プロセスを経て、実際の使用に耐えうると判断された時点を示す。
    * リリースは、開発チームが新しい機能や修正を「完成」とマークする行為です。しかし、これは必ずしもソフトウェアが実際にエンドユーザーに到達しているとは限らない。
* デプロイ
    * デプロイは、リリースされたソフトウェアを実際の運用環境（本番環境）に配置し、ユーザーがアクセスできるようにするプロセスである。
    * ソフトウェアをサーバにアップロードし、必要な設定を行い、動作を保証するための一連の手順が含まれる。
    * 製品が実際にエンドユーザーに届けられ、利用される段階を表す。

なので、従来はリリース判定で合格したものを、デプロイしてユーザに届けるのが通常でした。これをデプロイがリリースに先んじるようにしよう。というのが、Operating Continuouslyの中心的なアイデアです。具体的にはフィーチャーフラグを使って、デプロイ後に本番で動作確認し、問題なさそうなら一般ユーザに向けて機能開放していくということを指します。

## デプロイ

漸進的なデプロイの戦術としては以下の２通りが示されています。

* ブルーグリーンデプロイ
    * 現行のバージョンのアプリケーション(ブルー)と、新しいバージョンのアプリケーション(グリーン)を並行稼働させる。
    * グリーンでの動作確認ができたら、ロードバランサなどで、外部からのトラフィックもブルーからグリーンへ向き先を変える。
    * しばらくはブルーもアクティブな状態にしておいて、グリーンで問題発生したらすぐに切り戻せるようにしておく。
* カナリアデプロイ
    * 新しいバージョンのアプリケーションを並行稼働させるところまでは、ブルーグリーンと同じだが、トラフィックを一気に切り替えるのではなく、少しずつ新バージョンに移していく。
    * 新バージョンのアプリケーションの問題の影響を受けるユーザ数をなるべく少なくする狙い。

## リリース

デプロイしたものを徐々にユーザにリリースしていくのを、漸進リリース(Progressive Release)と呼びます。デプロイの方でのカナリアと似ているものの、カナリアデプロイはインフラをトラフィックがだんだん増えていくようにデプロイすることを指し、漸進リリースはコードをユーザの割合がだんだん増えていくようにリリースすることを指します。

ユーザの割合を徐々に増やしていくのに、フィーチャーフラグがよく使われます。

[LaunchDarkly](https://launchdarkly.com/)のような、フィーチャー管理プラットフォームを使うと、開発者や運用者でなくても、フィーチャーフラグの設定をして、リリースできるようになります。したがってより機能リリースに責任を持つ人に、実際のリリース作業を段階的に委譲でき、その方がアジリティが上がります。これを漸進委譲と呼びます(これは『Operating Continuously』オリジナルの用語かもしれません)。

## 運用、計測

このフェーズには、特に新しい話はありませんが、インシデント事後処理のポストモーテムは、よくBlameless(責任追及しない)がセットで語られます。

これは以前[まとめたもの](https://scrapbox.io/kawasima/%E3%83%9D%E3%82%B9%E3%83%88%E3%83%A2%E3%83%BC%E3%83%86%E3%83%A0)
がありますので、そちらをご覧ください。

## アプリケーション設計視点からの漸進リリース

A/Bテストが流行り出した当初から課題としてありましたが、

1. アプリケーションコードにバージョン判定するif文が入りまくる。
2. データベーススキーマの変更を伴う場合の互換性確保

に関しては、あまり有効な手立ては、本書でも述べられていないし、フィーチャー管理プラットフォームのサイトでもあまり言及されていません。

１の観点に関しては、[AB Tastyのサイト](https://www.abtasty.com/blog/technical-debt-feature-flag/)には、「技術的負債のもとである」としており、「不要になったif文を消していく」が対策として書かれています。うーん…

厄介なのは、永続的なものに昇格するフィーチャーフラグもあり、if文じゃなくてポリモーフィズムが適切な設計かも…だったり、フラグの意味がわかりにくく可読性が下がる…だったりの負債として残り続けるものがあることです。これもまた解決策は継続的なリファクタリングや命名の工夫が挙げられていて、地道な対策しか提示されていません。

2の観点はさらに厄介です。[LaunchDarklyのサイト](https://docs.launchdarkly.com/guides/infrastructure/infrastructure-migration)で、シンプルなマイグレーションの例は挙げられています。

データベース側の基本戦術としては、新バージョンと旧バージョンで両方動くようなスキーマ変更をしていくことになるので、[データベース リファクタリング](https://www.amazon.co.jp/%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%83%BB%E3%83%AA%E3%83%95%E3%82%A1%E3%82%AF%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0-%E3%82%B9%E3%82%B3%E3%83%83%E3%83%88-W-%E3%82%A2%E3%83%B3%E3%83%96%E3%83%A9%E3%83%BC/dp/4894715007)に書かれているような手法を使うのが、現時点での現実界のように思います。
※　データベースリファクタリングの書籍では、新旧テーブルの互換性維持のために、比較的データベーストリガーを使う手法を多用しています。複雑性が高くなるので、別の手段を考えた方が良いかもしれません。