中文字幕第五页-中文字幕第页-中文字幕韩国-中文字幕最新-国产尤物二区三区在线观看-国产尤物福利视频一区二区

Kubernetes中鎖機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)方法是什么

這篇文章主要講解了“Kubernetes中鎖機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)方法是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Kubernetes中鎖機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)方法是什么”吧!

成都創(chuàng)新互聯(lián)公司成立十多年來,這條路我們正越走越好,積累了技術(shù)與客戶資源,形成了良好的口碑。為客戶提供網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì)、網(wǎng)站策劃、網(wǎng)頁設(shè)計(jì)、域名注冊、網(wǎng)絡(luò)營銷、VI設(shè)計(jì)、網(wǎng)站改版、漏洞修補(bǔ)等服務(wù)。網(wǎng)站是否美觀、功能強(qiáng)大、用戶體驗(yàn)好、性價比高、打開快等等,這些對于網(wǎng)站建設(shè)都非常重要,成都創(chuàng)新互聯(lián)公司通過對建站技術(shù)性的掌握、對創(chuàng)意設(shè)計(jì)的研究為客戶提供一站式互聯(lián)網(wǎng)解決方案,攜手廣大客戶,共同發(fā)展進(jìn)步。

面向終態(tài)的鎖基礎(chǔ)篇

在分布式系統(tǒng)中通常由各種各樣的鎖,我們先來看下,主流的鎖里面有哪些共性,以及是如何進(jìn)行設(shè)計(jì)的。

分布式系統(tǒng)中的鎖

在分布式系統(tǒng)中鎖有很多種實(shí)現(xiàn)方式: 基于CP模型的、基于AP模型的 ,但是這些鎖機(jī)制都有一些通用的設(shè)計(jì)原則,接下來我們先看下這部分。

1. 鎖憑證

鎖憑證主要來證明誰持有鎖,不同系統(tǒng)里面的實(shí)現(xiàn)各不相同,比如在zookeeper中是臨時順序節(jié)點(diǎn),而在redission中則是通過uuid+threadID組成,而K8s中則是LeaderElectionRecord,  通過該憑證來識別當(dāng)前是哪個客戶端加的鎖。

2. 鎖超時

當(dāng)有l(wèi)eader節(jié)點(diǎn)持有鎖之后,其余的節(jié)點(diǎn)就需要嘗試競爭鎖,在CP系統(tǒng)中通常會由服務(wù)端進(jìn)行維護(hù),即如果發(fā)現(xiàn)對應(yīng)的節(jié)點(diǎn)沒有心跳,則會進(jìn)行節(jié)點(diǎn)的踢出,并且通過watch這種機(jī)制進(jìn)行回調(diào),而在AP系統(tǒng)中則需要客戶端自己維護(hù),比如redission里面的時間戳。

3. 時鐘

在分布式系統(tǒng)中通常我們無法保證各個節(jié)點(diǎn)的物理時鐘完全一致,通常就會有一個邏輯時鐘的概念,在很多系統(tǒng)中比如raft和zab中其實(shí)就是一個遞增的全局計(jì)數(shù)器,但是在redission中則是通過物理時鐘,即需要保證大家的物理時鐘盡可能同步,不能超過鎖超時的時間。

網(wǎng)絡(luò)分區(qū)問題

Kubernetes中鎖機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)方法是什么

無論是CP還是AP,在分布式系統(tǒng)中通常我們都要保證P即分區(qū)可用性,那如果持有鎖的Leader節(jié)點(diǎn)發(fā)生網(wǎng)絡(luò)分區(qū)的情況,則需要一種保護(hù)機(jī)制,即Leader節(jié)點(diǎn)需要主動退出。

在zookeeper中因?yàn)閘eader節(jié)點(diǎn)需要通過session來進(jìn)行心跳的維護(hù),如果說對應(yīng)的leader節(jié)點(diǎn)發(fā)生分區(qū),則session就無法進(jìn)行心跳的發(fā)生,就會退出,就需要通知我們的主流程來進(jìn)行退出清理工作。

