KubernetesのDaemonsetでRollbackをしてみる


# はじめに

kubernetes 1.7 で DaemonSet の Rollback が Deployment のようにできるようになっていました。
試してみたのでまとめてみます。やっていることは[この記事](http://blog.kubernetes.io/2017/09/kubernetes-statefulsets-daemonsets.html
)の後半をなぞっています。

# 準備

## Kubernetes Cluster

Kubernetes の環境を準備します。今回は3 NodeのGKE上の1.8で試しています。


## DaemonSet

DaemonSet で動かす image として`node-exporter`を使ってみます。何でも良いです。

```yaml:node-exporter-v0.13.yml
apiVersion: apps/v1beta2
kind: DaemonSet
metadata:
  name: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  minReadySeconds: 5
  template:
    metadata:
      name: node-exporter
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - image: prom/node-exporter:v0.14.0
        imagePullPolicy: IfNotPresent
        name: node-exporter
        ports:
          - containerPort: 9100
            hostPort: 9100
            name: scrape
```


# 実行

では実際に動かしてみます。

## 起動

DaemonSetを作成してみます。`kubectl apply` で作成します。


```shell-session
$ kubectl apply -f node-exporter-v0.14.yml --record
daemonset "node-exporter" created
```

作成された内容も確認してみます。


```shell-session
$ kubectl get ds
NAME            DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE-SELECTOR   AGE
node-exporter   3         3         3         3            3           <none>          25s
$ kubectl get po
NAME               READY     STATUS    RESTARTS   AGE
NAME                  READY     STATUS    RESTARTS   AGE
node-exporter-8zbkw   1/1       Running   0          45s
node-exporter-bvtsg   1/1       Running   0          45s
node-exporter-frlhj   1/1       Running   0          45s
```

3 Node 全てで問題なく Pod が起動しています。

## 更新

続いて image の更新をします。`kubectl patch` で node-exporter の image を v0.15.0 にします。

```shell-session
$ kubectl patch ds node-exporter -p'{"spec":{"template":{"spec":{"containers":[{"name":"node-exporter","image":"prom/node-exporter:v0.15.0"}]}}}}'
daemonset "node-exporter" patched
```

もしくは以下のように`kubectl set image` でもできます。

```
$ kubectl set image ds/node-exporter node-exporter=prom/node-exporter:v0.15.0
daemonset "node-exporter" image updated
```

状態を確認します。

```shell-session
$ kubectl rollout status ds/node-exporter
Waiting for rollout to finish: 1 out of 3 new pods have been updated...
Waiting for rollout to finish: 1 out of 3 new pods have been updated...
Waiting for rollout to finish: 1 out of 3 new pods have been updated...
Waiting for rollout to finish: 1 out of 3 new pods have been updated...
Waiting for rollout to finish: 2 out of 3 new pods have been updated...
Waiting for rollout to finish: 2 out of 3 new pods have been updated...
Waiting for rollout to finish: 2 out of 3 new pods have been updated...
Waiting for rollout to finish: 2 out of 3 new pods have been updated...
Waiting for rollout to finish: 2 of 3 updated pods are available...
Waiting for rollout to finish: 2 of 3 updated pods are available...
daemon set "node-exporter" successfully rolled out
$ kubectl get ds -o wide
NAME            DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE-SELECTOR   AGE       CONTAINER(S)    IMAGE(S)                     SELECTOR
node-exporter   3         3         3         3            3           <none>          11m       node-exporter   prom/node-exporter:v0.15.0   app=node-exporter
$ kubectl get po 
NAME                  READY     STATUS    RESTARTS   AGE
node-exporter-5w6n6   1/1       Running   0          59s
node-exporter-hbh8f   1/1       Running   0          39s
node-exporter-njr9n   1/1       Running   0          30s
```

3 Pod とも更新されました。

## 履歴の確認

続いて DaemonSet の履歴を確認してみます。

```
$ kubectl rollout history ds/node-exporter
daemonsets "node-exporter"
REVISION        CHANGE-CAUSE
1               kubectl create --filename=node-exporter-v0.14.yml --record=true
2               kubectl create --filename=node-exporter-v0.14.yml --record=true
```

各 revision の内容も確認してみます。 image が更新されていることがわかります。

```
$ kubectl rollout history ds/node-exporter --revision=1
daemonsets "node-exporter" with revision #1
Pod Template:
  Labels:       app=node-exporter
  Containers:
   node-exporter:
    Image:      prom/node-exporter:v0.14.0
    Port:       9100/TCP
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>
$ kubectl rollout history ds/node-exporter --revision=2
daemonsets "node-exporter" with revision #2
Pod Template:
  Labels:       app=node-exporter
  Containers:
   node-exporter:
    Image:      prom/node-exporter:v0.15.0
    Port:       9100/TCP
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>

```

## rollback

`undo` してみます。image が v0.14.0 に戻ります。

```
$ kubectl rollout undo ds/node-exporter
daemonset "node-exporter" rolled back
$ kubectl get ds -o wide
NAME            DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE-SELECTOR   AGE       CONTAINER(S)    IMAGE(S)                     SELECTOR
node-exporter   3         3         3         1            2           <none>          9m        node-exporter   prom/node-exporter:v0.14.0   app=node-exporter
$ daemonsets "node-exporter"
REVISION        CHANGE-CAUSE
2               kubectl create --context=gke_imposing-pager-91704_asia-northeast1-b_haruna-test --filename=node-exporter-v0.14.yml --record=true
3               kubectl create --context=gke_imposing-pager-91704_asia-northeast1-b_haruna-test --filename=node-exporter-v0.14.yml --record=true
$ kubectl rollout history ds/node-exporter --revision=3
daemonsets "node-exporter" with revision #3
Pod Template:
  Labels:       app=node-exporter
  Containers:
   node-exporter:
    Image:      prom/node-exporter:v0.14.0
    Port:       9100/TCP
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>

```

`undo` した結果 revision 3 が v0.14.0 になりました。`--to-revision` を指定することで任意の revision へ戻すことができます。


# まとめ

`kubectl rollout` で DaemonsetのRollbackをしました。 最初に書きましたが、Deployment でももちろん同じように対応することができます。