kubernetes 中定時(shí)任務(wù)的實(shí)現(xiàn)

k8s 中有許多優(yōu)秀的包都可以在平時(shí)的開發(fā)中借鑒與使用于个,比如,任務(wù)的定時(shí)輪詢暮顺、高可用的實(shí)現(xiàn)厅篓、日志處理、緩存使用等都是獨(dú)立的包捶码,可以直接引用羽氮。本篇文章會(huì)介紹 k8s 中定時(shí)任務(wù)的實(shí)現(xiàn),k8s 中定時(shí)任務(wù)都是通過 wait 包實(shí)現(xiàn)的惫恼,wait 包在 k8s 的多個(gè)組件中都有用到档押,以下是 wait 包在 kubelet 中的幾處使用:

func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan struct{}) (err error) {
        ...
        // kubelet 每5分鐘一次從 apiserver 獲取證書
        closeAllConns, err := kubeletcertificate.UpdateTransport(wait.NeverStop, clientConfig, clientCertificateManager, 5*time.Minute)
        if err != nil {
            return err
        }
        
        closeAllConns, err := kubeletcertificate.UpdateTransport(wait.NeverStop, clientConfig, clientCertificateManager, 5*time.Minute)
        if err != nil {
            return err
        }
        ...
}

...

func startKubelet(k kubelet.Bootstrap, podCfg *config.PodConfig, kubeCfg *kubeletconfiginternal.KubeletConfiguration,   kubeDeps *kubelet.Dependencies, enableServer bool) {
    // 持續(xù)監(jiān)聽 pod 的變化
    go wait.Until(func() {
        k.Run(podCfg.Updates())
    }, 0, wait.NeverStop)
    ...
}

golang 中可以通過 time.Ticker 實(shí)現(xiàn)定時(shí)任務(wù)的執(zhí)行,但在 k8s 中用了更原生的方式祈纯,使用 time.Timer 實(shí)現(xiàn)的令宿。time.Ticker 和 time.Timer 的使用區(qū)別如下:

  • ticker 只要定義完成,從此刻開始計(jì)時(shí)腕窥,不需要任何其他的操作粒没,每隔固定時(shí)間都會(huì)自動(dòng)觸發(fā)。
  • timer 定時(shí)器是到了固定時(shí)間后會(huì)執(zhí)行一次簇爆,僅執(zhí)行一次
  • 如果 timer 定時(shí)器要每隔間隔的時(shí)間執(zhí)行癞松,實(shí)現(xiàn) ticker 的效果,使用 func (t *Timer) Reset(d Duration) bool

一個(gè)示例:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup

    timer1 := time.NewTimer(2 * time.Second)
    ticker1 := time.NewTicker(2 * time.Second)

    wg.Add(1)
    go func(t *time.Ticker) {
        defer wg.Done()
        for {
            <-t.C
            fmt.Println("exec ticker", time.Now().Format("2006-01-02 15:04:05"))
        }
    }(ticker1)

    wg.Add(1)
    go func(t *time.Timer) {
        defer wg.Done()
        for {
            <-t.C
            fmt.Println("exec timer", time.Now().Format("2006-01-02 15:04:05"))
            t.Reset(2 * time.Second)
        }
    }(timer1)
    
    wg.Wait()
}

一入蛆、wait 包中的核心代碼

核心代碼(k8s.io/apimachinery/pkg/util/wait/wait.go):

func JitterUntil(f func(), period time.Duration, jitterFactor float64, sliding bool, stopCh <-chan struct{}) {
    var t *time.Timer
    var sawTimeout bool

    for {
        select {
        case <-stopCh:
            return
        default:
        }

        jitteredPeriod := period
        if jitterFactor > 0.0 {
            jitteredPeriod = Jitter(period, jitterFactor)
        }

        if !sliding {
            t = resetOrReuseTimer(t, jitteredPeriod, sawTimeout)
        }

        func() {
            defer runtime.HandleCrash()
            f()
        }()

        if sliding {
            t = resetOrReuseTimer(t, jitteredPeriod, sawTimeout)
        }

        select {
        case <-stopCh:
            return
        case <-t.C:
            sawTimeout = true
        }
    }
}

...

func resetOrReuseTimer(t *time.Timer, d time.Duration, sawTimeout bool) *time.Timer {
    if t == nil {
        return time.NewTimer(d)
    }
    if !t.Stop() && !sawTimeout {
        <-t.C
    }
    t.Reset(d)
    return t
}

