- 作者: Marko Luksa
- 出版社/メーカー: Manning Publications
- 発売日: 2018/01/20
- メディア: ペーパーバック
- この商品を含むブログを見る
追記 2018/07/11
以下にまとめ直したのでこちらをご参照下さい。以下のリンク先のほうが詳しいです。
- Kubernetes勉強会第1回 〜Secrets、StatefulSet、DaemonSet、API server への接続方法〜
- Kubernetes勉強会第2回 〜RBAC、セキュリティを高める方法、PodSecurityPolicy、NetworkPolicy〜
- Kubernetes勉強会第3回 〜Resource RequestとResource Limit、pod QoSクラス、LimitRangeリソース、ResourceQuotaリソース〜
- Kubernetes勉強会第4回 〜cAdvisor、Heapster、podとnodeのauto scaling、taintsとtolerations〜
- Kubernetes勉強会第5回 〜node affinity, pod affinity、Init containers、lifecycle hooks〜
- Kubernetes勉強会第6回 〜Kubernetesの実行と管理、CustomResourceDefinitions(CRD)、Container Runtime Interface(CRI)〜
最近Kubernetesを触っていて、英語の勉強がてらこの「Kubernetes in Action」を読んだ。 (600ページもあって1日1時間読むようにしてたけど2ヶ月半くらいかかった。。) Kubernetesを知るためには非常に良い本で、Kubernetesの基礎からKubernetesの内部、セキュリティ周りまで丁寧に書かれていた。とてもおすすめです。
日本語に翻訳された本が出てほしいですね。
https://www.manning.com/books/kubernetes-in-action から1章と3章が無料でダウンロードできるので興味がある人は読んでみて下さい。
ということで、忘れないように重要な点を書き残しておく。
個人的な記録なので、日本語訳や内容が間違っている可能性があるので、ご注意下さい。
- 1〜6
- 7. ConfigMaps and Secrets: configuring applications
- 8. Accessing pod metadata and other resources from applications
- 10. StatefulSets: deploying replicated stateful application
- 11. Understanding Kubernetes internals
- 12. Securing the Kubernetes API serve
- 13. Securing cluster nodes and the network
- 14. Managing pods’ computational resources
- 14.3 pod QoSクラス
- 14.4 namespaceごとに、pod作成時にpodにデフォルトのresource requests/limitsを設定する
- 14.5 namespaceに対して使用可能リソース量を指定する
- 14.6 podリソースの使用量のモニタリング
- 14.7 Summary
- 15 podとnodeのauto scaling
- 15.1.4 Scaling based on other and custom metrics
- 15.1.5 どんなmetricsがautoscalingに適しているか判断する
- 15.2 Vertical pod autoscaling
- 15.3
- 15.3.3 cluster scale donw時にサービスの中断を抑える
- 15.4 Summary
- 16 Advanced scheduling
- 16.1.3 Adding tolerations to pods
- 16.2 Using node affinity to attract pods to certain nodes
- 16.3 pod affinity と pod anti-affinityを用いて一緒に配置する
- 16.3.4 Scheduling pods away from each other with pod anti-affinity
- 16.4 Summry
- 17.2.3 Starting pods in a specific order
- 17.2.4 Adding lifecycle hooks
- 17.3 Ensuring all client requests are handled properly
- 17.4 Making your apps easy to run and manage in Kubernetes
- 17.4.6 Handling application logs
- 17.6 Summary
- 18 Extending Kubernetes
- 18.1 Defining custom API objects
- 18.2 Introducing CustomResourceDefinitions
- 18.1.4 Providing a custom API server for your custom objects
- 18.2 Extending Kubernetes with the Kubernetes Service Catalog
- 18.2.2 Introducing the Service Catalog API server and Controller Manager
- 18.2.3 Introducing Service Brokers and the OpenServiceBroker API
- 18.2.4 Provisioning and using a service
- 18.4 Summary
- appendix A: Using kubectl with multiple clusters
- appendix B: Setting up a multi-node cluster with kubeadm
- appendix C: Using other container runtimes
- appendix D: Cluster Federation
1〜6
基本的なことだったので省略
7. ConfigMaps and Secrets: configuring applications
7.5 Using Secrets to pass sensitive data to containers
- 環境変数として渡せるし、ファイルとしてmountすることもできる。
- Secretはメモリ内に読み込まれる、ファイルには書き出されない。(volumeとしてmountするときはtmpfsに書かれる)
- ただしectdに保存されるときは平文で保存される(https://kubernetes.io/docs/concepts/configuration/secret/)
- By default, the default-token Secret is mounted into every container,
$ kc exec git-sync-demo-b9cb448f7-972rh ls /var/run/secrets/kubernetes.io/serviceaccount/ ca.crt namespace token
- Secretがbase64なのは、バイナリデータも含めることができるように。
- Secretのサイズ上限は1M
- private dockerレジストリからimageをpullする時の認証をsecretに登録するためには
$ kubectl create secret docker-registry mydockerhubsecret \ --docker-username=myusername --docker-password=mypassword \ --docker-email=my.email@provider.com
のようにしてsecret genericではなくsecret docker-registryを指定する。 podには以下のように imagePullSecrets を指定
apiVersion: v1 kind: Pod metadata: name: private-pod spec: imagePullSecrets: - name: mydockerhubsecret containers: - image: username/private:tag name: main
8. Accessing pod metadata and other resources from applications
8.2.2 Talking to the API server from within a pod
kc exec -it curl /bin/bash
でpodにログインし、
env | grep KUBERNETES_SERVICE # でkubernetes APIのIPとPORTがわかる。 export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) curl -H "Authorization: Bearer $TOKEN" https://kubernetes/api/v1/namespaces/default/pods curl -H "Authorization: Bearer $TOKEN" https://kubernetes/api/v1/namespaces/default/services/git-sync-demo
ちなみに、 /var/run/secrets/kubernetes.io/serviceaccount/namespace にnamespaceが書いてある。
Rubyのkubernetes API クライアントは https://github.com/abonas/kubeclient がある。
10. StatefulSets: deploying replicated stateful application
- 再作成されてもpod nameやhostnameは同じ名前で生成される。
- また同じPersistentVolumeClaimsを使おうとする。
- 作成されるときは、次の使われていないindexを使って作成される。
- 現在が2で3が使われている時、4が使われる。(3が使われているときってどんな時…)
- またpodが削除されるときは大きいindexから削除される。
- 削除されるときは使っていたPersistentVolumeClaimsは削除されない。
11. Understanding Kubernetes internals
- Kubernetes SystemコンポーネントだけがKubernetes API Serverと通信をする
- Kubernetes API serverのみがetcdと通信をする。他のコンポーネントは直接etcdと通信しない。
- ectdには楽観ロックで操作するので一貫性がとれる。
11.4.3 Introducing the Container Network Interface
コンテナが簡単にネットワークに接続できるようにContainer Network Interface (CNI)というプロジェクトがスタートした。 KubernetesはいくつかのCNI pluginを使うことができる。
- Calico
- Flannel
- Romana
- Weave Net
- And others
DaemonSetとして各Nodeにデプロイされる。
11.5.1 How services are implemente
serviceはiptables rulesを追加する。実態はiptables rule。(340ページの図 参照)
11.5.2 How kube-proxy uses iptables
Endpoint objectは後ろにserviceがある全てのpodのIP/portのペアを保持している。
12. Securing the Kubernetes API serve
12.1.3 Creating ServiceAccounts
- ServiceAccountsで使われているtokeは、JWT token
12.2.2 Introducing RBAC resources
Role
とClusterRole
は、どのリソースにどんな操作を許可するかを指定するものRoleBinding
とClusterRoleBinding
はどのRole
/ClusterRole
をどのユーザ/グループ/ServiceAcctount
に紐付けるかを定義するもの
RoleとClusterRoleの違い、RoleBindingとClusterRoleBindingの違いは、Role/RoleBindingは特定のnamespaceに属するが、ClusterRole/ClusterRoleBindingはnamespaceに属さない(cluster-lebel resource)
- 操作とは
- get, create, update, delete, list, watch, deletecollection がある。
- リソースとは
- これはkubernetesのリソース。pod, depoyment, service, secret etc..
例: service-reader.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: foo name: service-reader rules: - apiGroups: [""] verbs: ["get", "list"] resources: ["services"]
- ServiceAccountについて
- podはデフォルトではdefault ServiceAccountに紐づく。default ServiceAccountはnamespace作成時に作成される。
- 追加のServiceAccountを手動で作成することができ、podに紐付けることができる
(roleのbind先のUserやGroupって何を指すんだろう。。)
- adminという名前のclusterRoleは そのnamespece内のどんなリソースの操作もできる。ただしResourceQuotasとそのnamespaceリソースを除いて。
- clusterRolesのedit と admin の違いは、そのnamespaceの Roles and RoleBindingsを参照/変更できるかどうか。adminはできる。
もしminikube上でRBACを有効にしたい場合は、minikube起動時に、--extra-config=apiserver.Authorization.Mode=RBAC
を指定する必要がある。
13. Securing cluster nodes and the network
- podが自身のvirtualネットワークではなく、nodeのネットワークを使いたい場合、
hostNetwork
プロパティを設定すればOK。 - Kubernetes Control Plane components がpodとしてdeployされるとき、hostNetworkがONでデプロイされる。
- 同じようにnodeのportを使いたい場合は、hostPortを設定すればOK。
- しかしその場合、そのpodはnodeに1つしか配置できない。なぜなら同じportを複数のpodで使えないから。
- 同じように hostPID: true、 hostIPC: true もできる
- podのコンテナのプロセスの実行ユーザを限定する方法として、以下のようにユーザidを指定できる
apiVersion: v1 kind: Pod metadata: name: pod-as-user-guest spec: containers: - name: main image: alpine command: ["/bin/sleep", "999999"] securityContext: runAsUser: 405
- セキュリティをあげるための方法として以下がある
またlinuxのcapabilitiesをコンテナに指定することができる
13.3 Restricting the use of security-related features in pods
PodSecurityPolicyリソース
参考: https://docs.bitnami.com/kubernetes/how-to/secure-kubernetes-cluster-psp/ https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
PodSecurityPolicy とはクラスタ全体のセキュリティ上のポリシーを定義する機能です。ホストに影響を与える可能性がある 特権 (privileged) や HostIPC などの機能を制限し Pod に脆弱性があった場合にクラスタを守ることができます。
参考: Kubernetes: Pod Security Policy によるセキュリティの設定 https://qiita.com/tkusumi/items/6692af743ae03dc0fdcc
またRBACによって、ServiceAccountに紐付けることができる。
できること
- どのpodがホストのIPC, PID or Network namespaceを使用できるか
- どのホストポートをpodが使えるか
- どのユーザでコンテナのプロセスを動かすか
- privileged containeを持ったpodを作れるかどうか
- どの kernel capabilitieを許可するか、またデフォルトでどのkernel capabilitieを追加or削除するか
- どんな SELinuxLabelをコンテナが使うか
- コンテナがrootファイルシステムを書き込み許可するかどうか
- コンテナがどのfile system groupを実行できるか
- podがどのvolumeタイプを使用できるか
13.4 Isolating the pod network
もしnetworking pluginがサポートしていれば、NetworkPolicyリソースを作成することによって、 ネットワークの隔離をすることができる。 要はpod間の通信の制限ができる。 ingress and egress rulesと呼ばれる。Ingressリソースとは関係がない。 ingressはネットワークの流入、egressはネットワークの流出のルールを定義できる。
このpodはこのpodへしかリクエストを送れないor受け取れないとかこのportを使ってしかあのpodへリクエストを送れないor受け取れないとかが設定できる。 13.4.2 参照。 また特定のlabelがついたnamespace内のpodからリクエストを受け取らないということができる。 もしくはcidrを使ってリクエストを制限することもできる
13.5 Summary
- podは自分のではなくnodeの Linux namespacesを使うことができる
- コンテナはコンテナイメージで指定されたユーザとは別のユーザで実行するように設定することができる
- コンテナはprivileged modeで動かすことができる
- コンテナはプロセスがファイル書き込みをしないようにread onlyで動くように設定することができる(また特定のvolumeのみ書き込みが可能に設定できる)
- Cluster-levelリソースであるPodSecurityPolicyは、nodeの安全を脅かすpodの生成を防ぐことができる。
- PodSecurityPolicyはRBACのClusterRoleとClusterRoleBindingを使って特定のuserに紐付けることができる。
- NetworkPolicyリソースはpodのinbound/outbound trafficを制限することができる。
14. Managing pods’ computational resources
resource requests
podをデプロイする時に必要とするリソース(CPU/メモリ)を指定することができる。 もちろんそれ以上使うこともできる。(リソース使用量の制限はlimitを使う) またその指定したリソースがそのpod用に確保されるわけではない。 あくまでpodをデプロイ時にそのリソース量が空いているかをチェックするためのもの。 そのリソース量が空いていないnodeにはデプロイされない。
apiVersion: v1 kind: Pod metadata: name: requests-pod spec: containers: - image: busybox command: ["dd", "if=/dev/zero", "of=/dev/null"] name: main resources: requests: cpu: 200m memory: 10Mi
cpu 200m は200 millicoresの略で1000milli coreで1cpu。200 mill coreで 1/5 CPU使うということ。 10Miは 10 mebibytes 。
$ kubectl describe nodes Name: minikube ... Capacity: # nodeの使用可能リソース量 cpu: 2 memory: 2048484Ki pods: 110 Allocatable: #ここがresource requestsで指定した割当量 cpu: 2 memory: 1946084Ki pods: 110
ポイントとしては、podをデプロイするときに、nodeのリソース使用量は見ないで、resource requestsをみてデプロイが行われる。 なので、nodeのリソースが100%でも、resource requestsに空きがあればデプロイされる。
resource limits
apiVersion: v1 kind: Pod metadata: name: limited-pod spec: containers: - image: busybox command: ["dd", "if=/dev/zero", "of=/dev/null"] name: main resources: limits: # ここで制限を指定 cpu: 1 memory: 20Mi
上記のようにresource requestsを指定していなかったら、limit値と同様の値がresource requestsに設定される。 resource requestと違って、resource limitはnodeの使用可能リソース量を超えて指定ができる。 たとえばメモリが1Gのnodeがあって、pod Aのメモリrequestが500MBでlimitが800MB、pod Bのメモリrequestが500MBでlimitが500MBでもOK。 CPUも同様。
ちなみにそのnode上で使用可能なCPUリソース以上をpodたちが使用しようとした場合、 CPU速度が遅くなるだけで、問題が起きるわけではない。 しかしメモリの場合は違う。resource limitで指定した以上のメモリをpodたちが使用しようとした場合、 コンテナはOOM killされる。 もしpodのrestart policyがAlways or OnFailureが設定されていた場合、podのコンテナは自動的に再起動される。なのでkillされたことに気づかないかもしれない。 もし再度メモリオーバーになったら再度再起動されるが、再起動時間はexponential backoffアルゴリズムにしたがって段々遅くなる。 その場合、podのstatusはCrashLoopBackOffになる。 CrashLoopBackOffはkubeletが諦めたことをささない。少しずつ再起動期間は伸びるが最終的に5分間隔で再起動が繰り返されるようになる。 再起動回数はpodのRESTARTSに表示される。
14.3 pod QoSクラス
Kubernetesは3つのQuality of Service (QoS)クラスを提供する。Qosはpodに付与される。
- BestEffort (the lowest priority)
- Burstable
- Guaranteed (the highest)
QoS classはresource requestsとresource limitsの2つから決定される。
BestEffortが設定される条件
- pod内のどのコンテナにもresource requestsとlimitsが設定されていない
Guaranteed (the highest)が設定される条件
- CPUとメモリの両方に、resouce requestsとlimitsがセットされていること
- 上記がpod内のそれぞれのコンテナにセットされていること。
- resouce requestsとlimitsの値がそれぞれ同じであること。
Burstableが設定される条件
- BestEffortもGuaranteedも設定されていない場合
pod内に複数のコンテナが存在する場合、どうやってpodのQoSが決まるか。 まず各コンテナに上記のルールに従ってQoSを割り当てる。 全てのコンテナがBestEffortならpodのQoSはBestEffortになる。 全てのコンテナがGuaranteedならpodのQoSはGuaranteedになる。 それ以外の場合はpodのQoSはBestEffortになる。
podのQoSはkubectl describe pod -o yaml|json したときに、status.qosClass fieldに表示される。
nodeのメモリ上限に達した場合、どういった判断でプロセスがkillされるか
QoSに従ってどのコンテナがkillされるか決まる。 最初にkillされるのはBestEffort。つぎに、Burstable。最後にGuaranteed(ただしsystem processがメモリを必要とした場合のみkillされる)。
同じQoSクラスだった場合、どうやってどのコンテナがkillされるかを決めているか
どの実行中プロセスもOutOfMemory (OOM) scoreを持っている。 システムはOutOfMemory (OOM) scoreのよってどのプロセスをkillするかを比較して決めている。
14.4 namespaceごとに、pod作成時にpodにデフォルトのresource requests/limitsを設定する
LimitRangeリソース
LimitRangeリソースを定義すると、そのLimitRangeリソースが属しているnamespace内にpodを作成するときに、 LimitRangeリソースで指定したresource requestsとlimitsを設定することができる。
apiVersion: v1 kind: LimitRange metadata: name: example spec: limits: - type: Pod min: cpu: 50m memory: 5Mi max: cpu: 1 memory: 1Gi - type: Container defaultRequest: # resource requestsを設定していないコンテナはこのデフォルト値が設定される cpu: 100m memory: 10Mi default: # resource limitsが設定されていないコンテナはこのデフォルト値が設定される。 cpu: 200m memory: 100Mi min: # コンテナが設定できる最小のrequests/limits値 cpu: 50m memory: 5Mi max: # コンテナが設定できる最大のrequests/limits値 cpu: 1 memory: 1Gi maxLimitRequestRatio: # Maximum ratio between the limit and request for each resource cpu: 4 memory: 10 - type: PersistentVolumeClaim # PVCに対しても制限がかけられる min: storage: 1Gi max: storage: 10Gi
14.5 namespaceに対して使用可能リソース量を指定する
ResourceQuotaリソース
LimitRangeリソースはpodごとに適用される。 ResourceQuotaリソースはnamespaceに対して適用される。 制限できるのは、 CPU, メモリ、PersistentVolumeClaimのディスク使用量, podの数, 他のAPI objects users(?)が作成すること
apiVersion: v1 kind: ResourceQuota metadata: name: cpu-and-mem spec: hard: requests.cpu: 400m requests.memory: 200Mi limits.cpu: 600m limits.memory: 500Mi
ResourceQuotaリソースはそのnamespace内のpodのrequests/limitsのトータル値に対して制限がかかる。
kubectl describe quota で詳細がみれる。
14.6 podリソースの使用量のモニタリング
kubeletには内部にcAdvisorというものを持っている。 cAdvisorはnode自体のリソース使用量及びnode上で実行されているコンテナのリソース消費量のデータを収集する役割。 それらのデータをクラスタ全体で集約するために、Heapsterとよばれるコンポーネントがある。 Heapsterはnodeのうち1つのnode上でpodとして動作する。 Heapsterはserviceを通して公開される。
minikubeの場合は以下のコマンドでheapsterを有効にできる。 minikube addons enable heapster
heapsterが実行されていれば、 kubectl top node でその集約データ結果からnodeのリソース使用量がみれる。
$ kubectl top node NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% minikube 170m 8% 556Mi 27%
グラフィカルにリソースをモニタリングしたい場合、 GKEならGoogle Cloud Monitoringが使える。しかしminikubeやオンプレの場合は、 データの保存にInfluxDB, ビジュアリングにGrafanaが使える。
http://github.com/kubernetes/heapster/tree/master/deploy/kube-config/influxdb に従ってKubernetesクラスタにデプロイできる。 minikubeならHeapster add-onを有効にした時点でInfluxDBもGrafanaも有効になっている。 以下のように。
$ kubectl cluster-info ... monitoring-grafana is running at https://192.168.99.100:8443/api/v1/proxy/namespaces/kube- system/services/monitoring-grafana
14.7 Summary
- resource requestを指定することはpodをscheduleするときに役に立つ
- resource limitsを指定することはpodが他のpodのリソースを使い過ぎることを防ぐ
- 使われていないCPU時間はコンテナのrequestsに基づいて割り当てられる
- コンテナはCPUを使い過ぎても決してkillされないが、メモリを使い過ぎようとしたらkillされる。
- QoSと実際のメモリ使用量に基づいて、より重要なpodのために他のpodが消えるされることもある。
- LimitRangeを定義することによって、それぞれのpodに対して、resource requestsとlimitsの最小値,最大値, デフォルト値を設定することができる。
- ResourceQuotaを定義することによって、namespace内のpodのresourceの総量に対して最小, 最大を設定することができる。
- どのくらい高いpod resource requests/limitsを指定しているか知るために、長い間モニタリングをする必要があります。
15 podとnodeのauto scaling
podのスケールアウト(Horizontal pod autoscaling)とはpodの数を増やすこと HorizontalPodAutoscalerリソースを定義することで可能になる。
まずDeployment, ReplicaSet, ReplicationController, or StatefulSetはscaled resource objectと呼ばれる。 これらはauto scalingが可能なリソース。
autoscalingプロセスは以下の3つで行われる。
- scaled resource objectによって管理されている全てのpodのメトリックを取得する
- メトリックを定義されたターゲット値に近づけるためにはどのくらいのpodが必要か計算する
- scaled resourceのreplicas fieldを更新する。
メトリックはHorizontalPodAutoscalerリソースによって取得されるが、HorizontalPodAutoscalerリソースはHeapsterからメトリックを取得する。HeapsterはcAdvisorからメトリックを取得する。 そのためauto scalingにはHeapsterが起動していないといけない。
scaleoutのための計算方法は、 440のFigure 15.2 の図を参照 もしくは、 https://github.com/kubernetes/community/blob/master/contributors/design-proposals/autoscaling/horizontal-pod-autoscaler.md#autoscaling-algorithm を参照。
※ポイントとしては、auto scalingはtarget valueに近づくようにpod数が調整されるということ。 target valueが80なら 全体(全podの合計)のCPU使用率が80%になるように調整される。たとえば全体のCPU使用率が90%ならpod数は増えるし、50%ならpod数は減らされる。
HorizontalPodAutoscalerリソースには、autoscale条件と、最小/最大pod数の指定ができる。
重要な点は、定期的にメトリックの取得をしているため、すぐにはscalingが行われないということ。少し時間がかかる。 scale up(pod数を増やす)イベントは3分おきに発生する。 scale down(pod数を減らす)イベントは5分おきに発生する。
Memory-based autoscaling was introduced in Kubernetes version 1.8, and is configured exactly like CPU-based autoscaling. とあるが、ほんとか?
15.1.4 Scaling based on other and custom metrics
custom metricsを用いてauto scalingを行うことができる。 HPAには以下の3種類を指定することができる。
- Resource
- resource requests/limitsのようなresource metrics
- Pods
- custom metricsを含むpodに関係するmetrics。 例えばQueries Per Second (QPS) や message broker’s queueの数。
- Object
- podとは直接関係ないmetrics。たとえばIngressのlatency。
15.1.5 どんなmetricsがautoscalingに適しているか判断する
podのメモリ消費量はautoscaling metricsに向かない。 podが増えるほど全体のメモリ消費量は増え、使えるメモリ量が逆に減るからだ。 metricsの一つとして、Queries per Second (QPS)がある。 autoscaling metricsとしてcustom metricsを使う前に、podが増減したらそのmetricsがどのように振る舞うかよく考えること。
15.2 Vertical pod autoscaling
スケールアウトはサーバーの台数を増やすこと、スケールアップはサーバーのスペックを上げることだが、 podをスケールアップはまだサポートされていない。が、今後サポートされるであろう。 podのスケールアップというのは、podのresource requests or limitsを変更するということ。
15.3
Kubernetesは、cloud providerが提供していれば、nodeのauto scalingもでき、Cluster Autoscalerという機能が担っている。 Cluster Autoscalerは、リソースが枯渇して既存のnodeにpodがschedulingできない場合に、nodeを追加する。 またリソース負荷が低いならnodeの削除も行う。 Cluster Autoscalerはnodeを追加する前にそのnodeにpodがscheduleできるかを確認する。じゃないとnodeを追加してもpodがscheduleできない事態になってしまう。
nodeを削除するとき(scale downするとき)system podsが実行されているかチェックしされているならnodeの削除を行わない。ただしsystem podsがDaemonSetの場合を除く。DaemonSetは各nodeで実行されているためnodeからpodを削除しても問題ないため。 また unmanaged pod(replicasetやdeploymentによって管理されていないpod)やlocal strageを使っているpodが存在する場合もnodeを削除しない。 nodeを削除するさいには、nodeにunschedulableを設定する。これによりpodがscheduleされなくなる。 そしてnode上のpodが追い出される。 追い出されたpodはreplicasetやdeploymentの管理下なので他のnodeへ再scheduleされる。
tips
kubectl cordon <node>
でnodeにunschedulableを設定できる。
kubectl drain <node>
でnodeにunschedulableを設定し、node上のpodを追い出す。
kubectl uncordon <node>
を実行すればnodeのunschedulableを解除できる。
15.3.3 cluster scale donw時にサービスの中断を抑える
nodeが突然死んだ場合はどうしようもないが、手動もしくはCluster Autoscalerでnodeの削除が行わえる場合は、サービスを中断させないことができる。 DisruptionBudgetリソースを作成すればよい。 参考: https://qiita.com/tkusumi/items/946b0f31931d21a78058 「PodDisruptionBudget とは Node を計画的に停止したい場合に、Pod の状況を見ながら退去 (evict) させる機能です」
15.4 Summary
- podの水平スケーリング(scale out)はHorizontalPodAutoscalerリソースを作成し、それをDeployment, ReplicaSetに指定し、対象CPU使用量を指定することで簡単にできる。
- podのCPU使用量の他に、アプリケーションが提供するcustom metricsやclusterにdeployされている他のリソースのmetricsをもとにauto scalingすることができる。
- 垂直スケーリング(scale up)はまだ提供されていない
- (cloud providerから提供されていれば)cluster nodeもautoscalingできる。
16 Advanced scheduling
最初、特定のnodeに特定のpodをscheduleする方法はnode selectorを使う方法があった。 しかし後からもっと柔軟にscheduleするためのメカニズムが導入された。 それがtaintsとtolerations。 これによって特定のtaintsをもったnodeに、特定のtolerationsをもったpodのみをscheduleすることが可能になる。 taints/tolerationsとnode selector / node affinityにはいくらか違いがある。 node selector / node affinityは、podに対して情報を付与することによってpodがどのnodeにscheduleされるかを決めるための仕組み。 taints/tolerationsはそれに加えて、既存のpodに情報を付与せずnodeに情報を付与することによってpodを特定のnodeにscheduleされないようにすることができる仕組み。
例えば、
$ kubectl describe node master.k8s Name: master.k8s Role: Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux kubernetes.io/hostname=master.k8s node-role.kubernetes.io/master= Annotations: node.alpha.kubernetes.io/ttl=0 volumes.kubernetes.io/controller-managed-attach-detach=true Taints: node-role.kubernetes.io/master:NoSchedule
この場合、node-role.kubernetes.io/master:NoSchedule
がTaints。
taintsは
たとえば
$ kubectl describe po kube-proxy-80wqm -n kube-system ... Tolerations: node-role.kubernetes.io/master=:NoSchedule node.alpha.kubernetes.io/notReady=:Exists:NoExecute node.alpha.kubernetes.io/unreachable=:Exists:NoExecute ...
はnode-role.kubernetes.io/master=:NoSchedule
というtolerationをもっているので上記のnodeへscheduleできる。
node.alpha.kubernetes.io/notReady=:Exists:NoExecute のExistsは、値がnullではないことを指す。
effectは以下の4種類ある。
- NoSchedule
- taintが許容できなければnodeへscheduleさせない
- PreferNoSchedule
- taintが許容できるnodeを探し、なければ許容できないnodeであってもscheduleする
- NoExecute
- scheduling時に影響があるNoScheduleやPreferNoScheduleと違って、NoExecuteはnode上で実行中のpodへも影響がある。もしNoExecuteエフェクトをもったtaintをnodeへ追加した場合でかつpodがそのtaintを許容できない場合、そのpodはnode上から追い出される。
このtaints/tolerationsの分かりやすい使用例としては、production nodeに non-productionなpodをscheduleしたいくない場合に使える。
16.1.3 Adding tolerations to pods
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: prod spec: replicas: 5 template: spec: ... tolerations: - key: node-type Operator: Equal value: production effect: NoSchedule
podのtolerationsの設定は上記の用に設定できる。
16.2 Using node affinity to attract pods to certain nodes
taintsは特定のnodeからpodを避けるための仕組み。 node affinityという仕組みは、podを特定のnode集合へscheduleするための仕組み。 node affinityの前身はnode selectorだった。node affinityはnode selectorよりももっとパワフル。 node selectorはいずれ非推奨になる。
node selectorと同様に、各podに自身のaffinity ruleを設定する。
まずnodeのLabelにaffinityを設定する。
$ kubectl describe node gke-kubia-default-pool-db274c5a-mjnf Name: gke-kubia-default-pool-db274c5a-mjnf Role: Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/fluentd-ds-ready=true beta.kubernetes.io/instance-type=f1-micro beta.kubernetes.io/os=linux cloud.google.com/gke-nodepool=default-pool failure-domain.beta.kubernetes.io/region=europe-west1 failure-domain.beta.kubernetes.io/zone=europe-west1-d kubernetes.io/hostname=gke-kubia-default-pool-db274c5a-mjnf
上記だと下3つがaffinityで、
- failure-domain.beta.kubernetes.io/region
- はnodeが位置するregionを指す
- failure-domain.beta.kubernetes.io/zone
- はnodeが属するzoneを指す
- kubernetes.io/hostname
- はhostnameを指す
podには以下のようにnodeAffinityを設定する。
apiVersion: v1 kind: Pod metadata: name: kubia-gpu spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: gpu operator: In values: - "true"
matchExpressionsを使って柔軟に条件を設定することができる。 requiredDuringSchedulingIgnoredDuringExecution は2つに分解できる。
requiredDuringScheduling はnodeをscheduleするさいこのaffinity ruleに合致するnodeにしかscheduleされないことを意味する。 IgnoredDuringExecution はこのaffinity ruleはnodeで実行中のpodには影響を与えないことを意味する。
preferredDuringSchedulingIgnoredDuringExecution というのもある。 preferredDuringSchedulingはnodeをscheduleするさいこのaffinity ruleに合致するnodeに優先的にscheduleするが合致するnodeがなければ他のnodeへscheduleすることを意味する。 またIgnoredDuringExecutionとは対象的なRequiredDuringExecutionもある。これはnod上で実行中のpodに影響を与えることを意味するが、まだKubernetesで実装されていなく、今後実装される予定。
またnode affinityの設定は複数定義することができ、それぞれにweightを設定することができる。
16.3 pod affinity と pod anti-affinityを用いて一緒に配置する
node selectorと node affinityはpodとnodeの影響を与えるものだった。 pod affinityはpod間に影響を与える仕組み。 たとえばfrontend podとbackend podがあった場合それらのpodが近いほうがlatencyが減らせるので、それぞれ近いほうがいい。 pod affinityを使えば同じnode(もしくはラック、もしくはデータセンター)にscheduleすることができる。
以下のような定義。
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: frontend spec: replicas: 5 template: ... spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: kubernetes.io/rack labelSelector: matchLabels: app: backend
topologyKey: kubernetes.io/rack
だが、こうすると同じrackにあるnodeにpodが配置される。
どういう仕組かというと、nodeにrack=rack_a
, rack=rack_b
のようにLabelをつける。
つまりrack_aに属するnodeにはrack=rack_a
というLabelをつける。
すると、app=backend
というLabelが先にrack_aのnodeに配置されている場合は、このpod affinity ruleをもつpodはrack_aのnodeのいずれかに配置される。
16.3.4 Scheduling pods away from each other with pod anti-affinity
pod anti-affinityを使うと、pod affinityと反対のことができる。
16.4 Summry
- もしnodeにtaintsをセットすると、podがそのtaintsを許容できるtolerationをセットしていない限りそのnodeにそのpodはscheduleされない。
- taintsは3タイプあり、NoScheduleは完璧にschedulingされない。 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を避けさせることができる
17.2.3 Starting pods in a specific order
https://qiita.com/tkusumi/items/f64fff37a724b86d9819#init-containers-alpha
Pod内で初期化処理をするコンテナを指定をできる機能です。Podの定義にinitContainersという項目で、従来のcontainersで指定したコンテナの前に起動するコンテナを指定できるようになるようです。複数のコンテナを指定することができますが、containersがパラレルに起動されるのに対してinitContainersは指定した順番に1つずつ起動していくようです。
使用用途としては例えば以下のようなものが挙げられます。
- データを動的にダウンロードしてくる
- データベーススキーマの反映
- アプリケーションが何らかの事前条件を満たすまでウェイトする
BEST PRACTICES FOR HANDLING INTER-POD DEPENDENCIES
init containersを使えば事前条件が満たされるまでpodのmainコンテナが起動するのを遅らせることができる。 readiness probesを設定するのを忘れてはいけません。 アプリケーションがまだ準備段階ではない場合にserviceにpodが追加されるのを防ぐことができますし、 Deployment controllerが、bad versionをrolloutするのを防ぐためにも使用されます。
17.2.4 Adding 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として実行される
USING A POST-START CONTAINER LIFECYCLE HOOK
Post-start hookはコンテナのmain processが実行された後すぐに実行される。
もしコンテナのアプリケーションとは別のアプリケーションを動かしたい場合、あなたがそのアプリケーションの開発者ならアプリケーション内で別のアプリケーションを動かすことができるが、アプリケーションの開発者ではない場合、post-start hookは役に立つ。
Post-start hookはmain processと平行して実行されるが、以下の点でcontainerに影響を与える
まずPost-start hookの実行が完了するまで、containerのstate
はWaiting
のままでありreason
はContainerCreating
のまま。そのため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に書き込むこと。
USING A PRE-STOP CONTAINER LIFECYCLE HOOK
https://qiita.com/superbrothers/items/3ac78daba3560ea406b2
17.3 Ensuring all client requests are handled properly
17.3.1 Preventing broken client connections when a pod is starting up
readinessを設定すること
17.3.2 Preventing broken connections during pod shut-down
まず、podが削除されるときの、Kubernetesの動きは以下になる。
1, client(kubectlとか)からpodの削除リクエストがくる 2, A1とB1が並行して同時に実行される A1, kubeletにpodの削除通知が送られる A2, kubeletからpodにコンテナの停止リクエストが送られる A3, コンテナのpre-stop hookが実行され、, SIGTERMが送られ、, 一定時間待った後、それでもまだコンテナのプロセスが動いていたら強制的にkillする B1, EndpointsControllerへpodの削除通知が送られる B2, EndpointsControllerはAPI Serverへendpointからpodを削除するようにリクエストする B3, API Serverはkube-proxyへEndpoints変更通知を送る B4, kube-proxyはnodeのiptablesからpodを削除する
コンテナが停止プロセスを実行しているときに処理中のリクエストはどうなってしまうか。 リクエストの処理に時間がかかる場合であれば、“Connection Refused”が起こるのは避けられない。 なので考えられる選択肢としては以下。 * 数分待ち、新しいリクエストを受け取るのを止める * 全てのkeep-aliveコネクションを閉じる * 全ての処理中のリクエストが処理完了するまで待つ * shut downを完了させる
pre-stop hookに数分待つように仕込めば実現できる。 しかしそれを入れるとpodの削除まで時間がかかってしまうので諸刃の剣。
17.4 Making your apps easy to run and manage in Kubernetes
17.4.1 Making manageable container images
imageのサイズは小さくし、不要なファイルやツールは含めないように。
17.4.2 Properly tagging your images and using imagePullPolicy wisely
docker imageのtagにはlatestが使えるが、podのyamlファイルにはlatestを指定しないようにしよう。 もしimageを更新しても、新しくscheduleするpodにはその新しいimageが使用されるが、既存のpodのコンテナのimageは古いバージョンのまま。 またlatestタグを使うと1つ前のバージョンへrollbackができない。
もしあなたがimageのタグにmutable tag(同じタグを使い続けること)を使うならpodのspecのimagePullPolicyはAlwaysにしなければならない。 しかしそれはproductionでは大きな落とし穴になる。 もしAlwaysを設定したら、新しいpodがscheduleするたびにcontainer runtimeは毎回container registryに問い合わせることになる。 これはpodが起動するのが少し遅くなる。なぜならnodeは毎回imageが更新されているかチェックする必要がでてくるため。またcontainer registryが応答がない場合、podが起動するのを妨げてしまう。
17.4.3 Using multi-dimensional instead of single-dimensional labels
podだけではなく他のリソースにもlabelをつけることを忘れないようにしよう。 各リソースに複数のlabelをつけるようにすれば、リソースのselectが簡単になる。 labelには例えば以下のものがよいだろう。
- リソースが属しているアプリケーション(もしくはマイクロサービス)の名前
- Enviroment(development, QA, staging, production 等)
- バージョン
- リリースのタイプ(stable, canary, green or blue for green/blue deployments等)
- テナント(あなたがもしpodをnamespaceを使用する代わりに各テナントで動かしている場合)
- シャードシステムならそのシャード
17.4.4 Describing each resource through annotations
他の追加情報はannotationに含めましょう。 たとえばそのアプリケーションの責任を持っている人の情報とか。 もしマイクロサービスであれば、そのpodが使用している他のサービスの名前とか。 バージョン情報とか、ツールやGUIツールが使用するmetadataとか。
17.4.5 Providing information on why the process terminated
Kubernetesにはなぜコンテナが終了したのかの情報を含めることができます。 コンテナの /dev/termination-log に終了した理由を書き込んでおけば、 kubectl describe podしたときにContainersのLast StateのMessageに表示される。
17.4.6 Handling application logs
アプリケーションログは標準に出すべき。 そうすればkubectl logsで見れる。 一つ前のpodのlogはkubectl logs --previousでみれる。
特定のログファイルにはいていたら、
$ kubectl exec <pod> cat <logfile>
でみれる。
または、pod内にコンテナが1つなら
$ kubectl cp foo-pod:/var/log/foo.log foo.log
でログをローカルへcpすることができる。
複数のコンテナが実行されていたら -c containerName オプションでコンテナを指定する。
Kubernetesはログ集約システムは提供していない。 しかしそれをログ集約システムをデプロイするのは簡単。 Google Kubernetes EngineならEnable Stackdriver Logging checkbox にチェックを入れればいい。
EFK(ElacsticSeach, Fluentd, kibana)のようなスタックをデプロイすれば使うこともできる。 fluentdのようなログ収集ミドルウェアは複数行ログ(たとえばJavaのスタックトレースのような)は1行1行別のログになってしまうので、jsonとして出力するのがよい。 ただjsonログは人間には見にくいので(kubectl logsした場合)、 標準出力にはplain textにして、特定のログファイルにはjsonで出力するのがよい。
17.6 Summary
- podのような頻繁にrelocateするappと、ほとんど移動しないappの違いについて
- マイクロサービスのような複数のコンポーネントアプリは特定の順序で起動にすることに頼るべきではないことを理解する
- init containersの紹介。init containersとはpodの起動に使用されたり、事前条件を満たすまでpodのmain containerの起動を遅らせることができる
- コンテナのlifecycle hooks の紹介
- Kubernetesコンポーネントの分散性質の結果と結果整合性モデルの深い理解
- リクエストを壊すことないアプリケーションの適切なshut downの仕方について
- imageサイズを小さくすることにや、annotationsや複数のlabelを各リソースに追加することによって管理がどのように楽になるか
- どのようにKubernetes上での動くアプリケーションの開発をするか、また、multi node clusterにデプロイする前にminikubeやローカルでどのように開発するか
18 Extending Kubernetes
18.1 Defining custom API objects
自分のAPI objectを定義し、それらのobjectのためのcontrollersを実装することができる。
18.2 Introducing CustomResourceDefinitions
新しいリソースを作成するためには、CustomResourceDefinition objectを定義する必要がある。 CustomResourceDefinitionを定義すれば、他のリソースが同様, yamlやjsonを通してそのinstanceを作成することができるようになる。 以下が定義例。
apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: websites.extensions.example.com spec: scope: Namespaced group: extensions.example.com version: v1 names: kind: Website singular: website plural: websites
このリソースのinstanceを作成する場合は以下。
apiVersion: extensions.example.com/v1 kind: Website metadata: name: kubia spec:  gitRepo: https://github.com/luksa/kubia-website-example.git
そして新しく定義したこのリソースに対するcontrollerを実装する必要がある。
例 https://github.com/luksa/k8s-website-controller
controllerもpodとして動かすことができる。
apiVersion: apps/v1beta1 kind: Deployment metadata: name: website-controller spec: replicas: 1 template: metadata: name: website-controller labels: app: website-controller spec: serviceAccountName: website-controller containers: - name: main image: luksa/website-controller - name: proxy image: luksa/kubectl-proxy:1.6.2
custom objectのバリデートはKubernetes1.8でアルファ機能として導入された。 API serverで バリデートするためにはCustomResourceValidation機能を有効にする必要がある。
18.1.4 Providing a custom API server for your custom objects
Kubernetesでcustom objectのサポートを提供する良い方法は、自分のAPI serverを実装し、clientがそのAPI serverとやり取りさせること。 Kubernetes 1.7から、KubernetesのデフォルトのmainのAPI Serverと自分で作成したAPI serverを統合することができるようになった。 複数のAPI Serverがあっても1つのAPIServerとして扱うことができる。
custom api serverを登録するには、custom api serverをpodとしてdeployしserverを通して公開すればよい。
18.2 Extending Kubernetes with the Kubernetes Service Catalog
最初の追加API Serverとして、Service Catalog API serverがある。 Service Catalogとは名前の通りserviceのカタログで、Service Catalog機能を使えば、カタログの中からサービス(アプリケーション)を選んで、pod,service,configmap等を直接扱うこと無く簡単にデプロイすることができるようになる。
Service Catalogは以下のリソースを提供している。
- ClusterServiceBroker。これはサービスを提供する(外部)システムについて定義したもの
- ClusterServiceClass。これは提供されるサービスについて定義したもの
- ServiceInstance。これは提供されたサービスのinstance
- ServiceBinding。これはServiceInstanceとclients(pods)のセットを結びつけるもの
Kubernetesは、提供されるサービスのリストをbrokerへ問い合わせ、ClusterServiceClassリソースを作成する ユーザが提供されるサービスが必要な場合、KubernetesはServiceInstanceを作成し、ServiceInstanceをpodsに結びつける(bindingする) それらのpodsに必要な認証情報や接続に必要な情報をsecretを通して渡す。
18.2.2 Introducing the Service Catalog API server and Controller Manager
Kubernetesと似ていて、Service Catalog以下の3つのコンポーネントからなる分散システムである。
- Service Catalog API Server
- etcd as the storage
- Controller Manager, where all the controllers run
18.2.3 Introducing Service Brokers and the OpenServiceBroker API
クラスタの管理者は1つ以上の外部ServiceBrokerをService Catalogに登録することができる。 各brokerはOpenServiceBroker APIを実装する必要がある。
Service Catalogがサービスの一覧を取得したあと、Service Catalog は各ClusterServiceClassリソースを生成する。各ClusterServiceClassリソースは、サービスの1つのタイプが定義されている(例えばあるClusterServiceClassは“PostgreSQL database”)。 各ClusterServiceClassは、1つ以上のservice planを持っている。ユーザは必要とするそのサービスレベルを選択することができる。たとえばdatabase ClusterServiceClassはHDDのfreeプランや、SSDのPremiumプランを提供したりするだろう。
18.2.4 Provisioning and using a service
実際にserviceが提供されるためには、service instanceを作成する必要がある。 例:
apiVersion: servicecatalog.k8s.io/v1alpha1 kind: ServiceInstance metadata: name: my-postgres-db spec: clusterServiceClassName: postgres-database clusterServicePlanName: free parameters: init-db-args: --data-checksums
重要なのは、このservice(これだとpostgres-database)は、Kubernetesクラスタ外に作成されてもいいということ。なので例えばクラウド上のDBでもよい。 serviceへの接続情報はServiceBindingリソースを使ってsecretを通して与えられる。
例:
apiVersion: servicecatalog.k8s.io/v1alpha1 kind: ServiceBinding metadata: name: my-postgres-db-binding spec: instanceRef: name: my-postgres-db secretName: postgres-secret #ここに好きなsecret名を指定
将来的にはPodPresetsというKubernetesの機能が導入される予定。
Service CatalogはServiceBindingで指定した名前で新しいSecretを生成し、必要な情報をsecret内に保存する。 あとはpodからそのsecretをmountして使えば、podが接続情報を得ることができる。
18.4 Summary
- CustomResourceDefinition objectを作成することで、Custom resourcesをAPI Serverに登録することができる
- API Serverのコードを変更すること無く、CustomObjectのインスタンスを保存、取得、更新、削除することができる
- custom objectsを実際にKubernetes上で動くようにCustom Controllerを実装することができる
- API aggregation機能を通し、Custom API Serverを使うことでKubernetesを拡張することができる
- Kubernetes上に構築されたPasSはコンテナを使ったアプリケーションを構築するのが楽になる
- パッケージマネージャーのhelmは既存のアプリケーションをresource manifestsを必要とせずにデプロイすることができる
appendix A: Using kubectl with multiple clusters
A.2.2 Understanding the contents of the kubeconfig file
apiVersion: v1 clusters: - cluster: certificate-authority: /home/luksa/.minikube/ca.crt server: https://192.168.99.100:8443 name: minikube contexts: - context: cluster: minikube user: minikube namespace: default name: minikube current-context: minikube kind: Config preferences: {} users: - name: minikube user: client-certificate: /home/luksa/.minikube/apiserver.crt client-key: /home/luksa/.minikube/apiserver.key
上記のようにKubeconfig fileは以下で構成されている。
- clustersのリスト
- usersのリスト
- contextsのリスト
- current contextの名前
それぞれの詳細
cluster
- Kubernetes clusterを表している。API ServerのURL、certificate authority(CA)ファイル、他には必須ではないがAPI serverと通信するためのいくつかのオプション。 CA certificateは分割して保存できそれをkubeconfigファイル内から指定できる。また直接certificate-authority-dataフィールドに含めることも出来る。
user
- どのuserもAPI Serverと通信する時に使うcredentialsを定義する。credentialsには以下が使える
- usernameとpassowrd
- authentication token
- client key and certificate
- client key and certificateはkubeconfig fileに含めることができる。もしくはファイルを分割してconfig file内で指定することができる。以下のように
users: - name: minikube user: client-certificate: /home/luksa/.minikube/apiserver.crt client-key: /home/luksa/.minikube/apiserver.key
context
- contextはclusterとuserを紐付けるもの。またkubectlで使われるデフォルトのnamespaceを指定できる。複数のcontextで、同じuserや同じclusterを指定することができる。
appendix B: Setting up a multi-node cluster with kubeadm
kubeadmを使えば複数nodeクラスタが簡単に作成できる。
appendix C: Using other container runtimes
C.1 Replacing Docker with rkt
container runtimeとしてdockerのほかにrktがある。
rktはデフォルトでPod(複数の関連するコンテナを実行する)の概念をサポートしている。
rktはDocker-formatted container imageをそのまま実行することができるのでリパッケージは必要がない。
Kubernetesでrktを使うためにはkubeletに--container-runtime=rkt
オプションを渡してあげればよい。
なおkubeletはContainer Runtimeとやりとりする唯一のコンポーネント。
C.2 Using other container runtimes through the CRI
Kubernetes 1.5 から Container Runtime Interface (CRI) が導入された。 CRIはplugin APIで他のcontainer runtimeを統一的に操作することができる。 kubeletはDockerやrktをCRIを通して操作する。
新しいCRI実装として、CRI-Oというものもでてきた。
Kubernetesをコンテナの代わりにVM上でアプリケーションを動かせる新しいCRI実装が開発中。 そのうちの一つはFrakti(The hypervisor-based container runtime for Kubernetes.)というもの。 https://github.com/kubernetes/frakti
ほかには Mirantis VirtletというCRI実装があり、これは、docker imageの代わりに実際にVM imagesを動かすというもの。
appendix D: Cluster Federation
Kubernetesは複数のKubernetesを1つのKubernetesとして扱うための Cluster Federationという機能がある。 これにより、Kubernetes Clusterを複数のdata center、複数のアベイラビリティゾーン、もしくは複数のクラウドに冗長化することができる。