@@ -26,6 +26,7 @@ import (
2626 "github.com/jatalocks/kube-reqsizer/pkg/cache/localcache"
2727 "github.com/jatalocks/kube-reqsizer/pkg/cache/rediscache"
2828 "github.com/jatalocks/kube-reqsizer/types"
29+ "github.com/prometheus/client_golang/prometheus"
2930 corev1 "k8s.io/api/core/v1"
3031 v1 "k8s.io/api/core/v1"
3132 apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -36,6 +37,7 @@ import (
3637
3738 ctrl "sigs.k8s.io/controller-runtime"
3839 "sigs.k8s.io/controller-runtime/pkg/client"
40+ "sigs.k8s.io/controller-runtime/pkg/metrics"
3941)
4042
4143// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;update;patch
@@ -66,64 +68,90 @@ const (
6668 operatorModeAnnotation = "reqsizer.jatalocks.github.io/mode"
6769)
6870
71+ var (
72+ cpuOffset = prometheus .NewGauge (
73+ prometheus.GaugeOpts {
74+ Name : "cpu_offset" ,
75+ Help : "Number of milli-cores that have been increased/removed since startup" ,
76+ },
77+ )
78+ memoryOffset = prometheus .NewGauge (
79+ prometheus.GaugeOpts {
80+ Name : "memory_offset" ,
81+ Help : "Number of megabits that have been increased/removed since startup" ,
82+ },
83+ )
84+ cacheSize = prometheus .NewGauge (
85+ prometheus.GaugeOpts {
86+ Name : "cache_size" ,
87+ Help : "Number of pod controllers currently in cache" ,
88+ },
89+ )
90+ )
91+
92+ func init () {
93+ // Register custom metrics with the global prometheus registry
94+ metrics .Registry .MustRegister (cpuOffset , memoryOffset , cacheSize )
95+ }
96+
6997func cacheKeyFunc (obj interface {}) (string , error ) {
70- return obj .(types.PodRequests ).Name + "-" + obj .(types. PodRequests ). Namespace , nil
98+ return obj .(types.PodRequests ).Name , nil
7199}
72100
73101var cacheStore = cache .NewStore (cacheKeyFunc )
74102
75103// Reconcile handles a reconciliation request for a Pod.
76104func (r * PodReconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (ctrl.Result , error ) {
77105 log := r .Log .WithValues ("pod" , req .NamespacedName )
78-
106+ if r .EnablePersistence {
107+ cacheSize .Set (float64 (r .RedisClient .CacheSize ()))
108+ } else {
109+ cacheSize .Set (float64 (len (cacheStore .List ())))
110+ }
79111 /*
80112 Step 0: Fetch the Pod from the Kubernetes API.
81113 */
82-
83114 var pod corev1.Pod
115+
84116 if err := r .Get (ctx , req .NamespacedName , & pod ); err != nil {
85117 if apierrors .IsNotFound (err ) {
86- // we'll ignore not-found errors, since they can't be fixed by an immediate
87- // requeue (we'll need to wait for a new notification), and we can get them
88- // on deleted requests.
89118 return ctrl.Result {}, nil
90119 }
91120 log .Error (nil , "unable to fetch Pod" )
92121 return ctrl.Result {}, err
93122 }
94-
95- annotation , err := r .NamespaceOrPodHaveAnnotation (pod , ctx )
123+ podReferenceName := r . GetPodCacheName ( & pod ) + "-" + pod . Namespace
124+ annotation , err := r .NamespaceOrPodHaveAnnotation (& pod , ctx )
96125 if err != nil {
97126 log .Error (nil , "failed to get annotations" )
98127 return ctrl.Result {}, err
99128 }
100- ignoreAnnotation , err := r .NamespaceOrPodHaveIgnoreAnnotation (pod , ctx )
129+ ignoreAnnotation , err := r .NamespaceOrPodHaveIgnoreAnnotation (& pod , ctx )
101130 if err != nil {
102131 log .Error (nil , "failed to get annotations" )
103132 return ctrl.Result {}, err
104133 }
105134
106135 if ((! r .EnableAnnotation ) || (r .EnableAnnotation && annotation )) && ! ignoreAnnotation {
136+ log .Info ("Cache Reference Name: " + podReferenceName )
137+
107138 data , err := r .ClientSet .RESTClient ().Get ().AbsPath (fmt .Sprintf ("apis/metrics.k8s.io/v1beta1/namespaces/%v/pods/%v" , pod .Namespace , pod .Name )).DoRaw (ctx )
108139
109140 if err != nil {
110141 log .Error (nil , "failed to get stats from pod" )
111142 return ctrl.Result {}, err
112143 }
113144 PodUsageData := GeneratePodRequestsObjectFromRestData (data )
114- err , _ , _ , deploymentName := r .GetPodParentKind (pod , ctx )
115- if err != nil {
116- deploymentName = pod .Name
117- }
118- SumPodRequest := types.PodRequests {Name : deploymentName , Namespace : pod .Namespace , ContainerRequests : []types.ContainerRequests {}}
145+ SumPodRequest := types.PodRequests {Name : podReferenceName , Namespace : pod .Namespace , ContainerRequests : []types.ContainerRequests {}}
119146
120147 SumPodRequest .ContainerRequests = PodUsageData .ContainerRequests
121148 var LatestPodRequest types.PodRequests
122149 if r .EnablePersistence {
123- LatestPodRequest , err = r .RedisClient .FetchFromCache (deploymentName + "-" + pod . Namespace )
150+ LatestPodRequest , err = r .RedisClient .FetchFromCache (podReferenceName )
124151 } else {
125- LatestPodRequest , err = localcache .FetchFromCache (cacheStore , deploymentName + "-" + pod . Namespace )
152+ LatestPodRequest , err = localcache .FetchFromCache (cacheStore , podReferenceName )
126153 }
154+
127155 if err != nil {
128156 SumPodRequest .Sample = 0
129157 log .Info (fmt .Sprint ("Adding cache sample " , SumPodRequest .Sample ))
@@ -184,7 +212,6 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
184212 }
185213 }
186214 }
187- log .Info (fmt .Sprint (SumPodRequest ))
188215 if (SumPodRequest .Sample >= r .SampleSize ) && r .MinimumUptimeOfPodInParent (pod , ctx ) {
189216 log .Info ("Sample Size and Minimum Time have been reached" )
190217 PodChange := false
@@ -216,28 +243,34 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
216243 case "average" :
217244 if r .ValidateCPU (currentC .CPU , AverageUsageCPU ) {
218245 pod .Spec .Containers [i ].Resources .Requests [v1 .ResourceCPU ] = resource .MustParse (fmt .Sprintf ("%dm" , int (float64 (AverageUsageCPU )* r .CPUFactor )))
246+ cpuOffset .Add (float64 (int (float64 (AverageUsageCPU )* r .CPUFactor ) - int (currentC .CPU )))
219247 PodChange = true
220248 }
221249 if r .ValidateMemory (currentC .Memory , AverageUsageMemory ) {
222250 pod .Spec .Containers [i ].Resources .Requests [v1 .ResourceMemory ] = resource .MustParse (fmt .Sprintf ("%dMi" , int (float64 (AverageUsageMemory )* r .MemoryFactor )))
251+ memoryOffset .Add (float64 (int (float64 (AverageUsageMemory )* r .MemoryFactor ) - int (currentC .Memory )))
223252 PodChange = true
224253 }
225254 case "min" :
226255 if r .ValidateCPU (currentC .CPU , c .MinCPU ) {
227256 pod .Spec .Containers [i ].Resources .Requests [v1 .ResourceCPU ] = resource .MustParse (fmt .Sprintf ("%dm" , int (float64 (c .MinCPU )* r .CPUFactor )))
257+ cpuOffset .Add (float64 (int (float64 (c .MinCPU )* r .CPUFactor ) - int (currentC .CPU )))
228258 PodChange = true
229259 }
230260 if r .ValidateMemory (currentC .Memory , c .MinMemory ) {
231261 pod .Spec .Containers [i ].Resources .Requests [v1 .ResourceMemory ] = resource .MustParse (fmt .Sprintf ("%dMi" , int (float64 (c .MinMemory )* r .MemoryFactor )))
262+ memoryOffset .Add (float64 (int (float64 (c .MinMemory )* r .MemoryFactor ) - int (currentC .Memory )))
232263 PodChange = true
233264 }
234265 case "max" :
235266 if r .ValidateCPU (currentC .CPU , c .MaxCPU ) {
236267 pod .Spec .Containers [i ].Resources .Requests [v1 .ResourceCPU ] = resource .MustParse (fmt .Sprintf ("%dm" , int (float64 (c .MaxCPU )* r .CPUFactor )))
268+ cpuOffset .Add (float64 (int (float64 (c .MaxCPU )* r .CPUFactor ) - int (currentC .CPU )))
237269 PodChange = true
238270 }
239271 if r .ValidateMemory (currentC .Memory , c .MaxMemory ) {
240272 pod .Spec .Containers [i ].Resources .Requests [v1 .ResourceMemory ] = resource .MustParse (fmt .Sprintf ("%dMi" , int (float64 (c .MaxMemory )* r .MemoryFactor )))
273+ memoryOffset .Add (float64 (int (float64 (c .MaxMemory )* r .MemoryFactor ) - int (currentC .Memory )))
241274 PodChange = true
242275 }
243276 }
@@ -249,6 +282,15 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
249282 }
250283 }
251284 }
285+ if r .EnablePersistence {
286+ if err := r .RedisClient .DeleteFromCache (SumPodRequest ); err != nil {
287+ log .Error (err , err .Error ())
288+ }
289+ } else {
290+ if err := localcache .DeleteFromCache (cacheStore , LatestPodRequest ); err != nil {
291+ log .Error (err , err .Error ())
292+ }
293+ }
252294 if PodChange {
253295 pod .Annotations ["reqsizer.jatalocks.github.io/changed" ] = "true"
254296
@@ -267,20 +309,9 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
267309 UpdatePodController (podSpec , Requests , ctx )
268310
269311 return r .UpdateKubeObject (deployment .(client.Object ), ctx )
270-
271- }
272-
273- if r .EnablePersistence {
274- if err := r .RedisClient .DeleteFromCache (SumPodRequest ); err != nil {
275- log .Error (err , err .Error ())
276- }
277- } else {
278- if err := localcache .DeleteFromCache (cacheStore , LatestPodRequest ); err != nil {
279- log .Error (err , err .Error ())
280- }
281312 }
282313 }
283314 }
284315
285- return ctrl.Result {RequeueAfter : 10 * time .Second }, nil
316+ return ctrl.Result {RequeueAfter : 5 * time .Second }, nil
286317}
0 commit comments