Postgres_GKE PR2-sysbench - Standalone PostgreSQL Sysbench benchmark on GKE#6563
Postgres_GKE PR2-sysbench - Standalone PostgreSQL Sysbench benchmark on GKE#6563manojcns wants to merge 7 commits into
Conversation
| ``` | ||
|
|
||
|
|
||
| ## HA (CloudNativePG) Tests |
There was a problem hiding this comment.
Again, please remove all HA references.
There was a problem hiding this comment.
Acknowledged, will update
| ``` | ||
|
|
||
| ### Architecture & Logic | ||
| 1. **Pod as VM Abstraction**: PKB's Kubernetes provider treats Kubernetes pods as Virtual Machines. When the benchmark runs, PKB provisions: |
There was a problem hiding this comment.
You mention "Pod as VM", but it looks like the code supports both that as well as k8s-native.
Is there a strong reason to support both? I'd prefer just the k8s-native way, since that's the way users would run a real workload.
There was a problem hiding this comment.
Acknowledged, will update code
| * **v1 (Infrastructure)**: Uses Container-Optimized OS (COS) for nodes and Ubuntu 24.04 for the client. | ||
| * **v2 (Startup)**: Uses Ubuntu node image and removes the init container for faster startup (at the cost of less robust permission handling). | ||
| * **v3 (Kernel)**: Applies sysctl tuning (`vm.swappiness=1`, `vm.dirty_ratio=10`, etc.) to the node. | ||
| * **v4 (HugePages)**: Enables HugePages (2MB) on the node and configures PostgreSQL (`huge_pages=on`) to use them. This reduces TLB misses and improves memory management efficiency. | ||
| * **v6 (Postgres Tuning)**: Applies aggressive PostgreSQL configuration tuning (e.g., `shared_buffers=35GB`, `effective_io_concurrency=200`, `max_worker_processes=32`). | ||
| * **v1+v6+v4 (All-in-One)**: Combines Infrastructure, Postgres Tuning, and HugePages for maximum performance. | ||
| * **v1+v6+v4+hostnetwork (HostNetwork Optimized)**: Extends the "All-in-One" profile by enabling Host Networking (`hostNetwork: true`) for the PostgreSQL pods. This bypasses the Kubernetes CNI/Overlay network stack, allowing the database to use the node's native network interface for maximum throughput and reduced latency. | ||
|
|
There was a problem hiding this comment.
Can the profiles be renamed using words instead of arbitrary numbers? It'd be easier to understand something like infra+hugepages+pg (or similar).
There was a problem hiding this comment.
Hey Hank, This can be done, would below work? Thanks
v1 -> infra-tuned (COS nodes + Ubuntu clients)
v2 -> fast-startup (No init container)
v3 -> kernel-tuned (Sysctl params)
v4 -> hugepages (HugePages on)
v6 -> postgres-tuned (Aggressive PG memory/worker tuning)
v1+v6 -> infra+postgres
v1+v6+v4 -> infra+postgres+hugepages
v1+v6+v4+hostnetwork -> infra+postgres+hugepages+hostnetwork
| requests: | ||
| cpu: "4" | ||
| memory: "10Gi" | ||
| limits: | ||
| cpu: "8" | ||
| memory: "20Gi" |
There was a problem hiding this comment.
I understand the original intent of this benchmark was very narrow in scope, but I think it'd be worthwhile to provide configurability so users can run the benchmark generically on other machine types, rather than being limited to the original ones tested.
There was a problem hiding this comment.
Acknowledged, let me review
| - name: PGUSER | ||
| value: benchmark | ||
| - name: PGPASSWORD | ||
| value: {{ password }} |
There was a problem hiding this comment.
Can a k8s secret be used instead? The client is exposing the password here to anyone that can kubectl describe pod.
There was a problem hiding this comment.
Acknowledged, let me review
There was a problem hiding this comment.
Is this used anywhere? Can it be removed? I see the node-config.yaml next, which is the preferred way of handling this setup.
|
|
||
| # Wait a bit for resources to be created | ||
| logging.info('Waiting 30 seconds for resources to be created...') | ||
| time.sleep(30) |
There was a problem hiding this comment.
Better to poll for availability with timeout than to sleep arbitrarily.
|
|
||
| # Give it more time to stabilize (important for large shared_buffers) | ||
| logging.info('Waiting 60 seconds for PostgreSQL to fully stabilize...') | ||
| time.sleep(60) |
There was a problem hiding this comment.
Is there a way to poll here instead of waiting?
908c8b2 to
a5ba694
Compare
|
@hankfreund - this PR is ready for re-review; please take a look when time permits |
hankfreund
left a comment
There was a problem hiding this comment.
Thanks Manoj! I'll ping the team to take a look.
|
|
||
| # PostgreSQL configuration flags | ||
| flags.DEFINE_string( | ||
| 'postgres_gke_shared_buffers', |
There was a problem hiding this comment.
could you just have 2 sets of defaults for baseline and optimized? This will limit the choices for the pkb users. See SHARED_BUFFERS_CONF in perfkitbenchmarker/linux_packages/postgresql.py.
| 'PostgreSQL shared_buffers size (baseline: 15GB, optimized: 35GB)', | ||
| ) | ||
| flags.DEFINE_integer( | ||
| 'postgres_gke_max_connections', 1000, 'PostgreSQL max_connections' |
There was a problem hiding this comment.
Just hard code into default if you do not plan to use other numbers as variables.
| ) | ||
| flags.DEFINE_string( | ||
| 'postgres_gke_effective_cache_size', | ||
| '30GB', |
| """ | ||
|
|
||
| # Machine type to disk type mapping | ||
| MACHINE_DISK_MAPPING = { |
There was a problem hiding this comment.
Pls do not add this mapping here.
This file should be cloud agnostic.
We usually manage this complexity at scheduling time.
|
|
||
| # Optimization profiles | ||
| # NOTE: These profile memory and CPU values are tuned for c4-standard-16 and n2-standard-16 only. | ||
| OPTIMIZATION_PROFILES = { |
There was a problem hiding this comment.
since you have this, why have the flags above?
| ]['GCP']['machine_type'] | ||
|
|
||
| # Calculate dynamic HugePages needed mapped to the architecture | ||
| machine_family = server_machine.split('-')[0] |
There was a problem hiding this comment.
we dont put gcp specific code in benchmark
| if machine_family in ['c4a', 'n4', 'n4a', 'n4d']: | ||
| node_mem_gb = node_cpus * 4.0 | ||
| elif machine_family == 'c4d': | ||
| node_mem_gb = node_cpus * 3.875 |
There was a problem hiding this comment.
I am not familiar with GKE, but can you pull the accessible memory using gke version of 'free -h'?
This is not maintainable.
| hugepage_mb = int(pod_mem_gb * 0.45) * 1024 | ||
| hugepage_size2m = int(hugepage_mb / 2) | ||
|
|
||
| import os |
There was a problem hiding this comment.
imports at top of file.
| if not machine_type: | ||
| machine_type = 'c4-standard-16' | ||
|
|
||
| parts = machine_type.split('-') |
There was a problem hiding this comment.
prefer you query from within the pod/node.
| ].vm_spec['GCP']['machine_type'] | ||
| except (KeyError, AttributeError): | ||
| # Default to c4-standard-16 if we can't find it | ||
| machine_type = 'c4-standard-16' |
There was a problem hiding this comment.
fail if you cannot find it
| vm_util.IssueCommand(cmd) | ||
|
|
||
| # 2. Delete the Client Pod | ||
| cmd = [ |
There was a problem hiding this comment.
Does the container cluster resource not clean this up automatically?
| ] | ||
| vm_util.IssueCommand(cmd) | ||
|
|
||
| # 3. Explicitly delete all PVCs to ensure disks are released |
There was a problem hiding this comment.
Does deleting the cluster not delete the pvcs?
… scrub HA/VM docs)
- Enforce profile-based tuning by removing granular config flags. - Deduplicate base PostgreSQL configurations across profiles. - Standardize storage using native PKB data_disk flags. - Replace hardcoded GCP machine mappings with dynamic K8s API queries. - Rely on PKB's native cluster lifecycle manager for teardown.
- Renamed 'postgres_sysbench_gke' to 'kubernetes_postgres_sysbench' to adhere to the official PKB naming convention for K8s benchmarks. - Updated module filename to kubernetes_postgres_sysbench_benchmark.py. - Updated BENCHMARK_NAME and BENCHMARK_CONFIG root keys internally. - Refactored module docstrings and markdown documentation to accurately reflect cloud-agnostic Kubernetes capability rather than being exclusively GKE-focused.
9d3ed13 to
b8ac5f5
Compare
Summary
This PR introduces standalone PostgreSQL Sysbench benchmark for GKE, enabling repeatable OLTP performance testing using Sysbench workloads against a single-instance PostgreSQL deployment on Kubernetes.
This is the second in a series of three PRs for GKE PostgreSQL benchmarking:
LoadBalancer endpoint refactor, additive Kubernetes cluster methods)
All new files. Zero modifications to existing benchmark modules.
Files Changed
1. [perfkitbenchmarker/linux_benchmarks/postgres_sysbench_gke_benchmark.py) (New)
hyperdisk-balanced,pd-ssd--system-config-from-fileon the GKE nodepool — existingbenchmarks that do not set
gke_node_system_configare completely unaffectedpostgres_gke_*— no collisions with existing flags2.
data/container/postgres_sysbench/(New — 2 manifest templates)postgres_all.yaml.j2: StatefulSet + Service + PVC for the Postgres server podclient_pod.yaml.j2: Sysbench client pod spec3.
docs/(New — 2 documentation files)GKE_PostgreSQL_Quickstart_generic.MD: Quickstart guide with example PKB commandsTechnical_Architecture_PostgreSQL_PKB.md: Architecture overviewBackward Compatibility
postgres_gke_*does not conflict with any existing PKB flags.hugepageskey is selected. Benchmarks not using this flag are unaffected.sysbench_benchmark.py(VM-based MySQL/Postgres) is not touched — the newbenchmark is GKE-only and independently implemented.