Wantedly Engineering Handbook
  • Wantedly Engineering Handbook
  • まえがき
  • 第一部:開発チームへの案内
    • 技術とアーキテクチャ
    • プロダクト概要(未執筆)
    • 開発チームの構造
    • コミュニケーションの全体
    • ドキュメンテーション(未執筆)
    • カレンダー
    • 障害対応の心構え
    • 効率的な社内知識の調べ方
    • 外部発信(執筆中)
  • 第二部:技術領域への案内
    • Apps
      • アプリを提供するプラットフォーム
      • デザインシステム入門
      • Web アプリのアーキテクチャ
      • プロダクトデザイナーと上手に協働するための心得
      • Web アプリのデザインシステムライブラリ
      • Web アプリ共通ライブラリ "React Shared Component" の紹介
      • モバイルアプリのアーキテクチャ
      • モバイルアプリのデザインシステムライブラリ(未執筆)
    • The System
      • protobuf スキーマと gRPC 通信
      • 実践: gRPC in Ruby
      • 実践: gRPC in Go
      • GraphQL Gateway - アプリ向けに API を公開する
      • Wantedly Visit で BFF GraphQL サーバーを辞めた理由
      • 実践: GraphQL スキーマ設計(未執筆)
      • API での認可処理 (Authorization)
      • マイクロサービス共通ライブラリ "servicex" の紹介
      • 非同期メッセージング処理入門(未執筆)
      • バッチ処理入門(未執筆)
    • Infrastructure
      • Infrastructure Squad
      • プロダクト開発のための Kubernetes 入門
      • インフラ構成概要
      • リリース・デプロイ戦略を支える技術
      • SaaS を活用する:New Relic, Honeybadger, Datadog
    • Data
      • データ基盤入門
      • レコメンデーション
      • Looker 入門
      • 推薦システムの開発に使っているツール
    • 開発プロセス
      • Git の慣習
      • ポストモーテムの取り組み
      • 負債返済日の取り組み
      • プロダクトの課題発見及び解決
      • ソフトウェアデザインの基礎
      • コードレビュー
      • コーディング規約
      • リリース・デプロイ戦略
      • 上長承認が必要な作業
      • アーキテクチャディシジョンレコード(ADR)
      • 作業ログを残す意味
      • 多言語化対応(i18n)
      • メール開発
    • 開発ツール
      • 社内利用している開発ツールの最新状況
      • kube
      • Code Coverage
      • Kubefork
  • おわりに
    • ロードマップ(未執筆)
    • Handbook の書き方
    • コントリビューター
  • 付録
    • 社内用語集
    • 主要な GitHub レポジトリのリスト(未執筆)
    • 今後の挑戦・未解決イシュー(未執筆)
    • プロダクト開発組織のバリュー(未執筆)
    • 採用についての考え方(未執筆)
GitBook提供
このページ内
  • デプロイ基盤
  • GitHub Flow の実現方法
  • Rolling Deploy
  • Kubernetes Manifest 管理
  • FeatureFlag
  • Override 宣言のやり方
  • Override のやり方
  • Pull Request Preview
  • Migration

役に立ちましたか?

  1. 第二部:技術領域への案内
  2. Infrastructure

リリース・デプロイ戦略を支える技術

前へインフラ構成概要次へSaaS を活用する:New Relic, Honeybadger, Datadog

最終更新 1 か月前

役に立ちましたか?

ここでは Kubernetes 上で起動する server や worker の deploy 戦略について説明します。 Wantedly における Git 及び GitHub の運用方法が前提となるので事前に を読んでおくと良いでしょう。

デプロイ基盤

GitHub Flow の実現方法

各 repository で CI/CD で下の2つのことを行うことで GitHub Flow を実現しています。

  • 全 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 されます。

いわゆる CIOps という Push 型のデプロイです。

Docker image 以外の更新、つまり Kubernetes Manifest のデプロイについては Argo CD による GitOps という Pull 型のデプロイを採用しています。

Rolling Deploy

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

Kubernetes Manifest 管理

Argo CD による GitOps

Kubernetes Manifest は を導入して GitOps という Pull 型のデプロイを行っています。

もともと Wantedly では Docker image の deploy を CICD で行っていましたが、Deployment 以外の Kubernetes manifest は長らく手動での apply になっていました。 そのため、以下のような課題・問題がありました。

  • リリースフローの自動化・高速化・簡易化を行い、インフラチーム以外でも Kubernetes Manifest の管理を可能にすることで開発・リリースの速度を早めたい

  • apply 忘れなどで repository と実際に apply されている manifest が異なり、Kubernetes Cluster のメンテナンスや Upgrade のブロックになっていた

  • apply 忘れなどで repository と実際に apply されている manifest が異なり、リリース時にアプリケーションエラーを引き起こすインシデントになった

ただし先述したとおり、アプリケーションコンテナのデプロイ は CICD で Kubernetes Deployment に対して変更を加えて Rolling Deploy を行っているため、2022年1月現在、docker image tag は GitOps の対象外となっています。 これは

  • 課題に対して docker image tag の GitOps は一旦スコープアウトできる

  • 障害対応時には kube <env> deploy <commit hash> コマンドで緊急切り戻しを行っているため、このフローのアジリティを壊したくなかった

といった背景がありました。

今後、docker image tag も含めて CIOps から GitOps への移行を検討するなど、さらなるデプロイ戦略の改善を進めています。

Kubernetes Manifest の自動生成・更新

GitOps に加えて、Wantedly の microservice ための Kubernetes Manifest を自動生成して継続的に更新する仕組みがあります。 たとえば kube generate autoscale --save を実行すると、その repository に必要な Deployment, HPA, Service, PDB といった Kubernetes Resource が生成されます。もちろん、Wantedly の microservice における推奨設定が自動的に入っています。

