Slide 1

Slide 1 text

Kubernetes上でアプリケーションを 運⽤するまでの道のり Mix Leep Study #32 / January 30, 2019 Shunya Murata @shmurata_

Slide 2

Slide 2 text

▶ アジェンダ 1. Kubernetes に向いたアプリケーションを作る・作り変える 2. アプリケーションをコンテナにする 3. Kubernetesにデプロイする 1. デプロイの⽅法 2. マニフェストの管理 4. 本番環境で動作させる 5. まとめ 2

Slide 3

Slide 3 text

Shunya Murata/ @shmurata_ ▶ ゼットラボ株式会社 ソフトウェアエンジニア ▶ 2010年にヤフー株式会社に新卒⼊社、2015年ゼットラボ株式会社に出向 3

Slide 4

Slide 4 text

Kubernetesに向いたアプリケーション を作る・作り変える

Slide 5

Slide 5 text

▶ Kuberneteに向いたアプリケーションとは ▶ Pod(コンテナ)は⼀時的なオブジェクトとして扱えるようにすべき + Pod はいつでも終了して別のNodeへ移動できるように作るべき ▶ 特定のノードに依存しない + IP アドレスなどのノード固有の情報に依存しない ▶ アプリケーション例 + The Twelve Factor App: https://12factor.net/ja/ 5 https://cdn.chrisshort.net/The-Illustrated-Childrens-Guide-to-Kubernetes.pdf

Slide 6

Slide 6 text

アプリケーションをコンテナにする

Slide 7

Slide 7 text

▶ Dockerfile のベストプラクティス ▶ コンテナはエフェメラルであるべき ▶ コンテナ毎に1つのプロセスだけ実⾏ ▶ 不要なパッケージのインストールは避ける + multi-stage build 7 https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

Slide 8

Slide 8 text

Kubernetesにデプロイする

Slide 9

Slide 9 text

▶ 宣⾔的なアプローチでデプロイしよう ▶ kubectl + 命令的なコマンド : kubectl run, kubectl create deployment + 命令的なオブジェクトの操作: kubectl create -f, kubectl replace -f + 宣⾔的なオブジェクトの操作: kubectl apply -f 9 https://kubernetes.io/docs/concepts/overview/object-management-kubectl/declarative-config/

Slide 10

Slide 10 text

10 https://twitter.com/jbeda/status/815298029452279808

Slide 11

Slide 11 text

11 https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/declarative-application-management.md

Slide 12

Slide 12 text

▶ 宣⾔的なアプローチのメリット ▶ This declarative approach is critical to the system’s self-healing, autonomic capabilities, and application updates. + セルフヒーリングや⾃⽴制御、更新しやすい ▶ Version control facilitates reproducibility, reversibility, and an audit trail. + 再現性、可逆性、監査 ▶ Version control enables the use of familiar tools and processes for change control, review, and conflict resolution. + 変更管理、レビュー、コンフリクトの解消が容易 12

Slide 13

Slide 13 text

▶ YAMLでデプロイしよう! ▶ 構成がシンプルになる ▶ Kubernetes API の変更に強い ▶ 既存のツールとの連携が容易 ▶ 抽象化されたDSLやGUIの使い⽅を覚えなくて良い + まだスタンダートとなるプロダクトがない + Kuberentes の標準オブジェクトの API はほぼ仕様が固まってきている + バージョン管理も明確に⾏われている ▶ YAMLにはKubernetesの考え⽅や仕組みが詰まっている + YAMLを覚えれば Kubernetes の理解が進む + 結局問題が起きると理解する必要が出てくる 13

Slide 14

Slide 14 text

apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx name: nginx spec: replicas: 1 selector: matchLabels: app: nginx strategy: {} template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx name: nginx resources: {} status: {} ▶ kubectl create deployment nginx --image=nginx -- dry-run -o yaml ▶ kubectl explain ▶ マニフェストを作成する 14

Slide 15

Slide 15 text

▶ マニフェストの管理 ▶ 環境別の設定 + kustomize: https://github.com/kubernetes-sigs/kustomize + helm: https://helm.sh/ + ksonnet: https://ksonnet.io/ ▶ SCM(バージョン管理システム)で管理 + GitOps: https://www.weave.works/blog/gitops-operations-by-pull-request + CI/CD パイプラインを作成して git の操作だけでオペレーションする 15

Slide 16

Slide 16 text

▶ kubectl apply -f ▶ 差分を検知して変更点を反映する + 差分の反映は単純な上書きではないので注意が必要 + applyで作成したオブジェクトはapply以外では変更しない ▶ 詳しくは 「Kubernetes: kubectl apply の動作」 @tkusumi + https://qiita.com/tkusumi/items/0bf5417c865ef716b221 16 https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands

Slide 17

Slide 17 text

本番環境で動作させる

Slide 18

Slide 18 text

apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx name: nginx spec: replicas: 1 selector: matchLabels: app: nginx strategy: {} template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx name: nginx resources: {} status: {} ▶ 本番環境で動作させるには設定が⾜りていない 18

Slide 19

Slide 19 text

▶ 本番環境で動作させるには? ▶ リソースを考慮したスケジュールを⾏えるようにする ▶ アプリケーションのハングアップを⾃動復旧する ▶ ゼロダウンタイムでアプリケーションを更新する ▶ クラスタのメンテナンスに対応する 19

Slide 20

Slide 20 text

▶ リソースを考慮したスケジュールを⾏えるようにする ▶ Kubernetesのリソース管理 + Podの要求したリソース量を利⽤できるNodeにスケジュールされる 20 Kubernetes スケジューラ Node: 32GB Pod: 16GB Node: 32GB Node: 32GB Pod: 16GB Pod: 16GB Pod: 16GB Pod: 16GB Pod: 16GB

