LoginSignup
3
1

More than 3 years have passed since last update.

Real Allocatable Resources on Kubernetes Nodes

Last updated at Posted at 2019-01-03

Overview

Kubernetes では、起動したノードのリソース (CPU/Memory) を全て使えるわけではありません。ノードで必須となる Container Runtime / kubelet / kube-proxy に加え、名前空間 kube-system 配下で起動する DNS 等のアドオンがあります。

アドオンによるリソース占有は、ある程度の規模のクラスタであれば無視できる率ですが、小規模クラスタの場合、不要なアドオンを起動したままにしていると Kubernetes を動かすために大半のコストをかける羽目にもなります。

Google Kubernetes Engine を例にして、デフォルトで設定されるアドオンがどれくらいのリソースを占有しているかを調べ、カスタマイズを通じて理解を深めたいと思います。

How to Inspect Allocated Resources

kubectl describe nodes でノードの詳細情報が得られます。どの Pod がどのくらいのリソースを占有しているかを確認できます。

$ kubectl describe nodes | grep 'Allocated resources:' -A 4

コンテナごとのリソース要求 spec.containers[].resources.requests を知るには kubectl get pods で確認できます。好みの go-template を用意しておくと便利です。

$ kubectl get pods --namespace=kube-system -o go-template-file=pod-requests.tpl
Host IP Pod Container   CPU Memory
...
10.146.0.4  kube-dns-788979dc8f-lkxvz   kubedns 100m    70Mi
10.146.0.4  kube-dns-788979dc8f-lkxvz   dnsmasq 150m    20Mi
10.146.0.4  kube-dns-788979dc8f-lkxvz   sidecar 10m 20Mi
10.146.0.4  kube-dns-788979dc8f-lkxvz   prometheus-to-sd    <no value>  <no value>
...
pod-requests.tpl
Host IP{{"\t"}}Pod{{"\t"}}Container{{"\t"}}CPU{{"\t"}}Memory
{{- range $i, $v := .items }}
  {{- range .spec.containers }}
{{ $v.status.hostIP }}{{"\t"}}{{ $v.metadata.name }}{{"\t"}}{{ .name }}{{"\t"}}{{ .resources.requests.cpu }}{{"\t"}}{{ .resources.requests.memory }}
  {{- end }}
{{- end}}

アドオンにリソースが占有されるパターンは、大きく分けて以下の3つがあることがわかります。

  • 固定量で占有
  • リソース空き状況に応じて増減して占有
  • ノード数に比例して占有

Google Kubernetes Engine

GKE (Google Kubernetes Engine) において、ノードで占有されるリソース配分は、以下のドキュメントに記載があります。

Allocatable memory and CPU resources に占有率についての記載がありますが、注意書きにある通り kube-system 配下の Pods を含みません。概ね 40% の vCPU と 400MB のメモリが、それぞれのノードで占有されるとあります。

Note: The values listed for allocatable resources do not account for the resources used by kube-system pods, the amount of which varies with each Kubernetes release. These system pods generally occupy an additional 0.4 vCPU and 400 MiB memory on each node (values are approximate). It is recommended that you directly inspect your cluster if you require an exact accounting of usable resources on each node.

以下のバージョンのノードで調べてみました。

  • Node Version: 1.10.9-gke.5
  • Image: Container-Optimized OS (cos)

1コアのノード1台構成だと kube-system だけで CPU を 72% 占有してしまい、デフォルトのCPU割り当て 0.1(100m) では、2つまでしかコンテナを起動することができません。

$ kubectl describe nodes | grep 'Allocated resources:' -A 4
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ------------  ----------  ---------------  -------------
  681m (72%)    296m (31%)  807312Ki (29%)   1216912Ki (45%)

3コア未満では GKE を使うメリットはなく、3コア以上でようやく半分のリソースが使えるようになる感じです。

Cores Allocated CPU Allocated Memory
1 0.7 0.8GB
2 1.2 1.2GB
3 1.4 1.4GB
4 1.6 1.6GB

kube-system 配下のワークロードを確認すると Stackdriver のアドオンが含まれており、それなりのリソースを占有することがわかります。

