diff --git a/experiments/google/compute-engine/cpu/retest/README.md b/experiments/google/compute-engine/cpu/retest/README.md new file mode 100644 index 000000000..5074d39b7 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/README.md @@ -0,0 +1,9 @@ +# Retest of Compute Engine + +> Size 32 + +We are trying to diagnose why there are differences in Compute Engine vs. GKE. So far we have identified two variables: + +- MTU: on GKE was set to 8896 (and used the underlying default 1460 for Compute Engine) +- Tier 1 "PREMIUM" was set for GKE but not for Compute Engine +- COMPACT we were never able to get for compute engine, at least greater than 10 instances. I can try again but not sure it will be different. diff --git a/experiments/google/compute-engine/cpu/retest/base/main.tf b/experiments/google/compute-engine/cpu/retest/base/main.tf new file mode 100644 index 000000000..64c4aeafd --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/base/main.tf @@ -0,0 +1,44 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +module "compute_nodes" { + source = "./modules/compute" + + for_each = { + for index, node in var.compute_node_specs: + node.name_prefix => node + } + project_id = var.project_id + region = var.region + + family = var.family + + name_prefix = each.value.name_prefix + subnetwork = var.subnetwork + machine_arch = each.value.machine_arch + machine_type = each.value.machine_type + num_instances = each.value.instances + + boot_script = lookup(each.value, "boot_script", null) + compact_placement = lookup(each.value, "compact", false) + gpu = lookup(each.value, "gpu_type", null) == null || lookup(each.value, "gpu_count", 0) <= 0 ? null : { + type = each.value.gpu_type + count = each.value.gpu_count + } + service_account = { + email = var.service_account_emails["compute"] + scopes = var.compute_scopes + } + nfs_mounts = var.cluster_storage +} diff --git a/experiments/google/compute-engine/cpu/retest/base/modules/compute/main.tf b/experiments/google/compute-engine/cpu/retest/base/modules/compute/main.tf new file mode 100644 index 000000000..c49678058 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/base/modules/compute/main.tf @@ -0,0 +1,91 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +data "google_compute_image" "fluxfw_compute_x86_64_image" { + project = var.project_id + family = var.family +} + +data "google_compute_zones" "available" { + project = var.project_id + region = var.region +} + +resource "google_compute_address" "ip_address" { + name = "external-ip" +} + +locals { + automatic_restart = var.compact_placement ? false : var.automatic_restart + compute_images = { + "x86-64" = { + image = data.google_compute_image.fluxfw_compute_x86_64_image.self_link + project = data.google_compute_image.fluxfw_compute_x86_64_image.project + } + } + on_host_maintenance = var.compact_placement ? "TERMINATE" : var.on_host_maintenance + access_config = { + nat_ip = google_compute_address.ip_address.address + network_tier = var.network_tier + } +} + +resource "google_compute_resource_policy" "collocated" { + count = var.compact_placement ? 1 : 0 + name = "${var.name_prefix}-collocated-policy" + project = var.project_id + region = var.region + group_placement_policy { + vm_count = var.num_instances + collocation = "COLLOCATED" + } +} + +module "flux_compute_instance_template" { + source = "github.com/terraform-google-modules/terraform-google-vm/modules/instance_template" + region = var.region + project_id = var.project_id + name_prefix = var.name_prefix + subnetwork = var.subnetwork + gpu = var.gpu + service_account = var.service_account + access_config = [local.access_config] + tags = ["ssh", "flux", "compute"] + machine_type = var.machine_type + disk_size_gb = 256 + source_image = local.compute_images["${var.machine_arch}"].image + source_image_project = local.compute_images["${var.machine_arch}"].project + automatic_restart = local.automatic_restart + on_host_maintenance = local.on_host_maintenance + startup_script = var.boot_script + + metadata = { + "enable-oslogin" : "TRUE", + "VmDnsSetting" : "GlobalDefault", + "nfs-mounts" : jsonencode(var.nfs_mounts), + "gpus-attached" : var.gpu != null ? "TRUE" : "FALSE" + } +} + +module "flux_compute_instances" { + source = "github.com/terraform-google-modules/terraform-google-vm/modules/compute_instance" + region = var.region + zone = data.google_compute_zones.available.names[0] + hostname = var.name_prefix + add_hostname_suffix = true + num_instances = var.num_instances + resource_policies = var.compact_placement ? [ google_compute_resource_policy.collocated[0].self_link ] : [] + instance_template = module.flux_compute_instance_template.self_link + subnetwork = var.subnetwork +} diff --git a/experiments/google/compute-engine/cpu/retest/base/modules/compute/variables.tf b/experiments/google/compute-engine/cpu/retest/base/modules/compute/variables.tf new file mode 100644 index 000000000..3ccaf9553 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/base/modules/compute/variables.tf @@ -0,0 +1,94 @@ +variable "automatic_restart" { + type = bool + description = "(Optional) Specifies whether the instance should be automatically restarted if it is terminated by Compute Engine (not terminated by a user)." + default = true +} + +variable "boot_script" { + description = "(Optional) the name of a file containing a script to be executed on compute nodes at boot time" + type = string + default = null +} + +variable "compact_placement" { + description = "(Optional) a boolean which determines whether a set of compute nodes has a compact placement resource policy attached to them." + type = bool + default = false +} + +variable "family" { + description = "The source X86 image family prefix to use" + type = string + default = "flux-framework" +} + +variable "gpu" { + description = "The type and count of GPU(s) to attach to a compute node" + type = object({ + type = string + count = number + }) + default = null +} + +variable "machine_arch" { + description = "The instruction set architecture, usually x86_64, used by the compute node" + type = string +} + +variable "network_tier" { + description = "The network tier (STANDARD or PREMIUM)" + type = string + default = "STANDARD" +} + +variable "machine_type" { + description = "The Compute Engine machine type to be used for the compute node" + type = string +} + +variable "name_prefix" { + description = "The name prefix for the compute node instances, the full instances names will be this prefix followed by a node number" + type = string +} + +variable "nfs_mounts" { + description = "A map with keys 'share' and 'mountpoint' describing an NFS export and its intended mount point" + type = map(string) + default = {} +} + +variable "num_instances" { + description = "The number of compute node instances to create" + type = number + default = 1 +} + +variable "on_host_maintenance" { + type = string + description = "Instance availability Policy" + default = "MIGRATE" +} + +variable "project_id" { + description = "The GCP project ID" + type = string +} + +variable "region" { + description = "The GCP region where the cluster resides" + type = string +} + +variable "service_account" { + description = "The GCP service account used by the compute node" + type = object({ + email = string + scopes = set(string) + }) +} + +variable "subnetwork" { + description = "Subnetwork to deploy to" + type = string +} diff --git a/experiments/google/compute-engine/cpu/retest/base/variables.tf b/experiments/google/compute-engine/cpu/retest/base/variables.tf new file mode 100644 index 000000000..93cf53d66 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/base/variables.tf @@ -0,0 +1,53 @@ + +variable "cluster_storage" { + description = "A map with keys 'share' and 'mountpoint' describing an NFS export and its intended mount point" + type = map(string) +} + +variable "family" { + description = "The source image x86 prefix to be used by the compute node(s)" + type = string + default = "global" +} + +variable "compute_node_specs" { + description = "A list of compute node specifications" + type = list(object({ + name_prefix = string + machine_arch = string + machine_type = string + gpu_type = string + gpu_count = number + compact = bool + instances = number + properties = set(string) + boot_script = string + })) + default = [] +} + +variable "compute_scopes" { + description = "The set of access scopes for compute node instances" + default = [ "cloud-platform" ] + type = set(string) +} + +variable "project_id" { + description = "The GCP project ID" + type = string +} + +variable "region" { + description = "The GCP region where the cluster resides" + type = string +} + +variable "service_account_emails" { + description = "A map with keys: 'compute', 'login', 'manager' that map to the service account to be used by the respective nodes" + type = map(string) +} + +variable "subnetwork" { + description = "Subnetwork to deploy to" + type = string +} diff --git a/experiments/google/compute-engine/cpu/retest/size32/README.md b/experiments/google/compute-engine/cpu/retest/size32/README.md new file mode 100644 index 000000000..083a6614d --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/README.md @@ -0,0 +1,362 @@ +# "Bare Metal" on Compute Engine Size 32 + +- Note: cannot get compact placement group + +## Experiment + +Shell in: + +```bash +gcloud compute ssh flux-001 --project=converged-computing --zone=us-central1-a --tunnel-through-iap +``` + +### 0. Pulling Containers + +The containers are already pulled and located in `/opt/containers`. Oras is also installed. + +```bash +cd /opt/containers +``` + +### 1. Applications + +Write this script to file that we can run incrementally to save output (that does not exist yet) + +```bash +#!/bin/bash +output=$1 + +# When they are done: +for jobid in $(flux jobs -a --json | jq -r .jobs[].id) + do + # Get the job study id + study_id=$(flux job info $jobid jobspec | jq -r ".attributes.user.study_id") + if [[ -f "$output/${study_id}-${jobid}.out" ]] || [[ "$study_id" == "null" ]]; then + continue + fi + echo "Parsing jobid ${jobid} and study id ${study_id}" + flux job attach $jobid &> $output/${study_id}-${jobid}.out + echo "START OF JOBSPEC" >> $output/${study_id}-${jobid}.out + flux job info $jobid jobspec >> $output/${study_id}-${jobid}.out + echo "START OF EVENTLOG" >> $output/${study_id}-${jobid}.out + flux job info $jobid guest.exec.eventlog >> $output/${study_id}-${jobid}.out +done +``` +```bash +# Results and save script to home! +mkdir -p ./results +chmod +x ./save.sh +``` + +For each experiment, we need to be instance owner. This also cleans up `flux jobs -a` so you get a clean slate. + +```bash +flux alloc -N +flux alloc -N 32 +``` + +You'll need to login to oras just once: + +```bash +oras login ghcr.io --username vsoch +``` + +#### Single Node Benchmark + +Need to pull an updated container + +```bash +singularity pull docker://ghcr.io/converged-computing/metric-single-node:cpu-zen4-tmpfile +``` + +Here is a modified entrypoint: + +```console +export app=single-node +output=./results/$app +mkdir -p $output + +for node in $(seq 1 9); do + flux submit -N1 --requires="hosts:flux-00${node}" --setattr=user.study_id=$app-node-00${node} singularity exec /home/sochat1_llnl_gov/metric-single-node_cpu-zen4-tmpfile.sif /bin/bash /entrypoint.sh +done +for node in $(seq 10 32); do + flux submit -N1 --requires="hosts:flux-0${node}" --setattr=user.study_id=$app-node-00${node} singularity exec /home/sochat1_llnl_gov/metric-single-node_cpu-zen4-tmpfile.sif /bin/bash /entrypoint.sh +done + +./save.sh $output +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +#### AMG2023 + +This one requires sourcing spack, so we need to write a little wrapper for it. + +```bash +#!/bin/bash +# run_amg.sh +. /etc/profile.d/z10_spack_environment.sh +$@ +``` +```bash +# No need to share the file - the filesystem is shared +chmod +x run_amg.sh +``` + +```console +export app=amg2023 +export output=results/$app +mkdir -p $output + +for i in $(seq 1 5); do + echo "Running iteration $i" + time flux run --env OMP_NUM_THREADS=2 --env OMPI_MCA_btl_vader_single_copy_mechanism=none --setattr=user.study_id=$app-32-iter-$i -N 32 -n 896 -o cpu-affinity=per-task singularity exec /opt/containers/metric-amg2023_rocky8-cpu-int64-zen3.sif /bin/bash /home/sochat1_llnl_gov/run_amg.sh amg -n 256 256 128 -P 7 8 16 -problem 2 +done + +# When they are done: +./save.sh $output +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +#### Kripke + +```console +export app=kripke +export output=results/$app +mkdir -p $output + +for i in $(seq 1 5); do + echo "Running iteration $i" + flux submit --env OMP_NUM_THREADS=1 --env OMPI_MCA_btl_vader_single_copy_mechanism=none --setattr=user.study_id=$app-32-iter-$i -N 32 -n 1792 singularity exec /opt/containers/metric-kripke-cpu_rocky-8.sif kripke --layout DGZ --dset 16 --zones 448,168,256 --gset 16 --groups 16 --niter 500 --legendre 2 --quad 16 --procs 8,14,16 +done + +./save.sh $output +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +#### Laghos + +```console +export app=laghos-7-threads +export output=results/$app +mkdir -p $output + +# Killed at 17 minutes - would go until 50 minutes +for i in $(seq 1 1); do + echo "Running iteration $i" + time flux run --env OMP_NUM_THREADS=7 --cores-per-task=7 --exclusive -o cpu-affinity=per-task --setattr=user.study_id=$app-32-iter-$i -N 32 -n 256 --env OMPI_MCA_btl_vader_single_copy_mechanism=none /opt/containers/metric-laghos_rocky-8.sif /opt/laghos/laghos -pa -p 1 -tf 0.6 -pt 311 -m /opt/laghos/data/cube_311_hex.mesh --ode-solver 7 --max-steps 400 --cg-tol 0 -cgm 50 -ok 3 -ot 2 -rs 4 -rp 2 --fom +done +./save.sh $output +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +#### LAMMPS-REAX + +```console +export app=lammps-reax +export output=results/$app +mkdir -p $output + +# Lammps data needs to be copied from first container +singularity shell /opt/containers/metric-lammps-cpu_zen4-reax.sif +cp -R /code /home/sochat1_llnl_gov/lammps-data +exit +cd /home/sochat1_llnl_gov/lammps-data + +for i in $(seq 1 5); do + echo "Running iteration $i" + time flux run --setattr=user.study_id=$app-32-iter-$i --env OMPI_MCA_btl_vader_single_copy_mechanism=none -o cpu-affinity=per-task -N32 -n 1792 singularity exec /opt/containers/metric-lammps-cpu_rocky-8.sif /usr/bin/lmp -v x 64 -v y 64 -v z 32 -in in.reaxff.hns -nocite +done + +# When they are done: +./save.sh $output +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +#### MiniFE + +```bash +# 8.4 seconds +time flux run -N2 -o cpu-affinity=per-task singularity exec --env OMPI_MCA_btl_vader_single_copy_mechanism=none /opt/containers/metric-minife_rocky-8.sif miniFE.x nx=230 ny=230 nz=230 use_locking=1 elem_group_size=10 use_elem_mat_fields=300 verify_solution=0 + +# the larger problem size segfaults here, it gives a message about running out of memory, but could be only having two nodes. +``` + +```console +export app=minife +export output=results/$app +mkdir -p $output + +i=1 +time flux run --setattr=user.study_id=$app-32-iter-$i -N32 -n 1792 -o cpu-affinity=per-task singularity exec --env OMPI_MCA_btl_vader_single_copy_mechanism=none /opt/containers/metric-minife_rocky-8.sif miniFE.x nx=230 ny=230 nz=230 use_locking=1 elem_group_size=10 use_elem_mat_fields=300 verify_solution=0 + +for i in $(seq 1 5); do + echo "Running iteration $i" + time flux run --setattr=user.study_id=$app-32-iter-$i -N32 -n 1792 -o cpu-affinity=per-task singularity exec --env OMPI_MCA_btl_vader_single_copy_mechanism=none /opt/containers/metric-minife_rocky-8.sif miniFE.x nx=230 ny=230 nz=230 use_locking=1 elem_group_size=10 use_elem_mat_fields=300 verify_solution=0 +done + +# Note that minife outputs more result files!! +mkdir -p $output/miniFe +mv miniFE* $output/miniFe +# When they are done: +./save.sh $output + +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +#### Mixbench + +```bash +flux proxy local:///mnt/flux/view/run/flux/local bash +``` + +```console +export app=mixbench +export output=results/$app +mkdir -p $output + +for i in $(seq 1 5); do + echo "Running iteration $i" + time flux run --setattr=user.study_id=$app-$size-iter-$i -l -N2 singularity exec --env OMPI_MCA_btl_vader_single_copy_mechanism=none /opt/containers/metric-mixbench_cpu.sif mixbench-cpu 32 +done + +# When they are done: +./save.sh $output + +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +#### Mt-Gemm + +```console +export app=mt-gemm +export output=results/$app +mkdir -p $output + +for i in $(seq 1 5); do + echo "Running iteration $i" + time flux run --setattr=user.study_id=$app-32-iter-$i -N32 -n 1792 --env OMPI_MCA_btl_vader_single_copy_mechanism=none -o cpu-affinity=per-task singularity exec /opt/containers/mt-gemm_rocky-8.sif /opt/dense_linear_algebra/gemm/mpi/build/1_dense_gemm_mpi +done + +./save.sh $output +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +#### OSU + +Write this script to the filesystem `flux-run-combinations.sh` + +```bash +#/bin/bash + +nodes=$1 +app=$2 + +# At most 28 combinations, 8 nodes 2 at a time +hosts=$(flux run -N $1 hostname | shuf -n 8 | tr '\n' ' ') +list=${hosts} + +dequeue_from_list() { + shift; + list=$@ +} + +iter=0 +for i in $hosts; do + dequeue_from_list $list + for j in $list; do + echo "${i} ${j}" + time flux run -N 2 -n 2 \ + --env OMPI_MCA_btl_vader_single_copy_mechanism=none \ + --setattr=user.study_id=$app-2-iter-$iter \ + --requires="hosts:${i},${j}" \ + -o cpu-affinity=per-task \ + singularity exec /opt/containers/metric-osu-cpu_rocky-8.sif /opt/osu-benchmark/build.openmpi/mpi/pt2pt/osu_latency + time flux run -N 2 -n 2 \ + --env OMPI_MCA_btl_vader_single_copy_mechanism=none \ + --setattr=user.study_id=$app-2-iter-$iter \ + --requires="hosts:${i},${j}" \ + -o cpu-affinity=per-task \ + singularity exec /opt/containers/metric-osu-cpu_rocky-8.sif /opt/osu-benchmark/build.openmpi/mpi/pt2pt/osu_bw + iter=$((iter+1)) + done +done +``` + +And then run as follows. + +```console +export app=osu +export output=results/$app +mkdir -p $output + +./flux-run-combinations.sh 32 $app + +for i in $(seq 1 5); do + echo "Running iteration $i" + time flux run --setattr=user.study_id=$app-32-iter-$i -N32 -n 1792 --env OMPI_MCA_btl_vader_single_copy_mechanism=none -o cpu-affinity=per-task singularity exec /opt/containers/metric-osu-cpu_rocky-8.sif /opt/osu-benchmark/build.openmpi/mpi/collective/osu_allreduce +done + +# When they are done: +./save.sh $output +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +#### Quicksilver + +```console +export app=quicksilver +export output=results/$app +mkdir -p $output + +for i in $(seq 1 5); do + echo "Running iteration $i" + time flux run --cores-per-task=7 --exclusive --env OMP_NUM_THREADS=7 --setattr=user.study_id=$app-32-iter-$i -N32 -n 256 singularity exec /opt/containers/metric-quicksilver-cpu_rocky-8.sif qs --inputFile /opt/quicksilver/Examples/CORAL2_Benchmark/Problem1/Coral2_P1.inp -X 64 -Y 64 -Z 64 -x 64 -y 64 -z 64 -I 8 -J 8 -K 4 -n 83886080 +done + +# When they are done: +./save.sh $output + +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +#### Stream + +```console +export app=stream +export output=results/$app +mkdir -p $output + +for i in $(seq 1 5); do + echo "Running iteration $i" + for node in $(seq 1 9); do + flux submit --env OMPI_MCA_btl_vader_single_copy_mechanism=none --exclusive --requires="hosts:flux-00${node}" --setattr=user.study_id=$app-1-iter-$i-node-$node -N1 -n 56 -o cpu-affinity=per-task singularity exec /opt/containers/metric-stream_rocky-8.sif stream_c.exe + done + for node in $(seq 10 32); do + flux submit --env OMPI_MCA_btl_vader_single_copy_mechanism=none --exclusive --requires="hosts:flux-0${node}" --setattr=user.study_id=$app-1-iter-$i-node-$node -N1 -n 56 -o cpu-affinity=per-task singularity exec /opt/containers/metric-stream_rocky-8.sif stream_c.exe + done +done + +# When they are done: +./save.sh $output + +oras push ghcr.io/converged-computing/metrics-operator-experiments/performance:compute-engine-cpu-32-$app $output +``` + +### Clean up + +When you are done, exit and: + +```bash +export GOOGLE_PROJECT=myproject +make destroy +``` + +```console +for tag in $(oras repo tags ghcr.io/converged-computing/metrics-operator-experiments/performance) + do + if [[ $tag == *"compute-engine-cpu-32"* ]]; then + echo $tag + oras pull ghcr.io/converged-computing/metrics-operator-experiments/performance:$tag + fi + done +``` diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/Makefile b/experiments/google/compute-engine/cpu/retest/size32/tf/Makefile new file mode 100644 index 000000000..a9cf753b2 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/Makefile @@ -0,0 +1,29 @@ +.PHONY: all +all: init fmt validate deploy + +.PHONY: init +init: + terraform init + +.PHONY: fmt +fmt: + terraform fmt + +.PHONY: validate +validate: + terraform validate + +.PHONY: template +template: + cp ./scripts/boot_script.sh ./boot_script_generated.sh + sed -i "s/NODELIST/${NODELIST}/g" ./boot_script_generated.sh + +.PHONY: deploy +deploy: + export GOOGLE_PROJECT=$(gcloud config get-value core/project) + terraform apply -var-file basic.tfvars -var region=us-central1 -var project_id=$(gcloud config get-value core/project) -var network_name=foundation-net -var zone=us-central1-a + +.PHONY: destroy +destroy: + export GOOGLE_PROJECT=$(gcloud config get-value core/project) + terraform destroy -var-file basic.tfvars -var region=us-central1 -var project_id=$(gcloud config get-value core/project) -var network_name=foundation-net -var zone=us-central1-a diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/README.md b/experiments/google/compute-engine/cpu/retest/size32/tf/README.md new file mode 100644 index 000000000..7dcbaa293 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/README.md @@ -0,0 +1,122 @@ +# Flux Framework on GCP (size 32) + +This deployment illustrates deploying a flux-framework cluster on GCP. +We use one single image base and configure via a bootscript. + +# Usage + +## Build images + +Make note that the machine types should be compatible with those you chose in [build-images](../../build-images) +First, edit variables in [basic.tfvars](basic.tfvars). + +## Curve Cert + +We will need a shared curve certificate for the nodes. We provide an example [curve.cert](curve.cert), +however you can (and should) generate one on your own for cases that go beyond testing. You can do this +with a flux container: + +```bash +docker run -it fluxrm/flux-sched:jammy bash +flux keygen curve.cert +``` + +Then copy the file locally, and later we are going to encode it into our boot script. + +## Bootscript Template + +> Note that we have a template provided if you don't want to customize defaults. + +Set variables for your nodelist and curve certificate (and check they are good): +Make the generated script with your NODEDLIST: + +```bash +make template NODELIST='flux-[001-003]' +``` + +Then base64 encode your curve cert and copy paste it into the variable `CURVECERT`. +Note that this can work in a programming language but bash does weird things with +the unexpected characters. + +``` +curve=$(cat curve.cert | base64) +$ echo $curve +``` + +Finally (sorry I know this is annoying) copy the entire bootscript into the +variable in [basic.tfvars](basic.tfvars). + +## Deploy + +Initialize the deployment with the command: + +```bash +$ terraform init +``` + +I find it's easiest to export my Google project in the environment for any terraform configs +that mysteriously need it. + +```bash +export GOOGLE_PROJECT=$(gcloud config get-value core/project) +``` + +You'll want to inspect basic.tfvars and change for your use case. Then: + +```bash +$ make +``` + +And inspect the [Makefile](Makefile) to see the terraform commands we apply +to init, format, validate, and deploy. The deploy will setup networking and all the instances! Note that +you can change any of the `-var` values to be appropriate for your environment. +Verify that the cluster is up. You can shell into any compute node. + +```bash +gcloud compute ssh gffw-compute-a-001 --zone us-central1-a +``` + +You can check the startup scripts to make sure that everything finished. + +```bash +sudo journalctl -u google-startup-scripts.service +``` + +And then you should be able to interact with Flux! + +```bash +$ flux resource list + STATE NNODES NCORES NODELIST + free 3 12 gffw-compute-a-[001-003] + allocated 0 0 + down 0 0 +``` +```bash +$ flux run --cwd /tmp -N 2 hostname +gffw-compute-a-001 +gffw-compute-a-002 +``` + +And when you are done, exit and: + +```bash +$ make destroy +``` + +## Advanced + +### Adding Buckets + +You'll first want to make your buckets! Edit the script [mkbuckets.sh](scripts/mkbuckets.sh) +to your needs. E.g.,: + + - If the bucket already exists, comment out the creation command for it + +You'll want to run the script and provide the name of your main bucket (e.g., +the one with some data to mount): + +```bash +$ ./mkbuckets.sh flux-operator-bucket +``` + +And then add the logic from [fuse-mounts.sh](scripts/fuse-mounts.sh) to your boot script. diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/basic.tfvars b/experiments/google/compute-engine/cpu/retest/size32/tf/basic.tfvars new file mode 100644 index 000000000..d01d8c67f --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/basic.tfvars @@ -0,0 +1,194 @@ +compute_family = "flux-framework" +compute_node_specs = [ + { + name_prefix = "flux" + machine_arch = "x86-64" + network_tier = "PREMIUM" # TIER 1 + machine_type = "c2d-standard-112" + gpu_type = null + gpu_count = 0 + compact = false + # TODO change back to 32, this is testing only + instances = 2 + properties = [] + boot_script = <> /etc/sudoers +printf "flux user identifiers:\n$(id flux)\n" + +export STATE_DIR=/var/lib/flux +mkdir -p /var/lib/flux +mkdir -p /usr/etc/flux/system/conf.d + +# --cores=IDS Assign cores with IDS to each rank in R, so we assign 0-(N-1) to each host +echo "flux R encode --hosts=flux-[001-032]" +flux R encode --hosts=flux-[001-032] --local > /usr/etc/flux/system/R +printf "\n📦 Resources\n" +cat /usr/etc/flux/system/R + +mkdir -p /etc/flux/imp/conf.d/ +cat <> /etc/flux/imp/conf.d/imp.toml +[exec] +allowed-users = [ "flux", "root" ] +allowed-shells = [ "/usr/libexec/flux/flux-shell" ] +EOT + +printf "\n🦊 Independent Minister of Privilege\n" +cat /etc/flux/imp/conf.d/imp.toml + +cat <> /tmp/system.toml +[exec] +imp = "/usr/libexec/flux/flux-imp" + +[access] +allow-guest-user = true +allow-root-owner = true + +[bootstrap] +curve_cert = "/usr/etc/flux/system/curve.cert" + +default_port = 8050 +default_bind = "tcp://eth0:%p" +default_connect = "tcp://%h:%p" + +hosts = [{host="flux-[001-032]"}] + +# Speed up detection of crashed network peers (system default is around 20m) +[tbon] +tcp_user_timeout = "2m" + +# Point to resource definition generated with flux-R(1). +# Uncomment to exclude nodes (e.g. mgmt, login), from eligibility to run jobs. +[resource] +path = "/usr/etc/flux/system/R" + +# Remove inactive jobs from the KVS after one week. +[job-manager] +inactive-age-limit = "7d" +EOT + +mv /tmp/system.toml /usr/etc/flux/system/conf.d/system.toml + +echo "🐸 Broker Configuration" +cat /usr/etc/flux/system/conf.d/system.toml + +# If we are communicating via the flux uri this service needs to be started +chmod u+s /usr/libexec/flux/flux-imp +chmod 4755 /usr/libexec/flux/flux-imp +chmod 0644 /etc/flux/imp/conf.d/imp.toml +# sudo chown -R flux:flux /usr/etc/flux/system/conf.d + +cat << "PYTHON_DECODING_SCRIPT" > /tmp/convert_curve_cert.py +#!/usr/bin/env python3 +import sys +import base64 + +string = sys.argv[1] +dest = sys.argv[2] +with open(dest, 'w') as fd: + fd.write(base64.b64decode(string).decode('utf-8')) +PYTHON_DECODING_SCRIPT + +python3 /tmp/convert_curve_cert.py "IyAgICoqKiogIEdlbmVyYXRlZCBvbiAyMDIzLTA3LTE2IDIwOjM5OjIxIGJ5IENaTVEgICoqKioK +IyAgIFplcm9NUSBDVVJWRSAqKlNlY3JldCoqIENlcnRpZmljYXRlCiMgICBETyBOT1QgUFJPVklE +RSBUSElTIEZJTEUgVE8gT1RIRVIgVVNFUlMgbm9yIGNoYW5nZSBpdHMgcGVybWlzc2lvbnMuCgpt +ZXRhZGF0YQogICAgbmFtZSA9ICJlODZhMTM1MWZiY2YiCiAgICBrZXlnZW4uY3ptcS12ZXJzaW9u +ID0gIjQuMi4wIgogICAga2V5Z2VuLnNvZGl1bS12ZXJzaW9uID0gIjEuMC4xOCIKICAgIGtleWdl +bi5mbHV4LWNvcmUtdmVyc2lvbiA9ICIwLjUxLjAtMTM1LWdiMjA0NjBhNmUiCiAgICBrZXlnZW4u +aG9zdG5hbWUgPSAiZTg2YTEzNTFmYmNmIgogICAga2V5Z2VuLnRpbWUgPSAiMjAyMy0wNy0xNlQy +MDozOToyMSIKICAgIGtleWdlbi51c2VyaWQgPSAiMTAwMiIKICAgIGtleWdlbi56bXEtdmVyc2lv +biA9ICI0LjMuMiIKY3VydmUKICAgIHB1YmxpYy1rZXkgPSAidVEmXnkrcDo3XndPUUQ8OkldLShL +RDkjbVo2I0wmeSlZTGUzTXBOMSIKICAgIHNlY3JldC1rZXkgPSAiVkUjQHBKKXgtRUE/WntrS1cx +ZWY9dTw+WCpOR2hKJjUqallNRSUjQCIKCg==" /tmp/curve.cert + +mv /tmp/curve.cert /usr/etc/flux/system/curve.cert +chmod u=r,g=,o= /usr/etc/flux/system/curve.cert +chown flux:flux /usr/etc/flux/system/curve.cert +# /usr/sbin/create-munge-key +service munge start + +# The rundir needs to be created first, and owned by user flux +# Along with the state directory and curve certificate +mkdir -p /run/flux +sudo chown -R flux:flux /run/flux + +# Remove group and other read +chmod o-r /usr/etc/flux/system/curve.cert +chmod g-r /usr/etc/flux/system/curve.cert +chown -R $fluxuid /run/flux /var/lib/flux /usr/etc/flux/system/curve.cert + +printf "\n✨ Curve certificate generated by helper pod\n" +cat /usr/etc/flux/system/curve.cert + +mkdir -p /etc/flux/manager + +cat << "FIRST_BOOT_UNIT" > /etc/systemd/system/flux-start.service +[Unit] +Description=Flux message broker +Wants=munge.service + +[Service] +Type=simple +NotifyAccess=main +TimeoutStopSec=90 +KillMode=mixed +ExecStart=/usr/bin/flux start --broker-opts --config /usr/etc/flux/system/conf.d -Stbon.fanout=256 -Srundir=/run/flux -Sbroker.rc2_none -Sstatedir=/var/lib/flux -Slocal-uri=local:///run/flux/local -Stbon.connect_timeout=5s -Stbon.zmqdebug=1 -Slog-stderr-level=7 -Slog-stderr-mode=local +SyslogIdentifier=flux +DefaultLimitMEMLOCK=infinity +LimitMEMLOCK=infinity +TasksMax=infinity +LimitNPROC=infinity +Restart=always +RestartSec=5s +RestartPreventExitStatus=42 +SuccessExitStatus=42 +User=flux +Group=flux +PermissionsStartOnly=true +Delegate=yes + +[Install] +WantedBy=multi-user.target +FIRST_BOOT_UNIT + +systemctl enable flux-start.service +systemctl start flux-start.service + +# This enables NFS +nfsmounts=$(curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/nfs-mounts" -H "Metadata-Flavor: Google") + +if [[ "X$nfsmounts" != "X" ]]; then + echo "Enabling NFS mounts" + share=$(echo $nfsmounts | jq -r '.share') + mountpoint=$(echo $nfsmounts | jq -r '.mountpoint') + + bash -c "sudo echo $share $mountpoint nfs defaults,hard,intr,_netdev 0 0 >> /etc/fstab" + mount -a +fi +BOOT_SCRIPT + + }, +] +compute_scopes = ["cloud-platform"] diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/curve.cert b/experiments/google/compute-engine/cpu/retest/size32/tf/curve.cert new file mode 100644 index 000000000..4d2bbbcb7 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/curve.cert @@ -0,0 +1,14 @@ +# ZeroMQ CURVE **Secret** Certificate +# DO NOT DISTRIBUTE + +metadata + name = "d9c849c04c59" + keygen.flux-core-version = "0.64.0-119-g29a916970" + keygen.hostname = "d9c849c04c59" + keygen.time = "2024-08-19T14:34:18" + keygen.userid = "1002" + keygen.zmq-version = "4.3.4" +curve + public-key = "P}N@Y/C$Z}]D!gDU?gCpcKYHdh2uLIzKE" + secret-key = "NtJfyEEcfmEMY@e4!3L)98FQXP!5(0v&TvlOOG%s" + diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/foundation.tf b/experiments/google/compute-engine/cpu/retest/size32/tf/foundation.tf new file mode 100644 index 000000000..5e1e82559 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/foundation.tf @@ -0,0 +1,136 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +locals { + subnet = "${var.region}/${var.network_name}-subnet-01" +} + +data "google_compute_default_service_account" "default" { + project = var.project_id +} + +data "google_compute_image" "rocky8" { + project = "rocky-linux-cloud" + family = "rocky-linux-8-optimized-gcp" +} + +module "network" { + source = "github.com/terraform-google-modules/terraform-google-network" + project_id = var.project_id + network_name = var.network_name + mtu = var.mtu + subnets = [ + { + subnet_name = "${var.network_name}-subnet-01" + subnet_ip = var.subnet_ip + subnet_region = var.region + } + ] +} + +module "nat" { + source = "github.com/terraform-google-modules/terraform-google-cloud-nat" + project_id = var.project_id + region = var.region + network = module.network.network_name + create_router = true + router = "${module.network.network_name}-router" +} + +module "firewall" { + source = "github.com/terraform-google-modules/terraform-google-network/modules/firewall-rules" + project_id = var.project_id + network_name = module.network.network_name + rules = [ + { + name = "${var.network_name}-allow-ssh" + direction = "INGRESS" + priority = null + description = null + ranges = ["0.0.0.0/0"] + source_tags = null + source_service_accounts = null + target_tags = ["flux"] + target_service_accounts = null + allow = [ + { + protocol = "tcp" + ports = ["22"] + } + ], + deny = [] + log_config = { + metadata = "INCLUDE_ALL_METADATA" + } + }, + { + name = "${var.network_name}-allow-interal-traffic" + direction = "INGRESS" + priority = null + description = null + ranges = ["0.0.0.0/0"] + source_tags = null + source_service_accounts = null + target_tags = ["ssh", "flux"] + target_service_accounts = null + allow = [ + { + protocol = "icmp" + ports = [] + }, + { + protocol = "udp" + ports = ["0-65535"] + }, + { + protocol = "tcp" + ports = ["0-65535"] + } + ] + deny = [] + log_config = { + metadata = "INCLUDE_ALL_METADATA" + } + } + ] +} + +module "nfs_server_instance_template" { + source = "github.com/terraform-google-modules/terraform-google-vm/modules/instance_template" + region = var.region + project_id = var.project_id + name_prefix = var.nfs_prefix + subnetwork = module.network.subnets["${var.region}/${var.network_name}-subnet-01"].self_link + tags = ["ssh", "flux", "nfs"] + machine_type = "e2-standard-4" + disk_size_gb = var.nfs_size + source_image = data.google_compute_image.rocky8.self_link + source_image_project = data.google_compute_image.rocky8.project + service_account = { + email = data.google_compute_default_service_account.default.email + scopes = ["cloud-platform"] + } + startup_script = file("${path.module}/scripts/install_nfs.sh") +} + +module "nfs_server_instance" { + source = "github.com/terraform-google-modules/terraform-google-vm/modules/compute_instance" + region = var.region + zone = var.zone + hostname = var.nfs_prefix + add_hostname_suffix = true + num_instances = 1 + instance_template = module.nfs_server_instance_template.self_link + subnetwork = module.network.subnets["${var.region}/${var.network_name}-subnet-01"].self_link +} diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/main.tf b/experiments/google/compute-engine/cpu/retest/size32/tf/main.tf new file mode 100644 index 000000000..83b0192d0 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/main.tf @@ -0,0 +1,34 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +module "cluster" { + source = "../../base" + project_id = var.project_id + region = var.region + + service_account_emails = { + manager = data.google_compute_default_service_account.default.email + login = data.google_compute_default_service_account.default.email + compute = data.google_compute_default_service_account.default.email + } + + subnetwork = module.network.subnets_self_links[0] + cluster_storage = { + mountpoint = "/home" + share = "${module.nfs_server_instance.instances_details.0.network_interface.0.network_ip}:/var/nfs/home" + } + compute_node_specs = var.compute_node_specs + compute_scopes = var.compute_scopes + family = var.compute_family +} diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/boot_script.sh b/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/boot_script.sh new file mode 100644 index 000000000..a9781585e --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/boot_script.sh @@ -0,0 +1,173 @@ +#!/bin/sh + +set -eEu -o pipefail + +# This is already built into the image +fluxuser=flux +fluxuid=$(id -u $fluxuser) + +# IMPORTANT - this needs to match the local cluster +fluxroot=/usr + +echo "Flux username: $fluxuser" +echo "Flux install root: $fluxroot" +export fluxroot + +# Prepare NFS +dnf install nfs-utils -y + +mkdir -p /var/nfs/home +chown nobody:nobody /var/nfs/home + +ip_addr=$(hostname -I) + +echo "/var/nfs/home *(rw,no_subtree_check,no_root_squash)" >> /etc/exports + +firewall-cmd --add-service={nfs,nfs3,mountd,rpc-bind} --permanent +firewall-cmd --reload + +systemctl enable --now nfs-server rpcbind + +# TODO we can allow custom logic here if needed + +echo "$fluxuser ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers +printf "$fluxuser user identifiers:\n$(id $fluxuser)\n" + +export STATE_DIR=/var/lib/flux +mkdir -p ${STATE_DIR} +mkdir -p $fluxroot/etc/flux/system/conf.d + +# --cores=IDS Assign cores with IDS to each rank in R, so we assign 0-(N-1) to each host +echo "flux R encode --hosts=NODELIST" +flux R encode --hosts=NODELIST --local > $fluxroot/etc/flux/system/R +printf "\n📦 Resources\n" +cat $fluxroot/etc/flux/system/R + +mkdir -p /etc/flux/imp/conf.d/ +cat <> /etc/flux/imp/conf.d/imp.toml +[exec] +allowed-users = [ "$fluxuser", "root" ] +allowed-shells = [ "$fluxroot/libexec/flux/flux-shell" ] +EOT + +printf "\n🦊 Independent Minister of Privilege\n" +cat /etc/flux/imp/conf.d/imp.toml + +cat <> /tmp/system.toml +[exec] +imp = "$fluxroot/libexec/flux/flux-imp" + +# Allow users other than the instance owner (guests) to connect to Flux +# Optionally, root may be given "owner privileges" for convenience +[access] +allow-guest-user = true +allow-root-owner = true + +# Point to shared network certificate generated flux-keygen(1). +# Define the network endpoints for Flux's tree based overlay network +# and inform Flux of the hostnames that will start flux-broker(1). +[bootstrap] +curve_cert = "$fluxroot/etc/flux/system/curve.cert" + +default_port = 8050 +default_bind = "tcp://eth0:%p" +default_connect = "tcp://%h:%p" + +hosts = [{host="NODELIST"}] + +# Speed up detection of crashed network peers (system default is around 20m) +[tbon] +tcp_user_timeout = "2m" + +# Point to resource definition generated with flux-R(1). +# Uncomment to exclude nodes (e.g. mgmt, login), from eligibility to run jobs. +[resource] +path = "$fluxroot/etc/flux/system/R" + +# Remove inactive jobs from the KVS after one week. +[job-manager] +inactive-age-limit = "7d" +EOT + +mv /tmp/system.toml $fluxroot/etc/flux/system/conf.d/system.toml + +echo "🐸 Broker Configuration" +cat $fluxroot/etc/flux/system/conf.d/system.toml + +# If we are communicating via the flux uri this service needs to be started +chmod u+s $fluxroot/libexec/flux/flux-imp +chmod 4755 $fluxroot/libexec/flux/flux-imp +chmod 0644 /etc/flux/imp/conf.d/imp.toml +# sudo chown -R $fluxuser:$fluxuser $fluxroot/etc/flux/system/conf.d + +cat << "PYTHON_DECODING_SCRIPT" > /tmp/convert_curve_cert.py +#!/usr/bin/env python3 +import sys +import base64 + +string = sys.argv[1] +dest = sys.argv[2] +with open(dest, 'w') as fd: + fd.write(base64.b64decode(string).decode('utf-8')) +PYTHON_DECODING_SCRIPT + +python3 /tmp/convert_curve_cert.py "CURVECERT" /tmp/curve.cert + +mv /tmp/curve.cert $fluxroot/etc/flux/system/curve.cert +chmod u=r,g=,o= $fluxroot/etc/flux/system/curve.cert +chown $fluxuser:$fluxuser $fluxroot/etc/flux/system/curve.cert +# munge.key gets shipped with image, needs to be same / shared +# /usr/sbin/create-munge-key +service munge start + +# The rundir needs to be created first, and owned by user flux +# Along with the state directory and curve certificate +mkdir -p /run/flux +sudo chown -R $fluxuser:$fluxuser /run/flux + +# Remove group and other read +chmod o-r $fluxroot/etc/flux/system/curve.cert +chmod g-r $fluxroot/etc/flux/system/curve.cert +chown -R $fluxuid /run/flux ${STATE_DIR} $fluxroot/etc/flux/system/curve.cert + +printf "\n✨ Curve certificate generated by helper pod\n" +cat $fluxroot/etc/flux/system/curve.cert + +cat << "FIRST_BOOT_UNIT" > /etc/systemd/system/flux-start.service +[Unit] +Description=Flux message broker +Wants=munge.service + +[Service] +Type=simple +NotifyAccess=main +TimeoutStopSec=90 +KillMode=mixed +ExecStart=/usr/bin/flux start --broker-opts --config /usr/etc/flux/system/conf.d -Stbon.fanout=256 -Srundir=/run/flux -Sbroker.rc2_none -Sstatedir=/var/lib/flux -Slocal-uri=local:///run/flux/local -Stbon.connect_timeout=5s -Stbon.zmqdebug=1 -Slog-stderr-level=7 -Slog-stderr-mode=local +SyslogIdentifier=flux +Restart=always +RestartSec=5s +RestartPreventExitStatus=42 +SuccessExitStatus=42 +User=flux +Group=flux +PermissionsStartOnly=true +Delegate=yes + +[Install] +WantedBy=multi-user.target +FIRST_BOOT_UNIT + +# This enables NFS +nfsmounts=$(curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/nfs-mounts" -H "Metadata-Flavor: Google") + +if [[ "X${nfsmounts}" != "X" ]]; then + share=$(echo $nfsmounts | jq -r '.share') + mountpoint=$(echo $nfsmounts | jq -r '.mountpoint') + + bash -c "sudo echo ${share} ${mountpoint} nfs defaults,hard,intr,_netdev 0 0 >> /etc/fstab" + mount -a +fi + +systemctl enable flux-start.service +systemctl start flux-start.service diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/fuse-mounts.sh b/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/fuse-mounts.sh new file mode 100644 index 000000000..00caa904b --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/fuse-mounts.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# --implicit-dirs is only needed if you have existing nested files you want to see +mkdir /mnt/workflow +gcsfuse -o ro,allow_other --implicit-dirs flux-operator-bucket /mnt/workflow + +mkdir /mnt/variables +gcsfuse -o rw,allow_other --implicit-dirs llnl-flux_variables /mnt/variables diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/install_nfs.sh b/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/install_nfs.sh new file mode 100644 index 000000000..4032a3824 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/install_nfs.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +dnf install nfs-utils -y + +mkdir -p /var/nfs/home +chown nobody:nobody /var/nfs/home + +ip_addr=$(hostname -I) + +echo "/var/nfs/home *(rw,no_subtree_check,no_root_squash)" >> /etc/exports + +firewall-cmd --add-service={nfs,nfs3,mountd,rpc-bind} --permanent +firewall-cmd --reload + +systemctl enable --now nfs-server rpcbind diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/mkbuckets.sh b/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/mkbuckets.sh new file mode 100755 index 000000000..1c02bb7ad --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/scripts/mkbuckets.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +project_id="$(gcloud config get-value core/project)" +main_bucket="${1}" +variables_bucket="${project_id}_variables" + +if [[ "${main_bucket}" == "" ]]; then + echo "Please provide the name of your main bucket as the first input." + exit +fi + +gcloud storage buckets create gs://${main_bucket} || echo "${main_bucket} already exists?" +gcloud storage buckets create gs://${variables_bucket} || echo "${variables_bucket} already exists?" + +gcloud storage cp ./main.tf gs://${main_bucket} +gcloud storage cp ./variables.tf gs://${variables_bucket} + +# --implicit-dirs is only needed if you have existing nested files you want to see +cat << EOF > ./fuse-mounts.sh +#!/bin/bash + +mkdir /mnt/workflow +gcsfuse -o ro,allow_other --implicit-dirs ${main_bucket} /mnt/workflow + +mkdir /mnt/variables +gcsfuse -o rw,allow_other --implicit-dirs ${variables_bucket} /mnt/variables +EOF diff --git a/experiments/google/compute-engine/cpu/retest/size32/tf/variables.tf b/experiments/google/compute-engine/cpu/retest/size32/tf/variables.tf new file mode 100644 index 000000000..c0373b135 --- /dev/null +++ b/experiments/google/compute-engine/cpu/retest/size32/tf/variables.tf @@ -0,0 +1,87 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +variable "compute_node_specs" { + description = "A list of compute node specifications" + type = list(object({ + name_prefix = string + machine_arch = string + machine_type = string + gpu_type = string + gpu_count = number + compact = bool + instances = number + properties = set(string) + boot_script = string + })) + default = [] +} + +variable "compute_scopes" { + description = "The set of access scopes for compute node instances" + default = ["cloud-platform"] + type = set(string) +} + +variable "mtu" { + type = number + default = 8896 +} + +variable "network_name" { + type = string +} + +variable "nfs_prefix" { + type = string + default = "nfs" +} + +variable "nfs_size" { + type = number + default = 512 +} + +variable "project_id" { + description = "The GCP project ID" + type = string +} + + +variable "region" { + description = "The GCP region where the cluster resides" + type = string +} + +variable "ssh_source_ranges" { + description = "List of CIDR ranges from which SSH connections are accepted" + type = list(string) + default = ["0.0.0.0/0"] +} + +variable "subnet_ip" { + description = "CIDR for the network subnet" + type = string + default = "10.10.0.0/18" +} + +variable "zone" { + type = string +} + +variable "compute_family" { + description = "The source image x86 prefix to be used by the compute node(s)" + type = string + default = "flux-framework" +}