- 設計
デプロイ方式の種類と違い|ブルーグリーン・カナリア・ローリング比較
デプロイ方式とは、稼働中のシステムを旧版から新版へ入れ替える進め方のことで、代表的なものは一括・ローリング・ブルーグリーン・カナリアの4つ、これに機能フラグの併用を加えた5つです。 違いは「追加で何台いるか」「止まる時間があるか」「どうやって元に戻すか」「新版と旧版が同時に動くか」の4点に集まります。
この記事は方式を選ぶところに絞り、5方式の比較表、方式ごとのシーケンス図、Kubernetes のマニフェスト、台数と所要時間の計算、切り戻し判断基準の記入テンプレート、新旧が同時に動く間のデータベース変更の順番をまとめます。
確認環境(2026-10-06):Ubuntu 24.04。マニフェストは kubernetes-validate 1.36.0(Kubernetes 1.36 のスキーマ)の厳密モードで検査、計算例は Python 3.11.15 で実行、SQL は PostgreSQL 16.15 で実行、図は @mermaid-js/mermaid-cli 11.14.0 で描画できることを確認しています。Kubernetes の既定値は公式ドキュメントの Deployments のページの記載です。
この記事の結論
- 切り戻しの速さを優先するなら、ブルーグリーン。 振り分け先を戻すだけで旧版に戻ります。そのかわり、切り替えの間はふだんの2倍の台数を使います。
- 影響範囲を絞って確かめたいなら、カナリア。 一部のリクエストだけを新版に流し、数値を見てから広げます。
- 追加の台数を抑えたいなら、ローリング。 数台ずつ入れ替えるので、追加は1台からで済みます。
- 止めてよい時間帯があり、新旧を同時に動かしたくないなら、一括。 仕組みがいちばん単純です。
- 「置く」と「見せる」を分けたいなら、機能フラグを併用。 デプロイは上のどれかで行い、公開はフラグで切り替えます。
デプロイ方式の選び方の早見表
| 優先したいこと | 選ぶ方式 | 理由 |
|---|---|---|
| 切り戻しを数秒〜数十秒で終えたい | ブルーグリーン | 旧版を動かしたまま残すので、振り分け先を戻すだけ |
| 新版の影響を一部の利用者にとどめて確かめたい | カナリア | 新版に流す割合を 10% などに絞れる |
| 追加の台数を少なくしたい | ローリング | 追加は maxSurge で指定した台数だけ |
| 新旧の混在を避けたい(データ形式が大きく変わるなど) | 一括 | 旧版を止めてから新版を起動する |
| 利用者への公開日をデプロイ日と別にしたい | 機能フラグ併用 | デプロイ後にフラグで公開する |
| まず標準の方法で始めたい | ローリング | Kubernetes の Deployment の既定の方式 |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「デプロイ方式の種類と違い|ブルーグリーン・カナリア・ローリング比較」
5方式の比較表(必要台数・停止時間・切り戻し・新旧混在)
ふだん N 台で動かしているシステムを入れ替える場合で比べます。
| 方式 | 入れ替え中の最大台数 | 停止時間 | 切り戻し手順 | 新旧の混在 |
|---|---|---|---|---|
| 一括(Recreate) | N | あり(旧版の停止から新版の準備完了まで) | 旧版を一括でデプロイし直す(もう一度止まる) | なし |
| ローリング | N + maxSurge | なし(maxUnavailable の分だけ処理できる台数が減る) | 旧版へ向けてもう一度ローリングする | あり(入れ替えの間ずっと) |
| ブルーグリーン | 2N | なし | 振り分け先を旧版へ戻す | アプリは切り替えの瞬間だけ。DB は共有するのであり |
| カナリア | N + カナリアの台数 | なし | 新版の割合を 0% に戻す(カナリアを 0 台にする) | あり(意図して混在させる) |
| 機能フラグ併用 | デプロイに使った方式と同じ | なし | フラグをオフに戻す(再デプロイなし) | 同じ版の中に新旧のコードが同居 |
表計算ソフトに貼れる形(タブ区切り)です。
方式 入れ替え中の最大台数 停止時間 切り戻し手順 新旧の混在
一括(Recreate) N あり 旧版を一括でデプロイし直す なし
ローリング N + maxSurge なし 旧版へ向けてもう一度ローリング あり
ブルーグリーン 2N なし 振り分け先を旧版へ戻す アプリは切り替えの瞬間だけ・DBはあり
カナリア N + カナリアの台数 なし 新版の割合を0%に戻す あり
機能フラグ併用 デプロイ方式と同じ なし フラグをオフに戻す 同じ版に新旧のコードが同居
「新旧の混在」が「あり」の方式では、新版と旧版が同じデータベースを同時に読み書きします。 この点が、後半の「DB 変更は追加→移行→削除の順に分ける」につながります。
デプロイとリリースの違い
方式を選ぶ前に、2つの言葉を分けておくと整理しやすくなります。
| 言葉 | 意味 | 切り替えるもの | 元に戻す方法 |
|---|---|---|---|
| デプロイ | 新版のプログラムを稼働環境に置いて動かすこと | サーバー上のプログラム | 旧版を置き直す、振り分け先を戻す |
| リリース | 新しい機能を利用者が使える状態にすること | 利用者に見えるかどうか | 振り分けの割合やフラグを戻す |
一括とローリングでは、デプロイが終わると同時にリリースも終わります。ブルーグリーンは「新版を起動する(デプロイ)」と「振り分け先を切り替える(リリース)」が別の操作になり、カナリアはリリースを割合で少しずつ進め、機能フラグはリリースをプログラムの外の設定に移します。
| 方式 | デプロイとリリースの関係 |
|---|---|
| 一括 | 同時 |
| ローリング | 同時(台ごとに順に) |
| ブルーグリーン | 分かれる(起動 → 確認 → 切り替え) |
| カナリア | 分かれる(起動 → 割合を段階的に上げる) |
| 機能フラグ併用 | 分かれる(デプロイ後、好きな日時に公開) |
一括デプロイ(Recreate)
旧版をすべて止めてから、新版をすべて起動します。新旧が同時に動かないので、データ形式が大きく変わる変更や、夜間に止められる社内システムに向きます。
sequenceDiagram
participant U as 利用者
participant LB as 振り分け
participant V1 as 旧版(全台)
participant V2 as 新版(全台)
U->>LB: リクエスト
LB->>V1: 旧版が応答
Note over V1: 旧版をすべて停止
U->>LB: リクエスト
LB--xU: 応答できない(停止時間)
Note over V2: 新版をすべて起動
U->>LB: リクエスト
LB->>V2: 新版が応答
Kubernetes では strategy.type を Recreate にします。公式ドキュメントには、Recreate では新しい Pod を作る前に既存の Pod がすべて終了されると書かれています。
# 一括(Recreate):旧版をすべて止めてから新版を起動する
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 10
strategy:
type: Recreate
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: registry.example.com/web:1.1.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /healthz
port: 8080
切り戻しは、イメージを旧版に戻して同じ操作をもう一度行います。切り戻しでも同じだけ止まるので、止めてよい時間を「入れ替え+切り戻し」の2回分で見ておきます。
ローリングデプロイ
数台ずつ振り分けから外し、新版に入れ替えて戻す、を繰り返します。追加の台数が少なく、止まる時間もありません。 Kubernetes の Deployment は、何も指定しなければこの方式(RollingUpdate)です。
sequenceDiagram
participant LB as 振り分け
participant A as 1〜3台目
participant B as 4〜6台目
participant C as 7〜10台目
Note over A,C: 全台が旧版
LB-->>A: 振り分けから外す
Note over A: 新版に入れ替え
A->>LB: 準備完了(戻す)
Note over A,C: 新版と旧版が混在
LB-->>B: 振り分けから外す
Note over B: 新版に入れ替え
B->>LB: 準備完了(戻す)
LB-->>C: 振り分けから外す
Note over C: 新版に入れ替え
C->>LB: 準備完了(戻す)
Note over A,C: 全台が新版
# ローリング:少しずつ入れ替える(Deployment の既定の方式)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 10
minReadySeconds: 10
progressDeadlineSeconds: 600
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: registry.example.com/web:1.1.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /healthz
port: 8080
| 項目 | 意味 | 既定値(公式ドキュメントの記載) |
|---|---|---|
maxSurge |
指定した台数を超えて作ってよい Pod の数 | 25%(割合は切り上げで台数に直す) |
maxUnavailable |
入れ替え中に使えなくてよい Pod の数 | 25%(割合は切り捨てで台数に直す) |
minReadySeconds |
準備完了のあと、利用可能と見なすまで待つ秒数 | 0 |
progressDeadlineSeconds |
進まないときに「進行していない」と報告するまでの秒数 | 600 |
revisionHistoryLimit |
切り戻し用に残す以前の ReplicaSet の数 | 10 |
切り戻しは次のコマンドです。直前の版へ向けて、同じローリングがもう一度走ります。
kubectl rollout undo deployment/web
kubectl rollout status deployment/web
切り戻しにも入れ替えと同じだけ時間がかかる点が、ブルーグリーンとの違いです。
ブルーグリーンデプロイ
旧版(ブルー)と同じ台数の新版(グリーン)を横に並べ、確認が済んだら振り分け先を一度に切り替えます。旧版を動かしたまま残すので、戻すときも振り分け先を変えるだけです。
sequenceDiagram
participant U as 利用者
participant LB as 振り分け
participant B as ブルー(旧版10台)
participant G as グリーン(新版10台)
U->>LB: リクエスト
LB->>B: 旧版が応答
Note over G: 新版を10台起動し、内部から動作確認
Note over LB: 振り分け先をグリーンへ切り替え
U->>LB: リクエスト
LB->>G: 新版が応答
Note over B: しばらく残す(切り戻し用)
alt 問題が見つかった
Note over LB: 振り分け先をブルーへ戻す
LB->>B: 旧版が応答
else 問題なし
Note over B: ブルーを片付ける
end
Kubernetes では、Deployment を2つ作り、Service の selector を書き換えて切り替える形にできます。
# ブルーグリーン:旧版(blue)と新版(green)を同じ台数で並べ、Service の selector で切り替える
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-blue
spec:
replicas: 10
selector:
matchLabels:
app: web
color: blue
template:
metadata:
labels:
app: web
color: blue
spec:
containers:
- name: web
image: registry.example.com/web:1.0.0
ports:
- containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-green
spec:
replicas: 10
selector:
matchLabels:
app: web
color: green
template:
metadata:
labels:
app: web
color: green
spec:
containers:
- name: web
image: registry.example.com/web:1.1.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
color: blue # ここを green に書き換えると切り替わる。blue に戻せば切り戻し
ports:
- port: 80
targetPort: 8080
切り替えと切り戻しは、Service の selector を書き換えるだけです。コマンドの形は、公式ドキュメントの Deployments のページにある kubectl patch・kubectl scale・kubectl rollout の書き方に合わせています。
# 切り替え(グリーンへ)
kubectl patch service/web -p '{"spec":{"selector":{"app":"web","color":"green"}}}'
# 切り戻し(ブルーへ)
kubectl patch service/web -p '{"spec":{"selector":{"app":"web","color":"blue"}}}'
切り替えのあと、ブルーをいつまで残すかを先に決めておきます(例:翌営業日の正午まで)。残している間は2倍の台数を使います。
カナリアリリース
新版を少数だけ起動し、一部のリクエストだけを流して、エラー率や応答時間を旧版と見比べます。基準を満たしたら割合を上げ、外れたら 0% に戻します。
sequenceDiagram
participant U as 利用者
participant LB as 振り分け
participant S as 安定版(旧版)
participant K as カナリア(新版)
Note over K: 新版を1台だけ起動
U->>LB: リクエスト 100件
LB->>S: 90件
LB->>K: 10件
Note over LB,K: エラー率と応答時間を見比べる
alt 基準を満たす
Note over LB: 新版の割合を 50% → 100% へ
LB->>K: すべて新版へ
else 基準を外れた
Note over LB: 新版の割合を 0% に戻す
LB->>S: すべて旧版へ
end
Kubernetes の公式ドキュメント(Managing Workloads)には、track: stable と track: canary のラベルを付けた2つの Deployment を作り、Service の selector には track を書かずに両方へ振り分ける例が載っています。同じ考え方で、安定版9台・カナリア1台にしたものが次のマニフェストです。
# カナリア:安定版 9 台に新版 1 台を混ぜる(Service は track を見ずに両方へ振り分ける)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-stable
spec:
replicas: 9
selector:
matchLabels:
app: web
track: stable
template:
metadata:
labels:
app: web
track: stable
spec:
containers:
- name: web
image: registry.example.com/web:1.0.0
ports:
- containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-canary
spec:
replicas: 1
selector:
matchLabels:
app: web
track: canary
template:
metadata:
labels:
app: web
track: canary
spec:
containers:
- name: web
image: registry.example.com/web:1.1.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web # track を書かないので stable と canary の両方が対象になる
ports:
- port: 80
targetPort: 8080
この形では、新版に流れる割合は台数の比で決まります(9台と1台なら約 10%)。1% のような細かい割合にしたいときは、台数の比ではなく、振り分け側で重みを指定できる仕組みを使います。
# 広げる:カナリアを増やし、安定版を減らす
kubectl scale deployment/web-canary --replicas=5
kubectl scale deployment/web-stable --replicas=5
# 切り戻し:カナリアを 0 台にする
kubectl scale deployment/web-canary --replicas=0
kubectl scale deployment/web-stable --replicas=10
機能フラグの併用
機能フラグ(フィーチャーフラグ)は、新しい機能をオフの状態でデプロイしておき、設定の切り替えで公開する方法です。デプロイそのものは、ここまでの4方式のどれかで行います。
sequenceDiagram
participant D as 開発者
participant P as 稼働環境
participant F as フラグ設定
participant U as 利用者
D->>P: 新機能をオフのままデプロイ
U->>P: リクエスト
P->>F: 新機能はオンか
F-->>P: オフ
P-->>U: これまでの画面
D->>F: オンに変更(リリース)
U->>P: リクエスト
P->>F: 新機能はオンか
F-->>P: オン
P-->>U: 新しい画面
Note over D,F: 問題があればフラグをオフに戻す(再デプロイなし)
| 向いている変更 | 向かない変更 |
|---|---|
| 画面や処理の追加など、if で分けられる機能 | ランタイムやライブラリの版上げ |
| 公開日が決まっている機能 | テーブル構造の変更そのもの |
| 一部の利用者から先に見せたい機能 | 起動時にしか読まれない設定の変更 |
フラグで戻せるのは、フラグで囲んだ範囲だけです。 プログラム全体に関わる変更は、デプロイ方式の切り戻しで戻します。
必要台数と所要時間の計算例
ふだん10台、1台の起動から準備完了まで60秒、旧版が処理中のリクエストを終えて止まるまで30秒、カナリアの1段階で様子を見る時間を600秒とした例です。数値はすべて例で、自分のシステムの値に書き換えて使います。
import math
def rolling_plan(n, max_surge="25%", max_unavailable="25%"):
"""Kubernetes の既定と同じ丸め(maxSurge は切り上げ、maxUnavailable は切り捨て)"""
def to_abs(v, up):
if isinstance(v, str) and v.endswith("%"):
x = n * int(v[:-1]) / 100
return math.ceil(x) if up else math.floor(x)
return int(v)
return to_abs(max_surge, True), to_abs(max_unavailable, False)
def rolling_rounds(n, surge, unavail):
"""1 巡 = 「新版を起動して準備完了になるまで」として、何巡で入れ替わるかを数える"""
old, new_ready, rounds, peak, low = n, 0, 0, n, n
while new_ready < n:
# 使える台数が n - unavail を下回らない範囲で旧版を止める
stop = min(old, max(0, old + new_ready - (n - unavail)))
old -= stop
low = min(low, old + new_ready)
# 合計が n + surge を超えない範囲で新版を起動する
start = min(n - new_ready, (n + surge) - (old + new_ready))
peak = max(peak, old + new_ready + start)
new_ready += start
rounds += 1
return rounds, peak, low
N = 10 # ふだんの台数
BOOT = 60 # 1 台が起動して準備完了になるまでの秒数(例)
STOP = 30 # 旧版が処理中のリクエストを終えて止まるまでの秒数(例)
WATCH = 600 # カナリアの 1 段階で様子を見る秒数(例)
print("方式\t最大台数\t追加台数\t所要時間(秒)\t停止時間(秒)")
print(f"一括\t{N}\t0\t{STOP + BOOT}\t{STOP + BOOT}")
for ms, mu in [("25%", "25%"), (1, 0), ("100%", 0)]:
s, u = rolling_plan(N, ms, mu)
r, peak, low = rolling_rounds(N, s, u)
print(f"ローリング(maxSurge={ms},maxUnavailable={mu})\t{peak}\t{peak - N}\t{r * BOOT}\t0(最少{low}台で処理)")
print(f"ブルーグリーン\t{2 * N}\t{N}\t{BOOT}\t0")
stages = [10, 50, 100]
print(f"カナリア({'→'.join(str(x) + '%' for x in stages)})\t{N + 1}\t1\t{BOOT + WATCH * (len(stages) - 1) + BOOT * 2}\t0")
print()
print("台数\tmaxSurge=25%\tmaxUnavailable=25%\t巡数\t最大台数\t最少台数")
for n in [2, 3, 4, 10, 20]:
s, u = rolling_plan(n)
if s == 0 and u == 0:
print(n, s, u, "進まない", sep="\t"); continue
r, peak, low = rolling_rounds(n, s, u)
print(n, s, u, r, peak, low, sep="\t")
方式 最大台数 追加台数 所要時間(秒) 停止時間(秒)
一括 10 0 90 90
ローリング(maxSurge=25%,maxUnavailable=25%) 13 3 120 0(最少8台で処理)
ローリング(maxSurge=1,maxUnavailable=0) 11 1 600 0(最少10台で処理)
ローリング(maxSurge=100%,maxUnavailable=0) 20 10 60 0(最少10台で処理)
ブルーグリーン 20 10 60 0
カナリア(10%→50%→100%) 11 1 1380 0
台数 maxSurge=25% maxUnavailable=25% 巡数 最大台数 最少台数
2 1 0 2 3 2
3 1 0 3 4 3
4 1 1 2 5 3
10 3 2 2 13 8
20 5 5 2 25 15
ローリングの所要時間は「1巡で起動できる台数ずつ進む」とした単純なモデルです。カナリアは、起動60秒+観察600秒+50%への入れ替え60秒+観察600秒+100%への入れ替え60秒で、1台増やしてから1台減らす進め方を前提にしています。
| 読み取れること | 数字 |
|---|---|
| ローリングは、追加を1台に絞ると時間が延びる | maxSurge=1 で 600秒、既定の 25% で 120秒 |
| ローリングで maxSurge を 100% にすると、台数も時間もブルーグリーンと同じになる | 最大20台・60秒 |
| 既定の 25% のままでは、処理できる台数が一時的に減る | 10台構成で最少8台 |
| カナリアは台数は少ないが、観察の時間がそのまま所要時間になる | 1380秒のうち 1200秒が観察 |
新旧が同時に動く間のDB変更は「追加→移行→削除」に分ける
ローリング・カナリアでは入れ替えの間、ブルーグリーンでも切り替えの前後と切り戻しに備える間、新版と旧版が同じデータベースを使います。 そこで、テーブルの変更は「どちらの版から見ても動く」形で3回に分けます。
| 手順 | DB の変更 | 合わせてデプロイする版 | 旧版から見て |
|---|---|---|---|
| 1. 追加 | 新しい列(やテーブル)を足す | まだ変えない | そのまま動く |
| 2. 移行 | 既存の行を新しい列へ写す | 両方の列に書き、新しい列を読む版 | そのまま動く |
| 3. 削除 | 以前の列を消す | 以前の列を使わない版が全台に行き渡ってから | 旧版はもう残っていない |
会員テーブルの列名 tel を phone に変える例を、PostgreSQL 16 で流した結果です。
CREATE TABLE members (id int PRIMARY KEY, name text NOT NULL, tel text);
INSERT INTO members VALUES (1,'山田 太郎','000-0000-0001'),(2,'佐藤 花子','000-0000-0002');
-- 止まる例:新旧が混在している間に、列名を直接変える
BEGIN;
ALTER TABLE members RENAME COLUMN tel TO phone;
SELECT id, name, tel FROM members WHERE id = 1; -- 旧版が発行する SQL
ROLLBACK;
ERROR: column "tel" does not exist
LINE 1: SELECT id, name, tel FROM members WHERE id = 1;
^
列名を一度に変えると、まだ残っている旧版の SQL がこのエラーで止まります。3つに分けると次のようになります。
-- 手順1 追加:新しい列を足す(旧版はそのまま動く)
ALTER TABLE members ADD COLUMN phone text;
SELECT id, name, tel FROM members WHERE id = 1; -- 旧版が発行する SQL
-- 手順2 移行:両方の列に書く版をデプロイし、既存の行を写す
INSERT INTO members (id, name, tel, phone) VALUES (3,'鈴木 次郎','000-0000-0003','000-0000-0003');
UPDATE members SET phone = tel WHERE phone IS NULL;
SELECT count(*) AS 未移行 FROM members WHERE phone IS DISTINCT FROM tel;
SELECT id, name, phone FROM members ORDER BY id; -- 新版が発行する SQL
-- 手順3 削除:旧版が1台も残っていないことを確かめてから列を消す
ALTER TABLE members DROP COLUMN tel;
ALTER TABLE
id | name | tel
----+-----------+---------------
1 | 山田 太郎 | 000-0000-0001
(1 row)
INSERT 0 1
UPDATE 2
未移行
--------
0
(1 row)
id | name | phone
----+-----------+---------------
1 | 山田 太郎 | 000-0000-0001
2 | 佐藤 花子 | 000-0000-0002
3 | 鈴木 次郎 | 000-0000-0003
(3 rows)
ALTER TABLE
手順3を別のデプロイに分けておくと、手順2までは旧版へ切り戻せます。 列を消したあとは旧版に戻せなくなるので、「削除」は切り戻しの期限が過ぎてから行います。
| DB の変更 | 新旧混在のまま進められるか | 進め方 |
|---|---|---|
| 列・テーブルの追加(NULL 可、または既定値あり) | 進められる | 手順1だけで済む |
| 列名の変更 | 分ければ進められる | 追加→移行→削除 |
| 列の型の変更 | 分ければ進められる | 新しい型の列を追加→移行→削除 |
| NOT NULL の追加 | 分ければ進められる | 新版が必ず値を入れるようにしてから制約を付ける |
| 列・テーブルの削除 | 最後に行う | どの版も使っていないことを確かめてから |
方式ごとの切り戻し手順と、判断基準の記入テンプレート
| 方式 | 切り戻しの操作 | かかる時間の目安 | 先に決めておくこと |
|---|---|---|---|
| 一括 | 旧版を一括でデプロイし直す | 入れ替えと同じ(上の例で90秒、その間は止まる) | 止めてよい時間を2回分で確保 |
| ローリング | kubectl rollout undo |
入れ替えと同じ(上の例で120〜600秒) | 残す履歴の数(revisionHistoryLimit) |
| ブルーグリーン | 振り分け先を旧版へ戻す | 振り分けの切り替えにかかる時間 | 旧版を残す期限 |
| カナリア | 新版の割合を 0% にする | 振り分けの切り替えにかかる時間 | 各段階の割合と観察時間 |
| 機能フラグ併用 | フラグをオフにする | 設定が反映されるまでの時間 | フラグの担当者と確認方法 |
切り戻すかどうかは、デプロイの前に数値で決めておきます。 当日に迷う時間を減らすための記入テンプレートです。
## 切り戻し判断基準(デプロイ前に記入)
- 対象:
- デプロイ方式:
- 切り戻しの操作:
- 切り戻しにかかる時間:
- 切り戻しができなくなる時点(例:以前の列を削除したあと):
- 判断する人: 代わりの人:
| No | 見る指標 | ふだんの値 | 切り戻す基準 | 見る期間 | 確認方法 |
|---|---|---|---|---|---|
| 1 | エラー率(5xx) | | | | |
| 2 | 応答時間(95パーセンタイル) | | | | |
| 3 | 主要な操作の成功数 | | | | |
| 4 | 問い合わせ件数 | | | | |
- 1つでも基準に当たったら切り戻す/ 個以上で切り戻す:
- 基準に当たらないが迷うときの扱い(例:割合を上げずにもう30分見る):
記入例(架空の備品予約システム、カナリアで公開する場合)です。数値は例です。
| No | 見る指標 | ふだんの値 | 切り戻す基準 | 見る期間 | 確認方法 |
|---|---|---|---|---|---|
| 1 | エラー率(5xx) | 0.1% | 新版が 1% を超える | 各段階 10分 | 監視画面で新版と旧版を並べる |
| 2 | 応答時間(95パーセンタイル) | 400ms | 新版が旧版の 1.5倍を超える | 各段階 10分 | 監視画面 |
| 3 | 予約登録の成功数 | 1分あたり 20件 | 新版側で 5分間 0件 | 各段階 10分 | アプリのログ集計 |
| 4 | 問い合わせ件数 | 1時間あたり 1件 | 同じ内容が 3件届く | 公開後 2時間 | 問い合わせ窓口と共有 |
No 見る指標 ふだんの値 切り戻す基準 見る期間 確認方法
1 エラー率(5xx) 0.1% 新版が1%を超える 各段階10分 監視画面で新版と旧版を並べる
2 応答時間(95パーセンタイル) 400ms 新版が旧版の1.5倍を超える 各段階10分 監視画面
3 予約登録の成功数 1分あたり20件 新版側で5分間0件 各段階10分 アプリのログ集計
4 問い合わせ件数 1時間あたり1件 同じ内容が3件届く 公開後2時間 問い合わせ窓口と共有
似た言葉との違いと、条件から選ぶ判断表
| 言葉 | デプロイ方式との関係 |
|---|---|
| A/B テスト | 振り分けの仕組みはカナリアと似ていますが、目的が違います。カナリアは「新版が安定して動くか」、A/B テストは「どちらの案が利用者に選ばれるか」を見ます |
| ダークローンチ | 利用者には見せずに新版を稼働環境で動かすこと。機能フラグをオフにしたデプロイがこれに当たります |
| イミュータブルな入れ替え | 動いているサーバーを書き換えず、新しいサーバーを作って置き換える考え方。ブルーグリーンはこの考え方に沿っています |
| ローリング再起動 | 版は変えずに、順番に再起動すること。進め方はローリングデプロイと同じです |
| 条件 | 選ぶ方式 |
|---|---|
| 止めてよい時間帯がある。新旧の混在を避けたい | 一括 |
| 止められない。台数に余裕が少ない | ローリング(maxSurge を小さく) |
| 止められない。切り戻しを最優先にしたい。一時的に2倍の台数を用意できる | ブルーグリーン |
| 止められない。新版の影響が読みきれないので少しずつ確かめたい。新旧を比べる監視がある | カナリア |
| 公開日を別に決めたい。画面や処理の追加である | いずれかの方式+機能フラグ |
| テーブルの列名や型が変わる | どの方式でも、DB 変更を追加→移行→削除に分ける |
確かめて分かったこと
- 既定の 25% は、台数が少ないと 0 台や 1 台に丸まります。 maxSurge は切り上げ、maxUnavailable は切り捨てなので、2台・3台の構成では「追加1台・使えなくてよい台数0」になり、処理できる台数は減りません。4台以上になると maxUnavailable が1以上になり、入れ替え中に処理できる台数が減ります。
- ローリングで maxSurge を 100%、maxUnavailable を 0 にすると、最大台数も所要時間もブルーグリーンと同じ数字になりました。 違いは、切り替えを人の判断で止められるかどうかと、切り戻しが振り分けの変更だけで済むかどうかです。
- カナリアの所要時間のほとんどは観察の時間でした。 上の例では 1380秒のうち 1200秒です。段階の数と観察時間を決めることが、そのまま所要時間の見積もりになります。
- マニフェストの項目名の書き間違いは、厳密モードの検査で見つかります。
maxSurgeをmaxSurgeeと書いたファイルを検査すると、次のメッセージが出ました。
ERROR bad.yaml did not validate for resource deployment/web against version 1.36: spec.strategy.rollingUpdate: Additional properties are not allowed ('maxSurgee' was unexpected)
- 列名を直接変えると、旧版の SQL は
column "tel" does not existで止まります。 列を足すだけなら旧版の SQL はそのまま動くので、最初の一歩は必ず「追加」にします。
よくある質問
Q. ブルーグリーンデプロイとカナリアリリースの違いは? A. 切り替え方が違います。ブルーグリーンは全リクエストを一度に新版へ切り替え、カナリアは一部のリクエストから段階的に新版へ移します。切り戻しはどちらも振り分けを戻すだけですが、ブルーグリーンは2倍の台数、カナリアは新旧を見比べる監視が必要です。
Q. ローリングアップデートとブルーグリーンの違いは? A. 追加の台数と切り戻しの速さが違います。ローリングは少ない追加台数で順に入れ替え、戻すときももう一度ローリングします。ブルーグリーンは同じ台数をもう1組用意し、戻すときは振り分け先を変えるだけです。
Q. デプロイとリリースの違いは? A. デプロイは新版を稼働環境に置くこと、リリースは利用者が使える状態にすることです。ブルーグリーン・カナリア・機能フラグは、この2つを別の操作に分けられます。
Q. カナリアリリースで切り戻しできないときは? A. まず、データベースの変更が旧版と合わなくなっていないかを確かめます。列の削除や列名の変更を新版のデプロイと同時に行うと、旧版が動かなくなります。変更を追加→移行→削除に分け、削除は切り戻しの期限のあとに回します。
Q. どの方式から始めればよいですか? A. Kubernetes を使っているなら、既定のローリングから始められます。切り戻しの時間が課題になったらブルーグリーン、影響範囲を絞りたくなったらカナリアを検討します。
まとめ
- デプロイ方式は、一括・ローリング・ブルーグリーン・カナリアの4つと、機能フラグの併用で整理できます。
- 比べる軸は、必要台数・停止時間・切り戻し手順・新旧混在の4つです。
- 切り戻しの速さならブルーグリーン、影響範囲を絞るならカナリア、追加台数を抑えるならローリングを選びます。
- デプロイ(置く)とリリース(見せる)を分けると、公開の判断と切り戻しがしやすくなります。
- 新旧が同時に動く間の DB 変更は、追加→移行→削除の順に分けます。 削除は切り戻しの期限のあとです。
- 切り戻す基準は、デプロイの前に数値で書いておきます。
参考・出典
- Kubernetes Documentation「Deployments」 https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
- Kubernetes Documentation「Managing Workloads」(Canary deployments) https://kubernetes.io/docs/concepts/workloads/management/
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「デプロイ方式の種類と違い|ブルーグリーン・カナリア・ローリング比較」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。