Workload Type CPU Memory Purpose
event-exporter Deployment - - Stackdriver Logging
fluentd-gcp-scaler Deployment - - Stackdriver Logging
fluentd-gcp DaemonSet 100m 200Mi Stackdriver Logging
heapster Deployment 138m 294Mi Stackdriver Monitoring
kube-dns Deployment 260m 110Mi Kube DNS
kube-dns-autoscaler Deployment 20m 10Mi Kube DNS
kube-proxy Pod 100m -
l7-default-backend Deployment 10m 20Mi HTTP load balancing
metrics-server Deployment 53m 154Mi Stackdriver Monitoring

ノード数に比例して占有率が増えるものは、見積もりは容易です。kube-proxy と DaemonSet はノードごとに Pod が作成されます。

リソース空き状況を元に占有率が増減するものは、閾値の設定を把握しておく必要があります。

GKE のドキュメントには、小規模クラスタ用にアドオンを無効にする方法が紹介されています。

すべてを無効にすることで、CPU: 110m / Memory: 20Mi まで削減することができました。

$ kubectl describe nodes | grep 'Allocated resources:' -A 4
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ------------  ----------  ---------------  -------------
  110m (11%)    10m (1%)    20Mi (0%)        20Mi (0%)

Stackdriver Logging

Stackdriver Logging では、以下のアドオンが追加されます。

  • event-exporter
  • fluentd-gcp-scaler
  • fluentd-gcp

DaemonSet である fluentd-gcp により、ノードあたり CPU:100m と Memory:200Mi が占有されます。

Stackdriver Logging を無効にするには gcloud コマンドで --logging-service none を指定します。

$ gcloud container clusters update <CLUSTER_NAME> --logging-service none

kubectl logs により、アクティブなコンテナのログは確認可能ですが、削除されたコンテナのログは確認できなくなります。

Stackdriver Monitoring

Stackdriver Monitoring では、以下のアドオンが追加されます。

  • heapster
  • metrics-server

Stackdriver Monitoring を無効にするには gcloud コマンドで --monitoring-service none を指定します。

$ gcloud beta container clusters update <CLUSTER_NAME> --monitoring-service none

Horizontal Pod Autoscaler は、リソースの空き状況をチェックして、動的にコンテナの割り当てリソースを調整しますが、Stackdriver Monitoring からの情報を元にしているため無効にします。

$ gcloud container clusters update <CLUSTER_NAME> --update-addons=HorizontalPodAutoscaling=DISABLED

これにより heapster が削除されます。ちなみに Heapster は Kubernetes 1.11 からは Deprecated となっています。

metrics-server は Deployment でレプリカ数を制御しているため --replicas=0 にします。

$ kubectl --namespace=kube-system scale deployment metrics-server-v0.2.1 --replicas=0

Stackdriver Monitoring を無効にすると、モニタリングができなくなるだけでなく、metrics-server に依存している、以下のような機能が使えなくなります。

Kube DNS

Kube DNS は、DNS ベースの Service Discovery の機能を提供します。kube-dns 単体で CPU:260m と Memory:110Mi を占有します。

可用性は落ちますが、kube-dns-autoscaler によるレプリケーションを無効にして kube-dns を1台構成とすれば、最低限のリソース占有で Service Discovery の機能を利用可能です。

$ kubectl scale --replicas=0 deployment/kube-dns-autoscaler --namespace=kube-system
$ kubectl scale --replicas=1 deployment/kube-dns --namespace=kube-system

kube-dns 自体を無効とするには --replicas=0 とします。

$ kubectl scale --replicas=0 deployment/kube-dns --namespace=kube-system

kube-dns が無効となると、Service Discovery の機能が利用できなくなるだけでなく、DNS Lookup のためには Pod ごとに外部ネームサーバを設定することが必要になります。

Conclusion

ノードとしては、Container Runtime / kubelet / kube-proxy さえ動いていれば、機能することがわかりました。

Kube DNS についてはノードサイズに比例して増えるものではなく、DNS ベースの Service Discovery は Kubernetes を使うメリットでもあるため、削減対象とするのは本末転倒に思えます。

Logging や Monitoring のアドオンは、本番運用では必要なものですが、カスタマイズの余地はあると感じました。GKE 謹製の Stackdriver Logging を例にすると、Fluentd を使ったログ転送エージェントが Ruby であるためなのか、デフォルトでは CPU:100m と Memory:200Mi が確保されてしまいます。DaemonSet でり、ノード数に比例して占有リソースは増えてしまうため、もっとミニマムなエージェントを使いたいところです。GKE のドキュメントでも、独自の ScalingPolicy を使ったチューニング例が紹介されています。

3
1
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
3
1