Skip to content

Commit 375b070

Browse files
committed
refactor(swap_encryption/pr4): thin benchmark using BaseResource pattern
- Prepare() uses SwapNodePool + SwapDaemonSet from spec.resources - Cleanup() is empty - PKB framework auto-deletes spec.resources - All _pod_exec(pod, ...) calls replaced with daemonset.PodExec(...) - DaemonSet: remove workload tools; separate PKB pods (r3457826290) - Remove cgroup v2 unlock hack (r3457928855) - Pre-fetch kernel source for Phase 3b - Fix COS_CONTAINERD -> UBUNTU_CONTAINERD (r3472549985)
1 parent 41d3cb1 commit 375b070

1 file changed

Lines changed: 62 additions & 85 deletions

File tree

perfkitbenchmarker/linux_benchmarks/swap_encryption_benchmark.py

Lines changed: 62 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
4040
Infrastructure 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.
@@ -88,7 +87,6 @@
8887
from perfkitbenchmarker import sample
8988
from perfkitbenchmarker.resources.container_service import kubectl
9089
from perfkitbenchmarker.resources.container_service import swap_daemonset as _ds_mod
91-
from perfkitbenchmarker.resources.container_service import swap_nodepool as _np_mod
9290

9391
FLAGS = flags.FLAGS
9492

@@ -105,26 +103,34 @@
105103
BENCHMARK_CONFIG = """
106104
swap_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]:
465471
def 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

554505
def 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)
716693
def Cleanup(spec: _BenchmarkSpec) -> None:
717694
"""Resources in spec.resources are auto-deleted by the PKB framework.
718695

0 commit comments

Comments
 (0)