リリース・デプロイ戦略
ここでは Kubernetes 上で起動する server や worker の deploy 戦略について説明します。

前提

Wantedly 2021 年時点で 100 以上の microsevice によって構成されています。 各 microservice は基本的に下の convention を取ります。
  • Kubernetes に deploy する
  • 1 つの GitHub repository をもつ
  • 1 つの Kubernetes namespace (repository 名と同名)ともつ
  • 1 つの Docker image をもつ
このため一つの名前で、GitHub repository, Kubernetes namespace, 一つの microservice など複数のものを指すことがありますが、 上記の対応関係のために混乱することは殆どありません。

基本

Wantedly では GitHub Flow を採用しています。 したがって下のようなスタイルの開発になっています。
  • master branch から topic branch を切る
  • master branch に対して pull request を作る
  • master branch が更新されるたびに本番環境に反映される
これを維持するために各 repository では CI で下の2つのことを行っています。
  • 全 branch: Docker image の build (kube ci-build)
  • master: Docker image の deploy (kube <env> deploy)
ここで ci-build は commit hash を tag にもつ docker image を作成して registry に保管し、 deploy コマンドが Kubernetes の Deployment に対する変更を反映することで rolling で deploy されます。

Rolling Deploy

Rolling deploy では新旧2つのアプリケーションバージョンを一部ずつ置き換えていきます。 このため、アプリケーションにもよりますが最大で数分程度複数のバージョンが共存する時間ができることになるため、 すべての deploy は後方互換性をもたせる必要があります。 一例としてフロントエンドとサーバーサイドのコードを 1 つのコードベースで管理している microservice (wantedly/wantedly, wantedly/perk など) では API 追加とその API に依存する frontend は先に API のみを merge する必要があります。また逆に機能を落とす場合は先にフロントエンドからの依存がない状態を merge 仕切ってから API を落とす pull request を merge する必要があります。

Kubernetes Manifest 管理

2021 年 7 月現在ほとんどの repository で manifest 管理は手動です。 wantedly/wantedly や wantedly/analytics においては CronJob の生成/更新/削除は自動化されていますがこの例を除き殆どの repository では作成時以外に manifest の更新を行うことがなかったためにこのような構成になっています。 しかしながら、継続的な manifest 更新の取り組み (internal) などで自動更新をしていくことのメリットが大きくなっているため、試験的に ArgoCD を導入しています。 自分の管理する repository で導入したい場合はArgoCD 導入依頼 discussion (internal) に報告してください。 この点については社内のポリシーが短期間で変わる可能性があるため最新情報についてはインフラチームに問い合わせてください。

FeatureFlag

基本的にリリースブランチを持たない我々の開発手法ではコンフリクトを避けるためにコンスタントに master branch へ merge していくことが重要です。 しかしながら master branch で merge されると自動で deploy がなされるため、場合によっては変更をユーザーに見せたくないこともあります。 このような場合に FeatureFlag が有用です。 FeatureFlag は boolean, string のいずれかを返す method の返り値を request ごとに任意の値に変更できる Wantedly の社内基盤です。 値の変更を許可しておきたい method を事前に FeatureFlag の library で wrap しておくと Chrome Extension (internal) から override ができるようになります。 これを用いることでユーザーには機能を隠しておきつつ、qa 環境では簡単にその機能を顕在化させることができます。

Override 宣言のやり方

まず override できる method を指定する方法を示します。 現在 Rails と React がサポートされていますがそれ以外のフレームワークや言語に対応要望がある場合は Developer Experience Squad に相談してください。

Rails

最新 version の servicex が install されていることを確認してください。
1
module SomeNewFeature
2
# この module を include すると module 内の任意の method が override 可能になる
3
include Servicex::FeatureFlag::Trapper
4
# 正規表現で特定の method に絞ることも可能
5
feature_flag_trap_only /\?$/
6
7
# 上記の正規表現に match するため override 可能になる
8
# フラグ名は `SomeNewFeature.released?` となる
9
def released?
10
false
11
end
12
end
Copied!
1
module SomeNewFeature
2
# より低いレイヤの API を用いることで method でなくても任意の場所での override が可能
3
def released?
4
return true if some_condition
5
6
# some-flag-name という名前で override 可能になる
7
Servicex::FeatureFlag::Interceptor.intercept("some-flag-name") do
8
false
9
end
10
end
11
end
Copied!

React

1
// 注意
2
// - 2021年現在ライブラリとしての共通化が完了していないので各 frontend repository で定義されているものを利用する
3
// - 別途 context provider を挿入する必要があるので詳しいことは各 repository を参照
4
//.- wantedly-frontend は `useFeatureFlag`, wantedly-admin-frontend は `useBoolFlag` がそれ
5
import { useBoolFeatureFlag } from "useFeatureFlag";
6
7
export const SomeComponent: React.FC<Props> = (props) => {
8
const featureEnabled = useBoolFeatureFlag("some-awesome-new-feature");
9
10
...
11
};
Copied!

Override のやり方

Chrome Extension

上記の方法で override 可能にした method は Chrome Extension (internal) から override できます。
Chrome Extension の popup を開いた表示
qa 環境にアクセスして Chrome Extension の popup を開くと response の render に使われた flag の一覧が表示されます。 ここで変更したい flag の override を値を更新してページをリロードすることでサーバーの挙動を override することができるためリリース前の機能などを試すことができます。

Kubefork

より高頻度に確認したい場合は、特定の Flag を有効にしたサーバーを別の URL で serve することができます。 具体例として下のような状況が実現できます。
  • 新しいデザインの LP を出すかどうかを new-lp という Flag で提供
  • https://new-lp.qa.wantedly.com のような URL を作成
  • ここにアクセスすると任意のブラウザにおいて Chrome Extension なしで new-lp が有効になっているものとして動作する
エンジニアチーム外の人にテストをお願いしたいときには特に便利です。
詳しい利用方法については fork のドキュメント の「特定の FeatureFlag が有効にしたものをテストしたい」のセクションを参照してください。

Pull Request Preview

上記のように FeatureFlag を使うことでリリースブランチを作らないようにすることが基本方針です。 しかしながら依存 Library の upgrade やアプリケーションの構成の変更などどうしてもリリースブランチを作る必要があることもあるでしょう。 こういったケースでは Pull Request Preview が便利です。 任意の Pull Request において /preview <env> とコメントすると次の図のように URL がコメントされるためここにアクセスするだけで preview が実現できます。
Pull Request Preview の例
ブランチに更新があると追従されるため、数週間以上に渡ってリリースブランチを維持しなくてはいけないときに特に有効です。 この機能のバックエンドは マイクロサービスでもポチポチ確認するための Kubefork であるため、 ユーザーフェイシングでないマイクロサービスでも利用可能です。 2021 年 7 月現在、主要な repository はサポートされていますが自分の管理する repository が対応しているかについては Developer Experience Squad に問い合わせてください。

Migration

GitHub Flow では master branch に存在する commit はすべて deploy 可能であるべきです。 もちろんこれを完全に保証することは不可能ですが、自動デプロイを行っているため少なくとも最新の commit が deploy されて困る状態は許容できません。 したがって、データベースの migration に依存する commit の merge は migration のあとに行われる必要があります。
そこでこれを保証する CI として pending-migration-checker があります。
Pending Migration Checker の例
この check が落ちている場合は migration が必要です。 migration を kube prod sh などで実行して、/check migration とコメントすることで再度 check が実行されます。 詳しい設定方法などは上記の repository のリンク先を参照してください。

話を聞きに行きたい

もっと知りたい

最終更新 1mo ago