Kubernetes勉強会第5回 〜node affinity, pod affinity、Init containers、lifecycle hooks〜

Kubernetes in Action

Kubernetes in Action

「Kubernetes in Action」を読んで学んだ結果を社内で共有しました。 その第5回の内容です。

node affinity, pod affinity

Kubernetesのnode affinity, pod affinityについて

Summry

  • もしnodeにtaintsをセットすると、podがそのtaintsを許容できるtolerationsをセットしていない限りそのnodeにそのpodはscheduleされない。
  • taintsは3タイプあり、NoScheduleは完璧にscheduleされない。 PreferNoScheduleはそこまで厳密ではない。NoExecuteはnode上の実行中のpodであっても追い出す。
  • NoExecute taintは、nodeがunreachableやunready状態になった場合podがどのくらいの時間schedulingされるのを待つか指定できる。
  • Node affinityはどのnodeにpodがscheduleされるべきか指定できる。
  • Pod affinityは同じaffinity ruleをもったpodが実行されているnodeにpodをscheduleすることができる
  • Pod anti-affinity はお互いのpodを避けさせることができる

Init containers

Init containersを使うと、Pod内のコンテナを起動する前に特定の順番で特定の処理を行うことができる。

https://qiita.com/tkusumi/items/f64fff37a724b86d9819#init-containers-alpha

Pod内で初期化処理をするコンテナを指定をできる機能です。Podの定義にinitContainersという項目で、従来のcontainersで指定したコンテナの前に起動するコンテナを指定できるようになるようです。複数のコンテナを指定することができますが、containersがパラレルに起動されるのに対してinitContainersは指定した順番に1つずつ起動していくようです。

使用用途としては例えば以下のようなものが挙げられます。

  • データを動的にダウンロードしてくる
  • データベーススキーマの反映
  • アプリケーションが何らかの事前条件を満たすまでウェイトする

Init containersを使えば事前条件が満たされるまでpodのmainコンテナが起動するのを遅らせることができます。 readiness probesを設定するのを忘れてはいけません。 アプリケーションがまだ準備段階ではない場合にserviceにpodが追加されるのを防ぐことができますし、 Deployment controllerが、bad versionをrolloutするのを防ぐためにも使用されます。

もしInit Containerの実行がエラーになった場合、KubernetesはInit Containerの実行が成功するまでpodを再起動します。 しかしもしrestartPolicyNeverに設定していたなら再起動しません。

例:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

参考: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

lifecycle hooks

podのlifecycleに以下の2つのhookを定義することができる。これらをlifecycle hooksと呼ぶ。

  • Post-start hooks
  • Pre-stop hooks

pod全体に設定するinit containersと違って、lifecycle hooksはpodのコンテナごとに設定できる。 lifecycle hooksはcontainerがstartするときとstopするときに実行される。

lifecycle hooksは、以下の点でlivenes、 readiness probesと似ている。

  • containerの内部で実行されるコマンド
  • URLに対してHTTP GET Requestとして実行される

Post-start hooks

Post-start hookはコンテナのmain processが実行された後すぐに実行される。 もしコンテナのアプリケーションとは別のアプリケーションを動かしたい場合、あなたがそのアプリケーションの開発者ならアプリケーション内で別のアプリケーションを動かすことができるが、アプリケーションの開発者ではない場合、post-start hookは役に立つ。 Post-start hookはmain processと平行して実行されるが、以下の点でcontainerに影響を与える まずPost-start hookの実行が完了するまで、containerのstateWaitingのままでありreasonContainerCreatingのまま。そのためpodのstatusはRunningではなくPendingのまま。 もしPost-start hookが実行に失敗したりnon-zero exit statusを返した場合、main containerはkillされる。

以下が定義例。

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-poststart-hook
spec:
  containers:
  - image: luksa/kubia
    name: kubia
    lifecycle:
      postStart:
        exec
          command:
          - sh
          - -c
          - "echo 'hook will fail with exit code 15'; sleep 5; exit 15"

hookによって開始されたprocessが標準出力に出力してもそれをみるすべはない。そのため永続的volumeに書き込むこと。

Pre-stop hooks

Pre-stop hooksはコンテナが終了する前にすぐに呼び出される。つまりコンテナが終了するのをブロッキングする。 なのでコンテナを削除する呼び出しが送られる前にPre-stop hooksは終了しなければならない。 またPre-stop hooksには何のパラメーターも渡されない。 Podの終了時の振る舞いの詳細はTermination of Podsを参照すること。

Pre-stop hooksの実行タイミング等は以下の記事がとても詳しいです。 Kubernetes: 詳解 Pods の終了

以下が定義例。コンテナが終了する前に http://POD_IP:8080/shutdown へリクエストが送信される。

apiVersion: v1
kind: Pod
metadata:
  name: pre-stop-hook-httpget-pod
spec:
  containers:
  - image: luksa/kubia
    name: kubia
    lifecycle:
       preStop:
         httpGet:
            port: 8080
            path: shutdown

また以下のように定義すると、shellコマンドが実行される。

apiVersion: v1
kind: Pod
metadata:
  name: pre-stop-hook-shell-pod
spec:
  containers:
  - image: luksa/kubia
    name: kubia
    lifecycle:
       preStop:
         exec:
           command: ["sh", "-c", "sleep 1; nginx -s quit; sleep 5"]

参考: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/