Slide 21

Slide 21 text

▶ Pod が要求するリソース量を設定する必要がある ▶ Pod.spec.containers[].resource.requests + コンテナが最低限利⽤するリソース量 + 指定しないとリソース量が0でも構わないという意味になる + スケジューラはこの値をもとにPodをスケジュールする ▶ Pod.spec.containers[].resource.limis + コンテナが最⼤利⽤できるリソース量 + 指定しないと無制限に利⽤しても構わないという意味になる 21 https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

Slide 22

Slide 22 text

▶ アプリケーションのハングアップから⾃動復旧する ▶ アプリケーションは様々な要因でハングアップする + リソースリーク、デッドロック ▶ Pod.spec.containers[].livenessProbe + コンテナの状態を監視する + httpGet, tcpSocket, exec + 監視の結果ダウンしていると判断したらコンテナを再起動 22 https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/

Slide 23

Slide 23 text

▶ ゼロダウンタイムでアプリケーションを更新する ▶ Deploymentのローリングアップデート + ゼロダウンタイムでReplicaSet(Pod)を更新するオブジェクト ▶ ゼロダウンタイムにするには仕組みを理解して適切に設定する必要がある + GracefulShutdown + ReadinessProbe + Serviceのロードバランス先の更新 23

Slide 24

Slide 24 text

▶ GracefulShutdown ▶ アプリケーション⾃体をグレースフルにシャットダウンできるようにする + SIGTERMシグナルまたはpreStopフックを受けてから短時間 (TerminationGracePeriodSeconds)に終了する必要がある ▶ Pod.spec.containers[]. lifecycle.preStop + Podの終了時に実⾏したいコマンドを実⾏することができる + SIGTERMでは終了処理を実現できない場合などに利⽤できる 24 https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/

Slide 25

Slide 25 text

▶ ReadinessProbe ▶ Pod.spec.containers[].ReadinessProbe + リクエストを受け付けられる(Readiness)状態であるかを監視する + httpGet, tcpSocket, exec + Readiness な状態と判断したら Service からリクエストが送られるようになる 25 https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/

Slide 26

Slide 26 text

▶ Serviceの更新 ▶ Serviceのロードバランス先の更新 + 終了中または終了したPodへリクエストを送らないようにする + Kuberentesのコントローラが⾃動的に実施するが現時点では注意が必要 ▶ つぎの2つの処理は並列に実施されるため考慮が必要 + Podの終了 + Serviceのロードバランス先の更新 26

Slide 27

Slide 27 text

▶ Serviceの更新への対応 ▶ ワークアラウンドの対応 + preStopフックで Service の更新が終わるのを待つようにする + 終了中もリクエストを受け付けられるようにする 27

Slide 28

Slide 28 text

▶ Podの終了処理 ▶ ৄ͘͠͸ ʮKubernetes: ৄղ Pods ͷऴྃʯ@superbrothers + https://qiita.com/superbrothers/items/3ac78daba3560ea406b2 28

Slide 29

Slide 29 text

▶ クラスタのメンテナンスに対応する ▶ Kuberentesクラスタのメンテナンス + 全体を⽌めないように少しずつ停⽌して更新していく + kubectl drain node + 指定のNodeを unschedulable にして Pod を退去(evict)する ▶ 特定の Node に Pod が偏っていると意図しないレプリカ数に減る可能性がある + PodDisruptionBudget + 指定した条件を満たすように削除を待つ + 例: 最低1Pod動いていることを条件にする 29 https://kubernetes.io/docs/tasks/run-application/configure-pdb/

Slide 30

Slide 30 text

▶ PodDisruptionBudget未設定 30 Node a Pod(Running) Node b Pod(Running) kubectl drain node a Kubernetes evict

Slide 31

Slide 31 text

▶ PodDisruptionBudget未設定 31 Node a Node b Kubernetes Pod(Terminating) Pod(Terminating) ͢΂ͯͷ Pod ͕ఀࢭ͢ΔՄೳੑ͕͋Δ

Slide 32

Slide 32 text

▶ PodDisruptionBudget設定済み 32 Node a Pod(Running) Node b Pod(Running) kubectl drain node a Kubernetes evict PDB minAvailable: 1

Slide 33

Slide 33 text

▶ PodDisruptionBudget設定済み 33 Node a Pod(Running) Node b Kubernetes Pod(Terminating) PDBͷઃఆʹج͍ͮͯୀڈΛ଴ͭ PDB minAvailable: 1

Slide 34

Slide 34 text

Node b ▶ PodDisruptionBudget設定済み 34 Node a Pod(Running) Kubernetes Pod(Terminating) PDBͷઃఆʹج͍ͮͯୀڈΛ଴ͭ Pod(Terminated) PDB minAvailable: 1

Slide 35

Slide 35 text

▶ PodDisruptionBudget設定済み 35 Node a Node b Kubernetes αʔϏεΛఀࢭͤͣʹ҆શʹNodeΛఀࢭͰ͖Δ Pod(Running) Pod(Running) Pod(Terminated) PDB minAvailable: 1

Slide 36

Slide 36 text

まとめ

Slide 37

Slide 37 text

▶ まとめ ▶ Kubernetes でアプリケーションを運⽤するまでの道のり + マニフェストの管理 + 宣⾔的にシステムの状態をファイルで定義 + ファイルをバージョン管理 + 本番環境に必要な設定 + resource.request + ReadinessProbe/LivenessProbe + GracefulShutdown/preStop + PodDisruptionBudget 37

Slide 38

Slide 38 text

Fin.