Cache interface 定義了兩種獲取 PodStatus 的方法:一種是非阻塞的 Get()另外一種為阻塞 GetNewerThan() 方法,分別用於不同的情境。
另外也定義了 Set 以及 Delete 的方法用來新增 pod status 以及刪除對應的 pod status 以及透過 UpdateTime 確保 cache 的新鮮度,我們就來看看 interface 實際上對應到的 code 。
1
2
3
4
5
6
7
8
9
typeCacheinterface{Get(types.UID)(*PodStatus,error)Set(types.UID,*PodStatus,error,time.Time)// GetNewerThan is a blocking call that only returns the status
// when it is newer than the given time.
GetNewerThan(types.UID,time.Time)(*PodStatus,error)Delete(types.UID)UpdateTime(time.Time)}
typecachestruct{locksync.RWMutex//確保資料的一致性讀多寫少,使用rw鎖
podsmap[types.UID]*data//使用 map 儲存 key 為 types.UID value為 pod status data
timestamp*time.Time//透過權域的timestamp來確認資料的新鮮度
subscribersmap[types.UID][]*subRecord//透過 map 紀錄哪一個 type.UID 目前是誰監聽
}//data 資料結構儲存 pod status
typedatastruct{status*PodStatus//儲存 pod status
// Error got when trying to inspect the pod.
errerror//儲存 pod inspect 錯誤
modifiedtime.Time//上一次 pod 被修改的時間
}//透過 subRecord 可以回傳給監聽者
typesubRecordstruct{timetime.Timechchan*data//透過 channel 回傳 pod status
}
了解了資料結構後,我們來看一下怎麼把 cache 建立起來。
New function
1
2
3
4
5
// NewCache creates a pod cache.
funcNewCache()Cache{//簡單的初始化 cache 會用到的 map
return&cache{pods:map[types.UID]*data{},subscribers:map[types.UID][]*subRecord{}}}
func(c*cache)Get(idtypes.UID)(*PodStatus,error){//防止競爭上鎖
c.lock.RLock()deferc.lock.RUnlock()//透過 types.UID 取得對應的 pod status
d:=c.get(id)returnd.status,d.err}func(c*cache)get(idtypes.UID)*data{//從 map 中透過 types.UID 找到對應的資料
d,ok:=c.pods[id]//如果沒有找到的話就建立一個預設的資料回傳
if!ok{returnmakeDefaultData(id)}//如果有找到直接回傳 map 中對應的資料
returnd}//建立一個空資料的 pod status
funcmakeDefaultData(idtypes.UID)*data{return&data{status:&PodStatus{ID:id},err:nil}}
GetNewerThan
透過 GetNewerThan function 我們可以傳入 types.UID 以及 minTime (用來對比新鮮度)可以得到對應的 pod status ,要注意它是一個 block 操作(直到取的 pod status 為止)。
更改 cache 的 timestamp 並通知所有的訂閱者,可以更新 pod status 給訂閱者。
1
2
3
4
5
6
7
8
9
func(c*cache)UpdateTime(timestamptime.Time){c.lock.Lock()deferc.lock.Unlock()c.timestamp=×tamp// Notify all the subscribers if the condition is met.
forid:=rangec.subscribers{c.notify(id,*c.timestamp)}}
小結
kubelet 使用 cache 來儲存 pod status 的狀態,並且透過 timestamp 確保 cache 的新鮮度,若是 cache 更新 timestamp 也會通知 subscribers 訂閱的 pod status 當前的狀態。
此外也提供兩種獲取 PodStatus 的方法:一種是非阻塞的 Get()另外一種為阻塞 GetNewerThan() 方法,分別用於不同的情境。