Improving the Performance of Your Kubernetes Cluster
KubeCon + CloudNativeCon Europe 2020 1日目 のセッションである Improving the Performance of Your Kubernetes Cluster
についてです。
Step 1: Calculating overhead
シングルプロセスのオーバヘッドを計算する: https://github.com/priyawadhwa/track-cpu
- duration と interval を指定すると、その間の監視対象プロセスの平均/最大 cpu 使用率を出してくれる
- 発表された方の自作ぽい
プロセス全体のオーバヘッドを計算する: https://github.com/tstromberg/cstat
- iostat より 100 倍正確らしい (README より)
それぞれの動作環境で CPU 使用率はそれぞれ以下の結果となった。
どのように Kubernetes Cluster のパフォーマンスを向上させるか、Minikube を例に以降の発表が続く。
Learning to use performance tools
こんなツールを使うといいよってやつ
The USE Method
USE: Utilization, Saturation and Errors
それぞれ確認した項目、コマンド、結論について述べられている。
Component | Command | Conclusion |
---|---|---|
CPU (system wide) | mpstat -P ALL 1 |
CPU の %sys は通常通りで、1コアに負荷が集中してるわけでもない |
CPU (minikube process) | pidstat 1 -C qemu -h |
minikube プロセスのオーバヘッドは平均 22% で、内 14.5 % は VM 内からくるもの |
Memory capacity | free -m |
通常 |
Storage Device I/O (Utilization) | iostat -xz 1 |
通常 |
Storage Device I/O (Utilization, per process) | sudo iotop --only |
一度に minikube のもつ複数プロセスがディスク書き込みをしていることが分かった |
eBPF in Minikube
biosnoop (Block Device I/O をトレースしてPID ごとの latency を取得) を実行してみると、殆ど etcd
Flame graph
ホストで Flame graph を取ると、CPU_n/KVM
というのが見える
CPU_0/KVM
の内訳をみると、ほとんど ioctl syscall が占めている
Is there a way to tune how often etcd writes to disk?
とりあえずやってみたチューニング (not significant と言われている)
- etcd のディスク書き込みの頻度を減らしたい!
- とりあえず etcd の
--snapshot-count
オプションをチューニングしてみる --snapshot-count=3000
にしたところ 2% しか向上しなかった
ここまでのまとめ
- オーバヘッドの調査をした
- USE の解析より、 etcd が disk 書き込みをめっちゃやってるように見えた
- Flame Graph より、ioctl 呼び出しが原因っぽい
- チューニング: etcd の snapshot count の数を減らした
- パフォーマンス向上は見られなかった
What are these spikes?
以下の図より、 CPU 使用率は断続的にスパイクがあるように見える
pidstat より kubectl apply -f /etc/kubernetes/addons
の実行が頻繁に CPU を使ってるように見えた
What is the addon manager?
kube-addon-manager *2 により5秒ごとに
kubectl apply
が実行されている!ポーリング間隔を延ばしてみてオーバヘッドが改善するか試した -> 改善した!
- ポーリング間隔とユーザエクスペリエンスはトレードオフだけど、今回は完全にポーリングをやめてみた
- 32% 削減! *3
kube-apiserver overhead
次にオーバヘッドがありそうな、 kube-apiserver の改善
pprof
kube-apiserver に対して Golang のプロファイリングツールである pprof を利用してみた
top
で CPU 使用率を見ると syscall.Syscall が flat%: 10.76%, sum%: 50.00% だったflame graph より以下が分かった
filters.ServeHTTP
が 16%transport.Reader
が 12%
Leader election requests from scheduler & controller manager
kube-apiserver を -v=10
で起動してみたら、 Leader election が目立った *4
- minikube はシングルノードなので leader election を切ってしまおう!
- kube-scheduler , kube-controller-manager それぞれのオプションに
--leader-elect=false
を指定
- kube-scheduler , kube-controller-manager それぞれのオプションに
- 18% の削減!
- ついでに codedns の replica 数も1にしたとしれっと書かれている
etcd overhead
etcd でも同じように pprof で見てみた
top
で CPU 使用率を見ると syscall.Syscall が flat%: 40.00%, sum%: 40.00% だったweb
でビジュアライズすると、http.writeFrameAsync
というメソッドが 40ms の始まりっぽいのが分かった
Searching through etcd code
- etcd のソースコード内で Golang の
http
ライブラリを使ってる箇所を調べた ->httpproxy
パッケージを使っている箇所を発見! refreshInterval
がデフォルト30秒で設定されていて、--proxy-refresh-interval
オプションで設定できることが分かった- --proxy-refresh-interval を 70000 (70秒) に設定 -> 4%削減!
Does changing the refresh interval make user experience worse?
--proxy-refresh-interval
の値は、endpoint *5 の更新間隔
まとめ
- 不必要なものを取り除いた
- Addon manager
- Coredns pod
- Leader election
- オーバヘッドとユーザエクスペリエンスのトレードオフは考慮しましょう
- コラボレーションはめっちゃ重要
- 分からないときには Slack で質問
感想
ツールを使って計測することで minikube のどこが重いかを調査する内容で、とてもおもしろかったです。 自分は ISUCON をやることがあるのですが、その中でよく使うツールがこの発表でも出てきたので 「おおー ISUCON だ」となりましたw
*1:https://github.com/iovisor/bcc
*2:https://qiita.com/inajob/items/300805e895eec6535dd2 (分かりやすかったので引用させていただきました)
*3:CPU使用率を32%減らした ではなく、最初の状態を100とした場合に32%性能が向上したってことぽい (多分)
*4:これを見て自分はそう思える自信がない・・・
*5:etcd のendpoint のこと?
*6:https://github.com/etcd-io/etcd/blob/cfdc296a3c4f21c7bba244f17b4c2d7f68595ece/proxy/httpproxy/director.go#L52-L68 (聴講後現在の master HEAD)