<p>I hope you can shed some light on this.</p>
<p>I am facing the same issue as described here: <a href="https://stackoverflow.com/questions/60959284/kubernetes-deployment-not-scaling-down-even-though-usage-is-below-threshold">Kubernetes deployment not scaling down even though usage is below threshold</a></p>
<p>My configuration is almost identical.</p>
<p>I have checked the hpa algorithm, but I cannot find an explanation for the fact that I am having only one replica of my-app3.
Any hints?</p>
<pre>kubectl get hpa -A 

NAMESPACE            NAME        REFERENCE              TARGETS            MINPODS   MAXPODS   REPLICAS   AGE
my-ns1               my-app1     Deployment/my-app1     49%/75%, 2%/75%    1         10        2          20h
my-ns2               my-app2     Deployment/my-app2     50%/75%, 10%/75%   1         10        2          22h
my-ns2               my-app3     Deployment/my-app3     47%/75%, 10%/75%   1         10        1          22h
</pre>
<pre>kubectl top po -A

NAMESPACE             NAME                                                     CPU(cores)   MEMORY(bytes)              
my-ns1                pod-app1-8d694bc8f-mkbrh                                 1m           76Mi            
my-ns1                pod-app1-8d694bc8f-qmlnw                                 1m           72Mi            
my-ns2                pod-app2-59d895d96d-86fgm                                1m           77Mi            
my-ns2                pod-app2-59d895d96d-zr67g                                1m           73Mi            
my-ns2                pod-app3-6f8cbb68bf-vdhsd                                1m           47Mi 
</pre>

Catalin
<p>Posting this answer as it could be beneficiary for the community members on why exactly <code>Horizontal Pod Autoscaler</code> decided <strong>not</strong> to scale the amount of replicas in this particular setup.</p>
<p>The formula for amount of replicas workload will have is:</p>
<blockquote>
<p>desiredReplicas = ceil[<strong>currentReplicas</strong> * ( currentMetricValue / desiredMetricValue )]</p>
</blockquote>
<p>Following on the describe of <code>HPA</code>:</p>
<pre class="lang-sh prettyprint-override"><code>NAMESPACE            NAME        REFERENCE              TARGETS            MINPODS   MAXPODS   REPLICAS   AGE
my-ns1               my-app1     Deployment/my-app1     49%/75%, 2%/75%    1         10        2          20h
my-ns2               my-app2     Deployment/my-app2     50%/75%, 10%/75%   1         10        2          22h
my-ns2               my-app3     Deployment/my-app3     47%/75%, 10%/75%   1         10        1          22h
</code></pre>
<p><code>HPA</code> decides on the amount of replicas on the premise of their <strong>current amount</strong>.</p>
<p><strong>A side note</strong>: In the setup that uses multiple metrics (for example <code>CPU</code> and <code>RAM</code>) it will use the higher metric and act accordingly.</p>
<p>Also please consider that <a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-cooldown-delay" rel="nofollow noreferrer">downscaling has a cooldown</a>.</p>
<hr />
<h3>Calculation on each of the <code>Deployments</code></h3>
<blockquote>
<p><code>ceil[]</code> - round a number up:</p>
<ul>
<li>ceil(4,55) = 5</li>
<li>ceil(4,01) = 5</li>
</ul>
</blockquote>
<p><code>app1</code>:</p>
<ul>
<li><code>Replicas</code> = ceil[<code>2</code> * (<code>49</code> / <code>75</code>)]</li>
<li><code>Replicas</code> = ceil[<code>2</code> * <code>0,6533..</code>]</li>
<li><code>Replicas</code> = ceil[<code>1,3066..</code>]</li>
<li><code>Replicas</code> = <strong><code>2</code></strong></li>
</ul>
<p>This example shows that there will be no changes to be amount of replicas.</p>
<p>Amount of replicas would go:</p>
<ul>
<li><strong>Up</strong> when the <code>currentMetricValue</code> (<code>49</code>) would exceed the <code>desiredMetricValue</code> (<code>75</code>)</li>
<li><strong>Down</strong> when the <code>currentMetricValue</code> (<code>49</code>) would be <strong>less than half</strong> of the <code>desiredMetricValue</code> (<code>75</code>)</li>
</ul>
<p><code>app2</code> is in the same situation as <code>app1</code> so it can be skipped</p>
<p><code>app3</code>:</p>
<ul>
<li><code>Replicas</code> = ceil[<code>1</code> * (<code>49</code> / <code>75</code>)]</li>
<li><code>Replicas</code> = ceil[<code>1</code> * <code>0,6266..</code>]</li>
<li><code>Replicas</code> = ceil[<code>0,6266..</code>]</li>
<li><code>Replicas</code> = <strong><code>1</code></strong></li>
</ul>
<p>This example also shows that there will be no changes to be amount of replicas.</p>
<p>Amount of replicas would go:</p>
<ul>
<li><strong>Up</strong> when the <code>currentMetricValue</code> (<code>47</code>) would exceed the <code>desiredMetricValue</code> (<code>75</code>)</li>
</ul>
<hr />
<p>Additional resources:</p>
<ul>
<li><em><a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/" rel="nofollow noreferrer">Kubernetes.io: Docs: Tasks: Run application: Horizontal pod autoscale</a></em></li>
</ul>
