Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scale from and to 0 support for autoscaler for VPC cluster #1523

Merged
merged 3 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions api/v1beta1/ibmvpc_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ func Convert_v1beta2_IBMVPCMachineSpec_To_v1beta1_IBMVPCMachineSpec(in *infrav1b
return autoConvert_v1beta2_IBMVPCMachineSpec_To_v1beta1_IBMVPCMachineSpec(in, out, s)
}

func Convert_v1beta2_IBMVPCMachineTemplateStatus_To_v1beta1_IBMVPCMachineTemplateStatus(in *infrav1beta2.IBMVPCMachineTemplateStatus, out *IBMVPCMachineTemplateStatus, s apiconversion.Scope) error {
return autoConvert_v1beta2_IBMVPCMachineTemplateStatus_To_v1beta1_IBMVPCMachineTemplateStatus(in, out, s)
}

func Convert_Slice_Pointer_string_To_Slice_Pointer_v1beta2_IBMVPCResourceReference(in *[]*string, out *[]*infrav1beta2.IBMVPCResourceReference, _ apiconversion.Scope) error {
for _, sshKey := range *in {
*out = append(*out, &infrav1beta2.IBMVPCResourceReference{
Expand Down
9 changes: 8 additions & 1 deletion api/v1beta1/ibmvpcmachinetemplate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ type IBMVPCMachineTemplateResource struct {
Spec IBMVPCMachineSpec `json:"spec"`
}

// IBMVPCMachineTemplateStatus defines the observed state of IBMVPCMachineTemplate.
type IBMVPCMachineTemplateStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}

// +kubebuilder:object:root=true
KeerthanaAP marked this conversation as resolved.
Show resolved Hide resolved
// +kubebuilder:resource:path=ibmvpcmachinetemplates,scope=Namespaced,categories=cluster-api

Expand All @@ -39,7 +45,8 @@ type IBMVPCMachineTemplate struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec IBMVPCMachineTemplateSpec `json:"spec,omitempty"`
Spec IBMVPCMachineTemplateSpec `json:"spec,omitempty"`
Status IBMVPCMachineTemplateStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
30 changes: 30 additions & 0 deletions api/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion api/v1beta2/ibmvpcmachinetemplate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package v1beta2

import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -31,6 +32,16 @@ type IBMVPCMachineTemplateResource struct {
Spec IBMVPCMachineSpec `json:"spec"`
}

// IBMVPCMachineTemplateStatus defines the observed state of IBMVPCMachineTemplate.
type IBMVPCMachineTemplateStatus struct {
// Capacity defines the resource capacity for this machine.
// This value is used for autoscaling from zero operations as defined in:
// https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210310-opt-in-autoscaling-from-zero.md
// +optional
Capacity corev1.ResourceList `json:"capacity,omitempty"`
}

//+kubebuilder:subresource:status
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=ibmvpcmachinetemplates,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion
Expand All @@ -40,7 +51,8 @@ type IBMVPCMachineTemplate struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec IBMVPCMachineTemplateSpec `json:"spec,omitempty"`
Spec IBMVPCMachineTemplateSpec `json:"spec,omitempty"`
Status IBMVPCMachineTemplateStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
23 changes: 23 additions & 0 deletions api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ spec:
required:
- template
type: object
status:
description: IBMVPCMachineTemplateStatus defines the observed state of
IBMVPCMachineTemplate.
type: object
type: object
served: true
storage: false
Expand Down Expand Up @@ -296,6 +300,24 @@ spec:
required:
- template
type: object
status:
description: IBMVPCMachineTemplateStatus defines the observed state of
IBMVPCMachineTemplate.
properties:
capacity:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Capacity defines the resource capacity for this machine.
This value is used for autoscaling from zero operations as defined
in: https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210310-opt-in-autoscaling-from-zero.md'
type: object
type: object
type: object
served: true
storage: true
subresources:
status: {}
16 changes: 16 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,19 @@ rules:
- get
- patch
- update
- apiGroups:
- infrastructure.cluster.x-k8s.io
resources:
- ibmvpcmachinetemplates
verbs:
- get
- list
- watch
- apiGroups:
- infrastructure.cluster.x-k8s.io
resources:
- ibmvpcmachinetemplates/status
verbs:
- get
- patch
- update
118 changes: 118 additions & 0 deletions controllers/ibmvpcmachinetemplate_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
Copyright 2023 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package controllers

import (
"context"
"fmt"
"reflect"

"github.com/IBM/vpc-go-sdk/vpcv1"

corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"

ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

"sigs.k8s.io/cluster-api/util/patch"

infrav1beta2 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2"
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/vpc"
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/endpoints"
)

// IBMVPCMachineTemplateReconciler reconciles a IBMVPCMachineTemplate object.
type IBMVPCMachineTemplateReconciler struct {
client.Client
Scheme *runtime.Scheme
ServiceEndpoint []endpoints.ServiceEndpoint
}

func (r *IBMVPCMachineTemplateReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&infrav1beta2.IBMVPCMachineTemplate{}).
Complete(r)
}

// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=ibmvpcmachinetemplates,verbs=get;list;watch
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=ibmvpcmachinetemplates/status,verbs=get;update;patch

func (r *IBMVPCMachineTemplateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := ctrl.LoggerFrom(ctx)
log.Info("Reconciling IBMVPCMachineTemplate")

var machineTemplate infrav1beta2.IBMVPCMachineTemplate
if err := r.Get(ctx, req.NamespacedName, &machineTemplate); err != nil {
log.Error(err, "Unable to fetch ibmvpcmachinetemplate")
return ctrl.Result{}, client.IgnoreNotFound(err)
}

region := endpoints.CostructRegionFromZone(machineTemplate.Spec.Template.Spec.Zone)

// Fetch the service endpoint.
svcEndpoint := endpoints.FetchVPCEndpoint(region, r.ServiceEndpoint)

vpcClient, err := vpc.NewService(svcEndpoint)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to create IBM VPC client: %w", err)
}

return r.reconcileNormal(ctx, vpcClient, machineTemplate)
}

func (r *IBMVPCMachineTemplateReconciler) reconcileNormal(ctx context.Context, vpcClient vpc.Vpc, machineTemplate infrav1beta2.IBMVPCMachineTemplate) (ctrl.Result, error) {
log := ctrl.LoggerFrom(ctx)
helper, err := patch.NewHelper(&machineTemplate, r.Client)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to init patch helper: %w", err)
}

options := &vpcv1.GetInstanceProfileOptions{}
options.SetName(machineTemplate.Spec.Template.Spec.Profile)
profileDetails, _, err := vpcClient.GetInstanceProfile(options)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to fetch profile Details: %w", err)
}

if profileDetails == nil {
KeerthanaAP marked this conversation as resolved.
Show resolved Hide resolved
return ctrl.Result{}, fmt.Errorf("failed to find profileDetails")
}

log.V(3).Info("Profile Details:", "profileDetails", profileDetails)

capacity := make(corev1.ResourceList)
memory := fmt.Sprintf("%vG", *profileDetails.Memory.(*vpcv1.InstanceProfileMemory).Value)
cpu := fmt.Sprintf("%v", *profileDetails.VcpuCount.(*vpcv1.InstanceProfileVcpu).Value)
capacity[corev1.ResourceCPU] = resource.MustParse(cpu)
capacity[corev1.ResourceMemory] = resource.MustParse(memory)

log.V(3).Info("Calculated capacity for machine template", "capacity", capacity)
if !reflect.DeepEqual(machineTemplate.Status.Capacity, capacity) {
machineTemplate.Status.Capacity = capacity
if err := helper.Patch(ctx, &machineTemplate); err != nil {
if !apierrors.IsNotFound(err) {
log.Error(err, "Failed to patch machineTemplate")
return ctrl.Result{}, err
}
}
}
log.V(3).Info("Machine template status", "status", machineTemplate.Status)
return ctrl.Result{}, nil
}
Loading