青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Fork me on GitHub
隨筆 - 215  文章 - 13  trackbacks - 0
<2017年1月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
2930311234


專注即時通訊及網游服務端編程
------------------------------------
Openresty 官方模塊
Openresty 標準模塊(Opm)
Openresty 三方模塊
------------------------------------
本博收藏大部分文章為轉載,并在文章開頭給出了原文出處,如有再轉,敬請保留相關信息,這是大家對原創作者勞動成果的自覺尊重!!如為您帶來不便,請于本博下留言,謝謝配合。

常用鏈接

留言簿(1)

隨筆分類

隨筆檔案

相冊

Awesome

Blog

Book

GitHub

Link

搜索

  •  

積分與排名

  • 積分 - 220951
  • 排名 - 117

最新評論

閱讀排行榜

轉自:https://my.oschina.net/caicloud/blog/829365
著作權歸作者所有,轉載請自覺標明出處,以示尊重!

大家好,我是徐超,從事 Kubernetes 開發已經兩年多了。 

今天,我從一個開發者的角度來講一講 client-go repository,以及怎么用 client-go 搭建 Controller。同時,也給大家講一講開發過程中遇到的坑,希望大家在開發的時候可以繞坑而行。

另外,我還會講一下 Kubernetes 的 API,讓 controller 功能變的更加強大。

那我們現在先來講,有哪些方法可以跟 APIserver 進行通訊。最常用的,可能就是 kubectl,以及官方支持的 UI,Kube Dashboard,這是 google 最近投入很多的一個項目。

開發過程中 debug 的時候可以直接去調用 k8s 的 Restful API,通過寫腳本去實現 Controller。

但是,這些做法無論從效率還是可編程性來說都是不太令人滿意的。

這也就是為什么我們要創建 client-go,我們其實就是把寫 controller 所需的 clients,utilities 等都放到了 client-go 這個 repository 里面。大家如果需要寫 controller 的話,可以在這里面找到所需要的工具。client-go 是 go 語言的 client,除了 go 語言之外,我們現在還支持 python 的 client,目前是 beta 版本。但是這個 python client 是我們直接從 open API spec 生成的,之后我們會繼續生成 client Java 或者一些其它的語言。

我們先看一下 client library 的內容。它主要包括各種 clients:clientset、DynamicClient 和 RESTClient。還有幫助你寫 Controller 時用到的 utilities:Workqueue 和 Informer。

我們先看一下 kube-controller 的大致結構,典型的 controller 一般會有 1 個或者多個 informer,來跟蹤某一個 resource,跟 APIserver 保持通訊,把最新的狀態反映到本地的 cache 中。只要這些資源有變化,informal 會調用 callback。這些 callbacks 只是做一些非常簡單的預處理,把不關心的的變化過濾掉,然后把關心的變更的 Object 放到 workqueue 里面。其實真正的 business logic 都是在 worker 里面, 一般 1 個 Controller 會啟動很多 goroutines 跑 Workers,處理 workqueue 里的 items。它會計算用戶想要達到的狀態和當前的狀態有多大的區別,然后通過 clients 向 APIserver 發送請求,來驅動這個集群向用戶要求的狀態演化。圖里面藍色的是 client-go 的原件,紅色是自己寫 controller 時填的代碼。

我們來仔細看一下各種 clients。

先講最常見的 Clientset,它是 k8s 中出鏡率最高的 client,用法比較簡單。先選 group,比如 core,再選具體的 resource,比如 pod 或者 job,最后在把動詞(create、get)填上。

clientset 的使用分兩種情況:集群內和集群外。

集群內:將 controller 容器化后以 pod 的形式在集群里跑,只需調用 rest.InClusterConfig(),默認的 service accoutns 就可以訪問 apiserver 的所有資源。

集群外,比如在本地,可以使用與 kubectl 一樣的 kube-config 來配置 clients。如果是在云上,比如 gke,還需要 import Auth Plugin。

clientset 是用 client-gen 生成的。如果你打開 pkg/api/v1/tyeps.go,在 pod 的定義上有一行注釋,叫做“+genclient=true”,這句話的意思是,需要為這個 type 生成一個 client,如果之后要做自己的 API type 拓展,也可以通過這樣的方式來生成對應的 clients。

