• 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
    			}
    		}
    	}
    
  • 相关阅读:
    流媒体传输协议之 RTP(下篇)
    我在春晚现场护航直播
    【邀请有礼】全球视频云创新挑战赛邀请有礼:参与 100% 获得 “壕” 礼,更有机会获得 JBL 音箱、Cherry 机械键盘
    流媒体传输协议之 RTMP
    WebRTC 音视频同步原理与实现
    阿里云联手 Intel 举办首届视频云挑战赛,40 万奖金邀你来战!
    你真的懂 MP4 格式吗?
    如何用 4 个小时搭建一个新 “Clubhouse” ,引爆声音社交新风口
    流媒体传输协议之 RTP (上篇)
    POJ 1655 Balancing Act【树形DP】POJ 1655 Balancing Act Balancing Act POJ 1655
  • 原文地址:https://www.cnblogs.com/bfmq/p/15874492.html
Copyright © 2020-2023  润新知