資源鎖的實(shí)現(xiàn)機(jī)制

資源鎖其實(shí)就是可以通過操作一個資源(順序一致性),借助前面說的鎖的思想來實(shí)現(xiàn)分布式鎖,其首先核心流程如下:

通過資源對象來存儲鎖憑證信息

即將標(biāo)識當(dāng)前Leader節(jié)點(diǎn)的信息放入到對應(yīng)的憑證里面,并嘗試進(jìn)行鎖競爭,進(jìn)行鎖的獲取的嘗試。

鎖超時

K8s的鎖超時的機(jī)制比較有趣,即他并不關(guān)心你的邏輯時鐘,而是以本地時鐘為準(zhǔn),即每個節(jié)點(diǎn)會存儲觀測到leader節(jié)點(diǎn)變更的時間,然后根據(jù)本地的鎖超時時間來檢測,是否重新發(fā)起leader的競爭。

核心源碼剖析

因?yàn)槠蜻@里只介紹基于configMap的resourceLock, 其他的都大同小異。

LeaderElectionRecord

在我的理解上這個數(shù)結(jié)構(gòu)的設(shè)計(jì),才是真正的那把鎖(就好像生活中我們可以隨便買把鎖,鎖各種門)。通過這個鎖屏蔽底層的各種鎖實(shí)現(xiàn)系統(tǒng)的實(shí)現(xiàn)細(xì)節(jié),但注意這把鎖并不是嚴(yán)格的分布式互斥鎖。

數(shù)據(jù)結(jié)構(gòu)

在鎖的實(shí)現(xiàn)中,數(shù)據(jù)主要分為三類:身份憑證、時間戳、全局計(jì)數(shù)器,然后我們依次來看猜下對應(yīng)的設(shè)計(jì)思路。

type LeaderElectionRecord struct {     HolderIdentity       string      `json:"holderIdentity"`     LeaseDurationSeconds int         `json:"leaseDurationSeconds"`     AcquireTime          metav1.Time `json:"acquireTime"`     RenewTime            metav1.Time `json:"renewTime"`     LeaderTransitions    int         `json:"leaderTransitions"` }

身份憑證:HolderIdentity

身份憑證主要是用于標(biāo)識一個節(jié)點(diǎn)信息,在一些分布式協(xié)調(diào)系統(tǒng)中通常都是系統(tǒng)自帶的機(jī)制,比如zookeeper中的session,  在此處資源鎖的場景下,主要是為了用于后續(xù)流程里驗(yàn)證當(dāng)前節(jié)點(diǎn)是否獲取到鎖。

時間戳:LeaseDurationSeconds、AcquireTime、RenewTime

因?yàn)橹罢f的時間同步的問題,這里的時間相關(guān)的主要是用于leader節(jié)點(diǎn)觸發(fā)節(jié)點(diǎn)變更來使用(Lease類型也在使用),非Leader節(jié)點(diǎn)則根據(jù)當(dāng)前記錄是否變更來檢測leader節(jié)點(diǎn)是否存活。

LeaderTransitions

計(jì)數(shù)器主要就是通過計(jì)數(shù)來記錄leader節(jié)點(diǎn)切換的次數(shù)。

ConfigMapLock

所謂的資源鎖其實(shí)就是通過創(chuàng)建一個ConfigMap實(shí)例來保存我們的鎖信息,并通過這個實(shí)例信息的維護(hù),來實(shí)現(xiàn)鎖的競爭和釋放。

1. 創(chuàng)建鎖

通過利用etcd的冪等性操作,可以保證同時只會有一個leader節(jié)點(diǎn)進(jìn)行鎖創(chuàng)建成功,并且通過Annotations來提交上面說的LeaderElectionRecord來進(jìn)行鎖的提交。

