client-go をひたすら触っているので、そのアウトプットをしていきます。
Informer, WorkQueue, コントローラの関係図
ちょっと全体像が見えなくなってきたので、ここで一度整理したいと思います。
下記は、client-goとcustom controllerの関係図になっています。
client-go
Reflectorは、Kubernetes APIを監視する役割を持っています。informer と Watcherがやってるのがまさにここの部分になります。この2つの違いがわからなかったけれど、同じようなものととりあえず理解しておこうと思います。
Informerはclient-goに存在するものであり、またWorkQueueはカスタムコントローラに存在することは覚えておこうと思います。
Indexer は、ObjectとKeyをスレッドセーフな状態で保存します。
custom controller
Resource event handlerは、client-go で投げられたリクエストを受け取ります。受け取ったものをwork queueに詰めていきます。そのあとは順に処理していきます。
Work Queue
サンプルの実装が client-go リポジトリの中にあるので、それベースで書いていきます。
Reflectorに該当するwatcherとworkqueueを作成しています。
// watcherの作成
podListWatcher := cache.NewListWatchFromClient(clientset.CoreV1().RESTClient(), "pods", v1.NamespaceDefault, fields.Everything())// workqueueの作成
queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())
下記の実装と上記の全体像を考慮すると、以下の処理を同時に行っていることがわかります。
・indexerの作成、informerの作成
・ResourceEventHandlerにObjectを渡す
・workqueueにkeyをEnqueueする
// indexerとinformerの作成
indexer, informer := cache.NewIndexerInformer(podListWatcher, &v1.Pod{}, 0, cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
key, err := cache.MetaNamespaceKeyFunc(obj)
if err == nil {
queue.Add(key)
}
},
...
}, cache.Indexers{})
最後にcontrollerを作成して、Runメソッドを呼べば良いということになります。controllerに必要な引数は、workqueue、indexer、informer であることがわかります。
controller := NewController(queue, indexer, informer)
go controller.Run(1, stop)