Slide 1

Slide 1 text

Cloud Native Developers JP Kubernetesマニアック @hhiroshell 1

Slide 2

Slide 2 text

Cloud Native Developers JP お品書き • Podの配置を制御する • Kubernetesの拡張 2

Slide 3

Slide 3 text

Cloud Native Developers JP Podの配置を制御する 3

Slide 4

Slide 4 text

Cloud Native Developers JP Podの配置を制御するために使われる機能 機能 どんなもの? nodeSelector Nodeにあらかじめ設定されたLabelを使って、 Podの配置先を制御する Node Affinity nodeSelectorと同様の役割だが、より多機能な 制御が可能 Pod Affinity Nodeで稼働中のPodにもとづいて、新たなPod の配置先を制御する TaintとToleration Nodeに条件を設定して、特定の条件を満たした Podだけがスケジュールされるようにする 4

Slide 5

Slide 5 text

Cloud Native Developers JP nodeSelector 5

Slide 6

Slide 6 text

Cloud Native Developers JP nodeSelector • Nodeにあらかじめ所定のLabelを設 定しておく • Pod側でnodeSelector要素を指定し、 条件にマッチするNodeから配置先 が選択される 6 apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd

Slide 7

Slide 7 text

Cloud Native Developers JP build-in node Lables • 利用者が追加しなくても、Nodeに設定されているLabelもある – kubernetes.io/hostname – beta.kubernetes.io/instance-type – beta.kubernetes.io/os – beta.kubernetes.io/arch – failure-domain.beta.kubernetes.io/zone – failure-domain.beta.kubernetes.io/region 7 マネージド・サービスを利用する場合に 通常設定されているもの ZoneやRegionを分けてPodを分散配置 したい場合に利用する

Slide 8

Slide 8 text

Cloud Native Developers JP Node Affinity / Pod Affinity 8

Slide 9

Slide 9 text

Cloud Native Developers JP Affinityとanti-Affinity • Podが配置されるNodeを制御するという意味では、nodeSelectorと 同様の役割 • nodeSelectorと比較して – 表現力が高い(ANDやマッチングだけではない) – 設定された条件を満たさなくても妥協的に残Nodeに配置することができる – すでに可動しているPodのLabelを条件に使える(同居させたい/させたくな いPodを指定可能) • 提供する機能に応じていくつか種類がある – node affinity – inter-pod affinity/anti-affinity 9

Slide 10

Slide 10 text

Cloud Native Developers JP Node Affinity (beta feature) • Node Affinityを設定するために、2種類のエントリーが利用可能 • requiredDuringSchedulingIgnoredDuringExecution – Podのスケジューリング時にチェックする条件 – 条件を満たすNodeがない場合はスケジューリングされない(required) • preferredDuringSchedulingIgnoredDuringExecution – Podのスケジューリング時にチェックする条件(同じく) – 条件を満たすNodeがあればそれに従い、ない場合もどこかに配置される (preferred) 10

Slide 11

Slide 11 text

Cloud Native Developers JP 設定例 • この例では – kube…/e2e-az-name が”e2e-az1”または”e2e-az2” のNodeを要求 – another…-keyがanother…- valueのNodeに余剰があれば それに配置 • Nodeが満たす条件の weightの合計が高いほど、 そのNodeに配置され易い • operator: – In, NotIn, Exists, DoesNotExist, Gt, Lt – 複数のValueを組み合わせた 条件を設定 11 apiVersion: v1 kind: Pod … spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/e2e-az-name operator: In values: - e2e-az1 - e2e-az2 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value

Slide 12

Slide 12 text

Cloud Native Developers JP Inter-pod affinityとanti-affinity (beta feature) • すでに可動しているPodにもとづいて、新しいPodを配置する条件を 指定 • nodeAffinityと同様の文法で条件を記述 – requiredDuringSchedulingIgnoredDuringExecution →条件を満たさなければPodはスケジュールされない – preferredDuringSchedulingIgnoredDuringExecution →条件を満たすPodがなくともスケジュールされうる • topologyKeyによって、配置先のZoneやNodeを更に絞る • namespaceを指定して、配置先namespaceを絞る事もできる 12