ingress や cronjob の他、Wantedly 内で独自定義された worker の Deployment などの様々な generate subcommand が用意されています。

$ kube generate                                              
Generate manifest files

Usage:
  kube generate [flags]
  kube generate [command]

Aliases:
  generate, g

Available Commands:
  autoscale          Generate manifest files for Deployment with Autoscale
  cronjob            Generate manifest files for Cronjob
  grpc               Generate manifest files for gRPC Deployment
  ingress            generate manifest files for Ingress to web pod
  internal-ingress   generate manifest files for Ingress resource for internal only
  namespace          Generate manifest files for Namespace
  rbac-kube-sh-by-ci Generate manifest files for resources to enable `kube sh` from CI
  redis              Generate manifest files for redis statefulset
  sidekiq-exporter   Generate manifest files for sidekiq-exporter
  worker             Generate manifest files for worker deployment

...

FeatureFlag

Override 宣言のやり方

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

Rails

最新 version の servicex が install されていることを確認してください。

module SomeNewFeature
  # この module を include すると module 内の任意の method が override 可能になる
  include Servicex::FeatureFlag::Trapper
  # 正規表現で特定の method に絞ることも可能
  feature_flag_trap_only /\?$/

  # 上記の正規表現に match するため override 可能になる
  # フラグ名は `SomeNewFeature.released?` となる
  def released?
    false
  end
end
module SomeNewFeature
  # より低いレイヤの API を用いることで method でなくても任意の場所での override が可能
  def released?
    return true if some_condition

    # some-flag-name という名前で override 可能になる
    Servicex::FeatureFlag::Interceptor.intercept("some-flag-name") do
      false
    end
  end
end

※Rails の FeatureFlag 実装は本番環境では override されないことに注意が必要です。 https://github.com/wantedly/servicex-ruby/blob/2709bd9c4e794cebf6fb694bec75f215972d72d6/lib/servicex/feature_flag.rb#L13

ただし本番環境でも FeatureFlag を使いたいケースは存在するため、実現に向けて検討中の段階となっています。 https://github.com/wantedly/dx/issues/382

使用したいモチベーションが冒頭の「コンスタントに master branch へ merge していくこと」だけならば 実装としては本番環境かどうかは予め環境変数で弾いておき、その上で Feature Flag の制御をするのがおすすめです。 こうすることで QA, Sandbox ではその制御を dev tool から flag を override して確かめることが可能です。

React

// 別途 context provider を挿入する必要があるので詳しいことは各 repository を参照
import { useBoolFlag } from "@wantedly_private/frontendx";

export const SomeComponent: React.FC<Props> = (props) => {
  const featureEnabled = useBoolFlag("some-awesome-new-feature");
  if (featureEnabled) {
    // ...
  }
};

(2022年2月現在booleanしか対応していない)

Override のやり方

Chrome Extension

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 が有効になっているものとして動作する

エンジニアチーム外の人にテストをお願いしたいときには特に便利です。

Pull Request Preview

上記のように FeatureFlag を使うことでリリースブランチを作らないようにすることが基本方針です。 しかしながら依存 Library の upgrade やアプリケーションの構成の変更などどうしてもリリースブランチを作る必要があることもあるでしょう。 こういったケースでは Pull Request Preview が便利です。 任意の Pull Request において /preview <env> とコメントすると次の図のように URL がコメントされるためここにアクセスするだけで preview が実現できます。

Migration

GitHub Flow では master branch に存在する commit はすべて deploy 可能であるべきです。 もちろんこれを完全に保証することは不可能ですが、自動デプロイを行っているため少なくとも最新の commit が deploy されて困る状態は許容できません。 したがって、データベースの migration に依存する commit の merge は migration のあとに行われる必要があります。

この check が落ちている場合は migration が必要です。 migration を kube prod sh などで実行して、/check migration とコメントすることで再度 check が実行されます。 詳しい設定方法などは上記の repository のリンク先を参照してください。

話を聞きに行きたい

もっと知りたい

  • https://github.com/wantedly/kube-go (internal)

そこで し、特に kubernetes manifest の継続的なデプロイの自動化をゴールとして、これらの課題を解決しています。

そしてこの自動生成された manifest は、 kube のバージョンが更新されるたびに新しくなります。最新版の manifest を保つために、Dependabot のような最新バージョンを検知して自動的に manifest 更新のプルリクエストを作ってくれる仕組みを作っています。 詳しく知りたい方はこちらも見てみてください。

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

上記の方法で override 可能にした method は から override できます。

詳しい利用方法については の「特定の FeatureFlag が有効にしたものをテストしたい」のセクションを参照してください。

ブランチに更新があると追従されるため、数週間以上に渡ってリリースブランチを維持しなくてはいけないときに特に有効です。 この機能のバックエンドは であるため、 ユーザーフェイシングでないマイクロサービスでも利用可能です。 2021 年 7 月現在、主要な repository はサポートされていますが自分の管理する repository が対応しているかについては Developer Experience Squad に問い合わせてください。

そこでこれを保証する CI として があります。

Slack: ,

Git の慣習
Argo CD
Argo CD による GitOps を導入 (internal)
継続的な manifest 更新の取り組み (internal)
Chrome Extension (internal)
Chrome Extension (internal)
fork のドキュメント
マイクロサービスでもポチポチ確認するための Kubefork
pending-migration-checker
#infra
#dx
マイクロサービスでもポチポチ確認するための Kubefork | Wantedly Engineer Blog
Chrome Extension の popup を開いた表示
Pull Request Preview の例
Pending Migration Checker の例