LoginSignup
26
23

More than 3 years have passed since last update.

KubernetesでPodをローリングアップデートをする

Last updated at Posted at 2019-06-20

概要

このページでは、Podのローリングアップデートの方法について説明する。
ダウンタイムについても解説する。

目次

ローリングアップデートの方法

Deploymentを利用している場合、PodのDockerイメージのversionを上げてapplyするだけで、ローリングアップデートが実行される。

ハンズオン

Deploymentを定義

以下のようにDeploymentのDockerイメージのversionを上げる。

deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-dep
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-dep 
  # このPodTemlateの部分に変更があったときに、ローリングアップデートが実行される
  template:
    metadata:
      labels:
        app: hello-dep
    spec:
      containers:
-     - image: gcr.io/google-samples/hello-app:1.0
+     - image: gcr.io/google-samples/hello-app:2.0
        imagePullPolicy: Always
        name: hello-dep
        ports:
          - containerPort: 8080

ローリングアップデート前のPodの状態を確認

以下2つが現在稼働しているPodである。

$ sudo kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
hello-dep-5ddf884dd9-nt22p   1/1     Running   0          16s
hello-dep-5ddf884dd9-wm6c9   1/1     Running   0          16s

Deploymentをapply

Dockerイメージのversionを更新したdeployment.ymlをapplyする。

$ sudo kubectl apply -f deployment.yml

ローリングアップデート開始

applyしたことにより、ローリングアップデートか開始される。
以下コマンドでPodの状態がリアルタイムで確認できる。

$ sudo kubectl get pod -w
NAME                         READY   STATUS    RESTARTS   AGE
# 旧Pod
hello-dep-5ddf884dd9-nt22p   1/1     Running   0          20s
hello-dep-5ddf884dd9-wm6c9   1/1     Running   0          20s
# 新Pod1を起動開始
hello-dep-6595cc66c4-kcd8r   0/1     Pending   0          0s
hello-dep-6595cc66c4-kcd8r   0/1     Pending   0          0s
hello-dep-6595cc66c4-kcd8r   0/1     ContainerCreating   0          0s
# 新Pod1がRunning状態になった
hello-dep-6595cc66c4-kcd8r   1/1     Running             0          2s
# 旧Pod1を破棄開始
hello-dep-5ddf884dd9-nt22p   1/1     Terminating         0          30s
# 新Pod2を起動開始
hello-dep-6595cc66c4-wcc7q   0/1     Pending             0          0s
hello-dep-6595cc66c4-wcc7q   0/1     Pending             0          0s
hello-dep-6595cc66c4-wcc7q   0/1     ContainerCreating   0          0s
# 旧Pod2を破棄開始
hello-dep-5ddf884dd9-nt22p   0/1     Terminating         0          31s
# 新Pod2がRunning状態になった
hello-dep-6595cc66c4-wcc7q   1/1     Running             0          2s
# 旧Pod1,2が破棄される
hello-dep-5ddf884dd9-wm6c9   1/1     Terminating         0          32s
hello-dep-5ddf884dd9-nt22p   0/1     Terminating         0          32s
hello-dep-5ddf884dd9-nt22p   0/1     Terminating         0          32s
hello-dep-5ddf884dd9-wm6c9   0/1     Terminating         0          33s
hello-dep-5ddf884dd9-wm6c9   0/1     Terminating         0          34s
hello-dep-5ddf884dd9-wm6c9   0/1     Terminating         0          34s

ローリングアップデート後のPodの状態を確認

Podが新しいものに置き換わっており(NAMEが、アップデート前のものとは違う)Runningになっている。

$ sudo kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
hello-dep-6595cc66c4-kcd8r   1/1     Running   0          19s
hello-dep-6595cc66c4-wcc7q   1/1     Running   0          17s

ローリングアップデートの手順としては、以上となる。
しかし、この方法ではダウンタイムが発生する可能性がある。

ダウンタイムについて

K8sは、旧versionのPodを破棄し、新versionのPodを起動するという形でローリングアップデートを実現するが、この間に微妙なダウンタイムが発生する可能性がある。
何故このような現象が起きるかというと、k8sは新versionのPodが起動したことまでは検知するが、Running状態になったことを検知しない。

つまり、新Podが起動した時点で旧Podはすぐに破棄されてしまうため、新PodがRunning状態になるまでの間、ダウンタイムが発生する可能性がある。

と、以下に書いてあった。
Enable Rolling updates in Kubernetes with Zero downtime

Once you apply this or edit this, notice that there maybe a little downtime on your application because the old pods are getting terminated and the new ones are getting created.

This happens because kubernetes doesn’t know when your new pod is ready to start accepting requests, so as soon as your new pod gets created, the old pod is terminated without waiting...

対策

ヘルスチェックを入れることで、ダウンタイムが発生しないようにする。
readinessProbeは、サービスがリクエストを受け付けられる状態かどうかを確認する。

以下の説明が詳しい。
https://www.ianlewis.org/jp/kubernetes-health-check

