namespace controller: use contextual logging

This commit is contained in:
JunYang
2022-10-29 22:34:47 +08:00
committed by 杨军10092085
parent a35650b833
commit f5bd8c86d4
7 changed files with 113 additions and 87 deletions

View File

@@ -39,11 +39,11 @@ import (
// NamespacedResourcesDeleterInterface is the interface to delete a namespace with all resources in it.
type NamespacedResourcesDeleterInterface interface {
Delete(nsName string) error
Delete(ctx context.Context, nsName string) error
}
// NewNamespacedResourcesDeleter returns a new NamespacedResourcesDeleter.
func NewNamespacedResourcesDeleter(nsClient v1clientset.NamespaceInterface,
func NewNamespacedResourcesDeleter(ctx context.Context, nsClient v1clientset.NamespaceInterface,
metadataClient metadata.Interface, podsGetter v1clientset.PodsGetter,
discoverResourcesFn func() ([]*metav1.APIResourceList, error),
finalizerToken v1.FinalizerName) NamespacedResourcesDeleterInterface {
@@ -57,7 +57,7 @@ func NewNamespacedResourcesDeleter(nsClient v1clientset.NamespaceInterface,
discoverResourcesFn: discoverResourcesFn,
finalizerToken: finalizerToken,
}
d.initOpCache()
d.initOpCache(ctx)
return d
}
@@ -93,7 +93,7 @@ type namespacedResourcesDeleter struct {
// Returns ResourcesRemainingError if it deleted some resources but needs
// to wait for them to go away.
// Caller is expected to keep calling this until it succeeds.
func (d *namespacedResourcesDeleter) Delete(nsName string) error {
func (d *namespacedResourcesDeleter) Delete(ctx context.Context, nsName string) error {
// Multiple controllers may edit a namespace during termination
// first get the latest state of the namespace before proceeding
// if the namespace was deleted already, don't do anything
@@ -108,7 +108,7 @@ func (d *namespacedResourcesDeleter) Delete(nsName string) error {
return nil
}
klog.V(5).Infof("namespace controller - syncNamespace - namespace: %s, finalizerToken: %s", namespace.Name, d.finalizerToken)
klog.FromContext(ctx).V(5).Info("Namespace controller - syncNamespace", "namespace", namespace.Name, "finalizerToken", d.finalizerToken)
// ensure that the status is up to date on the namespace
// if we get a not found error, we assume the namespace is truly gone
@@ -131,7 +131,7 @@ func (d *namespacedResourcesDeleter) Delete(nsName string) error {
}
// there may still be content for us to remove
estimate, err := d.deleteAllContent(namespace)
estimate, err := d.deleteAllContent(ctx, namespace)
if err != nil {
return err
}
@@ -153,7 +153,7 @@ func (d *namespacedResourcesDeleter) Delete(nsName string) error {
return nil
}
func (d *namespacedResourcesDeleter) initOpCache() {
func (d *namespacedResourcesDeleter) initOpCache(ctx context.Context) {
// pre-fill opCache with the discovery info
//
// TODO(sttts): get rid of opCache and http 405 logic around it and trust discovery info
@@ -161,14 +161,16 @@ func (d *namespacedResourcesDeleter) initOpCache() {
if err != nil {
utilruntime.HandleError(fmt.Errorf("unable to get all supported resources from server: %v", err))
}
logger := klog.FromContext(ctx)
if len(resources) == 0 {
klog.Fatalf("Unable to get any supported resources from server: %v", err)
logger.Error(err, "Unable to get any supported resources from server")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}
for _, rl := range resources {
gv, err := schema.ParseGroupVersion(rl.GroupVersion)
if err != nil {
klog.Errorf("Failed to parse GroupVersion %q, skipping: %v", rl.GroupVersion, err)
logger.Error(err, "Failed to parse GroupVersion, skipping", "groupVersion", rl.GroupVersion)
continue
}
@@ -177,7 +179,7 @@ func (d *namespacedResourcesDeleter) initOpCache() {
verbs := sets.NewString([]string(r.Verbs)...)
if !verbs.Has("delete") {
klog.V(6).Infof("Skipping resource %v because it cannot be deleted.", gvr)
logger.V(6).Info("Skipping resource because it cannot be deleted", "resource", gvr)
}
for _, op := range []operation{operationList, operationDeleteCollection} {
@@ -205,7 +207,7 @@ const (
operationDeleteCollection operation = "deletecollection"
operationList operation = "list"
// assume a default estimate for finalizers to complete when found on items pending deletion.
finalizerEstimateSeconds int64 = int64(15)
finalizerEstimateSeconds = int64(15)
)
// operationKey is an entry in a cache.
@@ -304,12 +306,13 @@ func (d *namespacedResourcesDeleter) finalizeNamespace(namespace *v1.Namespace)
// deleteCollection is a helper function that will delete the collection of resources
// it returns true if the operation was supported on the server.
// it returns an error if the operation was supported on the server but was unable to complete.
func (d *namespacedResourcesDeleter) deleteCollection(gvr schema.GroupVersionResource, namespace string) (bool, error) {
klog.V(5).Infof("namespace controller - deleteCollection - namespace: %s, gvr: %v", namespace, gvr)
func (d *namespacedResourcesDeleter) deleteCollection(ctx context.Context, gvr schema.GroupVersionResource, namespace string) (bool, error) {
logger := klog.FromContext(ctx)
logger.V(5).Info("Namespace controller - deleteCollection", "namespace", namespace, "resource", gvr)
key := operationKey{operation: operationDeleteCollection, gvr: gvr}
if !d.opCache.isSupported(key) {
klog.V(5).Infof("namespace controller - deleteCollection ignored since not supported - namespace: %s, gvr: %v", namespace, gvr)
logger.V(5).Info("Namespace controller - deleteCollection ignored since not supported", "namespace", namespace, "resource", gvr)
return false, nil
}
@@ -330,11 +333,11 @@ func (d *namespacedResourcesDeleter) deleteCollection(gvr schema.GroupVersionRes
// /apis/extensions/v1beta1/namespaces/default/replicationcontrollers
// when working with this resource type, we will get a literal not found error rather than expected method not supported
if errors.IsMethodNotSupported(err) || errors.IsNotFound(err) {
klog.V(5).Infof("namespace controller - deleteCollection not supported - namespace: %s, gvr: %v", namespace, gvr)
logger.V(5).Info("Namespace controller - deleteCollection not supported", "namespace", namespace, "resource", gvr)
return false, nil
}
klog.V(5).Infof("namespace controller - deleteCollection unexpected error - namespace: %s, gvr: %v, error: %v", namespace, gvr, err)
logger.V(5).Info("Namespace controller - deleteCollection unexpected error", "namespace", namespace, "resource", gvr, "err", err)
return true, err
}
@@ -344,12 +347,13 @@ func (d *namespacedResourcesDeleter) deleteCollection(gvr schema.GroupVersionRes
// the list of items in the collection (if found)
// a boolean if the operation is supported
// an error if the operation is supported but could not be completed.
func (d *namespacedResourcesDeleter) listCollection(gvr schema.GroupVersionResource, namespace string) (*metav1.PartialObjectMetadataList, bool, error) {
klog.V(5).Infof("namespace controller - listCollection - namespace: %s, gvr: %v", namespace, gvr)
func (d *namespacedResourcesDeleter) listCollection(ctx context.Context, gvr schema.GroupVersionResource, namespace string) (*metav1.PartialObjectMetadataList, bool, error) {
logger := klog.FromContext(ctx)
logger.V(5).Info("Namespace controller - listCollection", "namespace", namespace, "resource", gvr)
key := operationKey{operation: operationList, gvr: gvr}
if !d.opCache.isSupported(key) {
klog.V(5).Infof("namespace controller - listCollection ignored since not supported - namespace: %s, gvr: %v", namespace, gvr)
logger.V(5).Info("Namespace controller - listCollection ignored since not supported", "namespace", namespace, "resource", gvr)
return nil, false, nil
}
@@ -364,7 +368,7 @@ func (d *namespacedResourcesDeleter) listCollection(gvr schema.GroupVersionResou
// /apis/extensions/v1beta1/namespaces/default/replicationcontrollers
// when working with this resource type, we will get a literal not found error rather than expected method not supported
if errors.IsMethodNotSupported(err) || errors.IsNotFound(err) {
klog.V(5).Infof("namespace controller - listCollection not supported - namespace: %s, gvr: %v", namespace, gvr)
logger.V(5).Info("Namespace controller - listCollection not supported", "namespace", namespace, "resource", gvr)
return nil, false, nil
}
@@ -372,10 +376,10 @@ func (d *namespacedResourcesDeleter) listCollection(gvr schema.GroupVersionResou
}
// deleteEachItem is a helper function that will list the collection of resources and delete each item 1 by 1.
func (d *namespacedResourcesDeleter) deleteEachItem(gvr schema.GroupVersionResource, namespace string) error {
klog.V(5).Infof("namespace controller - deleteEachItem - namespace: %s, gvr: %v", namespace, gvr)
func (d *namespacedResourcesDeleter) deleteEachItem(ctx context.Context, gvr schema.GroupVersionResource, namespace string) error {
klog.FromContext(ctx).V(5).Info("Namespace controller - deleteEachItem", "namespace", namespace, "resource", gvr)
unstructuredList, listSupported, err := d.listCollection(gvr, namespace)
unstructuredList, listSupported, err := d.listCollection(ctx, gvr, namespace)
if err != nil {
return err
}
@@ -406,27 +410,29 @@ type gvrDeletionMetadata struct {
// It returns an estimate of the time remaining before the remaining resources are deleted.
// If estimate > 0, not all resources are guaranteed to be gone.
func (d *namespacedResourcesDeleter) deleteAllContentForGroupVersionResource(
ctx context.Context,
gvr schema.GroupVersionResource, namespace string,
namespaceDeletedAt metav1.Time) (gvrDeletionMetadata, error) {
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - namespace: %s, gvr: %v", namespace, gvr)
logger := klog.FromContext(ctx)
logger.V(5).Info("Namespace controller - deleteAllContentForGroupVersionResource", "namespace", namespace, "resource", gvr)
// estimate how long it will take for the resource to be deleted (needed for objects that support graceful delete)
estimate, err := d.estimateGracefulTermination(gvr, namespace, namespaceDeletedAt)
estimate, err := d.estimateGracefulTermination(ctx, gvr, namespace, namespaceDeletedAt)
if err != nil {
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - unable to estimate - namespace: %s, gvr: %v, err: %v", namespace, gvr, err)
logger.V(5).Info("Namespace controller - deleteAllContentForGroupVersionResource - unable to estimate", "namespace", namespace, "resource", gvr, "err", err)
return gvrDeletionMetadata{}, err
}
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - estimate - namespace: %s, gvr: %v, estimate: %v", namespace, gvr, estimate)
logger.V(5).Info("Namespace controller - deleteAllContentForGroupVersionResource - estimate", "namespace", namespace, "resource", gvr, "estimate", estimate)
// first try to delete the entire collection
deleteCollectionSupported, err := d.deleteCollection(gvr, namespace)
deleteCollectionSupported, err := d.deleteCollection(ctx, gvr, namespace)
if err != nil {
return gvrDeletionMetadata{finalizerEstimateSeconds: estimate}, err
}
// delete collection was not supported, so we list and delete each item...
if !deleteCollectionSupported {
err = d.deleteEachItem(gvr, namespace)
err = d.deleteEachItem(ctx, gvr, namespace)
if err != nil {
return gvrDeletionMetadata{finalizerEstimateSeconds: estimate}, err
}
@@ -434,16 +440,16 @@ func (d *namespacedResourcesDeleter) deleteAllContentForGroupVersionResource(
// verify there are no more remaining items
// it is not an error condition for there to be remaining items if local estimate is non-zero
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - checking for no more items in namespace: %s, gvr: %v", namespace, gvr)
unstructuredList, listSupported, err := d.listCollection(gvr, namespace)
logger.V(5).Info("Namespace controller - deleteAllContentForGroupVersionResource - checking for no more items in namespace", "namespace", namespace, "resource", gvr)
unstructuredList, listSupported, err := d.listCollection(ctx, gvr, namespace)
if err != nil {
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - error verifying no items in namespace: %s, gvr: %v, err: %v", namespace, gvr, err)
logger.V(5).Info("Namespace controller - deleteAllContentForGroupVersionResource - error verifying no items in namespace", "namespace", namespace, "resource", gvr, "err", err)
return gvrDeletionMetadata{finalizerEstimateSeconds: estimate}, err
}
if !listSupported {
return gvrDeletionMetadata{finalizerEstimateSeconds: estimate}, nil
}
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - items remaining - namespace: %s, gvr: %v, items: %v", namespace, gvr, len(unstructuredList.Items))
logger.V(5).Info("Namespace controller - deleteAllContentForGroupVersionResource - items remaining", "namespace", namespace, "resource", gvr, "items", len(unstructuredList.Items))
if len(unstructuredList.Items) == 0 {
// we're done
return gvrDeletionMetadata{finalizerEstimateSeconds: 0, numRemaining: 0}, nil
@@ -458,7 +464,7 @@ func (d *namespacedResourcesDeleter) deleteAllContentForGroupVersionResource(
}
if estimate != int64(0) {
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - estimate is present - namespace: %s, gvr: %v, finalizers: %v", namespace, gvr, finalizersToNumRemaining)
logger.V(5).Info("Namespace controller - deleteAllContentForGroupVersionResource - estimate is present", "namespace", namespace, "resource", gvr, "finalizers", finalizersToNumRemaining)
return gvrDeletionMetadata{
finalizerEstimateSeconds: estimate,
numRemaining: len(unstructuredList.Items),
@@ -468,7 +474,7 @@ func (d *namespacedResourcesDeleter) deleteAllContentForGroupVersionResource(
// if any item has a finalizer, we treat that as a normal condition, and use a default estimation to allow for GC to complete.
if len(finalizersToNumRemaining) > 0 {
klog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - items remaining with finalizers - namespace: %s, gvr: %v, finalizers: %v", namespace, gvr, finalizersToNumRemaining)
logger.V(5).Info("Namespace controller - deleteAllContentForGroupVersionResource - items remaining with finalizers", "namespace", namespace, "resource", gvr, "finalizers", finalizersToNumRemaining)
return gvrDeletionMetadata{
finalizerEstimateSeconds: finalizerEstimateSeconds,
numRemaining: len(unstructuredList.Items),
@@ -493,13 +499,14 @@ type allGVRDeletionMetadata struct {
// deleteAllContent will use the dynamic client to delete each resource identified in groupVersionResources.
// It returns an estimate of the time remaining before the remaining resources are deleted.
// If estimate > 0, not all resources are guaranteed to be gone.
func (d *namespacedResourcesDeleter) deleteAllContent(ns *v1.Namespace) (int64, error) {
func (d *namespacedResourcesDeleter) deleteAllContent(ctx context.Context, ns *v1.Namespace) (int64, error) {
namespace := ns.Name
namespaceDeletedAt := *ns.DeletionTimestamp
var errs []error
conditionUpdater := namespaceConditionUpdater{}
estimate := int64(0)
klog.V(4).Infof("namespace controller - deleteAllContent - namespace: %s", namespace)
logger := klog.FromContext(ctx)
logger.V(4).Info("namespace controller - deleteAllContent", "namespace", namespace)
resources, err := d.discoverResourcesFn()
if err != nil {
@@ -521,7 +528,7 @@ func (d *namespacedResourcesDeleter) deleteAllContent(ns *v1.Namespace) (int64,
finalizersToNumRemaining: map[string]int{},
}
for gvr := range groupVersionResources {
gvrDeletionMetadata, err := d.deleteAllContentForGroupVersionResource(gvr, namespace, namespaceDeletedAt)
gvrDeletionMetadata, err := d.deleteAllContentForGroupVersionResource(ctx, gvr, namespace, namespaceDeletedAt)
if err != nil {
// If there is an error, hold on to it but proceed with all the remaining
// groupVersionResources.
@@ -553,19 +560,20 @@ func (d *namespacedResourcesDeleter) deleteAllContent(ns *v1.Namespace) (int64,
}
// if len(errs)==0, NewAggregate returns nil.
klog.V(4).Infof("namespace controller - deleteAllContent - namespace: %s, estimate: %v, errors: %v", namespace, estimate, utilerrors.NewAggregate(errs))
return estimate, utilerrors.NewAggregate(errs)
err = utilerrors.NewAggregate(errs)
logger.V(4).Info("namespace controller - deleteAllContent", "namespace", namespace, "estimate", estimate, "err", err)
return estimate, err
}
// estimateGracefulTermination will estimate the graceful termination required for the specific entity in the namespace
func (d *namespacedResourcesDeleter) estimateGracefulTermination(gvr schema.GroupVersionResource, ns string, namespaceDeletedAt metav1.Time) (int64, error) {
func (d *namespacedResourcesDeleter) estimateGracefulTermination(ctx context.Context, gvr schema.GroupVersionResource, ns string, namespaceDeletedAt metav1.Time) (int64, error) {
groupResource := gvr.GroupResource()
klog.V(5).Infof("namespace controller - estimateGracefulTermination - group %s, resource: %s", groupResource.Group, groupResource.Resource)
klog.FromContext(ctx).V(5).Info("Namespace controller - estimateGracefulTermination", "group", groupResource.Group, "resource", groupResource.Resource)
estimate := int64(0)
var err error
switch groupResource {
case schema.GroupResource{Group: "", Resource: "pods"}:
estimate, err = d.estimateGracefulTerminationForPods(ns)
estimate, err = d.estimateGracefulTerminationForPods(ctx, ns)
}
if err != nil {
return 0, err
@@ -580,8 +588,8 @@ func (d *namespacedResourcesDeleter) estimateGracefulTermination(gvr schema.Grou
}
// estimateGracefulTerminationForPods determines the graceful termination period for pods in the namespace
func (d *namespacedResourcesDeleter) estimateGracefulTerminationForPods(ns string) (int64, error) {
klog.V(5).Infof("namespace controller - estimateGracefulTerminationForPods - namespace %s", ns)
func (d *namespacedResourcesDeleter) estimateGracefulTerminationForPods(ctx context.Context, ns string) (int64, error) {
klog.FromContext(ctx).V(5).Info("Namespace controller - estimateGracefulTerminationForPods", "namespace", ns)
estimate := int64(0)
podsGetter := d.podsGetter
if podsGetter == nil || reflect.ValueOf(podsGetter).IsNil() {