幾個(gè)關(guān)鍵點(diǎn)的說明:

  • 1拦惋、如果 sliding 為 true,則在 f() 運(yùn)行之后計(jì)算周期安寺。如果為 false,那么 period 包含 f() 的執(zhí)行時(shí)間首尼。
  • 2挑庶、在 golang 中 select 沒有優(yōu)先級選擇,為了避免額外執(zhí)行 f(),在每次循環(huán)開始后會(huì)先判斷 stopCh chan软能。

k8s 中 wait 包其實(shí)是對 time.Timer 做了一層封裝實(shí)現(xiàn)迎捺。

二、wait 包常用的方法

1查排、定期執(zhí)行一個(gè)函數(shù)凳枝,永不停止,可以使用 Forever 方法:

func Forever(f func(), period time.Duration)

2、在需要的時(shí)候停止循環(huán)岖瑰,那么可以使用下面的方法叛买,增加一個(gè)用于停止的 chan 即可,方法定義如下:

func Until(f func(), period time.Duration, stopCh <-chan struct{})

上面的第三個(gè)參數(shù) stopCh 就是用于退出無限循環(huán)的標(biāo)志蹋订,停止的時(shí)候我們 close 掉這個(gè) chan 就可以了率挣。

3、有時(shí)候露戒,我們還會(huì)需要在運(yùn)行前去檢查先決條件椒功,在條件滿足的時(shí)候才去運(yùn)行某一任務(wù),這時(shí)候可以使用 Poll 方法:

func Poll(interval, timeout time.Duration, condition ConditionFunc)

這個(gè)函數(shù)會(huì)以 interval 為間隔智什,不斷去檢查 condition 條件是否為真动漾,如果為真則可以繼續(xù)后續(xù)處理;如果指定了 timeout 參數(shù)荠锭,則該函數(shù)也可以只常識指定的時(shí)間旱眯。

4、PollUntil 方法和上面的類似节沦,但是沒有 timeout 參數(shù)键思,多了一個(gè) stopCh 參數(shù),如下所示:

PollUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error

此外還有 PollImmediate 甫贯、 PollInfinite 和 PollImmediateInfinite 方法吼鳞。

三、總結(jié)

本篇文章主要講了 k8s 中定時(shí)任務(wù)的實(shí)現(xiàn)與對應(yīng)包(wait)中方法的使用叫搁。通過閱讀 k8s 的源代碼赔桌,可以發(fā)現(xiàn) k8s 中許多功能的實(shí)現(xiàn)也都是我們需要在平時(shí)工作中用的,其大部分包的性能都是經(jīng)過大規(guī)目事撸考驗(yàn)的疾党,通過使用其相關(guān)的工具包不僅能學(xué)到大量的編程技巧也能避免自己造輪子。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惨奕,一起剝皮案震驚了整個(gè)濱河市雪位,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌梨撞,老刑警劉巖雹洗,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異卧波,居然都是意外死亡时肿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門港粱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來螃成,“玉大人,你說我怎么就攤上這事〈绾辏” “怎么了宁炫?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長击吱。 經(jīng)常有香客問我淋淀,道長,這世上最難降的妖魔是什么覆醇? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任朵纷,我火速辦了婚禮,結(jié)果婚禮上永脓,老公的妹妹穿的比我還像新娘袍辞。我一直安慰自己,他們只是感情好常摧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布搅吁。 她就那樣靜靜地躺著,像睡著了一般落午。 火紅的嫁衣襯著肌膚如雪谎懦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天溃斋,我揣著相機(jī)與錄音界拦,去河邊找鬼。 笑死梗劫,一個(gè)胖子當(dāng)著我的面吹牛享甸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梳侨,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼蛉威,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了走哺?” 一聲冷哼從身側(cè)響起蚯嫌,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎丙躏,沒想到半個(gè)月后齐帚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡彼哼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了湘今。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敢朱。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拴签,到底是詐尸還是另有隱情孝常,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布蚓哩,位于F島的核電站构灸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏岸梨。R本人自食惡果不足惜喜颁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望曹阔。 院中可真熱鬧半开,春花似錦、人聲如沸赃份。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抓韩。三九已至纠永,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谒拴,已是汗流浹背尝江。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彪薛,地道東北人茂装。 一個(gè)月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像善延,于是被迫代替她去往敵國和親少态。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348