Slide 13

Slide 13 text

Cloud Native Developers JP Inter-pod affinityとanti-affinityの利用例 • Redisクラスターとクライアント – Redisキャッシュのコンテナを Nodeをまたいで分散配置 – Redisのクライアントアプリを 各Redisコンテナと同じNode に配置 • manifestの例はこちらに – https://kubernetes.io/docs/conce pts/configuration/assign-pod- node/#more-practical-use-cases 13 Redis Redis Redis App App App

Slide 14

Slide 14 text

Cloud Native Developers JP 設定例 • この例では – securityがS1のPodが配置 されているNodeと同じ ZoneのNodeを要求 – securityがS2のPodが配置 されているNodeへのスケ ジュールは避けようとする • operatorで使えるもの は: – In, NotIn, Exists, DoesNotExist 14 apiVersion: v1 kind: Pod … spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - S1 topologyKey: failure-domain.beta.kubernetes.io/zone podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: security operator: In values: - S2 topologyKey: kubernetes.io/hostname

Slide 15

Slide 15 text

Cloud Native Developers JP topologyKeyには制約がいろいろある • podAffinityとpodAntiAffinityでは、 requiredDuringSchedulingIgnoredDuringExecutionを使う場合は topologyKeyが必須 • podAntiAffinityにrequiredDuringSchedulingIgnoredDuringExecutionを組 み合わせる場合、kubernets.io/hostnameのtopologyKeyはadmission controllerにより無効化される。この条件を使いたい場合はadmission controllerを無効にする必要がある • podAntiAffinityにpreferredDuringSchedulingIgnoredDuringExecutionを 組み合わせる場合で、topologyKeyを省略すると”全てのトポロジーを許 可”として解釈される • 上述の条件を除けば、topologyKeyには任意のLabelのKeyを設定できる 15

Slide 16

Slide 16 text

Cloud Native Developers JP TaintとToleration 16

Slide 17

Slide 17 text

Cloud Native Developers JP TaintsとTolerations • Taint: 汚点、汚染 → Nodeに設定 • Toleration: 忍耐、容認 → Podに設定 • Nodeに条件を設定して、特定の条件を満たしたPodだけがスケ ジュールされるようにする 17 Node gpu=true: NoSchedule GPUが使いたいPod以外はスケジュールするなー OK! NG! Pod Pod gpu=true operator: Equal (Tolerationなし)

Slide 18

Slide 18 text

Cloud Native Developers JP TaintsとTolerations • Taintsはkubectlから設定 • TorerationはPodのmanifestに記述 – 上記のTaintsにマッチする(スケジュールされる)例 18 tolerations: - key: "key" value: “value” operator: "Equal" effect: "NoSchedule" tolerations: - key: "key" operator: "Exists" effect: "NoSchedule" $ kubectl taint nodes node1 key=value:NoSchedule ↑一致するkeyのTaintがあればマッチ ↑keyとvalueが一致するTaintがあればマッチ

Slide 19

Slide 19 text

Cloud Native Developers JP TaintsとTolerations その他のルール • keyが設定されない場合、Existsオペレーターが全てのキーにマッチ する • effectが設定されない場合、keyが一致すれば全てマッチする 19 tolerations: - operator: "Exists" tolerations: - key: "key" operator: "Exists"

Slide 20

Slide 20 text

Cloud Native Developers JP TaintsとTolerations – Effectに設定できる値 • NoSchedule: – TaintにマッチしないPodは配置しない • PreferNoSchedule: – TaintもマッチしないPodのスケジュールを避けようとするが、他にNodeがな い場合にはスケジュールされる場合もある • NoExecute: – Taintを設定したときすでに稼働中のPodに対しても効果が及ぶ – すでに可動中のPodでこのTaintにTolerationがマッチしない場合、Podから排 除され、それ以降スケジュールされない – tolerationsSecondsを指定することで、そのPodが排除されるまでの猶予時間 を指定できる 20

