国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【博客683】k8s list請求優(yōu)化以及合理使用list以維護集群穩(wěn)定性

這篇具有很好參考價值的文章主要介紹了【博客683】k8s list請求優(yōu)化以及合理使用list以維護集群穩(wěn)定性。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

k8s list請求優(yōu)化以及合理使用list以維護集群穩(wěn)定性

apiserver/etcd List 示例分析

  • 1、LIST apis/cilium.io/v2/ciliumendpoints?limit=500&resourceVersion = 0

    這里同時傳了兩個參數(shù),但 resourceVersion=0 會導(dǎo)致 apiserver 忽略 limit=500, 所以客戶端拿到的是全量 ciliumendpoints 數(shù)據(jù)

    此時不會查etcd,因為有resourceVersion = 0,且resourceVersion = 0會忽略limit,因為limit一定要查etcd
    一種資源的全量數(shù)據(jù)可能是比較大的,需要考慮清楚是否真的需要全量數(shù)據(jù)

  • 2、LIST api/v1/pods?filedSelector=spec.nodeName%3Dnode1

    這個請求是獲取 node1 上的所有 pods(%3D 是 = 的轉(zhuǎn)義)。
    根據(jù) nodename 做過濾,給人的感覺可能是數(shù)據(jù)量不太大,但其實背后要比看上去復(fù)雜:

    這種行為是要避免的,除非對數(shù)據(jù)準確性有極高要求,特意要繞過 apiserver 緩存。
    首先,這里沒有指定 resourceVersion=0,導(dǎo)致 apiserver 跳過緩存,直接去etcd讀數(shù)據(jù);
    其次,etcd 只是 KV 存儲,沒有按 label/field 過濾功能(只處理 limit/continue),
    所以,apiserver 是從 etcd 拉全量數(shù)據(jù),然后在內(nèi)存做過濾,開銷也是很大的,后文有代碼分析。

  • 3、LISTapi/v1/pods?filedSelector=spec.nodeName%3Dnode1&resourceVersion = 0

    跟 2 的區(qū)別是加上了 resourceVersion=0,因此 apiserver 會從緩存讀數(shù)據(jù),性能會有量級的提升。
    但要注意,雖然實際上返回給客戶端的可能只有幾百 KB 到上百 MB(取決于 node 上 pod 的數(shù)量、pod 上 label 的多少等因素), 但 apiserver 需要處理的數(shù)據(jù)量可能是幾個 GB。后面會有定量分析。

以上可以看到,不同的 LIST 操作產(chǎn)生的影響是不一樣的,而客戶端看到數(shù)據(jù)還有可能只 是 apiserver/etcd 處理數(shù)據(jù)的很小一部分。如果基礎(chǔ)服務(wù)大規(guī)模啟動或重啟, 就極有可能把控制平面打爆。

判斷是否必須從 etcd 讀數(shù)據(jù):shouldDelegateList()

func shouldDelegateList(opts storage.ListOptions) bool {
    resourceVersion := opts.ResourceVersion
    pred            := opts.Predicate
    pagingEnabled   := DefaultFeatureGate.Enabled(features.APIListChunking)      // 默認是啟用的
    hasContinuation := pagingEnabled && len(pred.Continue) > 0                   // Continue 是個 token
    hasLimit        := pagingEnabled && pred.Limit > 0 && resourceVersion != "0" // 只有在 resourceVersion != "0" 的情況下,hasLimit 才有可能為 true

    // 1. 如果未指定 resourceVersion,從底層存儲(etcd)拉去數(shù)據(jù);
    // 2. 如果有 continuation,也從底層存儲拉數(shù)據(jù);
    // 3. 只有 resourceVersion != "0" 時,才會將 limit 傳給底層存儲(etcd),因為 watch cache 不支持 continuation
    return resourceVersion == "" || hasContinuation || hasLimit || opts.ResourceVersionMatch == metav1.ResourceVersionMatchExact
}
  • 問:客戶端未設(shè)置 ListOption{} 中的 ResourceVersion 字段,是否對應(yīng)到這里的 resourceVersion == “”?

    答:是的,所以第一節(jié)的 例子 會導(dǎo)致從 etcd 拉全量數(shù)據(jù)。

  • 問:客戶端設(shè)置了 limit=500&resourceVersion=0 是否會導(dǎo)致下次 hasContinuation==true?

    答:不會,resourceVersion=0 將導(dǎo)致 limit 被忽略(hasLimit 那一行代碼),也就是說, 雖然指定了 limit=500,但這個請求會返回全量數(shù)據(jù)。

  • 問:還有其他情況需要去etcd拉取嗎?

    答:apiserver cache未建立完成的時候

