3939
4040Infrastructure lifecycle lives in two BaseResource subclasses:
4141
42- SwapNodePool (perfkitbenchmarker/resources/container_service/swap_nodepool.py)
4342 _Create(): gcloud container node-pools create with linuxConfig.swapConfig
4443 + sysctl via --system-config-from-file; waits for node Ready;
4544 optionally creates and attaches a dedicated swap disk.
9998from perfkitbenchmarker import vm_util
10099from perfkitbenchmarker .resources .container_service import kubectl
101100from perfkitbenchmarker .resources .container_service import swap_daemonset as _ds_mod
102- from perfkitbenchmarker .resources .container_service import swap_nodepool as _np_mod
103101
104102FLAGS = flags .FLAGS
105103
115113BENCHMARK_CONFIG = """
116114swap_encryption:
117115 description: >
118- GKE vs. EKS swap encryption and LSSD performance comparison.
119- Two-step nodepool setup: PKB provisions a minimal cluster with a cheap
120- default nodepool (Step 1), then Prepare() adds the real benchmark
121- nodepool (n4-highmem-32 / c4-*-lssd, UBUNTU_CONTAINERD, 80k IOPS) with a
122- node-level startup script that configures dm-crypt swap before any pod
123- is scheduled, then removes the default nodepool (Step 2). All benchmark
124- phases run inside a privileged DaemonSet pinned to the benchmark nodepool.
125- flags: {}
116+ fio microbenchmarks (Tier 1) on swap-encrypted GKE/EKS nodes. Swap-enabled 'benchmark' nodepool declared in BENCHMARK_CONFIG;
117+ GKE cluster creation applies --system-config-from-file (dm-crypt swapConfig)
118+ automatically via swap_config field on NodepoolSpec.
126119 container_cluster:
120+ cloud: GCP
127121 type: Kubernetes
128122 vm_count: 1
129123 vm_spec:
130124 GCP:
131- # Cheap placeholder — the benchmark nodepool is created in Prepare().
132125 machine_type: e2-medium
133126 boot_disk_size: 20
134- AWS:
135- # Cheap placeholder — the benchmark nodegroup is added in Prepare().
136- machine_type: t3.medium
137- boot_disk_size: 20
127+ zone: us-central1-a
128+ nodepools:
129+ benchmark:
130+ vm_count: 1
131+ vm_spec:
132+ GCP:
133+ machine_type: n4-highmem-32
134+ boot_disk_type: hyperdisk-balanced
135+ boot_disk_size: 500
136+ zone: us-central1-a
137+ swap_config:
138+ enabled: true
139+ swappiness: 100
140+ min_free_kbytes: 200
141+ watermark_scale_factor: 500
142+ boot_disk_iops: 160000
143+ boot_disk_throughput: 2400
138144"""
139145
140146
@@ -422,60 +428,20 @@ def GetConfig(user_config: dict[str, Any]) -> dict[str, Any]:
422428def Prepare (spec : _BenchmarkSpec ) -> None :
423429 """Two-step nodepool setup then DaemonSet deployment.
424430
425- Step 1 (handled by PKB infrastructure): cluster provisioned with a cheap
426- e2-medium default nodepool.
427-
428- Step 2 (this function):
429- a. GCP: Create SwapNodePool (benchmark nodepool + optional swap disk).
430- EKS: label existing nodes with pkb_nodepool=benchmark.
431- b. Create SwapDaemonSet: deploy manifest + wait for Running + sentinel.
432- c. GCP: DeleteDefaultPool() — safe now that DaemonSet pod is Running.
433- d. GCP: re-resolve pod name in case default-pool deletion evicts the pod.
431+ PKB cluster creation automatically provisions the swap-enabled 'benchmark'
432+ nodepool (swap_config in BENCHMARK_CONFIG). This function only:
433+ 1. Deploys the privileged SwapDaemonSet and waits for Running.
434+ 2. Deletes the cheap e2-medium default-pool (required at cluster create).
434435
435- Both resources are appended to spec.resources for auto-cleanup.
436+ DaemonSet is appended to spec.resources for PKB auto-cleanup.
436437 """
437438 cluster = spec .container_cluster
438- is_gcp = getattr (cluster , 'project' , None ) is not None
439-
440- if is_gcp :
441- # ── Step 2a (GCP): create benchmark nodepool + wait for node ──────────
442- logging .info ('[swap_encryption] Step 2a: creating benchmark nodepool' )
443- nodepool = _np_mod .SwapNodePool (
444- cluster = cluster ,
445- machine_type = _BENCHMARK_MACHINE_TYPE .value ,
446- node_image_type = _NODE_IMAGE_TYPE .value ,
447- disk_type = _BOOT_DISK_TYPE .value ,
448- disk_size_gb = _BOOT_DISK_SIZE_GB .value ,
449- disk_iops = _BOOT_DISK_IOPS .value ,
450- disk_throughput = _BOOT_DISK_THROUGHPUT .value ,
451- lssd = _BENCHMARK_LSSD .value ,
452- lssd_count = _LSSD_COUNT .value ,
453- add_swap_disk = _ADD_SWAP_DISK .value ,
454- swap_disk_size_gb = _SWAP_DISK_SIZE_GB .value ,
455- )
456- nodepool .Create ()
457- spec .resources .append (nodepool )
458- else :
459- # ── Step 2a (EKS): label existing nodes to match DaemonSet selector ──
460- logging .info (
461- '[swap_encryption] EKS cluster — labelling existing nodes with'
462- ' pkb_nodepool=%s so the DaemonSet nodeSelector matches.' ,
463- _BENCHMARK_NODEPOOL ,
464- )
465- kubectl .RunKubectlCommand ([
466- 'label' ,
467- 'nodes' ,
468- '--all' ,
469- '--overwrite' ,
470- f'pkb_nodepool={ _BENCHMARK_NODEPOOL } ' ,
471- ])
472- _ensure_io2_volume ()
473-
474- # ── Step 2b: deploy DaemonSet and wait for pod ────────────────────────────
475- # Deploy BEFORE deleting the default pool: deleting the default pool while
476- # the benchmark node is still joining causes a brief API-server I/O timeout.
477- # The pod being Running means the cluster is fully stable.
478- logging .info ('[swap_encryption] Step 2b: deploying privileged DaemonSet' )
439+
440+ # The swap-enabled 'benchmark' nodepool is already provisioned by GKE
441+ # cluster creation (swap_config declared in BENCHMARK_CONFIG).
442+ # Prepare() only deploys the privileged DaemonSet + deletes the cheap
443+ # e2-medium default pool that GKE requires at cluster creation time.
444+ logging .info ('[swap_encryption] Deploying privileged DaemonSet' )
479445 daemonset = _ds_mod .SwapDaemonSet (
480446 name = _DS_NAME ,
481447 namespace = _DS_NAMESPACE ,
@@ -485,28 +451,13 @@ def Prepare(spec: _BenchmarkSpec) -> None:
485451 )
486452 daemonset .Create ()
487453 spec .resources .append (daemonset )
454+ logging .info ('[swap_encryption] Benchmark pod ready: %s' , daemonset .pod_name )
455+ _delete_default_pool (cluster )
456+ daemonset .WaitForPod ()
488457 logging .info (
489- '[swap_encryption] Benchmark pod ready : %s' , daemonset .pod_name
458+ '[swap_encryption] Benchmark pod (post-deletion) : %s' , daemonset .pod_name
490459 )
491460
492- # ── Step 2c+d (GCP): delete dummy default nodepool, re-resolve pod name ──
493- if is_gcp :
494- logging .info (
495- '[swap_encryption] Step 2c: deleting dummy default nodepool'
496- )
497- nodepool .DeleteDefaultPool ()
498- # The pod may be evicted and rescheduled with a new name during the
499- # default nodepool deletion. Re-resolve to avoid stale references.
500- logging .info (
501- '[swap_encryption] Step 2d: re-resolving benchmark pod after'
502- ' nodepool deletion'
503- )
504- daemonset .WaitForPod ()
505- logging .info (
506- '[swap_encryption] Benchmark pod (post-deletion): %s' ,
507- daemonset .pod_name ,
508- )
509-
510461 # Tune kernel swap aggressiveness.
511462 daemonset .PodExec ('sysctl -w vm.swappiness=100' , ignore_failure = True )
512463 if _MIN_FREE_KBYTES .value > 0 :
@@ -706,6 +657,32 @@ def Run(spec: _BenchmarkSpec) -> list[sample.Sample]:
706657 return results
707658
708659
660+
661+ def _delete_default_pool (cluster ) -> None :
662+ """Delete the dummy e2-medium default-pool once the benchmark pod is Running.
663+
664+ GKE requires at least one nodepool at cluster creation time; the e2-medium
665+ default-pool satisfies that requirement. Deleting it before the DaemonSet
666+ pod is Running can trigger a brief API-server timeout while two concurrent
667+ nodepool operations are in progress.
668+ """
669+ try :
670+ cmd = cluster ._GcloudCommand ( # pylint: disable=protected-access
671+ 'container' , 'node-pools' , 'delete' , _DEFAULT_POOL ,
672+ '--cluster' , cluster .name ,
673+ )
674+ cmd .args .append ('--quiet' )
675+ logging .info ('[swap_encryption] Deleting default nodepool: %s' , _DEFAULT_POOL )
676+ _ , stderr , rc = cmd .Issue (timeout = 300 , raise_on_failure = False )
677+ if rc != 0 :
678+ logging .warning (
679+ '[swap_encryption] Could not delete default nodepool (rc=%d): %s' ,
680+ rc , stderr ,
681+ )
682+ else :
683+ logging .info ('[swap_encryption] Default nodepool deleted' )
684+ except Exception as e : # pylint: disable=broad-except
685+ logging .warning ('[swap_encryption] _delete_default_pool failed: %s' , e )
709686def Cleanup (spec : _BenchmarkSpec ) -> None :
710687 """Resources in spec.resources are auto-deleted by the PKB framework.
711688
0 commit comments