GKE, Kubernetes, コンテナのローリングアップデート

## ローリングアップデート概要
サービスを止めることなくアップデートするために、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コントローラを使ったアプリのデプロイをしている場合、Deploymentｓへ乗り換えることを検討してもよい。なぜなら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を行う。

なおデプロイした定義ファイルはそれぞれ以下である。

```rc.yaml
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
```

```rc2.yaml
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が１つ作成されていることを確認できた。

```
$ 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つ削除し、新しいコンテナを１つデプロイしようとする。

```
$ 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分経つと、同様に古いコンテナを１つ落とし、新しいコンテナを１つ上げる。

```
$ 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
```

更に一分後、古いコンテナの最後の１つが削除されて、すべて新しいバージョンに置き換わったことを確認。

```
$ 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
```

今回の検証では本来４つのコンテナが常時起動してなければならないところ、5つのコンテナが動いていた。コンテナの起動が速く（だいたい3sec以内）、terminateが遅い（1m程度）かかってるので、ズレがでてるような感じを受けた。