apiserver/etcd List 開銷分析

List 請求可以分為兩種:

  • 1、List 全量數(shù)據(jù):開銷主要花在數(shù)據(jù)傳輸;

  • 2、指定用 label 或字段(field)過濾,只需要匹配的數(shù)據(jù)。

    大部分情況下,apiserver 會用自己的緩存做過濾,這個很快,因此耗時主要花在數(shù)據(jù)傳輸;
    需要將請求轉(zhuǎn)給 etcd 的情況,
    前面已經(jīng)提到,etcd 只是 KV 存儲,并不理解 label/field 信息,因此它無法處理過濾請求。實際的過程是:apiserver 從 etcd 拉全量數(shù)據(jù),然后在內(nèi)存做過濾,再返回給客戶端。
    因此除了數(shù)據(jù)傳輸開銷(網(wǎng)絡(luò)帶寬),這種情況下還會占用大量apiserver CPU 和內(nèi)存

大規(guī)模部署時潛在的問題

用 k8s client-go 根據(jù) nodename 過濾 pod:

podList, err := Client().CoreV1().Pods(“”).List(ctx(), ListOptions{FieldSelector: “spec.nodeName=node1”})

來實際看一下它背后的數(shù)據(jù)量。以一個 4000 node,10w pod 的集群為例,全量 pod 數(shù)據(jù)量:

  • etcd 中:緊湊的非結(jié)構(gòu)化 KV 存儲,在 1GB 量級;
  • apiserver 緩存中:已經(jīng)是結(jié)構(gòu)化的 golang objects,在 2GB 量級
  • apiserver 返回:client 一般選擇默認的 json 格式接收, 也已經(jīng)是結(jié)構(gòu)化數(shù)據(jù)。全量 pod 的 json 也在 2GB 量級。

可以看到,某些請求看起來很簡單,只是客戶端一行代碼的事情,但背后的數(shù)據(jù)量是驚人的。指定按 nodeName 過濾 pod 可能只返回了 500KB 數(shù)據(jù),但 apiserver 卻需要過濾 2GB 數(shù)據(jù) —— 最壞的情況,etcd 也要跟著處理 1GB 數(shù)據(jù) (以上參數(shù)配置確實命中了最壞情況,見下文代碼分析)。

集群規(guī)模比較小的時候,這個問題可能看不出來(etcd 在 LIST 響應(yīng)延遲超過某個閾值 后才開始打印 warning 日志);規(guī)模大了之后,如果這樣的請求比較多,apiserver/etcd 肯定是扛不住的。

LIST example

為了避免客戶端庫(例如 client-go)自動幫我們設(shè)置一些參數(shù),我們直接用 curl 來測試,指定證書就行了:

$ cat curl-k8s-apiserver.sh
curl -s --cert /etc/kubernetes/pki/admin.crt --key /etc/kubernetes/pki/admin.key --cacert /etc/kubernetes/pki/ca.crt $@
使用方式:

$ ./curl-k8s-apiserver.sh "https://localhost:6443/api/v1/pods?limit=2"
{
  "kind": "PodList",
  "metadata": {
    "resourceVersion": "2127852936",
    "continue": "eyJ2IjoibWV0YS5rOHMuaW8vdjEiLCJ...",
  },
  "items": [ {pod1 data }, {pod2 data}]
}

指定 limit=2:response 將返回分頁信息(continue)

$ ./curl-k8s-apiserver.sh "https://localhost:6443/api/v1/pods?limit=2"
{
  "kind": "PodList",
  "metadata": {
    "resourceVersion": "2127852936",
    "continue": "eyJ2IjoibWV0YS5rOHMuaW8vdjEiLCJ...",
  },
  "items": [ {pod1 data }, {pod2 data}]
}

可以看到:

  • 確實返回了兩個 pod 信息,在 items[] 字段中;
  • 另外在 metadata 中返回了一個 continue 字段,客戶端下次帶上這個參數(shù),apiserver 將繼續(xù)返回剩下的內(nèi)容,直到 apiserver 不再返回 continue。

指定 limit=2&resourceVersion=0:limit=2 將被忽略,返回全量數(shù)據(jù):

$ ./curl-k8s-apiserver.sh "https://localhost:6443/api/v1/pods?limit=2&resourceVersion=0"
{
  "kind": "PodList",
  "metadata": {
    "resourceVersion": "2127852936",
    "continue": "eyJ2IjoibWV0YS5rOHMuaW8vdjEiLCJ...",
  },
  "items": [ {pod1 data }, {pod2 data}, ...]
}

items[] 里面是全量 pod 信息。

指定 spec.nodeName=node1&resourceVersion=0 vs. spec.nodeName=node1

$ ./curl-k8s-apiserver.sh "https://localhost:6443/api/v1/namespaces/default/pods?fieldSelector=spec.nodeName%3Dnode1" | jq '.items[].spec.nodeName'
"node1"
"node1"
"node1"
...

$ ./curl-k8s-apiserver.sh "https://localhost:6443/api/v1/namespaces/default/pods?fieldSelector=spec.nodeName%3Dnode1&resourceVersion=0" | jq '.items[].spec.nodeName'
"node1"
"node1"
"node1"
...

速度差異很大,用 time 測量以上兩種情況下的耗時,會發(fā)現(xiàn)對于大一些的集群,這兩種請求的響應(yīng)時間就會有明顯差異。

對于 4K nodes, 100K pods 規(guī)模的集群,以下數(shù)據(jù)供參考:

  • 不帶 resourceVersion=0(讀 etcd 并在 apiserver 過濾): 耗時 10s
  • 帶 resourceVersion=0(讀 apiserver 緩存): 耗時 0.05s

部署和調(diào)優(yōu)建議

1、List 請求默認設(shè)置 ResourceVersion=0

不設(shè)置這個參數(shù)將導(dǎo)致 apiserver 從 etcd 拉全量數(shù)據(jù)再過濾,導(dǎo)致很慢,規(guī)模大了 etcd 扛不住

因此,除非對數(shù)據(jù)準確性要求極高,必須從 etcd 拉數(shù)據(jù),否則應(yīng)該在 LIST 請求時設(shè)置 ResourceVersion=0 參數(shù), 讓 apiserver 用緩存提供服務(wù)。

如果你使用的是 client-go 的 ListWatch/informer 接口, 那它默認已經(jīng)設(shè)置了 ResourceVersion=0。

2、優(yōu)先使用 namespaced API

如果要 LIST 的資源在單個或少數(shù)幾個 namespace,考慮使用 namespaced API:

Namespaced API: /api/v1/namespaces//pods?query=xxx

Un-namespaced API: /api/v1/pods?query=xxx

3、Restart backoff

對于 per-node 部署的基礎(chǔ)服務(wù),例如 kubelet、cilium-agent、daemonsets,需要 通過有效的 restart backoff 降低大面積重啟時對控制平面的壓力。

例如,同時掛掉后,每分鐘重啟的 agent 數(shù)量不超過集群規(guī)模的 10%(可配置,或可自動計算)。

4、優(yōu)先通過 label/field selector 在服務(wù)端做過濾

如果需要緩存某些資源并監(jiān)聽變動,那需要使用 ListWatch 機制,將數(shù)據(jù)拉到本地,業(yè)務(wù)邏輯根據(jù)需要自己從 local cache 過濾。這是 client-go 的 ListWatch/informer 機制。

