GKEのノードプールを利用したKubernetesのアップグレード

**Google Cloud Platform(2) Advent Calendar 2016** 2日目
[**CyberAgent Developers Advent Calendar 2016**] (http://www.adventar.org/calendars/1620) 19日目
を担当する[strsk](https://twitter.com/strsk)です。

**Google Cloud Platform(2) Advent Calendar 2016** 1日目は、前職でほぼ仕事的に絡みのなかった、僕の師匠とも言える[kumanoryo](https://twitter.com/ryok0607)さんのゲロ吐くほど丁寧な記事ではじまったアドベントカレンダーですが、2日目はカジュアルにGKEのノードプールを利用したKubernetesのアップグレード手順についてお話します。

# gcloudコマンドでのアップグレード

アップグレード方法はいくつかありますが、稼働中でなければ以下のコマンドを打つだけです。

```
$ gcloud container clusters upgrade CLUSTER_NAME
```

gcloudコマンドでアップグレードした場合は、ノードのインスタンスが1台ずつ削除されアップグレードされます。ただし一度始めると中断できなかったり終了するPodなどをコントロールできないため、稼働中のクラスターで実行するのは危険です。

# ノードプールを利用したアップグレード

そこで、GKEのノードプールを利用してアップグレードを行います。この方法であれば、移行後のPodの動作確認や切り戻しが容易にできるので安全にアップグレードできます。

## アップグレード手順

### ノードプールの確認

```
$ gcloud container node-pools list --cluster=hoge --zone=asia-east1-a
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
default-pool  n1-standard-1  100           1.2.4
```

### ノードプール作成

```
$ gcloud container node-pools create v145 --cluster=hoge --machine-type=n1-standard-1 --disk-size=100 --num-nodes=1 --zone=asia-east1-a
Creating node pool v145...done.
Created [https://container.googleapis.com/v1/projects/hogehoge/zones/asia-east1-a/clusters/hoge/nodePools/v145].
NAME  MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
v145  n1-standard-1  100           1.4.5
```

これで新しいバージョンのノードプールが作成されました。

```
$ gcloud container node-pools list --cluster=hoge --zone=asia-east1-a
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
default-pool  n1-standard-1  100           1.2.4
v145          n1-standard-1  100           1.4.5

$ kubectl get no
NAME                          STATUS    AGE
gke-hoge-65141ecf-node-0ajo   Ready     30d
gke-hoge-v145-632da77c-kkzf   Ready     1m
```

#### 追記（12/19）

GKEクラスターをHTTP Load Balancerに紐付けている場合は、以下の設定も変えてから作業を行いましょう。

- GCE Instance groupsのPort name mapping
- HTTP Load BalancerのBackend serviceで設定しているInstance group

### Podのスケジューリング停止

次に、Podを移行する前にdefault-poolへのPodのスケジューリングを停止します。`kubectl cordon`コマンドでノードを指定するとステータスが`SchedulingDisabled`になり新規のPodは配置されなくなります。既に起動しているPodには影響ありません。

```
$ kubectl cordon hoge-65141ecf-node-0ajo
node "gke-hoge-65141ecf-node-0ajo" cordoned

$ kubectl get node
NAME                          STATUS                     AGE
gke-hoge-65141ecf-node-0ajo   Ready,SchedulingDisabled   30d
gke-hoge-v145-632da77c-kkzf   Ready                      1m
```

### Podの再配置

試しにPodを1台だけdeleteしてみます。

```
$ kubectl delete po fugapod-fclfa
pod "fugapod-fclfa" deleted

$ kubectl get po -o wide |grep fugapod
fugapod-fclfa             1/1       Terminating         0          8h        10.178.15.5     gke-hoge-65141ecf-node-0ajo
fugapod-vpqeh             0/1       ContainerCreating   0          2s        <none>          gke-hoge-v145-632da77c-bro2
fugapod-zwhn7             1/1       Running             0          8h        10.178.20.5     gke-hoge-65141ecf-node-0ajo
```

新しいノードに再作成されています。

```
$ kubectl get po -o wide |grep fugapod
fugapod-vpqeh             1/1       Running   0          2s        10.178.63.3     gke-hoge-v145-632da77c-bro2
fugapod-zwhn7             1/1       Running   0          8h        10.178.20.5     gke-hoge-65141ecf-node-0ajo
```

### 動作確認

この状態でPodのログなどを確認して問題なければ全台新しいノードに移行させます。
[Kubetool](https://github.com/abema/kubetool)などで行うと便利です。

### 最後に

GKEクラスタのマスターは自動的にアップグレードされますが、クラスタノードとマイナーバージョンが3つ以上古くなると[正しく動作しなくなる可能性](https://cloud.google.com/container-engine/docs/clusters/upgrade)があります。また、Kubernetesは開発が早くリリースが頻繁です。安全にアップグレードし、便利に使っていきましょう！メリークリスマス！！