L'éditeur PHP Strawberry a rencontré une erreur courante lors de l'exploration de l'utilisation de Golang pour développer des opérateurs Kubernetes : "L'objet a été modifié". Cette erreur se produit généralement lorsque plusieurs goroutines modifient le même objet en même temps, entraînant une incohérence des données ou des conditions de concurrence. Dans cet article, nous explorerons les causes et les solutions de cette erreur pour aider les développeurs à mieux comprendre et gérer des problèmes similaires.
L'erreur "L'objet a été modifié" apparaît sur l'opérateur k8s
import "sigs.k8s.io/controller-runtime"
Il y a beaucoup de discussions à propos de cette erreur. La réponse principale est "Ce problème se produit car j'ai une ancienne version de l'objet lorsque j'essaie de mettre à jour." Mais j'ai aussi quelques questions. Chez mon opérateur, pour certains scénarios, je dois mettre à jour l'annotation d'un pod 2 fois au cours d'un seul appel « coordonnées ». Bien sûr, j'obtiens souvent l'erreur "l'objet a été modifié".
Question : Je veux savoir où 'r.Get()' et 'r.Update()' récupèrent/mettent à jour les objets ? Depuis le cache local ou le serveur API ?
1 : Je pense que 'r.Get()' récupère l'objet du 'cache' et 'r.Update()' met à jour l'objet dans le cache, n'est-ce pas ? Si oui, pourquoi est-ce que j'obtiens cette erreur ? Je ne pourrai pas mettre à jour mon objet pod pour toujours pendant la « réconciliation » en cours si l'objet pod change pour des raisons autres que l'opérateur ? (Puisque l'objet mis en cache est local, il est déjà désynchronisé avec le serveur API.) Pourquoi « réessayer » parfois pour obtenir le dernier objet ?
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 : Si 'r.Get()' doit récupérer l'objet du serveur API, et 'r.Update()' met également à jour le serveur API. Pourquoi dois-je réessayer de mettre à jour l’objet ?
Lorsque vous utilisez r.Get() et r.Update() dans un contrôleur Kubernetes, l'interaction avec le serveur API implique à la fois le cache local et le serveur API lui-même.
r.Get()
:
r.Get() récupère l'objet du cache local s'il existe ; sinon, elle l'obtient du serveur API. Si l'objet existe dans le cache local, il est renvoyé immédiatement. Sinon, demandez au serveur API d'obtenir l'objet et stockez l'objet obtenu dans le cache local pour une utilisation ultérieure. r.Update() :
r.Update()
La fonction met à jour les objets dans le cache local et le serveur API.
Les opérations de mise à jour sur le serveur API peuvent échouer avec une erreur « conflit » si l'objet a été modifié dans le cache local depuis sa récupération initiale. Cela se produit lorsque la version d'un objet dans le cache ne correspond pas à la version sur le serveur API, indiquant que quelqu'un d'autre a modifié l'objet entre-temps.
Il existe des stratégies pour y faire face -
乐观并发控制(OCC):
- Mis à jour pour correspondre à la version précédente. retry
-retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { return r.Update(ctx, pod) }) if retryErr != nil { return retryErr }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!