Clientset 的動詞很多細微的地方比較燒腦,我來幫助大家理解一下。

我們先來說 Get 的 GetOptions,這是 1.6 的 feature,如果在里面看 client 的 get 的話,有一個 field,叫做 resource version。

resourece version 是 kubernetes 里面一個 logical clock,用作 optimistic concurrency。如果沒有設置 resourceversion,api-server 收到請求后會從 etcd 讀出最新的值。但設為 0 的話,APIserver 就會從 local 的 cache 里面把值讀取出來,cache 的值可能會有一定的延遲。這樣可以減輕 APIserver 和 etcd 后端的壓力。現在是用得比較多的是 kubelet,經常要 get node status,但是不需要最新的 node status,如果集群很大,就能夠省不少 cpu/memory 的開銷。如果 resource version 設成非常大的值,get request 會在 api-server 掛起,沒有響應的話會 time-out。

同樣的,在 list 這個操作的時候,你可以提供一個 listOption,這個 listOption 里面也有 resource version,和 get 里的意義一樣。我們在寫 informer 的時候會用到。因為每一個 controller 在啟動的時候,會向 api-server 發送 list 請求,如果每一個 request 都是從 etcd 里讀取過來的話,這個開銷非常大,所以 list 會從 api-server 的 cache 讀取。

在 watch 里面也有一個 listOption,里面 resrouce version 的意義不一樣。在 watch 的時候,apiserver 會從這個 resuorce version 開始所有的變化。這里的 best practice 設置成:永遠要設置 resource version。因為如果不設置,那么 APIserver 就會從 cache 里隨便的一個時間點開始推送,令 controller 的行為不好預測。

我們看 informer 是怎么使用 list 進行 watch 的。在 informer 里面,我們一般都是先 list,把 resource version 設為 0,API Server 就可以從 cache 里面給我 list。List 完之后,把 list 的 resource version 取出來,并且設置為 watch 的 listOption,這樣就可以保證 informer 拿到的 events 是連續的。

另外要注意的是,watch 不是一勞永逸的,apiserver 會 timeout 一個 watchrequest 的,默認值是 5~10 分鐘。這時你需要重新 watch。

說一下這個 update,client 里面有兩種 update:Update 和 UpdateStatus。

他們的區別是,如果你 Update 一個 pod,那么你對 status 的修改會被  API server overwrite 掉。UptateStatus 則相反。

k8s 有 OptimisticConcurrency 機制,如果有兩個 client 都在 update 同一個,會 fail。所以寫代碼時一般會把 update 寫到 loop 里,直到 api-server 返回 200,ok 時才確定 update 成功。

另外,使用 get+update 有一個 bug:假設 cluster 的 pod 有一個新的 field,如果你使用一個舊的 client,它不知道這個新的 field,那么 get 到的 pod 是沒有這個新的 field 的,再 update 的時候,這個新的 field 會被覆蓋掉。

可能會在 1.7 的時候把這個 bug 處理掉。

跟 update 相對應的就是 patch。Update 像拆遷隊,只會把整個 object 推倒重做。Patch 則像手術刀,可以做精細操作,可以精確修改一個 object 的 field。

patch 如果有 conflicts,會在 apiserver 重試 5 次。除非有用戶 patch 同一個 field,否則一般 client 會一次 patch 成功。當然 patch 有性能問題,因為要在 API serve 做 Json serialiation 和 deserialization。我們估計會在 1.7 的時候優化。如果不關心性能,我們還是推薦用 patch。

提醒一下:你在做 Patch 的時候,最佳實踐是把 original 的 UID 填在 patch 里。因為 API server 的 key-value store 是以“namespace + name”作為 key 的。在任意一個時間,這個組合都是唯一的。但是如果把時間這條軸加進來的話,比如你有一個 pod,刪除后過了一會兒,又在同一個 namespace 下建了同名的 pod,但是把所有的 spec 都改掉了,那么 controller 舊的 patch 可能會被應用到這個新建的 pod 上,這樣就會有 bug 了。如果在 patch 里加入 uid 的話,一旦發生剛才所說的情況,apiserver 會以為你是要修改 uid,這個是不允許的,所以這個 patch 就會 fail 掉,防止了 bug。

Delete Option,有一個選項叫 precondition,它有一個 uid 選項。也是為了防止 namespace+name 的組合在時間軸上不唯一。

當時,我們發現 K8S 的 CI tests 經常會莫名其妙的 fail 掉。最后我發現是因為剛 create 的 pod 跟之前已經被刪除的 pod 重名,但是 kubelet 不知道,就把新的 pod 給誤刪除了。所以我們 delete 的時候,這個 precondition 的 UID 請勿刪除。

 

Delete 從 1.4 開始有一個 field 叫做 OrphanDependents。如果設為 true 或者 unset 的話,當 delete()返回的時候,這個 object 可能會在繼續存在一會兒,雖然最終還是會被刪掉。另外,這個時候,如果你把 OrphanDependents 設置成 true 或者不設置的話,要刪除的 Dependents 是不會被刪除的。如果設成 false,只要 delete()返回了,這個 object 就肯定已經在 apiserver 上被刪掉了,除非你另外設置了 finalizer。并且 garbage collector 會在背景里面慢慢刪除 dependents。

現在講一下另外一種 client,叫做 dynamic client。

dynamic client 用法比較靈活。因為你可以任意設置要操作的 resource。它的 return value,不是一個 structure,而是 map[string]interface{}。如果一個 controller 需要控制所有 API,比如 namespace controller 或者 garbage collector,那就用 dynamic client。使用時可以先通過 discovery,發現有哪些 API,再通過使用 dynamic client access 所有的 api。dynamic client 也支持 third party resources。

dynamic client 的缺點是它只支持 JSON 一種序列化。而 JSON 的效率遠遠低于 proto buf。

現在我們講一下 rest client。

Rest Client 是 client 和 dynamic client 的基礎。屬于比較底層的,跟 dynamic client 一樣,你可以使用它操作各種 resource。支持 Do() 和 DoRaw。

相比 dynamic client,支持 protobuf 和 json。效率會比較高。

但是問題就是,如果你要 access third party resource,需要自己寫反序列化,不能直接 decode 到 type。在 demo 里會進行演示。

現在我們講 informer,它的 input 其實就兩個,一是要 list function 和 watch function,二是你要給 informer 提供一些 callback。informer 跑起來后,它會維護 localstore。你之后就可以直接訪問 localstore,而不用跟 APIserver 通訊。提高一些 performance。

使用 informer 的好處一個是性能比較好,還有一個是可靠性。如果有 network partition,informer 后會從斷點開始繼續 watch,它不會錯過任何 event 的。

Informer 也有一些 best practice,第一點,在 controller run 之前,最好等這些 informer 都 sync 了(初始化)。這樣做,一是可以避免 controller 初始化時的 churn:比如 replica set controller 要 watch replica set 和 pod,如果不 sync 就開始 run,controller 會以為現在沒有任何 pod,會創建很多不必要的 pod,之后還要刪除。二來就是會避免很多很詭異的 bug。我在寫 garbage collector 的時候就遇到過不少。

另外 informer 提供的 localcache 是 read-only 的。如果要修改,先用 DeepCopy 拷貝出來,否則可能有 read-write race。并且你的 cache 可能是和其他 controller 共享的,修改 cache 會影響其他 controller。

第三個要注意的地方就是,informer 傳遞給 callbacks 的 object 不一定是你所期待的 type。比如 informer 追蹤所有 pod,返回的 Object 可能不是 pod,而是 DeletedFinalStateUnknown。所以在處理 delete 的時候,除了要處理原來跟蹤的 object,還要處理 DeletedFinalStateUnknown。

最后要講一下的就是,informer 的 resyncoption。它只是周期性地把所有的 local cache 的東西重新放到 FIFO 里。并不是說把 APIserver 上所有的最新狀態都重新 list 一遍。這個 option 大家一般都是不會用到的,可以放心大膽地把這個 resync period 設成 0。

最后再講一下這個 workqueue。

