support watch namespaces matched namespace selector (#7472)

skip caching namespaces at cluster scope if only watching single namespace

add --watch-namespace-selector in user guide

add e2e test
This commit is contained in:
zryfish 2021-11-13 03:46:28 +08:00 committed by GitHub
parent 67e13bf692
commit 7203a0b8bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 461 additions and 19 deletions

View file

@ -32,6 +32,7 @@ import (
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
k8sruntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@ -127,6 +128,7 @@ type Informer struct {
Service cache.SharedIndexInformer
Secret cache.SharedIndexInformer
ConfigMap cache.SharedIndexInformer
Namespace cache.SharedIndexInformer
}
// Lister contains object listers (stores).
@ -137,6 +139,7 @@ type Lister struct {
Endpoint EndpointLister
Secret SecretLister
ConfigMap ConfigMapLister
Namespace NamespaceLister
IngressWithAnnotation IngressWithAnnotationsLister
}
@ -172,6 +175,15 @@ func (i *Informer) Run(stopCh chan struct{}) {
runtime.HandleError(fmt.Errorf("timed out waiting for ingress classcaches to sync"))
}
// when limit controller scope to one namespace, skip sync namespaces at cluster scope
if i.Namespace != nil {
go i.Namespace.Run(stopCh)
if !cache.WaitForCacheSync(stopCh, i.Namespace.HasSynced) {
runtime.HandleError(fmt.Errorf("timed out waiting for caches to sync"))
}
}
// in big clusters, deltas can keep arriving even after HasSynced
// functions have returned 'true'
time.Sleep(1 * time.Second)
@ -225,7 +237,9 @@ type k8sStore struct {
// New creates a new object store to be used in the ingress controller
func New(
namespace, configmap, tcp, udp, defaultSSLCertificate string,
namespace string,
namespaceSelector labels.Selector,
configmap, tcp, udp, defaultSSLCertificate string,
resyncPeriod time.Duration,
client clientset.Interface,
updateCh *channels.RingChannel,
@ -322,6 +336,35 @@ func New(
store.informers.Service = infFactory.Core().V1().Services().Informer()
store.listers.Service.Store = store.informers.Service.GetStore()
// avoid caching namespaces at cluster scope when watching single namespace
if namespaceSelector != nil && !namespaceSelector.Empty() {
// cache informers factory for namespaces
infFactoryNamespaces := informers.NewSharedInformerFactoryWithOptions(client, resyncPeriod,
informers.WithTweakListOptions(labelsTweakListOptionsFunc),
)
store.informers.Namespace = infFactoryNamespaces.Core().V1().Namespaces().Informer()
store.listers.Namespace.Store = store.informers.Namespace.GetStore()
}
watchedNamespace := func(namespace string) bool {
if namespaceSelector == nil || namespaceSelector.Empty() {
return true
}
item, ok, err := store.listers.Namespace.GetByKey(namespace)
if !ok {
klog.Errorf("Namespace %s not existed: %v.", namespace, err)
return false
}
ns, ok := item.(*corev1.Namespace)
if !ok {
return false
}
return namespaceSelector.Matches(labels.Set(ns.Labels))
}
ingDeleteHandler := func(obj interface{}) {
ing, ok := toIngress(obj)
if !ok {
@ -338,6 +381,10 @@ func New(
}
}
if !watchedNamespace(ing.Namespace) {
return
}
_, err := store.GetIngressClass(ing, icConfig)
if err != nil {
klog.InfoS("Ignoring ingress because of error while validating ingress class", "ingress", klog.KObj(ing), "error", err)
@ -363,6 +410,11 @@ func New(
ingEventHandler := cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
ing, _ := toIngress(obj)
if !watchedNamespace(ing.Namespace) {
return
}
ic, err := store.GetIngressClass(ing, icConfig)
if err != nil {
klog.InfoS("Ignoring ingress because of error while validating ingress class", "ingress", klog.KObj(ing), "error", err)
@ -392,6 +444,10 @@ func New(
oldIng, _ := toIngress(old)
curIng, _ := toIngress(cur)
if !watchedNamespace(oldIng.Namespace) {
return
}
var errOld, errCur error
var classCur string
if !icConfig.IgnoreIngressClass {
@ -528,6 +584,10 @@ func New(
sec := cur.(*corev1.Secret)
key := k8s.MetaNamespaceKey(sec)
if !watchedNamespace(sec.Namespace) {
return
}
if store.defaultSSLCertificate == key {
store.syncSecret(store.defaultSSLCertificate)
}
@ -566,6 +626,10 @@ func New(
}
}
if !watchedNamespace(sec.Namespace) {
return
}
store.sslStore.Delete(k8s.MetaNamespaceKey(sec))
key := k8s.MetaNamespaceKey(sec)