> For the complete documentation index, see [llms.txt](https://docs.wantedly.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.wantedly.dev/fields/dev-process/deploy-strategy-overview.md).

# リリース・デプロイ戦略

デプロイとはソフトウェアを実際にユーザーが使えるようにする行動です。 デプロイ戦略はその工夫によってプロダクト開発の速度と品質を担保し、ユーザーへの価値提供を最大化するための取り組みです。

デプロイには単純にアプリケーションを入れ替える他にも一部のユーザーだけに機能を使えるようにしたり、 一部のリクエストのみで新しいアプリケーションをリリースするなどの様々な戦略があります。

ここでは主にコンテナ上で動作するアプリケーション・サーバーを中心にウォンテッドリーにおいて選択可能なデプロイ戦略を紹介します。

* デプロイの前提
* 基本となるデプロイ戦略
  * Rolling Update
  * Rollback
  * Migration
  * 自動デプロイの仕組み
* 応用編
  * FeatureFlag
  * Canary Deploy
* ここに書かれていること以外のデプロイ戦略

## デプロイの前提

前提として、本番環境にデプロイする前に変更の Pull Request を作成し、CI をオールグリーンにしましょう。 また開発 / QA 環境での動作確認を行い、プロジェクト/プロダクトに要求される品質に応じて QA Squad による QA テストをクリアしましょう。

## 基本となるデプロイ戦略

基本的にウォンテッドリーのアプリケーションサーバー（= Kubernetes 上のコンテナ）の多くは コードをリポジトリの main ブランチ (master ブランチ) にコミットすると CI によってテストが実行され、 テストが通った場合にのみ本番環境へデプロイが自動的に実行されます。

要素としては次のようなものがあります。

* GitHub Flow & CI/CD
* Rolling Update

また、デプロイ関連する概念として次のようなものがあります。

* Rollback
* Migration

### Rolling Update

デプロイでは展開されたアプリケーションサーバーを順番に入れ替えていきます。 そのため最大で数分程度複数のバージョンが共存する時間ができることになるため、 すべてのデプロイは後方互換性をもたせる必要があります。

### Rollback

デプロイしたコードに問題があった場合、その問題を収束させるためにまず前のバージョンのコードに戻す、Rollback 作業を検討してください。 破壊的な変更の場合は Rollback ができないこともありますが、Rollback ができる場合は Rollback が最も早く問題を収束させることができます。

問題となったコードが再度デプロイされることを防ぐために lock することを推奨しています。

```
$ kube prod deploy <前のバージョンのコミットハッシュ>
$ kube prod lock 2h
```

この操作は本番環境にデプロイ操作を行うための権限を持つ人が行う必要があります。

また Revert Pull Request を作成して問題となったコードを main ブランチ (master ブランチ) から取り除きましょう。

### Migration

GitHub Flow では main ブランチ (master ブランチ) に存在するコミットはすべてデプロイ可能であるべきです。 もちろんこれを完全に保証することは不可能ですが、自動デプロイを行っているため少なくとも最新のコミットがデプロイされて困る状態は許容できません。 したがって、データベースのマイグレーションに依存するコミットのマージはマイグレーションのあとに行われる必要があります。

そこでこれを保証する CI として [pending-migration-checker (internal)](https://github.com/wantedly/pending-migration-checker) があります。

![Pending Migration Checker の例](/files/-MhWAMxbipCI544UJN_J)

この CI が落ちている場合はデータベースのマイグレーションが必要です。 マイグレーションを `kube prod sh` などで実行して、`/check migration` とコメントすることで再度 check が実行されます。

### 自動デプロイの仕組み

基本的にウォンテッドリーでは main ブランチ (master ブランチ) に変更がコミットされてから本番環境にデプロイされるまでが自動化されています。 その仕組みを簡単に図解します。

![wantedly-cicd.drawio.png](/files/ZpcTY7Si2fB0RI76wVwR)

main (master) にコミットしたアプリケーションコードの変更は CI によってコンテナイメージにビルドされ、テストが実行されます。 テストがパスすると、Kubernetes で動いているコンテナイメージを今回新しくビルドしたコンテナイメージに差し替える処理を行い本番環境にデプロイされます。

また、 main (master) にコミットしたインフラストラクチャのコード (= Kubernetes manifest YAML) は Argo CD によって本番環境に変更がデプロイされます。

技術的な詳細は [リリース・デプロイ戦略を支える技術#Kubernetes Manifest 管理](/fields/infrastructure/deploy-strategy-implement.md) を参照してください。

## 応用編

プロダクト開発において一部のユーザーや少数のリクエストだけで動作を確認したい、など柔軟なデプロイが求められるシーンがあります。 ウォンテッドリーでは応用的なデプロイとして戦略と基盤がいくつか整備されています。

* FeatureFlag
* Canary Deploy

### FeatureFlag

基本的にリリースブランチを持たない我々の開発手法ではコンフリクトを避けるためにコンスタントに main ブランチ (master ブランチ) にマージしていくことが重要です。 しかしながら main ブランチ (master ブランチ) でマージされると自動でデプロイがなされるため、場合によっては変更をユーザーに見せたくないこともあります。 このような場合に FeatureFlag が有用です。 FeatureFlag は `boolean`, `string` のいずれかを返す method の返り値をリクエストごとに任意の値に変更できるウォンテッドリーの社内基盤です。 値の変更を許可しておきたい method を事前に FeatureFlag の library で wrap しておくと [Chrome Extension (internal)](https://github.com/wantedly/chrome-dev-extension) から override ができるようになります。 これを用いることでユーザーには機能を隠しておきつつ、QA 環境では簡単にその機能を顕在化させることができます。

またこれは、社内のメンバーのみに機能を先行して提供してフィードバックを集めたり、本番環境で問題を発見するために使うことができます。

詳しい方法は [リリース・デプロイ戦略を支える実装](/fields/infrastructure/deploy-strategy-implement.md) の FeatureFlag を参照してください。

### Canary Deploy

Canary Deploy (Canary release) は、すでにデプロイされているバージョンと新しいバージョンの間でトラフィックを分割し、 ユーザーのサブセットに展開して完全にロールアウトするアプリケーションの段階的なロールアウトです。

Canary Deploy は、新しいバージョンのアプリケーションが本番環境で問題を引き起こす可能性が拭いきれない場合に有用です。 少数のリクエストで問題があればすぐロールバックが可能なため、影響範囲を最小限に抑えることができます。

ただし、データベースのマイグレーションが伴うなど破壊的な変更の場合は注意が必要です。

実行例

```
# current branch で canary deploy を開始する
$ kube prod lock 2h
$ kube prod canary start --current
```

```
# current branch で canary deploy を終了する
kube prod canary stop
kube prod unlock
```

## ここに書かれている以外のデプロイ戦略

アプリケーションサーバー以外のデプロイは異なるデプロイ戦略の場合があります。 例えばモバイルアプリは Apple Store などのアプリストアを通してユーザーに提供されるため、ブランチ戦略から異なることがあります。

また、基本的にはデプロイ戦略はその工夫によってプロダクト開発の速度と品質を担保し、ユーザーへの価値提供を最大化するための取り組みです。 そのためシステムやアプリケーション、技術の変化によって最適なデプロイ戦略は変わってくることに注意してください。

このデプロイ戦略を実際に行ってみて問題や改善点があれば、ぜひ以下のチャンネルでフィードバックしてください。

#### 話を聞きに行きたい

* Slack: [#infra](https://wantedly.slack.com/archives/C010V922570)

#### もっと知りたい

* [マイクロサービスでもポチポチ確認するための Kubefork | Wantedly Engineer Blog](https://www.wantedly.com/companies/wantedly/post_articles/313884)
* <https://github.com/wantedly/kube-go> (internal)