func (cml *ConfigMapLock) Create(ler LeaderElectionRecord) error {     cml.cm, err = cml.Client.ConfigMaps(cml.ConfigMapMeta.Namespace).Create(&v1.ConfigMap{         ObjectMeta: metav1.ObjectMeta{             Name:      cml.ConfigMapMeta.Name,             Namespace: cml.ConfigMapMeta.Namespace,             Annotations: map[string]string{                 LeaderElectionRecordAnnotationKey: string(recordBytes),             },         },     })     return err }

2. 獲取鎖

func (cml *ConfigMapLock) Get() (*LeaderElectionRecord, []byte, error) {     cml.cm, err = cml.Client.ConfigMaps(cml.ConfigMapMeta.Namespace).Get(cml.ConfigMapMeta.Name, metav1.GetOptions{})     recordBytes, found := cml.cm.Annotations[LeaderElectionRecordAnnotationKey]     if found {         if err := json.Unmarshal([]byte(recordBytes), &record); err != nil {             return nil, nil, err         }     }     return &record, []byte(recordBytes), nil }

3. 更新鎖

func (cml *ConfigMapLock) Update(ler LeaderElectionRecord) error {     cml.cm.Annotations[LeaderElectionRecordAnnotationKey] = string(recordBytes)     cml.cm, err = cml.Client.ConfigMaps(cml.ConfigMapMeta.Namespace).Update(cml.cm)     return err }

LeaderElector

LeaderElector的核心流程分為三部分:競爭鎖、超時檢測、心跳維護(hù),首先所有節(jié)點(diǎn)都會進(jìn)行資源鎖的競爭,但是最終只會有一個節(jié)點(diǎn)成為Leader節(jié)點(diǎn),  然后核心流程就會按照角色分成兩個主流程, 讓我們一起來看下其實(shí)現(xiàn)。

1. 核心流程

如果節(jié)點(diǎn)沒有acquire成功則會一直進(jìn)行嘗試,直至取消或者競選成功,而leader節(jié)點(diǎn)則會執(zhí)行成為  leader節(jié)點(diǎn)的回調(diào)(補(bǔ)充基于leader的zookeeper的實(shí)現(xiàn)機(jī)制)

