-
CRD 리소스에서 Optimistic Concurrency Control(OCC) 구현Kubernetes 2025. 4. 2. 04:20728x90
Kubernetes는 분산 환경에서 여러 클라이언트가 동시에 리소스를 수정할 수 있기 때문에, 충돌 관리가 중요합니다. 이를 해결하기 위해 Kubernetes는 Optimistic Concurrency Control(OCC) 방식을 사용합니다.
이 글에서는 CRD(Custom Resource Definition) 리소스에서도 OCC를 어떻게 구현하고 사용하는지, 그리고 실제 Go 코드로 어떻게 처리하는지 알아보겠습니다.
OCC란?
OCC(낙관적 동시성 제어)는 "충돌이 자주 일어나지 않을 것"이라고 가정하고,
리소스를 수정할 때마다 현재 버전(resourceVersion)을 확인하여 충돌 여부를 판단하는 방식입니다.- 최신 버전일 경우 → 정상 업데이트
- 버전 불일치 시 → 409 Conflict 오류 발생 → 재시도 필요
Kubernetes에서는 모든 리소스가 metadata.resourceVersion 필드를 가지고 있으며, 이 값은 리소스가 수정될 때마다 변경됩니다.
CRD 리소스에서 OCC 적용 방법
CRD(Custom Resource)도 일반 리소스처럼 resourceVersion을 활용한 OCC가 적용됩니다.
즉, 리소스를 가져온 후 변경된 값을 업데이트할 때, resourceVersion이 바뀌었으면 충돌로 간주하고 실패하게 됩니다.이를 코드로 안전하게 처리하려면 다음과 같은 방식이 필요합니다:
- 리소스를 가져온다 (resourceVersion 포함됨)
- 원하는 내용을 수정한다
- 업데이트를 시도한다
- Conflict 오류 발생 시 재시도한다
Go 코드 예제 (controller-runtime 사용)
다음은 MyApp이라는 CRD 리소스를 안전하게 업데이트하는 예제입니다.
package main import ( "context" "fmt" "time" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" ctrl "sigs.k8s.io/controller-runtime" ) func main() { ctx := context.Background() // Kubernetes 클라이언트 생성 cfg := ctrl.GetConfigOrDie() k8sClient, err := client.New(cfg, client.Options{}) if err != nil { panic(err) } namespace := "default" name := "example-myapp" gvk := schema.GroupVersionKind{ Group: "myorg.io", Version: "v1", Kind: "MyApp", } for i := 0; i < 5; i++ { // 리소스 읽기 obj := &unstructured.Unstructured{} obj.SetGroupVersionKind(gvk) err := k8sClient.Get(ctx, types.NamespacedName{ Name: name, Namespace: namespace, }, obj) if err != nil { panic(fmt.Errorf("failed to get resource: %w", err)) } // spec.version 필드 수정 unstructured.SetNestedField(obj.Object, time.Now().Format(time.RFC3339), "spec", "version") // 업데이트 시도 err = k8sClient.Update(ctx, obj) if client.IgnoreConflict(err) == nil { fmt.Println("⚠️ Conflict detected, retrying...") time.Sleep(1 * time.Second) continue } else if err != nil { panic(fmt.Errorf("update failed: %w", err)) } fmt.Println("✅ Successfully updated MyApp CR") break } }
주요 포인트 정리
항목 설명 unstructured.Unstructured CRD 리소스를 동적으로 다루기 위한 타입 resourceVersion API 서버가 충돌 여부를 판단하는 기준 client.Update() 내부적으로 OCC 적용됨 client.IgnoreConflict() 409 Conflict 오류면 nil 반환 → 재시도 가능 재시도 로직 충돌 시 일정 시간 후 다시 시도 (낙관적 접근) 마무리
Kubernetes에서 OCC는 분산 환경에서의 정합성 유지를 위한 핵심 메커니즘입니다. CRD를 다룰 때도 이 원리를 이해하고 적용하면, 안정적인 커스텀 컨트롤러나 자동화 도구를 만들 수 있습니다.
특히, 리소스를 자주 변경하는 시스템이나 여러 컨트롤러가 동시에 접근하는 구조에서는 충돌 감지 → 재시도 로직을 반드시 포함해야 합니다.
728x90'Kubernetes' 카테고리의 다른 글
Kubernetes의 AdmissionReview (0) 2025.04.02 CRD에 대해 Webhook을 통한 유효성 검증 (0) 2025.04.02 Kubernetes의 Optimistic Concurrency Control (OCC) (0) 2025.04.02 Kubernetes API 서버에서 "Lock"을 관리하는 방법 (0) 2025.04.02 Amazon EKS Auto Mode (0) 2025.04.01