但如果只是一次性的 LIST 操作,并且有篩選條件,例如前面提到的根據(jù) nodename 過濾 pod 的例子, 那顯然應(yīng)該通過設(shè)置 label 或字段過濾器,讓 apiserver 幫我們把數(shù)據(jù)過濾出來。LIST 10w pods 需要幾十秒(大部分時間花在數(shù)據(jù)傳輸上,同時也占用 apiserver 大量 CPU/BW/IO), 而如果只需要本機上的 pod,那設(shè)置 nodeName=node1 之后,LIST 可能只需要 0.05s 就能返回結(jié)果。
另外非常重要的一點時,不要忘記在請求中同時帶上resourceVersion=0。

  • Label selector
    在 apiserver 內(nèi)存過濾。

  • Field selector
    在 apiserver 內(nèi)存過濾。

  • Namespace selector
    etcd 中 namespace 是前綴的一部分,因此能指定 namespace 過濾資源,速度比不是前綴的 selector 快很多。

5、配套基礎(chǔ)設(shè)施(監(jiān)控、告警等)

以上分析可以看成,client 的單個請求可能只返回幾百 KB 的數(shù)據(jù),但 apiserver(更糟糕的情況,etcd)需要處理上 GB 的數(shù)據(jù)。因此,應(yīng)該極力避免基礎(chǔ)服務(wù)的大規(guī)模重啟,為此需要在監(jiān)控、告警上做的盡量完善。

  • 使用獨立 ServiceAccount
    每個基礎(chǔ)服務(wù)(例如 kubelet、cilium-agent 等),以及對 apiserver 有大量 LIST 操作的各種 operator, 都使用各自獨立的 SA, 這樣便于 apiserver 區(qū)分請求來源,對監(jiān)控、排障和服務(wù)端限流都非常有用。

  • Liveness 監(jiān)控告警
    基礎(chǔ)服務(wù)必須覆蓋到 liveness 監(jiān)控。

6、Get 請求:GetOptions{}

基本原理與 ListOption{} 一樣,不設(shè)置 ResourceVersion=0 會導(dǎo)致 apiserver 去 etcd 拿數(shù)據(jù),應(yīng)該盡量避免。文章來源地址http://www.zghlxwxcb.cn/news/detail-609632.html