Slide 21

Slide 21 text

Cloud Native Developers JP TaintsとTolerations – 使用例 • Dedicated Nodes – 特定の範囲のユーザーだけにNodeを使わせたいケース – 管理者の作業は目的のNodeにTaintを設定するだけでよい。マッチする Tolerationを設定していないPodを全て乗らないようにできる • Node with Special Hardware – GPUのような特殊なHWを積んだNodeを、それを必要としないPodに使わせ ないようにするケース – PodはHWの利用を明示的に宣言(Tolerationを設定)することで、それを利 用するということを明確にさせる 21

Slide 22

Slide 22 text

Cloud Native Developers JP Kubernetesの拡張 22

Slide 23

Slide 23 text

Cloud Native Developers JP Kubernetesの拡張ポイント • Custom ResourceとKubernetes APIの拡張 • インフラの拡張 – Device Plugins – Network Plugins • Container Runtime Interface 23

Slide 24

Slide 24 text

Cloud Native Developers JP Custom ResourceとKubernetes APIの拡張 24

Slide 25

Slide 25 text

Cloud Native Developers JP その前に…PodとController • ほとんどのケースでは、DeploymentなどのControllerオブジェクト を作成することにより、結果的にPodが作成される – 例: Deploymentを作成してからPodが作成されるまで 25 Deployment Controller Deployment ReplicaSet Deployment Controller ReplicaSet Object/Resource Controller Watch Create Watch Create Create kubectl

Slide 26

Slide 26 text

Cloud Native Developers JP PodとControllerとController Manager • 目的のユースケースに合わせて、Podをよしなに制御してくれるの が標準Controller • Deployment, ReplicaSetなどの標準Controllerを動かしているデーモ ンプロセスがcontroller-manager • Custom Controller – Controllerは所定のオブジェクト/リソースの状態をウォッチして、必要に応 じて更新処理を走らせるプロセス – このように動くものは自分でも作れるし、クラスターにデプロイすることも できる→Custom Controller 26

Slide 27

Slide 27 text

Cloud Native Developers JP Custom ResourceとKubernetes APIの拡張 • Kubernetesに独自のリソース(Custom Object)を追加して利用する 拡張方法 • 以下の3つの実装をセットにして、機能が成立 – Kubernetes APIの拡張: Custom Objectを操作可能なAPIの追加 – Custom Objectの作成: 拡張されたAPIを利用してリソースを作成 – Custom Controllerの作成: Custom Objectの登録を受けて実行する処理の実装 27 Custom Controller Custom Object Object/Resource Controller Watch Update 拡張された Kubernets API Create

Slide 28

Slide 28 text

Cloud Native Developers JP Kubernetes APIの拡張 • Kubernetes APIを拡張する(≒Custom Objectを取り扱えるように する)2通りの方法 1. CustomResourceDefinition(CRD) • 利用者が追加作成できるリソース・タイプの定義 • CRDリソースをAPI Serverに登録することで、Custom Objectを取り扱えるようになる • v1.7まで使えたThirdPartyResourceの後継 2. Aggregation Layerの追加 • APIServiceオブジェクトを追加することで、標準のAPI Serverとは独立したAPI機能 (extension api-server)をクラスター内に立てる • Kubernetes APIの所定のPathにアクセスすると、extension api-serverにリクエストがプロ キシされる 28

Slide 29

Slide 29 text

