Skip to content

Commit 6301116

Browse files
ricolinCopilot
andcommitted
fix(resources): omit ephemeral-disk autoscaler annotation when 0
Address review feedback on PR #1014. For server_type=bm, the boot volume default returns 0 (Ironic boots from local disk, not Cinder), and the fallback flavor.disk is typically also 0 because root_gb lives on the Ironic node rather than the Nova flavor. Previously the autoscaler annotation capacity.cluster-autoscaler.kubernetes.io/ephemeral-disk was set to "0", which causes cluster-autoscaler to reject any pod that requests ephemeral-storage even if the Ironic node has plenty of local disk. Skip the annotation entirely in that case so the autoscaler can fall back to cpu/memory-only scheduling decisions, which is correct for BM nodes whose disk capacity we cannot reliably determine here. Also document the auto-default in docs/user/labels.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: ricolin <rlin@vexxhost.com>
1 parent 4d4b662 commit 6301116

3 files changed

Lines changed: 91 additions & 5 deletions

File tree

docs/user/labels.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ specify the volume size and type using the following labels:
1717

1818
: The size in gigabytes of the boot volume. If you set this value, it will
1919
enable boot from volume.
20-
**Default value**: Unset
20+
**Default value**: Unset for `server_type=vm` clusters; automatically
21+
`0` for `server_type=bm` clusters (baremetal nodes boot from local disk
22+
via Ironic and cannot use a Cinder root volume). Operators can still
23+
override explicitly on `server_type=bm` by setting this label on the
24+
cluster_template, cluster, or node_group.
2125

2226
`boot_volume_type`
2327

