diff --git a/VERSION-vendor b/VERSION-vendor index 942ff0a..2a2c58a 100644 --- a/VERSION-vendor +++ b/VERSION-vendor @@ -1 +1 @@ -2.0.1-1 +2.0.1-2 diff --git a/git-commit b/git-commit index 6571d62..0bdd019 100644 --- a/git-commit +++ b/git-commit @@ -1 +1 @@ -a9c36f5a595959f3790b24a91ec243c74d9e382d +4a7405a1676d1c80e9938f3e1328cbee82e1a65c diff --git a/patch/0001-rubik-remove-duplicate-log.patch b/patch/0001-rubik-remove-duplicate-log.patch new file mode 100644 index 0000000..369be90 --- /dev/null +++ b/patch/0001-rubik-remove-duplicate-log.patch @@ -0,0 +1,331 @@ +From 15aafa185d19c34d02c6e7a459d997f3751b410d Mon Sep 17 00:00:00 2001 +From: vegbir +Date: Thu, 21 Nov 2024 15:02:45 +0000 +Subject: [PATCH] rubik: remove duplicate log + +Signed-off-by: vegbir +--- + pkg/core/trigger/common/type.go | 1 - + pkg/core/trigger/executor/resource.go | 12 ++++++------ + pkg/core/trigger/template/base.go | 8 -------- + pkg/core/typedef/containerinfo.go | 11 +++++------ + pkg/core/typedef/rawpod.go | 14 ++++++-------- + pkg/resource/analyze/analyzer.go | 9 +++++---- + pkg/services/eviction/common/manager.go | 15 +++++++++++---- + pkg/services/eviction/cpu/cpu.go | 19 ++++++++++--------- + pkg/services/eviction/memory/memory.go | 13 +++++++------ + 9 files changed, 50 insertions(+), 52 deletions(-) + +diff --git a/pkg/core/trigger/common/type.go b/pkg/core/trigger/common/type.go +index 901ca0d..5bfa5eb 100644 +--- a/pkg/core/trigger/common/type.go ++++ b/pkg/core/trigger/common/type.go +@@ -22,7 +22,6 @@ type ( + + const ( + TARGETPODS Factor = iota +- DEPORTPOD + ) + + // Descriptor defines methods for describing triggers +diff --git a/pkg/core/trigger/executor/resource.go b/pkg/core/trigger/executor/resource.go +index 46731dd..2f28271 100644 +--- a/pkg/core/trigger/executor/resource.go ++++ b/pkg/core/trigger/executor/resource.go +@@ -36,7 +36,7 @@ func MaxValueTransformer(cal analyze.Calculator) template.Transformation { + + pods, ok := ctx.Value(common.TARGETPODS).(map[string]*typedef.PodInfo) + if !ok { +- return ctx, fmt.Errorf("failed to get target pods") ++ return ctx, fmt.Errorf("invalid target pod type") + } + + for _, pod := range pods { +@@ -54,12 +54,12 @@ func MaxValueTransformer(cal analyze.Calculator) template.Transformation { + chosen = pod + } + } +- +- if chosen != nil { +- log.Infof("find the pod(%v) with the highest utilization(%v)", chosen.Name, maxValue) +- return context.WithValue(ctx, common.TARGETPODS, map[string]*typedef.PodInfo{chosen.Name: chosen}), nil ++ // If the object is successfully obtained, the object is returned, otherwise an empty object is returned ++ if chosen == nil { ++ return context.WithValue(ctx, common.TARGETPODS, map[string]*typedef.PodInfo{}), nil + } +- return context.Background(), fmt.Errorf("failed to find target pod") ++ log.Infof("find the pod(%v) with the highest utilization(%.2f%%)", chosen.Name, maxValue) ++ return context.WithValue(ctx, common.TARGETPODS, map[string]*typedef.PodInfo{chosen.Name: chosen}), nil + } + } + +diff --git a/pkg/core/trigger/template/base.go b/pkg/core/trigger/template/base.go +index f627884..9ad61de 100644 +--- a/pkg/core/trigger/template/base.go ++++ b/pkg/core/trigger/template/base.go +@@ -55,10 +55,6 @@ func transform(ctx context.Context, f Transformation) (context.Context, error) { + if f == nil { + return nil, fmt.Errorf("podFilter method is not implemented") + } +- // pods, ok := ctx.Value(common.TARGETPODS).(map[string]*typedef.PodInfo) +- // if !ok { +- // return ctx, fmt.Errorf("failed to get target pods") +- // } + ctx, err := f(ctx) + if err != nil { + return ctx, fmt.Errorf("failed to transform pod: %v", err) +@@ -70,10 +66,6 @@ func act(ctx context.Context, f Action) error { + if f == nil { + return fmt.Errorf("podAction method is not implemented") + } +- // pods, ok := ctx.Value(common.TARGETPODS).(map[string]*typedef.PodInfo) +- // if !ok { +- // return nil +- // } + return f(ctx) + } + +diff --git a/pkg/core/typedef/containerinfo.go b/pkg/core/typedef/containerinfo.go +index 3c61f08..ee5686b 100644 +--- a/pkg/core/typedef/containerinfo.go ++++ b/pkg/core/typedef/containerinfo.go +@@ -89,7 +89,7 @@ func NewContainerInfo(opts ...ConfigOpt) *ContainerInfo { + } + + if err := fromRawContainer(ci, conf.rawCont); err != nil { +- fmt.Printf("failed to parse raw container: %v", err) ++ fmt.Printf("failed to parse raw container: %v\n", err) + } + fromNRIContainer(ci, conf.nriCont) + fromPodCgroupPath(ci, conf.podCgroupPath) +@@ -109,17 +109,16 @@ func fromRawContainer(ci *ContainerInfo, rawCont *RawContainer) error { + if rawCont == nil { + return nil + } +- requests, limits := rawCont.GetResourceMaps() + id, err := rawCont.GetRealContainerID() + if err != nil { + return fmt.Errorf("failed to parse container ID: %v", err) + } +- if id == "" { +- return fmt.Errorf("empty container id") ++ // Note that the running pod may have containers that are being deleted or created, and their ids are empty. ++ if id != "" { ++ ci.ID = id + } +- + ci.Name = rawCont.status.Name +- ci.ID = id ++ requests, limits := rawCont.GetResourceMaps() + ci.RequestResources = requests + ci.LimitResources = limits + return nil +diff --git a/pkg/core/typedef/rawpod.go b/pkg/core/typedef/rawpod.go +index ed11c6b..45dbd40 100644 +--- a/pkg/core/typedef/rawpod.go ++++ b/pkg/core/typedef/rawpod.go +@@ -147,8 +147,8 @@ func (pod *RawPod) ExtractContainerInfos() map[string]*ContainerInfo { + WithRawContainer(rawContainer), + WithPodCgroup(pod.CgroupPath()), + ) ++ // The empty ID means that the container is being deleted and no updates are needed. + if ci.ID == "" { +- fmt.Printf("failed to parse id from raw container\n") + continue + } + idContainersMap[ci.ID] = ci +@@ -158,6 +158,10 @@ func (pod *RawPod) ExtractContainerInfos() map[string]*ContainerInfo { + + // GetRealContainerID parses the containerID of k8s + func (cont *RawContainer) GetRealContainerID() (string, error) { ++ // Empty container ID means the container may be in the creation or deletion phase. ++ if cont.status.ContainerID == "" { ++ return "", nil ++ } + /* + Note: + An UNDEFINED container engine was used when the function was executed for the first time +@@ -175,13 +179,7 @@ func (cont *RawContainer) GetRealContainerID() (string, error) { + if !currentContainerEngines.Support(cont) { + return "", fmt.Errorf("unsupported container engine: %v", cont.status.ContainerID) + } +- +- cid := cont.status.ContainerID[len(currentContainerEngines.Prefix()):] +- // the container may be in the creation or deletion phase. +- if len(cid) == 0 { +- return "", nil +- } +- return cid, nil ++ return cont.status.ContainerID[len(currentContainerEngines.Prefix()):], nil + } + + // GetResourceMaps returns the number of requests and limits of CPU and memory resources +diff --git a/pkg/resource/analyze/analyzer.go b/pkg/resource/analyze/analyzer.go +index 5c85897..20dd7b0 100644 +--- a/pkg/resource/analyze/analyzer.go ++++ b/pkg/resource/analyze/analyzer.go +@@ -14,6 +14,8 @@ + package analyze + + import ( ++ "runtime" ++ + v2 "github.com/google/cadvisor/info/v2" + + "isula.org/rubik/pkg/common/log" +@@ -53,7 +55,7 @@ func (a *Analyzer) CPUCalculatorBuilder(reqOpt *common.GetOption) Calculator { + cpuUsageUs = float64(last.Cpu.Usage.Total-penultimate.Cpu.Usage.Total) / nanoToMicro + timeDeltaUs = float64(last.Timestamp.Sub(penultimate.Timestamp).Microseconds()) + ) +- return util.Div(cpuUsageUs, timeDeltaUs) * percentageRate ++ return util.Div(cpuUsageUs, timeDeltaUs) / float64(runtime.NumCPU()) * percentageRate + } + } + +@@ -65,7 +67,6 @@ func (a *Analyzer) MemoryCalculatorBuilder(reqOpt *common.GetOption) Calculator + ) + podStats := a.getPodStats("/"+pi.Path, reqOpt) + if len(podStats) < miniNum { +- log.Errorf("pod %v has no enough memory stats collected, skip it", pi.Name) + return -1 + } + return float64(podStats[len(podStats)-1].Memory.Usage) / bytesToMb +@@ -75,12 +76,12 @@ func (a *Analyzer) MemoryCalculatorBuilder(reqOpt *common.GetOption) Calculator + func (a *Analyzer) getPodStats(cgroupPath string, reqOpt *common.GetOption) []*v2.ContainerStats { + infoMap, err := a.GetPodStats(cgroupPath, *reqOpt) + if err != nil { +- log.Errorf("failed to get cgroup information %v: %v", cgroupPath, err) ++ log.Warnf("failed to get cgroup information %v: %v", cgroupPath, err) + return nil + } + info, existed := infoMap[cgroupPath] + if !existed { +- log.Errorf("failed to get cgroup %v from cadvisor", cgroupPath) ++ log.Warnf("failed to get cgroup %v from cadvisor", cgroupPath) + return nil + } + return info.Stats +diff --git a/pkg/services/eviction/common/manager.go b/pkg/services/eviction/common/manager.go +index 4758c72..8a30e4b 100644 +--- a/pkg/services/eviction/common/manager.go ++++ b/pkg/services/eviction/common/manager.go +@@ -74,7 +74,7 @@ func newCadvisorManager() (resource.Manager, error) { + + // Controller is a controller for different resources + type Controller interface { +- Start(context.Context, func() error) ++ Start(context.Context, func(func() bool) error) + Config() interface{} + } + +@@ -213,12 +213,19 @@ func (m *Manager) Terminate(api.Viewer) error { + return err + } + +-func (m *Manager) alarm(typ string) func() error { +- return func() error { ++func (m *Manager) alarm(typ string) func(func() bool) error { ++ return func(needEvcit func() bool) error { ++ pods := m.viewer.ListPodsWithOptions(priority(false)) ++ if len(pods) == 0 { ++ return nil ++ } + var ( + errs error +- ctx = context.WithValue(context.Background(), common.TARGETPODS, m.viewer.ListPodsWithOptions(priority(false))) ++ ctx = context.WithValue(context.Background(), common.TARGETPODS, pods) + ) ++ if !needEvcit() { ++ return nil ++ } + for _, t := range m.baseMetric.Triggers[typ] { + errs = util.AppendErr(errs, t.Activate(ctx)) + } +diff --git a/pkg/services/eviction/cpu/cpu.go b/pkg/services/eviction/cpu/cpu.go +index b11d94b..1cdbe7d 100644 +--- a/pkg/services/eviction/cpu/cpu.go ++++ b/pkg/services/eviction/cpu/cpu.go +@@ -62,17 +62,14 @@ func fromConfig(name string, f helper.ConfigHandler) (*Controller, error) { + } + + // Start loop collects data and performs eviction +-func (c *Controller) Start(ctx context.Context, evictor func() error) { ++func (c *Controller) Start(ctx context.Context, evictor func(func() bool) error) { + wait.Until( + func() { + c.collect() + if atomic.LoadInt32(&c.block) == 1 { + return + } +- if !c.assertWithinLimit() { +- return +- } +- if err := evictor(); err != nil { ++ if err := evictor(c.assertWithinLimit); err != nil { + log.Errorf("failed to execute cpuevict %v", err) + return + } +@@ -128,16 +125,20 @@ func (c *Controller) averageUsage() float64 { + c.RLock() + defer c.RUnlock() + if len(c.usages) < minUsageLen { +- log.Infof("failed to get node cpu usage at %v", time.Now().Format(format)) +- return 0 ++ log.Debugf("failed to get node cpu usage at %v", time.Now().Format(format)) ++ return -1 + } + util := quotaturbo.CalculateUtils(c.usages[0].cpuStats, c.usages[len(c.usages)-1].cpuStats) +- log.Debugf("get node cpu usage %v at %v", util, time.Now().Format(format)) + return util + } + + func (c *Controller) assertWithinLimit() bool { +- return c.averageUsage() >= float64(c.conf.Threshold) ++ util := c.averageUsage() ++ if util >= float64(c.conf.Threshold) { ++ log.Infof("CPU exceeded: %v%%", util) ++ return true ++ } ++ return false + } + + // Config returns the configuration +diff --git a/pkg/services/eviction/memory/memory.go b/pkg/services/eviction/memory/memory.go +index 9aa82dc..5215a8a 100644 +--- a/pkg/services/eviction/memory/memory.go ++++ b/pkg/services/eviction/memory/memory.go +@@ -51,16 +51,13 @@ func fromConfig(name string, f helper.ConfigHandler) (*Controller, error) { + } + + // Start loop collects data and performs eviction +-func (c *Controller) Start(ctx context.Context, evictor func() error) { ++func (c *Controller) Start(ctx context.Context, evictor func(func() bool) error) { + wait.Until( + func() { + if atomic.LoadInt32(&c.block) == 1 { + return + } +- if !c.assertWithinLimit() { +- return +- } +- if err := evictor(); err != nil { ++ if err := evictor(c.assertWithinLimit); err != nil { + log.Errorf("failed to execute memory evict %v", err) + return + } +@@ -86,7 +83,11 @@ func (c *Controller) assertWithinLimit() bool { + log.Errorf("failed to get memory util at %v: %v", time.Now().Format(format), err) + return false + } +- return v.UsedPercent >= float64(c.conf.Threshold) ++ if v.UsedPercent >= float64(c.conf.Threshold) { ++ log.Infof("Memory exceeded: %v%%", v.UsedPercent) ++ return true ++ } ++ return false + } + + // Config returns the configuration +-- +2.45.0 + diff --git a/rubik.spec b/rubik.spec index f3f1a6d..d2cfe94 100644 --- a/rubik.spec +++ b/rubik.spec @@ -1,6 +1,6 @@ Name: rubik Version: 2.0.1 -Release: 1 +Release: 2 Summary: Hybrid Deployment for Cloud Native License: Mulan PSL V2 URL: https://gitee.com/openeuler/rubik @@ -59,6 +59,12 @@ install -Dp ./build_rubik_image.sh %{buildroot}%{_sharedstatedir}/%{name}/build_ rm -rf %{buildroot} %changelog +* Wed Nov 27 2024 vegbir - 2.0.1-2 +- Type: bugfix +- CVE:NA +- SUG:restart +- DESC:remove duplicate log + * Thu Nov 14 2024 vegbir - 2.0.1-1 - Type: bugfix - CVE:NA diff --git a/series.conf b/series.conf index 2a324cf..6d08b57 100644 --- a/series.conf +++ b/series.conf @@ -1 +1,2 @@ +patch/0001-rubik-remove-duplicate-log.patch # end of file \ No newline at end of file