Kubernetes Controller에서 Owns와 Watches의 차이점

 

Kubernetes 컨트롤러를 개발할 때 OwnsWatches를 설정하는 것은 매우 중요합니다. 이 두 개념은 컨트롤러가 특정 리소스를 어떻게 감시하고 반응할지를 결정하는데 영향을 줍니다. 이번 글에서는 OwnsWatches의 차이점을 명확히 이해하고, 언제 어떤 것을 사용해야 하는지 살펴보겠습니다.

 

Owns란

Owns는 컨트롤러가 직접 생성한 리소스를 감시할 때 사용됩니다. 즉, 컨트롤러가 특정 리소스를 생성하고, 그 리소스에 변경이 생길 때 이를 감지하여 다시 조정(Reconcile)하도록 설정할 수 있습니다. 또한, Owns를 사용하면 자동으로 해당 리소스의 OwnerReference가 설정됩니다. 이를 통해 컨트롤러는 해당 리소스의 변경 사항을 감지하고 적절한 대응을 할 수 있습니다.

예제 코드

// SetupWithManager sets up the controller with the Manager.
func (r *AyaTrackerReconciler) SetupWithManager(mgr ctrl.Manager) error {
	return ctrl.NewControllerManagedBy(mgr).
		For(&ayav1alpha1.AyaTracker{}).
		Complete(r)
}

 

위 코드에서 Owns(&corev1.Pod{})를 사용하여 AyaTracker 컨트롤러가 생성한 Pod 리소스를 감시하도록 설정했습니다. AyaTracker가 생성한 Pod가 변경되면 컨트롤러가 이를 감지하고 Reconcile 함수를 실행합니다.

또한, OwnerReference가 설정되어 있으므로, Pod가 삭제될 경우 AyaTracker 리소스에도 영향을 줄 수 있습니다.

 

Watches란 

Watches는 컨트롤러가 직접 생성하지 않은 리소스도 감시할 수 있도록 해줍니다. 즉, 특정 리소스를 감시하고, 해당 리소스에 변경이 생기면 지정한 핸들러를 통해 Reconcile을 호출할 수 있습니다.

 

예제 코드

func (r *AyaTrackerReconciler) SetupWithManager(mgr ctrl.Manager) error {
	return ctrl.NewControllerManagedBy(mgr).
		For(&ayav1alpha1.AyaTracker{}).
		Watches(
			&source.Kind{Type: &corev1.Pod{}},
			&handler.EnqueueRequestForObject{},
		).
		Complete(r)
}

 

위 코드에서 Watches를 사용하여 Pod를 감시하고 있습니다. 중요한 점은 이 PodAyaTracker 컨트롤러에 의해 생성된 것이 아닐 수도 있다는 것입니다.

이때 handler.EnqueueRequestForObject{}를 사용하면 Pod의 변경 사항이 발생할 경우, 해당 객체의 namespacenameReconcile 요청으로 보냅니다. 이를 통해 컨트롤러는 직접 생성하지 않은 리소스라도 변경 사항을 감지하고 대응할 수 있습니다.

Watches 핸들러

https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/handler

 

handler package - sigs.k8s.io/controller-runtime/pkg/handler - Go Packages

Discover Packages sigs.k8s.io/controller-runtime pkg handler Version: v0.20.1 Opens a new window with list of versions in this module. Published: Jan 23, 2025 License: Apache-2.0 Opens a new window with license information. Imports: 15 Opens a new window w

pkg.go.dev

 

EnqueueRequestForObject

컨트롤러는 감시 중인 리소스(Pod 등)의 변경이 발생하면, 해당 객체의 네임스페이스와 이름을 기반으로 Reconcile을 실행합니다. 이를 통해 컨트롤러는 직접 생성하지 않은 리소스라도 변경 사항을 감지하고 대응할 수 있습니다.

&handler.EnqueueRequestForObject{}

 

EnqueueRequestForOwner

Owns는 컨트롤러가 직접 생성한 리소스를 감시하는 반면, EnqueueRequestForOwner는 컨트롤러가 생성하지 않은 리소스라도 특정 소유자(Owner)에 대해 감시할 수 있도록 합니다. 예를 들어, 컨트롤러(A)가 생성한 리소스를 컨트롤러(B)가 감시하고, 해당 리소스가 변경되면 컨트롤러(B)는 Reconcile을 실행할 수 있습니다.

&handler.EnqueueRequestForOwner{
    OwnerType:    &ayav1alpha1.OtherResource{},
    IsController: false,
}

 

EnqueueRequestsFromMapFunc

컨트롤러는 리소스 변경 시 특정 로직을 적용하여 여러 개의 Reconcile 요청을 생성할 수 있습니다. Label을 기반으로 여러 리소스를 감시하고 대응할 때 활용할 수 있습니다. 예를 들어, 특정 Label (tracked=true)을 가진 ConfigMap이 변경될 때, 컨트롤러는 CustomResourceBReconcile을 실행할 수 있습니다.

&handler.EnqueueRequestsFromMapFunc(func(a client.Object) []reconcile.Request {
    return []reconcile.Request{
        {NamespacedName: types.NamespacedName{Name: "example", Namespace: "default"}},
    }
})