func (le *LeaderElector) Run(ctx context.Context) {     defer func() {         runtime.HandleCrash()         le.config.Callbacks.OnStoppedLeading()     }()     if !le.acquire(ctx)  { // 精選鎖         return // ctx signalled done     }     // 如果鎖競選成功,則leader節(jié)點(diǎn)會執(zhí)行剩余流程,而非leader節(jié)點(diǎn)則繼續(xù)嘗試acquire     ctx, cancel := context.WithCancel(ctx)     defer cancel()     go le.config.Callbacks.OnStartedLeading(ctx)     le.renew(ctx) }

2. 鎖的續(xù)約

如果競選為leader節(jié)點(diǎn),則就需要進(jìn)行鎖的續(xù)約操作,就是通過調(diào)用上面提到的更新鎖的操作來,周期性的更新鎖記錄信息即LeaderElectionRecord,從而達(dá)到續(xù)約的目標(biāo)。

func (le *LeaderElector) renew(ctx context.Context) {     ctx, cancel := context.WithCancel(ctx)     defer cancel()     wait.Until(func() {         timeoutCtx, timeoutCancel := context.WithTimeout(ctx, le.config.RenewDeadline)         defer timeoutCancel()         err := wait.PollImmediateUntil(le.config.RetryPeriod, func() (bool, error) {             done := make(chan bool, 1)             go func() {                 defer close(done)                 // 鎖的續(xù)約                 done <- le.tryAcquireOrRenew()             }()              select {             case <-timeoutCtx.Done():                 return false, fmt.Errorf("failed to tryAcquireOrRenew %s", timeoutCtx.Err())             case result := <-done:                 return result, nil             }         }, timeoutCtx.Done())         cancel()     }, le.config.RetryPeriod, ctx.Done())      // if we hold the lease, give it up     if le.config.ReleaseOnCancel {         // 釋放鎖         le.release()     } }

3. 鎖的釋放

鎖的釋放則比較好玩,就是更新對應(yīng)的資源,去掉annotations里面的信息,這樣在獲取鎖的時候,因?yàn)闄z測到當(dāng)前資源沒有被任何憑證信息,就會嘗試進(jìn)行競選。

func (le *LeaderElector) release() bool {     if !le.IsLeader() {         return true     }     leaderElectionRecord := rl.LeaderElectionRecord{         LeaderTransitions: le.observedRecord.LeaderTransitions,     }     if err := le.config.Lock.Update(leaderElectionRecord); err != nil {         klog.Errorf("Failed to release lock: %v", err)         return false     }     le.observedRecord = leaderElectionRecord     le.observedTime = le.clock.Now()     return true }

4. 鎖的競爭

Kubernetes中鎖機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)方法是什么

鎖的競爭整體分為四個部分: 1)獲取鎖 2)創(chuàng)建鎖 3)檢測鎖 4)更新鎖,下面來依次看下對應(yīng)的實(shí)現(xiàn)。

獲取鎖

首先會嘗試獲取對應(yīng)的鎖,在獲取鎖中會檢測對應(yīng)的annotations中是否存在,如果不存在則oldLeaderElectionRecord就為空,即當(dāng)前資源鎖沒有被人持有。

oldLeaderElectionRecord, oldLeaderElectionRawRecord, err := le.config.Lock.Get()

創(chuàng)建鎖

如果檢測到對應(yīng)的鎖不存在,則就會直接進(jìn)行鎖的創(chuàng)建,如果創(chuàng)建成功則表明當(dāng)前節(jié)點(diǎn)獲取鎖,則就成為leader,執(zhí)行l(wèi)eader的回調(diào)邏輯。

if err != nil {         if !errors.IsNotFound(err) {             klog.Errorf("error retrieving resource lock %v: %v", le.config.Lock.Describe(), err)             return false         }         // 創(chuàng)建鎖         if err = le.config.Lock.Create(leaderElectionRecord); err != nil {             klog.Errorf("error initially creating leader election record: %v", err)             return false         }         // 記錄當(dāng)前的選舉記錄,還有時鐘         le.observedRecord = leaderElectionRecord         le.observedTime = le.clock.Now()         return true     }

檢查鎖

在K8s里面并沒有使用邏輯時鐘而是使用本地時間,通過對比每次鎖憑證是否更新,來進(jìn)行本地observedTime的更新,如果leader沒有在LeaseDuration內(nèi)來更新對應(yīng)的鎖憑證信息,則當(dāng)前節(jié)點(diǎn)就會嘗試成為leader。

同時這里還會保障最終的一致性鎖,因?yàn)楹罄m(xù)的renew其實(shí)也是走的這個邏輯,如果說當(dāng)前節(jié)點(diǎn)最開始持有鎖,但是被別的節(jié)點(diǎn)搶占,則當(dāng)前節(jié)點(diǎn)會主動讓出鎖。

if !bytes.Equal(le.observedRawRecord, oldLeaderElectionRawRecord) {         le.observedRecord = *oldLeaderElectionRecord         le.observedRawRecord = oldLeaderElectionRawRecord         le.observedTime = le.clock.Now() // 此處更新的是本地的時鐘     }     if len(oldLeaderElectionRecord.HolderIdentity) > 0 &&         le.observedTime.Add(le.config.LeaseDuration).After(now.Time) &&         !le.IsLeader() {         // 如果當(dāng)前Leader任期沒有超時,則當(dāng)前競選鎖失敗         klog.V(4).Infof("lock is held by %v and has not yet expired", oldLeaderElectionRecord.HolderIdentity)         return false     }

更新鎖

核心邏輯其實(shí)就是Lock.Update這個地方,設(shè)計(jì)的比較有意思,不同于強(qiáng)一致性的鎖,在K8s中我們可以同時有多個節(jié)點(diǎn)都走到這里,但是因?yàn)楦耬tcd是一個原子的操作,最終只會有一個節(jié)點(diǎn)更新成功,那如何保證最終的鎖的語義呢,其實(shí)就要配合上面的檢測鎖,這樣就可以實(shí)現(xiàn)一個面向終態(tài)的最終的鎖機(jī)制。

if le.IsLeader() {         leaderElectionRecord.AcquireTime = oldLeaderElectionRecord.AcquireTime         leaderElectionRecord.LeaderTransitions = oldLeaderElectionRecord.LeaderTransitions     } else {         leaderElectionRecord.LeaderTransitions = oldLeaderElectionRecord.LeaderTransitions + 1     }      // update the lock itself     if err = le.config.Lock.Update(leaderElectionRecord); err != nil {         klog.Errorf("Failed to update lock: %v", err)         return false     }      le.observedRecord = leaderElectionRecord     le.observedTime = le.clock.Now()     return true

疑問

回過來看鎖是因?yàn)樽罱谧鱿到y(tǒng)設(shè)計(jì)的時候,想到的一個問題。在PAAS系統(tǒng)中通常會有N多的Operator,那在一些沖突的場景該如何解決呢?比如擴(kuò)縮容、發(fā)布、容災(zāi)這幾個控制器,如果要操作同一個app下面的pod該如何被調(diào)度呢?

其實(shí)我理解這個流程中是無法做到各種完美cover各種異常沖突的,但是我們可以玩另外一種有意思的事情,比如我們可以加一個保護(hù)狀態(tài),因?yàn)閷ιa(chǎn)穩(wěn)定壓倒一起。即對應(yīng)的控制器,關(guān)注當(dāng)前的狀態(tài)是否處于穩(wěn)定狀態(tài),如果是非穩(wěn)定狀態(tài),則就應(yīng)該自身凍結(jié),等當(dāng)前應(yīng)用處于非保護(hù)狀態(tài)再進(jìn)行操作,保證SLA的同時也不影響各種好玩的操作。

