Skip to content

Commit 5a8ca3d

Browse files
p3rf Teamcopybara-github
authored andcommitted
Split out cluster from container_service/base.py
PiperOrigin-RevId: 856340104
1 parent dff53ab commit 5a8ca3d

File tree

3 files changed

+281
-263
lines changed

3 files changed

+281
-263
lines changed

perfkitbenchmarker/container_service/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,21 @@
2020
expanded to support first-class container benchmarks.
2121
"""
2222

23+
# Temporarily hoist container_class related classes into this namespace
24+
from perfkitbenchmarker.container_service.container_cluster import BaseContainerCluster
25+
from perfkitbenchmarker.container_service.container_cluster import DEFAULT_NODEPOOL
26+
from perfkitbenchmarker.container_service.container_cluster import GetContainerClusterClass
2327
# Temporarily hoist error related classes into this namespace
2428
from perfkitbenchmarker.container_service.errors import ContainerException
2529
from perfkitbenchmarker.container_service.errors import FatalContainerException
2630
from perfkitbenchmarker.container_service.errors import RetriableContainerException
2731
# Temporarily hoist base related classes into this namespace
2832
from .base import BaseContainer
29-
from .base import BaseContainerCluster
3033
from .base import BaseContainerRegistry
3134
from .base import BaseContainerService
3235
from .base import BaseNodePoolConfig
3336
from .base import ContainerImage
34-
from .base import DEFAULT_NODEPOOL
3537
from .base import FLAGS
36-
from .base import GetContainerClusterClass
3738
from .base import GetContainerRegistryClass
3839
from .base import KUBERNETES
3940
from .base import NodePoolName

perfkitbenchmarker/container_service/base.py

Lines changed: 1 addition & 260 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,13 @@
1313
# limitations under the License.
1414
"""Contains classes related to managed container services."""
1515

16-
import collections
17-
import itertools
1816
import os
1917
import time
20-
from typing import Any, Callable, Iterable
18+
from typing import Any
2119

2220
from absl import flags
2321
from perfkitbenchmarker import context
2422
from perfkitbenchmarker import data
25-
from perfkitbenchmarker import os_types
26-
from perfkitbenchmarker import provider_info
2723
from perfkitbenchmarker import resource
2824
from perfkitbenchmarker import sample
2925
from perfkitbenchmarker import virtual_machine
@@ -311,258 +307,3 @@ def __init__(self, vm_config: virtual_machine.BaseVirtualMachine, name: str):
311307
self.min_cpu_platform: str
312308
self.cpus: int
313309
self.memory_mib: int
314-
315-
316-
class BaseContainerCluster(resource.BaseResource):
317-
"""A cluster that can be used to schedule containers."""
318-
319-
RESOURCE_TYPE = 'BaseContainerCluster'
320-
REQUIRED_ATTRS = ['CLOUD', 'CLUSTER_TYPE']
321-
CLOUD: str
322-
CLUSTER_TYPE: str
323-
324-
def __init__(self, cluster_spec: container_spec_lib.ContainerClusterSpec):
325-
super().__init__(user_managed=bool(cluster_spec.static_cluster))
326-
self.name: str = cluster_spec.static_cluster or 'pkb-' + FLAGS.run_uri
327-
# Go get a BaseVM, to use strictly for config values.
328-
default_vm_class = virtual_machine.GetVmClass(
329-
self.CLOUD, os_types.DEFAULT, provider_info.DEFAULT_VM_PLATFORM
330-
)
331-
default_vm_config: virtual_machine.BaseVirtualMachine = default_vm_class(
332-
cluster_spec.vm_spec
333-
) # pytype: disable=not-instantiable
334-
self.default_nodepool = self._InitializeDefaultNodePool(
335-
cluster_spec, default_vm_config
336-
)
337-
self.nodepools: dict[str, BaseNodePoolConfig] = {}
338-
for name, nodepool_spec in cluster_spec.nodepools.copy().items():
339-
vm_config: virtual_machine.BaseVirtualMachine = default_vm_class(
340-
nodepool_spec.vm_spec
341-
) # pytype: disable=not-instantiable
342-
nodepool = self._InitializeNodePool(name, nodepool_spec, vm_config)
343-
self.nodepools[nodepool.name] = nodepool
344-
self.min_nodes: int = (
345-
cluster_spec.min_vm_count or self.default_nodepool.num_nodes
346-
)
347-
self.max_nodes: int = (
348-
cluster_spec.max_vm_count or self.default_nodepool.num_nodes
349-
)
350-
self.containers: dict[str, list[BaseContainer]] = collections.defaultdict(
351-
list
352-
)
353-
self.services: dict[str, BaseContainerService] = {}
354-
self._extra_samples: list[sample.Sample] = []
355-
self.container_registry: BaseContainerRegistry | None = None
356-
self.enable_vpa: bool = cluster_spec.enable_vpa
357-
358-
@property
359-
def num_nodes(self) -> int:
360-
return self.default_nodepool.num_nodes
361-
362-
@property
363-
def zone(self) -> str:
364-
return self.default_nodepool.zone
365-
366-
def SetContainerRegistry(self, container_registry):
367-
"""Sets the container registry for the cluster."""
368-
self.container_registry = container_registry
369-
370-
def _InitializeDefaultNodePool(
371-
self,
372-
cluster_spec: container_spec_lib.ContainerClusterSpec,
373-
vm_config: virtual_machine.BaseVirtualMachine,
374-
) -> BaseNodePoolConfig:
375-
nodepool_config = BaseNodePoolConfig(
376-
vm_config,
377-
DEFAULT_NODEPOOL,
378-
)
379-
nodepool_config.num_nodes = cluster_spec.vm_count
380-
self.InitializeNodePoolForCloud(vm_config, nodepool_config)
381-
return nodepool_config
382-
383-
def _InitializeNodePool(
384-
self,
385-
name: str,
386-
nodepool_spec: container_spec_lib.NodepoolSpec,
387-
vm_config: virtual_machine.BaseVirtualMachine,
388-
) -> BaseNodePoolConfig:
389-
zone = (
390-
nodepool_spec.vm_spec.zone
391-
if nodepool_spec.vm_spec
392-
else self.default_nodepool.zone
393-
)
394-
nodepool_config = BaseNodePoolConfig(
395-
vm_config,
396-
name,
397-
)
398-
nodepool_config.sandbox_config = nodepool_spec.sandbox_config
399-
nodepool_config.zone = zone
400-
nodepool_config.num_nodes = nodepool_spec.vm_count
401-
self.InitializeNodePoolForCloud(vm_config, nodepool_config)
402-
return nodepool_config
403-
404-
def InitializeNodePoolForCloud(
405-
self,
406-
vm_config: virtual_machine.BaseVirtualMachine,
407-
nodepool_config: BaseNodePoolConfig,
408-
):
409-
"""Override to initialize cloud specific configs."""
410-
pass
411-
412-
def GetNodePoolFromNodeName(
413-
self, node_name: str
414-
) -> BaseNodePoolConfig | None:
415-
"""Get the nodepool from the node name.
416-
417-
This method assumes that the nodepool name is embedded in the node name.
418-
Better would be a lookup from the cloud provider.
419-
420-
Args:
421-
node_name: The name of the node.
422-
423-
Returns:
424-
The associated nodepool, or None if not found.
425-
"""
426-
nodepool_names = self.nodepools.keys()
427-
found_pools = []
428-
if '-default-' in node_name:
429-
found_pools.append(self.default_nodepool)
430-
for pool_name in nodepool_names:
431-
if f'-{pool_name}-' in node_name:
432-
found_pools.append(self.nodepools[pool_name])
433-
if len(found_pools) == 1:
434-
return found_pools[0]
435-
if len(found_pools) > 1:
436-
raise ValueError(
437-
f'Multiple nodepools found for node with name {node_name}:'
438-
f' {found_pools}. Please change the name of the nodepools used to'
439-
' avoid this.'
440-
)
441-
return None
442-
443-
def GetMachineTypeFromNodeName(self, node_name: str) -> str | None:
444-
"""Get the machine type from the node name."""
445-
nodepool = self.GetNodePoolFromNodeName(node_name)
446-
if nodepool is None:
447-
return None
448-
return nodepool.machine_type
449-
450-
def DeleteContainers(self):
451-
"""Delete containers belonging to the cluster."""
452-
for container in itertools.chain(*list(self.containers.values())):
453-
container.Delete()
454-
455-
def DeleteServices(self):
456-
"""Delete services belonging to the cluster."""
457-
for service in self.services.values():
458-
service.Delete()
459-
460-
def GetResourceMetadata(self):
461-
"""Returns a dictionary of cluster metadata."""
462-
nodepools_metadata = {}
463-
for name, nodepool in self.nodepools.items():
464-
nodepool_metadata = {
465-
'size': nodepool.num_nodes,
466-
'machine_type': nodepool.machine_type,
467-
'name': name,
468-
}
469-
if nodepool.sandbox_config is not None:
470-
nodepool_metadata['sandbox_config'] = {
471-
'type': nodepool.sandbox_config.type,
472-
}
473-
nodepools_metadata[name] = nodepool_metadata
474-
475-
metadata = {
476-
'cloud': self.CLOUD,
477-
'cluster_type': self.CLUSTER_TYPE,
478-
'zone': self.default_nodepool.zone,
479-
'size': self.default_nodepool.num_nodes,
480-
'machine_type': self.default_nodepool.machine_type,
481-
'nodepools': nodepools_metadata,
482-
}
483-
484-
if (
485-
self.min_nodes != self.default_nodepool.num_nodes
486-
or self.max_nodes != self.default_nodepool.num_nodes
487-
):
488-
metadata.update({
489-
'max_size': self.max_nodes,
490-
'min_size': self.min_nodes,
491-
})
492-
493-
return metadata
494-
495-
def DeployContainer(self, name, container_spec):
496-
"""Deploys Containers according to the ContainerSpec."""
497-
raise NotImplementedError()
498-
499-
def DeployContainerService(self, name, container_spec):
500-
"""Deploys a ContainerSerivice according to the ContainerSpec."""
501-
raise NotImplementedError()
502-
503-
def AddSamples(self, samples: Iterable[sample.Sample]):
504-
self._extra_samples += samples
505-
506-
def GetSamples(self):
507-
"""Return samples with information about deployment times."""
508-
samples = super().GetSamples()
509-
for container in itertools.chain(*list(self.containers.values())):
510-
metadata = {'image': container.image.split('/')[-1]}
511-
if container.resource_ready_time and container.create_start_time:
512-
samples.append(
513-
sample.Sample(
514-
'Container Deployment Time',
515-
container.resource_ready_time - container.create_start_time,
516-
'seconds',
517-
metadata,
518-
)
519-
)
520-
if container.delete_end_time and container.delete_start_time:
521-
samples.append(
522-
sample.Sample(
523-
'Container Delete Time',
524-
container.delete_end_time - container.delete_start_time,
525-
'seconds',
526-
metadata,
527-
)
528-
)
529-
for service in self.services.values():
530-
metadata = {'image': service.image.split('/')[-1]}
531-
if service.resource_ready_time and service.create_start_time:
532-
samples.append(
533-
sample.Sample(
534-
'Service Deployment Time',
535-
service.resource_ready_time - service.create_start_time,
536-
'seconds',
537-
metadata,
538-
)
539-
)
540-
if service.delete_end_time and service.delete_start_time:
541-
samples.append(
542-
sample.Sample(
543-
'Service Delete Time',
544-
service.delete_end_time - service.delete_start_time,
545-
'seconds',
546-
metadata,
547-
)
548-
)
549-
550-
samples += self._extra_samples
551-
552-
return samples
553-
554-
def ResizeNodePool(self, new_size: int, node_pool: str = DEFAULT_NODEPOOL):
555-
"""Change the number of nodes in the node pool."""
556-
raise NotImplementedError
557-
558-
def GetNodePoolNames(self) -> list[str]:
559-
"""Get node pool names for the cluster."""
560-
raise NotImplementedError
561-
562-
563-
def GetContainerClusterClass(
564-
cloud: str, cluster_type: str
565-
) -> Callable[[container_spec_lib.ContainerClusterSpec], BaseContainerCluster]:
566-
return resource.GetResourceClass(
567-
BaseContainerCluster, CLOUD=cloud, CLUSTER_TYPE=cluster_type
568-
)

0 commit comments

Comments
 (0)