NamespaceController

cmd\kube-controller-manager\app\core.go
func startNamespaceController(ctx context.Context, controllerContext ControllerContext) (controller.Interface, bool, error) {
	return startModifiedNamespaceController(ctx, controllerContext, namespaceKubeClient, nsKubeconfig)
}


func startModifiedNamespaceController(ctx context.Context, controllerContext ControllerContext, namespaceKubeClient clientset.Interface, nsKubeconfig *restclient.Config) (controller.Interface, bool, error) {
	namespaceController := namespacecontroller.NewNamespaceController(
		namespaceKubeClient,
		metadataClient,
		discoverResourcesFn,
		controllerContext.InformerFactory.Core().V1().Namespaces(),
		controllerContext.ComponentConfig.NamespaceController.NamespaceSyncPeriod.Duration,
		v1.FinalizerKubernetes,
	)
	go namespaceController.Run(int(controllerContext.ComponentConfig.NamespaceController.ConcurrentNamespaceSyncs), ctx.Done())
	return nil, true, nil
}
pkg\controller\namespace\namespace_controller.go
NewNamespaceController
	namespaceInformer.Informer().AddEventHandlerWithResyncPeriod(
		cache.ResourceEventHandlerFuncs{
			AddFunc: func(obj interface{}) {
				namespace := obj.(*v1.Namespace)
				namespaceController.enqueueNamespace(namespace)
			},
			UpdateFunc: func(oldObj, newObj interface{}) {
				namespace := newObj.(*v1.Namespace)
				namespaceController.enqueueNamespace(namespace)
			},
		},
		resyncPeriod,
	)


Run
		go wait.Until(nm.worker, time.Second, stopCh)


worker
	workFunc := func() bool {
		key, quit := nm.queue.Get()
		if quit {
			return true
		}
		defer nm.queue.Done(key)

		err := nm.syncNamespaceFromKey(key.(string))
		if err == nil {
			// no error, forget this entry and return
			nm.queue.Forget(key)
			return false
		}

		if estimate, ok := err.(*deletion.ResourcesRemainingError); ok {
			// 等待预估时间再次入队
			t := estimate.Estimate/2 + 1
			nm.queue.AddAfter(key, time.Duration(t)*time.Second)
		} else {
			// 有其他错误不等待直接入队下次处理
			nm.queue.AddRateLimited(key)
		}
		return false
	}

	for {
		quit := workFunc()

		if quit {
			return
		}
	}


syncNamespaceFromKey
	...
	return nm.namespacedResourcesDeleter.Delete(namespace.Name) --->pkg\controller\namespace\deletion\namespaced_resources_deleter.go

pkg\controller\namespace\deletion\namespaced_resources_deleter.go

**Delete**
	// 获取namespace
	namespace, err := d.nsClient.Get(context.TODO(), nsName, metav1.GetOptions{})
	...
	// 使用updateNamespaceStatusFunc方法将namespace强制更新,保证其是最新的状态
	namespace, err = d.retryOnConflictError(namespace, d.updateNamespaceStatusFunc)
	...
	if namespace.DeletionTimestamp.IsZero() {
		return nil
	}
	// 可以进行非级联删除,直接返回
	if finalized(namespace) {
		return nil
	}
	// 删除namespace下所有资源
	estimate, err := d.deleteAllContent(namespace)
	...
	// 使用finalizeNamespace冻结namespace
	_, err = d.retryOnConflictError(namespace, d.finalizeNamespace)


func (d *namespacedResourcesDeleter) retryOnConflictError(namespace *v1.Namespace, fn updateNamespaceFunc) (result *v1.Namespace, err error) {
	for {
		...
		result, err = fn(latestNamespace)
		...
	}
}


// 更新当前newNamespace
updateNamespaceStatusFunc
	...
	newNamespace := namespace.DeepCopy()
	newNamespace.Status.Phase = v1.NamespaceTerminating
	return d.nsClient.UpdateStatus(context.TODO(), newNamespace, metav1.UpdateOptions{})

// 冻结当前newNamespace
finalizeNamespace
	namespaceFinalize := v1.Namespace{}
	namespaceFinalize.ObjectMeta = namespace.ObjectMeta
	namespaceFinalize.Spec = namespace.Spec
	finalizerSet := sets.NewString()
	for i := range namespace.Spec.Finalizers {
		if namespace.Spec.Finalizers[i] != d.finalizerToken {
			finalizerSet.Insert(string(namespace.Spec.Finalizers[i]))
		}
	}
	namespaceFinalize.Spec.Finalizers = make([]v1.FinalizerName, 0, len(finalizerSet))
	for _, value := range finalizerSet.List() {
		namespaceFinalize.Spec.Finalizers = append(namespaceFinalize.Spec.Finalizers, v1.FinalizerName(value))
	}
	namespace, err := d.nsClient.Finalize(context.Background(), &namespaceFinalize, metav1.UpdateOptions{})
	return namespace, err


// 删除该namespace下所有资源,并预估删除时间
**deleteAllContent**
	...
	deletableResources := discovery.FilteredBy(discovery.SupportsAllVerbs{Verbs: []string{"delete"}}, resources)
	groupVersionResources, err := discovery.GroupVersionResources(deletableResources)
	...
	// 删除各资源并预估其删除时间
	for gvr := range groupVersionResources {
		gvrDeletionMetadata, err := d.deleteAllContentForGroupVersionResource(gvr, namespace, namespaceDeletedAt)
		if gvrDeletionMetadata.finalizerEstimateSeconds > estimate {
			estimate = gvrDeletionMetadata.finalizerEstimateSeconds
		}
		if gvrDeletionMetadata.numRemaining > 0 {
			numRemainingTotals.gvrToNumRemaining[gvr] = gvrDeletionMetadata.numRemaining
			for finalizer, numRemaining := range gvrDeletionMetadata.finalizersToNumRemaining {
				if numRemaining == 0 {
					continue
				}
				numRemainingTotals.finalizersToNumRemaining[finalizer] = numRemainingTotals.finalizersToNumRemaining[finalizer] + numRemaining
			}
		}
	}
上一篇:mysql从一个数据库向另一个数据库插数据


下一篇:SmartRF Studio 7 not able to open device control pannel for.......