k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/registry/scheduling/rest/storage_scheduling.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package rest 18 19 import ( 20 "context" 21 "fmt" 22 "time" 23 24 "k8s.io/klog/v2" 25 26 apierrors "k8s.io/apimachinery/pkg/api/errors" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 utilruntime "k8s.io/apimachinery/pkg/util/runtime" 29 "k8s.io/apimachinery/pkg/util/wait" 30 "k8s.io/apiserver/pkg/registry/generic" 31 "k8s.io/apiserver/pkg/registry/rest" 32 genericapiserver "k8s.io/apiserver/pkg/server" 33 serverstorage "k8s.io/apiserver/pkg/server/storage" 34 schedulingclient "k8s.io/client-go/kubernetes/typed/scheduling/v1" 35 "k8s.io/kubernetes/pkg/api/legacyscheme" 36 "k8s.io/kubernetes/pkg/apis/scheduling" 37 schedulingapiv1 "k8s.io/kubernetes/pkg/apis/scheduling/v1" 38 priorityclassstore "k8s.io/kubernetes/pkg/registry/scheduling/priorityclass/storage" 39 ) 40 41 const PostStartHookName = "scheduling/bootstrap-system-priority-classes" 42 43 type RESTStorageProvider struct{} 44 45 var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{} 46 47 func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { 48 apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(scheduling.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) 49 50 if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { 51 return genericapiserver.APIGroupInfo{}, err 52 } else if len(storageMap) > 0 { 53 apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1.SchemeGroupVersion.Version] = storageMap 54 } 55 56 return apiGroupInfo, nil 57 } 58 59 func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { 60 storage := map[string]rest.Storage{} 61 62 // priorityclasses 63 if resource := "priorityclasses"; apiResourceConfigSource.ResourceEnabled(schedulingapiv1.SchemeGroupVersion.WithResource(resource)) { 64 if priorityClassStorage, err := priorityclassstore.NewREST(restOptionsGetter); err != nil { 65 return nil, err 66 } else { 67 storage[resource] = priorityClassStorage 68 } 69 } 70 71 return storage, nil 72 } 73 74 func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStartHookFunc, error) { 75 return PostStartHookName, AddSystemPriorityClasses(), nil 76 } 77 78 func AddSystemPriorityClasses() genericapiserver.PostStartHookFunc { 79 return func(hookContext genericapiserver.PostStartHookContext) error { 80 // Adding system priority classes is important. If they fail to add, many critical system 81 // components may fail and cluster may break. 82 err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) { 83 schedClientSet, err := schedulingclient.NewForConfig(hookContext.LoopbackClientConfig) 84 if err != nil { 85 utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err)) 86 return false, nil 87 } 88 89 for _, pc := range schedulingapiv1.SystemPriorityClasses() { 90 _, err := schedClientSet.PriorityClasses().Get(context.TODO(), pc.Name, metav1.GetOptions{}) 91 if err != nil { 92 if apierrors.IsNotFound(err) { 93 _, err := schedClientSet.PriorityClasses().Create(context.TODO(), pc, metav1.CreateOptions{}) 94 if err == nil || apierrors.IsAlreadyExists(err) { 95 klog.Infof("created PriorityClass %s with value %v", pc.Name, pc.Value) 96 continue 97 } 98 // ServiceUnavailble error is returned when the API server is blocked by storage version updates 99 if apierrors.IsServiceUnavailable(err) { 100 klog.Infof("going to retry, unable to create PriorityClass %s: %v", pc.Name, err) 101 return false, nil 102 } 103 return false, err 104 } else { 105 // Unable to get the priority class for reasons other than "not found". 106 klog.Warningf("unable to get PriorityClass %v: %v. Retrying...", pc.Name, err) 107 return false, nil 108 } 109 } 110 } 111 klog.Infof("all system priority classes are created successfully or already exist.") 112 return true, nil 113 }) 114 // if we're never able to make it through initialization, kill the API server. 115 if err != nil { 116 return fmt.Errorf("unable to add default system priority classes: %v", err) 117 } 118 return nil 119 } 120 } 121 122 func (p RESTStorageProvider) GroupName() string { 123 return scheduling.GroupName 124 }