HorizontalPodAutoscaler
Does ZopNight manage HorizontalPodAutoscaler?
HorizontalPodAutoscalers move replicas between minReplicas and maxReplicas, and the minimum is a cost floor that holds capacity at 3 a.m. ZopNight records target, bounds, current and desired replicas, and conditions, flagging saturation only when ScalingLimited reports TooManyReplicas, since desiredReplicas is clamped and can never exceed the max.
Rules that fire on HorizontalPodAutoscaler
A HorizontalPodAutoscaler moves a workload’s replica count between a floor and a ceiling based on observed metrics. Both bounds are cost decisions: the floor is capacity you pay for at 3 a.m., and the ceiling is where saturation hides.
minReplicas is a spending floor
Discovery records the target workload (targetRef and kind), minReplicas, maxReplicas, current and desired replicas, the configured metrics, current metric readings, conditions, and the last scale time. The floor deserves the most scrutiny: an HPA with a generous minimum keeps that many pods, and the node capacity beneath them, running through every quiet hour, which is over-provisioning wearing an autoscaling costume.
Why at-max detection reads a condition, not a comparison
Kubernetes clamps desiredReplicas to maxReplicas, so the intuitive check (desired above max) can never be observed on real data. The HPA At Max Capacity rule (RC-1717 / RC-1817 / RC-1917, high severity) instead reads the HPA’s own ScalingLimited condition and fires only when it is True with reason TooManyReplicas: the controller’s first-hand record that it wanted more replicas than the ceiling allowed. A workload that merely happens to run at exactly max is left alone, and missing or unparseable conditions cause the rule to abstain rather than guess.
Removed and recreated around scheduled downtime
A plain HPA does not act on a workload scaled to 0 replicas, so it is not what undoes a scheduled stop; KEDA is, which is why a namespace schedule deletes KEDA ScaledObjects first. The HPAs that target each workload are then saved and deleted as housekeeping while the workloads scale down, and recreated at resume with their original spec, so the autoscaling setup comes back exactly as it was.
kubectl get hpa -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,TARGET:.spec.scaleTargetRef.name,MIN:.spec.minReplicas,MAX:.spec.maxReplicas,CURRENT:.status.currentReplicasReading an HPA in review
Three questions cover most audits: does the floor reflect real overnight demand or just caution; has ScalingLimited been true recently, meaning the ceiling is throttling real traffic; and does the target workload still exist? The recorded conditions and last scale time answer all three without touching the cluster.