ローリングアップデート概要
サービスを止めることなくアップデートするために、kubectlは"rolling update"機能を備えている。この機能は同時に全サービスを止めるのではなく、Podを1つずつアップデートしていく。
rolling updateの詳細については以下を参照。
https://github.com/kubernetes/kubernetes/blob/master/docs/design/simple-rolling-update.md
kubectlのrolling-updateはReplicationコントローラのみサポートしているが、Replicationコントローラを使ったアプリのデプロイをしている場合、Deploymentsへ乗り換えることを検討してもよい。なぜならDeploymentsは高レベルのコントローラで、rolling-updateの自動化を行うことができる。
ここではReplication Controllerを使った方法を記載する。
rolling updateはreplication controllerによって管理されているpodの構成を変更することができる。この変更は新しいreplication controller設定ファイルとして渡すことができる。イメージのアップデートだけなら、新しいコンテナイメージを直接指定してもよい。
Rolling updateは以下の振る舞いをする。
- 新しいReplication Controllerを作成
- 妥当なreplica数になるまで新旧それぞれのコントローラに対してreplica数の増減を行う
- オリジナルのReplication Controllerを削除
以下のコマンドを実行することでconfigファイルを使用してrolling updateを実施できる。
このときmetadata.nameの値は異なる値を指定し、spec.sectorフィールドの共通ラベルは上書きし、metadata.namespaceは同じものを使用する必要がある。
$ kubectl rolling-update NAME -f FILE
イメージのアップデートだけなら以下のコマンドでも可能
$ kubectl rolling-update NAME [NEW_NAME] --image=IMAGE:TAG
ローリングアップデートの実行と考察
実行環境:GKE,kubernetesのバージョン:1.3.5
以下のコマンドを実行し、rolling-updateを行う。
なおデプロイした定義ファイルはそれぞれ以下である。
apiVersion: v1
kind: ReplicationController
metadata:
name: gcp-cost
spec:
replicas: 4
template:
metadata:
labels:
name: gcp-cost-pods
spec:
containers:
- name: gcp-cost-container
image: gcr.io/{PJ Name}/gcp-cost:0.11
apiVersion: v1
kind: ReplicationController
metadata:
name: gcp-cost2
spec:
replicas: 4
template:
metadata:
labels:
name: gcp-cost-pods2
spec:
containers:
- name: gcp-cost-container
image: gcr.io/{PJ Name}/gcp-cost:0.12
$ kubectl rolling-update gcp-cost -f rc2.yaml
Created gcp-cost2
Scaling up gcp-cost2 from 0 to 4, scaling down gcp-cost from 4 to 0 (keep 4 pods available, don't exceed 5 pods)
Scaling gcp-cost2 up to 1
Scaling gcp-cost down to 3
Scaling gcp-cost2 up to 2
Scaling gcp-cost down to 2
Scaling gcp-cost2 up to 3
Scaling gcp-cost down to 1
Scaling gcp-cost2 up to 4
Scaling gcp-cost down to 0
Update succeeded. Deleting gcp-cost
replicationcontroller "gcp-cost" rolling updated to "gcp-cost2"
コマンド実行中に下記コマンドでPodのステータスを確認。
コマンド実行前の状態は以下のとおり4つコンテナが起動。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-0ui0d 1/1 Running 0 3s
gcp-cost-jlslu 1/1 Running 0 3s
gcp-cost-msy6u 1/1 Running 0 3s
gcp-cost-txmkr 1/1 Running 0 3s
$ kubectl get rc
NAME DESIRED CURRENT AGE
gcp-cost 4 4 25s
rolling-updateコマンド実行直後にpodの状態を確認すると以下のようにgcp-cost2が1つ作成されていることを確認できた。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-0ui0d 1/1 Running 0 3m
gcp-cost-jlslu 1/1 Running 0 3m
gcp-cost-msy6u 1/1 Running 0 3m
gcp-cost-txmkr 1/1 Running 0 3m
gcp-cost2-g80sp 1/1 Running 0 4s
1分経つと古いバージョンのコンテナを1つ削除し、新しいコンテナを1つデプロイしようとする。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-0ui0d 1/1 Running 0 4m
gcp-cost-jlslu 1/1 Running 0 4m
gcp-cost-msy6u 1/1 Terminating 0 4m
gcp-cost-txmkr 1/1 Running 0 4m
gcp-cost2-g80sp 1/1 Running 0 1m
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-0ui0d 1/1 Running 0 4m
gcp-cost-jlslu 1/1 Running 0 4m
gcp-cost-msy6u 1/1 Terminating 0 4m
gcp-cost-txmkr 1/1 Running 0 4m
gcp-cost2-g80sp 1/1 Running 0 1m
gcp-cost2-hctq1 0/1 ContainerCreating 0 1s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-0ui0d 1/1 Running 0 5m
gcp-cost-jlslu 1/1 Running 0 5m
gcp-cost-txmkr 1/1 Running 0 5m
gcp-cost2-g80sp 1/1 Running 0 2m
gcp-cost2-hctq1 1/1 Running 0 54s
新しいコンテナが作成されて1分経つと、同様に古いコンテナを1つ落とし、新しいコンテナを1つ上げる。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-0ui0d 1/1 Terminating 0 5m
gcp-cost-jlslu 1/1 Running 0 5m
gcp-cost-txmkr 1/1 Running 0 5m
gcp-cost2-g80sp 1/1 Running 0 2m
gcp-cost2-hctq1 1/1 Running 0 1m
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-0ui0d 1/1 Terminating 0 5m
gcp-cost-jlslu 1/1 Running 0 5m
gcp-cost-txmkr 1/1 Running 0 5m
gcp-cost2-g80sp 1/1 Running 0 2m
gcp-cost2-hctq1 1/1 Running 0 1m
gcp-cost2-wl1xd 0/1 ContainerCreating 0 1s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-jlslu 1/1 Running 0 6m
gcp-cost-txmkr 1/1 Running 0 6m
gcp-cost2-g80sp 1/1 Running 0 2m
gcp-cost2-hctq1 1/1 Running 0 1m
gcp-cost2-wl1xd 1/1 Running 0 35s
さらに一分経つと同様の処理を実施。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-jlslu 1/1 Terminating 0 6m
gcp-cost-txmkr 1/1 Running 0 6m
gcp-cost2-g80sp 1/1 Running 0 3m
gcp-cost2-hctq1 1/1 Running 0 2m
gcp-cost2-wl1xd 1/1 Running 0 1m
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-jlslu 1/1 Terminating 0 7m
gcp-cost-txmkr 1/1 Running 0 7m
gcp-cost2-747ev 0/1 ContainerCreating 0 0s
gcp-cost2-g80sp 1/1 Running 0 3m
gcp-cost2-hctq1 1/1 Running 0 2m
gcp-cost2-wl1xd 1/1 Running 0 1m
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-txmkr 1/1 Running 0 7m
gcp-cost2-747ev 1/1 Running 0 40s
gcp-cost2-g80sp 1/1 Running 0 4m
gcp-cost2-hctq1 1/1 Running 0 3m
gcp-cost2-wl1xd 1/1 Running 0 1m
更に一分後、古いコンテナの最後の1つが削除されて、すべて新しいバージョンに置き換わったことを確認。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost-txmkr 1/1 Terminating 0 8m
gcp-cost2-747ev 1/1 Running 0 1m
gcp-cost2-g80sp 1/1 Running 0 4m
gcp-cost2-hctq1 1/1 Running 0 3m
gcp-cost2-wl1xd 1/1 Running 0 2m
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gcp-cost2-747ev 1/1 Running 0 14m
gcp-cost2-g80sp 1/1 Running 0 17m
gcp-cost2-hctq1 1/1 Running 0 16m
gcp-cost2-wl1xd 1/1 Running 0 15m
今回の検証では本来4つのコンテナが常時起動してなければならないところ、5つのコンテナが動いていた。コンテナの起動が速く(だいたい3sec以内)、terminateが遅い(1m程度)かかってるので、ズレがでてるような感じを受けた。