syncable_cli/analyzer/k8s_optimize/rules/
k8s_opt_008.rs

1//! K8S-OPT-008: Memory limit to request ratio is excessive.
2
3use super::{OptimizationRule, RuleContext, codes};
4use crate::analyzer::k8s_optimize::config::K8sOptimizeConfig;
5use crate::analyzer::k8s_optimize::parser::{
6    bytes_to_memory_string, memory_limit_to_request_ratio, parse_memory_to_bytes,
7};
8use crate::analyzer::k8s_optimize::types::{
9    OptimizationIssue, ResourceRecommendation, ResourceSpec, RuleCode, Severity,
10};
11
12/// Rule: Excessive memory limit to request ratio.
13pub struct ExcessiveMemoryRatioRule;
14
15impl OptimizationRule for ExcessiveMemoryRatioRule {
16    fn code(&self) -> &'static str {
17        codes::EXCESSIVE_MEMORY_RATIO
18    }
19
20    fn description(&self) -> &'static str {
21        "Memory limit to request ratio is excessive"
22    }
23
24    fn default_severity(&self) -> Severity {
25        Severity::Medium
26    }
27
28    fn check(
29        &self,
30        ctx: &RuleContext,
31        config: &K8sOptimizeConfig,
32    ) -> Option<ResourceRecommendation> {
33        let ratio = memory_limit_to_request_ratio(&ctx.current)?;
34
35        // Check if exceeds threshold
36        if ratio <= config.max_memory_limit_ratio as f64 {
37            return None;
38        }
39
40        // Calculate balanced memory limit
41        let memory_limit = if let Some(ref memory_request) = ctx.current.memory_request {
42            if let Some(bytes) = parse_memory_to_bytes(memory_request) {
43                let limit_bytes = (bytes as f64 * config.max_memory_limit_ratio as f64) as u64;
44                bytes_to_memory_string(limit_bytes)
45            } else {
46                ctx.current.memory_limit.clone().unwrap_or_default()
47            }
48        } else {
49            ctx.current.memory_limit.clone().unwrap_or_default()
50        };
51
52        let recommended = ResourceSpec {
53            cpu_request: ctx.current.cpu_request.clone(),
54            cpu_limit: ctx.current.cpu_limit.clone(),
55            memory_request: ctx.current.memory_request.clone(),
56            memory_limit: Some(memory_limit),
57        };
58
59        Some(ResourceRecommendation {
60            resource_kind: ctx.resource_kind.clone(),
61            resource_name: ctx.resource_name.clone(),
62            namespace: ctx.namespace.clone(),
63            container: ctx.container_name.clone(),
64            file_path: ctx.file_path.clone(),
65            line: ctx.line,
66            issue: OptimizationIssue::ExcessiveRatio,
67            severity: self.default_severity(),
68            message: format!(
69                "Memory limit to request ratio is {:.1}x (threshold: {}x). Large ratios can lead to OOM kills under pressure.",
70                ratio, config.max_memory_limit_ratio
71            ),
72            workload_type: ctx.workload_type,
73            current: ctx.current.clone(),
74            actual_usage: None,
75            recommended: recommended.clone(),
76            savings: None,
77            fix_yaml: recommended.to_yaml(),
78            rule_code: RuleCode::new(self.code()),
79        })
80    }
81}