Cloud Native Developers JP CRDによるAPIの拡張 • CRDを登録すればOK – これをkubectl create –fで 登録するとAPI Serverの所定 のパスでこのリソースを操作 できる – /apis/stable.example.com/v 1/namespaces/*/crontabs/. .. – kubectlでも操作できる(次 ページ) 29 apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: crontabs.stable.example.com spec: group: stable.example.com version: v1 scope: Namespaced names: # plural name used in the URL: /apis/// plural: crontabs # singular name to be used as an alias on the CLI and for display singular: crontab # kind is normally the CamelCased singular type kind: CronTab # shortNames to match your resource on the CLI shortNames: - ct

Slide 30

Slide 30 text

Cloud Native Developers JP Custom Objectの作成 • Custom Objectを追加する – 右例のようなmanifestを作成して kubectl create -f 30 apiVersion: "stable.example.com/v1" kind: CronTab metadata: name: my-new-cron-object spec: cronSpec: "* * * * */5" image: my-awesome-cron-image

Slide 31

Slide 31 text

Cloud Native Developers JP Custom Controllerの作成 – 1. client-goの生成 • 全て自力で実装することも不可能ではないと思われるが、クライア ントライブラリ(client-go)の生成ツールがある – https://github.com/kubernetes/code-generator – Custom Objectの型定義とAPIのメタ情報をgoで記述して、ツールにかませる と、Custom Controllerで利用可能なクライアントライブラリが生成される 31

Slide 32

Slide 32 text

Cloud Native Developers JP Custom Controllerの作成 – 2. Controllerの実装 • client-goを使って Custom Controllerを 実装する – サンプルがあるのでそれを 参考に頑張る…。 https://github.com/kubernetes/kubernetes/tre e/master/staging/src/k8s.io/sample-controller 32 client-goが やってくれるところ controllerとして 実装するところ https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/sampl e-controller/docs/controller-client-go.md

Slide 33

Slide 33 text

Cloud Native Developers JP Custom Controllerの作成 – 3. Controllerのデプロイ • もちろんコンテナ化してデプロイします。 – コンテナ化してレジストリにプッシュ – DeploymentオブジェクトでControllerのコンテナイメージを指定やればよい 33

Slide 34

Slide 34 text

Cloud Native Developers JP Custom Controller関連の参考リンク • Custom Controllerの作成は情報がまとまっていないのが辛い • 以下参考にできるリンク – 「KubernetesのCRD(Custom Resource Definition)とカスタムコントローラーの作 成」 • https://qiita.com/__Attsun__/items/785008ef970ad82c679c – 公式のsample-controller実装: • https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/sample- controller – クライアントライブラリ生成ツール: • https://github.com/kubernetes/code-generator – CRD周りの公式ドキュメント: • https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource- definitions/ 34

Slide 35

Slide 35 text

Cloud Native Developers JP インフラの拡張 35

Slide 36

Slide 36 text

Cloud Native Developers JP Infrastructureの拡張 – Device Plugin • Nodeに実装された特殊なデバイスを利用するためのプラグインの仕 組み – 例えば、NVIDIA製GPUをコンテナから利用して機械学習を行うなど • 利用のするまでの流れ 1. デバイスプラグイン本体の準備→デバイスベンダーからの情報に従う • e.g. NVIDIAのGPUのドキュメント: https://github.com/NVIDIA/k8s-device-plugin 2. kubeletのDevice Pluginサポートを有効化 • kubeletの設定ファイル /etc/systemd/system/kubelet.service.d/10-kubeadm.conf に以下の環境オプショ ンを設定→kubeletを再起動 – Environment="KUBELET_EXTRA_ARGS=--feature-gates=DevicePlugins=true“ 3. Podでデバイスの利用を宣言 36

Slide 37

Slide 37 text

Cloud Native Developers JP GPUを利用するPodの例 • resource limits/requestを 設定することで、所望のデ バイスのリソースを利用す ることを宣言 37 apiVersion: v1 kind: Pod metadata: name: gpu-pod spec: containers: - name: cuda-container image: nvidia/cuda:9.0-devel resources: limits: nvidia.com/gpu: 2 # requesting 2 GPUs - name: digits-container image: nvidia/digits:6.0 resources: limits: nvidia.com/gpu: 2 # requesting 2 GPUs

