Heim  >  Artikel  >  Backend-Entwicklung  >  Golang-Fehler „Objekt wurde geändert“ beim k8s-Operator

Golang-Fehler „Objekt wurde geändert“ beim k8s-Operator

王林
王林nach vorne
2024-02-13 15:42:08756Durchsuche

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

Der PHP-Editor Strawberry ist auf einen häufigen Fehler gestoßen, als er die Verwendung von Golang zur Entwicklung von Kubernetes-Operatoren untersuchte: „Das Objekt wurde geändert“. Dieser Fehler tritt normalerweise auf, wenn mehrere Goroutinen gleichzeitig dasselbe Objekt ändern, was zu Dateninkonsistenzen oder Race Conditions führt. In diesem Artikel werden wir die Ursachen und Lösungen dieses Fehlers untersuchen, um Entwicklern zu helfen, ähnliche Probleme besser zu verstehen und damit umzugehen.

Probleminhalt

Der Fehler „Das Objekt wurde geändert“ wird beim k8s-Operator angezeigt

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

Über diesen Fehler wird viel diskutiert. Die Hauptantwort lautet: „Dieses Problem tritt auf, weil ich eine alte Version des Objekts habe, wenn ich versuche, es zu aktualisieren.“ Aber ich habe auch einige Fragen. Bei meinem Betreiber muss ich in einigen Szenarien die Anmerkung eines Pods während eines einzelnen „Koordinaten“-Aufrufs zweimal aktualisieren. Natürlich bekomme ich oft die Fehlermeldung „Objekt wurde geändert“.

Frage: Ich möchte wissen, wo „r.Get()“ und „r.Update()“ Objekte abrufen/aktualisieren? Vom lokalen Cache oder API-Server?

1: Ich denke, „r.Get()“ holt das Objekt aus „Cache“ und „r.Update()“ aktualisiert das Objekt im Cache, oder? Wenn ja, warum erhalte ich diese Fehlermeldung? Ich kann mein Pod-Objekt während des aktuellen „Abgleichs“ nicht dauerhaft aktualisieren, wenn sich das Pod-Objekt aus anderen Gründen als dem Betreiber ändert? (Da das zwischengespeicherte Objekt lokal ist, ist es bereits nicht mehr mit dem API-Server synchronisiert.) Warum manchmal „wiederholen“, um das neueste Objekt abzurufen?

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: Wenn „r.Get()“ das Objekt vom API-Server abrufen soll und „r.Update()“ auch den API-Server aktualisiert. Warum muss ich erneut versuchen, das Objekt zu aktualisieren?

Workaround

Wenn Sie r.Get() und r.Update() in einem Kubernetes-Controller verwenden, betrifft die Interaktion mit dem API-Server sowohl den lokalen Cache als auch den API-Server selbst.

r.Get():

Die Funktion

r.Get() ruft das Objekt aus dem lokalen Cache ab, falls es vorhanden ist, andernfalls ruft sie es vom API-Server ab. Wenn das Objekt im lokalen Cache vorhanden ist, wird es sofort zurückgegeben. Wenn nicht, fordern Sie den API-Server auf, das Objekt abzurufen, und speichern Sie das erhaltene Objekt zur späteren Verwendung im lokalen Cache. r.Update():

r.Update() Funktion aktualisiert Objekte im lokalen Cache und API-Server. Aktualisierungsvorgänge auf dem API-Server schlagen möglicherweise mit einem „Konflikt“-Fehler fehl, wenn das Objekt seit dem ursprünglichen Abruf im lokalen Cache geändert wurde. Dies geschieht, wenn die Version eines Objekts im Cache nicht mit der Version auf dem API-Server übereinstimmt, was darauf hindeutet, dass jemand anderes das Objekt in der Zwischenzeit geändert hat.

Es gibt Strategien, damit umzugehen -

  1. 乐观并发控制(OCC): – Aktualisiert, um mit der vorherigen Version übereinzustimmen.
  2. retry -
retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
        return r.Update(ctx, pod)
    })
    if retryErr != nil {
        return retryErr
    }

Das obige ist der detaillierte Inhalt vonGolang-Fehler „Objekt wurde geändert“ beim k8s-Operator. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen