Skip to content

Commit 2a4de67

Browse files
committed
eks: support nodepool labels and taints
Add _ParseTaint helper and update _RenderNodeGroupJson in BaseEksCluster to pass node_labels and node_taints through to eksctl's node group JSON. Taints are parsed from 'key=value:Effect' or 'key:Effect' strings into the dict format eksctl expects.
1 parent 3956dcd commit 2a4de67

5 files changed

Lines changed: 77 additions & 3 deletions

File tree

perfkitbenchmarker/configs/container_spec.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ def __init__(
243243
self.vm_spec: virtual_machine_spec.BaseVmSpec
244244
self.machine_families: list[str] | None
245245
self.sandbox_config: SandboxSpec | None
246+
self.node_labels: dict[str, str] | None
247+
self.node_taints: list[str] | None
246248

247249
@classmethod
248250
def _GetOptionDecoderConstructions(cls):
@@ -273,6 +275,14 @@ def _GetOptionDecoderConstructions(cls):
273275
),
274276
'vm_spec': (spec.PerCloudConfigDecoder, {}),
275277
'sandbox_config': (_SandboxDecoder, {'default': None}),
278+
'node_labels': (
279+
option_decoders.TypeVerifier,
280+
{'valid_types': (dict,), 'default': None, 'none_ok': True},
281+
),
282+
'node_taints': (
283+
option_decoders.TypeVerifier,
284+
{'valid_types': (list,), 'default': None, 'none_ok': True},
285+
),
276286
})
277287
return result
278288

perfkitbenchmarker/providers/aws/elastic_kubernetes_service.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,22 @@ def ApplyInferenceS3PvAndPvc() -> None:
101101
logging.info('Successfully applied S3 PVC.')
102102

103103

104+
def _ParseTaint(taint_str: str) -> dict[str, str]:
105+
"""Parses a taint string into eksctl's dict format.
106+
107+
Args:
108+
taint_str: Taint in 'key=value:Effect' or 'key:Effect' format.
109+
110+
Returns:
111+
Dict with 'key', 'value' (optional), and 'effect' keys for eksctl.
112+
"""
113+
key_value, effect = taint_str.rsplit(':', 1)
114+
if '=' in key_value:
115+
key, value = key_value.split('=', 1)
116+
return {'key': key, 'value': value, 'effect': effect}
117+
return {'key': key_value, 'effect': effect}
118+
119+
104120
class BaseEksCluster(kubernetes_cluster.KubernetesCluster):
105121
"""Shared base class for Elastic Kubernetes Service cluster auto mode & not."""
106122

@@ -195,16 +211,19 @@ def _RenderNodeGroupJson(
195211
self, nodepool: container.BaseNodePoolConfig
196212
) -> dict[str, Any]:
197213
"""Constructs the node group json dictionary."""
214+
labels = {'pkb_nodepool': nodepool.name}
215+
if nodepool.node_labels:
216+
labels.update(nodepool.node_labels)
198217
group_json = {
199218
'name': nodepool.name,
200219
'instanceType': nodepool.machine_type,
201220
'desiredCapacity': nodepool.num_nodes,
202221
'amiFamily': 'AmazonLinux2023',
203222
'tags': util.MakeDefaultTags(),
204-
'labels': {
205-
'pkb_nodepool': nodepool.name,
206-
},
223+
'labels': labels,
207224
}
225+
if nodepool.node_taints:
226+
group_json['taints'] = [_ParseTaint(t) for t in nodepool.node_taints]
208227
if nodepool.min_nodes != nodepool.max_nodes:
209228
group_json['minSize'] = nodepool.min_nodes
210229
group_json['maxSize'] = nodepool.max_nodes

perfkitbenchmarker/resources/container_service/container.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ def __init__(
184184
self.disk_size: int = vm_spec.boot_disk_size
185185
self.gpu_type: str | None = vm_spec.gpu_type
186186
self.gpu_count: int | None = vm_spec.gpu_count
187+
self.node_labels: dict[str, str] | None = None
188+
self.node_taints: list[str] | None = None
187189
# Defined by GceVirtualMachineConfig. Used by google_kubernetes_engine
188190
# pylint: disable=g-missing-from-attributes
189191
self.sandbox_config: container_spec_lib.SandboxSpec | None = None

perfkitbenchmarker/resources/container_service/container_cluster.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ def _InitializeNodePool(
116116
nodepool_spec.machine_families,
117117
)
118118
nodepool_config.sandbox_config = nodepool_spec.sandbox_config
119+
nodepool_config.node_labels = nodepool_spec.node_labels
120+
nodepool_config.node_taints = nodepool_spec.node_taints
119121
nodepool_config.zone = zone
120122
nodepool_config.num_nodes = nodepool_spec.vm_count
121123
if nodepool_spec.min_vm_count is None:

tests/providers/aws/elastic_kubernetes_service_test.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,47 @@ def testEksClusterNodepoolsAutoscaling(self):
237237
self.assertEqual(node_groups[1]['maxSize'], 10)
238238
self.assertEqual(node_groups[1]['desiredCapacity'], 3)
239239

240+
def testEksClusterNodepoolLabels(self):
241+
cluster = elastic_kubernetes_service.EksCluster(EKS_SPEC)
242+
nodepool = cluster.default_nodepool
243+
nodepool.node_labels = {'env': 'prod', 'team': 'ml'}
244+
actual = cluster._RenderNodeGroupJson(nodepool)
245+
self.assertEqual(
246+
actual['labels'],
247+
{'pkb_nodepool': nodepool.name, 'env': 'prod', 'team': 'ml'},
248+
)
249+
250+
def testEksClusterNodepoolTaints(self):
251+
cluster = elastic_kubernetes_service.EksCluster(EKS_SPEC)
252+
nodepool = cluster.default_nodepool
253+
nodepool.node_taints = [
254+
'sandbox.gke.io/runtime=runsc:NoSchedule',
255+
'dedicated:NoExecute',
256+
]
257+
actual = cluster._RenderNodeGroupJson(nodepool)
258+
self.assertEqual(
259+
actual['taints'],
260+
[
261+
{
262+
'key': 'sandbox.gke.io/runtime',
263+
'value': 'runsc',
264+
'effect': 'NoSchedule',
265+
},
266+
{'key': 'dedicated', 'effect': 'NoExecute'},
267+
],
268+
)
269+
270+
271+
def testParseTaint(self):
272+
self.assertEqual(
273+
elastic_kubernetes_service._ParseTaint('key=value:NoSchedule'),
274+
{'key': 'key', 'value': 'value', 'effect': 'NoSchedule'},
275+
)
276+
self.assertEqual(
277+
elastic_kubernetes_service._ParseTaint('dedicated:NoExecute'),
278+
{'key': 'dedicated', 'effect': 'NoExecute'},
279+
)
280+
240281
def testGetNodePoolNames(self):
241282
# Mock the output of the aws cli command
242283
cluster = elastic_kubernetes_service.EksCluster(EKS_SPEC)

0 commit comments

Comments
 (0)