首頁 >後端開發 >Golang >golang 在 k8s 運算子上出現錯誤'物件已被修改”

golang 在 k8s 運算子上出現錯誤'物件已被修改”

王林
王林轉載
2024-02-13 15:42:08775瀏覽

golang 在 k8s 运算符上出现错误“对象已被修改”

php小編草莓在探索使用golang開發kubernetes運算子時,遇到了一個常見的錯誤:「物件已被修改」。這個錯誤通常發生在多個goroutine同時修改同一個物件時,導致資料不一致或競爭條件。在本文中,我們將探討這個錯誤的原因和解決方案,幫助開發者更好地理解和處理類似的問題。

問題內容

k8s 運算子上出現「物件已被修改」錯誤

import "sigs.k8s.io/controller-runtime"

關於這種錯誤有很多討論。主要答案是“發生此問題是因為當我嘗試更新時我有舊版本的物件。” 但我也有一些問題。在我的操作員中,對於某些場景,我需要在一次「協調」呼叫期間更新 pod 的註釋 2 次。當然,我經常收到“對像已被修改”的錯誤。

問題:我想知道 'r.Get()' 和 'r.Update()' 在哪裡取得/更新物件?來自本地緩存,還是 API 伺服器?

1: 我認為 'r.Get()' 是從 'cache' 取得對象,而 'r.Update()' 是更新對像到緩存,對嗎?如果是這樣,為什麼我會收到此錯誤?如果 pod 物件因操作員以外的原因而更改,我將無法在目前「協調」期間永遠更新我的 pod 物件? (由於快取物件是本地的,它已經與 API 伺服器不同步。)為什麼要「重試」有的時候能取得到最新的物件嗎?

import "sigs.k8s.io/controller-runtime"

var pod corev1.Pod
if err := r.Get(ctx, req.NamespacedName, &pod); err != nil {
    if !apierrors.IsNotFound(err) {
        log.Error(err, "unable to get pod")
        return ctrl.Result{}, err
    }
}

if err := r.Update(ctx, &pod); err != nil {
    log.Error(err, "unable to update chaosctl status")
    return ctrl.Result{}, err
}

2:如果'r.Get()'是從API伺服器取得對象,並且'r.Update()'也更新API伺服器。為什麼我需要重試更新物件?

解決方法

當您在 Kubernetes 控制器中使用 r.Get() 和 r.Update() 時,與 API 伺服器的互動涉及本機快取和 API 伺服器本身。

r.Get():

r.Get() 函數從本機快取中檢索物件(如果存在);否則,它會從 API 伺服器取得它。 如果該物件存在於本機快取中,則立即傳回。如果沒有,則向API伺服器請求取得該對象,並將取得到的對象儲存在本機快取中以供後續使用。 r.Update():

r.Update() 函數會更新本機快取和 API 伺服器中的物件。 如果該物件自最初檢索以來已在本機快取中修改,則對 API 伺服器的更新操作可能會失敗並出現「衝突」錯誤。當快取中物件的版本與 API 伺服器上的版本不符時,就會發生這種情況,表示其他人在此期間修改了該物件。

可以採取策略來處理它 -

  1. 樂觀並發控制(OCC): - 更新先前的版本符合。
  2. retry -
#
retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
        return r.Update(ctx, pod)
    })
    if retryErr != nil {
        return retryErr
    }

以上是golang 在 k8s 運算子上出現錯誤'物件已被修改”的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除