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.
8887from perfkitbenchmarker import sample
8988from perfkitbenchmarker .resources .container_service import kubectl
9089from perfkitbenchmarker .resources .container_service import swap_daemonset as _ds_mod
91- from perfkitbenchmarker .resources .container_service import swap_nodepool as _np_mod
9290
9391FLAGS = flags .FLAGS
9492
105103BENCHMARK_CONFIG = """
106104swap_encryption:
107105 description: >
108- GKE vs. EKS swap encryption and LSSD performance comparison.
109- Two-step nodepool setup: PKB provisions a minimal cluster with a cheap
110- default nodepool (Step 1), then Prepare() adds the real benchmark
111- nodepool (n4-highmem-32 / c4-*-lssd, UBUNTU_CONTAINERD, 80k IOPS) with a
112- node-level startup script that configures dm-crypt swap before any pod
113- is scheduled, then removes the default nodepool (Step 2). All benchmark
114- phases run inside a privileged DaemonSet pinned to the benchmark nodepool.
115- flags: {}
106+ CPU/IO overhead benchmarks (Tier 2) on swap-encrypted GKE/EKS nodes. Swap-enabled 'benchmark' nodepool declared in BENCHMARK_CONFIG;
107+ GKE cluster creation applies --system-config-from-file (dm-crypt swapConfig)
108+ automatically via swap_config field on NodepoolSpec.
116109 container_cluster:
110+ cloud: GCP
117111 type: Kubernetes
118112 vm_count: 1
119113 vm_spec:
120114 GCP:
121- # Cheap placeholder — the benchmark nodepool is created in Prepare().
122115 machine_type: e2-medium
123116 boot_disk_size: 20
124- AWS:
125- # Cheap placeholder — the benchmark nodegroup is added in Prepare().
126- machine_type: t3.medium
127- boot_disk_size: 20
117+ zone: us-central1-a
118+ nodepools:
119+ benchmark:
120+ vm_count: 1
121+ vm_spec:
122+ GCP:
123+ machine_type: n4-highmem-32
124+ boot_disk_type: hyperdisk-balanced
125+ boot_disk_size: 500
126+ zone: us-central1-a
127+ swap_config:
128+ enabled: true
129+ swappiness: 100
130+ min_free_kbytes: 200
131+ watermark_scale_factor: 500
132+ boot_disk_iops: 160000
133+ boot_disk_throughput: 2400
128134"""
129135
130136
@@ -465,60 +471,20 @@ def GetConfig(user_config: dict[str, Any]) -> dict[str, Any]:
465471def Prepare (spec : _BenchmarkSpec ) -> None :
466472 """Two-step nodepool setup then DaemonSet deployment.
467473
468- Step 1 (handled by PKB infrastructure): cluster provisioned with a cheap
469- e2-medium default nodepool.
470-
471- Step 2 (this function):
472- a. GCP: Create SwapNodePool (benchmark nodepool + optional swap disk).
473- EKS: label existing nodes with pkb_nodepool=benchmark.
474- b. Create SwapDaemonSet: deploy manifest + wait for Running + sentinel.
475- c. GCP: DeleteDefaultPool() — safe now that DaemonSet pod is Running.
476- d. GCP: re-resolve pod name in case default-pool deletion evicts the pod.
474+ PKB cluster creation automatically provisions the swap-enabled 'benchmark'
475+ nodepool (swap_config in BENCHMARK_CONFIG). This function only:
476+ 1. Deploys the privileged SwapDaemonSet and waits for Running.
477+ 2. Deletes the cheap e2-medium default-pool (required at cluster create).
477478
478- Both resources are appended to spec.resources for auto-cleanup.
479+ DaemonSet is appended to spec.resources for PKB auto-cleanup.
479480 """
480481 cluster = spec .container_cluster
481- is_gcp = getattr (cluster , 'project' , None ) is not None
482-
483- if is_gcp :
484- # ── Step 2a (GCP): create benchmark nodepool + wait for node ──────────
485- logging .info ('[swap_encryption] Step 2a: creating benchmark nodepool' )
486- nodepool = _np_mod .SwapNodePool (
487- cluster = cluster ,
488- machine_type = _BENCHMARK_MACHINE_TYPE .value ,
489- node_image_type = _NODE_IMAGE_TYPE .value ,
490- disk_type = _BOOT_DISK_TYPE .value ,
491- disk_size_gb = _BOOT_DISK_SIZE_GB .value ,
492- disk_iops = _BOOT_DISK_IOPS .value ,
493- disk_throughput = _BOOT_DISK_THROUGHPUT .value ,
494- lssd = _BENCHMARK_LSSD .value ,
495- lssd_count = _LSSD_COUNT .value ,
496- add_swap_disk = _ADD_SWAP_DISK .value ,
497- swap_disk_size_gb = _SWAP_DISK_SIZE_GB .value ,
498- )
499- nodepool .Create ()
500- spec .resources .append (nodepool )
501- else :
502- # ── Step 2a (EKS): label existing nodes to match DaemonSet selector ──
503- logging .info (
504- '[swap_encryption] EKS cluster — labelling existing nodes with'
505- ' pkb_nodepool=%s so the DaemonSet nodeSelector matches.' ,
506- _BENCHMARK_NODEPOOL ,
507- )
508- kubectl .RunKubectlCommand ([
509- 'label' ,
510- 'nodes' ,
511- '--all' ,
512- '--overwrite' ,
513- f'pkb_nodepool={ _BENCHMARK_NODEPOOL } ' ,
514- ])
515- _ensure_io2_volume ()
516-
517- # ── Step 2b: deploy DaemonSet and wait for pod ────────────────────────────
518- # Deploy BEFORE deleting the default pool: deleting the default pool while
519- # the benchmark node is still joining causes a brief API-server I/O timeout.
520- # The pod being Running means the cluster is fully stable.
521- logging .info ('[swap_encryption] Step 2b: deploying privileged DaemonSet' )
482+
483+ # The swap-enabled 'benchmark' nodepool is already provisioned by GKE
484+ # cluster creation (swap_config declared in BENCHMARK_CONFIG).
485+ # Prepare() only deploys the privileged DaemonSet + deletes the cheap
486+ # e2-medium default pool that GKE requires at cluster creation time.
487+ logging .info ('[swap_encryption] Deploying privileged DaemonSet' )
522488 daemonset = _ds_mod .SwapDaemonSet (
523489 name = _DS_NAME ,
524490 namespace = _DS_NAMESPACE ,
@@ -528,28 +494,13 @@ def Prepare(spec: _BenchmarkSpec) -> None:
528494 )
529495 daemonset .Create ()
530496 spec .resources .append (daemonset )
497+ logging .info ('[swap_encryption] Benchmark pod ready: %s' , daemonset .pod_name )
498+ _delete_default_pool (cluster )
499+ daemonset .WaitForPod ()
531500 logging .info (
532- '[swap_encryption] Benchmark pod ready : %s' , daemonset .pod_name
501+ '[swap_encryption] Benchmark pod (post-deletion) : %s' , daemonset .pod_name
533502 )
534503
535- # ── Step 2c+d (GCP): delete dummy default nodepool, re-resolve pod name ──
536- if is_gcp :
537- logging .info (
538- '[swap_encryption] Step 2c: deleting dummy default nodepool'
539- )
540- nodepool .DeleteDefaultPool ()
541- # The pod may be evicted and rescheduled with a new name during the
542- # default nodepool deletion. Re-resolve to avoid stale references.
543- logging .info (
544- '[swap_encryption] Step 2d: re-resolving benchmark pod after'
545- ' nodepool deletion'
546- )
547- daemonset .WaitForPod ()
548- logging .info (
549- '[swap_encryption] Benchmark pod (post-deletion): %s' ,
550- daemonset .pod_name ,
551- )
552-
553504
554505def Run (spec : _BenchmarkSpec ) -> list [sample .Sample ]:
555506 """Execute all benchmark phases with gate logic.
@@ -713,6 +664,32 @@ def Run(spec: _BenchmarkSpec) -> list[sample.Sample]:
713664 return results
714665
715666
667+
668+ def _delete_default_pool (cluster ) -> None :
669+ """Delete the dummy e2-medium default-pool once the benchmark pod is Running.
670+
671+ GKE requires at least one nodepool at cluster creation time; the e2-medium
672+ default-pool satisfies that requirement. Deleting it before the DaemonSet
673+ pod is Running can trigger a brief API-server timeout while two concurrent
674+ nodepool operations are in progress.
675+ """
676+ try :
677+ cmd = cluster ._GcloudCommand ( # pylint: disable=protected-access
678+ 'container' , 'node-pools' , 'delete' , _DEFAULT_POOL ,
679+ '--cluster' , cluster .name ,
680+ )
681+ cmd .args .append ('--quiet' )
682+ logging .info ('[swap_encryption] Deleting default nodepool: %s' , _DEFAULT_POOL )
683+ _ , stderr , rc = cmd .Issue (timeout = 300 , raise_on_failure = False )
684+ if rc != 0 :
685+ logging .warning (
686+ '[swap_encryption] Could not delete default nodepool (rc=%d): %s' ,
687+ rc , stderr ,
688+ )
689+ else :
690+ logging .info ('[swap_encryption] Default nodepool deleted' )
691+ except Exception as e : # pylint: disable=broad-except
692+ logging .warning ('[swap_encryption] _delete_default_pool failed: %s' , e )
716693def Cleanup (spec : _BenchmarkSpec ) -> None :
717694 """Resources in spec.resources are auto-deleted by the PKB framework.
718695
0 commit comments