KubernetesでDaemonSetのRolling Updateする


# はじめに

kubernetes 1.6 で DaemonSet へのRolling Updateができるようになっていました。
1.5までだと、DaemonSetのイメージを更新したい時などで`kubectl apply`で一発更新できず、`kubectl delete ds`とかでDaemonSetを一旦作り直す運用などをしてました。いまさら感もありますが書きかけだったので投稿してみます。



# 準備

## Kubernetes Cluster

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

## DaemonSet

例ではDaemonSetで動かすimageとして`docker-dd-agent`を使っています。`fluentd`でも`newrelic/infrastructure`でも`mackerel-agent`でも何でも良いです。

```yaml:dd-agent-11.0.5160-ds.yml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: dd-agent
spec:
  selector:
    matchLabels:
      app: dd-agent
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  minReadySeconds: 5
  template:
    metadata:
      name: dd-agent
      labels:
        app: dd-agent
    spec:
      hostNetwork: true
      containers:
      - image: datadog/docker-dd-agent:11.0.5160-alpine
        imagePullPolicy: IfNotPresent
        name: dd-agent
        ports:
          - containerPort: 8125
            name: dogstatsdport
        env:
        - name: KUBERNETES
          value: "yes"
        - name: TAGS
          value: foo:bar
        envFrom:
        - SecretRef:
            name: dd-api-key
        volumeMounts:
          - name: dockersocket
            mountPath: /var/run/docker.sock
          - name: procdir
            mountPath: /host/proc
            readOnly: true
          - name: cgroups
            mountPath: /host/sys/fs/cgroup
            readOnly: true
      volumes:
        - hostPath:
            path: /var/run/docker.sock
          name: dockersocket
        - hostPath:
            path: /proc
          name: procdir
        - hostPath:
            path: /sys/fs/cgroup
          name: cgroups
```

```yaml:dd-agent-sercet.yml
apiVersion: v1
kind: Secret
metadata: {
  name: dd-api-key
}
type: Opaque
data: {
  API_KEY: <base64でエンコードした api key>
}
```

`spec.updateStrategy`と`sepc.minReadySeconds` の部分がrolling updateで使われる設定部分です。`type: RollingUpdate` でRollingUpdateの設定をして、`maxUnavailable` でUpdate中に利用不能になる最大Pod数を定義します。数字が小さいとNode数が多いときはupdateに時間がかかるかもしれません。ここは、Deploymentと同じですね。`minReadySeconds`はPodが正常に起動したと判断する秒数を遅らせます。


# 実行

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

## 起動

Secretを作成してからDaemonSetを作成してみます。kubectl applyで作成します。

```shell-session
$ kubectl apply -f dd-agent-sercet.yml
$ kubectl apply -f dd-agent-11.0.5160-ds.yml
```

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

```shell-session
$ kubectl get secret
NAME                  TYPE                                  DATA      AGE
dd-api-key            Opaque                                1         43s
$ kubectl get ds
NAME       DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE-SELECTOR   AGE
dd-agent   5         5         0         5            0           <none>          12s
$ kubectl get po
NAME               READY     STATUS    RESTARTS   AGE
dd-agent-79l4p     1/1       Running   0          27s
dd-agent-b4n3t     1/1       Running   0          27s
dd-agent-h83g1     1/1       Running   0          27s
dd-agent-st4g1     1/1       Running   0          27s
dd-agent-vhr3j     1/1       Running   0          27s
```

## 更新

続いてimageの更新をします。dd-agentのimageを12.3.5172-alpineにしてみます。

```shell-session
$ kubectl patch ds dd-agent -p'{"spec":{"template":{"spec":{"containers":[{"name":"dd-agent","image":"datadog/docker-dd-agent:12.3.5172-alpine"}]}}}}'
daemonset "dd-agent" patched
```

もしくは、上記ymlのimageの部分を書き換えた下記ymlを流します。

```yaml:dd-agent-12.3.5172-ds.yml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: dd-agent
spec:
  selector:
    matchLabels:
      app: dd-agent
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  minReadySeconds: 5
  template:
    metadata:
      name: dd-agent
      labels:
        app: dd-agent
    spec:
      hostNetwork: true
      containers:
      - image: datadog/docker-dd-agent:12.3.5172-alpine
        imagePullPolicy: IfNotPresent
        name: dd-agent
        ports:
          - containerPort: 8125
            name: dogstatsdport
        env:
        - name: KUBERNETES
          value: "yes"
        - name: TAGS
          value: foo:bar
        envFrom:
        - SecretRef:
            name: dd-api-key
        volumeMounts:
          - name: dockersocket
            mountPath: /var/run/docker.sock
          - name: procdir
            mountPath: /host/proc
            readOnly: true
          - name: cgroups
            mountPath: /host/sys/fs/cgroup
            readOnly: true
      volumes:
        - hostPath:
            path: /var/run/docker.sock
          name: dockersocket
        - hostPath:
            path: /proc
          name: procdir
        - hostPath:
            path: /sys/fs/cgroup
          name: cgroups
```

```shell-session
$ kubectl apply -f dd-agent-12.3.5172-ds.yml
daemonset "dd-agent" configured
```

状態を確認してみます

```shell-session
$ kubectl rollout status ds/dd-agent
Waiting for rollout to finish: 1 out of 5 new pods have been updated...
Waiting for rollout to finish: 1 out of 5 new pods have been updated...
Waiting for rollout to finish: 2 out of 5 new pods have been updated...
Waiting for rollout to finish: 2 out of 5 new pods have been updated...
Waiting for rollout to finish: 2 out of 5 new pods have been updated...
Waiting for rollout to finish: 2 out of 5 new pods have been updated...
Waiting for rollout to finish: 3 out of 5 new pods have been updated...
Waiting for rollout to finish: 3 out of 5 new pods have been updated...
Waiting for rollout to finish: 3 out of 5 new pods have been updated...
Waiting for rollout to finish: 4 out of 5 new pods have been updated...
Waiting for rollout to finish: 4 out of 5 new pods have been updated...
Waiting for rollout to finish: 4 out of 5 new pods have been updated...
Waiting for rollout to finish: 4 out of 5 new pods have been updated...
Waiting for rollout to finish: 4 of 5 updated pods are available...
Waiting for rollout to finish: 4 of 5 updated pods are available...
daemon set "dd-agent" successfully rolled out
$ kubectl get po
NAME               READY     STATUS    RESTARTS   AGE
dd-agent-0t2cj     1/1       Running   0          1m
dd-agent-3tg81     1/1       Running   0          2m
dd-agent-8rd6t     1/1       Running   0          1m
dd-agent-t6xkt     1/1       Running   0          1m
dd-agent-znfkm     1/1       Running   0          2m
```

1podずつ更新されていることが確認できました。


# まとめ

DaemonSetのRolling Update機能を試してみました。`kubectl apply`による統一的な運用ができ、CI/CDの中でも使いやすくなったのでないかと思います。