到了這里,關(guān)于【博客683】k8s list請求優(yōu)化以及合理使用list以維護集群穩(wěn)定性的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Kubernetes(K8S)快速搭建typecho個人博客

    Kubernetes(K8S)快速搭建typecho個人博客

    Kubernetes(K8S)快速搭建typecho個人博客 K8S集群環(huán)境,搭建教程參考騰訊云Lighthouse組建跨地域Kubernetes集群 K8S集群面板,搭建教程參考Kubernetes集群管理面板的安裝及使用 - 青陽のblog-一個計算機愛好者的個人博客 (hipyt.cn) 如果沒有集群或者服務(wù)器不夠可以通過傳送門新購。 騰訊

    2024年02月04日
    瀏覽(42)
  • Kubeadm - K8S1.20 - 高可用集群部署(博客)

    1.系統(tǒng)設(shè)置 注意事項: master節(jié)點cpu核心數(shù)要求大于2 ●最新的版本不一定好,但相對于舊版本,核心功能穩(wěn)定,但新增功能、接口相對不穩(wěn) ●學(xué)會一個版本的 高可用部署,其他版本操作都差不多 ●宿主機盡量升級到CentOS 7.9 ●內(nèi)核kernel升級到 4.19+ 這種穩(wěn)定的內(nèi)核 ●部署k8

    2024年02月05日
    瀏覽(23)
  • k8s 操作命令(合集List)

    一、K8S最常用命令如下: 1、獲取pod信息:kubectl get pod 2、查看指定pod的日志信息:kubectl logs -f --tail(最后多少行) 500 podName(pod名) 3、查看pod的描述信息:kubectl describe pod podName 4、查看節(jié)點信息:kubectl get nodes 5、查看pod的詳細信息,以yaml或者json格式展示:kubectl get pods -o yaml、

    2024年02月12日
    瀏覽(12)
  • 【博客682】k8s apiserver bookmarks機制以更高效檢測變更

    【博客682】k8s apiserver bookmarks機制以更高效檢測變更

    List-Watch 是kubernetes中server和client通信的最核心的機制, 比如說api-server監(jiān)聽etcd, kubelet監(jiān)聽api-server, scheduler監(jiān)聽api-server等等,其實其他模塊監(jiān)聽api-server相當(dāng)于監(jiān)聽etcd,因為在k8s的設(shè)計中,只有api-server能跟etcd通信,其他模塊需要etcd的數(shù)據(jù)就只好監(jiān)聽api-server了。 etcd默認保留

    2024年02月15日
    瀏覽(25)
  • docker在k8s容器中的作用,以及docker的底層原理,以及k8s的常用命令

    ? ? Docker的設(shè)計思想就是創(chuàng)建軟件程序可移植性的輕量級容器,讓其可以在任何安裝了Docker的機器上,不用關(guān)心底層操作系統(tǒng),就可以運行開發(fā)程序,就像集裝箱一樣使用。 Docker 是一個開源的應(yīng)用容器引擎,基于 Go 語言 并遵從Apache2.0協(xié)議開源。 Docker 可以讓開發(fā)者打包他們

    2024年04月27日
    瀏覽(35)
  • 云原生之深入解析K8S的請求和限制

    云原生之深入解析K8S的請求和限制

    在 Kubernetes 中使用容器時,了解涉及的資源是什么以及為何需要它們很重要。有些進程比其它進程需要更多的 CPU 或內(nèi)存,這很關(guān)鍵,永遠不應(yīng)該讓進程饑餓,知道了這一點,那么應(yīng)該正確配置容器和 Pod,以便充分利用兩者。 使用 Kubernetes 時,限制和請求是重要的設(shè)置。Ku

    2024年02月13日
    瀏覽(96)
  • K8s技術(shù)全景:架構(gòu)、應(yīng)用與優(yōu)化

    K8s技術(shù)全景:架構(gòu)、應(yīng)用與優(yōu)化

    本文深入探討了Kubernetes(K8s)的關(guān)鍵方面,包括其架構(gòu)、容器編排、網(wǎng)絡(luò)與存儲管理、安全與合規(guī)、高可用性、災(zāi)難恢復(fù)以及監(jiān)控與日志系統(tǒng)。 關(guān)注【TechLeadCloud】,分享互聯(lián)網(wǎng)架構(gòu)、云服務(wù)技術(shù)的全維度知識。作者擁有10+年互聯(lián)網(wǎng)服務(wù)架構(gòu)、AI產(chǎn)品研發(fā)經(jīng)驗、團隊管理經(jīng)驗

    2024年04月08日
    瀏覽(25)
  • Gitlab+Jenkins+Docker+Harbor+K8s集群搭建CICD平臺(持續(xù)集成部署Hexo博客Demo)

    Gitlab+Jenkins+Docker+Harbor+K8s集群搭建CICD平臺(持續(xù)集成部署Hexo博客Demo)

    目錄 涉及內(nèi)容: 一、CICD服務(wù)器環(huán)境搭建 1、docker 環(huán)境安裝 (1)、拉取鏡像,啟動并設(shè)置開機自啟 (2)、配置docker加速器 2、安裝并配置GitLab (1)、創(chuàng)建共享卷目錄 (2)、創(chuàng)建 gitlab 容器 (3)、關(guān)閉容器修改配置文件 (4)、修改完配置文件之后。直接啟動容器 (5)、相關(guān)

    2024年03月15日
    瀏覽(37)
  • 完全清理k8s以及網(wǎng)絡(luò)插件

    在卸載K8s組件前,先在所有節(jié)點執(zhí)行kubeadm reset命令,清空K8s集群設(shè)置 使用一開始創(chuàng)建pod時同樣的yaml文件 檢查所有節(jié)點上的網(wǎng)絡(luò),看看是否存在Tunl0 刪除Tunl0 直接清空所有鏡像即可,如果有需要保留的鏡像,則選擇清空

    2024年02月11日
    瀏覽(16)
  • 6 張配圖通俗易懂說透 K8S 請求和限制

    6 張配圖通俗易懂說透 K8S 請求和限制

    在 Kubernetes 中使用容器時,了解涉及的資源是什么以及為何需要它們很重要。有些進程比其他進程需要更多的 CPU 或內(nèi)存。這很關(guān)鍵,永遠不應(yīng)該讓進程挨餓。知道了這一點,我們應(yīng)該正確配置容器和 Pod,以便充分利用兩者。 使用 Kubernetes 時,限制和請求是重要的設(shè)置。本文

    2024年02月09日
    瀏覽(13)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包