diff --git a/cluster-autoscaler/cloudprovider/azure/OWNERS b/cluster-autoscaler/cloudprovider/azure/OWNERS index 17a63885d5c1..002bf520d5e0 100644 --- a/cluster-autoscaler/cloudprovider/azure/OWNERS +++ b/cluster-autoscaler/cloudprovider/azure/OWNERS @@ -3,12 +3,14 @@ approvers: - nilo19 - tallaxes - bryce-soghigian +- comtalyst - jackfrancis reviewers: - feiskyer - nilo19 - tallaxes -- bryce-soghigian +- bryce-soghigian +- comtalyst - jackfrancis emeritus_approvers: - marwanad diff --git a/cluster-autoscaler/cloudprovider/cloud_provider.go b/cluster-autoscaler/cloudprovider/cloud_provider.go index 4b858bedd955..33719ac63f31 100644 --- a/cluster-autoscaler/cloudprovider/cloud_provider.go +++ b/cluster-autoscaler/cloudprovider/cloud_provider.go @@ -183,14 +183,11 @@ type NodeGroup interface { IncreaseSize(delta int) error // AtomicIncreaseSize tries to increase the size of the node group atomically. - // - If the method returns nil, it guarantees that delta instances will be added to the node group - // within its MaxNodeProvisionTime. The function should wait until node group size is updated. - // The cloud provider is responsible for tracking and ensuring successful scale up asynchronously. - // - If the method returns an error, it guarantees that no new instances will be added to the node group - // as a result of this call. The cloud provider is responsible for ensuring that before returning from the method. - // Implementation is optional. If implemented, CA will take advantage of the method while scaling up - // GenericScaleUp ProvisioningClass, guaranteeing that all instances required for such a ProvisioningRequest - // are provisioned atomically. + // It returns error if requesting the entire delta fails. The method doesn't wait until the new instances appear. + // Implementation is optional. Implementation of this method generally requires external cloud provider support + // for atomically requesting multiple instances. If implemented, CA will take advantage of the method while scaling up + // BestEffortAtomicScaleUp ProvisioningClass, guaranteeing that all instances required for such a + // ProvisioningRequest are provisioned atomically. AtomicIncreaseSize(delta int) error // DeleteNodes deletes nodes from this node group. Error is returned either on diff --git a/cluster-autoscaler/cloudprovider/oci/instancepools/oci_cloud_provider.go b/cluster-autoscaler/cloudprovider/oci/instancepools/oci_cloud_provider.go index bb8ec2f2cab4..dfcc1728f7f2 100644 --- a/cluster-autoscaler/cloudprovider/oci/instancepools/oci_cloud_provider.go +++ b/cluster-autoscaler/cloudprovider/oci/instancepools/oci_cloud_provider.go @@ -5,6 +5,8 @@ Copyright 2021-2023 Oracle and/or its affiliates. package instancepools import ( + "strings" + "github.com/pkg/errors" apiv1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -19,7 +21,6 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/klog/v2" - "strings" ) // OciCloudProvider implements the CloudProvider interface for OCI. It contains an @@ -66,8 +67,25 @@ func (ocp *OciCloudProvider) NodeGroupForNode(n *apiv1.Node) (cloudprovider.Node } // HasInstance returns whether a given node has a corresponding instance in this cloud provider -func (ocp *OciCloudProvider) HasInstance(n *apiv1.Node) (bool, error) { - return true, cloudprovider.ErrNotImplemented +func (ocp *OciCloudProvider) HasInstance(node *apiv1.Node) (bool, error) { + instance, err := ocicommon.NodeToOciRef(node) + if err != nil { + return false, err + } + instancePool, err := ocp.poolManager.GetInstancePoolForInstance(instance) + if err != nil { + return false, err + } + instances, err := ocp.poolManager.GetInstancePoolNodes(*instancePool) + if err != nil { + return false, err + } + for _, i := range instances { + if i.Id == instance.InstanceID { + return true, nil + } + } + return false, nil } // Pricing returns pricing model for this cloud provider or error if not available. diff --git a/cluster-autoscaler/cloudprovider/oci/nodepools/oci_cloud_provider.go b/cluster-autoscaler/cloudprovider/oci/nodepools/oci_cloud_provider.go index abe69e432b49..b97f98fc6179 100644 --- a/cluster-autoscaler/cloudprovider/oci/nodepools/oci_cloud_provider.go +++ b/cluster-autoscaler/cloudprovider/oci/nodepools/oci_cloud_provider.go @@ -70,8 +70,25 @@ func (ocp *OciCloudProvider) GetNodeGpuConfig(node *apiv1.Node) *cloudprovider.G } // HasInstance returns whether a given node has a corresponding instance in this cloud provider -func (ocp *OciCloudProvider) HasInstance(n *apiv1.Node) (bool, error) { - return true, cloudprovider.ErrNotImplemented +func (ocp *OciCloudProvider) HasInstance(node *apiv1.Node) (bool, error) { + instance, err := ocicommon.NodeToOciRef(node) + if err != nil { + return true, err + } + np, err := ocp.manager.GetNodePoolForInstance(instance) + if err != nil { + return true, err + } + nodes, err := ocp.manager.GetNodePoolNodes(np) + if err != nil { + return true, err + } + for _, n := range nodes { + if n.Id == instance.InstanceID { + return true, nil + } + } + return false, nil } // Pricing returns pricing model for this cloud provider or error if not available. diff --git a/vertical-pod-autoscaler/OWNERS b/vertical-pod-autoscaler/OWNERS index 33390354e829..7d0f6b25cea5 100644 --- a/vertical-pod-autoscaler/OWNERS +++ b/vertical-pod-autoscaler/OWNERS @@ -10,6 +10,7 @@ reviewers: - jbartosik - krzysied - voelzmo +- raywainman emeritus_approvers: - schylek # 2022-09-30 labels: diff --git a/vertical-pod-autoscaler/README.md b/vertical-pod-autoscaler/README.md index efa7e4c23597..726023e22dd3 100644 --- a/vertical-pod-autoscaler/README.md +++ b/vertical-pod-autoscaler/README.md @@ -51,12 +51,13 @@ procedure described below. # Installation -The current default version is Vertical Pod Autoscaler 1.1.2 +The current default version is Vertical Pod Autoscaler 1.2.0 ### Compatibility | VPA version | Kubernetes version | |-----------------|--------------------| +| 1.2.0 | 1.27+ | | 1.1.2 | 1.25+ | | 1.1.1 | 1.25+ | | 1.0 | 1.25+ | diff --git a/vertical-pod-autoscaler/RELEASE.md b/vertical-pod-autoscaler/RELEASE.md index 72a19b9a288b..4551a946251c 100644 --- a/vertical-pod-autoscaler/RELEASE.md +++ b/vertical-pod-autoscaler/RELEASE.md @@ -121,14 +121,17 @@ other pattern start only with `vertical-pod-autoscaler/v0.9.0` so we should make sure nothing we care about will break if we do. 1. [ ] Update information about newest version and K8s compatibility in - [the installation section of README](https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/README.md#installation) - and the yaml files: + [the installation section of README](https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/README.md#installation). + +1. [ ] Update the yaml files: ```sh sed -i -s "s|[0-9]\+\.[0-9]\+\.[0-9]\+|[*vpa-version*]|" ./deploy/*-deployment*.yaml ./hack/vpa-process-yaml.sh ``` - Merge this change into branch vpa-release-1.{$minor} and optionally into master if 1.{$minor} is the latest minor release (example - PR: [#5460](https://github.com/kubernetes/autoscaler/pull/5460)). +1. [ ] Update the default tag in [vpa-up.sh](https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/hack/vpa-up.sh). + +1. [ ] Merge these changes into branch vpa-release-1.{$minor} and optionally into master if 1.{$minor} is the latest minor release + (example PR: [#5460](https://github.com/kubernetes/autoscaler/pull/5460)). 1. [ ] Tag the commit with version const change diff --git a/vertical-pod-autoscaler/pkg/recommender/input/cluster_feeder.go b/vertical-pod-autoscaler/pkg/recommender/input/cluster_feeder.go index cf1fff4b2dcb..a30140fbe922 100644 --- a/vertical-pod-autoscaler/pkg/recommender/input/cluster_feeder.go +++ b/vertical-pod-autoscaler/pkg/recommender/input/cluster_feeder.go @@ -233,13 +233,13 @@ func (feeder *clusterStateFeeder) setVpaCheckpoint(checkpoint *vpa_types.Vertica vpaID := model.VpaID{Namespace: checkpoint.Namespace, VpaName: checkpoint.Spec.VPAObjectName} vpa, exists := feeder.clusterState.Vpas[vpaID] if !exists { - return fmt.Errorf("cannot load checkpoint to missing VPA object %s/%s", vpa.ID.Namespace, vpa.ID.VpaName) + return fmt.Errorf("cannot load checkpoint to missing VPA object %s/%s", vpaID.Namespace, vpaID.VpaName) } cs := model.NewAggregateContainerState() err := cs.LoadFromCheckpoint(&checkpoint.Status) if err != nil { - return fmt.Errorf("cannot load checkpoint for VPA %s/%s. Reason: %v", vpa.ID.Namespace, vpa.ID.VpaName, err) + return fmt.Errorf("cannot load checkpoint for VPA %s/%s. Reason: %v", vpaID.Namespace, vpaID.VpaName, err) } vpa.ContainersInitialAggregateState[checkpoint.Spec.ContainerName] = cs return nil @@ -338,7 +338,7 @@ func filterVPAs(feeder *clusterStateFeeder, allVpaCRDs []*vpa_types.VerticalPodA } if slices.Contains(feeder.ignoredNamespaces, vpaCRD.ObjectMeta.Namespace) { - klog.V(6).Infof("Ignoring vpaCRD %s in namespace %s as namespace is ignored", vpaCRD.Name, vpaCRD.Namespace) + klog.V(6).Infof("Ignoring vpaCRD %s in namespace %s as namespace is ignored", klog.KObj(vpaCRD), vpaCRD.Namespace) continue }