亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

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長連接重連、本地緩存一致性……這些工作散落在一個資源一個資源的交互細節(jié)里你自己實現(xiàn)一遍基本相當于把客戶端框架重新造一次輪子。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建立基準之后靠Watch持續(xù)接收增量變化對象在本地緩存里維護控制器讀自己的緩存就能拿到最新狀態(tài)不需要反復(fù)打API Server。1.2 核心模塊掃一遍別被client-go龐大命名空間嚇到client-go的代碼量很大剛開始看確實容易迷路。我建議按下面這個分層來理解從上到下依次是抽象程度和靈活度遞增日常開發(fā)90%時間其實只跟中間兩層打交道。模塊典型對象作用適合場景RESTClientrest.RESTClient最底層的HTTP客戶端封裝直接操作URL、Method、Body需要自定義請求格式、臨時訪問非標準接口Clientsetkubernetes.Clientset按API Group組織起來的一套強類型客戶端內(nèi)置Pod、Deployment、Service等所有內(nèi)置資源的訪問方法絕大多數(shù)標準資源操作寫控制器必備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)后的異步處理防止事件風暴打崩控制器leaderelectiontools/leaderelection基于Lease實現(xiàn)選主多副本控制器保證同時只有一個實例在處理這套設(shè)計其實很像一個公司的內(nèi)部結(jié)構(gòu)DiscoveryClient是前臺負責告訴你“公司里有哪些部門”Clientset是標準業(yè)務(wù)接口你按部門去辦事就行DynamicClient是“臨時工窗口”不管什么類型的單子都能接Informer相當于一個企業(yè)內(nèi)部的信息推送系統(tǒng)訂閱了就有新消息自動送到桌上。1.3 Informer為什么是client-go的靈魂假設(shè)你寫了一個控制器要保證集群里的Deployment副本數(shù)始終等于期望值。最原始的做法是每分鐘全量List一次所有Deployment和期望值比較有差別就去調(diào)。這種輪詢模式有三個明顯的毛病第一集群大了反復(fù)全量List對API Server是巨大負擔第二從變化發(fā)生到你感知到變化最壞情況有一個輪詢周期控制面響應(yīng)很遲鈍第三事件一多自己的控制器也無從判斷先后順序。Informer把這三個問題一次性解決了。它首次啟動時會做一次全量List拿到所有對象的完整數(shù)據(jù)和當前resourceVersion之后建立一條Watch長連接只接收從該版本開始發(fā)生的增量變化。變化事件進入本地緩存后API Server壓力被降到最低控制器對事件的感知幾乎是實時的而且本地的狀態(tài)始終是“按事件順序回放出來的結(jié)果”一致性也有保障。真正用Informer時你會發(fā)現(xiàn)一個有意思的特性它的回調(diào)函數(shù)接收到對象后通常不是立刻去干活而是把對象key塞進WorkQueue就走。這背后是一個非常重要的設(shè)計哲學——寫控制器時事件處理邏輯和業(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ā)起細節(jié)Informer對外表現(xiàn)就是一個“對象變化的訂閱器”但實際構(gòu)造它的時候你需要給它一個數(shù)據(jù)源。這個數(shù)據(jù)源在client-go里叫ListWatch它包含了兩個動作先全量列表再持續(xù)監(jiā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}, )這里有幾個細節(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ù)想補會很麻煩。Informer跑起來之后內(nèi)部會有一個Reflector循環(huán)在做這樣的事從上一次List得到的resourceVersion開始Watch如果連接因為超時或其他原因中斷它會重新發(fā)起List然后接著Watch。整個過程是自動的你唯一需要理解的是watch斷掉之后重新List用的是“當前最新版本”不是斷線那一刻的版本這意味著斷線期間發(fā)生的部分對象變化可能會被覆蓋式地重新同步這正是為什么事件回調(diào)一定要寫成冪等的原因。2.2 三層結(jié)構(gòu)Reflector、DeltaFIFO、IndexerSharedIndexInformer內(nèi)部說白了是三段式流水線。最外層是Reflector它負責向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)。控制器代碼里常見的informer.GetIndexer().GetByKey(key)查的就是這一層緩存。它還支持自定義索引比如你想按label快速查對象可以注冊一個索引函數(shù)。用一個貼近生活的類比Reflector是外勤負責在外面收集情報DeltaFIFO是帶排序功能的收件箱外勤把情報單據(jù)一張張貼進收件箱Indexer是辦公室里的主檔案柜每次處理完最新情報就把檔案柜更新一遍。控制器查檔案的時候永遠查的是這個主檔案柜不用每次再打電話問外面。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 }這種模式幾乎成了官方控制器示例的標準骨架。它的好處是不管上游事件多密集worker永遠按自己的節(jié)奏消化任務(wù)某個對象處理失敗了也不會影響其他對象重試次數(shù)有上限不會因為一個不可恢復(fù)的錯誤把控制器拖垮。寫控制器時一定要把“監(jiān)聽到變化”和“處理這個變化”拆成兩個階段這個習慣能救你很多次。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)境準備先把依賴版本對齊否則后面全是坑寫client-go代碼前第一件事不是敲代碼而是確定版本。client-go的版本體系和Kubernetes本身嚴格對齊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ā)情況下最多積累多少個請求。默認值非常保守只有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。這個是官方文檔里不顯眼但實際作用非常大的細節(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ù)永遠與Informer內(nèi)部緩存保持一致而且不消耗API Server配額。只有在需要主動修改對象時才會用Clientset發(fā)起寫請求。3.4 讓進程體面退出context、WaitGroup與多worker并發(fā)一個生產(chǎn)級控制器不能只有Informer還必須能優(yōu)雅關(guān)閉。Kubernetes停止Pod時默認發(fā)SIGTERM信號如果你不做任何處理Informer的watch連接可能來不及關(guān)閉隊列里的任務(wù)也來不及清空留下一堆半成品狀態(tài)。標準的做法是用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消費到的事件可能因為對象還沒進緩存而被錯誤地認為“對象不存在”造成不必要的誤刪除操作。多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包默認的鎖資源是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ù)上當前Leader會被認為失聯(lián)RetryPeriod是續(xù)租的重試間隔。三者的合理比例大約是5:3:1社區(qū)普遍認可這個經(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雖然好但它只認內(nèi)置資源。你一旦開始處理自定義CRD或者做一個“什么資源都能管”的通用平臺Clientset就用不上了。這時候需要DynamicClient它操作的是unstructured.Unstructured一種把任意API對象的字段全部塞進map[string]interface{}的通用載體。使用DynamicClient的第一件事是拿到目標資源的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里取出來的類型永遠是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ā)方式是在類型定義上寫注釋標簽。比如你的類型長這樣// 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)學了client-go為什么還要學一個新框架其實controller-runtime沒有拋棄client-go它是在client-go之上做了一層更高階的封裝。它把Informer、WorkQueue、LeaderElection這些細節(jié)隱藏到Manager和Reconciler的抽象后面你只需要實現(xiàn)一個Reconcile(ctx, req ctrl.Request)方法框架自動幫你完成事件監(jiān)聽、隊列調(diào)度、失敗重試、優(yōu)雅退出等一大堆瑣事。維度client-gocontroller-runtime抽象程度底層控制力強高層API友好上手成本高要理解Informer、WorkQueue等概念相對低跟著腳手架走就行靈活性可以任意定制細節(jié)框架約定了一些最佳實踐定制復(fù)雜行為反而麻煩適合場景寫自定義控制器、深度定制邏輯寫標準Operator、CRD控制器我的個人建議是新手入門不要迷信框架先用client-go手寫一個簡單控制器把Informer、隊列、LeaderElection這些機制親手跑通再去用controller-runtime你會對IDE自動生成的那堆代碼有完全不一樣的理解。反過來如果你一上來就只會controller-runtime而完全不懂底層出了問題往往無從下手比如遇到事件不觸發(fā)、緩存不同步你連日志里Informer在報什么錯都看不明白。4.4 一個容易被忽略的場景Device Plugin周邊也需要client-go很多做異構(gòu)硬件接入的同學會接觸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è)備異?!詣e以為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細分或者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。當resync開啟時Update回調(diào)會對緩存里的所有對象重新觸發(fā)一遍如果你在回調(diào)里沒有處理“數(shù)據(jù)其實沒變”的情況可能誤以為有新事件到了。這點寫控制器的時候要心里有數(shù)。5.4 QPS與Burst設(shè)置別讓默認限流卡死你的控制器rest.Config里的QPS和Burst默認值低得驚人尤其對控制器這種事件驅(qū)動型程序來說默認5和10幾乎等于“慢性毒藥”。我之前一個巡檢控制器連接了一個500節(jié)點、上萬Pod的集群默認參數(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過濾不當、版本錯配檢查同步狀態(tài)、精簡selector、對齊client-go版本watch請求返回404/405client-go版本與API Server版本差太遠業(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)上老帖子里的代碼當死規(guī)矩go.mod里的依賴版本才是你唯一可信的基準。我寫第一個控制器時天真地把業(yè)務(wù)邏輯全塞進AddFunc結(jié)果一次批量驅(qū)逐Node事件直接把進程拖死改成“事件入隊worker消費”之后才明白這套設(shè)計不是刻意復(fù)雜而是分布式系統(tǒng)里抗壓的基本功。如果你正在寫第二個或第三個控制器把這些經(jīng)驗套進去能省掉很多凌晨三點被告警吵醒的夜晚。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
欧美极品女人的天堂| 无码一区二区三区四区五区六区七区八区九区十区视频 | 人妻精品视频一区二区| 国产97在线播放| 精品然女一区二区| 日本九九久久99播| 青娱乐国产精品| 一起草三级AV电影在线观看| 97碰碰色| 欧美性高潮在线| 囯产精品一区二区三区线|亚洲人成无码网WWW动漫|国产精品免费一级... | 精品日韩产品在线,日韩在线不卡视频,欧美日韩免费专区/久, | 欧美片第一页| 啊啊啊操死我| 91亚.色| 亚洲男人的天堂网| 男女啪啪网站免费视频| 久久久专区| 欧美爆操91| 精品99999久久久久久| 一区二区日韩欧美久久| 久7色| 99国产人成精品| 日韩精品一区的| av天堂5| 人人操人人肉久久精品| 野狼福利社区| 91天天| 日韩精品在线视频,日韩精品……| 亚洲人妻日日日| 热久久无毒不卡| 人妻色情天天操| 亚州高清AV| 9丨久久九九九| 男人的天堂va| 东北女人操逼| 国产日产精品久久快鸭的功能介绍| 看大黄色大片原件| 久久久成人国产精品无码| Av色五月| 色婷婷综合久久中文字幕雪峰| 超碰97在线 欧美 国产| 精品久久九| 亚精品无码毛片一区二区三区| 高清不卡 中文 人妻| 欧美亚州综合网图片| 男人天堂2017| .精品人妻一区二区三| 国产精品成人无码a v毛片| 国产不卡免费在线视频| 综合五月天| 5252色欧美在线| 中文字幕在线第二页| www.四虎在线| 午夜精品久久久久久久男人的天堂| 精品久久視頻在线| 97中文综合| 亚洲国产精品9999在线观看| 日韩资源网| 天躁夜夜躁2021| 欧美美女在线高潮999| 人人操人人插人人摸人人干| 久久一区二区蜜桃| 亚洲色香| 国产欧美日韩在线不卡第一页| 久久性爱精品一区| 欧美性爱18观看| 欧美韩日精品99综合| 久久25| 色91综合网| 天天综合网91入口| 亚洲自拍欧美色综合| 亚洲宗合电影| 亚洲AV无码久久精品蜜桃小说| 国产精品 久久久精品一牛| 中文操逼字幕| 最新岛国大片| 欧亚在线视频| 超碰99在线观看| 欧美激情中文字幕另类小说| 丁香五月色情| 天堂8在线新版官网| 999国产精品999| 天堂8在线新版官网| 国产精品探花视频| 亚洲精品人妻吞精av| 91久久免费视频互動交流| 日韩一区二区精彩视频| 精品久久无码午夜福利| 亚洲av无线观看| 天天日天天搞天天干| 国产强奸超碰AV| 五月丁香大香蕉| 久久黄黄| 久久999久| 亚洲限制级| 淫乱图区 | 欧洲小说色图视频另类| 无码九九| 中国一级操逼视频| 中文字幕一区二区三区蜜臀| 69久久| 被窝影院午夜看片无码| 少妇一级婬片免费放一级a性色. | 亚洲性爱电影| 五月天综合网| 粉嫩久久久极品| 国产精品免费1区2区视频| 人人干人人操人人..com| 久久色人体| 亚洲色性情三级| 国产精品色哟哟| 色麻豆AV| 国产美女自拍AV| 亚洲精品影视老司机| 亚洲综合另类| 少妇高潮一区二区三区在线| 国产亲戚伦亲在线| 日日干日日操五月天伦理视频| 欧美一区二区| 毛片电影一区二区三区| SUV一区二区在线看| 丰满熟女一区二区三区在线播放| 99爱爱| 丰满精品人妻少妇久久字幕| 男女做爰猛烈动高潮A片免费应用| 成人电影一区| 亚洲色图自拍| 国产精品熟女九色九色蜜臀| 91在线综合网| 成人av性爱电影在线观看| 亚洲综合激情五月久久| 欧美亚洲手机在线| 玖玖97综合 | 国产一区二区成人av在线播放| 亚洲午夜AV| 色香欲天天天天综合色| 日本丝袜人妻内射| 加勒比伊人综合| 日韩欧美成人性爱在线| 动漫av中文| 91欧美巨乳| 日日骚AV| 欧美性爱一区二区三区四区| 亚洲高清无码在线桃色| 中文字幕一二三av| 欧美视频在线视频免费va| 激情内射| 日韩人妻制服丝袜av| 1204av韩国| 男人天堂黄片| 一区e区三| 五月天婷婷色| 高清孕妇孕交 交| 九九热精品| 欧美亚洲丝袜人妻制服中文99| 免费观看的av| 国产农村妇女精品| 久久国模av| 91影库| 亚洲淫乱骚妇AV| 国产精品久久久久久亚洲色欲| 青青操在线亚洲视频观看欧美在线 | 欧美亚洲色图另类国产| 后入式视频国产自| 99激情视频| 男女性无套 免费九一| 国产白领连续中出在线观看| 国产九九九九九九九九| 东京热综合久久一区二区| 91老熟女逼| 97超碰久久| 国产美女激情| 东京太热久久久| 色久桃花影院在线观看| 91在线一起| 久久,精品一二三| 强奸抽插av| 999熟女精品| 亚洲色偷偷色噜噜狠狠99网| 影音先锋少妇| 蜜桃久久一区| 久久亚洲天堂| 伊人一区二区三区| 91丝袜美女国产| 日韩人妻丝袜中文字幕| 啊啊啊在线观看免费视频| 免费的很黄很污的全部视频| nuu12国产麻豆精品| 九色精品视频导航1| 九热久| 欧美激情五月天| 蜜臀无码视频在线观看| 热G综合热G中文| 中文字幕视频免费| 97一区二压| 婬女免费一二三区A片| 超碰97精品| 色老大| 亚洲日韩乱码中文无码蜜桃臀网站 | 九九九九精品| 日1区2区3区2020| 日韩欧美天天爽爽爽天天爽爽| www鬼畜国产男人的天堂| 日韩一级成人毛片免费观看| 曰韩操B| 99夜夜操| 九九九偷拍| 亚洲第一页欧美| 最近2019中文字幕国语免费版| 一级性爱啪啪视频| 草草影院日本第一页| 蜜桃狠狠色伊人亚洲综合网站| 丝袜美腿91| 色香网| 久操av在线| 少妇熟女视频一区二区三区| 操逼精品视频| 麻豆AV短剧| 吉田爱美AV在线| 色五月av| 97亚洲一区| 超碰三级秋霞| 国产亚洲国产超碰| 日逼视频日本| 久久性爱城| 亚洲天堂五月天国产| 精品免费视频国产一区| 国产在线观看一区二区三区| 大屁股人妻女教师撅着屁股| 人妻一二三区| 人妻中文字幕日韩电影| 成人电影一区| 久久国色天香香蕉| 国产天天看| 婷婷日韩一区二区三区中文字幕在线| 人妻啊啊人妻啊啊| 亚熟hd视频在线| 欧美少妇色综合| 99蜜月精品久久| 日日骚网站| 91丨精品丨国产丨丝袜| 亚洲丝袜在线观看| 久久九色| 国产精品ⅴ无码大片在线看.| 日韩免费簧片| 精品久久久高清无码| 中文字幕亚洲永久精品| 亚洲另类久操网| 亚洲最大黄网| 青青草一区二区三区四| 免费99精品国产自在在线| 亚州久久9| 嗯嗯,啊啊,国产精品| 啊嗯嗯啊好大好爽| 超碰地址久久| 黄色网址在线免费观看| 国产熟女少妇一区| 中文字幕 一区二区 亚洲无码| 97超级欧美| 日产成人久久| 久久久久久性爱免费视频| 韩日色费| 五月激情小说| 试看福利| 综合网久久| 超碰这里有精品| 免费男人的天堂| 另类专区加勒比| 东北女人高潮视频| 久草网站免费在线观看| 岛国成人av在线播放网址| 日本天堂网| 亚洲蜜臀懂色| 精品国产乱码久久久A| 大香蕉一级黄色片久久| 一区二区三区 丝袜 高跟 美腿| 欧洲亚洲综合| 久久国产乱子伦精品免费女人| 亚洲欧洲另类| aV中文麻| 婷婷激情五月综合| 操老熟女AV| 极品尤物自安慰| 夜夜国产一区| 亚洲色婷婷久久91| 久久婷婷色综合一区二区三区| 日本免费二区三区| 爱射综合| 九九九九9999| 欧美日日夜夜| 国产成人拍国产亚洲精品| 国产精品久久久三级无码| 欧美性爱伊人| 91精品久久久久久77777| 欧美另类自拍 | 激情五月天网| 国产精品久久久久久久久久久久久久吹 | 操久久久久| 殴美在线AⅤ| 日本孕妇孕交| 婷婷五月天激情网| 操逼网站网站| 亚洲男人的天堂一区二区| 久久少妇视频| 国产在线视频二区| 91欧美性| 亚洲欧美日韩夜夜| 偷拍精品一区二区三区| 激情第四色| 欧美亚洲首页| 小草三级久久观看| 国产亚洲深夜激情| 91天美传媒在线观看| 啊啊啊用力在线观看| 另类图片天天影视| 91黑丝美女| 中文字幕一二区二三区人妻专区| 日本天天干天天日一区| 日韩视频啪啪| 97超碰日韩| 日韩情色视频| 午夜福利精品| 加勒比aⅴ| 亚洲综合小视频小说在线观看 | 性91| 欧美专利1区2区3区4区5区免费| 熟女高潮合集-永久久久-成人AV | 欧美大干日韩| 亚洲一区二区三区久久 亚洲一区二区| 啊啊啊好舒服视频| 图色综合网| 成人午夜无码视频| 性色A∨91| 午夜福利在线合集| 精品人妻一区二区三区-国产| 91足交| 日韩91网| 国产不卡精品91| 无码聚合| 久九九九| 亚洲中文字幕熟女少妇一区二区| 精品国产嫩穴视频| 国内毛片欧美香蕉精品| rion磁力链接| 亚洲综合嫩| 国产性爱欧美性爱在线| 久久亚洲影院一区二区| 久99视频| 神马久久久久久伦理片| 久久九色| 天美传媒精品一区二区三区| 97资源制服丝袜| 欧美一级特黄淫片在线观看| 亚洲情色综合| 日本不卡一区| 嗯嗯啊啊啊好爽| 国产97综合| 欧美日日夜夜| 伊人黄色视频免费观看| 在线观看不卡一区二区三区| 日本性一区| 啊啊啊要高潮了| 插老姨肥穴| 天天插天天操| 一区二区三区激情在线观看| 免费在线黄片视频| 亚洲色图欧美色图日韩色图| 青青草中文字幕| 极品久久久久久久久久久久久久| 蜜臀99999| 美女诱惑在线一区| 久久久久元码视频| 蜜臀无码一区二区| 精品乱码在线观看| 屁股久久久久久久久| 久久香蕉超碰97国产精品| 成人精品欧洲亚洲| 亚洲风情综合网| 久99在线免费观看视频| 久久嫩草| 女人与公拘交酡2020视频| 嗯嗯啊啊日韩精品| 国产后入清纯| 国产又粗又长的视频| 久草精品在线| 日本二三四区| 亚洲国产精品无石码久久| 中文字幕一区二区无码成人| 国产无码成人无码| 97人人操人人摸| 日本亚洲熟女视频| 花野真衣| 97免费视频在线观看视频| 超碰爽人妻熟女Av| 1.igao73.com 加入收藏 免费专区 国产精品 中文字幕 日韩精品 欧美精品 精彩 | 澳门特级毛片免费观看| 91蜜臀在线久久久久| 中文久久一区| 色阁阁AV综合网| 日本黄页视频在线观看| 91n.欧美| 色五月AV| 国产精品分类在线观看| 亚洲国产激情国产av| 欧美性爱一内片一区二区三区| 手机久操欧美综合色码| 亚洲天天精品| 国产后入| 啪啪资源网| 成人网址在线观看| 久久久久久久久久久久久久久乱码| 偷拍片久久| 中文字幕国产在线天堂| 国模少妇一区二区三区| 99激情| 亚洲色图综合网| WWW美腿丝袜香蕉中文| 免费人成毛片乱码| 插穴性爱视频在线观看| 神马福利久草| 91天美免费| a片 xxxx受爽视频| 久9热| 欧美男人亚洲天堂| 国产1024在线播放| 天天操天天舔| 91人妻久久久久久久久久久久久| 五十路一区无码| 欧美美女视频| 伊人色综合网电影| 日韩淫色网| 国产黄色在线播放观看| 五月丁香成人网| 国产丝袜高跟美女av免费观看| 国产真乱mangent| 亚洲激情网一二三四区| 97久久超碰日韩精品| 天天色图| 国产精品久久久久无码Av网曝门 | 老女人碰碰在线碰碰视频| 日韩猛交| 精品久久久av| 嗯嗯啊啊啊好爽| 高清国产av无码| 亚州色图狠狠干| 中文久久| 性色乱AV一区二区| 78操B| 五月婷婷丁香六月| 天操老女人| 久久青娱乐| 一区操逼日比视频| 日本熟妇色熟妇在线视频播放| 香港澳门日本三级网站| 爱干爱射网啊啊啊| 国产强奸乱伦第1页| 中文字幕 人妻不满 在线视频| 蜜汁欧美| 女人天堂AV五区在线| 综合色区偷拍| 东北夫妻性偷拍| 日韩精品中文字幕人妻| 亚洲色入欧美| 一块操欧美性爱| 亚州国产成人精品女人久久| 99人人干| 久久东京热久久| 97精彩视频网站| 欧美日产国产在线成人第一区| 夜夜高潮夜夜爽| a片自拍直播视频| 99性爱视频| 国产9 9在线 | 亚洲| 96爱综合| 欧美男女午夜啪啪| 中文字幕亚洲热播人妻| 在线视频免费观看午夜| 亚洲情色 自拍| 800zy一区二区| 国产三级多多影院2022国产AA一级毛片无码 | 日韩一级欧美一级国产一级台湾| 啊a一区在线| 五月天婷婷久久| 蜜乳AV一区二区三区四| 不卡av在线中文字幕| 欧美 亚洲精品首页| 在线观看午夜婷婷久久久久清性观看| 亚洲伊人久久精品影院| 亚洲情色 自拍| 亚洲加勒比久久日本道| 成人毛片免费| 大象AV在线| 国产无码精品久久久久久| aa片毛片| 国产在线视频二区| 欧美另类综合久久| 色天使亚洲综合在线观看| 芊芊操逼视频无码| 性爱乱伦网址| 另类一区| 99热精品在线| 欧美十八禁在线看| 大香蕉人妻| 天天插天天插| AV天堂国产| 精…码一二三区| 欧美精品三级黄片| 1区2区3区视频| 青草伊人网| 亚洲 欧美 日韩另类 麻豆| 大学生口爆吞精| 久操视频免费观看| 国产99999| 99精品人妻| 亚洲国产成人福利在线观看| 免费簧片在线观看| 日韩AV一区二区三区四四| 欧美亚洲AN| 91美| 蜜臀中文字幕| 九九探花视频在线观看| 一区二区三区国产精产| 97操B| 日本免费中文字幕在线| 久草综合京东| 日本三级A片网站com| 日本精品999| 操逼视频色| 色综合一区二区三区| 极品欧美一区二区三区| 国人欧美精品一区二区| 91亚洲精品青草| 亚洲91大片| 老司机香蕉久久久久| 8x福利精品第一福利视频导航| 五月香婷婷| 五月天激情网图片| AV中文在线| 91在线色综合| 日本久操视频| 黄片免费看的| 国产a片操逼| 成人免费不卡在线视频| 亚热日本熟女| 九九九热| 亚欧成人中文字幕一区| 韩国一区二区精品亚洲| 97视频新免费| 久热精品在线| 亚洲加勒比久久日本道| 成人三一级一片aaa| 后入内射蜜桃臀| 自拍六区| 欧美日本国产日韩激情视频| 91高跟美女在线播放| 亚洲永久永久永久永久一级一级一级精品| 五月久久HDAV| 人妻一区久久二区三区色播| 亚洲欧美日韩中文播放| 色婷婷电影网| 欲女人妻性色av| 国语av狠狠色丁香婷婷综合激情| 久久久成人国产精品无码| 日本精品人妻少妇一区二区| 殴美色网| 99色在线观看| 国产精品白丝AV| 国产精品自在自拍视频| 夜夜嗨一区二区三区三州加勒比| 精品一区二区成人动漫| 吊色| 日本久久女同性恋视频| 日本欧美不卡| 另类亚洲一区二区三区| 蜜臀人妻少妇久久在线观看| 亚洲综合首页| 婷婷五月av| 91劲爆| 欧美操逼熟女| 亚洲色性情三级| a片偷拍视频| 国产免费大片| 久久久男人的天堂| 日韩乱中文| 920日本午夜免费| 精品无吗m| 美女国产一区二区久久| 佐山爱中文字幕| 色爽——AV| 麻豆尤物视频网| 亚洲AV无码乱码在线观看性色| 嗯嗯不要视频| 91在线免费观看处女| 欧美日韩插逼视频| h色99999| 97最新在线播放视频| 无码视频黄色网战| 99蜜桃臀久久久欧美精品网站| 99999亚洲另类| 在线观看黄色电话| 日本熟妇色熟妇在线视频播放| 日本熟妇浓毛hdsex| 天天日夜干| 精品人妻av区天天看片| 五月婷婷激情网| 亚洲永久永久永久永久一级一级一级精品 | 欧美一级久久久丰满| 一区,二区,三区网站| 最新AV在线| 婷婷色导航| 97久久久久| 婷婷亚洲五月***久久| 日本天堂在线播放| 五月丁香啪| 丰满少妇一区二区三区免费看| 国产精品自在自拍视频| 久久成人东京热人妻| 日本操嫩b网| 人妻久热在线| 国产高清26uuu| 东京热大香焦| 成人资源中文字幕在线观看天天| 国产综合久久久麻桃个| 亚洲另类色图片| 免费亚洲黄色视频在线观看| 中文字幕人妻资源在线| 天天操狠狠日夜夜干超碰撸com视频在线观看 | 美女诱惑久久| 欧美成人色| 亚洲乱码尤物193YW| 97欧美精品| 秋霞一区二区三区四区五区六区七区| 日本人人操人人操| 97干97色| 超碰这里只有精品| 午夜电影在线观看无码专区| 色九九综合AV| 欧美日韩性感| 成人a级高清视频在线观看| 男人 天堂 日 亚洲| 国产麻豆一级精品视频| 热99re69精品8在线播放| 999九九精品| 熟妇在线视频一区二区| 国产精品一区二区手机看片| 欧美综合狠| 日本久操视频| 日韩人妻一区二区精品| 久久午夜鲁丝片| 日韩人妻精品中文字幕| 亚洲,欧美,春色,另类| 十八禁av无码免费网站APP| 色97欧美| 今日头条成人一区二区三区四虎精品| 嗯嗯啊啊视频在线看| 在线v中文字幕一区二区三区 | 人人操人人色网| 97欧美日韩中文| 亚洲日韩精品在线播放| 双插性欧美一二三区| 超碰色老头| 精品无码产区一区二| 久久国产精品,久久国产| 熟女五十路一区二区三| 国产操逼视频在线观看| 国产精品免费久久久久久久久久| 0755午夜福利视频| 天天操天天日青青草超碰av| www.97在线| 成人免费在线网站| 国产精品嫩草影院免费| 久久五月天婷婷丁香中文字幕| 久久风骚城市| 99精品综合久久久久五月天| 97人人爱人人做人人乐| 狠狠狠狠狠狠| 亚洲欧洲国产综合av| 成全在线观看免费观看| 男女猛烈无遮掩视频免费软件| 综合色一区三区二区| 亚洲成人帖图| 肥臀熟女一区二区三区视频| 我想要啊 啊 啊| 亚洲在钱| 欧美91丝袜| 欧美人人天天网| 97 国产一区| 欧美日韩人人精品| 天天插天天射| 欧美精品久久96人妻无码| 亚洲日韩人妻中文字幕一区| 欧亚乱色熟一区二区三四区| 性影在线视频| 另类小说综合网| 日本成人免费一区二区三区| 精品欧美老熟女一二区| 国产精品久久| 男人的天堂2018| 欧美伊人久久综合网| 天天色天天干天天射| 眼镜人妻101.com| 午夜视频久久久久一区| www国产天美久久久| xxx0国产在线播放| 久久精品国产免费观看99| 九九色影院| 骚逼高潮久久精品| 91在线综合网| 超碰97玖玖爱| 蜜臀久久精品久久久久视频| 制服中出中文人人精品| 人妻精品一区二区三区| 欧美一级黄色免费专区| 日韩 欧美 视频 在线 一区| 日韩AC| 欧美日韩性爱操大逼| 成人日韩欧美| 天美欧美国产| 欧美97色| www久久国产精品| 亚洲国产欧美一区二区潘金莲| 亚洲暴力强奸AV| 色噜噜综合在线| 天天摸天天碰天天添青青| 日本人体九九九九九九| 国产一区96在线| 日本最新免费韩国1区2区视频播放| 国产精品在线一区二区| 精品人妻中文字幕高清| 亚洲欧美中文一区二区三| 欧美夜夜狠| 1000午夜黄色| 亚洲日韩视频二区| 成人电影一区| 久久人妇| 超碰97COm中文| 国产亚洲精品久久久久小| 天综合中文| 精品无码一区二区三区| 少妇啪啪自拍| 亚洲欧美大香蕉| 色色九区| 欧美三级中文字幕hd| www.色婷婷| 高清无码人妻久久久一区二区三区aⅴ| 亚洲情色91| 一级性爱啪啪视频| 日韩97视频!在线| 欧美日韩小说| 国产久久久久久久久一区二区| 玖玖爱一区在线| 熟妇乱伦一区二区| 色婷婷影视| 色臀aV| 91亚洲色人| 91色综合激情| dy888午夜老子影视达达兔| 操逼片中文| 亚洲资源网| 播播亚洲小说亚洲| 玖玖超碰熟| 91精品人妻偷情| 五月天婷婷久久| 久久久极品| 久久小视频| 亚洲精品97久久| 人妻啊啊人妻啊| 四虎精品亚洲| 婷婷五月天福利| 亚洲日韩天堂| 五月丁香六月激情综合| 好爽免费视频| 亚州色站 日韩电影| 成在线人在线观看视频| 欧洲大香蕉| 岛国黄色大片网站| 日韩BBN| 97精品综合| 国产剧情在线| 久久精品免视看国产成人﹣蜜臀av一区. 久久精品免视看国产成人,蜜臀av一区 | 尤物av网站免费在线播放| 熟妇熟女一区二三区| 黄色视频60分钟| 亚洲熟女乱综合一区二区三区| 午夜福利在线合集| 亚洲黄色网址| 色情成人五月天| 亚洲天堂在线怕怕视频| 欧美亚洲韩国视频十五区| 香蕉在线一区二区三区| 天天色,天天干,天天干| 骚熟女AV网| 不卡超碰护士AV在线免费播放| 天天做天天爱夜夜爽毛片试看| 亚洲无限观看| 中文字幕 人妻不满 在线视频| 欧美黄色手机在线观看| 国产精品粉嫩福利在线| 天天摸,夜夜摸| 高清有码一区二区| 亚洲 欧美 第一页| 色av中文字| 99re公开精品免费视频| 97干色| 久久久成人免费av电影| 97硬碰| 国产日本熟女顶级一区二区三区视频| 亚洲操逼无码| 免费的很黄很污的全部视频| 1769一区| 91日韩国产欧美亚洲另类精盘州至城都| 老女人碰碰在线碰碰视频| ,国产乱人伦精品一区二区三区| 十八禁视频网站| 欧美,日韩综合久久| 亚洲色图一区二区三区| 久久熟妇五十路一区| 丝袜AV一二三区| 99精品在线播放| 97福利视频| 国产97色在线| 色欲天天综合网| 国产又色又粗又黄又爽| av毛片aaaaa免费看| 成人怡红院| 欧美色欧美| 天天综合网日韩| 国产色图乱伦| 99中文字幕| 亚洲色图欧洲| 91春色| 日韩欧美亚洲自拍偷拍| 中文字幕一二三| 探花精品 一区二区| 国产二区三区免费视频| 蜜乳AV免费观看| 波多野结衣被操50分钟免费视频| 免费1级a做爰片观看| 天天懆天天日| 欧美日韩香蕉| 90后性网国产欧美| 欧美亚洲综合色| 中文字幕亚洲欧美在线不卡| 热久久九九热| 91亚洲狠狠色| 久久久久久久久一区二区三区| 超碰91在线| 亚洲啪啪视频免费| 日人妻视频91| 五月天婷婷基地| 亚洲瓯美色图| AV色五月| 亚洲少妇视频| 最新日本中文字幕| 日韩亚洲中文字幕在线| 婷婷伊人网| 综合亚洲情色| 国产乱码久久久久久| 网友自拍第1页| 亚洲国产ⅴ高清在线观看| 美国日韩黄色片| 大香蕉伊人亚洲| 国产精品乱码久久久久久| 91亚洲欧洲| 亚洲成a人片在线观看中文!!!| 国产人妖视频一区在线观看| 911粉嫩人妻| 97视频网站在线观看| 在线观看午夜婷婷久久久久清性观看| 97人人爱人人乐| 性饥渴少妇av无码毛片| 精品无码久久久久久国产浪潮| 手机在线视频国内精品| 国语国产操逼伊人AV网| 99热网站| 男人天堂日日夜夜| av天堂加勒比| 色图综合网| 国产精品久久久久中文字幕| 超碰97起碰| 国产精品亚洲四五区在线观看| 美女网站黄页| 国产又黄又爽又刺激久久久久久| 欧美一级A片在线看视频性色| 天天日老熟妇| 久草成人影片| 日韩免费三级黄片电影| 激情99| 劲爆欧美人妖三区91| 大色综合| 丁香五月久久| 日韩色女精品| 性影在线视频| 水澄无码AV| 丁香五月偷拍| 亚洲人精品午夜不卡| 69天堂| 乱论91| 欧美日韩电影一区二区| 91国产丝袜白虎| 3d成人精品一区二区| 高树玛利亚无码流出| 欧美色91| 黑人精品成人一区二区三区 | 最新av在线| 91精品丝袜久久久久久| 日本色色色视频| 黑丝日韩av丝袜av| 白丝被操91| 久久久久久久久久久六六| 欧美97免费| 日本性爱少妇| 爱干爱射网啊啊啊| 欧美黄色手机在线观看| 江都AV在线| 午夜舔阴达高潮视频免费看| www久久久| 亚洲精品不卡一二三区| 精品人妻一区| 天天综合网合集91| 综合免费无码中文| 97久久国产亚洲精品超碰热| 嗯啊抽插大香蕉网页| 色爽——AV| 人人摸人人摸人人干| 精品然女一区二区| 综合操逼| 五十路熟女,国产欧美精品区一区二区三区| 草草网站影院白丝内射| 夜色97| 中国一级操逼视频| 久草热制服丝袜在线观看| 亚洲一区日韩精品中文字幕| 欧美男人一区| 亚洲成人激情小说视频| 国产嫩草精品A88AV在线| 欧美性色网| 亚洲s在线观看| 国产自产自拍| 精品无码一区二区人妻久久蜜桃| 中文字幕av乱伦| 97免费视频在线| 暖暖精品二区三区观看| 伊人久久在线视频观看| 欧美亚洲韩国视频十五区| 国产91久久九九免费精品无码| 嗯嗯啊啊啊好爽| 美女露胸露屁股| 久久大黄片| 韩日精品福利视频一区不卡在线免 | 嗯嗯啊在线视频| 中文字幕乱码人妻二区三区| 综合激情一一91| AV天天在线观看| 蜜乳中文字幕a在线| 1区2区3区中文字幕日韩| 久久久国产成人一区二区三区在线| AAAA级日本片免费视频| 中文字幕久久亚州无码| 五月婷婷综合网| 国产 日韩 欧美高清| 蜜臀久久99精品久久久久久婷婷| 激情小说亚洲视频| 蜜臀亚洲中文| 久久精精区一区二区一蜜桃一区二区| 视频黄色国产一级| 欧美片第一页| 久久久久女教师免费一区| 欧美日韩国产中文超碰| 日韩成人性爱AV| 九色黄站| 91综合天天看| 天天操人人操骚逼网站| 久久人妻97久久久久久久| 芊芊操逼视频无码| 97碰碰色| 综合九九| 青青草日本中文字幕| 国产人妻精品久久久一区二区三区 | 日韩欧美日韩| 97久久超碰日韩精品| 色香综合天天影视综合 | 91人妻尻屄视频| 欧美自拍偷拍综合图片| 青青草公开在线免费不卡视频| 日日噜噜夜夜久久亚洲一区二区| 五月丁香网站| 中文字幕交换人妻| 国产91乱伦| 久久东京伊人一本到鬼色| 超碰国产精品无码| 青娱乐啪啪视频| 日韩综合97p| 91天美免费| 在线免费试看60秒| 试看60秒| 熟妇国产免费一区| 1024午夜激情男人的天堂| 91/欧美| 久久亚码| 蜜臀无码一区二区| 国产风韵犹存熟妇三区| 久久精品视-一级做a爰片性色毛片16美国-中国女与老外在线精品 | 狠操91,com| 激情久久av一区av二区av| 青青草吊丝| 亚洲影院小综合| 日日橹狠狠爱欧美超碰| 在线啊啊啊啊| 精品国产乱码久久久久久影片| 爽爽歪在线视频| 精品v1区| 蜜桃臀久久| 78精品| 少妇久久久久久| 久久无码一区二区二三区性色| 操操操五月天婷婷丁香影院| 18禁中文字幕| 欧美日韩操操操| 伊人AAA| 婷婷四五区| 日韩美女高潮喷水视频| 精品美女人人干| 校园春色美腿丝袜 | 国产精品久久久久久久久AV大片| 黄网在线播放| 欧美高清性猛交| 久久禁| a男人的天堂久久一级A毛片| 99re热有精品视频国产| 中文字幕亚洲在线一区| 日韩亚洲美州欧洲综三区一品在线| 少妇精品久久久| 97免费在线观看| 欧美另类综合久久| 日韩操人| 国产视频小说| 东北少妇高潮zzzz| 国产人妻天天干精品| 欧美综合色站| 精品人妻一区二区三区四区| 黄色av网站在线播放| 婷婷久草一区二区三区| 呦女网站| 1769国内精品视频| 亚洲天堂综合AV| 超碰偷拍| 日韩Va亚洲va欧美Ⅴa久久| 亚洲 欧美 中文 日韩超碰| 97精品中文字幕| av一区二区三区不卡| 久久伊人大香蕉| 亚洲91大片| 青娱乐欧美激情一区二区| 精品国产少妇高潮视频| 99精品无码| 综合欧美日韩在线观看| 在线一区| 日韩操啪| 2001天天操| 久久久涩| 欧美很很操视频| 97天天在线| 精品午夜福利| 丁香激情网| 青青青草伊人精品| 亚洲一区二区三区不卡国产欧美| 日韩在线视频1234| 国产精品久久久亚洲第一牛牛_在线观看| 国产亚洲日韩在线三区黑人| 中文字幕97色| 欧美一级特黄淫片在线观看| 美腿丝袜偷拍亚洲欧美| 啪啪视频亚洲第一| 99re99视频在线免费观看| 天天插夜夜操| 都市激情人妻一区二区青青操视频 | 夜夜草我| 97人人爱人人做人人乐| 中国和日本人色哪个不下载能放| 国产成人无码网站在线视频| 99爱爱| 淫荡少妇免费| 亚州综合图片| 艹比视频国产精品| 竹菊一区二区三区AV线| 亚洲97成人在线观看| 夜夜夜久久| 人妻干天天| 久草草一二三四区久久| 亚洲Av无码成人精品国产| 亚洲狠狠入| 91婷婷伊人狠人| 91九色丨风韵犹存| 熟妇视频一区二区三区在线观看| 八戒无码国产午夜福利| 亚洲日韩XXX| 色色色综合| 乱操乱伦AV| 九七人妻在线| 精品一区二区啪啪啪| 精品无码久久久久久久杏吧| 国产丝袜美女诱惑| 搡老女人老妇女AAA一VU麻豆| 成人草草视频| 欧插网站| 国产专区第一页| 欧美色网络| 操操操操网黑人| 欧美国产日韩高清在线| 手机午夜电影神马久久| 色偷偷人人玩人人舔人人操人人摸人人爽 | 欧美强奸乱| 另类亚洲图色| 日本操色导航| 天天干18禁| 精吧天堂| 亚州操操穴网| 国产女生在线| 国产强奸无码乱伦| 新怡红院| 骚逼一区二区| 亚洲宅男天堂| 婷婷去俺也去六月色| 风骚少妇视频中文字幕| 日本美女性生活久久久久久久| 亚洲学生妹高清av| 大香蕉综合在线| 精品免费一区二区三区在线亚洲人成| 黄色小视频日本txt| 亚洲āv网址在线观看| 色汉综合| 中文字幕老熟妇黄色视频| 国产免费内射视频| 91亚洲狠狠色| 激情综合 婷婷五月 红杏| 老熟女综合网 | 成人亚欧免费视频| 国产精品视频在线观看| 另类图片五月| A片三级无码| 中文久久爆乳| 人人操人人狠狠操| 亚洲 日韩 欧美 国产综合体| 色香蕉影院| 男人的天堂啪啪| 狠狠狠一区二区三区| 久久九七| 欧美 综合 亚洲| 精品久操| 国产400孕妇孕交群| 成人线上超碰| 一区在线精品中文字幕| 日本熟女不卡视频| 亚洲欧美综合区自拍另类| 天天草天天干天天日| 九九碰九九爱97超碰| 久久大香蕉手机高清| 欧美 日韩 婷婷 五月|