Slide 38

Slide 38 text

Cloud Native Developers JP Infrastructureの拡張 – Network Plugin(alpha) • KubernetesはOverlay Networkに相当する部分をプラグインするこ とができ、CNI, kubenetの2方式がある 38 Node Pod Container eth0: 10.100.0.2 docker0: 1.0.1.1 veth0: 1.0.1.2 Node Pod Container eth0: 10.100.0.3 docker0: 1.0.2.1 veth0: 1.0.2.2 この辺の構成は Kubernetesのプロセスが やってくれる Overlay Network / ここをプラグイン的に別実装に変えられる

Slide 39

Slide 39 text

Cloud Native Developers JP Network Plugin - CNI • CNCFのプロジェクトとして仕様策定が行われている – https://github.com/containernetworking/cni/blob/master/SPEC.md#netwo rk-configuration • KubernetesはCNIの各種実装をOverlay Networkにプラグインでき る – Calico, Weave … 39

Slide 40

Slide 40 text

Cloud Native Developers JP CNIの導入方法 • CNIを使うために必要な作業 – CNIの設定ファイルを作成してNodeに配置 – プラグイン本体のバイナリを用意してNodeに配置 – kubelet の起動時に以下のオプションを指定 • --network-plugin=cni • --cni-conf-dir=[CNIの設定ファイルのパス] • --cni-bin-dir=[プラグイン本体のバイナリのパス] • 詳しくは公式を – https://github.com/containernetworking/cni/blob/master/SPEC.md#netwo rk-configuration 40

Slide 41

Slide 41 text

Cloud Native Developers JP Network Plugin - kubenet • kubenet – クラウドプロバイダーのネットワークインフラに実装されたノード間ルー ティングと組み合わせて利用することを想定しているプラグイン – GKEなどでクラスターを作成すると自動で構成される – 内部にCNIのインタフェースを使っている部分もあるらしい… 41

Slide 42

Slide 42 text

Cloud Native Developers JP Container Runtime Interface (CRI) 42

Slide 43

Slide 43 text

Cloud Native Developers JP Container Runtime Interface(CRI) • Kubernetes Container Runtime Interface(CRI) – KubeletからPodおよび Containerを操作するため の共通インターフェース – CRIに対応した実装の例 • cri-o, rktlet, Frakti, Docker CRI shim • cri-oはOCI標準に準拠し たランタイムを実行する 仕組み 43 CRIのインターフェース OCI標準準拠のランタイムを実行

Slide 44

Slide 44 text

Cloud Native Developers JP Open Container Initiatives(OCI) • OCI – CNCFに属する下位組織(?) – コンテナランタイムの標準仕様を策定している • OCIの標準仕様 – runtime-spec / image-spec で構成 – コンテナの配布プロトコルの標準化も始めている • OCIのスペックに準拠したコンテナ・ランタイムの例 – runC(リファレンス実装), containerd, railcar 44

Slide 45

Slide 45 text

Cloud Native Developers JP oci-oの利用方法 • 具体的な手順はこちら – https://adtech.cyberagent.io/techblog/archives/4036 – (渋谷方面に足を向けて寝られない) 45

Slide 46

Slide 46 text

Cloud Native Developers JP Fin. 46

Slide 47

Slide 47 text

Cloud Native Developers JP やりきれなかったところ • スケジューリングの制御周りはまだいろいろあります – Custom Schedulers • スケジューラーを独自実装して利用する機能 • デフォルトのスケジューラーと併せて、複数のCustom Schedulerを同時に利用可能 – Disruptions / Pod Disruption Budget – Taint based Evictions – Taint Nodes by Condition – Pod Priority and Preemption • オートスケーリングも大事 – Horizontal Pod Autoscaler – Cluster Autoscaling 47 • ストレージもプラグインできます – Storage Plugins