github.com/argoproj-labs/argocd-operator@v0.10.0/controllers/argocd/hpa.go (about) 1 // Copyright 2019 ArgoCD Operator Developers 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package argocd 16 17 import ( 18 "context" 19 "reflect" 20 21 autoscaling "k8s.io/api/autoscaling/v1" 22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 24 argoproj "github.com/argoproj-labs/argocd-operator/api/v1beta1" 25 "github.com/argoproj-labs/argocd-operator/common" 26 "github.com/argoproj-labs/argocd-operator/controllers/argoutil" 27 ) 28 29 var ( 30 maxReplicas int32 = 3 31 minReplicas int32 = 1 32 tcup int32 = 50 33 ) 34 35 func newHorizontalPodAutoscaler(cr *argoproj.ArgoCD) *autoscaling.HorizontalPodAutoscaler { 36 return &autoscaling.HorizontalPodAutoscaler{ 37 ObjectMeta: metav1.ObjectMeta{ 38 Name: cr.Name, 39 Namespace: cr.Namespace, 40 Labels: argoutil.LabelsForCluster(cr), 41 }, 42 } 43 } 44 45 func newHorizontalPodAutoscalerWithName(name string, cr *argoproj.ArgoCD) *autoscaling.HorizontalPodAutoscaler { 46 hpa := newHorizontalPodAutoscaler(cr) 47 hpa.ObjectMeta.Name = name 48 49 lbls := hpa.ObjectMeta.Labels 50 lbls[common.ArgoCDKeyName] = name 51 hpa.ObjectMeta.Labels = lbls 52 53 return hpa 54 } 55 56 func newHorizontalPodAutoscalerWithSuffix(suffix string, cr *argoproj.ArgoCD) *autoscaling.HorizontalPodAutoscaler { 57 return newHorizontalPodAutoscalerWithName(nameWithSuffix(suffix, cr), cr) 58 } 59 60 // reconcileServerHPA will ensure that the HorizontalPodAutoscaler is present for the Argo CD Server component, and reconcile any detected changes. 61 func (r *ReconcileArgoCD) reconcileServerHPA(cr *argoproj.ArgoCD) error { 62 63 defaultHPA := newHorizontalPodAutoscalerWithSuffix("server", cr) 64 defaultHPA.Spec = autoscaling.HorizontalPodAutoscalerSpec{ 65 MaxReplicas: maxReplicas, 66 MinReplicas: &minReplicas, 67 TargetCPUUtilizationPercentage: &tcup, 68 ScaleTargetRef: autoscaling.CrossVersionObjectReference{ 69 APIVersion: "apps/v1", 70 Kind: "Deployment", 71 Name: nameWithSuffix("server", cr), 72 }, 73 } 74 75 existingHPA := newHorizontalPodAutoscalerWithSuffix("server", cr) 76 if argoutil.IsObjectFound(r.Client, cr.Namespace, existingHPA.Name, existingHPA) { 77 if !cr.Spec.Server.Autoscale.Enabled { 78 return r.Client.Delete(context.TODO(), existingHPA) // HorizontalPodAutoscaler found but globally disabled, delete it. 79 } 80 81 changed := false 82 // HorizontalPodAutoscaler found, reconcile if necessary changes detected 83 if cr.Spec.Server.Autoscale.HPA != nil { 84 if !reflect.DeepEqual(existingHPA.Spec, cr.Spec.Server.Autoscale.HPA) { 85 existingHPA.Spec = *cr.Spec.Server.Autoscale.HPA 86 changed = true 87 } 88 } 89 90 if changed { 91 return r.Client.Update(context.TODO(), existingHPA) 92 } 93 94 // HorizontalPodAutoscaler found, no changes detected 95 return nil 96 } 97 98 if !cr.Spec.Server.Autoscale.Enabled { 99 return nil // AutoScale not enabled, move along... 100 } 101 102 // AutoScale enabled, no existing HPA found, create 103 if cr.Spec.Server.Autoscale.HPA != nil { 104 defaultHPA.Spec = *cr.Spec.Server.Autoscale.HPA 105 } 106 107 return r.Client.Create(context.TODO(), defaultHPA) 108 } 109 110 // reconcileAutoscalers will ensure that all HorizontalPodAutoscalers are present for the given ArgoCD. 111 func (r *ReconcileArgoCD) reconcileAutoscalers(cr *argoproj.ArgoCD) error { 112 if err := r.reconcileServerHPA(cr); err != nil { 113 return err 114 } 115 return nil 116 }