感謝各位的閱讀,以上就是“Kubernetes中鎖機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)方法是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Kubernetes中鎖機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

文章題目:Kubernetes中鎖機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)方法是什么
網(wǎng)頁網(wǎng)址:http://www.2m8n56k.cn/article48/jcgeep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈網(wǎng)站制作全網(wǎng)營銷推廣搜索引擎優(yōu)化App開發(fā)軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:[email protected]。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司
主站蜘蛛池模板: 九九99香蕉在线视频免费 | 欧美性色黄大片在线观看 | 国产午夜亚洲精品一区网站 | 99热com| 男人的天堂免费 | 国产精品久久久久一区二区 | 亚洲综合一二三区 | 在线视频一区二区日韩国产 | 久久亚洲国产最新网站 | 成人国产精品免费视频不卡 | 99国产精品免费视频观看 | 成人永久福利在线观看不卡 | 新26uuu在线亚洲欧美 | bt天堂国产亚洲欧美在线 | 成人国产免费 | 国产欧美日韩视频在线观看 | 91久久亚洲国产成人精品性色 | 福利国产视频 | 朝鲜美女免费一级毛片 | 国产精品久久久久一区二区 | 国产午夜精品久久久久九九 | 国产成人三级经典中文 | 玖草在线播放 | 国产原创一区二区 | 亚洲一区三区 | 欧美一级毛片一级 | 久久中文字幕综合不卡一二区 | 中国一级毛片免费观看 | 亚洲欧美一区二区三区国产精品 | www伊人| 日韩精品一区二区三区毛片 | 欧美成人高清免费大片观看 | 一级毛片免费播放视频 | 国产精选在线视频 | 免费一区二区三区 | 日本一区二区在线 | 九九线精品视频 | 成人在线综合网 | 久久久精品久久久久久久久久久 | 男女男精品视频网站在线观看 | 亚洲高清国产一线久久 |