Kubernetes の Deployment のローリングアップデートが起こる条件と設定についてのメモです。Deployment のローリングアップデート自体の仕組みについては Kubernetes: Deployment の仕組み にまとめています。
Deployment のローリングアップデートが起きる条件
Deployment のローリングアップデートは Deployment の Pod Template (.spec.template
) という Pod のテンプレート情報に変更があったときにのみ行われます。例えば Deployment のアノテーション(.metadata.annotations
) を変更してもローリングアップデートは起きませんが、Pod Template のアノテーション(.spec.template.metadata.annotations
) を更新するとローリングアップデートが実行されます。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
run: myapp
name: myapp
spec:
replicas: 1
selector:
matchLabels:
run: myapp
# この部分が PodTemlate。ここに変更があったときローリングアップデートが起こる
template:
metadata:
labels:
run: myapp
spec:
containers:
- image: nginx:1.13
name: myapp
手動のローリングアップデート
Deployment の PodTemlate の値を書き換えることで Pod のイメージの変更なしにローリングアップデートを手動で行うことができます。Pod を再起動させたいときに便利です。変更は Pod Template のどの値でも良いですが、アノテーション(.spec.template.metadata.annotations
)が一番影響が少ないと思われます。下記のように kubectl patch
コマンドで書き換えることができます。
# dummy-for-update というアノテーションに現在時刻を書き込んでローリングアップデートさせる
$ kubectl patch deployment $DEPLOYMENT_NAME \
-p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"dummy-for-update\":\"$(date +%s)\"}}}}}"
自分の所属している Z Lab ではforce-update-deploymentというスクリプトにして利用しています。
# kube-dns の kube-dns を再起動する
$ force-update-deployment kube-dns -n kube-system
deployment "kube-dns" patched
ローリングアップデート時の Pod 数の増減の設定
Deployment では下記の 2つのフィールドによってローリングアップデート時の Pod 数の増減を制御できます。manifest で指定した Deployment の apiVersion によってデフォルト値が異なるため注意が必要です。extensions/v1beta1
のデフォルトの挙動ではレプリカ数 (.spec.replicas
) が 1 の場合 ready 状態の Pod が 0 になるタイミングがありえます。
apiVersion に関わらずレプリカ数の値を 2 以上にしておけば多くの場合問題ないでしょう。
-
.spec.strategy.rollingUpdate.maxUnavailable
ローリングアップデート時に許容できる最大の unavailable になる Pod 数 (削除できる Pod 数)- apiVersion が
extensions/v1beta1
の場合デフォルトは1
- apiVersion が
apps/v1beta1
,apps/v1beta2
の場合デフォルトは25%
。端数は切り捨て
- apiVersion が
-
.spec.strategy.rollingUpdate.maxSurge
ローリングアップデート時に許容できる超過して作られる Pod の最大数- apiVersion が
extensions/v1beta1
の場合デフォルトは1
- apiVersion が
apps/v1beta1
,apps/v1beta2
の場合デフォルトは25%
。端数は切り上げ
- apiVersion が
apps/v1beta2
は kubernetes v1.8 からの apiVersion になります。
apiVersion が extensions/v1beta1
の場合
maxUnavailable, maxSurge ともに 1
がデフォルトのため、Pod を新しく作って そのready を待たず、すぐにPod を削除する挙動になります。レプリカ数が 1 の場合は一時的にどれも ready になっていない状態がありえます。 maxUnavailable を 0 に設定することで最低 1 pod は ready な状態を保つことができます。
$ kubectl get deploy mydep-ext -w
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
mydep-ext 1 1 1 1 3m # rolling-update 前
mydep-ext 1 1 0 1 3m # 今の Pod が up-to-date でなくなる
mydep-ext 1 2 1 1 3m # 新しいバージョンの Pod が作られる
mydep-ext 1 1 1 0 3m # ready を待たず古い Pod を削除
mydep-ext 1 1 1 1 3m # 新しいバージョンが ready になる
apiVersion が apps/v1beta1
の場合
maxUnavailable, maxSurge ともに 25%
がデフォルトになっており、maxUnavailable の方は端数は切り捨てられるので、レプリカ数が 1の場合、unavailable として許容する Pod数は 0 となります。Pod を新しく作り ready になるのを待ってから Pod を削除するため、レプリカ数が 1 であっても最低 1 Pod は ready な状態になります。
$ kubectl get deploy mydep-app -w
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
mydep-app 1 1 1 1 37s # rolling-update 前
mydep-app 1 1 0 1 37s # 今の Pod が up-to-date でなくなる
mydep-app 1 2 1 1 37s # 新しいバージョンの Pod が作られる
mydep-app 1 2 1 2 41s # ready を待つ
mydep-app 1 1 1 1 41s # 古い Pod を削除