To start working with Terraform and AWS resources, you’ll need to set up an AWS account and configure administrative permissions. Follow the steps below:
- Go to the AWS Sign-Up Page and create a new AWS account.
- Complete the registration form with your details and payment information. Once registered, you can log in to the AWS Console.
-
Log into AWS Console
Once logged in, navigate to the AWS Management Console. -
Access IAM
In the console, search for "IAM" in the search bar at the top and select IAM under Services. -
Create an Admin User
- In the left sidebar under Access Management, click Users.
- Click Add User and enter a username (e.g.,
Admin). - For AWS Management Console access, select Provide user access to the AWS Management Console.
- Set a password preference (either autogenerated or custom).
-
Assign Administrator Permissions
- In the Permissions step, select Attach policies directly.
- Find and check the box for the AdministratorAccess policy. This grants full access to AWS services, which is required for setting up resources via Terraform.
-
Review and Create User
- Click Next through the remaining steps to Review and create the user.
- Download the credentials file containing the Access Key ID and Secret Access Key. Store this file securely as it will be required to sign in and authenticate for Terraform operations.
To monitor costs and usage within your account:
- In the AWS Console, go to Billing and Cost Management from the Account menu (top-right corner).
- Enable billing and cost management access if prompted, which allows you to view detailed usage statistics and avoid unexpected expenses.
Note: Use the Admin IAM user you created for logging in and managing resources rather than the root account for better security and access control.
MacOS Users:
- Open Terminal on your Mac.
Windows Users:
- Open Command Prompt or PowerShell on your Windows computer.
-
Navigate to the Desired Directory:
Use thecdcommand to navigate to the directory where you want to set up the project.- Example command:
cd Documents
- Example command:
-
Create a New Directory:
Create a folder to store your Terraform code by usingmkdir.- Example command:
mkdir rev-parallel-cluster
- Example command:
-
Move into the New Directory:
Change into the newly created project folder.- Example command:
cd rev-parallel-cluster
- Example command:
-
Clone the Project Repository:
Usegitto clone the project repository and get the necessary code files.- Example command:
git clone https://github.com/switchbox-data/rev-parallel-cluster.git
- Example command:
-
Install AWS CLI using Homebrew:
brew install awscli
-
Configure AWS CLI with your credentials:
aws configure
Follow the prompts to enter your Access Key ID, Secret Access Key, Region, and Output Format.
- Download the AWS CLI installer from the official site and run it.
- After installation, open a terminal (PowerShell or Command Prompt) and run:
Follow the prompts to set up your Access Key ID, Secret Access Key, Region, and Output Format.
aws configure
-
Install Terraform using Homebrew:
brew install terraform
-
Verify the installation:
terraform -version
- Download Terraform from the official site.
- Extract the Terraform executable and add it to your PATH:
- Open System Properties > Environment Variables > Path and add the folder containing
terraform.exe.
- Open System Properties > Environment Variables > Path and add the folder containing
- Verify the installation:
terraform -version
Once both tools are installed, navigate to your project directory:
cd rev-parallel-cluster/-
Open your project in an Editor/IDE:
Open therev-parallel-clusterdirectory in your preferred text editor or IDE. -
Create a
terraform.tfvarsfile:
In therev-parallel-clusterdirectory, create a file namedterraform.tfvarsto define the necessary Terraform variables.
Generate a new SSH key pair:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"Add the following variable definitions in your terraform.tfvars file:
terraform_state_s3_bucket_name = "<insert-bucket-name-here>"
subnet_id = "<insert-public-subnet-id-here>"
parallel_cluster_api_stack_name = "ParallelCluster"
parallel_cluster_api_stack_version = "3.10.0"
region = "us-west-2"
sns_alert_emails = ["<insert-emails-here>"]
spending_alert_threshold = <insert-spending-alert-threshold> # spending limit for alerts
monthly_spend_limit = <insert-monthly-spend-limit>
post_install_scripts_bucket_name = "<insert-bucket-name-post-install>"
output_files_bucket_name = "<insert-output-files-bucket-name>"-
terraform_state_s3_bucket_name:- Purpose: Stores the Terraform state file, which keeps track of the current state of your infrastructure.
- Explanation: This bucket name must be unique because S3 bucket names are globally unique across AWS. Storing the Terraform state in S3 allows multiple team members or systems to access and maintain the infrastructure’s state consistently.
- Creation Command:
terraform-state-storage-$(uuidgen | tr '[:upper:]' '[:lower:]')
-
subnet_id:- Purpose: Specifies the public subnet where the ParallelCluster and its resources, like EC2 instances, will be deployed.
- Explanation: This should be a subnet ID in the
us-west-2aavailability zone (or the relevant zone you’re using). The subnet must have internet access for resources that need to communicate externally. In the AWS Console, go to VPC > Subnets to find an existing subnet or create a new one if necessary.
-
parallel_cluster_api_stack_name:- Purpose: Defines the name for the AWS CloudFormation stack that deploys the ParallelCluster API.
- Explanation: This stack handles the API layer for managing the ParallelCluster. Naming it makes it easy to locate in AWS CloudFormation and ensures it won’t conflict with other stacks. You can leave this as "ParallelCluster" or change it if needed.
-
parallel_cluster_api_stack_version:- Purpose: Specifies the version of ParallelCluster you want to use.
- Explanation: Make sure the version you specify is compatible with any other configurations or dependencies you have. Using the latest stable version (like 3.10.0 here) is recommended unless you need a specific version for compatibility.
-
region:- Purpose: Sets the AWS region where all resources, including the ParallelCluster, will be deployed.
- Explanation: Ensure that this matches the region where your resources (like S3 buckets, subnets, etc.) reside. Here,
us-west-2is used, but this can be any region depending on where your data and operations are centered.
-
sns_alert_emails:- Purpose: A list of email addresses that will receive alerts if the cluster usage exceeds the defined spending limits.
- Explanation: This should include any email addresses of stakeholders who need to monitor budget usage. AWS Simple Notification Service (SNS) will use this to send alert emails. Add valid email addresses in a list format, for example:
sns_alert_emails = ["admin@example.com", "finance@example.com"]
-
spending_alert_threshold:- Purpose: The spending limit that triggers alerts, measured in USD.
- Explanation: Once the threshold is met, an alert will be sent to the emails in
sns_alert_emails. Set this to a realistic amount based on expected usage patterns, for example:spending_alert_threshold = 500
-
monthly_spend_limit:- Purpose: Sets the monthly spending limit for the entire ParallelCluster setup.
- Explanation: If the total usage cost exceeds this amount, it may trigger additional actions or notifications. Set this to align with your monthly budget cap, such as:
monthly_spend_limit = 1000
-
post_install_scripts_bucket_name:- Purpose: The unique bucket used to store post-install scripts that run on EC2 instances during cluster setup.
- Explanation: These scripts, which could include commands for configuring services like HSDS on EC2 instances, need to be accessible by the cluster upon initialization. Since this bucket stores scripts, it also needs a unique name.
- Creation Command:
bash post-install-bucket-$(uuidgen | tr '[:upper:]' '[:lower:]')Here’s a similar setup foroutput_files_bucket_name:
- Purpose: A unique bucket used by the head node to upload files to S3 manually after completing a run. This allows easy access and management of output files generated during the run.
- Explanation: The bucket is specifically used for storing files from completed runs, making it easier to retrieve and organize results.
- Creation Command:
output-files-bucket-$(uuidgen | tr '[:upper:]' '[:lower:]')
Once you have your unique bucket names, email addresses, and budget limits defined, your configuration might look like this:
terraform_state_s3_bucket_name = "terraform-state-storage-123abc456def"
subnet_id = "subnet-0abcd1234efgh5678"
parallel_cluster_api_stack_name = "ParallelCluster"
parallel_cluster_api_stack_version = "3.10.0"
region = "us-west-2"
sns_alert_emails = ["admin@example.com", "finance@example.com"]
spending_alert_threshold = 500 # spending limit for alerts in USD
monthly_spend_limit = 1000 # monthly spending cap in USD
post_install_scripts_bucket_name = "post-install-bucket-789ghi012jkl"
output_files_bucket_name = "output-files-12345"terraform init- Purpose: Initializes the Terraform working directory by downloading necessary provider plugins and setting up the backend configuration.
- Explanation: This command is essential before running any other Terraform command, as it ensures that Terraform has access to the correct providers (e.g., AWS) and prepares the environment to handle your infrastructure setup.
terraform plan- Purpose: Generates an execution plan that shows you exactly what Terraform will do when you apply changes.
- Explanation: This command is useful for reviewing changes before they’re applied, so you can verify that the planned operations align with your expectations. It provides a preview of resources that will be added, modified, or destroyed without making any changes to actual infrastructure.
terraform apply- Purpose: Deploys the infrastructure as specified in the configuration files.
- Explanation: This command applies all defined resources in your Terraform configuration files to the specified environment. After running
terraform apply, Terraform will prompt for confirmation (unless you pass the-auto-approveflag), allowing you to verify the changes one final time. After confirmation, Terraform creates or modifies resources to match the configuration.
For the initial run, some code lines need to be commented out to allow Terraform to set up the foundational resources without trying to build dependencies that aren't yet ready. After the initial run is complete, follow these steps to finalize your configuration:
-
Remove the Placeholder Comments: Uncomment the lines labeled
# RemoveCommentin your configuration files to enable the dependent resources to be created. -
Reinitialize and Apply the Configuration:
- Re-run
terraform init(if necessary) to refresh the environment and ensure Terraform acknowledges the uncommented lines. - Apply the configuration again to build the dependent resources:
terraform apply
- Re-run
This staged approach ensures that Terraform can reference the newly created resources and then proceed to build out the dependent infrastructure.
- Replace the placeholder with
terraform_state_s3_bucket_namein the specified line (e.g., line 24) in your Terraform configuration file to point to the secure S3 bucket specified interraform.tfvars. This will ensure Terraform’s state is stored securely in your S3 bucket.
If you encounter an error message such as Provider produced inconsistent final plan, it may be due to dependencies between resources that need to be refreshed or re-evaluated. Simply re-running the command can often resolve this issue, as Terraform will try to re-plan and verify resources before applying changes.
To access the ParallelCluster’s head node, use the SSH command below with your private key and the head node’s public IP:
ssh -i ~/.ssh/id_rsa ec2-user@<head-node-ip-address>- Finding the Head Node IP: In the AWS Console, navigate to EC2, locate your head node, and copy its public IP address.
- Once connected, continue with the following commands to set up the environment.
We’ll install Miniconda to manage Python dependencies:
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
sh Miniconda3-latest-Linux-x86_64.sh- Note: During installation, press
Enterto proceed, then typeyeswhen prompted. - After installation, activate the Miniconda environment:
source ~/.bashrcNow we’ll create a Python environment specifically for reV and install the necessary packages:
conda create --name rev python=3.9
conda activate rev
pip install NREL-reV
git clone https://github.com/switchbox-data/rev-parallel-cluster-example-files.gitTo verify that SLURM and the environment are set up correctly, we’ll run a simple SLURM job:
echo -e '#!/bin/bash\nsleep 30\necho "Hello World from $(hostname)"' > my_script.sh
chmod +x my_script.sh
sbatch my_script.shAfter submitting the job, check the SLURM controller status:
sudo systemctl status slurmctld- Monitor the Job: Use
squeueto check job status. If auto-provisioning is enabled, the job will remain in theCF(configuring) state until nodes are provisioned. Once running, the status changes toR.
For detailed instructions on running reV jobs, please refer to the example repo that has information regarding how to use reV with the parallel cluster
https://github.com/switchbox-data/rev-parallel-cluster-example-files
To customize your ParallelCluster configuration, there are a few key parameters and settings you can adjust, depending on your requirements. Below are the main configuration options you can modify.
Region: ${region}
Image:
Os: alinux2
HeadNode:
InstanceType: t2.large
Networking:
SubnetId: ${subnet_id}
Ssh:
KeyName: ${ssh_key}
Iam:
AdditionalIamPolicies:
- Policy: arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
- Policy: ${pass_and_attach_role_policy}
Scheduling:
Scheduler: slurm
SlurmQueues:
- Name: compute
CapacityType: ONDEMAND
Networking:
SubnetIds:
- ${subnet_id}
AssignPublicIp: true
Iam:
AdditionalIamPolicies:
- Policy: arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
- Policy: arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
- Policy: ${s3_readonly_post_install_scripts_policy}
- Policy: ${pass_and_attach_role_policy}
ComputeResources:
- Name: queue1
InstanceType: c5.2xlarge
MinCount: 1
MaxCount: 100
CustomActions:
OnNodeConfigured:
Script: s3://${post_install_bucket}/hsds_post_install.sh
SlurmSettings:
QueueUpdateStrategy: TERMINATE
SharedStorage:
- Name: ebs1
MountDir: /shared
StorageType: Ebs
EbsSettings:
VolumeType: gp2
Size: 20
DeletionPolicy: Delete- Region: Defines the AWS region for the cluster deployment.
- InstanceType: Determines the instance type for the head and compute nodes. For higher compute needs, consider increasing this to a larger instance type.
- SubnetId: Specifies the subnet ID for network configuration. Adjust this based on network requirements and security settings.
- Iam Policies: Sets additional IAM policies. Policies like
AmazonSSMManagedInstanceCoreandAmazonEC2ContainerRegistryReadOnlyprovide permissions for management and container registry access. Modify these policies if there are any specific security or access requirements. - ComputeResources: Controls compute node resources. The
InstanceType,MinCount, andMaxCountcontrol the node type and scaling limits. Increase theInstanceTypeorMaxCountto handle more intensive workloads. - SharedStorage: Defines storage settings, such as EBS volumes. Increasing the EBS
Sizecan help if the workload requires more storage. - CapacityType: Specifies the type of compute nodes to be used in your parallel cluster. Setting this to
SPOTenables the use of spot instances, which utilize unused compute capacity at a significantly reduced cost—up to 70% less than on-demand instances. Spot instances are quick to provision and are ideal for cost-sensitive workloads. However, they can be reclaimed by AWS when needed for other services, which may interrupt your jobs. In such cases, jobs will either restart or resume from the last saved checkpoint, depending on your configuration.
To apply configuration changes, you’ll need to redeploy the cluster:
-
Comment Out the ParallelCluster Module
Inmain.tf, temporarily comment out themodule "parallel_cluster" { ... }block. -
Reinitialize and Apply Changes
Run the following commands:terraform init terraform apply
If you encounter an error related to resource conflicts or other issues, follow the next steps.
-
Check CloudFormation Stack Status
- Go to the CloudFormation section in the AWS Console.
- Look for the
rev-clusterstack to monitor its status and identify any errors.
-
If Necessary, Manually Clean Up Resources
- If you encounter persistent errors, consider checking for any dangling resources that may need manual intervention.
-
Uncomment the ParallelCluster Module
- Uncomment the
module "parallel_cluster"block inmain.tf. - Make any desired changes to
rev_cluster_config.yaml.tpl.
- Uncomment the
-
Deploy the Updated Cluster
- Run the following commands to redeploy:
terraform init terraform apply
- Run the following commands to redeploy:
Your cluster will redeploy with the updated configuration. For any issues, check the AWS Console logs for more detailed troubleshooting.
To avoid incurring additional or unnecessary costs while not using the cluster, make sure to turn it off. Follow these steps:
-
Run the Command to Stop the Compute Fleet: Execute the following command in your terminal:
pcluster update-compute-fleet --cluster-name revcluster --status STOP_REQUESTED
-
Manually Stop the Head Node:
- Log in to the AWS Management Console.
- Navigate to the EC2 Dashboard.
- In the left sidebar, click on Instances.
- Find the instance corresponding to your head node (you can identify it by the instance name, which typically follows the format
revcluster-head-*). - Select the instance and click on the Instance state dropdown button.
- Choose Stop instance from the options.
- Confirm the action when prompted.
When you are ready to use the cluster again, follow these steps to restart it:
-
Run the Command to Start the Compute Fleet: Execute the following command in your terminal:
pcluster update-compute-fleet --cluster-name revcluster --status START_REQUESTED
-
Start the Head Node:
- Log in to the AWS Management Console.
- Navigate to the EC2 Dashboard.
- In the left sidebar, click on Instances.
- Find the instance corresponding to your head node.
- Select the instance and click on the Instance state dropdown button.
- Choose Start instance from the options.
- Confirm the action when prompted.
-
Log in to the AWS Management Console: Navigate to the AWS Management Console.
-
Access the EC2 Dashboard: In the top search bar, type "EC2" and select EC2 from the drop-down menu.
-
Locate Your Instance:
- In the left-hand sidebar, click on Instances.
- Find your head node instance in the list.
-
Modify Instance Settings:
- Select the instance, and in the Instance details pane, look for the Actions dropdown menu at the top right.
- Click on Instance Settings > Edit User Data.
-
Add User Data Script: You can add a script that will run when the instance starts. This script can be used to add the SSH key. Here’s an example script you can use:
#!/bin/bash echo "<paste-your-public-key-here>" >> /home/ec2-user/.ssh/authorized_keys
Replace
<paste-your-public-key-here>with the actual public key of the user you want to grant access to. -
Save Changes:
- Click on Update User Data or Save to apply the changes.
-
Reboot the Instance: You may need to reboot the instance for the user data script to execute. You can do this from the Instance state dropdown by selecting Reboot.
- User Data Execution: The user data script runs only during the initial launch of the instance or upon reboot if modified. Make sure to add the correct public key.
- Security: Ensure that you only add trusted public keys and regularly manage your
authorized_keysfile.
If one of your jobs fails, navigate to the logs/stdout directory and locate the corresponding .e file for the failed run.
- Common Error: If you see an error related to 503, it indicates an issue with the HSDS service setup. This can often be caused by the
max_task_countbeing too low.- Solution: You can either increase the
max_task_countin the post-install script or utilize more nodes to reduce the number of concurrent requests.
- Solution: You can either increase the
- Common Error: If you encounter an error stating Unexpected Path, it likely means that your
~/.hscfgfile is incorrectly formatted or located.- Solution: Ensure that the
~/.hscfgfile is correctly formatted and copied to the right location, with all passwords and settings accurately defined.
- Solution: Ensure that the
If you receive an error related to the HeadNodeWait condition when deploying your cluster, this suggests a problem running the post-install script.
- Solution: SSH into your head node and attempt to run the post-install script directly from there to identify any issues. Ensure that the head node has the necessary S3 permissions in its role. You can retrieve the full post-install script from the S3 bucket.
To verify that your Docker container is functioning correctly, execute the following commands:
-
Run:
curl http://localhost:5101/about
This command checks if the HSDS service is responsive.
-
Next, to run a simple test script, ensure you have the
h5pydpackage installed in your Conda environment:pip install h5pyd
-
Then run the following test script to access a known file:
import h5pyd try: f = h5pyd.File("/nrel/wtk/conus/wtk_conus_2008.h5", "r") print("File accessed successfully") except Exception as e: print(f"Error accessing file: {e}")
- 403 Forbidden: Indicates an authorization issue, potentially due to incorrect permissions or the
bucket_namenot being set correctly in the configuration. - Unexpected Path: This error means the
~/.hscfgfile is incorrectly formatted or located, leading to issues in accessing the required paths. - HeadNodeWait Condition Failure: Suggests problems running the post-install script, indicating the need for additional permissions or configurations.