背景簡介
隨着容器技術的發展,容器服務已經成為行業主流,然而想要在生產環境中成功部署和操作容器,關鍵還是容器編排技術。市場上有各種各樣的容器編排工具,如Docker原生的Swarm、Mesos、Kubernetes等,其中Google開發的Kubernetes因為業界各大巨頭的加入和開源社區的全力支撐,成為了容器編排的首選。
簡單來講,Kubernetes是容器集群管理系統,為容器化的應用提供資源調度、部署運行、滾動升級、擴容縮容等功能。容器集群管理給業務帶來了便利,但是隨着業務的不斷增長,應用數量可能會發生爆發式的增長。那在這種情況下,Kubernetes能否快速地完成擴容、擴容到大規模時Kubernetes管理能力是否穩定成了挑戰。
K8s & K3s 架構

集群內部:如上Kubernetes架構圖所示,無論外部客戶端,還是Kubernetes集群內部組件,其通信都需要經過Kubernetes的apiserver,API的響應性決定着集群性能的好壞。
集群外部:對於外部客戶而言,他只關注創建容器服務所用的時間,因此,pod的啟動時間也是影響集群性能的另外一個因素。
目前,業內普遍采用的性能標准是:
- API響應性:99%的API調用響應時間小於1s。
- Pod啟動時間:99%的pods(已經拉取好鏡像)啟動時間在5s以內。
“pod啟動時間”包括了ReplicationController的創建,RC依次創建pod,調度器調度pod,Kubernetes為pod設置網絡,啟動容器,等待容器成功響應健康檢查,並最終等待容器將其狀態上報回API服務器,最后API服務器將pod的狀態報告給正在監聽中的客戶端。
除此之外,網絡吞吐量、鏡像大小(需要拉取)都會影響Kubernetes的整體性能。
Kubernetes性能的關鍵點
1 當集群資源使用率是X%(50%、90% 、99%等不同規模下)的時候,創建新的pod所需的時間(這種場景需要提前鋪底,然后在鋪底基礎上用不同的並發梯度創建pod,測試pod創建耗時,評估集群性能)。在測試kubernetes新版本時,一般是以老版本穩定水位(node、pod等)鋪底,然后梯度增加進行測試。
2 當集群使用率高於90%時,容器啟動時延的增大(系統會經歷一個異常的減速)還有etcd測試的線性性質和“模型建立”的因素。調優方法是:調研etcd新版本是否有解決該問題。
3 測試的過程中要找出集群的一個最高點,低於和高於這個閾值點,集群性能都不是最優的。
4 組件負載會消耗master節點的資源,資源消耗所產生的不穩定性和性能問題,會導致集群不可用。所以,在測試過程中要時刻關注資源情況。
5 客戶端創建資源對象的格式 —— API服務對編碼和解碼JSON對象也需要花費大量的時間 —— 這也可以作為一個優化點。
集群壓測
集群整體指標
1 不同的集群使用水位線(0%,50%, 90%)上,pod/deployment(rs 等資源)創建、擴縮容等核心操作的性能。可以通過預先創建出一批dp(副本數默認設置為3)來填充集群,達到預期的水位,即鋪底。
2 不同水位對系統性能的影響——安全水位,極限水位
3 容器有無掛載數據盤對容器創建性能的影響。例如,掛載數據盤增加了kubelet掛載磁盤的耗時,會增加pod的啟動時長。
測試kubernetes集群的性能時,重點關注在不同水位、不同並發數下,長時間執行壓力測試時,系統的穩定性,包括:
1 系統性能表現,在較長時間范圍內的變化趨勢
2 系統資源使用情況,在較長時間范圍內的變化趨勢
3 各個服務組件的TPS、響應時間、錯誤率
4 內部模塊間訪問次數、耗時、錯誤率等內部性能數據
5 各個模塊資源使用情況
6 各個服務端組件長時間運行時,是否出現進程意外退出、重啟等情況
7 服務端日志是否有未知錯誤
8 系統日志是否報錯
apiserver
1 關注api的響應時間。數據寫到etcd即可,然后根據情況關注異步操作是否真正執行完成。
2 關注apiserver緩存的存儲設備對性能的影響。例如,master端節點的磁盤io。
3 流控對系統、系統性能的影響。
4 apiserver 日志中的錯誤響應碼。
5 apiserver 重啟恢復的時間。需要考慮該時間用戶是否可接受,重啟后請求或者資源使用是否有異常。
6 關注apiserver在壓力測試情況下,響應時間和資源使用情況。
scheduler
1 壓測scheduler處理能力
並發創建大量pod,測試各個pod被調度器調度的耗時(從Pod創建到其被bind到host)
不斷加大新建的pod數量來增加調度器的負載
關注不同pod數量級下,調度器的平均耗時、最大時間、最大QPS(吞吐量)
2 scheduler 重啟恢復的時間(從重啟開始到重啟后系統恢復穩定)。需要考慮該時間用戶是否可接受,重啟后請求或者資源使用是否有異常。
3 關注scheduler日志中的錯誤信息。
controller
1 壓測 deployment controller處理能力
並發創建大量rc(1.3 以后是deployment,單副本),測試各個deployment被空感知並創建對應rs的耗時
觀察rs controller創建對應pod的耗時
擴容、縮容(縮容到0副本)的耗時
注: 不斷加大新建deployment的數,測試在不同deployment數量級下,控制器處理deployment的平均耗時、最大時間、最大QPS(吞吐量)和控制器負載等情況
2 controller 重啟恢復的時間(從重啟開始到重啟后系統恢復穩定)。需要考慮該時間用戶是否可接受,重啟后請求或者資源使用是否有異常。
3 關注controller日志中的錯誤信息。
kubelet
1 node心跳對系統性能的影響。
2 kubelet重啟恢復的時間(從重啟開始到重啟后系統恢復穩定)。需要考慮該時間用戶是否可接受,重啟后請求或者資源使用是否有異常。
3 關注kubelet日志中的錯誤信息。
etcd
1 關注etcd 的寫入性能
寫最大並發數
寫入性能瓶頸,這個主要是定期持久化snapshot操作的性能
2 etcd 的存儲設備對性能的影響。例如,寫etcd的io。
3 watcher hub 數對kubernetes系統性能的影響。
Kubectl 基礎命令
- 資源創建
# 創建資源,也可以使用遠程 URL
kubectl create -f ./my.yaml
# 使用多個文件創建資源
kubectl create -f ./my1.yaml -f ./my2.yaml
# 使用目錄下的所有清單文件來創建資源
kubectl create -f ./dir
# 啟動一個 nginx 實例
kubectl run nginx --image=ngin
- 顯示和查找
# 列出所有 namespace 中的 service
kubectl get services
# 列出所有 namespace 中的 pod
kubectl get pods --all-namespaces
# 列出 kube-system 中的 pod
kubectl get pods -n kube-system
# 列出所有 pod 並顯示詳細信息
kubectl get pods -o wid
- 更新資源
# 滾動更新 pod frontend-v1
kubectl rolling-update frontend-v1 -f frontend-v2.json
# 更新資源名稱並更新鏡像
kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2
# 更新 frontend pod 中的鏡像
kubectl rolling-update frontend --image=image:v2
# 強制替換,刪除后重新創建資源。會導致服務中斷。
kubectl replace --force -f ./pod.json
# 為 nginx RC 創建服務,啟用本地 80 端口連接到容器上的 8000 端口
kubectl expose rc nginx --port=80 --target-port=800
- 刪除資源
# 刪除 pod.json 文件中定義的類型和名稱的 pod
kubectl delete -f ./pod.json
# 刪除名為 "baz" 的 pod 和名為 "foo" 的 service
kubectl delete pod, service baz foo
# 刪除具有 name=myLabel 標簽的 pod 和 serivce
kubectl delete pods, services -l name=myLabel
# 刪除具有 name=myLabel 標簽的 pod 和 service,包括尚未初始化的
kubectl delete pods, services -l name=myLabel --include-uninitialized
# 刪除 my-ns namespace 下的所有 pod 和 serivce,包括尚未初始化的
kubectl -n my-ns delete po,svc --al
- pod交互
# 流式輸出 pod 的日志(stdout
kubectl logs -f my-pod
# 流式輸出 pod 中容器的日志(stdout,pod 中有多個容器的情況下使用)
kubectl logs -f my-pod -c my-container
# 交互式 shell 的方式運行 pod
kubectl run -i --tty busybox --image=busybox -- sh
# 連接到運行中的容器
kubectl attach my-pod -i
# 在已存在的容器中執行命令(pod 中有多個容器的情況下)
kubectl exec my-pod -c my-container -- ls
Dashboard簡介
Kubernetes Dashboard 是一個管理 Kubernetes 集群的全功能 Web 界面,旨在以 UI 的方式完全替代命令行工具(kubectl 等)。
在 Dashboard 頁面上,可以查看 Kubernetes 的集群狀態,對集群進行相關的操作。但是,Dashboard 無法圖形化展現集群度量指標信息,需要安裝 Heapser 插件。
kubernetes-dashboard搭建方式: https://www.cnblogs.com/vpc123/articles/14366619.html
監控架構圖如下

