NamespaceController

image

cmd\kube-controller-manager\app\apps.go
startDaemonSetController
func startNamespaceController(ctx context.Context, controllerContext ControllerContext) (controller.Interface, bool, error) {
	...
	return startModifiedNamespaceController(ctx, controllerContext, namespaceKubeClient, nsKubeconfig)
}
startModifiedNamespaceController
func startModifiedNamespaceController(ctx context.Context, controllerContext ControllerContext, namespaceKubeClient clientset.Interface, nsKubeconfig *restclient.Config) (controller.Interface, bool, error) {
	metadataClient, err := metadata.NewForConfig(nsKubeconfig)
	discoverResourcesFn := namespaceKubeClient.Discovery().ServerPreferredNamespacedResources
	namespaceController := namespacecontroller.NewNamespaceController(
		namespaceKubeClient,
		metadataClient,
		discoverResourcesFn,
		controllerContext.InformerFactory.Core().V1().Namespaces(), // 仅关注ns对象
		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
func 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,
	)
}
enqueueNamespace
func (nm *NamespaceController) enqueueNamespace(obj interface{}) {
	key, err := controller.KeyFunc(obj)
	namespace := obj.(*v1.Namespace)
	//  ns已经被标识删除就不用重复处理了
	if namespace.DeletionTimestamp == nil || namespace.DeletionTimestamp.IsZero() {
		return
	}
	nm.queue.AddAfter(key, namespaceDeletionGracePeriod)
}
Run
func (nm *NamespaceController) Run(workers int, stopCh <-chan struct{}) {
	...
	for i := 0; i < workers; i++ {
		go wait.Until(nm.worker, time.Second, stopCh)
	}
	<-stopCh
}
worker
func (nm *NamespaceController) worker() {
	workFunc := func() bool {
		key, quit := nm.queue.Get()
		err := nm.syncNamespaceFromKey(key.(string))
		...
		return false
	}
	...
}
syncNamespaceFromKey
func (nm *NamespaceController) syncNamespaceFromKey(key string) (err error) {
	namespace, err := nm.lister.Get(key)
	return nm.namespacedResourcesDeleter.Delete(namespace.Name)
}
pkg\controller\namespace\deletion\namespaced_resources_deleter.go
Delete
func (d *namespacedResourcesDeleter) Delete(nsName string) error {
	namespace, err := d.nsClient.Get(context.TODO(), nsName, metav1.GetOptions{})
	if namespace.DeletionTimestamp == nil {
		return nil
	}
	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)

	return nil
}
updateNamespaceStatusFunc
func (d *namespacedResourcesDeleter) updateNamespaceStatusFunc(namespace *v1.Namespace) (*v1.Namespace, error) {
	if namespace.DeletionTimestamp.IsZero() || namespace.Status.Phase == v1.NamespaceTerminating {
		return namespace, nil
	}
	newNamespace := namespace.DeepCopy()
	newNamespace.Status.Phase = v1.NamespaceTerminating		// 更新ns为Terminating状态
	return d.nsClient.UpdateStatus(context.TODO(), newNamespace, metav1.UpdateOptions{})
}
finalizeNamespace
func (d *namespacedResourcesDeleter) finalizeNamespace(namespace *v1.Namespace) (*v1.Namespace, error) {
	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{})		// 冻结掉ns下所有资源
	if err != nil {
		if errors.IsNotFound(err) {
			return namespace, nil
		}
	}
	return namespace, err
}
deleteAllContent
func (d *namespacedResourcesDeleter) deleteAllContent(ns *v1.Namespace) (int64, error) {
	...
	deletableResources := discovery.FilteredBy(discovery.SupportsAllVerbs{Verbs: []string{"delete"}}, resources)
	// 使用dynamic client因为ns下可能有crd资源
	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
			}
		}
	}
	...
}
posted @ 2022-02-09 12:13  北方姆Q  阅读(109)  评论(0)    收藏  举报