mirror of
https://github.com/outbackdingo/cozystack.git
synced 2026-02-05 08:17:59 +00:00
* Count Workload resources for pods by requests, not limits
* Do not count init container requests
* Prefix Workloads for pods with `pod-`, just like the other types to
prevent possible name collisions (closes #787)
The previous version of the WorkloadMonitor controller incorrectly
summed resource limits on pods, rather than requests. This prevented it
from tracking the resource allocation for pods, which only had requests
specified, which is particularly the case for kubevirt's virtual machine
pods. Additionally, it counted the limits for all containers, including
init containers, which are short-lived and do not contribute much to the
total resource usage.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Bug Fixes**
- Improved handling of workloads with unrecognized prefixes by ensuring
they are properly deleted and not processed further.
- Corrected resource aggregation for Pods to sum container resource
requests instead of limits, and now only includes normal containers.
- **New Features**
- Added support for monitoring workloads with names prefixed by "pod-".
- **Tests**
- Introduced unit tests to verify correct handling of workload name
prefixes and monitored object creation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
(cherry picked from commit 1e59e5fbb6)
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
100 lines
2.5 KiB
Go
100 lines
2.5 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
ctrl "sigs.k8s.io/controller-runtime"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/log"
|
|
|
|
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
|
)
|
|
|
|
// WorkloadMonitorReconciler reconciles a WorkloadMonitor object
|
|
type WorkloadReconciler struct {
|
|
client.Client
|
|
Scheme *runtime.Scheme
|
|
}
|
|
|
|
func (r *WorkloadReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
|
logger := log.FromContext(ctx)
|
|
w := &cozyv1alpha1.Workload{}
|
|
err := r.Get(ctx, req.NamespacedName, w)
|
|
if err != nil {
|
|
if apierrors.IsNotFound(err) {
|
|
return ctrl.Result{}, nil
|
|
}
|
|
logger.Error(err, "Unable to fetch Workload")
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
// it's being deleted, nothing to handle
|
|
if w.DeletionTimestamp != nil {
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
t := getMonitoredObject(w)
|
|
|
|
if t == nil {
|
|
err = r.Delete(ctx, w)
|
|
if err != nil {
|
|
logger.Error(err, "failed to delete workload")
|
|
}
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
err = r.Get(ctx, types.NamespacedName{Name: t.GetName(), Namespace: t.GetNamespace()}, t)
|
|
|
|
// found object, nothing to do
|
|
if err == nil {
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
// error getting object but not 404 -- requeue
|
|
if !apierrors.IsNotFound(err) {
|
|
logger.Error(err, "failed to get dependent object", "kind", t.GetObjectKind(), "dependent-object-name", t.GetName())
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
err = r.Delete(ctx, w)
|
|
if err != nil {
|
|
logger.Error(err, "failed to delete workload")
|
|
}
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
// SetupWithManager registers our controller with the Manager and sets up watches.
|
|
func (r *WorkloadReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
|
return ctrl.NewControllerManagedBy(mgr).
|
|
// Watch WorkloadMonitor objects
|
|
For(&cozyv1alpha1.Workload{}).
|
|
Complete(r)
|
|
}
|
|
|
|
func getMonitoredObject(w *cozyv1alpha1.Workload) client.Object {
|
|
switch {
|
|
case strings.HasPrefix(w.Name, "pvc-"):
|
|
obj := &corev1.PersistentVolumeClaim{}
|
|
obj.Name = strings.TrimPrefix(w.Name, "pvc-")
|
|
obj.Namespace = w.Namespace
|
|
return obj
|
|
case strings.HasPrefix(w.Name, "svc-"):
|
|
obj := &corev1.Service{}
|
|
obj.Name = strings.TrimPrefix(w.Name, "svc-")
|
|
obj.Namespace = w.Namespace
|
|
return obj
|
|
case strings.HasPrefix(w.Name, "pod-"):
|
|
obj := &corev1.Pod{}
|
|
obj.Name = strings.TrimPrefix(w.Name, "pod-")
|
|
obj.Namespace = w.Namespace
|
|
return obj
|
|
}
|
|
var obj client.Object
|
|
return obj
|
|
}
|