免费国产精品自在自线-91精品国产色综合久久久浪潮-99热久久免费频精品-国产精品国模在线观看-久久亚洲国产精品成人?V秋霞-久久国产一级A片免费播放-亚洲国产欧洲综合97久久-久久国产白嫩美女呻吟高潮

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運營的一線實戰(zhàn)洞察。

client-go實戰(zhàn)指南:Informer、WorkQueue與控制器開發(fā)避坑要點

client-go實戰(zhàn)指南:Informer、WorkQueue與控制器開發(fā)避坑要點 如果你寫過Operator、Controller或者在公司里維護過Kubernetes平臺的自動化工具那client-go大概率是你繞不開的第一個依賴。它是Kubernetes官方維護的Go語言客戶端庫kubectl、kube-controller-manager里的核心組件以及社區(qū)里大量控制器、調(diào)度器、發(fā)布系統(tǒng)底層都是靠它和API Server打交道。這篇是“Kubernetes組件合集”的第三篇我不會把文檔里能查到的API再抄一遍而是從一個實際寫控制器的角度把這些年用client-go踩過的關(guān)鍵點一次講清楚。讀完你至少能明白Informer為什么這樣設(shè)計、初始化客戶端時哪些配置必須調(diào)、以及企業(yè)級項目里哪些坑是真正會遇到的。1. client-go在Kubernetes生態(tài)中的定位為什么所有二次開發(fā)都繞不開它1.1 它到底解決了什么問題很多人剛開始接觸Kubernetes二次開發(fā)時第一反應(yīng)是“不就是調(diào)API嗎我用HTTP請求直接訪問API Server不就行了”理論上確實可以但真的上手你會抓狂API路徑版本協(xié)商、token或證書鑒權(quán)、對象序列化和反序列化、分頁拉取、watch長連接重連、本地緩存一致性……這些工作散落在一個資源一個資源的交互細(xì)節(jié)里你自己實現(xiàn)一遍基本相當(dāng)于把客戶端框架重新造一次輪子。client-go的價值就在這里它把“和Kubernetes API Server安全通信”這件事封裝成了開箱即用的Go包。你寫代碼時面對的是kubernetes.NewForConfig、CoreV1().Pods(ns).List(...)這種很直接的接口底層那一堆鑒權(quán)、限流、重試、緩存邏輯全部隱藏掉了。kubectl本身就是client-go最典型的例子你每天敲的kubectl get pods本質(zhì)就是client-go客戶端發(fā)起的一次List調(diào)用。除了省事client-go更大的價值是它提供了Informer這套“監(jiān)聽緩存”機制。Kubernetes控制面是一個基于聲明式狀態(tài)機的系統(tǒng)任何對象的變化都會通過API Server以增量事件的方式廣播出去。如果你不用Informer而是每隔幾秒全量拉一次資源小規(guī)模集群還能將就一旦node數(shù)量、pod數(shù)量上來對API Server的壓力是非??植赖目刂破鞅旧淼捻憫?yīng)延遲也會被拉到秒級甚至分鐘級。Informer就是為此設(shè)計的一次全量List建立基準(zhǔn)之后靠Watch持續(xù)接收增量變化對象在本地緩存里維護控制器讀自己的緩存就能拿到最新狀態(tài)不需要反復(fù)打API Server。1.2 核心模塊掃一遍別被client-go龐大命名空間嚇到client-go的代碼量很大剛開始看確實容易迷路。我建議按下面這個分層來理解從上到下依次是抽象程度和靈活度遞增日常開發(fā)90%時間其實只跟中間兩層打交道。模塊典型對象作用適合場景RESTClientrest.RESTClient最底層的HTTP客戶端封裝直接操作URL、Method、Body需要自定義請求格式、臨時訪問非標(biāo)準(zhǔn)接口Clientsetkubernetes.Clientset按API Group組織起來的一套強類型客戶端內(nèi)置Pod、Deployment、Service等所有內(nèi)置資源的訪問方法絕大多數(shù)標(biāo)準(zhǔn)資源操作寫控制器必備DynamicClientdynamic.Interface操作Unstructured對象不用預(yù)先知道Go類型處理自定義CRD、搭建通用巡檢平臺、動態(tài)編排DiscoveryClientdiscovery.DiscoveryClient查詢集群支持哪些APIGroup、資源、版本做版本兼容、資源探測、API清單導(dǎo)出Informer/ListWatchercache.SharedIndexInformer監(jiān)聽資源變化維護本地緩存觸發(fā)事件回調(diào)控制器核心幾乎所有事件驅(qū)動邏輯都依賴它WorkQueueworkqueue.RateLimitingInterface帶限速、去重、失敗重試的工作隊列事件回調(diào)后的異步處理防止事件風(fēng)暴打崩控制器leaderelectiontools/leaderelection基于Lease實現(xiàn)選主多副本控制器保證同時只有一個實例在處理這套設(shè)計其實很像一個公司的內(nèi)部結(jié)構(gòu)DiscoveryClient是前臺負(fù)責(zé)告訴你“公司里有哪些部門”Clientset是標(biāo)準(zhǔn)業(yè)務(wù)接口你按部門去辦事就行DynamicClient是“臨時工窗口”不管什么類型的單子都能接Informer相當(dāng)于一個企業(yè)內(nèi)部的信息推送系統(tǒng)訂閱了就有新消息自動送到桌上。1.3 Informer為什么是client-go的靈魂假設(shè)你寫了一個控制器要保證集群里的Deployment副本數(shù)始終等于期望值。最原始的做法是每分鐘全量List一次所有Deployment和期望值比較有差別就去調(diào)。這種輪詢模式有三個明顯的毛病第一集群大了反復(fù)全量List對API Server是巨大負(fù)擔(dān)第二從變化發(fā)生到你感知到變化最壞情況有一個輪詢周期控制面響應(yīng)很遲鈍第三事件一多自己的控制器也無從判斷先后順序。Informer把這三個問題一次性解決了。它首次啟動時會做一次全量List拿到所有對象的完整數(shù)據(jù)和當(dāng)前resourceVersion之后建立一條Watch長連接只接收從該版本開始發(fā)生的增量變化。變化事件進入本地緩存后API Server壓力被降到最低控制器對事件的感知幾乎是實時的而且本地的狀態(tài)始終是“按事件順序回放出來的結(jié)果”一致性也有保障。真正用Informer時你會發(fā)現(xiàn)一個有意思的特性它的回調(diào)函數(shù)接收到對象后通常不是立刻去干活而是把對象key塞進WorkQueue就走。這背后是一個非常重要的設(shè)計哲學(xué)——寫控制器時事件處理邏輯和業(yè)務(wù)處理邏輯必須解耦。Informer回調(diào)跑在它自己的goroutine里如果你把耗時操作直接寫在回調(diào)函數(shù)里一個Pod同步卡住后面所有對象的處理節(jié)奏都會被拖住。事件進隊列、業(yè)務(wù)邏輯由worker從隊列里取出來慢慢消化各管各的這也是client-go官方示例和工作隊列入門的核心套路。2. 把Informer拆開了看ListWatch、緩存與WorkQueue是怎么協(xié)同的2.1 先搞清楚ListWatch的發(fā)起細(xì)節(jié)Informer對外表現(xiàn)就是一個“對象變化的訂閱器”但實際構(gòu)造它的時候你需要給它一個數(shù)據(jù)源。這個數(shù)據(jù)源在client-go里叫ListWatch它包含了兩個動作先全量列表再持續(xù)監(jiān)聽。標(biāo)準(zhǔn)寫法長這樣watcher : cache.NewListWatchFromClient( clientset.CoreV1().RESTClient(), pods, v1.NamespaceAll, fields.Everything(), ) informer : cache.NewSharedIndexInformer( watcher, corev1.Pod{}, time.Minute, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, )這里有幾個細(xì)節(jié)值得注意。第一NewListWatchFromClient的第一個參數(shù)傳的是RESTClient不是整個Clientset因為ListWatch需要直接和/api/v1/pods這類REST端點打交道。第二第三個參數(shù)傳NamespaceAll就是要監(jiān)聽所有命名空間如果你只關(guān)心某個命名空間這里可以填具體名字API Server返回的內(nèi)容會少很多。第三最后的fields.Everything()表示不按字段過濾你也可以改成fields.ParseSelector(status.phaseRunning)但我不建議在Informer層做太細(xì)的字段過濾因為你漏掉的事件后續(xù)想補會很麻煩。Informer跑起來之后內(nèi)部會有一個Reflector循環(huán)在做這樣的事從上一次List得到的resourceVersion開始Watch如果連接因為超時或其他原因中斷它會重新發(fā)起List然后接著Watch。整個過程是自動的你唯一需要理解的是watch斷掉之后重新List用的是“當(dāng)前最新版本”不是斷線那一刻的版本這意味著斷線期間發(fā)生的部分對象變化可能會被覆蓋式地重新同步這正是為什么事件回調(diào)一定要寫成冪等的原因。2.2 三層結(jié)構(gòu)Reflector、DeltaFIFO、IndexerSharedIndexInformer內(nèi)部說白了是三段式流水線。最外層是Reflector它負(fù)責(zé)向API Server發(fā)起List和Watch把拿到的對象事件封裝成watch.Event。事件進入第二層DeltaFIFO——這個名字很直白它是一個隊列隊列里存的不是某個對象而是“對象變化類型”的組合比如Pod Added、Pod Updated、Pod Deleted。DeltaFIFO的special之處在于它對同一個對象支持累積多條Delta再統(tǒng)一消費比如對象在短時間內(nèi)連續(xù)變了好幾次隊列會把這幾個變化合并成一條最新數(shù)據(jù)再交給下游避免處理線程被高頻小變化淹沒。第三層是Indexer它是真正的本地緩存。Indexer本質(zhì)上就是一個帶索引的內(nèi)存mapkey是namespace/namevalue是對象的完整結(jié)構(gòu)??刂破鞔a里常見的informer.GetIndexer().GetByKey(key)查的就是這一層緩存。它還支持自定義索引比如你想按label快速查對象可以注冊一個索引函數(shù)。用一個貼近生活的類比Reflector是外勤負(fù)責(zé)在外面收集情報DeltaFIFO是帶排序功能的收件箱外勤把情報單據(jù)一張張貼進收件箱Indexer是辦公室里的主檔案柜每次處理完最新情報就把檔案柜更新一遍??刂破鞑闄n案的時候永遠(yuǎn)查的是這個主檔案柜不用每次再打電話問外面。2.3 WorkQueue為什么你的事件回調(diào)里不應(yīng)該直接干活新手最容易犯的錯是直接在AddFunc、UpdateFunc里寫業(yè)務(wù)邏輯。我在前面的章節(jié)提過這個問題這里再展開說說隊列的價值。workqueue.RateLimitingInterface是client-go專門為控制器場景定制的隊列它有三個核心特性。第一它可以自動去重同一個key已經(jīng)排在隊列里時不會重復(fù)入隊避免重復(fù)消費第二它支持指數(shù)退避重試處理失敗后重新入隊重試間隔會從1秒、2秒、4秒這樣遞增而不是無限死循環(huán)第三它可以配合多個worker并發(fā)消費處理好鎖和刷新的問題。典型寫法是這樣的func (c *Controller) processNextItem() bool { key, quit : c.queue.Get() if quit { return false } defer c.queue.Done(key) err : c.syncHandler(key.(string)) if err nil { // 處理成功清掉該key的重試計數(shù) c.queue.Forget(key) return true } // 處理失敗判斷是否超過最大重試次數(shù) if c.queue.NumRequeues(key) c.maxRetries { c.queue.AddRateLimited(key) return true } c.queue.Forget(key) utilruntime.HandleError(fmt.Errorf(dropping key %s after max retries: %v, key, err)) return true }這種模式幾乎成了官方控制器示例的標(biāo)準(zhǔn)骨架。它的好處是不管上游事件多密集worker永遠(yuǎn)按自己的節(jié)奏消化任務(wù)某個對象處理失敗了也不會影響其他對象重試次數(shù)有上限不會因為一個不可恢復(fù)的錯誤把控制器拖垮。寫控制器時一定要把“監(jiān)聽到變化”和“處理這個變化”拆成兩個階段這個習(xí)慣能救你很多次。2.4 多handler的注冊和Resync機制Informer允許同時注冊多個事件回調(diào)比如你既要在Pod變化時更新監(jiān)控緩存又要在Pod變化時觸發(fā)告警邏輯可以調(diào)用兩次AddEventHandler。多個回調(diào)之間是串行執(zhí)行的所以依然要遵守“回調(diào)里不做重活”的原則。還有一個容易忽略的參數(shù)NewSharedIndexInformer的第三個參數(shù)是resyncPeriod。如果你傳了一個非零值比如60秒Informer會每隔一段時間把緩存里的所有對象重新觸發(fā)一次Update回調(diào)。這個機制不是為了刷新數(shù)據(jù)——數(shù)據(jù)本來就在本地緩存里主要用途是讓控制器定期“自檢”一遍彌補某些事件在watch過程中可能丟失的遺漏。但resync會帶來一個副作用你的Update回調(diào)會頻繁被調(diào)用一些明明沒變化的資源也會進隊列。社區(qū)里很多控制器會在UpdateFunc里判斷一下resourceVersion或者關(guān)鍵字段是否真的變了沒變就直接返回這是應(yīng)對resync最有效的辦法。如果你完全不需要resync傳0就能關(guān)掉。3. 手寫第一個client-go控制器初始化、事件監(jiān)聽、優(yōu)雅退出3.1 環(huán)境準(zhǔn)備先把依賴版本對齊否則后面全是坑寫client-go代碼前第一件事不是敲代碼而是確定版本。client-go的版本體系和Kubernetes本身嚴(yán)格對齊Kubernetes v1.27對應(yīng)client-go v0.27.xv1.28對應(yīng)v0.28.x。你在go.mod里同時引入k8s.io/client-go、k8s.io/api、k8s.io/apimachinery時這三者的版本必須保持一致不然編譯期就會出現(xiàn)類型不匹配、scheme注冊不到資源等詭異問題。比較省心的做法是讓Go自動選擇兼容版本。先初始化module再直接加依賴go mod init mycontroller go get k8s.io/client-gov0.27.4 go get k8s.io/apiv0.27.4 go get k8s.io/apimachineryv0.27.4如果自己的集群版本高一些比如1.29client-go版本可以稍微低一點但最低不要低過兩個minor版本跨太多版本很可能遇到部分新API字段不解析、watch端點404之類的問題。最穩(wěn)妥的做法是讓client-go的版本和集群API Server的版本完全對應(yīng)少一點花活。3.2 三種初始化客戶端的方式別只會一種client-go官方支持三種定位config的場景在集群內(nèi)運行、使用kubeconfig文件、直接代碼構(gòu)造rest.Config。實際寫控制器時這三種往往都要遇到。集群內(nèi)運行是最常見的因為你的控制器最終會作為Pod部署到Kubernetes里這時使用rest.InClusterConfig()就能自動加載ServiceAccount的token和CA證書config, err : rest.InClusterConfig() if err ! nil { log.Fatalf(in-cluster config failed: %v, err) }本地調(diào)試時InClusterConfig會失敗這時要回退到kubeconfigkubeconfig : filepath.Join(home, .kube, config) config, err : clientcmd.BuildConfigFromFlags(, kubeconfig) if err ! nil { log.Fatalf(build config from kubeconfig failed: %v, err) }但無論哪種方式拿到的*rest.Config在真正創(chuàng)建客戶端之前我強烈建議你做兩件事。第一設(shè)置config.UserAgent比如my-controller/v0.1.0這樣出現(xiàn)問題查API Server審計日志時能一眼看出是哪個客戶端在調(diào)用。第二關(guān)注config.QPS和config.Burst這兩個字段控制著客戶端每秒最多發(fā)多少請求、突發(fā)情況下最多積累多少個請求。默認(rèn)值非常保守只有5和10對控制器這種有Informer在持續(xù)監(jiān)聽的程序來說太不夠用了建議至少調(diào)到50和100后面我會專門講這個問題。創(chuàng)建客戶端本身很簡單clientset, err : kubernetes.NewForConfig(config) if err ! nil { log.Fatalf(create kubernetes client failed: %v, err) }NewForConfig做的一件事很關(guān)鍵它會用你傳入的config構(gòu)造一個RESTClient并把所有內(nèi)置資源的序列化器、版本轉(zhuǎn)換器注冊好。這就是為什么你在Cilentset上直接調(diào)用CoreV1().Pods()就能拿到強類型對象不用自己手動解析JSON。3.3 實現(xiàn)核心事件循環(huán)從Informer回調(diào)到業(yè)務(wù)處理有了客戶端下一步就是構(gòu)造Informer、注冊回調(diào)、啟動處理循環(huán)。這里我給一個可以直接跑的骨架以監(jiān)聽Pod為例。queue : workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) informer : cache.NewSharedIndexInformer( cache.NewListWatchFromClient(clientset.CoreV1().RESTClient(), pods, v1.NamespaceAll, fields.Everything()), corev1.Pod{}, 0, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { key, err : cache.MetaNamespaceKeyFunc(obj) if err nil { queue.Add(key) } }, UpdateFunc: func(oldObj, newObj interface{}) { key, err : cache.MetaNamespaceKeyFunc(newObj) if err nil { queue.Add(key) } }, DeleteFunc: func(obj interface{}) { key, err : cache.DeletionHandlingMetaNamespaceKeyFunc(obj) if err nil { queue.Add(key) } }, })注意DeleteFunc這里用的是cache.DeletionHandlingMetaNamespaceKeyFunc而不是普通的MetaNamespaceKeyFunc。原因很微妙Delete事件里拿到的對象可能因為已經(jīng)不在緩存中某些字段是空的甚至可能是cache.DeletedFinalStateUnknown包裝過的對象直接用普通函數(shù)容易panic或只能拿到殘缺key。這個是官方文檔里不顯眼但實際作用非常大的細(xì)節(jié)。處理循環(huán)的worker部分核心邏輯就是前面提到的processNextItem。真正干活時建議把業(yè)務(wù)處理收斂到一個方法里func (c *Controller) syncPod(key string) error { ns, name, err : cache.SplitMetaNamespaceKey(key) if err ! nil { return err } pod, exists, err : c.informer.GetStore().GetByKey(key) if err ! nil { return err } if !exists { // 對象已刪除做清理工作 return nil } p : pod.(*corev1.Pod) // 在這里寫你的業(yè)務(wù)邏輯比如檢查注解、調(diào)用API更新狀態(tài)等 return nil }這里的“從緩存讀對象”而不是“用Clientset直接Get對象”是Informer模式的精髓。你通過GetByKey拿到的數(shù)據(jù)永遠(yuǎn)與Informer內(nèi)部緩存保持一致而且不消耗API Server配額。只有在需要主動修改對象時才會用Clientset發(fā)起寫請求。3.4 讓進程體面退出context、WaitGroup與多worker并發(fā)一個生產(chǎn)級控制器不能只有Informer還必須能優(yōu)雅關(guān)閉。Kubernetes停止Pod時默認(rèn)發(fā)SIGTERM信號如果你不做任何處理Informer的watch連接可能來不及關(guān)閉隊列里的任務(wù)也來不及清空留下一堆半成品狀態(tài)。標(biāo)準(zhǔn)的做法是用context.Context控制整個生命周期再用sync.WaitGroup等待所有worker退出ctx, cancel : context.WithCancel(context.Background()) defer cancel() stopCh : ctx.Done() go informer.Run(stopCh) if !cache.WaitForCacheSync(stopCh, informer.HasSynced) { log.Fatal(failed to wait for caches to sync) } var wg sync.WaitGroup for i : 0; i runtime.NumCPU(); i { wg.Add(1) go func() { defer wg.Done() for c.processNextItem() { } }() } go func() { -stopCh queue.ShutDown() }() sigCh : make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) -sigCh cancel() wg.Wait()cache.WaitForCacheSync這行很重要。它確保Informer完成首次全量List并同步完所有對象之后才開始消費隊列里的任務(wù)。如果不做這一步啟動初期緩存是空的worker消費到的事件可能因為對象還沒進緩存而被錯誤地認(rèn)為“對象不存在”造成不必要的誤刪除操作。多worker的意義在于提高消費吞吐量。Informer回調(diào)把事件塞進隊列的速度很快如果只有一個worker慢慢處理大規(guī)模節(jié)點故障時隊列會急劇膨脹。用runtime.NumCPU()起多個worker是一種簡單有效的擴容方式但要注意你的業(yè)務(wù)邏輯對同一個對象的并發(fā)處理是否安全。如果某個對象需要在多個worker之間串行處理最好在syncHandler內(nèi)部對key加一把帶namespace/name粒度的鎖。3.5 企業(yè)多副本部署逃不開的一課Leader Election單副本控制器部署簡單但問題很多升級時會有幾分鐘空窗期節(jié)點故障時整個控制器直接不可用。生產(chǎn)環(huán)境一般都會給控制器開多個副本此時所有副本同時監(jiān)聽事件、同時處理就會產(chǎn)生重復(fù)操作甚至互相干擾。解決辦法是選主讓同一時刻只有一個副本真正執(zhí)行業(yè)務(wù)邏輯其他副本只是熱備。client-go自帶leaderelection包默認(rèn)的鎖資源是Leasecoordination.k8s.io/v1。一個最小實現(xiàn)大概是這樣lock : resourcelock.LeaseLock{ LeaseMeta: metav1.ObjectMeta{ Name: my-controller, Namespace: kube-system, }, Client: clientset.CoordinationV1(), LockConfig: resourcelock.ResourceLockConfig{ Identity: hostname, }, } leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{ Lock: lock, ReleaseOnCancel: true, LeaseDuration: 15 * time.Second, RenewDeadline: 10 * time.Second, RetryPeriod: 2 * time.Second, Callbacks: leaderelection.LeaderCallbacks{ OnStartedLeading: func(ctx context.Context) { // 這里才啟動你的控制器主循環(huán) }, OnStoppedLeading: func() { log.Fatal(lost leadership, exiting) }, }, })幾個參數(shù)值得解釋。LeaseDuration是租約時長超過這個時間沒續(xù)租其他副本就可以搶主RenewDeadline是續(xù)租超時超過這個時間還沒續(xù)上當(dāng)前Leader會被認(rèn)為失聯(lián)RetryPeriod是續(xù)租的重試間隔。三者的合理比例大約是5:3:1社區(qū)普遍認(rèn)可這個經(jīng)驗值。ReleaseOnCancel設(shè)成true是讓Leader在退讓時主動釋放Lease這樣下一個Leader能立刻接管不用干等一個LeaseDuration。實際踩坑點OnStartedLeading回調(diào)里必須阻塞不能直接返回否則Leader立刻失去資格如果你用的是client-go的舊版本ReleaseOnCancel可能還不存在需要自己調(diào)用lock.Release()來釋放。4. 進階玩法DynamicClient、代碼生成與controller-runtime怎么選4.1 處理不確定的GVKDynamicClient什么時候上場Clientset雖然好但它只認(rèn)內(nèi)置資源。你一旦開始處理自定義CRD或者做一個“什么資源都能管”的通用平臺Clientset就用不上了。這時候需要DynamicClient它操作的是unstructured.Unstructured一種把任意API對象的字段全部塞進map[string]interface{}的通用載體。使用DynamicClient的第一件事是拿到目標(biāo)資源的GVRGroup/Version/Resource而不是GVKGroup/Version/Kind。GVR指的是REST資源路徑比如apps/v1組下的deploymentsGVK指的是類型比如Deployment。你寫代碼時經(jīng)常要先把Kind轉(zhuǎn)成Resource有個小技巧是直接用API Server的DiscoveryClient去查。gvr : schema.GroupVersionResource{ Group: apps, Version: v1, Resource: deployments, } list, err : dynamicClient.Resource(gvr).Namespace(default).List(ctx, metav1.ListOptions{}) if err ! nil { return err } for _, obj : range list.Items { name, _ : obj.GetName() replicas, found, _ : unstructured.NestedInt64(obj.Object, spec, replicas) if found { fmt.Printf(deployment %s replicas%d\n, name, replicas) } }unstructured.NestedInt64這類輔助函數(shù)非常常用因為嵌套字段從map里取出來的類型永遠(yuǎn)是interface{}不轉(zhuǎn)一下根本沒法參與運算。還有一個更省事的辦法把Unstructured對象序列化成JSON再用json.Unmarshal進一個自定義類型或者用runtime.DefaultUnstructuredConverter.FromUnstructured幫你轉(zhuǎn)。DynamicClient的靈活性是用類型安全換來的所以能用Clientset的地方還是優(yōu)先用Clientset。4.2 別手動寫CRD客戶端了code-generator用起來如果你開發(fā)的CRD需要長期維護比如一個自定義的Monitor資源你可以像Kubernetes內(nèi)置資源一樣用./clientset、./informers、./listers生成一套強類型客戶端。這個能力來自k8s.io/code-generator庫它不是運行時依賴而是構(gòu)建時一次性執(zhí)行的代碼生成工具。代碼生成的觸發(fā)方式是在類型定義上寫注釋標(biāo)簽。比如你的類型長這樣// genclient // genclient:nonNamespaced // k8s:deepcopy-gen:interfacesk8s.io/apimachinery/pkg/runtime.Object type Monitor struct { metav1.TypeMeta json:,inline metav1.ObjectMeta json:metadata,omitempty Spec MonitorSpec json:spec,omitempty }然后在項目里跑一下deepcopy-gen、client-gen、informer-gen、lister-gen就能自動產(chǎn)出對應(yīng)的代碼。很多項目把這套生成命令寫進hack/update-codegen.sh配合generate-groups.sh腳本一鍵執(zhí)行。到底要不要用代碼生成我的建議是如果CRD數(shù)量少、操作簡單DynamicClient足夠如果CRD是你的核心產(chǎn)品你需要像操作內(nèi)置資源一樣舒服地讀寫、監(jiān)聽它那生成一套強類型客戶端非常值。生成的Informer和Lister會幫你在類型層面避免大多Unstructured才有的低級錯誤開發(fā)體驗提升非常明顯。4.3 controller-runtime和client-go到底是什么關(guān)系現(xiàn)在社區(qū)寫Operator首選的框架往往是controller-runtime也就是kubebuilder/operator-sdk底層依賴的那個庫。你可能會疑惑我已經(jīng)學(xué)了client-go為什么還要學(xué)一個新框架其實controller-runtime沒有拋棄client-go它是在client-go之上做了一層更高階的封裝。它把Informer、WorkQueue、LeaderElection這些細(xì)節(jié)隱藏到Manager和Reconciler的抽象后面你只需要實現(xiàn)一個Reconcile(ctx, req ctrl.Request)方法框架自動幫你完成事件監(jiān)聽、隊列調(diào)度、失敗重試、優(yōu)雅退出等一大堆瑣事。維度client-gocontroller-runtime抽象程度底層控制力強高層API友好上手成本高要理解Informer、WorkQueue等概念相對低跟著腳手架走就行靈活性可以任意定制細(xì)節(jié)框架約定了一些最佳實踐定制復(fù)雜行為反而麻煩適合場景寫自定義控制器、深度定制邏輯寫標(biāo)準(zhǔn)Operator、CRD控制器我的個人建議是新手入門不要迷信框架先用client-go手寫一個簡單控制器把Informer、隊列、LeaderElection這些機制親手跑通再去用controller-runtime你會對IDE自動生成的那堆代碼有完全不一樣的理解。反過來如果你一上來就只會controller-runtime而完全不懂底層出了問題往往無從下手比如遇到事件不觸發(fā)、緩存不同步你連日志里Informer在報什么錯都看不明白。4.4 一個容易被忽略的場景Device Plugin周邊也需要client-go很多做異構(gòu)硬件接入的同學(xué)會接觸Kubernetes Device Plugin機制比如GPU、NPU、FPGA的節(jié)點資源上報。Device Plugin本身是kubelet通過unix socket用gRPC通信的但它并不是閉環(huán)。設(shè)備插件要報告設(shè)備數(shù)量、更新設(shè)備健康狀態(tài)、配合調(diào)度器展示資源通常還會有一到多個配套控制器或輔助組件在集群里運行這時候就離不開client-go了。舉個例子一個GPU設(shè)備插件在節(jié)點上啟動后需要把節(jié)點上可用GPU數(shù)量寫進Node.Status.Capacity這個過程實際上要把自定義資源對象同步到API Server往往由一個獨立controller通過client-go的Clientset或DynamicClient完成。你在看熱詞“kubernetes device plugin”相關(guān)項目源碼時會驚訝地發(fā)現(xiàn)好多邏輯都建立在client-go上監(jiān)聽Node資源、同步Device CRD、處理Pod調(diào)度結(jié)果、上報設(shè)備異常……所以別以為client-go只跟傳統(tǒng)控制器有關(guān)系在新型異構(gòu)計算場景里它同樣是抓手。5. 這些問題我踩過版本錯配、限流、資源泄露與安全加固5.1 版本錯配是第一大坑先講一個我印象特別深的案例有一次我在集群A上驗證一個控制器集群版本是1.28但代碼里client-go還是0.24。本地測試一切正常部署上去之后Informer的watch請求直接返回404查API Server日志發(fā)現(xiàn)是watch路徑里帶了舊版的apiVersion。換到對應(yīng)版本重新編譯問題立刻消失。這個問題很典型client-go的版本直接影響它跟API Server協(xié)商出來的API版本、序列化格式和資源發(fā)現(xiàn)行為。版本差太多輕則部分字段解析不出來重則整個watch鏈路直接不可用。排查時可以先用DiscoveryClient拉一下集群的資源版本或者直接看kubectl version -o yaml里的serverVersion然后把go.mod里依賴對齊。如果你發(fā)現(xiàn)某個字段在結(jié)構(gòu)體定義里存在但實際解析后一直是零值第一反應(yīng)就懷疑版本錯配。5.2 ListWatch的字段選擇器、資源版本和分頁Informer在List階段可以指定label selector和field selector但很多人踩過這樣的坑cache.NewListWatchFromClient(clientset.CoreV1().RESTClient(), pods, v1.NamespaceAll, fields.OneTermEqualSelector(spec.nodeName, node1))字段選擇器不是所有字段都能用的比如spec.nodeName在List請求里作為fieldSelector通常不受支持這會導(dǎo)致Informer始終同步不到對象但完全沒有報錯。更穩(wěn)妥的做法是先按namespace細(xì)分或者Label選擇器字段選擇器留給確有需求的場景并且先用kubectl get --field-selector驗證一下能不能生效。ResourceVersion這個參數(shù)也可能給你使絆子。Informer每次重新List時如果收到的對象數(shù)據(jù)量特別大API Server可能會返回410 Gone意味著你請求的resourceVersion已經(jīng)太舊數(shù)據(jù)不完整。client-go的Reflector對這種情況有自己的處理邏輯會自動重新全量同步一般不需要你干預(yù)。但如果你自己手動寫類ListWatch邏輯一定要注意resourceVersionMatch的取值Kubernetes 1.26之后推薦使用NotOlderThan配合resourceVersion來避免返回空列表帶來的狀態(tài)不一致。5.3 緩存不同步、事件丟失與goroutine泄漏Informer跑起來之后你要是發(fā)現(xiàn)“明明資源變了但是回調(diào)沒觸發(fā)”優(yōu)先檢查三件事第一WaitForCacheSync是否真的等到了HasSynced第二你的selector是不是過濾掉了這部分事件第三是不是多個informer實例重復(fù)監(jiān)聽導(dǎo)致資源版本混亂。更隱蔽的是goroutine泄漏。代碼里每調(diào)用一次cache.NewSharedIndexInformer你就要在退出時調(diào)用它的Run(stopCh)方法并確保傳入的stopCh能從外部關(guān)閉。我見過有人為了每次同步都新建一個informer但從來沒人調(diào)用Run與關(guān)閉結(jié)果Pod重啟前API Server的連接數(shù)一路飆升最后把整個節(jié)點連接打滿。如果確實需要一次性拉取數(shù)據(jù)用Clientset直接List就好了沒必要開Informer。另一個容易導(dǎo)致事件“看起來丟失”的情況就是前面強調(diào)過的resync。當(dāng)resync開啟時Update回調(diào)會對緩存里的所有對象重新觸發(fā)一遍如果你在回調(diào)里沒有處理“數(shù)據(jù)其實沒變”的情況可能誤以為有新事件到了。這點寫控制器的時候要心里有數(shù)。5.4 QPS與Burst設(shè)置別讓默認(rèn)限流卡死你的控制器rest.Config里的QPS和Burst默認(rèn)值低得驚人尤其對控制器這種事件驅(qū)動型程序來說默認(rèn)5和10幾乎等于“慢性毒藥”。我之前一個巡檢控制器連接了一個500節(jié)點、上萬Pod的集群默認(rèn)參數(shù)下每次同步要等很久Informer事件堆積隊列膨脹CPU和內(nèi)存雙雙飆升。原因很簡單Informer首次List就需要拉取大量對象以每秒5個請求的速度要拉多少秒你自己算算。這里建議把QPS調(diào)到50到100Burst調(diào)到100到200對于大多數(shù)控制器來說足夠又不至于把API Server打崩。如果是核心集群的巡檢組件可以通過壓測來確定更合理數(shù)值。有一點容易被忽略DynamicClient、DiscoveryClient和Clientset雖然是同一個config創(chuàng)建的但它們在RESTClient層是獨立的實例限流器也是獨立的。如果你在代碼里混合使用了多種客戶端實際對API Server的請求壓力會疊加QPS的“預(yù)算”也要把這一層算進去。5.5 站在安全角度重新審視client-go的使用現(xiàn)在很多企業(yè)項目把“Kubernetes未授權(quán)訪問”掛在嘴邊其實從客戶端開發(fā)者的視角來看這個問題很大一部分出在用client-go的程序以及它的運行環(huán)境上。最常見的錯誤是把一個擁有集群admin權(quán)限的kubeconfig文件直接打包進鏡像或?qū)懰涝贑I配置里。一旦這個文件泄露整個集群等于拱手讓人。正確的做法是控制器部署在集群內(nèi)時優(yōu)先使用ServiceAccount并用RBAC給它授最小權(quán)限。比如你的控制器只需要讀Pod和更新Deployment那就只給如下監(jiān)聽與操作權(quán)限apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: myapp rules: - apiGroups: [] resources: [pods] verbs: [get, list, watch] - apiGroups: [apps] resources: [deployments] verbs: [get, list, watch, update, patch]再配合RoleBinding綁定到控制器Pod所使用的ServiceAccount上。這樣即使控制器被攻破攻擊者也只能看到和修改被授權(quán)的那一小部分資源。另一個容易被忽略的點是Token過期問題ServiceAccount的Token如果沒配自動刷新可能運行幾個月后突然失效API調(diào)用開始返回401。建議關(guān)注TokenRequest API并在代碼里依賴rest.InClusterConfig的自動刷新能力而不是手動硬編碼一個永久Token。5.6 問題速查表幾類典型的控制面故障癥狀可能原因解決方案Informer完全不觸發(fā)回調(diào)WaitForCacheSync未通過、selector過濾不當(dāng)、版本錯配檢查同步狀態(tài)、精簡selector、對齊client-go版本watch請求返回404/405client-go版本與API Server版本差太遠(yuǎn)業(yè)務(wù)依賴版本對齊本地調(diào)試正常集群內(nèi)部署失敗InClusterConfig失敗、RBAC權(quán)限不足檢查ServiceAccount、Role/ClusterRole綁定控制器CPU內(nèi)存飆升QPS/Burst過低或并發(fā)worker過多調(diào)整限流參數(shù)、壓縮隊列長度、減少worker數(shù)資源被重復(fù)處理或互相覆蓋多副本控制器沒做LeaderElection接入leaderelection保證同一時刻單Leader更新事件頻繁觸發(fā)resync機制在起作用UpdateFunc里判斷關(guān)鍵字段或resourceVersion是否變化刪除事件回調(diào)panic未用DeletionHandlingMetaNamespaceKeyFunc替換為帶刪除處理的key函數(shù)長時間運行后請求401ServiceAccount Token過期或kubeconfig過期啟用Token自動刷新定期更新kubeconfig最后說一點個人體會client-go的API每隔一兩個版本就有breaking change別把網(wǎng)上老帖子里的代碼當(dāng)死規(guī)矩go.mod里的依賴版本才是你唯一可信的基準(zhǔn)。我寫第一個控制器時天真地把業(yè)務(wù)邏輯全塞進AddFunc結(jié)果一次批量驅(qū)逐Node事件直接把進程拖死改成“事件入隊worker消費”之后才明白這套設(shè)計不是刻意復(fù)雜而是分布式系統(tǒng)里抗壓的基本功。如果你正在寫第二個或第三個控制器把這些經(jīng)驗套進去能省掉很多凌晨三點被告警吵醒的夜晚。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
色五月丁香婷婷| 丁香五月婷婷亚洲综合精品| 538任你爽| 久操热| 99热只有这里才是精品| 视频这里只有精品| 999激情视频| 色啪网| 热99在线| 国产资源91在线| 亚洲国产婷婷色五月| 123日本不卡在线| 91碰碰视频| 五月激情网综合| 丁香五月天激情五月天激情五月天激情网| 五月婷婷深深爱| BBWCUCKOLD精品熟妇| 色色色9| 在线另类| 超碰在线观看99| 成人AV片播放| 日本大人久久| 精品日本视频444| 少妇高潮一区二区三区99欧美| 99亚洲色| 99热这里只要精品免费| 五月丁香六月婷婷开心网| 色五月激情综合网| 激情婷婷五月久久| site:xiongshengzz.com| AV动漫不卡无码免费| 五月丁香婷婷色啪| 99网址在线观看| 国产精品99久久久久久久女警| 五月丁香 啪啪| 色婷婷色五月天| 激情五月综合免费| 狠狠狠狠狠草| 五月天社区狠狠| 婷婷综合五月天激情| 超碰狠狠操| 9热在线观看| 夜色爱爱亚洲| 大香蕉五月| 五月婷中文娱乐综合| 色狠狠色噜噜AV天堂五区| AV九九| 97色永久免费视频| 激情綜合W W W,激情五月天| 亚洲天堂热| 久久99精品九九久久久婷婷| 婷婷五月天网| 免费色婷婷| 97人碰人操| 免费无码毛片一区二区A片| 久久99精品视频| 人人爱人人草| 九色综合网| 另类丁香五月天区图| 无码激情AAAAA片-区区| 婷婷五月欧美AA片免费| 丁香六月婷| 99久操| 另类激情五| 色婷婷五月影院| 婷婷激情四射五月天| 男人的天堂99| 色婷婷XXXXX| 欧美激情 日韩无码 婷婷 五月天| 色婷婷六月性| 婷婷五月天成人综合网| 久久五月激情综合| 97在线观看| 久久婷婷五月综合色欧美| 国产精品久久久久久久久久| 秋霞少妇毛片| 无码一区二区三区四区五区| 欧美黄色AA片哗啦啦啦| 能直接看的av网站| 5Www色5夜| 97人人看一| 亚洲情色一区| 天天日天天日天天搞| 五月丁六月香| 91碰碰碰| 九九人人自拍| 影音先锋 婷婷| 亚州色色色| 97香蕉久久超级碰碰高清版| 影音先锋秋秋五月婷婷| 欧美天天草人人草| 欧美成人精品A片免费一区99| 97热这里精品在线视频| 婷婷97C| 99男人的天堂| 五月丁香另类网| 久久怡红院| 久热免费| 六月婷婷激情图片| 能直接看的av网站| 五月丁香色停停啪啪啪| 天天综合情| 99久久er| 国产精品99久久久久久久女警| 丁香色色五月| 久久这里只有精品16| 婷婷五月天视频亚洲| 丁香大香蕉| 成人做爰A片免费看视频| 狠狠狠狠草草| 操逼棍操逼| 超碰成人电影| 玖玖五月| 日熟女| 狠狠干.com| 久久色情| 激情五月综合| 精品成人久久久久久久_一二三四视| 五月丁香婷婷国产精品综合| 色五月激情网| 99色视| AV性爱在线| 久久婷婷伊人| 天天天久久久| 五月婷婷成人| 激情美女五月天| 五月 激情视频| 国产肥白大熟妇BBBB视频 | 亚洲综合激情五月天婷婷| 色婷婷先锋| 色色丁香| 六月激情婷婷色| 超碰在线免费9| 秋霞少妇AV网站| 亚洲激情亚洲激情| 色情五月婷婷| 婷婷综合另类小说| 俺也去色| 天天色五月| 99精品热| 99无码免费视频| 婷婷久久大香蕉| 久久五月天免费网站| 第六色在线| 色五月丁香婷婷| 噜噜操操| 久久这里只有精品热在99| 九九九午夜视频| 狠狠色综合五月| 婷婷伊人綜合中文字幕| 亚洲AAAA网| 少妇高潮A片无套内谢麻豆传| 99色色网| 亚洲精品V天堂中文字幕| 激情丁香婷婷六月天| 久操综合| 激情五月天之六月婷婷| 五月婷婷综合在线视频| 美欧成人视频| 日夜操B| 激情五月天色网站| 欧美综合婷婷欧美综| 人妻体体内射精一区二区| 永久思思热在线| 99久久婷婷国产综合| 超碰人人超碰| www.色五月| 丁香五月激情月| 国产做爰视频免费播放| 婷婷婷婷婷婷婷五月丁香| 啪啪五月婷婷| 亚洲午夜AV| 玖玖国产视频一区| 久久久久9久无码视频| 天天夜天天色天天| 欧美啪啪9| 91色在线/日韩| 99热精品在线播放| 久久九网| 综合色色婷婷| 丁香五月冃欧美| 91fuliwang| 来吧亚洲综合网| 欧美人久久| 婷婷五月色| 亚洲丁香网| 97极品在线| 超碰操网| 草做免费在线观看| 婷婷五月成人| 色99婷婷五月天| 97视频.干com| 深爱激清网| 丁香六月婷婷久久高清| 丁香六月成人| se99视频| 国产激情婷婷| 激情五月五月五月婷婷| 婷婷五月天AV| 超碰精品国产首页| 丁香五月大香蕉在线99| 依人大香蕉| 色情五月天A片| 五月丁香婷婷色色色| 丁香五月天婷婷激情| 九色视频这里只有精品| 五月婷婷激情四季| 任你日视频| 国产精品久久久爽爽爽麻豆色哟哟| 五月深爱激情网| 五月婷婷五月天| 婷婷丁香五月天激情四射| 日本熟妇精品99| 91高潮喷水久久久久久久久| 99九九久久| 五月丁香婷婷激情澎湃四射| 五月婷婷深深爱爱| 国产免费一区二区三区三州老师F1F1.CC | 91VIP在线观看| 五月天丁香综合| 久热这里只有精品6官网亚洲| www.丁香黄色五月天人与| 婷婷久久久| 欧美啄木乌丝袜人妻系列| caop在线视频| 情久久综合五月天| 热思思| 凹凸7777操操操| 久色激情| 久久一级片| 久久精品一区二区三区四区| 中国女人做爰A片| 999激情视频| 中文在线视频久1| 婷婷五月天成人动漫| 色九月欧美| 色天使色综合| 99re资源在线视频导航| 婷婷在线日韩综合| 99riAV成人在线视频| 婷婷香蕉| 无码91中文字幕| 久热99| 中文在线成人| 狠狠久久婷五月| 日日夜夜狠狠| 天天色天天日天天舔| 五月丁香基地| 五月激情婷婷丁香天堂| 美国十月色婷婷在线观看| WWW.夜夜| 五月天成人综合| 色五月天激情| 久久久精品色色色| 五月丁香综合激情| 婷婷爱五月| 99久久玖玖| 操一操插一插| 五月婷综合| 婷婷天天色| 婷婷精品性视频| 九九精品丁香花| www99热| 狠狠干狠狠色| 91日在线视频| 69精品人人人人人人| 超碰五月婷婷五月天| 91N 一起草| 69精品无码一区二区三区| 丁香五月婷婷综合激情啪啪啪| 碰久久精品w| 五月天婷婷激情网| 婷婷色网| 嫩BBB槡BBBB搡BBBB视频| 天天干天天玩天天夜天天射天天操天天日蜜臀少妇 | 狠狠草婷婷| 狠狠肏综合网| 六月婷婷开心| 五月婷婷五月| 亚洲超碰青涩| 91婷婷在线| 五月丁香六月激情综合网| 天天色爽| 婷婷爱五月天| 婷婷五月天伊人| 嫩BBB槡BBBB搡BBBB| 六月婷婷毛片| 五月婷中文字幕| 九九無妻| 五月丁香色停停啪啪啪| 丁香色六月婷婷| 久久久er热| site:feetmall.com| 国产毛片精品一区二区色欲黄A片| 99免费视频| 玖玖婷婷五月天| 亚洲视频综合网| www.无码com| 色热久资源| 久久久久人妻中文| 婷婷五月天影院| 日本在线观看99| 综合色网站| 夜夜爽天天| 亚洲丁香五月| 99热综合| 日韩超碰在线| 久久免片| 日本操天堂| 国产精品美女| 天天天天天久久久久久| 人人草人人舔| 丁香五月情| 五月天婷婷青青| 色婷婷精品视频| 人妻丰满精品一区二区A片| 九九色播五月丁香| 婷婷五月天啪啪| www.五月天| 成人免费视频一区| 亚洲激情色色| 香蕉AV福利精品导航| 色综合激情| 人妻熟妇国产精品| 婷婷va| 五月人人丁香婷婷五月人人丁香| 日韩中文欧美| 夜夜资源站| 五月婷婷之美女图片| 无码99| 9l视频自拍9l九色9l成人| 蜜乳国产网站| 牛牛热这里只有jingpin| www.99热视频| 丁香蜜臀黄色婷婷五月天| 婷婷丁香久久网| 国产xxxxx在线观看| 五月婷婷|欧美| 久久大大香| www.99热国产| 五月花婷婷| www.色综合| 婷婷的色色五月天| BT综合在线视频观看| av色色国产| 丁香花社区av| 性色视频| 婷婷黄色五月| 婷婷五月综合网| 九九草草逼| 五月丁香久久综合精品| 欧美成人AAA片一区国产精品| 婷色五月| 五月丁香啪啪网| 天天综合情| 五月天堂色| 婷婷色在线播放| 丁香五月a| 综合久久丁丁香婷| 天天日天天爱天天噪| www天堂99| 国产色五月婷婷| 5月丁香综合图区| 五月激情综合五月| 91操黄| 丁香五月激情婷婷| 婷婷五月天精品| 操一操干一干| 久热九九| 八戒青柠影视剧在线观看| 成人欧美一区二区三区在线观看| 久久九九激情五月天 | 国产成人AV在线| YJLZZJLZZ亚洲乱熟无码| 久操人妻| 欧美经典片免费观看大全| 日韩抽插操逼| 婷婷黄色网| 婷婷六月丁| 九热免费视频| 少妇性BBB搡BBB爽爽爽电影| 丁香成人视频| 亚洲操人| tingtingseav| 久草五月婷婷| 欧美噜一噜| 丁香六月成人| 五月婷婷激情网| 日韩一区二区在线播放| 人操91在线| 在线天堂9| 亚洲午夜精品久久久久久人妖| 亚洲无AV在线中文字幕| 色婷狠狠| 婷婷久久夜| 午夜]香婷婷深深爱| 91超级碰在线| 极品 少妇 内射| 伊人影院久久网| 91黄操| 色月视频| 天天日夜夜欢| 97操碰98| 五月天综合| 精品免费99| 99精品视频偷拍| 日韩中文字幕| 操人91| 婷婷日日天天| 色色五月婷婷| 亚洲操B视频| 五月色网| 狠狠爱婷婷丁香| 婷色成人| 大香蕉520| 久久久91精品| 婷婷久久综合| 97操碰视频| 天天综合亚洲综合| 久久机热这里只有精品免费视频| 狠狠草网| 一级片无码| 亚洲激情网| 久久视频这里有精品99| 欧美英丁香开心快乐六月天网| 国产视频福利| 99久久婷婷精品视频| 欧美这里只有精品| 成人婷婷| 天天爱天天爽| 综合激情五月天六月婷免费视频| 97色色色色色色色色色色色色色| 丁香五月婷婷亚洲人| 性色综合网| 中文字幕人妻熟女在线| 俺去也婷婷| 国产97色在线 | 日韩| 婷婷综合六| Se.婷婷五月天| 97在线/亚洲| 另类亚洲电影| 国产AV成人精品| 韩国真做片在线观看| 九九九九毛片| 玖玖综合色| 开心五月婷婷| 99ri精品在线| 伊人玖玖精品| 成人精品人妻| 99热青青草| 亚洲综合色网| 26.uuu丁香五月婷婷| 五月天婷婷成人| 久久这里只有国产视频| 五月丁香亚洲婷婷| 99久在线精品99re8| 午夜精品777| 五月婷婷高清| 婷婷舔| 九九视频这里只有精品在线播放| 密黄站| 欧美欧盟性爱网| 久久婷婷五月| 99热这里有精品6| 99热 免费| 色婷婷内射| 婷婷激情五月天7| 九九视频免费| 激情婷婷狠狠干| 影音先锋 91工厂| 久久奄也去色色网站| 激情网 五月天| se99在线| 婷婷色色欧美| 五月丁香 啪啪| 久久婷婷亚洲| 内射人妻视频国内| 殴美97色| 国产在线黄色| 五月丁香六月婷婷,婷| 婷婷爱综合| 六月婷婷影院| 人人操AV| 色五月婷婷老师| 熟女人妻一区二区三区免费看| 狠狠精品干练久久久无码中文字幕 | 偷拍丁香九月激情| 精品一区二区三区三区| 亚洲综合色色| www.夜夜操.con| 99精品视频免费观看,| 日日舔夜夜操| 成人av在线电影| 色婷婷五月天在线观看| 丁香婷婷六月| 日韩操逼大片| 国产成人精品一区二区三区视频 | 天天日人人爽| 婷婷五月天激情网| 中文字幕欧美日韩VA免费视频| 91丁香色| 中文字幕黄色片| 天天做天天要天天爽| 99精品免费欧美小视频| 婷婷五月天精品| 国产婷婷色综合AV蜜臀AV | 日韩操啪| 午夜理论片最新午夜理论剧 | 91精品国产99久久久久久天美| 五月开心网| 五月 婷 久| 五月久久婷婷丁香| 婷婷激情五月综合丁香社| 婷婷五月综合色拍| 久久婷婷综合五月| AV激情五月| 六月婷婷九月丁香亚洲综合| 五月天另类小说| 教师性爱毛片| 性五月激情| 色五月婷婷久久| 五月天综合在线| 日韩久久日| 另类激情五月天。| 色色色网站| 亚洲乱码日产精品BD| 婷婷五月天亚洲综合| 丁香综合伊人AV| 色五月综合在线| 狠狠色婷婷综合开心影视| 激情五月天在线观看婷婷| 婷婷丁香色五月| 五月婷婷六月激情| 黄色片区子| 亚洲视频伍月婷婷| 丁香网五月天| www.国产亚洲69ty.久久久久久久久久久久| 五月丁香六月欧美综合网站| 超碰日韩人妻在线| 色青青五月| 亚洲热视频在线| 亚州综合色| 亚洲激情97五月天| 亚洲精品**不卡在线播he| 久久ER视频com| 久久婷婷五月天| 性色av大香综合| 婷婷六月五月天综合| 五月丁香啪啪网| 久久99视频| 五月婷婷深深爱| 成人丁香五月婷| 婷婷六月花| AⅤ网站在线看| 99色啊| 五月丁香影院| 婷婷五月天改成什么了| 九九99精品| 91蜜桃婷婷狠狠久久综合9色| 亚洲婷婷基地| 五月激情婷婷综合| 中文字幕在线播放视频| 六月丁香啪啪| 婷婷亚洲综合| 色婷婷五月丁香在线观看| 激情五月婷| 激情网第九色| 五月色网| 激情久久天天| 91高潮喷水久久久久久久久 | 日本视频久久| 婷婷网五月| 偷拍九九热| 亚洲bt丁香五月天婷婷激情小说| av一区免费看| 五月天伊人| 国产精品成人AV在线| 婷婷五月香蕉| 久久久er热| 国产视频色色色色色色色| 天天天添天天操| 综合色七七| 九九视频这里只有精彩| 日本97在线| 强伦轩人妻一区二区电影| 91人人网| 国外亚洲成AV人片在线观看| 亚洲五月色| 99啪啪网| 久久婷婷五月天| 99久久9| 69午夜成人影片| 丁香六月婷婷基地| 婷婷五月六| 91无码视频| 天天草天天爽| 99无吗| 少妇人妻丰满做爰XXX| 人人视频色| 99久久.www| 激情五月天婷婷丁香| 五月丁香 久久久| 丁香婷婷婷| 99re免费精品视频| 亚洲五月天狠狠| 69精品无码一区二区三区| 99热伊人| 常久最新免费的色吊丝| 五月丁香激情综合网| 人妻体体内射精一区二区| 中文在线视频久1| 色婷婷网| 色色影院黄大片| 国产日韩欧美性爱| 激情小说视频图片| 玖玖在线资源视频| 久久婷婷五月综合成人d啪| 深爱五月天| 婷婷综合五月天| 91热er| 六月色激情| 高清无码网址| 婷婷天堂站| 艹B高清无码| 激情床戏| 丁香色婷婷五月天| 激情综合网,五月| 九九人人看| 国自产拍偷拍精品啪啪一区二区 | 六月婷婷av| www.夜夜騎夜夜狠| 狠狠色婷婷在线| 色色婷婷丁香五月天| 一本到不卡高清DVD| 熟女色专区| 五月综合激情久久| 九九热这里只有精品6| 五月色影院| 五月www| 久久婷婷五月天懂色| 色吧五月婷婷| oumeisesewang| 欧洲综合视频| 在线看黄色| co超碰在线观看| 五月婷激情| 婷婷五月激情的图片| 深爱五月最新网址| 婷婷四色五月| 婷婷久久夜| 久久久精品视频79| 日本啪啪天堂| 99ri精品在线| 九九精品99久久久| 综合爱久久| 九热网站| 激情性爱五月天网页| 成人做爰A片免费看视频| 91九色精品熟女内射| 天天爱天天操| 狠狠狠狠狠狠| 久99在线视频| www.久久爱.c n| 丁香六月激情国产| 综合婷| 久久精品噜噜噜成人A∨色欲| 99超碰欧美| 激情婷婷久久| 免费观看的av| www.韩日视频| 亚美欧色影院| 人妻激情视频| 六月婷婷av| 婷婷丁香人妻天久久| 五月香婷婷| 另类图片 五月激情| 丁香五月婷婷激情97| 99久久99热这里只有精品| 欧美色激情四射| 五月婷婷六月丁香色| 久人操| 国产成人AV在线| 色五月婷婷婷婷婷婷婷婷婷婷| 亚洲AV免费在线| 久久九九99亚洲国产久精综合| 色吊操色妞| 五月天丁香成人社| 4399在线观看免费高清电视剧| 亚洲深喉aV| 五月天四色房丁香亭亭| 先锋五月婷婷丁香草草| 亚洲精品又粗又大又爽A片| 五月婷婷无码专区| 日韩欧美一道四区中文字幕| 六月 丁香 视频| 天天日天天摸天天| 亚洲av无码影院| 久久9久| 婷婷丁香五另类网站| 人妻激情网| 99久久6| 日韩小视频在线99| 91要啪| 亚洲无AV在线中文字幕| 九九热在线观看视频| 99热乎| 偷偷操九九| 99久久6| 久久婷婷五月综合色丁香| 人人综合久| 丁香综合| 狠狠色婷婷7777久| 婷婷无码视频| 99色婷婷| 97AV人人插人人操| 婷婷色在线| 人人干人人操人人摸| 六月丁香婷婷综合色播| www.com任你艹| 99视频只有精品| 激情婷婷五月天| 亚洲激情视频网| 秋霞A V毛片| 婷婷影院A成人| 综合久久综合| 天天做天天爱天天要| 久久精品爱爱| 五月天婷婷色色网| 99婷五月| 成人精品在线| AV在线免费播放| 激情五婷网| 日日噜噜久久婷婷五月天 | 国产精品色色| 超碰99资源站| www.久久av.com| 五月丁香婷色| 色优久久| 国产avapp 网| 九月大香蕉| 九九综合九| 日韩婷婷| 久久婷婷六月综合| 性色天| 这里只有免费精品| 激情 婷婷 丁香五月天| 激情丁香久久| 五月婷在线观看| 一起草av在线观看| 在线超碰精品| 人人摸人人干| 伊人高清无码| 熟女人妻一区二区三区免费看| 五月激情小说网| 久久婷婷五月天| 丁香五月综合AV在线| 久久这里只有精品网| 婷婷五月蜜桃成人桃色丁香| 青草青草久热这里只有精品| 涩综合网| 婷婷丁香五月91| 久久天堂色| 丁香婷婷影院| 日韩日比视频在线| 成人性生活免费观看。| 色综合综合综合| 麻豆AV一区二区三区| www.超碰在线| 丁香五月电影| 99操视频| 99无码| EEUSS鲁片一区二区三区| 人人摸人人摸| 精品久久99码| 99久久99久久综合| 色婷婷电影| 婷婷色婷婷| 99视频只有精品| 五月激情小说| 欧美成人AAA片一区国产精品| 色色色综合网| 老师的粉嫩小又紧水又多A片视频| 九九热免费视频| 午夜少妇在线观看视频| 久久久天堂国产精品女人| 亚洲亚洲人成综合网络| 色婷婷在线电影| 国内熟女黄色系列| 92久久久| 丁香五月停停基地| 日韩性视频| ay2区| 69五月天视频| 亚洲婷婷五月天激情综合| 丁香五月六月欧美| 婷婷色五月丁香六月欧美啪| 五月婷婷六月丁香在线视频免费在线观看| 丁香婷婷激情五月天无毒不卡蜜桃| 99精品免费视频| 国产精品日日躁夜夜躁| 99视频内射三四| 天天操综合网| A短视频免费在线观看| 91国产精品视频播放| 五月丁香婷色| 亚洲成人一区| 这里只有精品视频在线观看免费| 中国AV性爱观看| 99视频一区| 99热精品在线观看| 99网| www五月婷婷88导航| 99丝袜精品视频网站| 久久婷婷91| 色五月婷婷少妇人妻| 99色在线观看| 99热| 亚洲1区| 色操综合| 99网址在线看| 狠狠久久婷五月综合色| 亚洲99热| 思思热精品在线| 色色色五月天婷婷| 久久精品91视频| 激情深愛五月視頻| 丁香六月无码| 超碰人人操人人干| 少妇人妻人伦A片| 大香蕉丁香| 性爱久久| 激情影院69| 另类图片色五月| 国产精品-91JQ就要激情网91JQ6.91JQ27.CASA:16888 | 九九99在线视频| 九九色热| 亚洲色综久久五月| 99啪| 五月丁小婷婷激情四射| 99九九在线观看免费| 天天干-天天日| 天天日天天舔| 超pen个人视频97| www.婷婷.com| 99人人操人人摸| 欧美在线干| 97超级碰人人| 欧美黑人大吊| 九九热99热| 五月色综合| 天天综合网~91| 五月天婷婷色播| 爆乳熟妇一区二区三区爆乳照片| 亚洲六月综合激情久久下卡| 淫视馆aV二区一区| 丁香六月在线| WWW.久久.COM| 草草视频91| 亚洲日日日| 国产亚洲精品久久久久久郑州| www.色九月| 午夜电影网VA内射| 思思久久99| 亚洲自拍天堂| 蜜臀嫩草| 国产午夜精品AV一区二区麻豆| 人人操女人| 五月婷婷丁香五月婷婷| 婷婷色综合| 久9免费视频| 日韩爱操视频| 操人妻AV| 国产精品色色666| 日韩成人无码人妻| 欧美在线视频免费播放| 伊人超碰在线| 丁香五月婷婷成人网| 婷婷五月天av| 久久婷婷色| 亚洲六月婷婷| 在线观看欧美3区| 丁香五月大片| 婷婷丁香在线| 久久久久9| 97性视频| 啪啪操操| www.五月天婷婷| 天天操天天国产三级片处女学生妹| 五月色导航| 婷婷久草| wwW天天干| 99精品在线观看视频| 精品久久9| www.婷婷.com| 色五月婷婷1| 五月综合婷婷五月| 99ri视频在线观看| 99热这里只有免费精品| 在线精品97| 色五月婷婷啪啪五月| 久久99久久99精品,久国产,久久精品免费,99久在线,久久久久国产精品免费网站,9 | 无码动漫AV| 夜夜操,天天撸| 五月婷婷激情在线| 五月天激情视频五月天| 操操综合网婷婷| 久久婷婷五月草视频| 五月婷婷色欲| 99热这里只有精品50| 爱超碰性| 五区毛片七区毛片| 亚洲人成网站999综合| 直接看的AV网站| 激情五月婷婷丁香综合网| 天天日天天日天天搞| 五月天另类小说久久小说网| www.av骚货| 潮汕成人AV片在线| 亚洲激情五月| 超碰a女人的天堂| 日本天堂爱爱| 五月丁香六月婷| AVDV久久| 五月婷婷五月天天| www.99精品日操伊人乱碰在线| 激情五月婷婷在线| 久久99草五月婷婷| 五月天婷久精视频| 日本婷婷在线| 99爱视频免费| 南京搡BBBB搡BBBB| 俺来也狠狠| 天天操天天曰| www.婷婷亚洲基地| 99热只有| 五月综合亚洲婷婷| 综久久久| 九九热av| 五月丁香激情婷婷综合字幕| 久久5 9视频免费观看| 五月天国产婷婷精品视频在线| 久xxxx| 婷婷99狠狠躁天天躁| site:picc-up.com| tingtingseav| 91无码视频| 天天肏屄夜夜爽| av婷婷六月丁香社区在线观看| 激情综合网五月天| 大香蕉五月天| 亚洲春色奇米影视| 婷婷性爱五月天| 日本91在线| 国产人妻777人伦精品HD| 国产VA亚洲VA96| 97人人搞| 日本精品久久久久中文字幕| 激情五月天小说| 精品激情| 丁香六月婷婷缴情欧美| 欧美乱码国产一级A片| 丁香色五月婷婷17C| 91九色超碰| 亚洲综合色色| 欧美va| 欧美激情综合色综合啪啪五月| 久久婷五月天| 在线综合网| 人妻性爱| 99热久97| 日韩无码专区| 激情五月天综合网| www。五月天。com| 丁香五月综合激情性爱| 亚洲熟妇AV乱码在线观看| 亚洲五月天激情| 婷婷五月情色| 国产三级片91| 久久久天堂国产精品女人| 99re热在线视频观看| 色综合色综合色综合高潮| 色综合香蕉| 成人无码髙潮喷水A片| 五月婷婷六月天| 性爱电影科技贸易有限公司| 色碰碰| 天天肏天天舔AV| 26UUU精品一区二区| 欧美VA在线| 亚洲五月天天| 日韩99视频| 影音先锋男人站,影音先锋男人色资源网,影音先锋AV最新资源站,影音先锋AV资源 | 夜夜躁爽日日| 97婷婷丁香五月天激情图片| 久99久热| 亚洲区1| 日韩丰满少妇无码内射 | 日本精品干| 666555。COm毛片| 四色99久久| 五月天最新网| Jh7Uf088VHafNm| 婷婷啪啪| 五月久久网| 超极99精品| 亚洲AV成人在线| 婷婷五月天Av| 丁香五月激情啪啪| 激情五月婷婷| 97久久超碰| 99热在线只有精品| 亚洲尤物在线| 五月天五月色婷婷综合| 91porn一起草| 综久久久| 久久桃花网色婷婷| 日本高清久久| 久热伊人| 9久久久久久久久久久| 五月婷婷中文字幕| 婷婷激情5月| 就爱啪啪婷婷| 久久色在线视频| 丁香激情久久| 91日视频| 婷婷五月激情五月丁香五月| 国产一级黄色影片,| 日本少妇裸体做爰高潮片| 99热| 色欲色香综合网| 丁香五月激情啪| 激情视频综合| 性综合网| 五月婷婷丁香五月 | 婷婷色一二三区波多野结衣| 99热综合在线观看| 色欧美色色色| 国产精品天天狠天天看| 99只有精品| 丁香五月成人| 91精品丝袜久久久久久| 丁香五月电影| 99re8这里只有精品99re8热视频| 亚洲在线综合| 久久精品婷婷| 婷婷精品视频| 色情五月婷婷| 99热婷婷| 99热这里只有精品22| 99综合视频一体| 草草视频91| 天天狠天天叉| 婷婷金品综合视频| 大香蕉综合网| 色婷婷综合视频| 97天堂| 亚洲日韩一页精品发布| av亚洲国产小电影| 爱99干99| 超碰97在线观看免费| 老师高潮流白浆喷水的A片| 婷婷五月丁香第四色超碰在线| 逼特逼在线免费播放| 热99视频精品在线| 亚洲综合欧美色丁香婷婷888月图片| 日本婷婷色| 狠狠综合久久综合| 蜜乳人妻一区二区三区| 99爱99操| 看婷婷五月天网| 国产成人VA| 国产高清RV综合aVa| 婷婷色欧美激情| 丁香桃色网| 天堂综合久久| 91精品久久久久久综合五月天| 97五月天| 男人的天堂婷婷色五月| 九九精品re免费视频| 另类亚洲视频| 九九aV| 五月婷婷啪啪啪啪| 人五月天婷婷喷水| 99人人操| 色婷婷狠狠| 天天 日综合| 天天插AV丝袜中| 97碰| 青青草免费公开视频| 激情婷婷五月在线合集| 操九色| 亚洲天天免费| 夜夜夜夜夜操| 婷婷五月天久久| 无码少妇高潮喷水A片免费| 婷婷99狠狠躁天天久久久九九九| 亚洲av成人一区二区电影在线| 九九综舍久久| 人人爱干人人爱草| 天天操天天爱天天玩| 美女精品一级不卡视频| 五月激情小说| 欲求不满的人妻| 99久久婷婷| AAA亚洲AV| 久久激情五月婷婷| 亚洲人妻av伦理| 婷婷色色丁香| 无码一区二区日韩| 日日操天天| 欧美色婷婷| 超碰人人摸AV| 婷婷五月丁香综合| 色五月色综合| 91丁香五月| 黄桃AV无码免费一区二区三区| 成人 九九九九| 色八月婷婷| 2025色婷婷| 亚洲激情av| 《丁香激情综合久久伊人久久》影视在线观看 -高清预告手机免费播放 -三妹影院 | 日本婷婷五月天| 五月综合激情图片| 综合狠狠伊人| 天天插插天天| 五月丁香网站| 超碰三级片| 婷婷综合网伊人| 日日噜噜夜夜狠狠久久丁香六月| 大香蕉久久视频久久视频| 99热在线精品播放| 日本激情五月天‘| 亚洲操B| 久人人操| 天天操天天日天天爽| 五月色婷婷中文字幕| 成人国产网| 色七色九九| 99久久www| 九九无毛| 激情婷婷五月天伊人在线观看 | 免费播放99性爱视频| 四色五月婷婷| 久婷首页| 色狠狠综合| 91狠狠色丁香婷婷综合久久精品| 五月丁香毛片| 狠狠狠狠狠操| 天天做天天爱天天高潮| 欧美WW在线网| 丁香婷婷色六月| 精品一二三区久久AAA片| 五月色网| 五月婷婷六月色| 9视频在线成人网站| 丁香五月AV在线| 久九色| 激情亭亭五月| 婷婷5月九九| 99精品视频在线观看| 婷婷色婷婷亚洲成人| 色情久久久| 色五月开心久久网| 婷婷激情五月天亚洲综合| www.色婷婷.com| 在线观看的av| 色欲婷婷五月天丁香| 天堂在线婷婷| 天天摸天天日天天舔| 日产精品一线二线三线芒果| 夜夜骑操AV| 丁香桃色网| 97碰碰视频在线观看| 亚洲五月天激情| 欧美婷婷五月丁香| 天堂久久婷婷| 五月天激情婷婷久久| 99在线精品免费视频| 九九热九九| 色婷婷五月天在线观看| 99九九在线| 91超碰在线播放| 国产激情在线| 五月婷婷六月丁香玖玖玫瑰91| www狠狠爱com| 丁香六月天堂| 91久久国产自产拍夜夜91久久精品文字>91麻豆精品国产 | 久久久噜噜噜操操操| 丁香激激情网| 婷婷丁香六月天| 亚洲综合丁香婷婷六月天| 色情婷婷| 婷婷美女精品视频| 疯狂做受XXXX高潮A片| 天天激情综合| 婷婷五月天AV| 婷婷激情五月天在线视频| 五月综合视频| 激情综合网,五月| 国产精品18久久久| 五月婷婷免费在线观看| 精品人妻在线免费观看| 婷婷激情啪啪| 欧美日韩国产成人在线| 婷婷播5月| 9久久网| 欧美激情综合色综合啪啪五月| 精品人妻在线| 91色五月| 色五月丁香六月资源站| 99久久久| 五月久久亚洲| 激情婷婷五月综合| 人人摸人人澡人人| 婷婷激情九月| 色色无码| 五月丁香婷中文字幕| 日本性视频| 丁香五月手机在线| 91碰在线| 色婷婷丁香五月| 99爱最新免费视频在线观看| 97碰碰免费.视频| 丁香五月六月| 超碰大香蕉网| 色色网站观看| 热久久这里只有精品| 婷婷丁香激情| 婷婷丁香五月天大香蕉| 久久作爱| 天天爱天天做天天舔| 国模狼狼| 在线中文亚洲| 99er这里只有精品视频| 无遮挡国产高潮视频免费观看| 都市激情小说婷婷| 五月丁香在线观看99| 日韩啊啊啊| 五月天婷爱综合| 国产亚洲99久久| 色播五月天激情| 99爱免费在线视频| 欧美色碰| 九九成人| 玖玖资源天天无码| 久久大香蕉同僚| 五月丁香| 色婷婷www| 99色综合| 午夜成人av在线| 亚洲综合视频在线| 婷婷五月天综合蜜桃| 9久热在线精品| 九九热精品| 毛片新网地| 超碰在线国产9| 精品成人无码A片观看香草视频| 色婷婷亚洲六月婷婷中文字幕| 激情视频婷婷五月花| 玖玖婷婷五月天毛片| 国产成人+综合亚洲+天堂| 婷婷娱乐丁香综合网| av色婷婷| 中文字幕91,综合| 婷婷丁香18| 久久精热|