リリース・デプロイ戦略を支える技術
最終更新
役に立ちましたか?
最終更新
役に立ちましたか?
ここでは Kubernetes 上で起動する server や worker の deploy 戦略について説明します。 Wantedly における Git 及び GitHub の運用方法が前提となるので事前に を読んでおくと良いでしょう。
各 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 では新旧2つのアプリケーションバージョンを一部ずつ置き換えていきます。 このため、アプリケーションにもよりますが最大で数分程度複数のバージョンが共存する時間ができることになるため、 すべての deploy は後方互換性をもたせる必要があります。 一例としてフロントエンドとサーバーサイドのコードを 1 つのコードベースで管理している microservice (wantedly/wantedly, wantedly/perk など) では API 追加とその API に依存する frontend は先に API のみを merge する必要があります。また逆に機能を落とす場合は先にフロントエンドからの依存がない状態を merge 仕切ってから API を落とす pull request を merge する必要があります。
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 への移行を検討するなど、さらなるデプロイ戦略の改善を進めています。
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 が用意されています。
まず override できる method を指定する方法を示します。 現在 Rails と React がサポートされていますがそれ以外のフレームワークや言語に対応要望がある場合は Developer Experience Squad に相談してください。
最新 version の servicex が install されていることを確認してください。
※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 して確かめることが可能です。
(2022年2月現在booleanしか対応していない)
qa 環境にアクセスして Chrome Extension の popup を開くと response の render に使われた flag の一覧が表示されます。 ここで変更したい flag の override を値を更新してページをリロードすることでサーバーの挙動を override することができるためリリース前の機能などを試すことができます。
より高頻度に確認したい場合は、特定の Flag を有効にしたサーバーを別の URL で serve することができます。 具体例として下のような状況が実現できます。
新しいデザインの LP を出すかどうかを new-lp
という Flag で提供
https://new-lp.qa.wantedly.com
のような URL を作成
ここにアクセスすると任意のブラウザにおいて Chrome Extension なしで new-lp
が有効になっているものとして動作する
エンジニアチーム外の人にテストをお願いしたいときには特に便利です。
上記のように FeatureFlag を使うことでリリースブランチを作らないようにすることが基本方針です。
しかしながら依存 Library の upgrade やアプリケーションの構成の変更などどうしてもリリースブランチを作る必要があることもあるでしょう。
こういったケースでは Pull Request Preview が便利です。
任意の Pull Request において /preview <env>
とコメントすると次の図のように URL がコメントされるためここにアクセスするだけで preview が実現できます。
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: ,