Watching Kubernetes custom resources with dynamic informers & golang
k8s Operator를 만들 때, CRD의 reconcile 로직을 적용하기 위해 Get / List Loop를 쓰는 경우가 있다.
- ineffective / slow way to find changes.
- 예컨대 리소스가 backoff 상태라면 Get / List 요청을 보내는 주기가 갈수록 느려진다.
- 리소스가 많을 경우 pagination 등... 고려할 것들이 늘어남
- client go에서 제공하는 (shared) cache를 사용해서 보완하기도 함
- 위의 방식들보다 더 나은, InformerFactory를 사용해서 Watcher를 만드는 방법
- Watcher: Event Stream that is dynamically connected; like a pipe from API server to your Implementation.
- send back & forth events over GRPC.
- get Real-time updates. Restful Request를 매번 주고받는 게 아니라 single Event Stream을 받는다.
- Watcher: Event Stream that is dynamically connected; like a pipe from API server to your Implementation.
- client go에서 informer 관련 구현체는 문서화가 덜 되어 있는 편임.
https://aly.arriqaaq.com/kubernetes-informers/
A Deep Dive Into Kubernetes Informers
I wanted to understand more about how Kubernetes controllers are implemented. Building controllers with controller-runtime [https://github.com/kubernetes-sigs/kubebuilder] is pretty easy but it masks many details on how the event-oriented architecture of c
aly.arriqaaq.com
구현할 것: Dynamic Shared Informer Factory.
- Dynamic? -> Not using Concrete Type defined in the client.
- k8s go client의 패키지 형태로 제공 https://pkg.go.dev/k8s.io/client-go/dynamic
- 원본 코드: https://github.com/cloud-native-skunkworks/dynamic-informer
package main | |
import ( | |
"log" | |
"os" | |
"time" | |
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1" | |
"k8s.io/client-go/dynamic" | |
"k8s.io/client-go/dynamic/dynamicinformer" | |
"k8s.io/client-go/rest" | |
"k8s.io/client-go/tools/cache" | |
"k8s.io/client-go/tools/clientcmd" | |
) | |
func buildConfiguration() (*rest.Config, error) { | |
kubeconfig := os.Getenv("KUBECONFIG") | |
var clusterConfig *rest.Config | |
var err error | |
if kubeconfig != "" { | |
clusterConfig, err = clientcmd.BuildConfigFromFlags("", kubeconfig) | |
} else { | |
clusterConfig, err = rest.InClusterConfig() | |
} | |
if err != nil { | |
return nil, err | |
} | |
return clusterConfig, nil | |
} | |
func main() { | |
clusterConfig, err := buildConfiguration() | |
if err != nil { | |
panic(err) | |
} | |
// traditional k8s client 대신 dynamic 패키지 사용. | |
clusterClient, err := dynamic.NewForConfig(clusterConfig) | |
if err != nil { | |
log.Fatalln(err) | |
} | |
// CRD operator에서 제공하는 Resource 정보. | |
resource := v1alpha1.GroupVersion.WithResource("featureflagconfigurations") | |
// shared Informer factory 생성. look at several different clsuter resources simultaneously. | |
//// resync time: cache between listing. | |
factory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(clusterClient, | |
time.Minute, "", nil) | |
informer := factory.ForResource(resource).Informer() | |
// event handler 추가. | |
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ | |
AddFunc: func(obj interface{}) { | |
log.Println("AddFunc") | |
}, | |
UpdateFunc: func(oldObj, newObj interface{}) { | |
log.Println("UpdateFunc") | |
// 이벤트 발생했을 때 interface{}를 필요한 리소스로 매핑하는 형태로 사용 가능. | |
// ex) | |
// var featureflagObject v1alpha1.FeatureFlagConfiguration | |
//err := runtime.DefaultUnstructuredConverter.FromUnstructured(newObj, (*unstructured.Unstructured).Object, &featureflagObject) | |
// if err != nil { | |
// log.Println(err.Error()) | |
// } | |
}, | |
DeleteFunc: func(obj interface{}) { | |
log.Println("DeleteFunc") | |
}, | |
}) | |
// informer에 context를 추가하거나 inline channel을 넣는다. | |
informer.Run(make(chan struct{})) | |
} |
더 자세한 내용은 https://blog.dsb.dev/posts/creating-dynamic-informers/ 서 확인할 수 있다.
Go: Creating Dynamic Kubernetes Informers
Introduction Recently, I published v1.0.0 of Kollect, a dynamic Kubernetes informer that publishes changes in cluster resources to a configurable event bus. At the heart of this project is a dynamic informer, a method of handling add/update/delete notifica
blog.dsb.dev
'학습일지 > kubernetes' 카테고리의 다른 글
Naver Engineering Day 2024 - Kubernetes에서 DNS 다루는 방법 (0) | 2024.06.26 |
---|---|
KubeCon 2020 - Kubernetes Leader Election for Fun and Profit (0) | 2023.08.05 |
if kakao 2022 - Kubernetes Controller를 위한 테스트코드 작성 (0) | 2023.02.24 |
ContainerDays 2021 - Into the Core of Kubernetes: the internals of etcd 정리 (0) | 2022.12.30 |
if kakao 2021 - k8s Cluster 확장, 어디까지 알아보고 오셨어요? (1) | 2022.06.02 |