magnum_cluster_api/resources.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -749,21 +749,30 @@ def mutate_machine_deployment(
749749
boot_volume_size = flavor.disk
750750

751751
machine_deployment["replicas"] = None
752-
machine_deployment["metadata"]["annotations"] = {
752+
annotations = {
753753
AUTOSCALE_ANNOTATION_MIN: str(node_group.min_node_count),
754754
AUTOSCALE_ANNOTATION_MAX: str(
755755
utils.get_node_group_max_node_count(node_group)
756756
),
757757
"capacity.cluster-autoscaler.kubernetes.io/memory": f"{math.ceil(flavor.ram / 1024)}G",
758758
"capacity.cluster-autoscaler.kubernetes.io/cpu": str(flavor.vcpus),
759-
"capacity.cluster-autoscaler.kubernetes.io/ephemeral-disk": str(
760-
boot_volume_size
761-
),
762759
"capacity.cluster-autoscaler.kubernetes.io/labels": (
763760
f"node-role.kubernetes.io/{node_group.role}=,"
764761
f"node.cluster.x-k8s.io/nodegroup={node_group.name}"
765762
),
766763
}
764+
# Only emit the ephemeral-disk capacity hint when we can resolve a
765+
# non-zero value. For server_type=bm the flavor.disk is typically
766+
# 0 (root_gb lives on the Ironic node, not the Nova flavor) and
767+
# the Cinder root volume default is also 0; advertising "0" here
768+
# would mislead the autoscaler into rejecting pods that request
769+
# ephemeral-storage. Omitting the annotation lets the autoscaler
770+
# fall back to scheduling on cpu/memory only.
771+
if boot_volume_size > 0:
772+
annotations["capacity.cluster-autoscaler.kubernetes.io/ephemeral-disk"] = (
773+
str(boot_volume_size)
774+
)
775+
machine_deployment["metadata"]["annotations"] = annotations
767776
else:
768777
machine_deployment["replicas"] = node_group.node_count
769778
machine_deployment["metadata"]["annotations"] = {}

magnum_cluster_api/tests/unit/test_resources.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ class TestExistingMutateMachineDeployment:
9696
@pytest.fixture(autouse=True)
9797
def setup(self, auto_scaling_enabled, auto_healing_enabled, context, mocker):
9898
self.cluster = utils.get_test_cluster(context, labels={})
99+
# mutate_machine_deployment now consults cluster.cluster_template.server_type
100+
# (via utils.get_default_boot_volume_size) which lazy-loads from the DB
101+
# in this test context. Stub the helper so existing assertions are
102+
# unaffected.
103+
mocker.patch(
104+
"magnum_cluster_api.utils.get_default_boot_volume_size",
105+
side_effect=lambda cluster, default: default,
106+
)
99107
if auto_scaling_enabled is not None:
100108
self.cluster.labels["auto_scaling_enabled"] = str(auto_scaling_enabled)
101109

@@ -161,3 +169,68 @@ def test_mutate_machine_deployment(self, context, auto_scaling_enabled):
161169
else:
162170
assert md["replicas"] == self.node_group.node_count
163171
assert md["metadata"]["annotations"] == {}
172+
173+
174+
def test_mutate_machine_deployment_bm_omits_ephemeral_disk_annotation(context, mocker):
175+
"""For server_type=bm flavors with disk=0 the autoscaler annotation
176+
should be omitted rather than emitted as "0", which would make the
177+
autoscaler reject pods that request ephemeral-storage."""
178+
cluster = utils.get_test_cluster(context, labels={})
179+
mocker.patch(
180+
"magnum_cluster_api.utils.get_default_boot_volume_size",
181+
return_value=0,
182+
)
183+
cluster.labels["auto_scaling_enabled"] = "true"
184+
node_group = utils.get_test_nodegroup(context, labels={})
185+
node_group.min_node_count = 1
186+
node_group.max_node_count = 3
187+
188+
mocker.patch("magnum_cluster_api.utils.lookup_image", return_value={"id": "foo"})
189+
mocker.patch(
190+
"magnum_cluster_api.utils.lookup_flavor",
191+
return_value=flavors.Flavor(
192+
None,
193+
{"name": "bm-flavor", "disk": 0, "ram": 4096, "vcpus": 4},
194+
),
195+
)
196+
197+
md = resources.mutate_machine_deployment(
198+
context, cluster, node_group, {"name": node_group.name}
199+
)
200+
201+
annotations = md["metadata"]["annotations"]
202+
assert "capacity.cluster-autoscaler.kubernetes.io/ephemeral-disk" not in annotations
203+
# The other autoscaler hints must still be set so the autoscaler can
204+
# schedule on cpu/memory.
205+
assert annotations["capacity.cluster-autoscaler.kubernetes.io/cpu"] == "4"
206+
assert annotations["capacity.cluster-autoscaler.kubernetes.io/memory"] == "4G"
207+
208+
209+
def test_mutate_machine_deployment_vm_keeps_ephemeral_disk_annotation(context, mocker):
210+
cluster = utils.get_test_cluster(context, labels={})
211+
mocker.patch(
212+
"magnum_cluster_api.utils.get_default_boot_volume_size",
213+
side_effect=lambda cluster, default: default,
214+
)
215+
cluster.labels["auto_scaling_enabled"] = "true"
216+
node_group = utils.get_test_nodegroup(context, labels={})
217+
node_group.min_node_count = 1
218+
node_group.max_node_count = 3
219+
220+
mocker.patch("magnum_cluster_api.utils.lookup_image", return_value={"id": "foo"})
221+
mocker.patch(
222+
"magnum_cluster_api.utils.lookup_flavor",
223+
return_value=flavors.Flavor(
224+
None,
225+
{"name": "vm-flavor", "disk": 20, "ram": 1024, "vcpus": 1},
226+
),
227+
)
228+
229+
md = resources.mutate_machine_deployment(
230+
context, cluster, node_group, {"name": node_group.name}
231+
)
232+
233+
annotations = md["metadata"]["annotations"]
234+
assert (
235+
annotations["capacity.cluster-autoscaler.kubernetes.io/ephemeral-disk"] == "20"
236+
)

0 commit comments

Comments
 (0)