- cAdvisor,是 Kubelet 內置的容器資源收集工具。它會自動收集本機容器 CPU、內存、網絡和文件系統的資源占用情況,並對外提供 API。
- InfluxDB,是一個開源分布式時序、事件和指標數據庫。
- Grafana,是 InfluxDB 的 Dashboard,提供了強大的圖表展示功能。常和 InfluxDB 組合使用,展示圖表化的監控數據。
- Heapster,提供了整個集群的資源監控,並支持持久化數據存儲到 InfluxDB 等后端存儲。
- kube-state-metrics,除了配置 cAdvisor、Heapster、Influx、Grafana,還可以考慮部署 kube-state-metrics。kube-state-metrics 會輪詢 Kubernetes API 調度了多少個replicas、現在可用的有幾個、多少個 Pod 是 running、stopped、terminated 狀態、Po 重啟了多少次。
參數配置如下
- 獲取官方配置 yaml:
git clone https://github.com/kubernetes/heapster.git
# 查看 yaml 配置列表
ls -l deploy/kube-config/influxdb/
grafana.yaml
heapster.yaml
influxdb.yaml
- Heapster、InfluxDB、Grafana 均以 Pod 的形式啟動和運行,創建 Pod:
kubectl create -f deploy/kube-config/influxdb/
deployment.extensions/monitoring-grafana created
service/monitoring-grafana created
serviceaccount/heapster created
deployment.extensions/heapster created
service/heapster created
deployment.extensions/monitoring-influxdb created
service/monitoring-influxdb created
- 可能需要等待幾分鍾,Pod 才會處於 Running 狀態:
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
heapster-7ff8d6bf9f-ngb9p 1/1 Running 0 31m
monitoring-grafana-68b57d754-4qwjm 1/1 Running 0 31m
monitoring-influxdb-cc95575b9-5j556 1/1 Running 0 31m
- 配置完畢之后,發現 Dashboard 並沒有顯示 CPU、內存等信息,查看 Heapser 日志:
kubectl logs -f heapster-7ff8d6bf9f-ngb9p -n kube-system
1 reflector.go:190] k8s.io/heapster/metrics/util/util.go:30: Failed to list *v1.Node: nodes is forbidden: User "system:serviceaccount:kube-system:heapster" cannot list nodes at the cluster scope
- 提示缺角色,無權訪問。新增授權:
kubectl create -f deploy/kube-config/rbac/heapster-rbac.yaml
clusterrolebinding.rbac.authorization.k8s.io/heapster created
- 更新 Heapser:
kubectl replace --force -f deploy/kube-config/influxdb/heapster.yaml
- 再次查看 Dashboard,Nodes 和 Pods 中,可以非常直觀的看到 CPU 和 MEM 的使用情況。


