// NewRESTClient creates a new RESTClient. This client performs generic REST functions // such as Get, Put, Post, and Delete on specified paths. Codec controls encoding and // decoding of responses from the server. func NewRESTClient(baseURL *url.URL, versionedAPIPath string, config ContentConfig, maxQPS float32, maxBurst int, rateLimiter flowcontrol.RateLimiter, client *http.Client) (*RESTClient, error) { base := *baseURL if !strings.HasSuffix(base.Path, "/") { base.Path += "/" } base.RawQuery = "" base.Fragment = "" if config.GroupVersion == nil { config.GroupVersion = &unversioned.GroupVersion{} } if len(config.ContentType) == 0 { config.ContentType = "application/json" } serializers, err := createSerializers(config) if err != nil { return nil, err } var throttle flowcontrol.RateLimiter if maxQPS > 0 && rateLimiter == nil { throttle = flowcontrol.NewTokenBucketRateLimiter(maxQPS, maxBurst) } else if rateLimiter != nil { throttle = rateLimiter } return &RESTClient{ base: &base, versionedAPIPath: versionedAPIPath, contentConfig: config, serializers: *serializers, createBackoffMgr: readExpBackoffConfig, Throttle: throttle, Client: client, }, nil }
// SwapLimiter safely swaps current limiter for this queue with the passed one if capacities or qps's differ. func (q *RateLimitedTimedQueue) SwapLimiter(newQPS float32) { q.limiterLock.Lock() defer q.limiterLock.Unlock() if q.limiter.QPS() == newQPS { return } var newLimiter flowcontrol.RateLimiter if newQPS <= 0 { newLimiter = flowcontrol.NewFakeNeverRateLimiter() } else { newLimiter = flowcontrol.NewTokenBucketRateLimiter(newQPS, evictionRateLimiterBurst) } // If we're currently waiting on limiter, we drain the new one - this is a good approach when Burst value is 1 // TODO: figure out if we need to support higher Burst values and decide on the drain logic, should we keep: // - saturation (percentage of used tokens) // - number of used tokens // - number of available tokens // - something else for q.limiter.Saturation() > newLimiter.Saturation() { // Check if we're not using fake limiter previousSaturation := newLimiter.Saturation() newLimiter.TryAccept() // It's a fake limiter if newLimiter.Saturation() == previousSaturation { break } } q.limiter.Stop() q.limiter = newLimiter }
// NewForConfig creates a new Clientset for the given config. func NewForConfig(c *restclient.Config) (*Clientset, error) { configShallowCopy := *c if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) } var cs Clientset var err error cs.CoreV1Client, err = v1core.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.BatchV1Client, err = v1batch.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.ExtensionsV1beta1Client, err = v1beta1extensions.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.FederationV1beta1Client, err = v1beta1federation.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil }
// NewForConfig creates a new Clientset for the given config. func NewForConfig(c *rest.Config) (*Clientset, error) { configShallowCopy := *c if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) } var clientset Clientset var err error clientset.CoreClient, err = v1core.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.AppsClient, err = v1alpha1apps.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.AuthenticationClient, err = v1beta1authentication.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.AuthorizationClient, err = v1beta1authorization.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.AutoscalingClient, err = v1autoscaling.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.BatchClient, err = v1batch.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.CertificatesClient, err = v1alpha1certificates.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.ExtensionsClient, err = v1beta1extensions.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.PolicyClient, err = v1alpha1policy.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.RbacClient, err = v1alpha1rbac.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.StorageClient, err = v1beta1storage.NewForConfig(&configShallowCopy) if err != nil { return nil, err } clientset.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &clientset, nil }
// NewForConfig creates a new Clientset for the given config. func NewForConfig(c *restclient.Config) (*Clientset, error) { configShallowCopy := *c if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) } var cs Clientset var err error cs.CoreClient, err = internalversioncore.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.AppsClient, err = internalversionapps.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.AuthenticationClient, err = internalversionauthentication.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.AuthorizationClient, err = internalversionauthorization.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.AutoscalingClient, err = internalversionautoscaling.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.BatchClient, err = internalversionbatch.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.CertificatesClient, err = internalversioncertificates.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.ExtensionsClient, err = internalversionextensions.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.PolicyClient, err = internalversionpolicy.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.RbacClient, err = internalversionrbac.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.StorageClient, err = internalversionstorage.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil }
// throttleImagePulling wraps kubecontainer.ImageService to throttle image // pulling based on the given QPS and burst limits. If QPS is zero, defaults // to no throttling. func throttleImagePulling(imageService kubecontainer.ImageService, qps float32, burst int) kubecontainer.ImageService { if qps == 0.0 { return imageService } return &throttledImageService{ ImageService: imageService, limiter: flowcontrol.NewTokenBucketRateLimiter(qps, burst), } }
func NewAltTokenSource(tokenURL, tokenBody string) oauth2.TokenSource { client := oauth2.NewClient(oauth2.NoContext, google.ComputeTokenSource("")) a := &AltTokenSource{ oauthClient: client, tokenURL: tokenURL, tokenBody: tokenBody, throttle: flowcontrol.NewTokenBucketRateLimiter(tokenURLQPS, tokenURLBurst), } return oauth2.ReuseTokenSource(nil, a) }
func ClientSetRateLimiterTest(t *testing.T) { rateLimiter := flowcontrol.NewTokenBucketRateLimiter(1.0, 10) config := restclient.Config{ RateLimiter: rateLimiter, } if err := restclient.SetKubernetesDefaults(&config); err != nil { t.Errorf("setting defaults failed for %#v: %v", config, err) } clientSet, err := NewForConfig(&config) if err != nil { t.Errorf("creating clientset for config %v failed: %v", config, err) } testGroupThrottler := clientSet.Testgroup().RESTClient().GetRateLimiter() if rateLimiter != testGroupThrottler { t.Errorf("Clients in client set should use rateLimiter passed in config:\noriginal: %v\ntestGroup: %v", rateLimiter, testGroupThrottler) } }
// NewForConfig creates a new Clientset for the given config. func NewForConfig(c *restclient.Config) (*Clientset, error) { configShallowCopy := *c if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) } var cs Clientset var err error cs.ApiregistrationV1alpha1Client, err = v1alpha1apiregistration.NewForConfig(&configShallowCopy) if err != nil { return nil, err } cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { glog.Errorf("failed to create the DiscoveryClient: %v", err) return nil, err } return &cs, nil }
// monitorNodeStatus verifies node status are constantly updated by kubelet, and if not, // post "NodeReady==ConditionUnknown". It also evicts all pods if node is not ready or // not reachable for a long period of time. func (nc *NodeController) monitorNodeStatus() error { // We are listing nodes from local cache as we can tolerate some small delays // comparing to state from etcd and there is eventual consistency anyway. nodes, err := nc.nodeStore.List() if err != nil { return err } added, deleted := nc.checkForNodeAddedDeleted(&nodes) for i := range added { glog.V(1).Infof("NodeController observed a new Node: %#v", added[i].Name) recordNodeEvent(nc.recorder, added[i].Name, string(added[i].UID), v1.EventTypeNormal, "RegisteredNode", fmt.Sprintf("Registered Node %v in NodeController", added[i].Name)) nc.knownNodeSet[added[i].Name] = added[i] // When adding new Nodes we need to check if new zone appeared, and if so add new evictor. zone := utilnode.GetZoneKey(added[i]) if _, found := nc.zonePodEvictor[zone]; !found { nc.zonePodEvictor[zone] = NewRateLimitedTimedQueue( flowcontrol.NewTokenBucketRateLimiter(nc.evictionLimiterQPS, evictionRateLimiterBurst)) // Init the metric for the new zone. glog.Infof("Initializing eviction metric for zone: %v", zone) EvictionsNumber.WithLabelValues(zone).Add(0) } nc.cancelPodEviction(added[i]) } for i := range deleted { glog.V(1).Infof("NodeController observed a Node deletion: %v", deleted[i].Name) recordNodeEvent(nc.recorder, deleted[i].Name, string(deleted[i].UID), v1.EventTypeNormal, "RemovingNode", fmt.Sprintf("Removing Node %v from NodeController", deleted[i].Name)) delete(nc.knownNodeSet, deleted[i].Name) } zoneToNodeConditions := map[string][]*v1.NodeCondition{} for i := range nodes.Items { var gracePeriod time.Duration var observedReadyCondition v1.NodeCondition var currentReadyCondition *v1.NodeCondition nodeCopy, err := api.Scheme.DeepCopy(&nodes.Items[i]) if err != nil { utilruntime.HandleError(err) continue } node := nodeCopy.(*v1.Node) if err := wait.PollImmediate(retrySleepTime, retrySleepTime*nodeStatusUpdateRetry, func() (bool, error) { gracePeriod, observedReadyCondition, currentReadyCondition, err = nc.tryUpdateNodeStatus(node) if err == nil { return true, nil } name := node.Name node, err = nc.kubeClient.Core().Nodes().Get(name, metav1.GetOptions{}) if err != nil { glog.Errorf("Failed while getting a Node to retry updating NodeStatus. Probably Node %s was deleted.", name) return false, err } return false, nil }); err != nil { glog.Errorf("Update status of Node %v from NodeController error : %v. "+ "Skipping - no pods will be evicted.", node.Name, err) continue } // We do not treat a master node as a part of the cluster for network disruption checking. if !system.IsMasterNode(node.Name) { zoneToNodeConditions[utilnode.GetZoneKey(node)] = append(zoneToNodeConditions[utilnode.GetZoneKey(node)], currentReadyCondition) } decisionTimestamp := nc.now() if currentReadyCondition != nil { // Check eviction timeout against decisionTimestamp if observedReadyCondition.Status == v1.ConditionFalse && decisionTimestamp.After(nc.nodeStatusMap[node.Name].readyTransitionTimestamp.Add(nc.podEvictionTimeout)) { if nc.evictPods(node) { glog.V(2).Infof("Evicting pods on node %s: %v is later than %v + %v", node.Name, decisionTimestamp, nc.nodeStatusMap[node.Name].readyTransitionTimestamp, nc.podEvictionTimeout) } } if observedReadyCondition.Status == v1.ConditionUnknown && decisionTimestamp.After(nc.nodeStatusMap[node.Name].probeTimestamp.Add(nc.podEvictionTimeout)) { if nc.evictPods(node) { glog.V(2).Infof("Evicting pods on node %s: %v is later than %v + %v", node.Name, decisionTimestamp, nc.nodeStatusMap[node.Name].readyTransitionTimestamp, nc.podEvictionTimeout-gracePeriod) } } if observedReadyCondition.Status == v1.ConditionTrue { if nc.cancelPodEviction(node) { glog.V(2).Infof("Node %s is ready again, cancelled pod eviction", node.Name) } } // Report node event. if currentReadyCondition.Status != v1.ConditionTrue && observedReadyCondition.Status == v1.ConditionTrue { recordNodeStatusChange(nc.recorder, node, "NodeNotReady") if err = markAllPodsNotReady(nc.kubeClient, node); err != nil { utilruntime.HandleError(fmt.Errorf("Unable to mark all pods NotReady on node %v: %v", node.Name, err)) } } // Check with the cloud provider to see if the node still exists. If it // doesn't, delete the node immediately. if currentReadyCondition.Status != v1.ConditionTrue && nc.cloud != nil { exists, err := nc.nodeExistsInCloudProvider(types.NodeName(node.Name)) if err != nil { glog.Errorf("Error determining if node %v exists in cloud: %v", node.Name, err) continue } if !exists { glog.V(2).Infof("Deleting node (no longer present in cloud provider): %s", node.Name) recordNodeEvent(nc.recorder, node.Name, string(node.UID), v1.EventTypeNormal, "DeletingNode", fmt.Sprintf("Deleting Node %v because it's not present according to cloud provider", node.Name)) go func(nodeName string) { defer utilruntime.HandleCrash() // Kubelet is not reporting and Cloud Provider says node // is gone. Delete it without worrying about grace // periods. if err := forcefullyDeleteNode(nc.kubeClient, nodeName); err != nil { glog.Errorf("Unable to forcefully delete node %q: %v", nodeName, err) } }(node.Name) } } } } nc.handleDisruption(zoneToNodeConditions, &nodes) return nil }