readinessProbeが失敗した場合、そのパッドがサービスのエンドポイントから外される。そうすると、Kubernetesのサービスディスカバリー機能でトラフィックを受けられないポッドにトラフィックを転送しない。例えば、ローリングアップデートの時や、スケールアップした時、新しいポッドが機能されていたんだけど、まだトラフィック受けられないタイミングでリクエストが来たら、困るので、readinessProbeでそういうことを防ぐ。

また合わせて、RollingUpdate時の設定も追加した。

deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-dep
  namespace: default
spec:
  replicas: 2
+ # RollingUpdate時の設定
+ strategy:
+   # Recreate or RollingUpdate
+   type: RollingUpdate
+   rollingUpdate:
+     # アップデート時に許容する最大pod数 = replicas+maxSurge
+     # 今回の場合はreplicas(2)+maxSurge(1)なので最大Pod数が3になる。
+     maxSurge: 1
+     # アップデート時に許容する一度にunavailableになるPodの数
+     maxUnavailable: 25%
  selector:
    matchLabels:
      app: hello-dep
  # このPodTemlateの部分に変更があったときに、ローリングアップデートが実行される
  template:
    metadata:
      labels:
        app: hello-dep
    spec:
      containers:
      - image: gcr.io/google-samples/hello-app:2.0
        imagePullPolicy: Always
        name: hello-dep
        ports:
          - containerPort: 8080
+       # ヘルスチェックの設定
+       readinessProbe:
+         # ヘルスチェックでアクセスするhttpエンドポイントの情報を書く。
+         httpGet:
+           path: /
+           port: 8080
+         # コンテナが起動してからヘルスチェックを始めるまでの秒数。Default: 0
+         initialDelaySeconds: 5
+         # ヘルスチェックのタイムアウト秒数。最小で1秒。Default: 1
+         timeoutSeconds: 1
+         # ヘルスチェックの間隔。最小で1秒。Default: 10
+         periodSeconds: 5
+         # Failure状態の時、何回成功したらSuccessになるか。最小で1回。Default: 1
+         successThreshold: 1

ローリングアップデート前のPodの状態を確認

$ sudo kubectl get pod
NAME                             READY   STATUS    RESTARTS   AGE
hello-dep-6ff6ff4cbf-j9pw9   1/1     Running   0          23s
hello-dep-6ff6ff4cbf-zgh5t   1/1     Running   0          23s

Deploymentをapply

$ sudo kubectl apply -f deployment.yml
deployment.apps/hello-dep created

ローリングアップデート開始

$ sudo kubectl get pod -w
NAME                         READY   STATUS    RESTARTS   AGE
# 旧Pod
hello-dep-6ff6ff4cbf-j9pw9   1/1     Running   0          38s
hello-dep-6ff6ff4cbf-zgh5t   1/1     Running   0          38s
# 新Pod1を起動開始
hello-dep-bb849d7c6-j9dqs    0/1     Pending   0          0s
hello-dep-bb849d7c6-j9dqs    0/1     Pending   0          0s
hello-dep-bb849d7c6-j9dqs    0/1     ContainerCreating   0          0s
hello-dep-bb849d7c6-j9dqs    0/1     Running             0          2s
# 新Pod1がRunning状態 & READY1/1になった
hello-dep-bb849d7c6-j9dqs    1/1     Running             0          10s
# 旧Pod1を破棄開始
hello-dep-6ff6ff4cbf-zgh5t   1/1     Terminating         0          64s
# 新Pod2を起動開始
hello-dep-bb849d7c6-wsnhf    0/1     Pending             0          0s
hello-dep-bb849d7c6-wsnhf    0/1     Pending             0          0s
hello-dep-bb849d7c6-wsnhf    0/1     ContainerCreating   0          0s
# 旧Pod2を破棄開始
hello-dep-6ff6ff4cbf-zgh5t   0/1     Terminating         0          64s
hello-dep-6ff6ff4cbf-zgh5t   0/1     Terminating         0          65s
hello-dep-6ff6ff4cbf-zgh5t   0/1     Terminating         0          65s
hello-dep-bb849d7c6-wsnhf    0/1     Running             0          1s
# 新Pod2がRunning状態 & READY1/1になった
hello-dep-bb849d7c6-wsnhf    1/1     Running             0          7s
# 旧Pod1,2を破棄
hello-dep-6ff6ff4cbf-j9pw9   1/1     Terminating         0          71s
hello-dep-6ff6ff4cbf-j9pw9   0/1     Terminating         0          72s
hello-dep-6ff6ff4cbf-j9pw9   0/1     Terminating         0          73s
hello-dep-6ff6ff4cbf-j9pw9   0/1     Terminating         0          73s

ローリングアップデート後のPodの状態を確認

Podが新しいものに置き換わっており(NAMEが、アップデート前のものとは違う)Runningになっている。

$ sudo kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
hello-dep-bb849d7c6-j9dqs   1/1     Running   0          25s
hello-dep-bb849d7c6-wsnhf   1/1     Running   0          15s

参考

26
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
23