壓力測試
Apache 提供的 ab 工具,對 Kubernetes 托管的 Nginx 服務進行簡單的壓力測試實驗。
- 安裝 Apache
********** Windows 安裝 ab *********
# 安裝 choco (管理員權限打開)
@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin
# 安裝 apache-httpd
choco install apache-httpd
********** Linux 安裝 ab *********
yum -y install httpd-tools

- 執行測試
壓測開始后,在 Dashboard 看到 CPU 和內存使用量

ab -c 125 -n 400000 http://集群地址IP:端口/
//並發請求數
Concurrency Level: 125
//整個測試持續的時間
Time taken for tests: 317.350 seconds
//完成的請求數
Complete requests: 400000
//失敗的請求數
Failed requests: 0
//吞吐率
Requests per second: 1260.44 [#/sec] (mean)
//用戶平均請求等待時間
Time per request: 99.172 [ms] (mean)
//服務器平均請求處理時間
Time per request: 0.793 [ms] (mean, across all concurrent requests)

拓展閱讀
ab是apachebench命令的縮寫。
ab的原理:ab命令會創建多個並發訪問線程,模擬多個訪問者同時對某一URL地址進行訪問。它的測試目標是基於URL的,因此,它既可以用來測試apache的負載壓力,也可以測試nginx、lighthttp、tomcat、IIS等其它Web服務器的壓力。
ab命令對發出負載的計算機要求很低,它既不會占用很高CPU,也不會占用很多內存。但卻會給目標服務器造成巨大的負載,其原理類似CC攻擊。自己測試使用也需要注意,否則一次上太多的負載。可能造成目標服務器資源耗完,嚴重時甚至導致死機。
- 壓測工具安裝
yum -y install httpd-tools
- ab 用法
ab [options] [http://]hostname[:port]/path
# ab 示例
ab -n 5000 -c 200 http://localhost/index.php
# 常見參數如下
-n :總共的請求執行數,缺省是1;
-c: 並發數,缺省是1;
-t:測試所進行的總時間,秒為單位,缺省50000s
-p:POST時的數據文件
-w: 以HTML表的格式輸出結果
執行測試用例:ab -n 1000 -c 100 -w http://localhost/index.php >>d:miss.html