其實主要是為了可以 concurrent processing,可以并行地讓 Callbacks 把狀態加到 workqueue 里,然后起一大堆的 worker。

workqueue 提供的一個保障就是,如果是同一個object,比如同一個 pod,被多次加到 workqueue 里,在 dequeue 時,它只會出現一次。防止會有同一個 object 被多個 worker 同時處理。

另外 workqueue 還有一些非常有用的 feature。比如說 rate limited:  如果你從 workqueue 里面拿出一個 object,處理時發生了錯誤,重新放回了 workqueue。這時,workqueue 保證這個 object 不會被立刻重新處理,防止 hot loop。

另外的一個 feature 就是提供 prometheus 監控。你可以實時監控 queue 的長度,延遲等。你可以監控 queue 的處理速度是否跟得上。

現在我給大家做一個 demo(https://github.com/caesarxuchao/servicelookup)。通過 k8s 的 api 用戶是沒辦法很快通過 pod 的名字找到對應的 service 的。當然你可以找到這個 pod 的 label,然后去跟 selector 進行比較而確定 service,但做這種逆向查詢是非常費時間的。

所以我這里就是寫了這樣一種  controller,watch 所有的 endpoints 和 pods,來做比對,找到 pod 服務的 service。

我先啟動兩個 informer,1 個 informer 是追蹤所有 pods 的變化,另一個追蹤所有 endpoints 變化。

給 informer 注冊 callback,來把 pod 和 endpoint 的變化放到 workqueue。

然后啟動許多 worker,從 workquue 里拿出 pod 和 endpoint 做比對。

運行時,先啟動兩個 informer,等它們 sync,最后啟動 worker。

Demo 的代碼在 github 上,https://github.com/caesarxuchao/servicelookup。
視頻鏈接:http://v.qq.com/iframe/player.html?vid=c03641vzw2m&width=670&height=502.5&auto=0

posted on 2017-01-23 17:06 思月行云 閱讀(574) 評論(0)  編輯 收藏 引用 所屬分類: Docker\K8s
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲午夜91| 亚洲男女自偷自拍图片另类| 久久久久一区二区| 久久国产乱子精品免费女 | 性亚洲最疯狂xxxx高清| 99视频有精品| 欧美久久久久久久久| 老司机一区二区| 精品动漫一区二区| 国内精品伊人久久久久av影院| 久久久午夜电影| 日韩视频精品在线| 久久久国产成人精品| av不卡在线看| 樱桃成人精品视频在线播放| 欧美理论在线播放| 久久av最新网址| 欧美成人网在线| 亚洲精品1234| 黄色成人小视频| 在线观看一区欧美| 狠狠色噜噜狠狠色综合久| 99re66热这里只有精品4| 亚洲成色精品| 国产亚洲一区二区精品| 国产精品影片在线观看| 欧美大片在线观看| 欧美gay视频| 欧美黄色片免费观看| 久久午夜精品一区二区| 欧美一区高清| 久久久久国产精品www| 久久天堂精品| 亚洲高清免费| 欧美夫妇交换俱乐部在线观看| 久久免费视频观看| 国产精品一区在线观看你懂的| 性伦欧美刺激片在线观看| 国产精品亚洲不卡a| 一区二区三区日韩在线观看 | 亚洲欧美视频在线观看| 国产精品五月天| 国产精品视频观看| 国产酒店精品激情| 伊人婷婷欧美激情| 一本色道久久综合亚洲二区三区| 亚洲一级在线观看| 久久精品中文字幕一区二区三区| 蜜桃久久精品乱码一区二区| 亚洲精品一区二区三区99| 亚洲激情六月丁香| 午夜一区在线| 欧美日韩国产精品专区| 国模精品一区二区三区色天香| 亚洲三级视频在线观看| 欧美有码在线观看视频| 91久久久国产精品| 久久久噜噜噜久久中文字幕色伊伊 | 亚洲大胆av| 午夜精品免费在线| 欧美高清视频一区二区三区在线观看| 国产精品网站在线观看| 一区二区三区四区国产精品| 麻豆精品在线播放| 亚洲综合精品四区| 国产精品99一区二区| 亚洲美女中出| 久久婷婷影院| 国产农村妇女精品一区二区| 一区二区三区精品在线| 欧美成人69av| 久久九九全国免费精品观看| 国产美女精品| 午夜精品久久久久久久蜜桃app| 久久国产欧美日韩精品| a4yy欧美一区二区三区| 久久国产精品99国产精| 好看的av在线不卡观看| 久久gogo国模啪啪人体图| 亚洲精品一区二区三区蜜桃久| 欧美成人69av| 亚洲人成艺术| 亚洲第一视频网站| 久久网站免费| 亚洲精品黄网在线观看| 亚洲国产精彩中文乱码av在线播放| 久久精品人人做人人综合 | 亚洲在线视频| 欧美日韩情趣电影| 99re热精品| 亚洲欧洲日本在线| 欧美日韩国产欧美日美国产精品| 亚洲精品欧美日韩专区| 91久久久一线二线三线品牌| 欧美激情一区在线| 亚洲新中文字幕| 宅男精品导航| 国产色综合网| 欧美成人午夜免费视在线看片| 久久九九国产精品| 日韩午夜三级在线| 99精品久久| 国产一区在线看| 亚洲国产精品va在线看黑人| 欧美日韩中文字幕| 日韩一级黄色av| 亚洲美女免费视频| 国产欧美欧美| 欧美成人午夜77777| 欧美日韩一区二区视频在线| 午夜精品久久久久久久久久久久久| 亚洲一区日韩在线| 亚洲电影av在线| 日韩午夜在线观看视频| 国产视频观看一区| 欧美激情免费观看| 国产精品一区二区久久久| 可以看av的网站久久看| 欧美日本国产一区| 亚洲午夜精品久久久久久浪潮| 日韩视频精品| 亚洲高清久久网| 亚洲一区二区精品| 亚洲品质自拍| 欧美亚洲视频在线观看| 亚洲精品久久久久久久久久久久久 | 欧美亚洲在线观看| 免费看成人av| 香蕉成人伊视频在线观看 | 欧美日韩午夜视频在线观看| 久久久.com| 欧美三级乱码| 欧美激情免费在线| 国产自产在线视频一区 | 久久综合五月| 国产精品日韩欧美一区| 亚洲国产欧美日韩精品| 精品1区2区3区4区| 亚洲在线观看免费| 欧美日韩三级| 亚洲女性裸体视频| 欧美高清在线视频观看不卡| 欧美精品久久久久久久久久| 久久蜜桃精品| 国产精品一区二区三区乱码| 欧美丰满少妇xxxbbb| 国精品一区二区三区| 亚洲视频二区| 亚洲一区二区在线视频| 欧美精品99| 亚洲三级毛片| 亚洲精品午夜| 免费视频一区| 欧美成人黑人xx视频免费观看| 国产热re99久久6国产精品| 一区二区三区久久久| 精品动漫一区| 久久精品视频在线观看| 国产精品视频内| 亚洲尤物在线视频观看| 亚洲欧美综合一区| 国产精品国产精品| 亚洲网在线观看| 欧美一级专区| 好看不卡的中文字幕| 久久综合色播五月| 亚洲国产成人在线| 夜夜嗨av一区二区三区网页| 欧美日韩在线观看视频| 亚洲深夜激情| 久久国产日韩| 一区二区在线看| 蜜桃久久av一区| 亚洲精品一二区| 黄色精品一区| 蜜臀91精品一区二区三区| 亚洲第一天堂av| 亚洲一区免费观看| 国产亚洲精品一区二555| 久久成人免费| 亚洲黄色性网站| 午夜精品视频网站| 国内精品伊人久久久久av影院 | 老司机免费视频一区二区| 玖玖国产精品视频| 亚洲精品网站在线播放gif| 亚洲一区二区免费| 国产一区91| 免费日韩av| 欧美在线观看网址综合| 亚洲国产高清在线| 久久看片网站| 亚洲午夜免费视频| 国内精品伊人久久久久av一坑| 欧美国产精品中文字幕| 亚洲一区精品视频| 欧美成人午夜激情在线| 亚洲欧美在线看| 亚洲精品一区二区三区四区高清| 欧美系列亚洲系列|