From 17c5b70fe0f6067363162a5e02ee0ef7b25ef10f Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Mon, 2 Oct 2023 18:15:01 +1100 Subject: [PATCH 01/12] WIP Solana nodes --- lib/constructs/config.interface.ts | 2 +- lib/solana/.env-sample | 33 ++ lib/solana/README.md | 206 +++++++++++ lib/solana/app.ts | 54 +++ lib/solana/cdk.json | 44 +++ .../assets/Architecture-HANodes.drawio.png | Bin 0 -> 131254 bytes .../assets/Architecture-SingleNode.drawio.png | Bin 0 -> 93863 bytes lib/solana/doc/assets/Architecture.drawio | 178 ++++++++++ lib/solana/doc/assets/Well_Architected.md | 26 ++ lib/solana/jest.config.js | 8 + lib/solana/lib/assets/cw-agent.json | 91 +++++ lib/solana/lib/assets/init-data-vol-ebs.sh | 53 +++ .../assets/init-data-vol-instance-store.sh | 37 ++ lib/solana/lib/assets/node-cw-dashboard.ts | 273 +++++++++++++++ .../syncchecker-bor-hemdall-mainnet.sh | 65 ++++ .../lib/assets/user-data/node-start copy.sh | 149 ++++++++ lib/solana/lib/assets/user-data/node-start.sh | 320 ++++++++++++++++++ lib/solana/lib/common-stack.ts | 63 ++++ .../lib/config/solanaConfig.interface.ts | 30 ++ lib/solana/lib/config/solanaConfig.ts | 53 +++ .../constructs/solana-node-security-group.ts | 51 +++ lib/solana/lib/ha-nodes-stack.ts | 127 +++++++ lib/solana/lib/single-node-stack.ts | 129 +++++++ lib/solana/package.json | 11 + .../sample-configs/.env-erigon-lighthouse | 29 ++ lib/solana/sample-configs/.env-erigon-prysm | 29 ++ .../sample-configs/.env-geth-lighthouse | 29 ++ lib/solana/test/.env-test | 29 ++ lib/solana/test/common-stack.test.ts | 101 ++++++ lib/solana/test/rpc-nodes-stack.test.ts | 286 ++++++++++++++++ lib/solana/test/sync-node-stack.test.ts | 161 +++++++++ 31 files changed, 2666 insertions(+), 1 deletion(-) create mode 100644 lib/solana/.env-sample create mode 100644 lib/solana/README.md create mode 100644 lib/solana/app.ts create mode 100644 lib/solana/cdk.json create mode 100644 lib/solana/doc/assets/Architecture-HANodes.drawio.png create mode 100644 lib/solana/doc/assets/Architecture-SingleNode.drawio.png create mode 100644 lib/solana/doc/assets/Architecture.drawio create mode 100644 lib/solana/doc/assets/Well_Architected.md create mode 100644 lib/solana/jest.config.js create mode 100644 lib/solana/lib/assets/cw-agent.json create mode 100644 lib/solana/lib/assets/init-data-vol-ebs.sh create mode 100644 lib/solana/lib/assets/init-data-vol-instance-store.sh create mode 100644 lib/solana/lib/assets/node-cw-dashboard.ts create mode 100644 lib/solana/lib/assets/sync-checker/syncchecker-bor-hemdall-mainnet.sh create mode 100644 lib/solana/lib/assets/user-data/node-start copy.sh create mode 100644 lib/solana/lib/assets/user-data/node-start.sh create mode 100644 lib/solana/lib/common-stack.ts create mode 100644 lib/solana/lib/config/solanaConfig.interface.ts create mode 100644 lib/solana/lib/config/solanaConfig.ts create mode 100644 lib/solana/lib/constructs/solana-node-security-group.ts create mode 100644 lib/solana/lib/ha-nodes-stack.ts create mode 100644 lib/solana/lib/single-node-stack.ts create mode 100644 lib/solana/package.json create mode 100644 lib/solana/sample-configs/.env-erigon-lighthouse create mode 100644 lib/solana/sample-configs/.env-erigon-prysm create mode 100644 lib/solana/sample-configs/.env-geth-lighthouse create mode 100644 lib/solana/test/.env-test create mode 100644 lib/solana/test/common-stack.test.ts create mode 100644 lib/solana/test/rpc-nodes-stack.test.ts create mode 100644 lib/solana/test/sync-node-stack.test.ts diff --git a/lib/constructs/config.interface.ts b/lib/constructs/config.interface.ts index 81429696..5105e553 100644 --- a/lib/constructs/config.interface.ts +++ b/lib/constructs/config.interface.ts @@ -12,7 +12,7 @@ export interface DataVolumeConfig { throughput: number; } -interface BaseNodeConfig { +export interface BaseNodeConfig { instanceType: ec2.InstanceType; instanceCpuType: ec2.AmazonLinuxCpuType; } diff --git a/lib/solana/.env-sample b/lib/solana/.env-sample new file mode 100644 index 00000000..c91d7d7d --- /dev/null +++ b/lib/solana/.env-sample @@ -0,0 +1,33 @@ +############################################################# +# Example configuration for Solana nodes runner app on AWS # +############################################################# + +## Set the AWS account is and region for your environment ## +AWS_ACCOUNT_ID="xxxxxxxxxxx" +AWS_REGION="us-east-2" + +## Common configuration parameters ## +SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" +SOLANA_NODE_CONF="lightrpc" # All options: "validator", "lightrpc", "heavyrpc" +SOLANA_INSTANCE_TYPE="r6a.8xlarge" +SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used +# Data volume configuration +SOLANA_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +SOLANA_DATA_VOL_SIZE="2000" # Current required data size to keep both smapshot archive and unarchived version of it +SOLANA_DATA_VOL_IOPS="12000" # Max IOPS for EBS volumes (not applicable for "instance-store") +SOLANA_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +# Accounts volume configuration +SOLANA_ACCOUNTS_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +SOLANA_ACCOUNTS_VOL_SIZE="500" # Current required data size to keep both smapshot archive and unarchived version of it +SOLANA_ACCOUNTS_VOL_IOPS="6000" # Max IOPS for EBS volumes (not applicable for "instance-store") +SOLANA_ACCOUNTS_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +# Secrets configuration +SOLANA_NODE_IDENTITY_SECRET_ARN="none" # Optional. The ARN of the secret in AWS Secrets Manager with the node identity key pair. In case you want to provision a node but keep the old identity. +SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. +SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. +SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for validator node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation + +## HA nodes configuration ## +SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 +SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="10" # Time enough to initialize the instance +SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="40" # Time sufficient enough for a node do download snapshot, from S3 bucket, start clients, and finish sycning the delta diff --git a/lib/solana/README.md b/lib/solana/README.md new file mode 100644 index 00000000..fd9dccc2 --- /dev/null +++ b/lib/solana/README.md @@ -0,0 +1,206 @@ +# Sample AWS Blockchain Node Runner app for Solana Nodes + +Solana nodes on AWS can be deployes in 3 different configurations: Validator, Light RPC and Heavy RPC. In addition, you can choose to deploy those configurations as a single node or a highly available (HA) nodes setup. Learn more about configurations on [Solana on AWS documentation page](https://docs.solana.com/TBA) and below are the details on single node and HA deployment setups. + +## Overview of Deployment Architectures for Single and HA setups + +### Single node setup + +![Single Node Deployment](./doc/assets/Architecture-SingleNode.drawio.png) + +1. A Solana node deployed in the [Default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) continuesly synchronizes with the rest of nodes on [Solana Clusters](https://docs.solana.com/clusters) through [Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html). +2. The Solana node is used by dApps or development tools internally from within the Default VPC. JSON RPC API is not exposed to the Internet directly to protect nodes from unauthorized access. +3. The Solanna node uses all required secrets locally, but stores a copy in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) as secure backup. +4. The Solana node sends various monitoring metrics for both EC2 and Solana nodes to Amazon CloudWatch. + +### HA setup + +![Highly Available Nodes Deployment](./doc/assets/Architecture-HANodes.drawio.png) +1. A set of Solana nodes are deployed within the [Auto Scaling Group](https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-groups.html) in the [Default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) continuesly synchronizes with the rest of nodes on [Solana Clusters](https://docs.solana.com/clusters) through [Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html). +2. The Solana nodes are accessed by dApps or development tools internallythrough [Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html). JSON RPC API is not exposed to the Internet to protect nodes from unauthorized access. dApps need to handle user authentication and API protection, like [in this example for dApps on AWS](https://aws.amazon.com/blogs/architecture/dapp-authentication-with-amazon-cognito-and-web3-proxy-with-amazon-api-gateway/). +3. The Solanna nodes use all required secrets locally, but store a copy in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) as secure backup. +4. The Solana nodes send various monitoring metrics for both EC2 and Solana nodes to Amazon CloudWatch. + +## Managing Secrets +During the startup, if a node can't find the necessary identity file on the attached Root EBS volume, it generates a new one and stores it in AWS Secrets Manager. For a single-node deployment, the ARN of a secret can be provided within the `.env` configuration file with configuration and the node will pick it up. + +Solana node in Light RPC or Heavy RPC configuration, it uses only 1 secret: + +- **Solana Node Identity Secret**: The identity key pair for a Solana node. + +A node in Validator configuration uses up to 3 more identity secrets: + +- **Vote Account Secret**: The [Validator Identity's key pair](https://docs.solana.com/running-validator/vote-accounts#validator-identity). + +- **Authorized Withdrawer Account Secret**: The [Authorized Withdrawer key pair](https://docs.solana.com/running-validator/vote-accounts#authorized-withdrawer). + +- **Registration Transaction Funding Account Secret**: An account that has sufficient SOL to pay for on-chain validator creation transaction. If not present, the node provisioning script assumes the on-chain validator creation transaction was issued elsewhere and will skip it. + +## Well-Architected + +Review the [Well-Architected Checklist](./doc/assets/Well_Architected.md) for pros and cons of this solution. + +## Solution Walkthrough + +### Setup Cloud9 + +We will use AWS Cloud9 to execute the subsequent commands. Follow the instructions in [Cloud9 Setup](../../doc/setup-cloud9.md) + +### Clone this repository and install dependencies + +```bash + git clone https://github.com/aws-samples/aws-blockchain-node-runners.git + cd aws-blockchain-node-runners + npm install +``` + +### Deploy Single Node + +1. Make sure you are in the root directory of the cloned repository + +2. If you have deleted or don't have the default VPC, create default VPC + +```bash + aws ec2 create-default-vpc + ``` + + **NOTE:** You may see the following error if the default VPC already exists: `An error occurred (DefaultVpcAlreadyExists) when calling the CreateDefaultVpc operation: A Default VPC already exists for this account in this region.`. That means you can just continue with the following steps. + +3. Configure your setup + +Create your own copy of `.env` file and edit it: +```bash + # Make sure you are in aws-blockchain-node-runners/lib/solana + cd lib/solana + pwd + cp .env-sample .env + nano .env +``` + **NOTE:** Example configuration parameters are set in the local `.env-sample` file. You can find more examples inside `sample-configs` directory. + + +4. Deploy common components such as IAM role, and Amazon S3 bucket to store data snapshots + +```bash + pwd + # Make sure you are in aws-blockchain-node-runners/lib/solana + npx cdk deploy solana-common +``` + +5. Deploy Sync Node + +```bash + pwd + # Make sure you are in aws-blockchain-node-runners/lib/solana + npx cdk deploy solana-single-node --json --outputs-file single-node-deploy.json +``` + +6. After starting the node you need to wait for the inital syncronization process to finish. It may take about 30 minutes and you can use Amazon CloudWatch to track the progress. There is a script that publishes CloudWatch metrics every 5 minutes, where you can watch `current block` and `slots behind` metrics. When the node is fully synced the `slots behind` metric should go to 0. To see them: + + - Navigate to [CloudWatch service](https://console.aws.amazon.com/cloudwatch/) (make sure you are in the region you have specified for `AWS_REGION`) + - Open `Dashboards` and select `solana-single-node` from the list of dashboards. + +### Deploy the HA Nodes + +1. Configure and deploy 2 HA Nodes + +```bash + pwd + # Make sure you are in aws-blockchain-node-runners/lib/solana + npx cdk deploy solana-ha-nodes --json --outputs-file ha-nodes-deploy.json +``` + +2. Give the new RPC nodes about 30 minutes to initialize and then run the following query against the load balancer behind the RPC node created + +```bash + export RPC_ABL_URL=$(cat ha-nodes-deploy.json | jq -r '..|.ALBURL? | select(. != null)') + echo $RPC_ABL_URL + + # We query token balance this account: https://solanabeach.io/address/9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM + curl http://$RPC_ABL_URL:8899 -X POST -H "Content-Type: application/json" \ + --data '{ "jsonrpc": "2.0", "id": 1, "method": "getBalance", "params": ["9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"]}' +``` + +The result should be like this (the actual balance might change): + +```javascript + {"jsonrpc":"2.0","id":1,"result":"14,870,473.061882488SOL +"} +``` + + If the nodes are still starting and catching up with the chain, you will see the following repsonse: + +```HTML + + 503 Service Temporarily Unavailable + +

503 Service Temporarily Unavailable

+ +``` + +**NOTE:** By default and for security reasons the load balancer is available only from wihtin the default VPC in the region where it is deployed. It is not available from the Internet and is not open for external connections. Before opening it up please make sure you protect your RPC APIs. + +### Clearing up and undeploying everything + +1. Undeploy RPC Nodes, Sync Nodes and Comon components + +```bash + # Setting the AWS account id and region in case local .env file is lost + export AWS_ACCOUNT_ID= + export AWS_REGION= + + pwd + # Make sure you are in aws-blockchain-node-runners/lib/solana + + # Undeploy HA Nodes + cdk destroy solana-ha-nodes + + # Undeploy Single Node + cdk destroy sync-single-node + + # Delete all common components like IAM role and Security Group + cdk destroy solana-common +``` + +2. Follow steps to delete the Cloud9 instance in [Cloud9 Setup](../../doc/setup-cloud9.md) + +### FAQ + +1. How to check the logs of the clients running on my sync node? + + **Note:** In this tutorial we chose not to use SSH and use Session Manager instead. That allows you to log all sessions in AWS CloudTrail to see who logged into the server and when. If you receive an error similar to `SessionManagerPlugin is not found`, [install Session Manager plugin for AWS CLI](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html) + +```bash + pwd + # Make sure you are in aws-blockchain-node-runners/lib/solana + + export INSTANCE_ID=$(cat single-node-deploy.json | jq -r '..|.node-instance-id? | select(. != null)') + echo "INSTANCE_ID=" $INSTANCE_ID + aws ssm start-session --target $INSTANCE_ID --region $AWS_REGION + sudo su bcuser + sudo journalctl -o cat -fu sol +``` +2. How to check the logs from the EC2 user-data script? + +```bash + pwd + # Make sure you are in aws-blockchain-node-runners/lib/solana + + export INSTANCE_ID=$(cat single-node-deploy.json | jq -r '..|.node-instance-id? | select(. != null)') + echo "INSTANCE_ID=" $INSTANCE_ID + aws ssm start-session --target $INSTANCE_ID --region $AWS_REGION + sudo cat /var/log/cloud-init-output.log +``` + +3. How can I restart the Solana serice? + +``` bash + export INSTANCE_ID=$(cat single-node-deploy.json | jq -r '..|.node-instance-id? | select(. != null)') + echo "INSTANCE_ID=" $INSTANCE_ID + aws ssm start-session --target $INSTANCE_ID --region $AWS_REGION + sudo systemctl status sol +``` + +## Upgrades + +When nodes need to be upgraded or downgraded, [use blue/green pattern to do it](https://aws.amazon.com/blogs/devops/performing-bluegreen-deployments-with-aws-codedeploy-and-auto-scaling-groups/). This is not yet automated and contributions are welcome! \ No newline at end of file diff --git a/lib/solana/app.ts b/lib/solana/app.ts new file mode 100644 index 00000000..6c0ba821 --- /dev/null +++ b/lib/solana/app.ts @@ -0,0 +1,54 @@ +#!/usr/bin/env node +import 'dotenv/config' +import "source-map-support/register"; +import * as cdk from "aws-cdk-lib"; +import * as nag from "cdk-nag"; +import * as config from "./lib/config/solanaConfig"; + +import { PolygonSyncNodeStack } from "./lib/single-node-stack"; +import { PolygonCommonStack } from "./lib/common-stack"; +import { PolygonRpcNodesStack } from "./lib/ha-nodes-stack"; + +const app = new cdk.App(); +cdk.Tags.of(app).add("Project", "AWSPolygon"); + +new PolygonCommonStack(app, "polygon-common", { + env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, + stackName: `polygon-nodes-common`, + createVpcEnpointS3: config.baseConfig.createVpcEnpointS3, +}); + +new PolygonSyncNodeStack(app, "polygon-sync-node", { + stackName: `polygon-sync-node-${config.baseConfig.clientCombination}`, + + env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, + polygonClientCombination: config.baseConfig.clientCombination, + network: config.baseConfig.network, + instanceType: config.syncNodeConfig.instanceType, + instanceCpuType: config.syncNodeConfig.instanceCpuType, + dataVolumes: config.syncNodeConfig.dataVolumes, +}); + +new PolygonRpcNodesStack(app, "polygon-rpc-nodes", { + stackName: `polygon-rpc-nodes-${config.baseConfig.clientCombination}`, + + env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, + polygonClientCombination: config.baseConfig.clientCombination, + network: config.baseConfig.network, + instanceType: config.rpcNodeConfig.instanceType, + instanceCpuType: config.rpcNodeConfig.instanceCpuType, + numberOfNodes: config.rpcNodeConfig.numberOfNodes, + albHealthCheckGracePeriodMin: config.rpcNodeConfig.albHealthCheckGracePeriodMin, + heartBeatDelayMin: config.rpcNodeConfig.heartBeatDelayMin, + dataVolumes: config.syncNodeConfig.dataVolumes, +}); + + +// Security Check +cdk.Aspects.of(app).add( + new nag.AwsSolutionsChecks({ + verbose: false, + reports: true, + logIgnores: false, + }) +); diff --git a/lib/solana/cdk.json b/lib/solana/cdk.json new file mode 100644 index 00000000..1994f2d7 --- /dev/null +++ b/lib/solana/cdk.json @@ -0,0 +1,44 @@ +{ + "app": "npx ts-node --prefer-ts-exts app.ts", + "watch": { + "include": [ + "**" + ], + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + "test" + ] + }, + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-iam:standardizedServicePrincipals": true, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, + "@aws-cdk/aws-route53-patters:useCertificate": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false + } +} \ No newline at end of file diff --git a/lib/solana/doc/assets/Architecture-HANodes.drawio.png b/lib/solana/doc/assets/Architecture-HANodes.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..286ca68e0b9ef2ef27efe151baf8c82cac457485 GIT binary patch literal 131254 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 E0c~~ulmGw# literal 0 HcmV?d00001 diff --git a/lib/solana/doc/assets/Architecture-SingleNode.drawio.png b/lib/solana/doc/assets/Architecture-SingleNode.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..71f7371ba7db3c21ba7ca77d3a0c328ad7a64976 GIT binary patch literal 93863 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 literal 0 HcmV?d00001 diff --git a/lib/solana/doc/assets/Architecture.drawio b/lib/solana/doc/assets/Architecture.drawio new file mode 100644 index 00000000..b6a5fb17 --- /dev/null +++ b/lib/solana/doc/assets/Architecture.drawio @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/solana/doc/assets/Well_Architected.md b/lib/solana/doc/assets/Well_Architected.md new file mode 100644 index 00000000..ddd50f5e --- /dev/null +++ b/lib/solana/doc/assets/Well_Architected.md @@ -0,0 +1,26 @@ +# Well-Architected Checklist + +This is the Well-Architected checklist for Ethereum nodes implementation of the AWS Blockchain Node Runner app. This checklist takes into account questions from the [AWS Well-Architected Framework](https://aws.amazon.com/architecture/well-architected/) which are relevant to this workload. Please feel free to add more checks from the framework if required for your workload. + +| Pillar | Control | Question/Check | Remarks | +|:------------------------|:----------------------------------|:---------------------------------------------------------------------------------|:-----------------| +| Security | Network protection | Are there unnecessary open ports in security groups? | Please note that Erigon snap sync port remains open for non-erigon clients, i.e. Port 42069 (TCP/UDP). | +| | | Traffic inspection | AWS WAF could be implemented for traffic inspection. Additional charges will apply. | +| | Compute protection | Reduce attack surface | This solution uses Amazon Linux 2 AMI. You may choose to run hardening scripts on it. | +| | | Enable people to perform actions at a distance | This solution uses AWS Systems Manager for terminal session, not ssh ports. | +| | Data protection at rest | Use encrypted Amazon Elastic Block Store (Amazon EBS) volumes | This solution uses encrypted Amazon EBS volumes. | +| | | Use encrypted Amazon Simple Storage Service (Amazon S3) buckets | This solution uses Amazon S3 managed keys (SSE-S3) encryption. | +| | Data protection in transit | Use TLS | The AWS Application Load balancer currently uses HTTP listener. Create HTTPS listener with self signed certificate if TLS is desired. | +| | Authorization and access control | Use instance profile with Amazon Elastic Compute Cloud (Amazon EC2) instances | This solution uses AWS Identity and Access Management (AWS IAM) role instead of IAM user. | +| | | Following principle of least privilege access | In sync node, root user is not used (using special user "ethereum" instead"). | +| | Application security | Security focused development practices | cdk-nag is being used with appropriate suppressions. | +| Cost optimization | Service selection | Use cost effective resources | AWS Graviton-based Amazon EC2 instances are being used, which are cost effective compared to Intel/AMD instances. | +| | Cost awareness | Estimate costs | One sync node with m7g.2xlarge for geth-lighthouse configuration (2048GB ssd) will cost around US$430 per month in the US East (N. Virginia) region. Additional charges will apply if you choose to deploy RPC nodes with load balancer. | +| Reliability | Resiliency implementation | Withstand component failures | This solution uses AWS Application Load Balancer with RPC nodes for high availability. If sync node fails, Amazon S3 backup can be used to reinstate the nodes. | +| | Data backup | How is data backed up? | Data is backed up to Amazon S3 using [s5cmd](https://github.com/peak/s5cmd) tool. | +| | Resource monitoring | How are workload resources monitored? | Resources are being monitored using Amazon CloudWatch dashboards. Amazon CloudWatch custom metrics are being pushed via CloudWatch Agent. | +| Performance efficiency | Compute selection | How is compute solution selected? | Compute solution is selected based on best price-performance, i.e. AWS Graviton-based Amazon EC2 instances. | +| | Storage selection | How is storage solution selected? | Storage solution is selected based on best price-performance, i.e. gp3 Amazon EBS volumes with optimal IOPS and throughput. | +| | Architecture selection | How is the best performance architecture selected? | s5cmd tool has been chosen for Amazon S3 uploads/downloads because it gives better price-performance compared to Amazon EBS snapshots (including Fast Snapshot Restore, which can be expensive). | +| Operational excellence | Workload health | How is health of workload determined? | Health of workload is determined via AWS Application Load Balancer Target Group Health Checks, on port 8545. | +| Sustainability | Hardware & services | Select most efficient hardware for your workload | This solution uses AWS Graviton-based Amazon EC2 instances which offer the best performance per watt of energy use in Amazon EC2. | \ No newline at end of file diff --git a/lib/solana/jest.config.js b/lib/solana/jest.config.js new file mode 100644 index 00000000..0bc77ac0 --- /dev/null +++ b/lib/solana/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + testEnvironment: 'node', + roots: ['/test'], + testMatch: ['**/*.test.ts'], + transform: { + '^.+\\.tsx?$': 'ts-jest' + }, +}; diff --git a/lib/solana/lib/assets/cw-agent.json b/lib/solana/lib/assets/cw-agent.json new file mode 100644 index 00000000..b4f3d972 --- /dev/null +++ b/lib/solana/lib/assets/cw-agent.json @@ -0,0 +1,91 @@ +{ + "agent": { + "metrics_collection_interval": 60, + "run_as_user": "root" + }, + "logs": { + "logs_collected": { + "files": { + "collect_list": [{ + "file_path": "/var/log/cloud-init-output.log", + "log_group_name": "cloud-init-output.log", + "log_stream_name": "{instance_id}" + }, { + "file_path": "/var/log/initial-sync.log", + "log_group_name": "initial-sync.log", + "log_stream_name": "{instance_id}" + }] + } + } + }, + "metrics": { + "aggregation_dimensions": [ + [ + "InstanceId" + ] + ], + "append_dimensions": { + "InstanceId": "${aws:InstanceId}" + }, + "metrics_collected": { + "cpu": { + "measurement": [ + "cpu_usage_idle", + "cpu_usage_iowait", + "cpu_usage_user", + "cpu_usage_system" + ], + "metrics_collection_interval": 60, + "resources": [ + "*" + ], + "totalcpu": false + }, + "disk": { + "measurement": [ + "used_percent" + ], + "metrics_collection_interval": 60, + "resources": [ + "*" + ] + }, + "diskio": { + "measurement": [ + "io_time", + "write_bytes", + "read_bytes", + "writes", + "reads", + "write_time", + "read_time", + "iops_in_progress" + ], + "metrics_collection_interval": 60, + "resources": [ + "*" + ] + }, + "mem": { + "measurement": [ + "mem_used_percent", + "mem_cached" + ], + "metrics_collection_interval": 60 + }, + "netstat": { + "measurement": [ + "tcp_established", + "tcp_time_wait" + ], + "metrics_collection_interval": 60 + }, + "swap": { + "measurement": [ + "swap_used_percent" + ], + "metrics_collection_interval": 60 + } + } + } +} \ No newline at end of file diff --git a/lib/solana/lib/assets/init-data-vol-ebs.sh b/lib/solana/lib/assets/init-data-vol-ebs.sh new file mode 100644 index 00000000..73a8ea5a --- /dev/null +++ b/lib/solana/lib/assets/init-data-vol-ebs.sh @@ -0,0 +1,53 @@ +#!/bin/bash +set +e + +FORMAT_VOLUME=${_FORMAT_VOLUME_} + +# Check if all parameters are provided +if [ "$#" -ne 1 ]; then + echo "Usage: bash [FORMAT_VOLUME]" + echo "FORMAT_VOLUME: true or false" + exit 1 +fi + +# Assign parameters to variables +FORMAT_VOLUME="$1" + +export DATA_VOLUME_NAME=nvme1n1 +export DATA_VOLUME_ID=/dev/$DATA_VOLUME_NAME +export DATA_DIRECTORY=/data + +mkdir -p $DATA_DIRECTORY + +echo "Preparing EBS data volume" + +echo "Wait for one minute for the volume to be available" +sleep 60 + +if $(lsblk | grep -q $DATA_VOLUME_NAME); then + echo "$DATA_VOLUME_NAME is found. Configuring attached storage" + + if [ "$FORMAT_VOLUME" == "false" ]; then + echo "Not creating a new filesystem in the VOLUME. Existing data might be present!!" + else + mkfs -t ext4 $DATA_VOLUME_ID + fi + + sleep 10 + # Define the line to add to fstab + DATA_VOLUME_UUID=$(lsblk -n -o UUID $DATA_VOLUME_ID) + line="UUID=$DATA_VOLUME_UUID $DATA_DIRECTORY ext4 defaults 0 2" + + # Write the line to fstab + echo $line | sudo tee -a /etc/fstab + + mount -a + +else + echo "nvme1n1 is not found. Not doing anything" +fi + +lsblk -d + +chown -R bcuser:bcuser $DATA_DIRECTORY +chmod -R 755 $DATA_DIRECTORY \ No newline at end of file diff --git a/lib/solana/lib/assets/init-data-vol-instance-store.sh b/lib/solana/lib/assets/init-data-vol-instance-store.sh new file mode 100644 index 00000000..167a418a --- /dev/null +++ b/lib/solana/lib/assets/init-data-vol-instance-store.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set +e + +echo "Preparing instance store data volume" +export DATA_VOLUME_ID=/dev/nvme1n1 +export DATA_DIRECTORY=/data + +mkdir -p $DATA_DIRECTORY + +echo "If Data volume is mounted, dont do anything" +if [ $(df --output=target | grep -c "$DATA_DIRECTORY") -lt 1 ]; then + echo "Checking fstab for Data volume" + + sudo mkfs.xfs -f $DATA_VOLUME_ID + sleep 10 + DATA_VOLUME_UUID=$(lsblk -fn -o UUID $DATA_VOLUME_ID) + DATA_VOLUME_FSTAB_CONF="UUID=$DATA_VOLUME_UUID $DATA_DIRECTORY xfs defaults 0 2" + echo "DATA_VOLUME_ID="$DATA_VOLUME_ID + echo "DATA_VOLUME_UUID="$DATA_VOLUME_UUID + echo "DATA_VOLUME_FSTAB_CONF="$DATA_VOLUME_FSTAB_CONF + + # Check if data disc is already in fstab and replace the line if it is with the new disc UUID + if [ $(grep -c "$DATA_DIRECTORY" /etc/fstab) -gt 0 ]; then + SED_REPLACEMENT_STRING="$(grep -n "$DATA_DIRECTORY" /etc/fstab | cut -d: -f1)s#.*#$DATA_VOLUME_FSTAB_CONF#" + sudo cp /etc/fstab /etc/fstab.bak + sudo sed -i "$SED_REPLACEMENT_STRING" /etc/fstab + else + echo $DATA_VOLUME_FSTAB_CONF | sudo tee -a /etc/fstab + fi + + sudo mount -a + + chown -R bcuser:bcuser $DATA_DIRECTORY + chmod -R 755 $DATA_DIRECTORY +else + echo "Data volume is mounted, nothing changed" +fi \ No newline at end of file diff --git a/lib/solana/lib/assets/node-cw-dashboard.ts b/lib/solana/lib/assets/node-cw-dashboard.ts new file mode 100644 index 00000000..587bf65b --- /dev/null +++ b/lib/solana/lib/assets/node-cw-dashboard.ts @@ -0,0 +1,273 @@ +export const SyncNodeCWDashboardJSON = { + "widgets": [ + { + "height": 5, + "width": 6, + "y": 0, + "x": 0, + "type": "metric", + "properties": { + "view": "timeSeries", + "stat": "Average", + "period": 300, + "stacked": false, + "yAxis": { + "left": { + "min": 0 + } + }, + "region": "${REGION}", + "metrics": [ + [ "AWS/EC2", "CPUUtilization", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + ], + "title": "CPU utilization (%)" + } + }, + { + "height": 5, + "width": 6, + "y": 5, + "x": 18, + "type": "metric", + "properties": { + "view": "timeSeries", + "stat": "Average", + "period": 300, + "stacked": false, + "yAxis": { + "left": { + "min": 0 + } + }, + "region": "${REGION}", + "metrics": [ + [ "AWS/EC2", "NetworkIn", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + ], + "title": "Network in (bytes)" + } + }, + { + "height": 5, + "width": 6, + "y": 0, + "x": 18, + "type": "metric", + "properties": { + "view": "timeSeries", + "stat": "Average", + "period": 300, + "stacked": false, + "yAxis": { + "left": { + "min": 0 + } + }, + "region": "${REGION}", + "metrics": [ + [ "AWS/EC2", "NetworkOut", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + ], + "title": "Network out (bytes)" + } + }, + { + "height": 5, + "width": 6, + "y": 10, + "x": 0, + "type": "metric", + "properties": { + "view": "timeSeries", + "stacked": false, + "region": "${REGION}", + "stat": "Average", + "period": 300, + "metrics": [ + [ "CWAgent", "mem_used_percent", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + ], + "title": "Mem Used (%)" + } + }, + { + "height": 5, + "width": 6, + "y": 5, + "x": 0, + "type": "metric", + "properties": { + "view": "timeSeries", + "stacked": false, + "region": "${REGION}", + "stat": "Average", + "period": 300, + "metrics": [ + [ "CWAgent", "cpu_usage_iowait", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + ], + "title": "CPU Usage IO wait (%)" + } + }, + { + "height": 5, + "width": 6, + "y": 0, + "x": 6, + "type": "metric", + "properties": { + "metrics": [ + [ { "expression": "m7/PERIOD(m7)", "label": "Read", "id": "e7" } ], + [ "CWAgent", "diskio_reads", "InstanceId", "${INSTANCE_ID}", "name", "nvme1n1", { "id": "m7", "visible": false, "stat": "Sum", "period": 60 } ], + [ { "expression": "m8/PERIOD(m8)", "label": "Write", "id": "e8" } ], + [ "CWAgent", "diskio_writes", "InstanceId", "${INSTANCE_ID}", "name", "nvme1n1", { "id": "m8", "visible": false, "stat": "Sum", "period": 60 } ] + ], + "view": "timeSeries", + "stacked": false, + "region": "${REGION}", + "stat": "Sum", + "period": 60, + "title": "nvme1n1 Volume Read/Write (IO/sec)" + } + }, + { + "height": 4, + "width": 6, + "y": 0, + "x": 12, + "type": "metric", + "properties": { + "metrics": [ + [ "CWAgent", "elc_sync_block", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + ], + "sparkline": true, + "view": "timeSeries", + "stacked": false, + "region": "${REGION}", + "stat": "Maximum", + "period": 60, + "title": "Execution Client Block Height" + } + }, + { + "height": 4, + "width": 6, + "y": 4, + "x": 12, + "type": "metric", + "properties": { + "sparkline": true, + "view": "timeSeries", + "stacked": false, + "region": "${REGION}", + "stat": "Maximum", + "period": 60, + "metrics": [ + [ "CWAgent", "elc_blocks_behind", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + ], + "title": "Execution Client Blocks Behind" + } + }, + { + "height": 3, + "width": 6, + "y": 8, + "x": 12, + "type": "metric", + "properties": { + "metrics": [ + [ "CWAgent", "clc_head_slot", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + ], + "sparkline": true, + "view": "timeSeries", + "stacked": false, + "region": "${REGION}", + "stat": "Maximum", + "period": 60, + "title": "Consensus Client Head Slot" + } + }, + { + "height": 4, + "width": 6, + "y": 11, + "x": 12, + "type": "metric", + "properties": { + "sparkline": true, + "view": "timeSeries", + "stacked": false, + "region": "${REGION}", + "stat": "Maximum", + "period": 60, + "metrics": [ + [ "CWAgent", "clc_sync_distance", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + ], + "title": "Consensus Client Sync Distance" + } + }, + { + "height": 5, + "width": 6, + "y": 5, + "x": 6, + "type": "metric", + "properties": { + "view": "timeSeries", + "stat": "Sum", + "period": 60, + "stacked": false, + "yAxis": { + "left": { + "min": 0 + } + }, + "region": "${REGION}", + "metrics": [ + [ { "expression": "IF(m7_2 !=0, (m7_1 / m7_2), 0)", "label": "Read", "id": "e7" } ], + [ "CWAgent", "diskio_read_time", "InstanceId", "${INSTANCE_ID}", "name", "nvme1n1", { "id": "m7_1", "visible": false, "stat": "Sum", "period": 60 } ], + [ "CWAgent", "diskio_reads", "InstanceId", "${INSTANCE_ID}", "name", "nvme1n1", { "id": "m7_2", "visible": false, "stat": "Sum", "period": 60 } ], + [ { "expression": "IF(m7_4 !=0, (m7_3 / m7_4), 0)", "label": "Write", "id": "e8" } ], + [ "CWAgent", "diskio_write_time", "InstanceId", "${INSTANCE_ID}", "name", "nvme1n1", { "id": "m7_3", "visible": false, "stat": "Sum", "period": 60 } ], + [ "CWAgent", "diskio_writes", "InstanceId", "${INSTANCE_ID}", "name", "nvme1n1", { "id": "m7_4", "visible": false, "stat": "Sum", "period": 60 } ] + ], + "title": "nvme1n1 Volume Read/Write latency (ms/op)" + } + }, + { + "height": 5, + "width": 6, + "y": 10, + "x": 6, + "type": "metric", + "properties": { + "metrics": [ + [ { "expression": "(m2/1048576)/PERIOD(m2)", "label": "Read", "id": "e2", "period": 60, "region": "${REGION}" } ], + [ "CWAgent", "diskio_read_bytes", "InstanceId", "${INSTANCE_ID}", "name", "nvme1n1", { "id": "m2", "stat": "Sum", "visible": false, "period": 60 } ], + [ { "expression": "(m3/1048576)/PERIOD(m3)", "label": "Write", "id": "e3", "period": 60, "region": "${REGION}" } ], + [ "CWAgent", "diskio_write_bytes", "InstanceId", "${INSTANCE_ID}", "name", "nvme1n1", { "id": "m3", "stat": "Sum", "visible": false, "period": 60 } ] + ], + "view": "timeSeries", + "stacked": false, + "region": "${REGION}", + "stat": "Average", + "period": 60, + "title": "nvme1n1 Volume Read/Write throughput (MiB/sec)" + } + }, + { + "height": 3, + "width": 6, + "y": 15, + "x": 6, + "type": "metric", + "properties": { + "metrics": [ + [ "CWAgent", "disk_used_percent", "path", "/data", "InstanceId", "${INSTANCE_ID}", "device", "nvme1n1", "fstype", "ext4", { "region": "${REGION}", "label": "/data" } ] + ], + "sparkline": true, + "view": "singleValue", + "region": "${REGION}", + "title": "nvme1n1 Disk Used (%)", + "period": 60, + "stat": "Average" + } + } + ] +} \ No newline at end of file diff --git a/lib/solana/lib/assets/sync-checker/syncchecker-bor-hemdall-mainnet.sh b/lib/solana/lib/assets/sync-checker/syncchecker-bor-hemdall-mainnet.sh new file mode 100644 index 00000000..b4cc7cba --- /dev/null +++ b/lib/solana/lib/assets/sync-checker/syncchecker-bor-hemdall-mainnet.sh @@ -0,0 +1,65 @@ +#!/bin/bash +source /etc/environment + +# Consensus client stats +CONSENSUS_CLIENT_SYNC_STATUS=$(curl -s http://localhost:5052/eth/v1/node/syncing | jq -r ".data") + +CONSENSUS_CLIENT_IS_SYNCING=$(echo $CONSENSUS_CLIENT_SYNC_STATUS | jq -r ".is_syncing") +CONSENSUS_CLIENT_IS_OPTIMISTIC=$(echo $CONSENSUS_CLIENT_SYNC_STATUS | jq -r ".is_optimistic") +CONSENSUS_CLIENT_SYNC_DISTANCE=$(echo $CONSENSUS_CLIENT_SYNC_STATUS | jq -r ".sync_distance") +CONSENSUS_CLIENT_HEAD_SLOT=$(echo $CONSENSUS_CLIENT_SYNC_STATUS | jq -r ".head_slot") + +if [[ -z "$CONSENSUS_CLIENT_SYNC_DISTANCE" ]]; then + CONSENSUS_CLIENT_SYNC_DISTANCE=0 +fi + +if [[ -z "$CONSENSUS_CLIENT_HEAD_SLOT" ]]; then + CONSENSUS_CLIENT_HEAD_SLOT=0 +fi + +# Execution client stats +EXECUTION_CLIENT_SYNC_STATS=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' http://localhost:8545 | jq -r ".result") + +if [[ "$EXECUTION_CLIENT_SYNC_STATS" == "false" ]]; then + EXECUTION_CLIENT_SYNC_BLOCK_HEX=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http://localhost:8545 | jq -r ".result") + EXECUTION_CLIENT_HIGHEST_BLOCK_HEX=$EXECUTION_CLIENT_SYNC_BLOCK_HEX +else + EXECUTION_CLIENT_SYNC_BLOCK_HEX=$(echo $EXECUTION_CLIENT_SYNC_STATS | jq -r ".currentBlock") + EXECUTION_CLIENT_HIGHEST_BLOCK_HEX=$(echo $EXECUTION_CLIENT_SYNC_STATS | jq -r ".highestBlock") +fi + +EXECUTION_CLIENT_HIGHEST_BLOCK=$(echo $((${EXECUTION_CLIENT_HIGHEST_BLOCK_HEX}))) +EXECUTION_CLIENT_SYNC_BLOCK=$(echo $((${EXECUTION_CLIENT_SYNC_BLOCK_HEX}))) +EXECUTION_CLIENT_BLOCKS_BEHIND="$((EXECUTION_CLIENT_HIGHEST_BLOCK-EXECUTION_CLIENT_SYNC_BLOCK))" + +# echo "EXECUTION_CLIENT_SYNC_STATS="$EXECUTION_CLIENT_SYNC_STATS +# echo "CONSENSUS_CLIENT_IS_SYNCING="$CONSENSUS_CLIENT_IS_SYNCING +# echo "CONSENSUS_CLIENT_IS_OPTIMISTIC="$CONSENSUS_CLIENT_IS_OPTIMISTIC +# echo "EXECUTION_CLIENT_HIGHEST_BLOCK="$EXECUTION_CLIENT_HIGHEST_BLOCK +# echo "EXECUTION_CLIENT_SYNC_BLOCK="$EXECUTION_CLIENT_SYNC_BLOCK +# echo "EXECUTION_CLIENT_BLOCKS_BEHIND="$EXECUTION_CLIENT_BLOCKS_BEHIND + +# Sending data to CloudWatch +TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") +INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id) +REGION=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq .region -r) +TIMESTAMP=$(date +"%Y-%m-%dT%H:%M:%S%:z") + +aws cloudwatch put-metric-data --metric-name clc_sync_distance --namespace CWAgent --value $CONSENSUS_CLIENT_SYNC_DISTANCE --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION +aws cloudwatch put-metric-data --metric-name clc_head_slot --namespace CWAgent --value $CONSENSUS_CLIENT_HEAD_SLOT --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION + +aws cloudwatch put-metric-data --metric-name elc_sync_block --namespace CWAgent --value $EXECUTION_CLIENT_SYNC_BLOCK --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION +aws cloudwatch put-metric-data --metric-name elc_blocks_behind --namespace CWAgent --value $EXECUTION_CLIENT_BLOCKS_BEHIND --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION + +# If the node is a sync node, check if the snapshot is already taken. If the snapshot is not taken, then take it and restart the node. +if [[ "$NODE_ROLE" == "sync-node" ]]; then + if [ ! -f "/data/snapshotted" ]; then + if [ "$EXECUTION_CLIENT_SYNC_STATS" == "false" ] && [ "$CONSENSUS_CLIENT_IS_SYNCING" == "false" ] && [ "$CONSENSUS_CLIENT_IS_OPTIMISTIC" == "false" ]; then + sudo /opt/copy-data-to-s3.sh + + # Take a snapshot once a day at midnight + (sudo crontab -u root -l; echo '0 0 * * * /opt/copy-data-to-s3.sh' ) | sudo crontab -u root - + sudo crontab -l + fi + fi +fi \ No newline at end of file diff --git a/lib/solana/lib/assets/user-data/node-start copy.sh b/lib/solana/lib/assets/user-data/node-start copy.sh new file mode 100644 index 00000000..cac1cbff --- /dev/null +++ b/lib/solana/lib/assets/user-data/node-start copy.sh @@ -0,0 +1,149 @@ +#!/bin/bash +set +e + +# Set by generic single-node and ha-node CDK components +ASSETS_S3_PATH=${_ASSETS_S3_PATH_} + +# Saving just in case for future use +echo "ASSETS_S3_PATH=$ASSETS_S3_PATH" >> /etc/environment + +arch=$(uname -m) + +echo "Architecture detected: $arch" + +if [ "$arch" == "x86_64" ]; then + SSM_AGENT_BINARY_URI=https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm + AWS_CLI_BINARY_URI=https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip + S5CMD_URI=https://github.com/peak/s5cmd/releases/download/v2.1.0/s5cmd_2.1.0_Linux-64bit.tar.gz +else + SSM_AGENT_BINARY_URI=https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_arm64/amazon-ssm-agent.rpm + AWS_CLI_BINARY_URI=https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip + S5CMD_URI=https://github.com/peak/s5cmd/releases/download/v2.1.0/s5cmd_2.1.0_Linux-arm64.tar.gz +fi + +echo "Updating and installing required system packages" +yum update -y +yum -y install amazon-cloudwatch-agent collectd jq gcc ncurses-devel telnet aws-cfn-bootstrap + +cd /opt + +echo "Downloading assets zip file" +aws s3 cp $ASSETS_S3_PATH ./assets.zip +unzip -q assets.zip + +echo 'Configuring CloudWatch Agent' +cp /opt/cw-agent.json /opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json + +echo "Starting CloudWatch Agent" +/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \ +-a fetch-config -c file:/opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json -m ec2 -s +systemctl status amazon-cloudwatch-agent + +echo 'Uninstalling AWS CLI v1' +yum remove awscli + +echo 'Installing AWS CLI v2' +curl $AWS_CLI_BINARY_URI -o "awscliv2.zip" +unzip -q awscliv2.zip +./aws/install +rm /usr/bin/aws +ln /usr/local/bin/aws /usr/bin/aws + +aws configure set default.s3.max_concurrent_requests 50 +aws configure set default.s3.multipart_chunksize 256MB + +echo 'Installing SSM Agent' +yum install -y $SSM_AGENT_BINARY_URI + +echo "Assigning Swap Space" +# Check if a swap file already exists +if [ -f /swapfile ]; then + # Remove the existing swap file + swapoff /swapfile + rm -rf /swapfile +fi + +# Create a new swap file +total_mem=$(grep MemTotal /proc/meminfo | awk '{print $2}') +# Calculate the swap size +swap_size=$((total_mem / 3)) +# Convert the swap size to MB +swap_size_mb=$((swap_size / 1024)) +unit=M +fallocate -l $swap_size_mb$unit /swapfile +chmod 600 /swapfile +mkswap /swapfile +swapon /swapfile + +# Enable the swap space to persist after reboot. +echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab + +sysctl vm.swappiness=6 +sysctl vm.vfs_cache_pressure=10 +echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf +echo "vm.vfs_cache_pressure=10" | sudo tee -a /etc/sysctl.conf + +free -h + +echo "Adding blockchain user and group" +groupadd -g 1002 bcuser +useradd -u 1002 -g 1002 -m -s /bin/bash bcuser +usermod -a -G docker bcuser +usermod -a -G docker ec2-user + +# Setting up sync node + +REGION=${_REGION_} +STACK_NAME=${_STACK_NAME_} +RESOURCE_ID=${_RESOURCE_ID_} +SNAPSHOT_S3_PATH=${_SNAPSHOT_S3_PATH_} +CLIENT_COMBINATION=${_CLIENT_COMBINATION_} +NETWORK=${_NETWORK_} +DATA_VOLUME_TYPE=${_DATA_VOLUME_TYPE_} +FORMAT_DISK=${_FORMAT_DISK_} + +# Saving just in case for future use +echo "REGION=$REGION" >> /etc/environment +echo "STACK_NAME=$STACK_NAME" >> /etc/environment +echo "RESOURCE_ID=$RESOURCE_ID" >> /etc/environment +echo "SNAPSHOT_S3_PATH=$SNAPSHOT_S3_PATH" >> /etc/environment +echo "NETWORK=$NETWORK" >> /etc/environment +echo "DATA_VOLUME_TYPE=$DATA_VOLUME_TYPE" >> /etc/environment +echo "FORMAT_DISK=$FORMAT_DISK" >> /etc/environment + +# Check if aria2c is installed +sudo yum update -y +sudo amazon-linux-extras install epel -y +sudo yum install zstd pv aria2 -y + +echo "Signaling completion to CloudFormation" +/opt/aws/bin/cfn-signal --stack $STACK_NAME --resource $RESOURCE_ID --region $REGION + +# Configure data volume +if [ "$DATA_VOLUME_TYPE" == "instance-store" ]; then + chmod +x /opt/init-data-vol-instance-store.sh + + (crontab -l; echo "@reboot /opt/init-data-vol-instance-store.sh >/tmp/init-data-vol-instance-store.log 2>&1") | crontab - + crontab -l + + /opt/init-data-vol-instance-store.sh +else + chmod +x /opt/init-data-vol-ebs.sh + /opt/init-data-vol-ebs.sh $FORMAT_DISK +fi + +chmod +x /opt/polygon/download-extract-polygon-snapshot.sh + +# Download the snapshot +case $CLIENT_COMBINATION in + "bor-heimdall") + mkdir -p /data/polygon/bor/bor/chaindata + mkdir -p /data/polygon/heimdall/data + echo "/opt/polygon/download-extract-polygon-snapshot.sh -n $NETWORK -c bor -d /data/polygon/bor/bor/chaindata -v true -s3 $SNAPSHOT_S3_PATH" | at now +3 minutes + echo "/opt/polygon/download-extract-polygon-snapshot.sh -n $NETWORK -c heimdall -d /data/polygon/heimdall/data -v true -s3 $SNAPSHOT_S3_PATH" | at now +4 minutes + ;; + *) + echo "Combination is not valid." + exit 1 + ;; +esac \ No newline at end of file diff --git a/lib/solana/lib/assets/user-data/node-start.sh b/lib/solana/lib/assets/user-data/node-start.sh new file mode 100644 index 00000000..aabb9af0 --- /dev/null +++ b/lib/solana/lib/assets/user-data/node-start.sh @@ -0,0 +1,320 @@ +#!/bin/bash +set +e + +# Set by generic single-node and ha-node CDK components +echo "ASSETS_S3_PATH=${_ASSETS_S3_PATH_}" >> /etc/environment +echo "CF_STACK_NAME=${CF_STACK_NAME}" >> /etc/environment +echo "ACCOUNTS_DISC_TYPE=${ACCOUNTS_DISC_TYPE}" >> /etc/environment +echo "DATA_DISC_TYPE=${DATA_DISC_TYPE}" >> /etc/environment +echo "SOLANA_VERSION=${SOLANA_VERSION}" >> /etc/environment +echo "SOLANA_NODE_TYPE=${SOLANA_NODE_TYPE}" >> /etc/environment +echo "NODE_IDENTITY_SECRET_ARN=${NODE_IDENTITY_SECRET_ARN}" >> /etc/environment +echo "VOTE_ACCOUNT_SECRET_ARN=${VOTE_ACCOUNT_SECRET_ARN}" >> /etc/environment +echo "AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN=${AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN}" >> /etc/environment +echo "REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN=${REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN}" >> /etc/environment +echo "SOLANA_CLUSTER_ID=${SOLANA_CLUSTER_ID}" >> /etc/environment +source /etc/environment + +apt-get -yqq update +apt-get -yqq install awscli jq + +# Saving just in case for future use +arch=$(uname -m) + +export AWS_REGION=`curl http://169.254.169.254/latest/dynamic/instance-identity/document|grep region|awk -F\" '{print $4}'` +export GIT_URL="https://raw.githubusercontent.com/frbrkoala/solana-configs-for-aws/main" + +case $SOLANA_CLUSTER_ID in + "mainnet-beta") + ENTRY_POINTS=" --entrypoint entrypoint.mainnet-beta.solana.com:8001 --entrypoint entrypoint2.mainnet-beta.solana.com:8001 --entrypoint entrypoint3.mainnet-beta.solana.com:8001 --entrypoint entrypoint4.mainnet-beta.solana.com:8001 --entrypoint entrypoint5.mainnet-beta.solana.com:8001" + KNOWN_VALIDATORS=" --known-validator 7Np41oeYqPefeNQEHSv1UDhYrehxin3NStELsSKCT4K2 --known-validator GdnSyH3YtwcxFvQrVVJMm1JhTS4QVX7MFsX56uJLUfiZ --known-validator DE1bawNcRJB9rVm3buyMVfr8mBEoyyu73NBovf2oXJsJ --known-validator CakcnaRDHka2gXyfbEd2d3xsvkJkqsLw2akB3zsN1D2S" + SOLANA_METRICS_CONFIG="host=https://metrics.solana.com:8086,db=mainnet-beta,u=mainnet-beta_write,p=password" + EXPECTED_GENESIS_HASH="5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d" + ;; + "testnet") + ENTRY_POINTS=" --entrypoint entrypoint.testnet.solana.com:8001 --entrypoint entrypoint2.testnet.solana.com:8001 --entrypoint entrypoint3.testnet.solana.com:8001" + KNOWN_VALIDATORS=" --known-validator 5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on --known-validator dDzy5SR3AXdYWVqbDEkVFdvSPCtS9ihF5kJkHCtXoFs --known-validator Ft5fbkqNa76vnsjYNwjDZUXoTWpP7VYm3mtsaQckQADN --known-validator eoKpUABi59aT4rR9HGS3LcMecfut9x7zJyodWWP43YQ --known-validator 9QxCLckBiJc783jnMvXZubK4wH86Eqqvashtrwvcsgkv" + SOLANA_METRICS_CONFIG="host=https://metrics.solana.com:8086,db=tds,u=testnet_write,p=c4fa841aa918bf8274e3e2a44d77568d9861b3ea" + EXPECTED_GENESIS_HASH="4uhcVJyU9pJkvQyS88uRDiswHXSCkY3zQawwpjk2NsNY" + ;; + "devnet") + ENTRY_POINTS=" --entrypoint entrypoint.devnet.solana.com:8001 --entrypoint entrypoint2.devnet.solana.com:8001 --entrypoint entrypoint3.devnet.solana.com:8001 --entrypoint entrypoint4.devnet.solana.com:8001 --entrypoint entrypoint5.devnet.solana.com:8001" + KNOWN_VALIDATORS=" --known-validator dv1ZAGvdsz5hHLwWXsVnM94hWf1pjbKVau1QVkaMJ92 --known-validator dv2eQHeP4RFrJZ6UeiZWoc3XTtmtZCUKxxCApCDcRNV --known-validator dv4ACNkpYPcE3aKmYDqZm9G5EB3J4MRoeE7WNDRBVJB --known-validator dv3qDFk1DTF36Z62bNvrCXe9sKATA6xvVy6A798xxAS" + SOLANA_METRICS_CONFIG="host=https://metrics.solana.com:8086,db=devnet,u=scratch_writer,p=topsecret" + EXPECTED_GENESIS_HASH="EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG" + ;; + *) + echo "Solana cluster id is not valid: $SOLANA_CLUSTER_ID" + exit 1 + ;; +esac + +echo "Install and configure CloudWatch agent" +wget -q https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb +sudo dpkg -i -E amazon-cloudwatch-agent.deb + +sudo wget -q $GIT_URL/src/configs/cloudwatch-agent-config.json +sudo cp ./cloudwatch-agent-config.json /opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json + +sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \ +-a fetch-config -c file:/opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json -m ec2 -s +#sudo systemctl status amazon-cloudwatch-agent + +echo "Fine tune sysctl to prepare the system for Solana" + +sudo bash -c "cat >/etc/sysctl.d/20-solana-additionals.conf </etc/sysctl.d/20-solana-mmaps.conf </etc/sysctl.d/20-solana-udp-buffers.conf <> /etc/systemd/system.conf" + +sudo sysctl -p /etc/sysctl.d/20-solana-mmaps.conf +sudo sysctl -p /etc/sysctl.d/20-solana-udp-buffers.conf +sudo sysctl -p /etc/sysctl.d/20-solana-additionals.conf + +sudo systemctl daemon-reload + +sudo bash -c "cat >/etc/security/limits.d/90-solana-nofiles.conf </tmp/setup-instance-store-volumes.log 2>&1") | crontab - + crontab -l + + sudo /opt/setup-instance-store-volumes.sh + +else + echo "Data volume type is EBS" + + # Our data volume size is 2TB + DATA_DISC_ID=/dev/$(lsblk -lnb | awk '{if ($4== 2147483648000) {print $1}}') + sudo mkfs -t xfs $DATA_DISC_ID + sleep 10 + DATA_DISC_UUID=$(lsblk -fn -o UUID $DATA_DISC_ID) + DATA_DISC_FSTAB_CONF="UUID=$DATA_DISC_UUID /var/solana/data xfs defaults 0 2" + echo "DATA_DISC_ID="$DATA_DISC_ID + echo "DATA_DISC_UUID="$DATA_DISC_UUID + echo "DATA_DISC_FSTAB_CONF="$DATA_DISC_FSTAB_CONF + echo $DATA_DISC_FSTAB_CONF | sudo tee -a /etc/fstab + sudo mount -a +fi + +if [[ "$ACCOUNTS_DISC_TYPE" == "instancestore" ]]; then + echo "Accounts volume type is instance store" + + if [[ "$DATA_DISC_TYPE" != "instancestore" ]]; then + cd /opt + sudo wget $GIT_URL/src/scripts/setup-instance-store-volumes.sh + + sudo chmod +x /opt/setup-instance-store-volumes.sh + + (crontab -l; echo "@reboot /opt/setup-instance-store-volumes.sh >/tmp/setup-instance-store-volumes.log 2>&1") | crontab - + crontab -l + + sudo /opt/setup-instance-store-volumes.sh + + else + echo "Data and Accounts volumes are instance stores and should be both configured by now" + fi + +else + echo "Accounts volume type is EBS" + # Our accounts volume size is 500GB + ACCOUNTS_DISC_ID=/dev/$(lsblk -lnb | awk '{if ($4== 536870912000) {print $1}}') + sudo mkfs -t xfs $ACCOUNTS_DISC_ID + sleep 10 + ACCOUNTS_DISC_UUID=$(lsblk -fn -o UUID $ACCOUNTS_DISC_ID) + ACCOUNTS_DISC_FSTAB_CONF="UUID=$ACCOUNTS_DISC_UUID /var/solana/accounts xfs defaults 0 2" + echo "ACCOUNTS_DISC_ID="$ACCOUNTS_DISC_ID + echo "ACCOUNTS_DISC_UUID="$ACCOUNTS_DISC_UUID + echo "ACCOUNTS_DISC_FSTAB_CONF="$ACCOUNTS_DISC_FSTAB_CONF + echo $ACCOUNTS_DISC_FSTAB_CONF | sudo tee -a /etc/fstab + + sudo mount -a +fi + +sudo mkdir /var/solana/data/ledger + +echo 'Adding solana user and group' +sudo groupadd -g 1002 solana +sudo useradd -u 1002 -g 1002 -m -s /bin/bash solana +sudo usermod -aG sudo solana + +cd /home/solana +sudo mkdir ./bin + +echo "Download and unpack Solana" +echo "Downloading x86 binaries for version v$SOLANA_VERSION" + +sudo wget -q https://github.com/solana-labs/solana/releases/download/v$SOLANA_VERSION/solana-release-x86_64-unknown-linux-gnu.tar.bz2 +sudo tar -xjvf solana-release-x86_64-unknown-linux-gnu.tar.bz2 +sudo mv solana-release/bin/* ./bin/ + +echo "Preparing Solana start script" + +cd /home/solana/bin + +if [[ $NODE_IDENTITY_SECRET_ARN == "none" ]]; then + echo "Create node identity" + sudo ./solana-keygen new --no-passphrase -o /home/solana/config/validator-keypair.json + NODE_IDENTITY=$(sudo ./solana-keygen pubkey /home/solana/config/validator-keypair.json) + echo "Backing up node identity to AWS Secrets Manager" + sudo aws secretsmanager create-secret --name "solana-node/"$NODE_IDENTITY --description "Solana Node Identity Secret created for stack $CF_STACK_NAME" --secret-string file:///home/solana/config/validator-keypair.json --region $AWS_REGION +else + echo "Retrieving node identity from AWS Secrets Manager" + sudo aws secretsmanager get-secret-value --secret-id $NODE_IDENTITY_SECRET_ARN --query SecretString --output text --region $AWS_REGION > ~/validator-keypair.json + sudo mv ~/validator-keypair.json /home/solana/config/validator-keypair.json +fi + +if [[ "$SOLANA_NODE_TYPE" == "validator" ]]; then + if [[ $VOTE_ACCOUNT_SECRET_ARN == "none" ]]; then + echo "Create Vote Account Secret" + sudo ./solana-keygen new --no-passphrase -o /home/solana/config/vote-account-keypair.json + NODE_IDENTITY=$(sudo ./solana-keygen pubkey /home/solana/config/vote-account-keypair.json) + echo "Backing up Vote Account Secret to AWS Secrets Manager" + sudo aws secretsmanager create-secret --name "solana-node/"$NODE_IDENTITY --description "Solana Vote Account Secret created for stack $CF_STACK_NAME" --secret-string file:///home/solana/config/vote-account-keypair.json --region $AWS_REGION + + if [[ $AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN == "none" ]]; then + echo "Create Authorized Withdrawer Account Secret" + sudo ./solana-keygen new --no-passphrase -o /home/solana/config/authorized-withdrawer-keypair.json + NODE_IDENTITY=$(sudo ./solana-keygen pubkey /home/solana/config/authorized-withdrawer-keypair.json) + echo "Backing up Authorized Withdrawer Account to AWS Secrets Manager" + sudo aws secretsmanager create-secret --name "solana-node/"$NODE_IDENTITY --description "Authorized Withdrawer Account Secret created for stack $CF_STACK_NAME" --secret-string file:///home/solana/config/authorized-withdrawer-keypair.json --region $AWS_REGION + + else + echo "Retrieving Authorized Withdrawer Account Secret from AWS Secrets Manager" + sudo aws secretsmanager get-secret-value --secret-id $AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN --query SecretString --output text --region $AWS_REGION > ~/authorized-withdrawer-keypair.json + sudo mv ~/authorized-withdrawer-keypair.json /home/solana/config/authorized-withdrawer-keypair.json + fi + + if [[ $REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN != "none" ]]; then + echo "Retrieving Registration Transaction Funding Account Secret from AWS Secrets Manager" + sudo aws secretsmanager get-secret-value --secret-id $REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN --query SecretString --output text --region $AWS_REGION > ~/id.json + sudo mkdir -p /root/.config/solana + sudo mv ~/id.json /root/.config/solana/id.json + echo "Creating Vote Account on-chain" + sudo ./solana create-vote-account /home/solana/config/vote-account-keypair.json /home/solana/config/validator-keypair.json /home/solana/config/authorized-withdrawer-keypair.json + + echo "Deleting Transaction Funding Account Secret from the local disc" + sudo rm /root/.config/solana/id.json + else + echo "Vote Account not created. Please create it manually: https://docs.solana.com/running-validator/validator-start#create-vote-account" + fi + + echo "Deleting Authorized Withdrawer Account from the local disc" + sudo rm /home/solana/config/authorized-withdrawer-keypair.json + else + echo "Retrieving Vote Account Secret from AWS Secrets Manager" + sudo aws secretsmanager get-secret-value --secret-id $VOTE_ACCOUNT_SECRET_ARN --query SecretString --output text --region $AWS_REGION > ~/vote-account-keypair.json + sudo mv ~/vote-account-keypair.json /home/solana/config/vote-account-keypair.json + fi + +sudo wget -q $GIT_URL/src/scripts/node-validator-template.sh +mv ./node-validator-template.sh /home/solana/bin/validator.sh +fi + +if [[ "$SOLANA_NODE_TYPE" == "lightrpc" ]]; then + sudo wget -q $GIT_URL/src/scripts/node-light-rpc-template.sh + mv ./node-light-rpc-template.sh /home/solana/bin/validator.sh +fi + +if [[ "$SOLANA_NODE_TYPE" == "heavyrpc" ]]; then + sudo wget -q $GIT_URL/src/scripts/node-heavy-rpc-template.sh + mv ./node-heavy-rpc-template.sh /home/solana/bin/validator.sh +fi + +sed -i "s;__SOLANA_METRICS_CONFIG__;\"$SOLANA_METRICS_CONFIG\";g" /home/solana/bin/validator.sh +sed -i "s/__EXPECTED_GENESIS_HASH__/$EXPECTED_GENESIS_HASH/g" /home/solana/bin/validator.sh +sed -i "s/__KNOWN_VALIDATORS__/$KNOWN_VALIDATORS/g" /home/solana/bin/validator.sh +sed -i "s/__ENTRY_POINTS__/$ENTRY_POINTS/g" /home/solana/bin/validator.sh +sudo chmod +x /home/solana/bin/validator.sh + +echo "Making sure the solana user has access to everything needed" +sudo chown -R solana:solana /var/solana +sudo chown -R solana:solana /home/solana + +echo "Starting solana as a service" +sudo bash -c 'cat > /etc/systemd/system/sol.service < logrotate.sol </tmp/syncchecker.log 2>&1") | crontab - +crontab -l + +echo "All Done!!" \ No newline at end of file diff --git a/lib/solana/lib/common-stack.ts b/lib/solana/lib/common-stack.ts new file mode 100644 index 00000000..e106ee48 --- /dev/null +++ b/lib/solana/lib/common-stack.ts @@ -0,0 +1,63 @@ +import * as cdk from "aws-cdk-lib"; +import * as cdkConstructs from "constructs"; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as nag from "cdk-nag"; + +export interface SolanaCommonStackProps extends cdk.StackProps { + createVpcEnpointS3: boolean; + +} + +export class SolanaCommonStack extends cdk.Stack { + AWS_STACKNAME = cdk.Stack.of(this).stackName; + AWS_ACCOUNT_ID = cdk.Stack.of(this).account; + + constructor(scope: cdkConstructs.Construct, id: string, props: SolanaCommonStackProps) { + super(scope, id, props); + + const region = cdk.Stack.of(this).region; + + const instanceRole = new iam.Role(this, `node-role`, { + assumedBy: new iam.ServicePrincipal("ec2.amazonaws.com"), + managedPolicies: [ + iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"), + iam.ManagedPolicy.fromAwsManagedPolicyName("CloudWatchAgentServerPolicy"), + ], + }); + + instanceRole.addToPolicy(new iam.PolicyStatement({ + // Can't target specific stack: https://github.com/aws/aws-cdk/issues/22657 + resources: ["*"], + actions: ["cloudformation:SignalResource"], + })); + + instanceRole.addToPolicy(new iam.PolicyStatement({ + resources: [`arn:aws:autoscaling:${region}:${this.AWS_ACCOUNT_ID}:autoScalingGroup:*:autoScalingGroupName/solana-*`], + actions: ["autoscaling:CompleteLifecycleAction"], + })); + + new cdk.CfnOutput(this, "Instance Role ARN", { + value: instanceRole.roleArn, + exportName: "SolanaNodeInstanceRoleArn", + }); + + /** + * cdk-nag suppressions + */ + + nag.NagSuppressions.addResourceSuppressions( + this, + [ + { + id: "AwsSolutions-IAM4", + reason: "AmazonSSMManagedInstanceCore and CloudWatchAgentServerPolicy are restrictive enough", + }, + { + id: "AwsSolutions-IAM5", + reason: "Can't target specific stack: https://github.com/aws/aws-cdk/issues/22657", + }, + ], + true + ); + } +} diff --git a/lib/solana/lib/config/solanaConfig.interface.ts b/lib/solana/lib/config/solanaConfig.interface.ts new file mode 100644 index 00000000..cba142b6 --- /dev/null +++ b/lib/solana/lib/config/solanaConfig.interface.ts @@ -0,0 +1,30 @@ +import * as configTypes from "../../../constructs/config.interface"; + +export type SolanaCluster = "mainnet-beta" | "testnet" | "devnet"; +export type SolanaNodeConfiguration = "validator" | "lightrpc" | "heavyrpc"; + +export interface SolanaDataVolumeConfig extends configTypes.DataVolumeConfig { +} + +export interface SolanaAccountsVolumeConfig extends configTypes.DataVolumeConfig { +} + +export interface SolanaBaseConfig extends configTypes.BaseConfig { +} + +export interface SolanaBaseNodeConfig extends configTypes.BaseNodeConfig { + solanaCluster: SolanaCluster; + nodeConfiguration: SolanaNodeConfiguration; + dataVolume: SolanaDataVolumeConfig; + accountsVolume: SolanaAccountsVolumeConfig; + solanaNodeIdentitySecretARN: string; + voteAccountSecretARN: string; + authorizedWithdrawerAccountSecretARN: string; + registrationTransactionFundingAccountSecretARN: string; +} + +export interface SolanaHAConfig { + albHealthCheckGracePeriodMin: number; + heartBeatDelayMin: number; + numberOfNodes: number; +} diff --git a/lib/solana/lib/config/solanaConfig.ts b/lib/solana/lib/config/solanaConfig.ts new file mode 100644 index 00000000..04494012 --- /dev/null +++ b/lib/solana/lib/config/solanaConfig.ts @@ -0,0 +1,53 @@ +import * as ec2 from "aws-cdk-lib/aws-ec2"; +import * as configTypes from "./solanaConfig.interface"; +import * as constants from "../../../constructs/constants"; + + +const parseDataVolumeType = (dataVolumeType: string) => { + switch (dataVolumeType) { + case "gp3": + return ec2.EbsDeviceVolumeType.GP3; + case "io2": + return ec2.EbsDeviceVolumeType.IO2; + case "io1": + return ec2.EbsDeviceVolumeType.IO1; + case "instance-store": + return constants.InstanceStoreageDeviceVolumeType; + default: + return ec2.EbsDeviceVolumeType.GP3; + } +} + +export const baseConfig: configTypes.SolanaBaseConfig = { + accountId: process.env.AWS_ACCOUNT_ID || "xxxxxxxxxxx", // Set your target AWS Account ID + region: process.env.AWS_REGION || "us-east-2", // Set your target AWS Region +} + +export const baseNodeConfig: configTypes.SolanaBaseNodeConfig = { + instanceType: new ec2.InstanceType(process.env.SOLANA_INSTANCE_TYPE ? process.env.SOLANA_INSTANCE_TYPE : "r6a.8xlarge"), + instanceCpuType: process.env.SOLANA_CPU_TYPE?.toLowerCase() == "x86_64" ? ec2.AmazonLinuxCpuType.X86_64 : ec2.AmazonLinuxCpuType.ARM_64, + solanaCluster: process.env.SOLANA_CLUSTER || "mainnet-beta", // Set the Solana cluster to be used + nodeConfiguration: process.env.SOLANA_NODE_CONFIGURATION || "lightrpc", // Set the Solana node configuration to be used + dataVolume: { + sizeGiB: process.env.SOLANA_DATA_VOL_SIZE ? parseInt(process.env.SOLANA_DATA_VOL_SIZE): 2000, + type: parseDataVolumeType(process.env.SOLANA_DATA_VOL_TYPE?.toLowerCase() ? process.env.SOLANA_DATA_VOL_TYPE?.toLowerCase() : "gp3"), + iops: process.env.SOLANA_DATA_VOL_IOPS ? parseInt(process.env.SOLANA_DATA_VOL_IOPS): 12000, + throughput: process.env.SOLANA_DATA_VOL_THROUGHPUT ? parseInt(process.env.SOLANA_DATA_VOL_THROUGHPUT): 700, + }, + accountsVolume: { + sizeGiB: process.env.SOLANA_ACCOUNTS_VOL_SIZE ? parseInt(process.env.SOLANA_ACCOUNTS_VOL_SIZE): 500, + type: parseDataVolumeType(process.env.SOLANA_ACCOUNTS_VOL_TYPE?.toLowerCase() ? process.env.SOLANA_ACCOUNTS_VOL_TYPE?.toLowerCase() : "gp3"), + iops: process.env.SOLANA_ACCOUNTS_VOL_IOPS ? parseInt(process.env.SOLANA_ACCOUNTS_VOL_IOPS): 6000, + throughput: process.env.SOLANA_ACCOUNTS_VOL_THROUGHPUT ? parseInt(process.env.SOLANA_ACCOUNTS_VOL_THROUGHPUT): 700, + }, + solanaNodeIdentitySecretARN: process.env.SOLANA_NODE_IDENTITY_SECRET_ARN || "none", + voteAccountSecretARN: process.env.SOLANA_VOTE_ACCOUNT_SECRET_ARN || "none", + authorizedWithdrawerAccountSecretARN: process.env.SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN || "none", + registrationTransactionFundingAccountSecretARN: process.env.SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN || "none", +}; + +export const haNodeConfig: configTypes.SolanaHAConfig = { + albHealthCheckGracePeriodMin: process.env.SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN ? parseInt(process.env.SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN) : 10, + heartBeatDelayMin: process.env.SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN ? parseInt(process.env.SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN) : 40, + numberOfNodes: process.env.SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN ? parseInt(process.env.SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN) : 2, +}; diff --git a/lib/solana/lib/constructs/solana-node-security-group.ts b/lib/solana/lib/constructs/solana-node-security-group.ts new file mode 100644 index 00000000..09c8fa02 --- /dev/null +++ b/lib/solana/lib/constructs/solana-node-security-group.ts @@ -0,0 +1,51 @@ +import * as cdk from "aws-cdk-lib"; +import * as cdkContructs from 'constructs'; +import * as ec2 from "aws-cdk-lib/aws-ec2"; +import * as nag from "cdk-nag"; + +export interface SolanaNodeSecurityGroupConstructProps { + vpc: cdk.aws_ec2.IVpc; + } + + export class SolanaNodeSecurityGroupConstruct extends cdkContructs.Construct { + public securityGroup: cdk.aws_ec2.ISecurityGroup; + + constructor(scope: cdkContructs.Construct, id: string, props: SolanaNodeSecurityGroupConstructProps) { + super(scope, id); + + const { + vpc, + } = props; + + const sg = new ec2.SecurityGroup(this, `rpc-node-security-group`, { + vpc, + description: "Security Group for Blockchain nodes", + allowAllOutbound: true, + }); + + // Public ports + sg.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcpRange(8801, 8812), "P2P protocols (gossip, turbine, repair, etc)"); + sg.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.udpRange(8801, 8812), "P2P protocols (gossip, turbine, repair, etc)"); + + // Private ports restricted only to the VPC IP range + sg.addIngressRule(ec2.Peer.ipv4(vpc.vpcCidrBlock), ec2.Port.tcp(8899), "RPC port HTTP (user access needs to be restricted. Allowed access only from internal IPs)"); + sg.addIngressRule(ec2.Peer.ipv4(vpc.vpcCidrBlock), ec2.Port.tcp(8900), "RPC port WebSocket (user access needs to be restricted. Allowed access only from internal IPs)"); + + this.securityGroup = sg + + /** + * cdk-nag suppressions + */ + + nag.NagSuppressions.addResourceSuppressions( + this, + [ + { + id: "AwsSolutions-EC23", + reason: "Need to use wildcard for P2P ports", + }, + ], + true + ); + } + } \ No newline at end of file diff --git a/lib/solana/lib/ha-nodes-stack.ts b/lib/solana/lib/ha-nodes-stack.ts new file mode 100644 index 00000000..bf975475 --- /dev/null +++ b/lib/solana/lib/ha-nodes-stack.ts @@ -0,0 +1,127 @@ +import * as cdk from "aws-cdk-lib"; +import * as cdkConstructs from "constructs"; +import * as ec2 from "aws-cdk-lib/aws-ec2"; +import * as iam from "aws-cdk-lib/aws-iam"; +import * as s3Assets from "aws-cdk-lib/aws-s3-assets"; +import * as nag from "cdk-nag"; +import * as path from "path"; +import * as fs from "fs"; +import * as config from "./config/solanaConfig.interface"; +import * as configTypes from "./config/solanaConfig.interface"; +import { PolygonNodeSecurityGroupConstruct } from "./constructs/polygon-rpc-node-security-group" +import { HANodesConstruct } from "../../constructs/ha-rpc-nodes-with-alb" + +export interface PolygonRpcNodesStackProps extends cdk.StackProps { + polygonClientCombination: config.PolygonClientCombination; + network: configTypes.PolygonNetwork; + instanceType: ec2.InstanceType; + instanceCpuType: ec2.AmazonLinuxCpuType; + dataVolumes: config.PolygonDataVolumeConfig[], + numberOfNodes: number; + albHealthCheckGracePeriodMin: number; + heartBeatDelayMin: number; +} + +export class PolygonRpcNodesStack extends cdk.Stack { + constructor(scope: cdkConstructs.Construct, id: string, props: PolygonRpcNodesStackProps) { + super(scope, id, props); + + // Setting up necessary environment variables + const REGION = cdk.Stack.of(this).region; + const STACK_NAME = cdk.Stack.of(this).stackName; + const lifecycleHookName = STACK_NAME; + const autoScalingGroupName = STACK_NAME; + + // Getting our config from initialization properties + const { + instanceType, + polygonClientCombination, + network, + instanceCpuType, + dataVolumes, + albHealthCheckGracePeriodMin, + heartBeatDelayMin, + numberOfNodes, + } = props; + + // Using default VPC + const vpc = ec2.Vpc.fromLookup(this, "vpc", { isDefault: true }); + + // Setting up the security group for the node from Polygon-specific construct + const instanceSG = new PolygonNodeSecurityGroupConstruct (this, "security-group", { + vpc: vpc, + clientCombination: polygonClientCombination, + }) + + // Making our scripts and configis from the local "assets" directory available for instance to download + const asset = new s3Assets.Asset(this, "assets", { + path: path.join(__dirname, "assets"), + }); + + // Getting the snapshot bucket name and IAM role ARN from the common stack + const importedInstanceRoleArn = cdk.Fn.importValue("PolygonNodeInstanceRoleArn"); + const snapshotBucketName = cdk.Fn.importValue("PolygonNodeSnapshotBucketName"); + + const instanceRole = iam.Role.fromRoleArn(this, "iam-role", importedInstanceRoleArn); + + // Parsing user data script and injecting necessary variables + const nodeScript = fs.readFileSync(path.join(__dirname, "assets", "user-data", "rpc-node-start.sh")).toString(); + + const modifiedInitNodeScript = cdk.Fn.sub(nodeScript, { + _LIFECYCLE_HOOK_NAME_: lifecycleHookName, + _AUTOSCALING_GROUP_NAME_: autoScalingGroupName, + _ASSETS_S3_PATH_: `s3://${asset.s3BucketName}/${asset.s3ObjectKey}`, + _REGION_: REGION, + _SNAPSHOT_S3_PATH_: `s3://${snapshotBucketName}/${polygonClientCombination}-${network}`, + _CLIENT_COMBINATION_: polygonClientCombination, + _STACK_NAME_: STACK_NAME, + _FORMAT_DISK_: "true", + _DATA_VOLUME_TYPE_: dataVolumes[0].type, + }); + + // Setting up the nodse using generic High Availability (HA) Node constract + const rpcNodes = new HANodesConstruct (this, "rpc-nodes", { + instanceType, + dataVolumes, + machineImage: new ec2.AmazonLinuxImage({ + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, + cpuType: instanceCpuType, + }), + role: instanceRole, + vpc, + securityGroup: instanceSG.securityGroup, + userData: modifiedInitNodeScript, + numberOfNodes, + rpcPortForALB: 8545, + albHealthCheckGracePeriodMin, + heartBeatDelayMin, + lifecycleHookName: lifecycleHookName, + autoScalingGroupName: autoScalingGroupName, + }); + + // Making sure we output the URL of our Applicaiton Load Balancer + new cdk.CfnOutput(this, "alb-url", { + value: rpcNodes.loadBalancerDnsName, + }); + + // Adding suppressions to the stack + nag.NagSuppressions.addResourceSuppressions( + this, + [ + { + id: "AwsSolutions-AS3", + reason: "No notifications needed", + }, + { + id: "AwsSolutions-S1", + reason: "No access log needed for ALB logs bucket", + }, + { + id: "AwsSolutions-EC28", + reason: "Using basic monitoring to save costs", + }, + ], + true + ); + } +} diff --git a/lib/solana/lib/single-node-stack.ts b/lib/solana/lib/single-node-stack.ts new file mode 100644 index 00000000..ebcb5996 --- /dev/null +++ b/lib/solana/lib/single-node-stack.ts @@ -0,0 +1,129 @@ +import * as cdk from "aws-cdk-lib"; +import * as cdkConstructs from "constructs"; +import * as ec2 from "aws-cdk-lib/aws-ec2"; +import * as iam from "aws-cdk-lib/aws-iam"; +import * as s3Assets from "aws-cdk-lib/aws-s3-assets"; +import * as path from "path"; +import * as fs from "fs"; +import * as nodeCwDashboard from "./assets/node-cw-dashboard" +import * as cw from 'aws-cdk-lib/aws-cloudwatch'; +import { SingleNodeConstruct } from "../../constructs/single-node" +import * as configTypes from "./config/solanaConfig.interface"; +import { SolanaNodeSecurityGroupConstruct } from "./constructs/solana-node-security-group" + +export interface SolanaSingleNodeStackProps extends cdk.StackProps { + instanceType: ec2.InstanceType; + instanceCpuType: ec2.AmazonLinuxCpuType; + solanaCluster: configTypes.SolanaCluster; + nodeConfiguration: configTypes.SolanaNodeConfiguration; + dataVolume: configTypes.SolanaDataVolumeConfig; + accountsVolume: configTypes.SolanaAccountsVolumeConfig; + solanaNodeIdentitySecretARN: string; + voteAccountSecretARN: string; + authorizedWithdrawerAccountSecretARN: string; + registrationTransactionFundingAccountSecretARN: string; +} + +export class SolanaSingleNodeStack extends cdk.Stack { + constructor(scope: cdkConstructs.Construct, id: string, props: SolanaSingleNodeStackProps) { + super(scope, id, props); + + // Setting up necessary environment variables + const REGION = cdk.Stack.of(this).region; + const STACK_NAME = cdk.Stack.of(this).stackName; + const availabilityZones = cdk.Stack.of(this).availabilityZones; + const chosenAvailabilityZone = availabilityZones.slice(0, 1)[0]; + + // Getting our config from initialization properties + const { + instanceType, + instanceCpuType, + solanaCluster, + nodeConfiguration, + dataVolume, + accountsVolume, + solanaNodeIdentitySecretARN, + voteAccountSecretARN, + authorizedWithdrawerAccountSecretARN, + registrationTransactionFundingAccountSecretARN, + } = props; + + // Using default VPC + const vpc = ec2.Vpc.fromLookup(this, "vpc", { isDefault: true }); + + // Setting up the security group for the node from Solana-specific construct + const instanceSG = new SolanaNodeSecurityGroupConstruct (this, "security-group", { + vpc: vpc, + }) + + // Making our scripts and configis from the local "assets" directory available for instance to download + const asset = new s3Assets.Asset(this, "assets", { + path: path.join(__dirname, "assets"), + }); + + // Getting the snapshot bucket name and IAM role ARN from the common stack + const importedInstanceRoleArn = cdk.Fn.importValue("SolanaNodeInstanceRoleArn"); + + const instanceRole = iam.Role.fromRoleArn(this, "iam-role", importedInstanceRoleArn); + + // Making sure our instance will be able to read the assets + asset.bucket.grantRead(instanceRole); + + // Setting up the node using generic Single Node constract + if (instanceCpuType === ec2.AmazonLinuxCpuType.x86_64) { + throw new Error("ARM64 is not supported"); + } + + // Use Ubuntu 20.04 LTS image for amd64 or arm64. Find more: https://discourse.ubuntu.com/t/finding-ubuntu-images-with-the-aws-ssm-parameter-store/15507 + const ubuntu204stableImageSsmName = instanceCpuType === ec2.AmazonLinuxCpuType.X86_64 ? + "/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id" : + "/aws/service/canonical/ubuntu/server/20.04/stable/current/arm64/hvm/ebs-gp2/ami-id"; + + const node = new SingleNodeConstruct(this, "sync-node", { + instanceName: STACK_NAME, + instanceType, + dataVolumes: [dataVolume, accountsVolume], + machineImage: ec2.MachineImage.fromSsmParameter(ubuntu204stableImageSsmName), + vpc, + availabilityZone: chosenAvailabilityZone, + role: instanceRole, + securityGroup: instanceSG.securityGroup, + vpcSubnets: { + subnetType: ec2.SubnetType.PUBLIC, + }, + }); + + // Parsing user data script and injecting necessary variables + const nodeStartScript = fs.readFileSync(path.join(__dirname, "assets", "user-data", "node-start.sh")).toString(); + + const modifiedInitNodeScript = cdk.Fn.sub(nodeStartScript, { + _ASSETS_S3_PATH_: `s3://${asset.s3BucketName}/${asset.s3ObjectKey}`, + _REGION_: REGION, + _STACK_NAME_: STACK_NAME, + _RESOURCE_ID_: syncNode.nodeCFLogicalId, + _SNAPSHOT_S3_PATH_: `s3://${snapshotBucketName}/${polygonClientCombination}-${network}`, + _CLIENT_COMBINATION_: polygonClientCombination, + _NETWORK_: network, + _DATA_VOLUME_TYPE_: dataVolumes[0].type, + _FORMAT_DISK_: "true", + + }); + node.instance.addUserData(modifiedInitNodeScript); + + // Adding CloudWatch dashboard to the node + const dashboardString = cdk.Fn.sub(JSON.stringify(nodeCwDashboard.SyncNodeCWDashboardJSON), { + INSTANCE_ID:node.instanceId, + INSTANCE_NAME: STACK_NAME, + REGION: REGION, + }) + + new cw.CfnDashboard(this, 'solana-cw-dashboard', { + dashboardName: STACK_NAME, + dashboardBody: dashboardString, + }); + + new cdk.CfnOutput(this, "node-instance-id", { + value: node.instanceId, + }); + } +} diff --git a/lib/solana/package.json b/lib/solana/package.json new file mode 100644 index 00000000..55b82753 --- /dev/null +++ b/lib/solana/package.json @@ -0,0 +1,11 @@ +{ + "name": "aws-blockchain-node-runners-ethereum", + "version": "0.1.0", + "scripts": { + "build": "npx tsc", + "watch": "npx tsc -w", + "test": "npx jest", + "cdk": "npx cdk", + "scan-cdk": "npx cdk synth" + } +} diff --git a/lib/solana/sample-configs/.env-erigon-lighthouse b/lib/solana/sample-configs/.env-erigon-lighthouse new file mode 100644 index 00000000..7cfb0553 --- /dev/null +++ b/lib/solana/sample-configs/.env-erigon-lighthouse @@ -0,0 +1,29 @@ +############################################################## +# Example configuration for Ethereum nodes runner app on AWS # +############################################################## + +# Set the AWS account is and region for your environment +AWS_ACCOUNT_ID="xxxxxxxxxxx" +AWS_REGION="us-east-2" + +# Common configuration parameters +CLIENT_COMBINATION="erigon-lighthouse-mainnet" # All options: "besu-teku-mainnet" | "geth-lighthouse-mainnet" | "erigon-lighthouse-mainnet" | "erigon-prysm-mainnet" | "nethermind-teku-mainnet" + +# Sync node configuration +ETH_SYNC_INSTANCE_TYPE="m7g.2xlarge" +ETH_SYNC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used +ETH_SYNC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 +ETH_SYNC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +ETH_SYNC_DATA_VOL_IOPS="7000" # Max IOPS for EBS volumes (not applicable for "instance-store") +ETH_SYNC_DATA_VOL_THROUGHPUT="500" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") + +# RPC nodes configuration +ETH_RPC_INSTANCE_TYPE="m7g.2xlarge" +ETH_RPC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used +ETH_RPC_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 +ETH_RPC_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="10" # Time enough to initialize the instance and start downloading snpashots +ETH_RPC_HA_NODES_HEARTBEAT_DELAY_MIN="150" # Time sufficient enough for a node do download snapshot, from S3 bucket, start clients, and finish sycning the delta +ETH_RPC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 +ETH_RPC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +ETH_RPC_DATA_VOL_IOPS="10000" # Max IOPS for EBS volumes (not applicable for "instance-store") +ETH_RPC_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") diff --git a/lib/solana/sample-configs/.env-erigon-prysm b/lib/solana/sample-configs/.env-erigon-prysm new file mode 100644 index 00000000..04f0129a --- /dev/null +++ b/lib/solana/sample-configs/.env-erigon-prysm @@ -0,0 +1,29 @@ +############################################################## +# Example configuration for Ethereum nodes runner app on AWS # +############################################################## + +# Set the AWS account is and region for your environment +AWS_ACCOUNT_ID="xxxxxxxxxxx" +AWS_REGION="us-east-2" + +# Common configuration parameters +CLIENT_COMBINATION="erigon-prysm-mainnet" # All options: "besu-teku-mainnet" | "geth-lighthouse-mainnet" | "erigon-lighthouse-mainnet" | "erigon-prysm-mainnet" | "nethermind-teku-mainnet" + +# Sync node configuration +ETH_SYNC_INSTANCE_TYPE="m7g.2xlarge" +ETH_SYNC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used +ETH_SYNC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 +ETH_SYNC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +ETH_SYNC_DATA_VOL_IOPS="7000" # Max IOPS for EBS volumes (not applicable for "instance-store") +ETH_SYNC_DATA_VOL_THROUGHPUT="500" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") + +# RPC nodes configuration +ETH_RPC_INSTANCE_TYPE="m7g.2xlarge" +ETH_RPC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used +ETH_RPC_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 +ETH_RPC_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="10" # Time enough to initialize the instance and start downloading snpashots +ETH_RPC_HA_NODES_HEARTBEAT_DELAY_MIN="150" # Time sufficient enough for a node do download snapshot, from S3 bucket, start clients, and finish sycning the delta +ETH_RPC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 +ETH_RPC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +ETH_RPC_DATA_VOL_IOPS="10000" # Max IOPS for EBS volumes (not applicable for "instance-store") +ETH_RPC_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") diff --git a/lib/solana/sample-configs/.env-geth-lighthouse b/lib/solana/sample-configs/.env-geth-lighthouse new file mode 100644 index 00000000..15b69472 --- /dev/null +++ b/lib/solana/sample-configs/.env-geth-lighthouse @@ -0,0 +1,29 @@ +############################################################## +# Example configuration for Ethereum nodes runner app on AWS # +############################################################## + +# Set the AWS account is and region for your environment +AWS_ACCOUNT_ID="xxxxxxxxxxx" +AWS_REGION="us-east-2" + +# Common configuration parameters +CLIENT_COMBINATION="geth-lighthouse-mainnet" # All options: "besu-teku-mainnet" | "geth-lighthouse-mainnet" | "erigon-lighthouse-mainnet" | "erigon-prysm-mainnet" | "nethermind-teku-mainnet" + +# Sync node configuration +ETH_SYNC_INSTANCE_TYPE="m6g.2xlarge" +ETH_SYNC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used +ETH_SYNC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 +ETH_SYNC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +ETH_SYNC_DATA_VOL_IOPS="6000" # Max IOPS for EBS volumes (not applicable for "instance-store") +ETH_SYNC_DATA_VOL_THROUGHPUT="400" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") + +# RPC nodes configuration +ETH_RPC_INSTANCE_TYPE="m7g.2xlarge" +ETH_RPC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used +ETH_RPC_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 +ETH_RPC_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="10" # Time enough to initialize the instance and start downloading snpashots +ETH_RPC_HA_NODES_HEARTBEAT_DELAY_MIN="60" # Time sufficient enough for a node do download snapshot, from S3 bucket, start clients, and finish sycning the delta +ETH_RPC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 +ETH_RPC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +ETH_RPC_DATA_VOL_IOPS="8000" # Max IOPS for EBS volumes (not applicable for "instance-store") +ETH_RPC_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") diff --git a/lib/solana/test/.env-test b/lib/solana/test/.env-test new file mode 100644 index 00000000..1e775251 --- /dev/null +++ b/lib/solana/test/.env-test @@ -0,0 +1,29 @@ +############################################################## +# Example configuration for Ethereum nodes runner app on AWS # +############################################################## + +# Set the AWS account is and region for your environment +AWS_ACCOUNT_ID="1234567890" +AWS_REGION="us-east-2" + +# Common configuration parameters +CLIENT_COMBINATION="geth-lighthouse-mainnet" # All options: "besu-teku-mainnet" | "geth-lighthouse-mainnet" | "erigon-lighthouse-mainnet" | "erigon-prysm-mainnet" | "nethermind-teku-mainnet" + +# Sync node configuration +ETH_SYNC_INSTANCE_TYPE="m6g.2xlarge" +ETH_SYNC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used +ETH_SYNC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 +ETH_SYNC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +ETH_SYNC_DATA_VOL_IOPS="6000" # Max IOPS for EBS volumes (not applicable for "instance-store") +ETH_SYNC_DATA_VOL_THROUGHPUT="400" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") + +# RPC nodes configuration +ETH_RPC_INSTANCE_TYPE="m7g.2xlarge" +ETH_RPC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used +ETH_RPC_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 +ETH_RPC_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="10" # Time enough to initialize the instance and start downloading snpashots +ETH_RPC_HA_NODES_HEARTBEAT_DELAY_MIN="60" # Time sufficient enough for a node do download snapshot, from S3 bucket, start clients, and finish sycning the delta +ETH_RPC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 +ETH_RPC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +ETH_RPC_DATA_VOL_IOPS="8000" # Max IOPS for EBS volumes (not applicable for "instance-store") +ETH_RPC_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") diff --git a/lib/solana/test/common-stack.test.ts b/lib/solana/test/common-stack.test.ts new file mode 100644 index 00000000..8f10e9a7 --- /dev/null +++ b/lib/solana/test/common-stack.test.ts @@ -0,0 +1,101 @@ +import { Match, Template } from "aws-cdk-lib/assertions"; +import * as cdk from "aws-cdk-lib"; +import * as dotenv from 'dotenv'; +dotenv.config({ path: './test/.env-test' }); +import * as config from "../lib/config/solanaConfig"; +import { EthCommonStack } from "../lib/common-stack"; + +describe("EthCommonStack", () => { + test("synthesizes the way we expect", () => { + const app = new cdk.App(); + + // Create the EthCommonStack. + const ethCommonStack = new EthCommonStack(app, "eth-common", { + env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, + stackName: `eth-nodes-common`, + }); + + // Prepare the stack for assertions. + const template = Template.fromStack(ethCommonStack); + + // Has Snapshot S3 bucket. + template.hasResourceProperties("AWS::S3::Bucket", { + BucketName: Match.stringLikeRegexp("eth-snapshots*"), + AccessControl: "Private", + BucketEncryption: { + ServerSideEncryptionConfiguration: [ + { + ServerSideEncryptionByDefault: { + SSEAlgorithm: "AES256" + } + } + ] + }, + PublicAccessBlockConfiguration: { + BlockPublicAcls: true, + BlockPublicPolicy: true, + IgnorePublicAcls: true, + RestrictPublicBuckets: true + } + }); + // Has VPC endpoint for S3. + template.hasResourceProperties("AWS::EC2::VPCEndpoint", { + ServiceName: { + "Fn::Join": [ + "", + [ + "com.amazonaws.", + { + "Ref": "AWS::Region" + }, + ".s3" + ] + ] + }, + VpcEndpointType: "Gateway", + VpcId: Match.stringLikeRegexp("vpc-*") + }); + + // Has EC2 instance role. + template.hasResourceProperties("AWS::IAM::Role", { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: "sts:AssumeRole", + Effect: "Allow", + Principal: { + Service: "ec2.amazonaws.com" + } + } + ] + }, + ManagedPolicyArns: [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + Ref: "AWS::Partition" + }, + ":iam::aws:policy/AmazonSSMManagedInstanceCore" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/CloudWatchAgentServerPolicy" + ] + ] + } + ] + }) + + }); +}); \ No newline at end of file diff --git a/lib/solana/test/rpc-nodes-stack.test.ts b/lib/solana/test/rpc-nodes-stack.test.ts new file mode 100644 index 00000000..fa7e6fea --- /dev/null +++ b/lib/solana/test/rpc-nodes-stack.test.ts @@ -0,0 +1,286 @@ +import { Match, Template } from "aws-cdk-lib/assertions"; +import * as cdk from "aws-cdk-lib"; +import * as dotenv from 'dotenv'; +dotenv.config({ path: './test/.env-test' }); +import * as config from "../lib/config/solanaConfig"; +import { EthRpcNodesStack } from "../lib/ha-nodes-stack"; + +describe("EthRpcNodesStack", () => { + test("synthesizes the way we expect", () => { + const app = new cdk.App(); + + // Create the EthRpcNodesStack. + const ethRpcNodesStack = new EthRpcNodesStack(app, "eth-sync-node", { + stackName: `eth-rpc-nodes-${config.baseConfig.clientCombination}`, + + env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, + PolygonClientCombination: config.baseConfig.clientCombination, + instanceType: config.rpcNodeConfig.instanceType, + instanceCpuType: config.rpcNodeConfig.instanceCpuType, + numberOfNodes: config.rpcNodeConfig.numberOfNodes, + albHealthCheckGracePeriodMin: config.rpcNodeConfig.albHealthCheckGracePeriodMin, + heartBeatDelayMin: config.rpcNodeConfig.heartBeatDelayMin, + dataVolumes: config.syncNodeConfig.dataVolumes, + }); + + // Prepare the stack for assertions. + const template = Template.fromStack(ethRpcNodesStack); + + // Has EC2 instance security group. + template.hasResourceProperties("AWS::EC2::SecurityGroup", { + GroupDescription: Match.anyValue(), + VpcId: Match.anyValue(), + SecurityGroupEgress: [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + SecurityGroupIngress: [ + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P", + "FromPort": 30303, + "IpProtocol": "tcp", + "ToPort": 30303 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P", + "FromPort": 30303, + "IpProtocol": "udp", + "ToPort": 30303 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P", + "FromPort": 30304, + "IpProtocol": "tcp", + "ToPort": 30304 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P", + "FromPort": 30304, + "IpProtocol": "udp", + "ToPort": 30304 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "CL Client P2P", + "FromPort": 9000, + "IpProtocol": "tcp", + "ToPort": 9000 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "CL Client P2P", + "FromPort": 9000, + "IpProtocol": "udp", + "ToPort": 9000 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "CL Client API", + "FromPort": 5051, + "IpProtocol": "tcp", + "ToPort": 5051 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "CL Client API", + "FromPort": 5052, + "IpProtocol": "tcp", + "ToPort": 5052 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "EL Client RPC (Auth)", + "FromPort": 8551, + "IpProtocol": "tcp", + "ToPort": 8551 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "EL Client RPC", + "FromPort": 8545, + "IpProtocol": "tcp", + "ToPort": 8545 + }, + { + "Description": Match.anyValue(), + "FromPort": 0, + "IpProtocol": "tcp", + "SourceSecurityGroupId": Match.anyValue(), + "ToPort": 65535 + } + ] + }) + + // Has security group from ALB to EC2. + template.hasResourceProperties("AWS::EC2::SecurityGroupIngress", { + Description: Match.anyValue(), + FromPort: 8545, + GroupId: Match.anyValue(), + IpProtocol: "tcp", + SourceSecurityGroupId: Match.anyValue(), + ToPort: 8545, + }) + + // Has launch template profile for EC2 instances. + template.hasResourceProperties("AWS::IAM::InstanceProfile", { + Roles: [Match.anyValue()] + }); + + // Has EC2 launch template. + template.hasResourceProperties("AWS::EC2::LaunchTemplate", { + LaunchTemplateData: { + BlockDeviceMappings: [ + { + "DeviceName": "/dev/xvda", + "Ebs": { + "DeleteOnTermination": true, + "Encrypted": true, + "Iops": 3000, + "Throughput": 125, + "VolumeSize": 46, + "VolumeType": "gp3" + } + }, + { + "DeviceName": "/dev/sdf", + "Ebs": { + "DeleteOnTermination": true, + "Encrypted": true, + "Iops": 6000, + "Throughput": 400, + "VolumeSize": 3072, + "VolumeType": "gp3" + } + } + ], + EbsOptimized: true, + IamInstanceProfile: Match.anyValue(), + ImageId: Match.anyValue(), + InstanceType:"m7g.2xlarge", + SecurityGroupIds: [Match.anyValue()], + UserData: Match.anyValue() + } + }) + + // Has Auto Scaling Group. + template.hasResourceProperties("AWS::AutoScaling::AutoScalingGroup", { + AutoScalingGroupName: `eth-rpc-nodes-${config.baseConfig.clientCombination}`, + HealthCheckGracePeriod: config.rpcNodeConfig.albHealthCheckGracePeriodMin * 60, + HealthCheckType: "ELB", + DefaultInstanceWarmup: 60, + MinSize: "0", + MaxSize: "4", + DesiredCapacity: config.rpcNodeConfig.numberOfNodes.toString(), + VPCZoneIdentifier: Match.anyValue(), + TargetGroupARNs: Match.anyValue(), + }); + + // Has Auto Scaling Lifecycle Hook. + template.hasResourceProperties("AWS::AutoScaling::LifecycleHook", { + DefaultResult: "ABANDON", + HeartbeatTimeout: config.rpcNodeConfig.heartBeatDelayMin * 60, + LifecycleHookName: `eth-rpc-nodes-${config.baseConfig.clientCombination}`, + LifecycleTransition: "autoscaling:EC2_INSTANCE_LAUNCHING", + }); + + // Has Auto Scaling Security Group. + template.hasResourceProperties("AWS::EC2::SecurityGroup", { + GroupDescription: Match.anyValue(), + SecurityGroupEgress: [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + SecurityGroupIngress: [ + { + "CidrIp": "1.2.3.4/5", + "Description": "Blockchain Node RPC", + "FromPort": 8545, + "IpProtocol": "tcp", + "ToPort": 8545 + } + ], + VpcId: Match.anyValue(), + }); + + // Has ALB. + template.hasResourceProperties("AWS::ElasticLoadBalancingV2::LoadBalancer", { + LoadBalancerAttributes: [ + { + Key: "deletion_protection.enabled", + Value: "false" + }, + { + Key: "access_logs.s3.enabled", + Value: "true" + }, + { + Key: "access_logs.s3.bucket", + Value: Match.anyValue(), + }, + { + Key: "access_logs.s3.prefix", + Value: `eth-rpc-nodes-${config.baseConfig.clientCombination}` + } + ], + Scheme: "internal", + SecurityGroups: [ + Match.anyValue() + ], + "Subnets": [ + Match.anyValue(), + Match.anyValue() + ], + Type: "application", + }); + + // Has ALB listener. + template.hasResourceProperties("AWS::ElasticLoadBalancingV2::Listener", { + "DefaultActions": [ + { + "TargetGroupArn": Match.anyValue(), + Type: "forward" + } + ], + LoadBalancerArn: Match.anyValue(), + Port: 8545, + Protocol: "HTTP" + }) + + // Has ALB target group. + template.hasResourceProperties("AWS::ElasticLoadBalancingV2::TargetGroup", { + HealthCheckEnabled: true, + HealthCheckIntervalSeconds: 30, + HealthCheckPath: "/", + HealthCheckPort: "8545", + HealthyThresholdCount: 3, + Matcher: { + HttpCode: "200-299" + }, + Port: 8545, + Protocol: "HTTP", + TargetGroupAttributes: [ + { + Key: "deregistration_delay.timeout_seconds", + Value: "30" + }, + { + Key: "stickiness.enabled", + Value: "false" + } + ], + TargetType: "instance", + UnhealthyThresholdCount: 2, + VpcId: Match.anyValue(), + }) + }); +}); \ No newline at end of file diff --git a/lib/solana/test/sync-node-stack.test.ts b/lib/solana/test/sync-node-stack.test.ts new file mode 100644 index 00000000..dcb8bbf0 --- /dev/null +++ b/lib/solana/test/sync-node-stack.test.ts @@ -0,0 +1,161 @@ +import { Match, Template } from "aws-cdk-lib/assertions"; +import * as cdk from "aws-cdk-lib"; +import * as dotenv from 'dotenv'; +dotenv.config({ path: './test/.env-test' }); +import * as config from "../lib/config/solanaConfig"; +import { EthSyncNodeStack } from "../lib/single-node-stack"; + +describe("EthSyncNodeStack", () => { + test("synthesizes the way we expect", () => { + const app = new cdk.App(); + + // Create the EthSyncNodeStack. + const ethSyncNodeStack = new EthSyncNodeStack(app, "eth-sync-node", { + stackName: `eth-sync-node-${config.baseConfig.clientCombination}`, + + env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, + PolygonClientCombination: config.baseConfig.clientCombination, + instanceType: config.syncNodeConfig.instanceType, + instanceCpuType: config.syncNodeConfig.instanceCpuType, + dataVolumes: config.syncNodeConfig.dataVolumes, + }); + + // Prepare the stack for assertions. + const template = Template.fromStack(ethSyncNodeStack); + + // Has EC2 instance security group. + template.hasResourceProperties("AWS::EC2::SecurityGroup", { + GroupDescription: Match.anyValue(), + VpcId: Match.anyValue(), + SecurityGroupEgress: [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + SecurityGroupIngress: [ + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P", + "FromPort": 30303, + "IpProtocol": "tcp", + "ToPort": 30303 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P", + "FromPort": 30303, + "IpProtocol": "udp", + "ToPort": 30303 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P", + "FromPort": 30304, + "IpProtocol": "tcp", + "ToPort": 30304 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P", + "FromPort": 30304, + "IpProtocol": "udp", + "ToPort": 30304 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "CL Client P2P", + "FromPort": 9000, + "IpProtocol": "tcp", + "ToPort": 9000 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "CL Client P2P", + "FromPort": 9000, + "IpProtocol": "udp", + "ToPort": 9000 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "CL Client API", + "FromPort": 5051, + "IpProtocol": "tcp", + "ToPort": 5051 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "CL Client API", + "FromPort": 5052, + "IpProtocol": "tcp", + "ToPort": 5052 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "EL Client RPC (Auth)", + "FromPort": 8551, + "IpProtocol": "tcp", + "ToPort": 8551 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "EL Client RPC", + "FromPort": 8545, + "IpProtocol": "tcp", + "ToPort": 8545 + } + ] + }) + + // Has EC2 instance with node configuration + template.hasResourceProperties("AWS::EC2::Instance", { + AvailabilityZone: Match.anyValue(), + UserData: Match.anyValue(), + BlockDeviceMappings: [ + { + DeviceName: "/dev/xvda", + Ebs: { + DeleteOnTermination: true, + Encrypted: true, + Iops: 3000, + VolumeSize: 46, + VolumeType: "gp3" + } + } + ], + IamInstanceProfile: Match.anyValue(), + ImageId: Match.anyValue(), + InstanceType: "m6g.2xlarge", + Monitoring: true, + PropagateTagsToVolumeOnCreation: true, + SecurityGroupIds: Match.anyValue(), + SubnetId: Match.anyValue(), + }) + + // Has EBS data volume. + template.hasResourceProperties("AWS::EC2::Volume", { + AvailabilityZone: Match.anyValue(), + Encrypted: true, + Iops: 6000, + MultiAttachEnabled: false, + Size: 3072, + Throughput: 400, + VolumeType: "gp3" + }) + + // Has EBS data volume attachment. + template.hasResourceProperties("AWS::EC2::VolumeAttachment", { + Device: "/dev/sdf", + InstanceId: Match.anyValue(), + VolumeId: Match.anyValue(), + }) + + // Has CloudWatch dashboard. + template.hasResourceProperties("AWS::CloudWatch::Dashboard", { + DashboardBody: Match.anyValue(), + DashboardName: `eth-sync-node-${config.baseConfig.clientCombination}` + }) + + }); +}); \ No newline at end of file From dcf2795b201e90de930604b57d2765cacd8a728b Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Wed, 4 Oct 2023 18:18:47 +1100 Subject: [PATCH 02/12] [WIP] Solana nodes testing --- lib/solana/.env-sample | 9 +- lib/solana/README.md | 18 +- lib/solana/app.ts | 60 ++++--- lib/solana/ha-nodes-deploy.json | 5 + .../lib/assets/cfn-hup/cfn-auto-reloader.conf | 4 + lib/solana/lib/assets/cfn-hup/cfn-hup.conf | 5 + lib/solana/lib/assets/cfn-hup/cfn-hup.service | 8 + lib/solana/lib/assets/cw-agent.json | 15 -- lib/solana/lib/assets/init-data-vol-ebs.sh | 53 ------ .../assets/init-data-vol-instance-store.sh | 37 ---- lib/solana/lib/assets/node-cw-dashboard.ts | 113 ++++++------ .../assets/setup-instance-store-volumes.sh | 78 +++++++++ .../assets/solana/node-heavy-rpc-template.sh | 41 +++++ .../assets/solana/node-light-rpc-template.sh | 36 ++++ .../assets/solana/node-validator-template.sh | 26 +++ .../syncchecker-bor-hemdall-mainnet.sh | 65 ------- .../assets/sync-checker/syncchecker-solana.sh | 32 ++++ .../lib/assets/user-data/node-start copy.sh | 149 ---------------- .../user-data/{node-start.sh => node.sh} | 161 +++++++++++------- lib/solana/lib/common-stack.ts | 2 +- .../lib/config/solanaConfig.interface.ts | 1 + lib/solana/lib/config/solanaConfig.ts | 13 +- lib/solana/lib/ha-nodes-stack.ts | 96 +++++++---- lib/solana/lib/single-node-stack.ts | 59 +++++-- .../sample-configs/.env-erigon-lighthouse | 29 ---- lib/solana/sample-configs/.env-erigon-prysm | 29 ---- .../sample-configs/.env-geth-lighthouse | 29 ---- .../sample-configs/.env-sample-heavyrpc | 36 ++++ .../sample-configs/.env-sample-lightrpc | 36 ++++ .../sample-configs/.env-sample-validator | 36 ++++ lib/solana/single-node-deploy.json | 5 + 31 files changed, 683 insertions(+), 603 deletions(-) create mode 100644 lib/solana/ha-nodes-deploy.json create mode 100644 lib/solana/lib/assets/cfn-hup/cfn-auto-reloader.conf create mode 100644 lib/solana/lib/assets/cfn-hup/cfn-hup.conf create mode 100644 lib/solana/lib/assets/cfn-hup/cfn-hup.service delete mode 100644 lib/solana/lib/assets/init-data-vol-ebs.sh delete mode 100644 lib/solana/lib/assets/init-data-vol-instance-store.sh create mode 100644 lib/solana/lib/assets/setup-instance-store-volumes.sh create mode 100644 lib/solana/lib/assets/solana/node-heavy-rpc-template.sh create mode 100644 lib/solana/lib/assets/solana/node-light-rpc-template.sh create mode 100644 lib/solana/lib/assets/solana/node-validator-template.sh delete mode 100644 lib/solana/lib/assets/sync-checker/syncchecker-bor-hemdall-mainnet.sh create mode 100644 lib/solana/lib/assets/sync-checker/syncchecker-solana.sh delete mode 100644 lib/solana/lib/assets/user-data/node-start copy.sh rename lib/solana/lib/assets/user-data/{node-start.sh => node.sh} (69%) delete mode 100644 lib/solana/sample-configs/.env-erigon-lighthouse delete mode 100644 lib/solana/sample-configs/.env-erigon-prysm delete mode 100644 lib/solana/sample-configs/.env-geth-lighthouse create mode 100644 lib/solana/sample-configs/.env-sample-heavyrpc create mode 100644 lib/solana/sample-configs/.env-sample-lightrpc create mode 100644 lib/solana/sample-configs/.env-sample-validator create mode 100644 lib/solana/single-node-deploy.json diff --git a/lib/solana/.env-sample b/lib/solana/.env-sample index c91d7d7d..2031bfa0 100644 --- a/lib/solana/.env-sample +++ b/lib/solana/.env-sample @@ -8,7 +8,9 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" -SOLANA_NODE_CONF="lightrpc" # All options: "validator", "lightrpc", "heavyrpc" +SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "validator", "lightrpc", "heavyrpc" +SOLANA_VERSION="1.16.2" # Current required version of Solana + SOLANA_INSTANCE_TYPE="r6a.8xlarge" SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used # Data volume configuration @@ -29,5 +31,6 @@ SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for ## HA nodes configuration ## SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 -SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="10" # Time enough to initialize the instance -SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="40" # Time sufficient enough for a node do download snapshot, from S3 bucket, start clients, and finish sycning the delta +SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="60" # Time enough to initialize the instance +SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="60" # Time sufficient enough for a node do sync + diff --git a/lib/solana/README.md b/lib/solana/README.md index fd9dccc2..6035038e 100644 --- a/lib/solana/README.md +++ b/lib/solana/README.md @@ -16,6 +16,7 @@ Solana nodes on AWS can be deployes in 3 different configurations: Validator, Li ### HA setup ![Highly Available Nodes Deployment](./doc/assets/Architecture-HANodes.drawio.png) + 1. A set of Solana nodes are deployed within the [Auto Scaling Group](https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-groups.html) in the [Default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) continuesly synchronizes with the rest of nodes on [Solana Clusters](https://docs.solana.com/clusters) through [Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html). 2. The Solana nodes are accessed by dApps or development tools internallythrough [Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html). JSON RPC API is not exposed to the Internet to protect nodes from unauthorized access. dApps need to handle user authentication and API protection, like [in this example for dApps on AWS](https://aws.amazon.com/blogs/architecture/dapp-authentication-with-amazon-cognito-and-web3-proxy-with-amazon-api-gateway/). 3. The Solanna nodes use all required secrets locally, but store a copy in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) as secure backup. @@ -102,7 +103,7 @@ Create your own copy of `.env` file and edit it: ### Deploy the HA Nodes -1. Configure and deploy 2 HA Nodes +1. Configure and deploy multiple HA Nodes ```bash pwd @@ -124,8 +125,7 @@ Create your own copy of `.env` file and edit it: The result should be like this (the actual balance might change): ```javascript - {"jsonrpc":"2.0","id":1,"result":"14,870,473.061882488SOL -"} + {"jsonrpc":"2.0","result":{"context":{"apiVersion":"1.16.2","slot":221433176},"value":12870473061872488},"id":1} ``` If the nodes are still starting and catching up with the chain, you will see the following repsonse: @@ -200,6 +200,18 @@ The result should be like this (the actual balance might change): aws ssm start-session --target $INSTANCE_ID --region $AWS_REGION sudo systemctl status sol ``` +4. How to upload a secret to AWS Secrets Manager? +```bash + # Create key pair + sudo ./solana-keygen new --no-passphrase -o /tmp/keypair.json + SOLANA_ADDRESS=$(sudo ./solana-keygen pubkey /tmp/keypair.json) + # Upload key pair to AWS Secrets Manager" + export AWS_REGION= + sudo aws secretsmanager create-secret --name "solana/"$SOLANA_ADDRESS --description "Solana secret key pair" --secret-string file:///tmp/keypair.json --region $AWS_REGION + #Delete key pair from the local file system + rm -rf /tmp/keypair.json + +``` ## Upgrades diff --git a/lib/solana/app.ts b/lib/solana/app.ts index 6c0ba821..c666c53f 100644 --- a/lib/solana/app.ts +++ b/lib/solana/app.ts @@ -5,42 +5,50 @@ import * as cdk from "aws-cdk-lib"; import * as nag from "cdk-nag"; import * as config from "./lib/config/solanaConfig"; -import { PolygonSyncNodeStack } from "./lib/single-node-stack"; -import { PolygonCommonStack } from "./lib/common-stack"; -import { PolygonRpcNodesStack } from "./lib/ha-nodes-stack"; +import { SolanaSingleNodeStack } from "./lib/single-node-stack"; +import { SolanaCommonStack } from "./lib/common-stack"; +import { SolanaHANodesStack } from "./lib/ha-nodes-stack"; const app = new cdk.App(); -cdk.Tags.of(app).add("Project", "AWSPolygon"); +cdk.Tags.of(app).add("Project", "AWSSolana"); -new PolygonCommonStack(app, "polygon-common", { +new SolanaCommonStack(app, "solana-common", { + stackName: `solana-nodes-common`, env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, - stackName: `polygon-nodes-common`, - createVpcEnpointS3: config.baseConfig.createVpcEnpointS3, }); -new PolygonSyncNodeStack(app, "polygon-sync-node", { - stackName: `polygon-sync-node-${config.baseConfig.clientCombination}`, - +new SolanaSingleNodeStack(app, "solana-single-node", { + stackName: `solana-single-node-${config.baseNodeConfig.nodeConfiguration}`, env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, - polygonClientCombination: config.baseConfig.clientCombination, - network: config.baseConfig.network, - instanceType: config.syncNodeConfig.instanceType, - instanceCpuType: config.syncNodeConfig.instanceCpuType, - dataVolumes: config.syncNodeConfig.dataVolumes, -}); -new PolygonRpcNodesStack(app, "polygon-rpc-nodes", { - stackName: `polygon-rpc-nodes-${config.baseConfig.clientCombination}`, + instanceType: config.baseNodeConfig.instanceType, + instanceCpuType: config.baseNodeConfig.instanceCpuType, + solanaCluster: config.baseNodeConfig.solanaCluster, + solanaVersion: config.baseNodeConfig.solanaVersion, + nodeConfiguration: config.baseNodeConfig.nodeConfiguration, + dataVolume: config.baseNodeConfig.dataVolume, + accountsVolume: config.baseNodeConfig.accountsVolume, + solanaNodeIdentitySecretARN: config.baseNodeConfig.solanaNodeIdentitySecretARN, + voteAccountSecretARN: config.baseNodeConfig.voteAccountSecretARN, + authorizedWithdrawerAccountSecretARN: config.baseNodeConfig.authorizedWithdrawerAccountSecretARN, + registrationTransactionFundingAccountSecretARN: config.baseNodeConfig.registrationTransactionFundingAccountSecretARN, +}); +new SolanaHANodesStack(app, "solana-ha-nodes", { + stackName: `solana-ha-nodes-${config.baseNodeConfig.nodeConfiguration}`, env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, - polygonClientCombination: config.baseConfig.clientCombination, - network: config.baseConfig.network, - instanceType: config.rpcNodeConfig.instanceType, - instanceCpuType: config.rpcNodeConfig.instanceCpuType, - numberOfNodes: config.rpcNodeConfig.numberOfNodes, - albHealthCheckGracePeriodMin: config.rpcNodeConfig.albHealthCheckGracePeriodMin, - heartBeatDelayMin: config.rpcNodeConfig.heartBeatDelayMin, - dataVolumes: config.syncNodeConfig.dataVolumes, + + instanceType: config.baseNodeConfig.instanceType, + instanceCpuType: config.baseNodeConfig.instanceCpuType, + solanaCluster: config.baseNodeConfig.solanaCluster, + solanaVersion: config.baseNodeConfig.solanaVersion, + nodeConfiguration: config.baseNodeConfig.nodeConfiguration, + dataVolume: config.baseNodeConfig.dataVolume, + accountsVolume: config.baseNodeConfig.accountsVolume, + + albHealthCheckGracePeriodMin: config.haNodeConfig.albHealthCheckGracePeriodMin, + heartBeatDelayMin: config.haNodeConfig.heartBeatDelayMin, + numberOfNodes: config.haNodeConfig.numberOfNodes, }); diff --git a/lib/solana/ha-nodes-deploy.json b/lib/solana/ha-nodes-deploy.json new file mode 100644 index 00000000..fb70e87b --- /dev/null +++ b/lib/solana/ha-nodes-deploy.json @@ -0,0 +1,5 @@ +{ + "solana-ha-nodes-lightrpc": { + "alburl": "internal-solan-rpcno-1KV8RF4TNOORQ-203724879.us-east-2.elb.amazonaws.com" + } +} diff --git a/lib/solana/lib/assets/cfn-hup/cfn-auto-reloader.conf b/lib/solana/lib/assets/cfn-hup/cfn-auto-reloader.conf new file mode 100644 index 00000000..35bb46f8 --- /dev/null +++ b/lib/solana/lib/assets/cfn-hup/cfn-auto-reloader.conf @@ -0,0 +1,4 @@ +[cfn-auto-reloader-hook] +triggers=post.update +path=Resources.WebServerHost.Metadata.AWS::CloudFormation::Init +action=/opt/aws/bin/cfn-init -v --stack __AWS_STACK_NAME__ --resource WebServerHost --region __AWS_REGION__ \ No newline at end of file diff --git a/lib/solana/lib/assets/cfn-hup/cfn-hup.conf b/lib/solana/lib/assets/cfn-hup/cfn-hup.conf new file mode 100644 index 00000000..4504c8c5 --- /dev/null +++ b/lib/solana/lib/assets/cfn-hup/cfn-hup.conf @@ -0,0 +1,5 @@ +[main] +stack=__AWS_STACK_ID__ +region=__AWS_REGION__ +# The interval used to check for changes to the resource metadata in minutes. Default is 15 +interval=2 \ No newline at end of file diff --git a/lib/solana/lib/assets/cfn-hup/cfn-hup.service b/lib/solana/lib/assets/cfn-hup/cfn-hup.service new file mode 100644 index 00000000..992ceb69 --- /dev/null +++ b/lib/solana/lib/assets/cfn-hup/cfn-hup.service @@ -0,0 +1,8 @@ +[Unit] +Description=cfn-hup daemon +[Service] +Type=simple +ExecStart=/usr/local/bin/cfn-hup +Restart=always +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/lib/solana/lib/assets/cw-agent.json b/lib/solana/lib/assets/cw-agent.json index b4f3d972..b0d696f3 100644 --- a/lib/solana/lib/assets/cw-agent.json +++ b/lib/solana/lib/assets/cw-agent.json @@ -3,21 +3,6 @@ "metrics_collection_interval": 60, "run_as_user": "root" }, - "logs": { - "logs_collected": { - "files": { - "collect_list": [{ - "file_path": "/var/log/cloud-init-output.log", - "log_group_name": "cloud-init-output.log", - "log_stream_name": "{instance_id}" - }, { - "file_path": "/var/log/initial-sync.log", - "log_group_name": "initial-sync.log", - "log_stream_name": "{instance_id}" - }] - } - } - }, "metrics": { "aggregation_dimensions": [ [ diff --git a/lib/solana/lib/assets/init-data-vol-ebs.sh b/lib/solana/lib/assets/init-data-vol-ebs.sh deleted file mode 100644 index 73a8ea5a..00000000 --- a/lib/solana/lib/assets/init-data-vol-ebs.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -set +e - -FORMAT_VOLUME=${_FORMAT_VOLUME_} - -# Check if all parameters are provided -if [ "$#" -ne 1 ]; then - echo "Usage: bash [FORMAT_VOLUME]" - echo "FORMAT_VOLUME: true or false" - exit 1 -fi - -# Assign parameters to variables -FORMAT_VOLUME="$1" - -export DATA_VOLUME_NAME=nvme1n1 -export DATA_VOLUME_ID=/dev/$DATA_VOLUME_NAME -export DATA_DIRECTORY=/data - -mkdir -p $DATA_DIRECTORY - -echo "Preparing EBS data volume" - -echo "Wait for one minute for the volume to be available" -sleep 60 - -if $(lsblk | grep -q $DATA_VOLUME_NAME); then - echo "$DATA_VOLUME_NAME is found. Configuring attached storage" - - if [ "$FORMAT_VOLUME" == "false" ]; then - echo "Not creating a new filesystem in the VOLUME. Existing data might be present!!" - else - mkfs -t ext4 $DATA_VOLUME_ID - fi - - sleep 10 - # Define the line to add to fstab - DATA_VOLUME_UUID=$(lsblk -n -o UUID $DATA_VOLUME_ID) - line="UUID=$DATA_VOLUME_UUID $DATA_DIRECTORY ext4 defaults 0 2" - - # Write the line to fstab - echo $line | sudo tee -a /etc/fstab - - mount -a - -else - echo "nvme1n1 is not found. Not doing anything" -fi - -lsblk -d - -chown -R bcuser:bcuser $DATA_DIRECTORY -chmod -R 755 $DATA_DIRECTORY \ No newline at end of file diff --git a/lib/solana/lib/assets/init-data-vol-instance-store.sh b/lib/solana/lib/assets/init-data-vol-instance-store.sh deleted file mode 100644 index 167a418a..00000000 --- a/lib/solana/lib/assets/init-data-vol-instance-store.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -set +e - -echo "Preparing instance store data volume" -export DATA_VOLUME_ID=/dev/nvme1n1 -export DATA_DIRECTORY=/data - -mkdir -p $DATA_DIRECTORY - -echo "If Data volume is mounted, dont do anything" -if [ $(df --output=target | grep -c "$DATA_DIRECTORY") -lt 1 ]; then - echo "Checking fstab for Data volume" - - sudo mkfs.xfs -f $DATA_VOLUME_ID - sleep 10 - DATA_VOLUME_UUID=$(lsblk -fn -o UUID $DATA_VOLUME_ID) - DATA_VOLUME_FSTAB_CONF="UUID=$DATA_VOLUME_UUID $DATA_DIRECTORY xfs defaults 0 2" - echo "DATA_VOLUME_ID="$DATA_VOLUME_ID - echo "DATA_VOLUME_UUID="$DATA_VOLUME_UUID - echo "DATA_VOLUME_FSTAB_CONF="$DATA_VOLUME_FSTAB_CONF - - # Check if data disc is already in fstab and replace the line if it is with the new disc UUID - if [ $(grep -c "$DATA_DIRECTORY" /etc/fstab) -gt 0 ]; then - SED_REPLACEMENT_STRING="$(grep -n "$DATA_DIRECTORY" /etc/fstab | cut -d: -f1)s#.*#$DATA_VOLUME_FSTAB_CONF#" - sudo cp /etc/fstab /etc/fstab.bak - sudo sed -i "$SED_REPLACEMENT_STRING" /etc/fstab - else - echo $DATA_VOLUME_FSTAB_CONF | sudo tee -a /etc/fstab - fi - - sudo mount -a - - chown -R bcuser:bcuser $DATA_DIRECTORY - chmod -R 755 $DATA_DIRECTORY -else - echo "Data volume is mounted, nothing changed" -fi \ No newline at end of file diff --git a/lib/solana/lib/assets/node-cw-dashboard.ts b/lib/solana/lib/assets/node-cw-dashboard.ts index 587bf65b..1f0e679e 100644 --- a/lib/solana/lib/assets/node-cw-dashboard.ts +++ b/lib/solana/lib/assets/node-cw-dashboard.ts @@ -1,4 +1,4 @@ -export const SyncNodeCWDashboardJSON = { +export const SingleNodeCWDashboardJSON = { "widgets": [ { "height": 5, @@ -24,9 +24,9 @@ export const SyncNodeCWDashboardJSON = { } }, { - "height": 5, + "height": 3, "width": 6, - "y": 5, + "y": 8, "x": 18, "type": "metric", "properties": { @@ -47,9 +47,9 @@ export const SyncNodeCWDashboardJSON = { } }, { - "height": 5, + "height": 4, "width": 6, - "y": 0, + "y": 11, "x": 18, "type": "metric", "properties": { @@ -127,52 +127,56 @@ export const SyncNodeCWDashboardJSON = { } }, { - "height": 4, + "height": 5, "width": 6, "y": 0, "x": 12, "type": "metric", "properties": { "metrics": [ - [ "CWAgent", "elc_sync_block", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + [ { "expression": "m7/PERIOD(m7)", "label": "Write", "id": "e7", "region": "${REGION}" } ], + [ "CWAgent", "diskio_writes", "InstanceId", "${INSTANCE_ID}", "name", "nvme2n1", { "id": "m7", "visible": false, "stat": "Sum", "period": 60 } ], + [ { "expression": "m8/PERIOD(m8)", "label": "Read", "id": "e8", "region": "${REGION}" } ], + [ "CWAgent", "diskio_reads", "InstanceId", "${INSTANCE_ID}", "name", "nvme2n1", { "id": "m8", "visible": false, "stat": "Sum", "period": 60 } ] ], - "sparkline": true, "view": "timeSeries", "stacked": false, "region": "${REGION}", - "stat": "Maximum", - "period": 60, - "title": "Execution Client Block Height" + "stat": "Average", + "period": 300, + "title": "nvme2n1 Volume Read/Write (IO/sec)" } }, { - "height": 4, + "height": 5, "width": 6, - "y": 4, + "y": 10, "x": 12, "type": "metric", "properties": { - "sparkline": true, + "metrics": [ + [ { "expression": "m2/PERIOD(m2)", "label": "Read", "id": "e2", "period": 60, "region": "${REGION}" } ], + [ "CWAgent", "diskio_read_bytes", "InstanceId", "${INSTANCE_ID}", "name", "nvme2n1", { "id": "m2", "stat": "Sum", "visible": false, "period": 60 } ], + [ { "expression": "m3/PERIOD(m3)", "label": "Write", "id": "e3", "period": 60, "region": "${REGION}" } ], + [ "CWAgent", "diskio_write_bytes", "InstanceId", "${INSTANCE_ID}", "name", "nvme2n1", { "id": "m3", "stat": "Sum", "visible": false, "period": 60 } ] + ], "view": "timeSeries", "stacked": false, "region": "${REGION}", - "stat": "Maximum", + "stat": "Average", "period": 60, - "metrics": [ - [ "CWAgent", "elc_blocks_behind", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] - ], - "title": "Execution Client Blocks Behind" + "title": "nvme2n1 Volume Read/Write throughput (bytes/sec)" } }, { - "height": 3, + "height": 4, "width": 6, - "y": 8, - "x": 12, + "y": 0, + "x": 18, "type": "metric", "properties": { "metrics": [ - [ "CWAgent", "clc_head_slot", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + [ "CWAgent", "solana_block_height", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] ], "sparkline": true, "view": "timeSeries", @@ -180,14 +184,14 @@ export const SyncNodeCWDashboardJSON = { "region": "${REGION}", "stat": "Maximum", "period": 60, - "title": "Consensus Client Head Slot" + "title": "Solana Block Height" } }, { "height": 4, "width": 6, - "y": 11, - "x": 12, + "y": 4, + "x": 18, "type": "metric", "properties": { "sparkline": true, @@ -197,9 +201,38 @@ export const SyncNodeCWDashboardJSON = { "stat": "Maximum", "period": 60, "metrics": [ - [ "CWAgent", "clc_sync_distance", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] + [ "CWAgent", "solana_slots_behind", "InstanceId", "${INSTANCE_ID}", { "label": "${INSTANCE_ID}-${INSTANCE_NAME}" } ] ], - "title": "Consensus Client Sync Distance" + "title": "Solana Slots Behind" + } + }, + { + "height": 5, + "width": 6, + "y": 5, + "x": 12, + "type": "metric", + "properties": { + "view": "timeSeries", + "stat": "Sum", + "period": 60, + "stacked": false, + "sparkline": true, + "yAxis": { + "left": { + "min": 0 + } + }, + "region": "${REGION}", + "metrics": [ + [ { "expression": "IF(m7_2 !=0, (m7_1 / m7_2), 0)", "label": "Read", "id": "e7" } ], + [ "CWAgent", "diskio_read_time", "InstanceId", "${INSTANCE_ID}", "name", "nvme2n1", { "id": "m7_1", "visible": false, "stat": "Sum", "period": 60 } ], + [ "CWAgent", "diskio_reads", "InstanceId", "${INSTANCE_ID}", "name", "nvme2n1", { "id": "m7_2", "visible": false, "stat": "Sum", "period": 60 } ], + [ { "expression": "IF(m7_4 !=0, (m7_3 / m7_4), 0)", "label": "Write", "id": "e8" } ], + [ "CWAgent", "diskio_write_time", "InstanceId", "${INSTANCE_ID}", "name", "nvme2n1", { "id": "m7_3", "visible": false, "stat": "Sum", "period": 60 } ], + [ "CWAgent", "diskio_writes", "InstanceId", "${INSTANCE_ID}", "name", "nvme2n1", { "id": "m7_4", "visible": false, "stat": "Sum", "period": 60 } ] + ], + "title": "nvme2n1 Volume Read/Write latency (ms/op)" } }, { @@ -238,9 +271,9 @@ export const SyncNodeCWDashboardJSON = { "type": "metric", "properties": { "metrics": [ - [ { "expression": "(m2/1048576)/PERIOD(m2)", "label": "Read", "id": "e2", "period": 60, "region": "${REGION}" } ], + [ { "expression": "m2/PERIOD(m2)", "label": "Read", "id": "e2", "period": 60, "region": "${REGION}" } ], [ "CWAgent", "diskio_read_bytes", "InstanceId", "${INSTANCE_ID}", "name", "nvme1n1", { "id": "m2", "stat": "Sum", "visible": false, "period": 60 } ], - [ { "expression": "(m3/1048576)/PERIOD(m3)", "label": "Write", "id": "e3", "period": 60, "region": "${REGION}" } ], + [ { "expression": "m3/PERIOD(m3)", "label": "Write", "id": "e3", "period": 60, "region": "${REGION}" } ], [ "CWAgent", "diskio_write_bytes", "InstanceId", "${INSTANCE_ID}", "name", "nvme1n1", { "id": "m3", "stat": "Sum", "visible": false, "period": 60 } ] ], "view": "timeSeries", @@ -248,25 +281,7 @@ export const SyncNodeCWDashboardJSON = { "region": "${REGION}", "stat": "Average", "period": 60, - "title": "nvme1n1 Volume Read/Write throughput (MiB/sec)" - } - }, - { - "height": 3, - "width": 6, - "y": 15, - "x": 6, - "type": "metric", - "properties": { - "metrics": [ - [ "CWAgent", "disk_used_percent", "path", "/data", "InstanceId", "${INSTANCE_ID}", "device", "nvme1n1", "fstype", "ext4", { "region": "${REGION}", "label": "/data" } ] - ], - "sparkline": true, - "view": "singleValue", - "region": "${REGION}", - "title": "nvme1n1 Disk Used (%)", - "period": 60, - "stat": "Average" + "title": "nvme1n1 Volume Read/Write throughput (bytes/sec)" } } ] diff --git a/lib/solana/lib/assets/setup-instance-store-volumes.sh b/lib/solana/lib/assets/setup-instance-store-volumes.sh new file mode 100644 index 00000000..108708a1 --- /dev/null +++ b/lib/solana/lib/assets/setup-instance-store-volumes.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +source /etc/environment + +if [[ "$DATA_VOLUME_TYPE" == "instance-store" ]]; then + echo "Data volume type is instance store" + export DATA_VOLUME_ID=/dev/nvme1n1 +fi + +if [[ "$ACCOUNTS_VOLUME_TYPE" == "instance-store" ]]; then + echo "Accounts volume type is instance store" + if [[ "$DATA_VOLUME_TYPE" == "instance-store" ]]; then + export ACCOUNTS_VOLUME_ID=/dev/nvme2n1 + else + export ACCOUNTS_VOLUME_ID=/dev/nvme1n1 + fi +fi + +if [ -n "$DATA_VOLUME_ID" ]; then + echo "If Data volume is mounted, dont do anything" + if [ $(df --output=target | grep -c "/var/solana/data") -lt 1 ]; then + echo "Checking fstab for Data volume" + + sudo mkfs.xfs -f $DATA_VOLUME_ID + sleep 10 + DATA_VOLUME_UUID=$(lsblk -fn -o UUID $DATA_VOLUME_ID) + DATA_VOLUME_FSTAB_CONF="UUID=$DATA_VOLUME_UUID /var/solana/data xfs defaults 0 2" + echo "DATA_VOLUME_ID="$DATA_VOLUME_ID + echo "DATA_VOLUME_UUID="$DATA_VOLUME_UUID + echo "DATA_VOLUME_FSTAB_CONF="$DATA_VOLUME_FSTAB_CONF + + # Check if data disc is already in fstab and replace the line if it is with the new disc UUID + if [ $(grep -c "data" /etc/fstab) -gt 0 ]; then + SED_REPLACEMENT_STRING="$(grep -n "/var/solana/data" /etc/fstab | cut -d: -f1)s#.*#$DATA_VOLUME_FSTAB_CONF#" + sudo cp /etc/fstab /etc/fstab.bak + sudo sed -i "$SED_REPLACEMENT_STRING" /etc/fstab + else + echo $DATA_VOLUME_FSTAB_CONF | sudo tee -a /etc/fstab + fi + + sudo mount -a + + sudo mkdir /var/solana/data/ledger + sudo chown -R solana:solana /var/solana + else + echo "Data volume is mounted, nothing changed" + fi +fi + +if [ -n "$ACCOUNTS_VOLUME_ID" ]; then + echo "If Accounts volume is mounted, dont do anything" + if [ $(df --output=target | grep -c "/var/solana/accounts") -lt 1 ]; then + echo "Checking fstab for Accounts volume" + + sudo mkfs.xfs -f $ACCOUNTS_VOLUME_ID + sleep 10 + ACCOUNTS_VOLUME_UUID=$(lsblk -fn -o UUID $ACCOUNTS_VOLUME_ID) + ACCOUNTS_VOLUME_FSTAB_CONF="UUID=$ACCOUNTS_VOLUME_UUID /var/solana/accounts xfs defaults 0 2" + echo "ACCOUNTS_VOLUME_ID="$ACCOUNTS_VOLUME_ID + echo "ACCOUNTS_VOLUME_UUID="$ACCOUNTS_VOLUME_UUID + echo "ACCOUNTS_VOLUME_FSTAB_CONF="$ACCOUNTS_VOLUME_FSTAB_CONF + + # Check if accounts disc is already in fstab and replace the line if it is with the new disc UUID + if [ $(grep -c "/var/solana/accounts" /etc/fstab) -gt 0 ]; then + SED_REPLACEMENT_STRING="$(grep -n "/var/solana/accounts" /etc/fstab | cut -d: -f1)s#.*#$ACCOUNTS_VOLUME_FSTAB_CONF#" + sudo cp /etc/fstab /etc/fstab.bak + sudo sed -i "$SED_REPLACEMENT_STRING" /etc/fstab + else + echo $ACCOUNTS_VOLUME_FSTAB_CONF | sudo tee -a /etc/fstab + fi + + sudo mount -a + + sudo chown -R solana:solana /var/solana + else + echo "Accounts volume is mounted, nothing changed" + fi +fi \ No newline at end of file diff --git a/lib/solana/lib/assets/solana/node-heavy-rpc-template.sh b/lib/solana/lib/assets/solana/node-heavy-rpc-template.sh new file mode 100644 index 00000000..a38f8630 --- /dev/null +++ b/lib/solana/lib/assets/solana/node-heavy-rpc-template.sh @@ -0,0 +1,41 @@ +#!/bin/bash +set -o errexit +set -o nounset +set -o pipefail +# Remove empty snapshots +find "/var/solana/data/ledger" -name "snapshot-*" -size 0 -print -exec rm {} \; || true +export RUST_LOG=warning +export RUST_BACKTRACE=full +export SOLANA_METRICS_CONFIG=__SOLANA_METRICS_CONFIG__ +/home/solana/bin/solana-validator \ +--ledger /var/solana/data/ledger \ +--identity /home/solana/config/validator-keypair.json \ +__KNOWN_VALIDATORS__ \ +--expected-genesis-hash __EXPECTED_GENESIS_HASH__ \ +__ENTRY_POINTS__ \ +--no-voting \ +--snapshot-interval-slots 500 \ +--maximum-local-snapshot-age 500 \ +--full-rpc-api \ +--rpc-port 8899 \ +--gossip-port 8801 \ +--dynamic-port-range 8800-8813 \ +--no-port-check \ +--wal-recovery-mode skip_any_corrupted_record \ +--enable-rpc-transaction-history \ +--enable-cpi-and-log-storage \ +--init-complete-file /var/solana/data/init-completed \ +--snapshot-compression none \ +--require-tower \ +--no-wait-for-vote-to-start-leader \ +--limit-ledger-size 50000000 \ +--accounts /var/solana/accounts \ +--no-os-cpu-stats-reporting \ +--no-os-memory-stats-reporting \ +--no-os-network-stats-reporting \ +--account-index spl-token-owner \ +--account-index program-id \ +--account-index spl-token-mint \ +--account-index-exclude-key kinXdEcpDQeHPEuQnqmUgtYykqKGVFq6CeVX5iAHJq6 \ +--account-index-exclude-key TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA \ +--log - \ No newline at end of file diff --git a/lib/solana/lib/assets/solana/node-light-rpc-template.sh b/lib/solana/lib/assets/solana/node-light-rpc-template.sh new file mode 100644 index 00000000..c5c1b96c --- /dev/null +++ b/lib/solana/lib/assets/solana/node-light-rpc-template.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -o errexit +set -o nounset +set -o pipefail +# Remove empty snapshots +find "/var/solana/data/ledger" -name "snapshot-*" -size 0 -print -exec rm {} \; || true +export RUST_LOG=warning +export RUST_BACKTRACE=full +export SOLANA_METRICS_CONFIG=__SOLANA_METRICS_CONFIG__ +/home/solana/bin/solana-validator \ +--ledger /var/solana/data/ledger \ +--identity /home/solana/config/validator-keypair.json \ +__KNOWN_VALIDATORS__ \ +--expected-genesis-hash __EXPECTED_GENESIS_HASH__ \ +__ENTRY_POINTS__ \ +--no-voting \ +--snapshot-interval-slots 500 \ +--maximum-local-snapshot-age 500 \ +--full-rpc-api \ +--rpc-port 8899 \ +--gossip-port 8801 \ +--dynamic-port-range 8800-8813 \ +--no-port-check \ +--wal-recovery-mode skip_any_corrupted_record \ +--enable-rpc-transaction-history \ +--enable-cpi-and-log-storage \ +--init-complete-file /var/solana/data/init-completed \ +--snapshot-compression none \ +--require-tower \ +--no-wait-for-vote-to-start-leader \ +--limit-ledger-size 50000000 \ +--accounts /var/solana/accounts \ +--no-os-cpu-stats-reporting \ +--no-os-memory-stats-reporting \ +--no-os-network-stats-reporting \ +--log - \ No newline at end of file diff --git a/lib/solana/lib/assets/solana/node-validator-template.sh b/lib/solana/lib/assets/solana/node-validator-template.sh new file mode 100644 index 00000000..903b2994 --- /dev/null +++ b/lib/solana/lib/assets/solana/node-validator-template.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -o errexit +set -o nounset +set -o pipefail +# Remove empty snapshots +find "/var/solana/data/ledger" -name "snapshot-*" -size 0 -print -exec rm {} \; || true +export RUST_LOG=warning +export RUST_BACKTRACE=full +export SOLANA_METRICS_CONFIG=__SOLANA_METRICS_CONFIG__ +/home/solana/bin/solana-validator \ +--ledger /var/solana/data/ledger \ +--identity /home/solana/config/validator-keypair.json \ +--vote-account /home/solana/config/vote-account-keypair.json \ +__KNOWN_VALIDATORS__ \ +--expected-genesis-hash __EXPECTED_GENESIS_HASH__ \ +__ENTRY_POINTS__ \ +--rpc-port 8899 \ +--no-port-check \ +--wal-recovery-mode skip_any_corrupted_record \ +--init-complete-file /var/solana/data/init-completed \ +--limit-ledger-size 50000000 \ +--accounts /var/solana/accounts \ +--no-os-cpu-stats-reporting \ +--no-os-memory-stats-reporting \ +--no-os-network-stats-reporting \ +--log - \ No newline at end of file diff --git a/lib/solana/lib/assets/sync-checker/syncchecker-bor-hemdall-mainnet.sh b/lib/solana/lib/assets/sync-checker/syncchecker-bor-hemdall-mainnet.sh deleted file mode 100644 index b4cc7cba..00000000 --- a/lib/solana/lib/assets/sync-checker/syncchecker-bor-hemdall-mainnet.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash -source /etc/environment - -# Consensus client stats -CONSENSUS_CLIENT_SYNC_STATUS=$(curl -s http://localhost:5052/eth/v1/node/syncing | jq -r ".data") - -CONSENSUS_CLIENT_IS_SYNCING=$(echo $CONSENSUS_CLIENT_SYNC_STATUS | jq -r ".is_syncing") -CONSENSUS_CLIENT_IS_OPTIMISTIC=$(echo $CONSENSUS_CLIENT_SYNC_STATUS | jq -r ".is_optimistic") -CONSENSUS_CLIENT_SYNC_DISTANCE=$(echo $CONSENSUS_CLIENT_SYNC_STATUS | jq -r ".sync_distance") -CONSENSUS_CLIENT_HEAD_SLOT=$(echo $CONSENSUS_CLIENT_SYNC_STATUS | jq -r ".head_slot") - -if [[ -z "$CONSENSUS_CLIENT_SYNC_DISTANCE" ]]; then - CONSENSUS_CLIENT_SYNC_DISTANCE=0 -fi - -if [[ -z "$CONSENSUS_CLIENT_HEAD_SLOT" ]]; then - CONSENSUS_CLIENT_HEAD_SLOT=0 -fi - -# Execution client stats -EXECUTION_CLIENT_SYNC_STATS=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' http://localhost:8545 | jq -r ".result") - -if [[ "$EXECUTION_CLIENT_SYNC_STATS" == "false" ]]; then - EXECUTION_CLIENT_SYNC_BLOCK_HEX=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http://localhost:8545 | jq -r ".result") - EXECUTION_CLIENT_HIGHEST_BLOCK_HEX=$EXECUTION_CLIENT_SYNC_BLOCK_HEX -else - EXECUTION_CLIENT_SYNC_BLOCK_HEX=$(echo $EXECUTION_CLIENT_SYNC_STATS | jq -r ".currentBlock") - EXECUTION_CLIENT_HIGHEST_BLOCK_HEX=$(echo $EXECUTION_CLIENT_SYNC_STATS | jq -r ".highestBlock") -fi - -EXECUTION_CLIENT_HIGHEST_BLOCK=$(echo $((${EXECUTION_CLIENT_HIGHEST_BLOCK_HEX}))) -EXECUTION_CLIENT_SYNC_BLOCK=$(echo $((${EXECUTION_CLIENT_SYNC_BLOCK_HEX}))) -EXECUTION_CLIENT_BLOCKS_BEHIND="$((EXECUTION_CLIENT_HIGHEST_BLOCK-EXECUTION_CLIENT_SYNC_BLOCK))" - -# echo "EXECUTION_CLIENT_SYNC_STATS="$EXECUTION_CLIENT_SYNC_STATS -# echo "CONSENSUS_CLIENT_IS_SYNCING="$CONSENSUS_CLIENT_IS_SYNCING -# echo "CONSENSUS_CLIENT_IS_OPTIMISTIC="$CONSENSUS_CLIENT_IS_OPTIMISTIC -# echo "EXECUTION_CLIENT_HIGHEST_BLOCK="$EXECUTION_CLIENT_HIGHEST_BLOCK -# echo "EXECUTION_CLIENT_SYNC_BLOCK="$EXECUTION_CLIENT_SYNC_BLOCK -# echo "EXECUTION_CLIENT_BLOCKS_BEHIND="$EXECUTION_CLIENT_BLOCKS_BEHIND - -# Sending data to CloudWatch -TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") -INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id) -REGION=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq .region -r) -TIMESTAMP=$(date +"%Y-%m-%dT%H:%M:%S%:z") - -aws cloudwatch put-metric-data --metric-name clc_sync_distance --namespace CWAgent --value $CONSENSUS_CLIENT_SYNC_DISTANCE --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION -aws cloudwatch put-metric-data --metric-name clc_head_slot --namespace CWAgent --value $CONSENSUS_CLIENT_HEAD_SLOT --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION - -aws cloudwatch put-metric-data --metric-name elc_sync_block --namespace CWAgent --value $EXECUTION_CLIENT_SYNC_BLOCK --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION -aws cloudwatch put-metric-data --metric-name elc_blocks_behind --namespace CWAgent --value $EXECUTION_CLIENT_BLOCKS_BEHIND --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION - -# If the node is a sync node, check if the snapshot is already taken. If the snapshot is not taken, then take it and restart the node. -if [[ "$NODE_ROLE" == "sync-node" ]]; then - if [ ! -f "/data/snapshotted" ]; then - if [ "$EXECUTION_CLIENT_SYNC_STATS" == "false" ] && [ "$CONSENSUS_CLIENT_IS_SYNCING" == "false" ] && [ "$CONSENSUS_CLIENT_IS_OPTIMISTIC" == "false" ]; then - sudo /opt/copy-data-to-s3.sh - - # Take a snapshot once a day at midnight - (sudo crontab -u root -l; echo '0 0 * * * /opt/copy-data-to-s3.sh' ) | sudo crontab -u root - - sudo crontab -l - fi - fi -fi \ No newline at end of file diff --git a/lib/solana/lib/assets/sync-checker/syncchecker-solana.sh b/lib/solana/lib/assets/sync-checker/syncchecker-solana.sh new file mode 100644 index 00000000..98748ca9 --- /dev/null +++ b/lib/solana/lib/assets/sync-checker/syncchecker-solana.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +INIT_COMPLETED_FILE=/var/solana/data/init-completed +INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) +REGION=$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq .region -r) +TIMESTAMP=$(date +"%Y-%m-%dT%H:%M:%S%:z") + +if [ -f "$INIT_COMPLETED_FILE" ]; then + SOLANA_BLOCK_HEIGHT=$(curl -s -X POST -H "Content-Type: application/json" -d ' {"jsonrpc":"2.0","id":1,"method":"getBlockHeight"}' http://localhost:8899 | jq .result) + SOLANA_SLOTS_BEHIND_DATA=$(curl -s -X POST -H "Content-Type: application/json" -d ' {"jsonrpc":"2.0","id":1, "method":"getHealth"}' http://localhost:8899 | jq .error.data) + SOLANA_SLOTS_BEHIND=$(echo $SOLANA_SLOTS_BEHIND_DATA | jq .numSlotsBehind -r) + + if [ $SOLANA_SLOTS_BEHIND == "null" ] + then + SOLANA_SLOTS_BEHIND=0 + fi + + if [ -z "$SOLANA_SLOTS_BEHIND" ] + then + SOLANA_SLOTS_BEHIND=0 + fi + + if [ -z "$SOLANA_BLOCK_HEIGHT" ] + then + SOLANA_BLOCK_HEIGHT=0 + fi + + aws cloudwatch put-metric-data --metric-name solana_block_height --namespace CWAgent --value $SOLANA_BLOCK_HEIGHT --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION + aws cloudwatch put-metric-data --metric-name solana_slots_behind --namespace CWAgent --value $SOLANA_SLOTS_BEHIND --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION +else + aws cloudwatch put-metric-data --metric-name solana_block_height --namespace CWAgent --value 0 --timestamp $TIMESTAMP --dimensions InstanceId=$INSTANCE_ID --region $REGION +fi \ No newline at end of file diff --git a/lib/solana/lib/assets/user-data/node-start copy.sh b/lib/solana/lib/assets/user-data/node-start copy.sh deleted file mode 100644 index cac1cbff..00000000 --- a/lib/solana/lib/assets/user-data/node-start copy.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/bash -set +e - -# Set by generic single-node and ha-node CDK components -ASSETS_S3_PATH=${_ASSETS_S3_PATH_} - -# Saving just in case for future use -echo "ASSETS_S3_PATH=$ASSETS_S3_PATH" >> /etc/environment - -arch=$(uname -m) - -echo "Architecture detected: $arch" - -if [ "$arch" == "x86_64" ]; then - SSM_AGENT_BINARY_URI=https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm - AWS_CLI_BINARY_URI=https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip - S5CMD_URI=https://github.com/peak/s5cmd/releases/download/v2.1.0/s5cmd_2.1.0_Linux-64bit.tar.gz -else - SSM_AGENT_BINARY_URI=https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_arm64/amazon-ssm-agent.rpm - AWS_CLI_BINARY_URI=https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip - S5CMD_URI=https://github.com/peak/s5cmd/releases/download/v2.1.0/s5cmd_2.1.0_Linux-arm64.tar.gz -fi - -echo "Updating and installing required system packages" -yum update -y -yum -y install amazon-cloudwatch-agent collectd jq gcc ncurses-devel telnet aws-cfn-bootstrap - -cd /opt - -echo "Downloading assets zip file" -aws s3 cp $ASSETS_S3_PATH ./assets.zip -unzip -q assets.zip - -echo 'Configuring CloudWatch Agent' -cp /opt/cw-agent.json /opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json - -echo "Starting CloudWatch Agent" -/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \ --a fetch-config -c file:/opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json -m ec2 -s -systemctl status amazon-cloudwatch-agent - -echo 'Uninstalling AWS CLI v1' -yum remove awscli - -echo 'Installing AWS CLI v2' -curl $AWS_CLI_BINARY_URI -o "awscliv2.zip" -unzip -q awscliv2.zip -./aws/install -rm /usr/bin/aws -ln /usr/local/bin/aws /usr/bin/aws - -aws configure set default.s3.max_concurrent_requests 50 -aws configure set default.s3.multipart_chunksize 256MB - -echo 'Installing SSM Agent' -yum install -y $SSM_AGENT_BINARY_URI - -echo "Assigning Swap Space" -# Check if a swap file already exists -if [ -f /swapfile ]; then - # Remove the existing swap file - swapoff /swapfile - rm -rf /swapfile -fi - -# Create a new swap file -total_mem=$(grep MemTotal /proc/meminfo | awk '{print $2}') -# Calculate the swap size -swap_size=$((total_mem / 3)) -# Convert the swap size to MB -swap_size_mb=$((swap_size / 1024)) -unit=M -fallocate -l $swap_size_mb$unit /swapfile -chmod 600 /swapfile -mkswap /swapfile -swapon /swapfile - -# Enable the swap space to persist after reboot. -echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab - -sysctl vm.swappiness=6 -sysctl vm.vfs_cache_pressure=10 -echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf -echo "vm.vfs_cache_pressure=10" | sudo tee -a /etc/sysctl.conf - -free -h - -echo "Adding blockchain user and group" -groupadd -g 1002 bcuser -useradd -u 1002 -g 1002 -m -s /bin/bash bcuser -usermod -a -G docker bcuser -usermod -a -G docker ec2-user - -# Setting up sync node - -REGION=${_REGION_} -STACK_NAME=${_STACK_NAME_} -RESOURCE_ID=${_RESOURCE_ID_} -SNAPSHOT_S3_PATH=${_SNAPSHOT_S3_PATH_} -CLIENT_COMBINATION=${_CLIENT_COMBINATION_} -NETWORK=${_NETWORK_} -DATA_VOLUME_TYPE=${_DATA_VOLUME_TYPE_} -FORMAT_DISK=${_FORMAT_DISK_} - -# Saving just in case for future use -echo "REGION=$REGION" >> /etc/environment -echo "STACK_NAME=$STACK_NAME" >> /etc/environment -echo "RESOURCE_ID=$RESOURCE_ID" >> /etc/environment -echo "SNAPSHOT_S3_PATH=$SNAPSHOT_S3_PATH" >> /etc/environment -echo "NETWORK=$NETWORK" >> /etc/environment -echo "DATA_VOLUME_TYPE=$DATA_VOLUME_TYPE" >> /etc/environment -echo "FORMAT_DISK=$FORMAT_DISK" >> /etc/environment - -# Check if aria2c is installed -sudo yum update -y -sudo amazon-linux-extras install epel -y -sudo yum install zstd pv aria2 -y - -echo "Signaling completion to CloudFormation" -/opt/aws/bin/cfn-signal --stack $STACK_NAME --resource $RESOURCE_ID --region $REGION - -# Configure data volume -if [ "$DATA_VOLUME_TYPE" == "instance-store" ]; then - chmod +x /opt/init-data-vol-instance-store.sh - - (crontab -l; echo "@reboot /opt/init-data-vol-instance-store.sh >/tmp/init-data-vol-instance-store.log 2>&1") | crontab - - crontab -l - - /opt/init-data-vol-instance-store.sh -else - chmod +x /opt/init-data-vol-ebs.sh - /opt/init-data-vol-ebs.sh $FORMAT_DISK -fi - -chmod +x /opt/polygon/download-extract-polygon-snapshot.sh - -# Download the snapshot -case $CLIENT_COMBINATION in - "bor-heimdall") - mkdir -p /data/polygon/bor/bor/chaindata - mkdir -p /data/polygon/heimdall/data - echo "/opt/polygon/download-extract-polygon-snapshot.sh -n $NETWORK -c bor -d /data/polygon/bor/bor/chaindata -v true -s3 $SNAPSHOT_S3_PATH" | at now +3 minutes - echo "/opt/polygon/download-extract-polygon-snapshot.sh -n $NETWORK -c heimdall -d /data/polygon/heimdall/data -v true -s3 $SNAPSHOT_S3_PATH" | at now +4 minutes - ;; - *) - echo "Combination is not valid." - exit 1 - ;; -esac \ No newline at end of file diff --git a/lib/solana/lib/assets/user-data/node-start.sh b/lib/solana/lib/assets/user-data/node.sh similarity index 69% rename from lib/solana/lib/assets/user-data/node-start.sh rename to lib/solana/lib/assets/user-data/node.sh index aabb9af0..c4c3ba09 100644 --- a/lib/solana/lib/assets/user-data/node-start.sh +++ b/lib/solana/lib/assets/user-data/node.sh @@ -2,29 +2,53 @@ set +e # Set by generic single-node and ha-node CDK components +echo "AWS_REGION=${_AWS_REGION_}" >> /etc/environment echo "ASSETS_S3_PATH=${_ASSETS_S3_PATH_}" >> /etc/environment -echo "CF_STACK_NAME=${CF_STACK_NAME}" >> /etc/environment -echo "ACCOUNTS_DISC_TYPE=${ACCOUNTS_DISC_TYPE}" >> /etc/environment -echo "DATA_DISC_TYPE=${DATA_DISC_TYPE}" >> /etc/environment -echo "SOLANA_VERSION=${SOLANA_VERSION}" >> /etc/environment -echo "SOLANA_NODE_TYPE=${SOLANA_NODE_TYPE}" >> /etc/environment -echo "NODE_IDENTITY_SECRET_ARN=${NODE_IDENTITY_SECRET_ARN}" >> /etc/environment -echo "VOTE_ACCOUNT_SECRET_ARN=${VOTE_ACCOUNT_SECRET_ARN}" >> /etc/environment -echo "AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN=${AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN}" >> /etc/environment -echo "REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN=${REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN}" >> /etc/environment -echo "SOLANA_CLUSTER_ID=${SOLANA_CLUSTER_ID}" >> /etc/environment +echo "STACK_NAME=${_STACK_NAME_}" >> /etc/environment +echo "STACK_ID=${_STACK_ID_}" >> /etc/environment +echo "RESOURCE_ID=${_NODE_CF_LOGICAL_ID_}" >> /etc/environment +echo "ACCOUNTS_VOLUME_TYPE=${_ACCOUNTS_VOLUME_TYPE_}" >> /etc/environment +echo "ACCOUNTS_VOLUME_SIZE=${_ACCOUNTS_VOLUME_SIZE_}" >> /etc/environment +echo "DATA_VOLUME_TYPE=${_DATA_VOLUME_TYPE_}" >> /etc/environment +echo "DATA_VOLUME_SIZE=${_DATA_VOLUME_SIZE_}" >> /etc/environment +echo "SOLANA_VERSION=${_SOLANA_VERSION_}" >> /etc/environment +echo "SOLANA_NODE_TYPE=${_SOLANA_NODE_TYPE_}" >> /etc/environment +echo "NODE_IDENTITY_SECRET_ARN=${_NODE_IDENTITY_SECRET_ARN_}" >> /etc/environment +echo "VOTE_ACCOUNT_SECRET_ARN=${_VOTE_ACCOUNT_SECRET_ARN_}" >> /etc/environment +echo "AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN=${_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN_}" >> /etc/environment +echo "REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN=${_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN_}" >> /etc/environment +echo "SOLANA_CLUSTER=${_SOLANA_CLUSTER_}" >> /etc/environment +echo "LIFECYCLE_HOOK_NAME=${_LIFECYCLE_HOOK_NAME_}" >> /etc/environment +echo "AUTOSCALING_GROUP_NAME=${_AUTOSCALING_GROUP_NAME_}" >> /etc/environment source /etc/environment -apt-get -yqq update -apt-get -yqq install awscli jq - # Saving just in case for future use arch=$(uname -m) -export AWS_REGION=`curl http://169.254.169.254/latest/dynamic/instance-identity/document|grep region|awk -F\" '{print $4}'` -export GIT_URL="https://raw.githubusercontent.com/frbrkoala/solana-configs-for-aws/main" +apt-get -yqq update +apt-get -yqq install awscli jq unzip python3-pip +apt install unzip + +cd /opt + +echo "Downloading assets zip file" +aws s3 cp $ASSETS_S3_PATH ./assets.zip +unzip -q assets.zip -case $SOLANA_CLUSTER_ID in +echo "Install and configure CloudWatch agent" +wget -q https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb +sudo dpkg -i -E amazon-cloudwatch-agent.deb + +echo 'Configuring CloudWatch Agent' +mkdir -p /opt/aws/amazon-cloudwatch-agent/etc/ +cp /opt/cw-agent.json /opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json + +echo "Starting CloudWatch Agent" +/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \ +-a fetch-config -c file:/opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json -m ec2 -s +systemctl status amazon-cloudwatch-agent + +case $SOLANA_CLUSTER in "mainnet-beta") ENTRY_POINTS=" --entrypoint entrypoint.mainnet-beta.solana.com:8001 --entrypoint entrypoint2.mainnet-beta.solana.com:8001 --entrypoint entrypoint3.mainnet-beta.solana.com:8001 --entrypoint entrypoint4.mainnet-beta.solana.com:8001 --entrypoint entrypoint5.mainnet-beta.solana.com:8001" KNOWN_VALIDATORS=" --known-validator 7Np41oeYqPefeNQEHSv1UDhYrehxin3NStELsSKCT4K2 --known-validator GdnSyH3YtwcxFvQrVVJMm1JhTS4QVX7MFsX56uJLUfiZ --known-validator DE1bawNcRJB9rVm3buyMVfr8mBEoyyu73NBovf2oXJsJ --known-validator CakcnaRDHka2gXyfbEd2d3xsvkJkqsLw2akB3zsN1D2S" @@ -44,22 +68,11 @@ case $SOLANA_CLUSTER_ID in EXPECTED_GENESIS_HASH="EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG" ;; *) - echo "Solana cluster id is not valid: $SOLANA_CLUSTER_ID" + echo "Solana cluster id is not valid: $SOLANA_CLUSTER" exit 1 ;; esac -echo "Install and configure CloudWatch agent" -wget -q https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb -sudo dpkg -i -E amazon-cloudwatch-agent.deb - -sudo wget -q $GIT_URL/src/configs/cloudwatch-agent-config.json -sudo cp ./cloudwatch-agent-config.json /opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json - -sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \ --a fetch-config -c file:/opt/aws/amazon-cloudwatch-agent/etc/custom-amazon-cloudwatch-agent.json -m ec2 -s -#sudo systemctl status amazon-cloudwatch-agent - echo "Fine tune sysctl to prepare the system for Solana" sudo bash -c "cat >/etc/sysctl.d/20-solana-additionals.conf </tmp/setup-instance-store-volumes.log 2>&1") | crontab - @@ -123,25 +164,24 @@ if [[ "$DATA_DISC_TYPE" == "instancestore" ]]; then else echo "Data volume type is EBS" - # Our data volume size is 2TB - DATA_DISC_ID=/dev/$(lsblk -lnb | awk '{if ($4== 2147483648000) {print $1}}') - sudo mkfs -t xfs $DATA_DISC_ID + # Our data volume size is over 2TB + DATA_VOLUME_ID=/dev/$(lsblk -lnb | awk -v VOLUME_SIZE_BYTES="$DATA_VOLUME_SIZE" '{if ($4== VOLUME_SIZE_BYTES) {print $1}}') + sudo mkfs -t xfs $DATA_VOLUME_ID sleep 10 - DATA_DISC_UUID=$(lsblk -fn -o UUID $DATA_DISC_ID) - DATA_DISC_FSTAB_CONF="UUID=$DATA_DISC_UUID /var/solana/data xfs defaults 0 2" - echo "DATA_DISC_ID="$DATA_DISC_ID - echo "DATA_DISC_UUID="$DATA_DISC_UUID - echo "DATA_DISC_FSTAB_CONF="$DATA_DISC_FSTAB_CONF - echo $DATA_DISC_FSTAB_CONF | sudo tee -a /etc/fstab + DATA_VOLUME_UUID=$(lsblk -fn -o UUID $DATA_VOLUME_ID) + DATA_VOLUME_FSTAB_CONF="UUID=$DATA_VOLUME_UUID /var/solana/data xfs defaults 0 2" + echo "DATA_VOLUME_ID="$DATA_VOLUME_ID + echo "DATA_VOLUME_UUID="$DATA_VOLUME_UUID + echo "DATA_VOLUME_FSTAB_CONF="$DATA_VOLUME_FSTAB_CONF + echo $DATA_VOLUME_FSTAB_CONF | sudo tee -a /etc/fstab sudo mount -a fi -if [[ "$ACCOUNTS_DISC_TYPE" == "instancestore" ]]; then +if [[ "$ACCOUNTS_VOLUME_TYPE" == "instance-store" ]]; then echo "Accounts volume type is instance store" - if [[ "$DATA_DISC_TYPE" != "instancestore" ]]; then + if [[ "$DATA_VOLUME_TYPE" != "instance-store" ]]; then cd /opt - sudo wget $GIT_URL/src/scripts/setup-instance-store-volumes.sh sudo chmod +x /opt/setup-instance-store-volumes.sh @@ -156,16 +196,16 @@ if [[ "$ACCOUNTS_DISC_TYPE" == "instancestore" ]]; then else echo "Accounts volume type is EBS" - # Our accounts volume size is 500GB - ACCOUNTS_DISC_ID=/dev/$(lsblk -lnb | awk '{if ($4== 536870912000) {print $1}}') - sudo mkfs -t xfs $ACCOUNTS_DISC_ID + # Our accounts volume size is over 500GB + ACCOUNTS_VOLUME_ID=/dev/$(lsblk -lnb | awk -v VOLUME_SIZE_BYTES="$ACCOUNTS_VOLUME_SIZE" '{if ($4== VOLUME_SIZE_BYTES) {print $1}}') + sudo mkfs -t xfs $ACCOUNTS_VOLUME_ID sleep 10 - ACCOUNTS_DISC_UUID=$(lsblk -fn -o UUID $ACCOUNTS_DISC_ID) - ACCOUNTS_DISC_FSTAB_CONF="UUID=$ACCOUNTS_DISC_UUID /var/solana/accounts xfs defaults 0 2" - echo "ACCOUNTS_DISC_ID="$ACCOUNTS_DISC_ID - echo "ACCOUNTS_DISC_UUID="$ACCOUNTS_DISC_UUID - echo "ACCOUNTS_DISC_FSTAB_CONF="$ACCOUNTS_DISC_FSTAB_CONF - echo $ACCOUNTS_DISC_FSTAB_CONF | sudo tee -a /etc/fstab + ACCOUNTS_VOLUME_UUID=$(lsblk -fn -o UUID $ACCOUNTS_VOLUME_ID) + ACCOUNTS_VOLUME_FSTAB_CONF="UUID=$ACCOUNTS_VOLUME_UUID /var/solana/accounts xfs defaults 0 2" + echo "ACCOUNTS_VOLUME_ID="$ACCOUNTS_VOLUME_ID + echo "ACCOUNTS_VOLUME_UUID="$ACCOUNTS_VOLUME_UUID + echo "ACCOUNTS_VOLUME_FSTAB_CONF="$ACCOUNTS_VOLUME_FSTAB_CONF + echo $ACCOUNTS_VOLUME_FSTAB_CONF | sudo tee -a /etc/fstab sudo mount -a fi @@ -246,18 +286,15 @@ if [[ "$SOLANA_NODE_TYPE" == "validator" ]]; then sudo mv ~/vote-account-keypair.json /home/solana/config/vote-account-keypair.json fi -sudo wget -q $GIT_URL/src/scripts/node-validator-template.sh -mv ./node-validator-template.sh /home/solana/bin/validator.sh +mv /opt/solana/node-validator-template.sh /home/solana/bin/validator.sh fi if [[ "$SOLANA_NODE_TYPE" == "lightrpc" ]]; then - sudo wget -q $GIT_URL/src/scripts/node-light-rpc-template.sh - mv ./node-light-rpc-template.sh /home/solana/bin/validator.sh + mv /opt/solana/node-light-rpc-template.sh /home/solana/bin/validator.sh fi if [[ "$SOLANA_NODE_TYPE" == "heavyrpc" ]]; then - sudo wget -q $GIT_URL/src/scripts/node-heavy-rpc-template.sh - mv ./node-heavy-rpc-template.sh /home/solana/bin/validator.sh + mv /opt/solana/node-heavy-rpc-template.sh /home/solana/bin/validator.sh fi sed -i "s;__SOLANA_METRICS_CONFIG__;\"$SOLANA_METRICS_CONFIG\";g" /home/solana/bin/validator.sh @@ -310,11 +347,15 @@ sudo systemctl restart logrotate.service echo "Configuring syncchecker script" cd /opt -sudo wget $GIT_URL/src/scripts/syncchecker-solana.sh -sudo mv /opt/syncchecker-solana.sh /opt/syncchecker.sh +sudo mv /opt/sync-checker/syncchecker-solana.sh /opt/syncchecker.sh sudo chmod +x /opt/syncchecker.sh (crontab -l; echo "*/1 * * * * /opt/syncchecker.sh >/tmp/syncchecker.log 2>&1") | crontab - crontab -l +# Signaling Autoscaling Gropup's lifecucle hook to complete +TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") +INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id) +aws autoscaling complete-lifecycle-action --lifecycle-action-result CONTINUE --instance-id $INSTANCE_ID --lifecycle-hook-name "$LIFECYCLE_HOOK_NAME" --auto-scaling-group-name "$AUTOSCALING_GROUP_NAME" --region $AWS_REGION + echo "All Done!!" \ No newline at end of file diff --git a/lib/solana/lib/common-stack.ts b/lib/solana/lib/common-stack.ts index e106ee48..56ca3373 100644 --- a/lib/solana/lib/common-stack.ts +++ b/lib/solana/lib/common-stack.ts @@ -4,7 +4,6 @@ import * as iam from 'aws-cdk-lib/aws-iam'; import * as nag from "cdk-nag"; export interface SolanaCommonStackProps extends cdk.StackProps { - createVpcEnpointS3: boolean; } @@ -20,6 +19,7 @@ export class SolanaCommonStack extends cdk.Stack { const instanceRole = new iam.Role(this, `node-role`, { assumedBy: new iam.ServicePrincipal("ec2.amazonaws.com"), managedPolicies: [ + iam.ManagedPolicy.fromAwsManagedPolicyName("SecretsManagerReadWrite"), iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"), iam.ManagedPolicy.fromAwsManagedPolicyName("CloudWatchAgentServerPolicy"), ], diff --git a/lib/solana/lib/config/solanaConfig.interface.ts b/lib/solana/lib/config/solanaConfig.interface.ts index cba142b6..4c4fc72a 100644 --- a/lib/solana/lib/config/solanaConfig.interface.ts +++ b/lib/solana/lib/config/solanaConfig.interface.ts @@ -14,6 +14,7 @@ export interface SolanaBaseConfig extends configTypes.BaseConfig { export interface SolanaBaseNodeConfig extends configTypes.BaseNodeConfig { solanaCluster: SolanaCluster; + solanaVersion: string; nodeConfiguration: SolanaNodeConfiguration; dataVolume: SolanaDataVolumeConfig; accountsVolume: SolanaAccountsVolumeConfig; diff --git a/lib/solana/lib/config/solanaConfig.ts b/lib/solana/lib/config/solanaConfig.ts index 04494012..dbf10455 100644 --- a/lib/solana/lib/config/solanaConfig.ts +++ b/lib/solana/lib/config/solanaConfig.ts @@ -19,15 +19,16 @@ const parseDataVolumeType = (dataVolumeType: string) => { } export const baseConfig: configTypes.SolanaBaseConfig = { - accountId: process.env.AWS_ACCOUNT_ID || "xxxxxxxxxxx", // Set your target AWS Account ID - region: process.env.AWS_REGION || "us-east-2", // Set your target AWS Region + accountId: process.env.AWS_ACCOUNT_ID || "xxxxxxxxxxx", + region: process.env.AWS_REGION || "us-east-2", } export const baseNodeConfig: configTypes.SolanaBaseNodeConfig = { instanceType: new ec2.InstanceType(process.env.SOLANA_INSTANCE_TYPE ? process.env.SOLANA_INSTANCE_TYPE : "r6a.8xlarge"), instanceCpuType: process.env.SOLANA_CPU_TYPE?.toLowerCase() == "x86_64" ? ec2.AmazonLinuxCpuType.X86_64 : ec2.AmazonLinuxCpuType.ARM_64, - solanaCluster: process.env.SOLANA_CLUSTER || "mainnet-beta", // Set the Solana cluster to be used - nodeConfiguration: process.env.SOLANA_NODE_CONFIGURATION || "lightrpc", // Set the Solana node configuration to be used + solanaCluster: process.env.SOLANA_CLUSTER || "mainnet-beta", + solanaVersion: process.env.SOLANA_VERSION || "1.16.2", + nodeConfiguration: process.env.SOLANA_NODE_CONFIGURATION || "lightrpc", dataVolume: { sizeGiB: process.env.SOLANA_DATA_VOL_SIZE ? parseInt(process.env.SOLANA_DATA_VOL_SIZE): 2000, type: parseDataVolumeType(process.env.SOLANA_DATA_VOL_TYPE?.toLowerCase() ? process.env.SOLANA_DATA_VOL_TYPE?.toLowerCase() : "gp3"), @@ -48,6 +49,6 @@ export const baseNodeConfig: configTypes.SolanaBaseNodeConfig = { export const haNodeConfig: configTypes.SolanaHAConfig = { albHealthCheckGracePeriodMin: process.env.SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN ? parseInt(process.env.SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN) : 10, - heartBeatDelayMin: process.env.SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN ? parseInt(process.env.SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN) : 40, - numberOfNodes: process.env.SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN ? parseInt(process.env.SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN) : 2, + heartBeatDelayMin: process.env.SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN ? parseInt(process.env.SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN) : 40, + numberOfNodes: process.env.SOLANA_HA_NUMBER_OF_NODES ? parseInt(process.env.SOLANA_HA_NUMBER_OF_NODES) : 2, }; diff --git a/lib/solana/lib/ha-nodes-stack.ts b/lib/solana/lib/ha-nodes-stack.ts index bf975475..acd2ba3c 100644 --- a/lib/solana/lib/ha-nodes-stack.ts +++ b/lib/solana/lib/ha-nodes-stack.ts @@ -6,24 +6,27 @@ import * as s3Assets from "aws-cdk-lib/aws-s3-assets"; import * as nag from "cdk-nag"; import * as path from "path"; import * as fs from "fs"; -import * as config from "./config/solanaConfig.interface"; import * as configTypes from "./config/solanaConfig.interface"; -import { PolygonNodeSecurityGroupConstruct } from "./constructs/polygon-rpc-node-security-group" +import { SolanaNodeSecurityGroupConstruct } from "./constructs/solana-node-security-group" import { HANodesConstruct } from "../../constructs/ha-rpc-nodes-with-alb" +import * as constants from "../../constructs/constants"; -export interface PolygonRpcNodesStackProps extends cdk.StackProps { - polygonClientCombination: config.PolygonClientCombination; - network: configTypes.PolygonNetwork; +export interface SolanaHANodesStackProps extends cdk.StackProps { instanceType: ec2.InstanceType; instanceCpuType: ec2.AmazonLinuxCpuType; - dataVolumes: config.PolygonDataVolumeConfig[], - numberOfNodes: number; + solanaCluster: configTypes.SolanaCluster; + solanaVersion: string; + nodeConfiguration: configTypes.SolanaNodeConfiguration; + dataVolume: configTypes.SolanaDataVolumeConfig; + accountsVolume: configTypes.SolanaAccountsVolumeConfig; + albHealthCheckGracePeriodMin: number; heartBeatDelayMin: number; + numberOfNodes: number; } -export class PolygonRpcNodesStack extends cdk.Stack { - constructor(scope: cdkConstructs.Construct, id: string, props: PolygonRpcNodesStackProps) { +export class SolanaHANodesStack extends cdk.Stack { + constructor(scope: cdkConstructs.Construct, id: string, props: SolanaHANodesStackProps) { super(scope, id, props); // Setting up necessary environment variables @@ -35,10 +38,12 @@ export class PolygonRpcNodesStack extends cdk.Stack { // Getting our config from initialization properties const { instanceType, - polygonClientCombination, - network, instanceCpuType, - dataVolumes, + solanaCluster, + solanaVersion, + nodeConfiguration, + dataVolume, + accountsVolume, albHealthCheckGracePeriodMin, heartBeatDelayMin, numberOfNodes, @@ -47,10 +52,9 @@ export class PolygonRpcNodesStack extends cdk.Stack { // Using default VPC const vpc = ec2.Vpc.fromLookup(this, "vpc", { isDefault: true }); - // Setting up the security group for the node from Polygon-specific construct - const instanceSG = new PolygonNodeSecurityGroupConstruct (this, "security-group", { + // Setting up the security group for the node from Solana-specific construct + const instanceSG = new SolanaNodeSecurityGroupConstruct (this, "security-group", { vpc: vpc, - clientCombination: polygonClientCombination, }) // Making our scripts and configis from the local "assets" directory available for instance to download @@ -58,42 +62,66 @@ export class PolygonRpcNodesStack extends cdk.Stack { path: path.join(__dirname, "assets"), }); - // Getting the snapshot bucket name and IAM role ARN from the common stack - const importedInstanceRoleArn = cdk.Fn.importValue("PolygonNodeInstanceRoleArn"); - const snapshotBucketName = cdk.Fn.importValue("PolygonNodeSnapshotBucketName"); + // Getting the IAM role ARN from the common stack + const importedInstanceRoleArn = cdk.Fn.importValue("SolanaNodeInstanceRoleArn"); const instanceRole = iam.Role.fromRoleArn(this, "iam-role", importedInstanceRoleArn); + // Making sure our instance will be able to read the assets + asset.bucket.grantRead(instanceRole); + + // Checking configuration + if (instanceCpuType === ec2.AmazonLinuxCpuType.ARM_64) { + throw new Error("ARM_64 is not yet supported"); + } + + if (nodeConfiguration === "validator") { + throw new Error("Validator node configuration is not yet supported for HA setup"); + } + + // Use Ubuntu 20.04 LTS image for amd64. Find more: https://discourse.ubuntu.com/t/finding-ubuntu-images-with-the-aws-ssm-parameter-store/15507 + const ubuntu204stableImageSsmName = "/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id" + // Parsing user data script and injecting necessary variables - const nodeScript = fs.readFileSync(path.join(__dirname, "assets", "user-data", "rpc-node-start.sh")).toString(); + const nodeScript = fs.readFileSync(path.join(__dirname, "assets", "user-data", "node.sh")).toString(); + const accountsVolumeSizeBytes = accountsVolume.sizeGiB * constants.GibibytesToBytesConversionCoefficient; + const dataVolumeSizeBytes = dataVolume.sizeGiB * constants.GibibytesToBytesConversionCoefficient; const modifiedInitNodeScript = cdk.Fn.sub(nodeScript, { - _LIFECYCLE_HOOK_NAME_: lifecycleHookName, - _AUTOSCALING_GROUP_NAME_: autoScalingGroupName, + _AWS_REGION_: REGION, _ASSETS_S3_PATH_: `s3://${asset.s3BucketName}/${asset.s3ObjectKey}`, - _REGION_: REGION, - _SNAPSHOT_S3_PATH_: `s3://${snapshotBucketName}/${polygonClientCombination}-${network}`, - _CLIENT_COMBINATION_: polygonClientCombination, _STACK_NAME_: STACK_NAME, - _FORMAT_DISK_: "true", - _DATA_VOLUME_TYPE_: dataVolumes[0].type, + _STACK_ID_: constants.NoneValue, + _NODE_CF_LOGICAL_ID_: constants.NoneValue, + _ACCOUNTS_VOLUME_TYPE_: accountsVolume.type, + _ACCOUNTS_VOLUME_SIZE_: accountsVolumeSizeBytes.toString(), + _DATA_VOLUME_TYPE_: dataVolume.type, + _DATA_VOLUME_SIZE_: dataVolumeSizeBytes.toString(), + _SOLANA_VERSION_: solanaVersion, + _SOLANA_NODE_TYPE_: nodeConfiguration, + _NODE_IDENTITY_SECRET_ARN_: constants.NoneValue, + _VOTE_ACCOUNT_SECRET_ARN_: constants.NoneValue, + _AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN_: constants.NoneValue, + _REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN_: constants.NoneValue, + _SOLANA_CLUSTER_: solanaCluster, + _LIFECYCLE_HOOK_NAME_: lifecycleHookName, + _AUTOSCALING_GROUP_NAME_: autoScalingGroupName, }); // Setting up the nodse using generic High Availability (HA) Node constract + const healthCheckPath = "/health"; const rpcNodes = new HANodesConstruct (this, "rpc-nodes", { instanceType, - dataVolumes, - machineImage: new ec2.AmazonLinuxImage({ - generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, - cpuType: instanceCpuType, - }), + dataVolumes: [dataVolume, accountsVolume], + machineImage: ec2.MachineImage.fromSsmParameter(ubuntu204stableImageSsmName), role: instanceRole, vpc, securityGroup: instanceSG.securityGroup, userData: modifiedInitNodeScript, numberOfNodes, - rpcPortForALB: 8545, + rpcPortForALB: 8899, albHealthCheckGracePeriodMin, + healthCheckPath, heartBeatDelayMin, lifecycleHookName: lifecycleHookName, autoScalingGroupName: autoScalingGroupName, @@ -120,6 +148,10 @@ export class PolygonRpcNodesStack extends cdk.Stack { id: "AwsSolutions-EC28", reason: "Using basic monitoring to save costs", }, + { + id: "AwsSolutions-IAM5", + reason: "Need read access to the S3 bucket with assets", + }, ], true ); diff --git a/lib/solana/lib/single-node-stack.ts b/lib/solana/lib/single-node-stack.ts index ebcb5996..f1c507bf 100644 --- a/lib/solana/lib/single-node-stack.ts +++ b/lib/solana/lib/single-node-stack.ts @@ -7,14 +7,17 @@ import * as path from "path"; import * as fs from "fs"; import * as nodeCwDashboard from "./assets/node-cw-dashboard" import * as cw from 'aws-cdk-lib/aws-cloudwatch'; +import * as nag from "cdk-nag"; import { SingleNodeConstruct } from "../../constructs/single-node" import * as configTypes from "./config/solanaConfig.interface"; +import * as constants from "../../constructs/constants"; import { SolanaNodeSecurityGroupConstruct } from "./constructs/solana-node-security-group" export interface SolanaSingleNodeStackProps extends cdk.StackProps { instanceType: ec2.InstanceType; instanceCpuType: ec2.AmazonLinuxCpuType; solanaCluster: configTypes.SolanaCluster; + solanaVersion: string; nodeConfiguration: configTypes.SolanaNodeConfiguration; dataVolume: configTypes.SolanaDataVolumeConfig; accountsVolume: configTypes.SolanaAccountsVolumeConfig; @@ -31,6 +34,7 @@ export class SolanaSingleNodeStack extends cdk.Stack { // Setting up necessary environment variables const REGION = cdk.Stack.of(this).region; const STACK_NAME = cdk.Stack.of(this).stackName; + const STACK_ID = cdk.Stack.of(this).stackId; const availabilityZones = cdk.Stack.of(this).availabilityZones; const chosenAvailabilityZone = availabilityZones.slice(0, 1)[0]; @@ -39,6 +43,7 @@ export class SolanaSingleNodeStack extends cdk.Stack { instanceType, instanceCpuType, solanaCluster, + solanaVersion, nodeConfiguration, dataVolume, accountsVolume, @@ -61,7 +66,7 @@ export class SolanaSingleNodeStack extends cdk.Stack { path: path.join(__dirname, "assets"), }); - // Getting the snapshot bucket name and IAM role ARN from the common stack + // Getting the IAM role ARN from the common stack const importedInstanceRoleArn = cdk.Fn.importValue("SolanaNodeInstanceRoleArn"); const instanceRole = iam.Role.fromRoleArn(this, "iam-role", importedInstanceRoleArn); @@ -70,19 +75,18 @@ export class SolanaSingleNodeStack extends cdk.Stack { asset.bucket.grantRead(instanceRole); // Setting up the node using generic Single Node constract - if (instanceCpuType === ec2.AmazonLinuxCpuType.x86_64) { - throw new Error("ARM64 is not supported"); + if (instanceCpuType === ec2.AmazonLinuxCpuType.ARM_64) { + throw new Error("ARM_64 is not yet supported"); } - // Use Ubuntu 20.04 LTS image for amd64 or arm64. Find more: https://discourse.ubuntu.com/t/finding-ubuntu-images-with-the-aws-ssm-parameter-store/15507 - const ubuntu204stableImageSsmName = instanceCpuType === ec2.AmazonLinuxCpuType.X86_64 ? - "/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id" : - "/aws/service/canonical/ubuntu/server/20.04/stable/current/arm64/hvm/ebs-gp2/ami-id"; + // Use Ubuntu 20.04 LTS image for amd64. Find more: https://discourse.ubuntu.com/t/finding-ubuntu-images-with-the-aws-ssm-parameter-store/15507 + const ubuntu204stableImageSsmName = "/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id" const node = new SingleNodeConstruct(this, "sync-node", { instanceName: STACK_NAME, instanceType, dataVolumes: [dataVolume, accountsVolume], + rootDataVolumeDeviceName: "/dev/sda1", machineImage: ec2.MachineImage.fromSsmParameter(ubuntu204stableImageSsmName), vpc, availabilityZone: chosenAvailabilityZone, @@ -94,24 +98,33 @@ export class SolanaSingleNodeStack extends cdk.Stack { }); // Parsing user data script and injecting necessary variables - const nodeStartScript = fs.readFileSync(path.join(__dirname, "assets", "user-data", "node-start.sh")).toString(); + const nodeStartScript = fs.readFileSync(path.join(__dirname, "assets", "user-data", "node.sh")).toString(); + const accountsVolumeSizeBytes = accountsVolume.sizeGiB * constants.GibibytesToBytesConversionCoefficient; + const dataVolumeSizeBytes = dataVolume.sizeGiB * constants.GibibytesToBytesConversionCoefficient; const modifiedInitNodeScript = cdk.Fn.sub(nodeStartScript, { + _AWS_REGION_: REGION, _ASSETS_S3_PATH_: `s3://${asset.s3BucketName}/${asset.s3ObjectKey}`, - _REGION_: REGION, _STACK_NAME_: STACK_NAME, - _RESOURCE_ID_: syncNode.nodeCFLogicalId, - _SNAPSHOT_S3_PATH_: `s3://${snapshotBucketName}/${polygonClientCombination}-${network}`, - _CLIENT_COMBINATION_: polygonClientCombination, - _NETWORK_: network, - _DATA_VOLUME_TYPE_: dataVolumes[0].type, - _FORMAT_DISK_: "true", - + _STACK_ID_: STACK_ID, + _NODE_CF_LOGICAL_ID_: node.nodeCFLogicalId, + _ACCOUNTS_VOLUME_TYPE_: accountsVolume.type, + _ACCOUNTS_VOLUME_SIZE_: accountsVolumeSizeBytes.toString(), + _DATA_VOLUME_TYPE_: dataVolume.type, + _DATA_VOLUME_SIZE_: dataVolumeSizeBytes.toString(), + _SOLANA_VERSION_: solanaVersion, + _SOLANA_NODE_TYPE_: nodeConfiguration, + _NODE_IDENTITY_SECRET_ARN_: solanaNodeIdentitySecretARN, + _VOTE_ACCOUNT_SECRET_ARN_: voteAccountSecretARN, + _AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN_: authorizedWithdrawerAccountSecretARN, + _REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN_: registrationTransactionFundingAccountSecretARN, + _SOLANA_CLUSTER_: solanaCluster, + _LIFECYCLE_HOOK_NAME_: constants.NoneValue, }); node.instance.addUserData(modifiedInitNodeScript); // Adding CloudWatch dashboard to the node - const dashboardString = cdk.Fn.sub(JSON.stringify(nodeCwDashboard.SyncNodeCWDashboardJSON), { + const dashboardString = cdk.Fn.sub(JSON.stringify(nodeCwDashboard.SingleNodeCWDashboardJSON), { INSTANCE_ID:node.instanceId, INSTANCE_NAME: STACK_NAME, REGION: REGION, @@ -125,5 +138,17 @@ export class SolanaSingleNodeStack extends cdk.Stack { new cdk.CfnOutput(this, "node-instance-id", { value: node.instanceId, }); + + // Adding suppressions to the stack + nag.NagSuppressions.addResourceSuppressions( + this, + [ + { + id: "AwsSolutions-IAM5", + reason: "Need read access to the S3 bucket with assets", + }, + ], + true + ); } } diff --git a/lib/solana/sample-configs/.env-erigon-lighthouse b/lib/solana/sample-configs/.env-erigon-lighthouse deleted file mode 100644 index 7cfb0553..00000000 --- a/lib/solana/sample-configs/.env-erigon-lighthouse +++ /dev/null @@ -1,29 +0,0 @@ -############################################################## -# Example configuration for Ethereum nodes runner app on AWS # -############################################################## - -# Set the AWS account is and region for your environment -AWS_ACCOUNT_ID="xxxxxxxxxxx" -AWS_REGION="us-east-2" - -# Common configuration parameters -CLIENT_COMBINATION="erigon-lighthouse-mainnet" # All options: "besu-teku-mainnet" | "geth-lighthouse-mainnet" | "erigon-lighthouse-mainnet" | "erigon-prysm-mainnet" | "nethermind-teku-mainnet" - -# Sync node configuration -ETH_SYNC_INSTANCE_TYPE="m7g.2xlarge" -ETH_SYNC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used -ETH_SYNC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 -ETH_SYNC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families -ETH_SYNC_DATA_VOL_IOPS="7000" # Max IOPS for EBS volumes (not applicable for "instance-store") -ETH_SYNC_DATA_VOL_THROUGHPUT="500" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") - -# RPC nodes configuration -ETH_RPC_INSTANCE_TYPE="m7g.2xlarge" -ETH_RPC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used -ETH_RPC_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 -ETH_RPC_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="10" # Time enough to initialize the instance and start downloading snpashots -ETH_RPC_HA_NODES_HEARTBEAT_DELAY_MIN="150" # Time sufficient enough for a node do download snapshot, from S3 bucket, start clients, and finish sycning the delta -ETH_RPC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 -ETH_RPC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families -ETH_RPC_DATA_VOL_IOPS="10000" # Max IOPS for EBS volumes (not applicable for "instance-store") -ETH_RPC_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") diff --git a/lib/solana/sample-configs/.env-erigon-prysm b/lib/solana/sample-configs/.env-erigon-prysm deleted file mode 100644 index 04f0129a..00000000 --- a/lib/solana/sample-configs/.env-erigon-prysm +++ /dev/null @@ -1,29 +0,0 @@ -############################################################## -# Example configuration for Ethereum nodes runner app on AWS # -############################################################## - -# Set the AWS account is and region for your environment -AWS_ACCOUNT_ID="xxxxxxxxxxx" -AWS_REGION="us-east-2" - -# Common configuration parameters -CLIENT_COMBINATION="erigon-prysm-mainnet" # All options: "besu-teku-mainnet" | "geth-lighthouse-mainnet" | "erigon-lighthouse-mainnet" | "erigon-prysm-mainnet" | "nethermind-teku-mainnet" - -# Sync node configuration -ETH_SYNC_INSTANCE_TYPE="m7g.2xlarge" -ETH_SYNC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used -ETH_SYNC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 -ETH_SYNC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families -ETH_SYNC_DATA_VOL_IOPS="7000" # Max IOPS for EBS volumes (not applicable for "instance-store") -ETH_SYNC_DATA_VOL_THROUGHPUT="500" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") - -# RPC nodes configuration -ETH_RPC_INSTANCE_TYPE="m7g.2xlarge" -ETH_RPC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used -ETH_RPC_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 -ETH_RPC_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="10" # Time enough to initialize the instance and start downloading snpashots -ETH_RPC_HA_NODES_HEARTBEAT_DELAY_MIN="150" # Time sufficient enough for a node do download snapshot, from S3 bucket, start clients, and finish sycning the delta -ETH_RPC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 -ETH_RPC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families -ETH_RPC_DATA_VOL_IOPS="10000" # Max IOPS for EBS volumes (not applicable for "instance-store") -ETH_RPC_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") diff --git a/lib/solana/sample-configs/.env-geth-lighthouse b/lib/solana/sample-configs/.env-geth-lighthouse deleted file mode 100644 index 15b69472..00000000 --- a/lib/solana/sample-configs/.env-geth-lighthouse +++ /dev/null @@ -1,29 +0,0 @@ -############################################################## -# Example configuration for Ethereum nodes runner app on AWS # -############################################################## - -# Set the AWS account is and region for your environment -AWS_ACCOUNT_ID="xxxxxxxxxxx" -AWS_REGION="us-east-2" - -# Common configuration parameters -CLIENT_COMBINATION="geth-lighthouse-mainnet" # All options: "besu-teku-mainnet" | "geth-lighthouse-mainnet" | "erigon-lighthouse-mainnet" | "erigon-prysm-mainnet" | "nethermind-teku-mainnet" - -# Sync node configuration -ETH_SYNC_INSTANCE_TYPE="m6g.2xlarge" -ETH_SYNC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used -ETH_SYNC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 -ETH_SYNC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families -ETH_SYNC_DATA_VOL_IOPS="6000" # Max IOPS for EBS volumes (not applicable for "instance-store") -ETH_SYNC_DATA_VOL_THROUGHPUT="400" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") - -# RPC nodes configuration -ETH_RPC_INSTANCE_TYPE="m7g.2xlarge" -ETH_RPC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used -ETH_RPC_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 -ETH_RPC_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="10" # Time enough to initialize the instance and start downloading snpashots -ETH_RPC_HA_NODES_HEARTBEAT_DELAY_MIN="60" # Time sufficient enough for a node do download snapshot, from S3 bucket, start clients, and finish sycning the delta -ETH_RPC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 -ETH_RPC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families -ETH_RPC_DATA_VOL_IOPS="8000" # Max IOPS for EBS volumes (not applicable for "instance-store") -ETH_RPC_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") diff --git a/lib/solana/sample-configs/.env-sample-heavyrpc b/lib/solana/sample-configs/.env-sample-heavyrpc new file mode 100644 index 00000000..91af0fcf --- /dev/null +++ b/lib/solana/sample-configs/.env-sample-heavyrpc @@ -0,0 +1,36 @@ +############################################################# +# Example configuration for Solana nodes runner app on AWS # +############################################################# + +## Set the AWS account is and region for your environment ## +AWS_ACCOUNT_ID="xxxxxxxxxxx" +AWS_REGION="us-east-2" + +## Common configuration parameters ## +SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" +SOLANA_NODE_CONFIGURATION="heavyrpc" # All options: "validator", "lightrpc", "heavyrpc" +SOLANA_VERSION="1.16.2" # Current required version of Solana + +SOLANA_INSTANCE_TYPE="x2idn.16xlarge" +SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used +# Data volume configuration +SOLANA_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +SOLANA_DATA_VOL_SIZE="2000" # Current required data size to keep both smapshot archive and unarchived version of it +SOLANA_DATA_VOL_IOPS="12000" # Max IOPS for EBS volumes (not applicable for "instance-store") +SOLANA_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +# Accounts volume configuration +SOLANA_ACCOUNTS_VOL_TYPE="instance-store" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +SOLANA_ACCOUNTS_VOL_SIZE="0" # Current required data size to keep both smapshot archive and unarchived version of it +SOLANA_ACCOUNTS_VOL_IOPS="0" # Max IOPS for EBS volumes (not applicable for "instance-store") +SOLANA_ACCOUNTS_VOL_THROUGHPUT="0" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +# Secrets configuration +SOLANA_NODE_IDENTITY_SECRET_ARN="none" # Optional. The ARN of the secret in AWS Secrets Manager with the node identity key pair. In case you want to provision a node but keep the old identity. +SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. +SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. +SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for validator node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation + +## HA nodes configuration ## +SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 +SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="80" # Time enough to initialize the instance +SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="80" # Time sufficient enough for a node do sync + diff --git a/lib/solana/sample-configs/.env-sample-lightrpc b/lib/solana/sample-configs/.env-sample-lightrpc new file mode 100644 index 00000000..2031bfa0 --- /dev/null +++ b/lib/solana/sample-configs/.env-sample-lightrpc @@ -0,0 +1,36 @@ +############################################################# +# Example configuration for Solana nodes runner app on AWS # +############################################################# + +## Set the AWS account is and region for your environment ## +AWS_ACCOUNT_ID="xxxxxxxxxxx" +AWS_REGION="us-east-2" + +## Common configuration parameters ## +SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" +SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "validator", "lightrpc", "heavyrpc" +SOLANA_VERSION="1.16.2" # Current required version of Solana + +SOLANA_INSTANCE_TYPE="r6a.8xlarge" +SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used +# Data volume configuration +SOLANA_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +SOLANA_DATA_VOL_SIZE="2000" # Current required data size to keep both smapshot archive and unarchived version of it +SOLANA_DATA_VOL_IOPS="12000" # Max IOPS for EBS volumes (not applicable for "instance-store") +SOLANA_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +# Accounts volume configuration +SOLANA_ACCOUNTS_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +SOLANA_ACCOUNTS_VOL_SIZE="500" # Current required data size to keep both smapshot archive and unarchived version of it +SOLANA_ACCOUNTS_VOL_IOPS="6000" # Max IOPS for EBS volumes (not applicable for "instance-store") +SOLANA_ACCOUNTS_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +# Secrets configuration +SOLANA_NODE_IDENTITY_SECRET_ARN="none" # Optional. The ARN of the secret in AWS Secrets Manager with the node identity key pair. In case you want to provision a node but keep the old identity. +SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. +SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. +SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for validator node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation + +## HA nodes configuration ## +SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 +SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="60" # Time enough to initialize the instance +SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="60" # Time sufficient enough for a node do sync + diff --git a/lib/solana/sample-configs/.env-sample-validator b/lib/solana/sample-configs/.env-sample-validator new file mode 100644 index 00000000..f35e4f7e --- /dev/null +++ b/lib/solana/sample-configs/.env-sample-validator @@ -0,0 +1,36 @@ +############################################################# +# Example configuration for Solana nodes runner app on AWS # +############################################################# + +## Set the AWS account is and region for your environment ## +AWS_ACCOUNT_ID="xxxxxxxxxxx" +AWS_REGION="us-east-2" + +## Common configuration parameters ## +SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" +SOLANA_NODE_CONFIGURATION="validator" # All options: "validator", "lightrpc", "heavyrpc" +SOLANA_VERSION="1.16.2" # Current required version of Solana + +SOLANA_INSTANCE_TYPE="r6a.8xlarge" +SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used +# Data volume configuration +SOLANA_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +SOLANA_DATA_VOL_SIZE="2000" # Current required data size to keep both smapshot archive and unarchived version of it +SOLANA_DATA_VOL_IOPS="12000" # Max IOPS for EBS volumes (not applicable for "instance-store") +SOLANA_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +# Accounts volume configuration +SOLANA_ACCOUNTS_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +SOLANA_ACCOUNTS_VOL_SIZE="500" # Current required data size to keep both smapshot archive and unarchived version of it +SOLANA_ACCOUNTS_VOL_IOPS="6000" # Max IOPS for EBS volumes (not applicable for "instance-store") +SOLANA_ACCOUNTS_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +# Secrets configuration +SOLANA_NODE_IDENTITY_SECRET_ARN="none" # Optional. The ARN of the secret in AWS Secrets Manager with the node identity key pair. In case you want to provision a node but keep the old identity. +SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. +SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. +SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for validator node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation + +## HA nodes configuration ## +SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 +SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="60" # Time enough to initialize the instance +SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="60" # Time sufficient enough for a node do sync + diff --git a/lib/solana/single-node-deploy.json b/lib/solana/single-node-deploy.json new file mode 100644 index 00000000..6f96ab75 --- /dev/null +++ b/lib/solana/single-node-deploy.json @@ -0,0 +1,5 @@ +{ + "solana-single-node-heavyrpc": { + "nodeinstanceid": "i-02e19726f5fa9af2e" + } +} From c599bdd3eda061865dfc6de37bfe12c5aa29bbaf Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Thu, 5 Oct 2023 18:01:38 +1100 Subject: [PATCH 03/12] [WIP] Draft version of Solana Node Runner --- lib/constructs/constants.ts | 3 +- lib/constructs/ha-rpc-nodes-with-alb.ts | 9 +++- lib/constructs/single-node.ts | 4 +- lib/ethereum/lib/assets/cw-agent.json | 15 ------ lib/solana/.env-sample | 10 ++-- lib/solana/README.md | 42 ++++++++------- lib/solana/doc/assets/Recommended_infra.md | 7 +++ lib/solana/doc/assets/Solana_on_AWS.md | 50 ++++++++++++++++++ lib/solana/doc/assets/Well_Architected.md | 26 ++++----- lib/solana/doc/assets/image.png | Bin 0 -> 367816 bytes lib/solana/ha-nodes-deploy.json | 4 +- ...template.sh => node-consensus-template.sh} | 0 lib/solana/lib/assets/user-data/node.sh | 13 ++--- .../lib/config/solanaConfig.interface.ts | 2 +- lib/solana/lib/ha-nodes-stack.ts | 6 +-- lib/solana/lib/single-node-stack.ts | 1 + ...sample-validator => .env-sample-consensus} | 10 ++-- .../sample-configs/.env-sample-heavyrpc | 13 +++-- .../sample-configs/.env-sample-lightrpc | 10 ++-- website/docusaurus.config.js | 2 +- website/package.json | 4 +- 21 files changed, 141 insertions(+), 90 deletions(-) create mode 100644 lib/solana/doc/assets/Recommended_infra.md create mode 100644 lib/solana/doc/assets/Solana_on_AWS.md create mode 100644 lib/solana/doc/assets/image.png rename lib/solana/lib/assets/solana/{node-validator-template.sh => node-consensus-template.sh} (100%) rename lib/solana/sample-configs/{.env-sample-validator => .env-sample-consensus} (89%) diff --git a/lib/constructs/constants.ts b/lib/constructs/constants.ts index 2a870e0a..3104a04b 100644 --- a/lib/constructs/constants.ts +++ b/lib/constructs/constants.ts @@ -1,3 +1,4 @@ export const InstanceStoreageDeviceVolumeType = "instance-store"; export const NoneValue = "none"; -export const VolumeDeviceNames = ["/dev/sdf", "/dev/sdg", "/dev/sdh", "/dev/sdi", "/dev/sdj", "/dev/sdk"] \ No newline at end of file +export const VolumeDeviceNames = ["/dev/sdf", "/dev/sdg", "/dev/sdh", "/dev/sdi", "/dev/sdj", "/dev/sdk"] +export const GibibytesToBytesConversionCoefficient = 1073741824; \ No newline at end of file diff --git a/lib/constructs/ha-rpc-nodes-with-alb.ts b/lib/constructs/ha-rpc-nodes-with-alb.ts index 14a6c47f..9a3bcba4 100644 --- a/lib/constructs/ha-rpc-nodes-with-alb.ts +++ b/lib/constructs/ha-rpc-nodes-with-alb.ts @@ -7,10 +7,12 @@ import * as albv2 from "aws-cdk-lib/aws-elasticloadbalancingv2"; import * as configTypes from "./config.interface"; import * as constants from "./constants"; import * as nag from "cdk-nag"; +import { HealthCheck } from "aws-cdk-lib/aws-appmesh"; export interface HANodesConstructCustomProps { instanceType: ec2.InstanceType, dataVolumes: configTypes.DataVolumeConfig[], + rootDataVolumeDeviceName?: string, machineImage: cdk.aws_ec2.IMachineImage, role: cdk.aws_iam.IRole, vpc: cdk.aws_ec2.IVpc, @@ -19,6 +21,7 @@ export interface HANodesConstructCustomProps { numberOfNodes: number; rpcPortForALB: number, albHealthCheckGracePeriodMin: number; + healthCheckPath? : string; heartBeatDelayMin: number; lifecycleHookName: string; autoScalingGroupName: string; @@ -35,6 +38,7 @@ export class HANodesConstruct extends cdkContructs.Construct { const { instanceType, dataVolumes, + rootDataVolumeDeviceName, machineImage, role, vpc, @@ -43,6 +47,7 @@ export class HANodesConstruct extends cdkContructs.Construct { numberOfNodes, rpcPortForALB, albHealthCheckGracePeriodMin, + healthCheckPath, heartBeatDelayMin, lifecycleHookName, autoScalingGroupName, @@ -51,7 +56,7 @@ export class HANodesConstruct extends cdkContructs.Construct { let blockDevices: ec2.BlockDevice[] = [ { // ROOT VOLUME - deviceName: "/dev/xvda", + deviceName: rootDataVolumeDeviceName ? rootDataVolumeDeviceName : "/dev/xvda", volume: autoscaling.BlockDeviceVolume.ebs(46, { deleteOnTermination: true, throughput: 125, @@ -172,7 +177,7 @@ export class HANodesConstruct extends cdkContructs.Construct { healthCheck: { enabled: true, healthyHttpCodes: "200-299", - path: "/", + path: healthCheckPath ? healthCheckPath : "/", // In the future, can create a separate service to have a more reliable health check port: rpcPortForALB.toString(), unhealthyThresholdCount: 2, diff --git a/lib/constructs/single-node.ts b/lib/constructs/single-node.ts index f1cb25e8..b9a31fec 100644 --- a/lib/constructs/single-node.ts +++ b/lib/constructs/single-node.ts @@ -9,6 +9,7 @@ export interface SingleNodeConstructCustomProps { instanceName: string, instanceType: ec2.InstanceType, dataVolumes: configTypes.DataVolumeConfig[], + rootDataVolumeDeviceName?: string, machineImage: cdk.aws_ec2.IMachineImage, role: cdk.aws_iam.IRole, vpc: cdk.aws_ec2.IVpc, @@ -28,6 +29,7 @@ export class SingleNodeConstruct extends cdkContructs.Construct { instanceName, instanceType, dataVolumes, + rootDataVolumeDeviceName, machineImage, role, vpc, @@ -45,7 +47,7 @@ export class SingleNodeConstruct extends cdkContructs.Construct { blockDevices: [ { // ROOT VOLUME - deviceName: "/dev/xvda", + deviceName: rootDataVolumeDeviceName ? rootDataVolumeDeviceName :"/dev/xvda", volume: ec2.BlockDeviceVolume.ebs(46, { deleteOnTermination: true, encrypted: true, diff --git a/lib/ethereum/lib/assets/cw-agent.json b/lib/ethereum/lib/assets/cw-agent.json index b4f3d972..b0d696f3 100644 --- a/lib/ethereum/lib/assets/cw-agent.json +++ b/lib/ethereum/lib/assets/cw-agent.json @@ -3,21 +3,6 @@ "metrics_collection_interval": 60, "run_as_user": "root" }, - "logs": { - "logs_collected": { - "files": { - "collect_list": [{ - "file_path": "/var/log/cloud-init-output.log", - "log_group_name": "cloud-init-output.log", - "log_stream_name": "{instance_id}" - }, { - "file_path": "/var/log/initial-sync.log", - "log_group_name": "initial-sync.log", - "log_stream_name": "{instance_id}" - }] - } - } - }, "metrics": { "aggregation_dimensions": [ [ diff --git a/lib/solana/.env-sample b/lib/solana/.env-sample index 2031bfa0..d9a6e71b 100644 --- a/lib/solana/.env-sample +++ b/lib/solana/.env-sample @@ -8,7 +8,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" -SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "validator", "lightrpc", "heavyrpc" +SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "consensus", "lightrpc", "heavyrpc" SOLANA_VERSION="1.16.2" # Current required version of Solana SOLANA_INSTANCE_TYPE="r6a.8xlarge" @@ -25,12 +25,12 @@ SOLANA_ACCOUNTS_VOL_IOPS="6000" # Max IOPS for EBS volumes (not ap SOLANA_ACCOUNTS_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") # Secrets configuration SOLANA_NODE_IDENTITY_SECRET_ARN="none" # Optional. The ARN of the secret in AWS Secrets Manager with the node identity key pair. In case you want to provision a node but keep the old identity. -SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. -SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. -SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for validator node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation +SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. +SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. +SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for consensus node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation ## HA nodes configuration ## SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="60" # Time enough to initialize the instance -SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="60" # Time sufficient enough for a node do sync +SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="10" # Time sufficient enough for a node do sync diff --git a/lib/solana/README.md b/lib/solana/README.md index 6035038e..b3af0ba2 100644 --- a/lib/solana/README.md +++ b/lib/solana/README.md @@ -1,6 +1,6 @@ # Sample AWS Blockchain Node Runner app for Solana Nodes -Solana nodes on AWS can be deployes in 3 different configurations: Validator, Light RPC and Heavy RPC. In addition, you can choose to deploy those configurations as a single node or a highly available (HA) nodes setup. Learn more about configurations on [Solana on AWS documentation page](https://docs.solana.com/TBA) and below are the details on single node and HA deployment setups. +Solana nodes on AWS can be deployed in 3 different configurations: Consensus, Light RPC and Heavy RPC. In addition, you can choose to deploy those configurations as a single node or a highly available (HA) nodes setup. Learn more about configurations on [Solana on AWS documentation page](https://docs.solana.com/TBA) and below are the details on single node and HA deployment setups. ## Overview of Deployment Architectures for Single and HA setups @@ -8,28 +8,28 @@ Solana nodes on AWS can be deployes in 3 different configurations: Validator, Li ![Single Node Deployment](./doc/assets/Architecture-SingleNode.drawio.png) -1. A Solana node deployed in the [Default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) continuesly synchronizes with the rest of nodes on [Solana Clusters](https://docs.solana.com/clusters) through [Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html). +1. A Solana node deployed in the [Default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) continuously synchronizes with the rest of nodes on [Solana Clusters](https://docs.solana.com/clusters) through [Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html). 2. The Solana node is used by dApps or development tools internally from within the Default VPC. JSON RPC API is not exposed to the Internet directly to protect nodes from unauthorized access. -3. The Solanna node uses all required secrets locally, but stores a copy in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) as secure backup. +3. The Solana node uses all required secrets locally, but stores a copy in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) as secure backup. 4. The Solana node sends various monitoring metrics for both EC2 and Solana nodes to Amazon CloudWatch. ### HA setup ![Highly Available Nodes Deployment](./doc/assets/Architecture-HANodes.drawio.png) -1. A set of Solana nodes are deployed within the [Auto Scaling Group](https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-groups.html) in the [Default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) continuesly synchronizes with the rest of nodes on [Solana Clusters](https://docs.solana.com/clusters) through [Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html). -2. The Solana nodes are accessed by dApps or development tools internallythrough [Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html). JSON RPC API is not exposed to the Internet to protect nodes from unauthorized access. dApps need to handle user authentication and API protection, like [in this example for dApps on AWS](https://aws.amazon.com/blogs/architecture/dapp-authentication-with-amazon-cognito-and-web3-proxy-with-amazon-api-gateway/). -3. The Solanna nodes use all required secrets locally, but store a copy in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) as secure backup. +1. A set of Solana nodes are deployed within the [Auto Scaling Group](https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-groups.html) in the [Default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) continuously synchronizes with the rest of nodes on [Solana Clusters](https://docs.solana.com/clusters) through [Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html). +2. The Solana nodes are accessed by dApps or development tools internally through [Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html). JSON RPC API is not exposed to the Internet to protect nodes from unauthorized access. dApps need to handle user authentication and API protection, like [in this example for dApps on AWS](https://aws.amazon.com/blogs/architecture/dapp-authentication-with-amazon-cognito-and-web3-proxy-with-amazon-api-gateway/). +3. The Solana nodes use all required secrets locally, but store a copy in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) as secure backup. 4. The Solana nodes send various monitoring metrics for both EC2 and Solana nodes to Amazon CloudWatch. ## Managing Secrets During the startup, if a node can't find the necessary identity file on the attached Root EBS volume, it generates a new one and stores it in AWS Secrets Manager. For a single-node deployment, the ARN of a secret can be provided within the `.env` configuration file with configuration and the node will pick it up. -Solana node in Light RPC or Heavy RPC configuration, it uses only 1 secret: +Light RPC or Heavy RPC nodes use only 1 secret: - **Solana Node Identity Secret**: The identity key pair for a Solana node. -A node in Validator configuration uses up to 3 more identity secrets: +Consensus node uses up to 3 more identity secrets: - **Vote Account Secret**: The [Validator Identity's key pair](https://docs.solana.com/running-validator/vote-accounts#validator-identity). @@ -37,11 +37,7 @@ A node in Validator configuration uses up to 3 more identity secrets: - **Registration Transaction Funding Account Secret**: An account that has sufficient SOL to pay for on-chain validator creation transaction. If not present, the node provisioning script assumes the on-chain validator creation transaction was issued elsewhere and will skip it. -## Well-Architected - -Review the [Well-Architected Checklist](./doc/assets/Well_Architected.md) for pros and cons of this solution. - -## Solution Walkthrough +## Setup Instructions ### Setup Cloud9 @@ -74,7 +70,7 @@ Create your own copy of `.env` file and edit it: # Make sure you are in aws-blockchain-node-runners/lib/solana cd lib/solana pwd - cp .env-sample .env + cp ./sample-configs/.env-sample-lightrpc .env nano .env ``` **NOTE:** Example configuration parameters are set in the local `.env-sample` file. You can find more examples inside `sample-configs` directory. @@ -96,7 +92,7 @@ Create your own copy of `.env` file and edit it: npx cdk deploy solana-single-node --json --outputs-file single-node-deploy.json ``` -6. After starting the node you need to wait for the inital syncronization process to finish. It may take about 30 minutes and you can use Amazon CloudWatch to track the progress. There is a script that publishes CloudWatch metrics every 5 minutes, where you can watch `current block` and `slots behind` metrics. When the node is fully synced the `slots behind` metric should go to 0. To see them: +6. After starting the node you need to wait for the initial synchronization process to finish. It may take about 30 minutes and you can use Amazon CloudWatch to track the progress. There is a script that publishes CloudWatch metrics every 5 minutes, where you can watch `current block` and `slots behind` metrics. When the node is fully synced the `slots behind` metric should go to 0. To see them: - Navigate to [CloudWatch service](https://console.aws.amazon.com/cloudwatch/) (make sure you are in the region you have specified for `AWS_REGION`) - Open `Dashboards` and select `solana-single-node` from the list of dashboards. @@ -128,7 +124,7 @@ The result should be like this (the actual balance might change): {"jsonrpc":"2.0","result":{"context":{"apiVersion":"1.16.2","slot":221433176},"value":12870473061872488},"id":1} ``` - If the nodes are still starting and catching up with the chain, you will see the following repsonse: + If the nodes are still starting and catching up with the chain, you will see the following response: ```HTML @@ -138,11 +134,11 @@ The result should be like this (the actual balance might change): ``` -**NOTE:** By default and for security reasons the load balancer is available only from wihtin the default VPC in the region where it is deployed. It is not available from the Internet and is not open for external connections. Before opening it up please make sure you protect your RPC APIs. +**NOTE:** By default and for security reasons the load balancer is available only from within the default VPC in the region where it is deployed. It is not available from the Internet and is not open for external connections. Before opening it up please make sure you protect your RPC APIs. -### Clearing up and undeploying everything +### Clearing up and undeploy everything -1. Undeploy RPC Nodes, Sync Nodes and Comon components +1. Undeploy HA Nodes, Single Nodes and Common stacks ```bash # Setting the AWS account id and region in case local .env file is lost @@ -213,6 +209,14 @@ The result should be like this (the actual balance might change): ``` +## Well-Architected + +Review the [Well-Architected Checklist](./doc/assets/Well_Architected.md) for pros and cons of this solution. + +## Recommended infrastructure + +Review the [Recommended Infrastructure](./doc/assets/Recommended_infra.md) document for details. + ## Upgrades When nodes need to be upgraded or downgraded, [use blue/green pattern to do it](https://aws.amazon.com/blogs/devops/performing-bluegreen-deployments-with-aws-codedeploy-and-auto-scaling-groups/). This is not yet automated and contributions are welcome! \ No newline at end of file diff --git a/lib/solana/doc/assets/Recommended_infra.md b/lib/solana/doc/assets/Recommended_infra.md new file mode 100644 index 00000000..4c36b43e --- /dev/null +++ b/lib/solana/doc/assets/Recommended_infra.md @@ -0,0 +1,7 @@ +# Recommended configurations for running Solana nodes on AWS + +| Usage pattern | Ideal configuration | Primary option on AWS | Data Transfer Estimates | Config reference | +|---|---|---|---|---| +| 1/ Consensus node | 32 vCPU, 256 GB RAM, Accounts volume: 1TB, 5K IOPS, 700 MB/s throughput, Data volume: 3TB, 10K IOPS, 700 MB/s throughput | r6a.8xlarge, Accounts volume: EBS gp3 1TB, 5K IOPS, 700 MB/s throughput, Data volume: EBS gp3 10K IOPS, 700 MB/s throughput | Proportional to the amount at stake. Between 200TB to 400TB/month | [.env-sample-consensus](../../sample-configs/.env-sample-consensus) | +| 2/ Light RPC node (no secondary indexes) | 32 vCPU, 256 GB RAM, Accounts volume: 1TB, 5K IOPS, 700 MB/s throughput, Data volume: 3TB, 12K IOPS, 700 MB/s throughput | r6a.8xlarge, Accounts volume: EBS gp3 1TB, 5K IOPS, 700 MB/s throughput Data volume: EBS gp3 12K IOPS, 700 MB/s throughput | 150-200TB/month (no staking) | [.env-sample-lightrpc](../../sample-configs/.env-sample-lightrpc) | +| 3/ Full RPC node (with all secondary indexes) | 64 vCPU, 1 TB RAM, Accounts volume: 1TB, 7K IOPS, 700 MB/s throughput, Data volume: 3TB, 16K IOPS, 700 MB/s throughput | x2idn.16xlarge, Accounts: instance storage (ephemeral NVMe volumes) 1.9 TB, Data volume: 3TB, 12K IOPS, 700 MB/s throughput | 150-200TB/month (no staking) | [.env-sample-heavyrpc](../../sample-configs/.env-sample-heavyrpc) | \ No newline at end of file diff --git a/lib/solana/doc/assets/Solana_on_AWS.md b/lib/solana/doc/assets/Solana_on_AWS.md new file mode 100644 index 00000000..77a66b85 --- /dev/null +++ b/lib/solana/doc/assets/Solana_on_AWS.md @@ -0,0 +1,50 @@ +# Solana on AWS + +Running Solana nodes on AWS can help to reduce operational costs and improve reliability of your validators or RPC services. In this guide we will review the major use cases for running self-managed Solana nodes, understand their infrastructure requirements, and costs considerations. + +## Solana node configurations on AWS + +There are four major use cases for running Solana nodes: consensus, “light” RPC node, “heavy” RPC node, and history node. Depending on the use case, you start your ‘solana-validator’ process with different set of parameters and might use different infrastructure configurations. Let’s review them. + +### Consensus node + +Consensus nodes on both Mainnet Beta and testnets [support proof-of-stake consensus](https://solana.com/staking) and are run by operators to either stake themselves or to accept delegated stakes from other holders of Solana tokens (SOL). At the time of writing (September 2023) the configuration on AWS with good cost/performance ratio is [r6a.8xlarge EC2 instance type](https://aws.amazon.com/ec2/instance-types/r6a/) with three [EBS gp3 volumes](https://aws.amazon.com/ebs/general-purpose/): one for root volume and two storing Accounts and Data separately: +- Root volume: EBS gp3 500 GB, 3K IOPS, 250 MB/s throughput, +- Accounts volume: EBS gp3 500GB, 5K IOPS, 700 MB/s throughput, +- Data volume: EBS gp3 2TB, 10K IOPS, 700 MB/s throughput. + +To set up new validator node, you first need to generate cryptographic keys that will be used in the process. After the keys are generated with the standard `solana-keygen` tool on the EC2 instance you can keep a backup copy of the key pair in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html). + +Based on amount you have at stake, you can estimate with [community-developed calculators](https://www.stakingrewards.com/asset/solana) the amount of profit your validator node can generate and then calculate the cost of the configuration with [AWS calculator](https://calculator.aws/#/). Also note that, depending on the amount at stake, your validator node will generate between 150 TB to 300 TB of data transfer out to the Internet per month, so talk to your AWS account manager about potential cost optimization. + +- To run a single Consensus node on AWS, use the [Solana Node Runner CDK application](https://github.com/aws-samples/aws-blockchain-node-runners/tree/solana/lib/solana) in [AWS Blockchain Node Runners](https://aws-samples.github.io/aws-blockchain-node-runners/) and use [sample config for Consensus node](https://github.com/aws-samples/aws-blockchain-node-runners/blob/solana/lib/solana/sample-configs/.env-sample-validator). + +### Light RPC nodes + +Light RPC nodes can be used by your application to perform all RPC calls, except those that trigger scan operation to the entire account set, like [getProgramAccounts](https://docs.solana.com/api/http#getprogramaccounts) and [SPL-token-specific requests](https://docs.solana.com/api/http#gettokenaccountsbydelegate): `getTokenAccountsByDelegate`, `getTokenAccountBalance`, `getTokenAccountsByOwner`, `getTokenLargestAccounts`, and `getTokenSupply`. These node types can use the same infrastructure as the consensus nodes, but instead of validating transactions, it will expose HTTP and WebSocket endpoints for your application to interact with the node trough JSON RPC API and RPC PubSub respectively. On AWS you can use the same as with consensus node `r6a.8xlarge` EC2 instance type the same three EBS gp3 volumes: +- Root volume: EBS gp3 500 GB, 3K IOPS, 250 MB/s throughput, +- Accounts volume: EBS gp3 500GB, 5K IOPS, 700 MB/s throughput, +- Data volume: EBS gp3 2TB, 10K IOPS, 700 MB/s throughput. + +Data transfer costs for this node can vary depending on whether you expose the RPC endpoints to the Internet (generates more traffic to the Internet) or consume it with the same AWS Availability Zone (will cost you nothing). If you are not exposing the RPC interface for external consumption, then your node will generate about 13-15 TB of outgoing data per month per node. It is less than Consensus nodes, but can still be sufficient and better be discussed with your AWS account manager. + +- To run Light RPC node on AWS, use the [Solana Node Runner CDK application](https://github.com/aws-samples/aws-blockchain-node-runners/tree/solana/lib/solana) in [AWS Blockchain Node Runners](https://aws-samples.github.io/aws-blockchain-node-runners/) and use [sample config for Light RPC node](https://github.com/aws-samples/aws-blockchain-node-runners/blob/solana/lib/solana/sample-configs/.env-sample-lightrpc). You can use both Single-node and Highly Available-node setup. + +### Heavy RPC nodes + +Heavy RPC nodes allow you to call "heavier" RPC functions like mentioned above. To use them you need to enable extra indexes on your RPC node, which requires more hardware. At the time of writing (September 2023) it is recommended to use at least 1 TB or RAM with NVMe discs, or, on AWS an instance like `x2idn.16xlarge` which is also equipped with a physically-attached NVMe SSD [Instance Store volume](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html). The storage configurations looks like this: +- Root volume: EBS gp3 500 GB, 3K IOPS, 250 MB/s throughput, +- Accounts volume: Instance store (comes with the `x2idn.16xlarge` instance) 1.9TB, +- Data volume: EBS gp3 2TB, 10K IOPS, 700 MB/s throughput. + +As with the Light RPC nodes, data transfer amount may vary and the estimated amount is 15 TB of outgoing data per month per node. + +- To run Heavy RPC node on AWS, use the [Solana Node Runner CDK application](https://github.com/aws-samples/aws-blockchain-node-runners/tree/solana/lib/solana) in [AWS Blockchain Node Runners](https://aws-samples.github.io/aws-blockchain-node-runners/) and use [sample config for Heavy RPC node](https://github.com/aws-samples/aws-blockchain-node-runners/blob/solana/lib/solana/sample-configs/.env-sample-heavyrpc). You can use both Single-node and Highly Available-node setup. + +### History nodes + +History nodes are not yet available on AWS because or dependency on the GCP's BigTable. But there is some awesome work that Solana community is doing to make this data available in cloud-agnostic way, so stay tuned. + +## Cost Optimization + +To optimize the cost you can use either [Compute Savings Plan for EC2](https://aws.amazon.com/savingsplans/compute-pricing/) or talk to one of the AWS partners like [Antimetal](https://www.antimetal.com/) or [Zesty](https://zesty.co/). We don’t recommend using Spot instances for Solana nodes because they can be terminated with a short notice and a similar instance might not be immediately available for you even with on-demand pricing. \ No newline at end of file diff --git a/lib/solana/doc/assets/Well_Architected.md b/lib/solana/doc/assets/Well_Architected.md index ddd50f5e..2c9a14d8 100644 --- a/lib/solana/doc/assets/Well_Architected.md +++ b/lib/solana/doc/assets/Well_Architected.md @@ -1,26 +1,26 @@ # Well-Architected Checklist -This is the Well-Architected checklist for Ethereum nodes implementation of the AWS Blockchain Node Runner app. This checklist takes into account questions from the [AWS Well-Architected Framework](https://aws.amazon.com/architecture/well-architected/) which are relevant to this workload. Please feel free to add more checks from the framework if required for your workload. +This is the Well-Architected checklist for Solana nodes implementation of the AWS Blockchain Node Runner app. This checklist takes into account questions from the [AWS Well-Architected Framework](https://aws.amazon.com/architecture/well-architected/) which are relevant to this workload. Please feel free to add more checks from the framework if required for your workload. | Pillar | Control | Question/Check | Remarks | |:------------------------|:----------------------------------|:---------------------------------------------------------------------------------|:-----------------| -| Security | Network protection | Are there unnecessary open ports in security groups? | Please note that Erigon snap sync port remains open for non-erigon clients, i.e. Port 42069 (TCP/UDP). | -| | | Traffic inspection | AWS WAF could be implemented for traffic inspection. Additional charges will apply. | -| | Compute protection | Reduce attack surface | This solution uses Amazon Linux 2 AMI. You may choose to run hardening scripts on it. | +| Security | Network protection | Are there unnecessary open ports in security groups? | Please note that ports 8801 to 8812 (TCP/UDP) for Solana are open to public to support P2P protocols. We have to rely on the protection mechanisms built into the Solana validators software to protect those ports. | +| | | Traffic inspection | Traffic protection is not used in the solution. AWS Web Applications Firewall (WAF) could be implemented for traffic inspection. Additional charges will apply. | +| | Compute protection | Reduce attack surface | This solution uses Ubuntu 20.04 AMI. You may choose to run hardening scripts on it. | | | | Enable people to perform actions at a distance | This solution uses AWS Systems Manager for terminal session, not ssh ports. | | | Data protection at rest | Use encrypted Amazon Elastic Block Store (Amazon EBS) volumes | This solution uses encrypted Amazon EBS volumes. | | | | Use encrypted Amazon Simple Storage Service (Amazon S3) buckets | This solution uses Amazon S3 managed keys (SSE-S3) encryption. | | | Data protection in transit | Use TLS | The AWS Application Load balancer currently uses HTTP listener. Create HTTPS listener with self signed certificate if TLS is desired. | | | Authorization and access control | Use instance profile with Amazon Elastic Compute Cloud (Amazon EC2) instances | This solution uses AWS Identity and Access Management (AWS IAM) role instead of IAM user. | -| | | Following principle of least privilege access | In sync node, root user is not used (using special user "ethereum" instead"). | +| | | Following principle of least privilege access | In all node types, root user is not used (using special user "solana" instead). | | | Application security | Security focused development practices | cdk-nag is being used with appropriate suppressions. | -| Cost optimization | Service selection | Use cost effective resources | AWS Graviton-based Amazon EC2 instances are being used, which are cost effective compared to Intel/AMD instances. | -| | Cost awareness | Estimate costs | One sync node with m7g.2xlarge for geth-lighthouse configuration (2048GB ssd) will cost around US$430 per month in the US East (N. Virginia) region. Additional charges will apply if you choose to deploy RPC nodes with load balancer. | -| Reliability | Resiliency implementation | Withstand component failures | This solution uses AWS Application Load Balancer with RPC nodes for high availability. If sync node fails, Amazon S3 backup can be used to reinstate the nodes. | -| | Data backup | How is data backed up? | Data is backed up to Amazon S3 using [s5cmd](https://github.com/peak/s5cmd) tool. | +| Cost optimization | Service selection | Use cost effective resources | 1/ AMD-based instances are used for Consensus and Light RPC node to save the costs. Consider compiling Graviton-based binaries to improve costs for compute. 2/ Cost-effective EBS gp3 are preferred instead of io2. 3/ Solana nodes generate a substantial amount of outgoing data traffic, which deeds to be addressed with non-technical means like getting private agreements with AWS. | +| | Cost awareness | Estimate costs | Single Light RPC node with `r6a.8xlarge` EBS gp3 volumes about 2549 GB with On-Demand pricing will cost around US$1,596.43 per month in the US East (N. Virginia) region. More cost-optimal option with 3 year Compute Savings plan the cost goes down to $962.84 USD. Additionally, the data transfer costs can be about $1,356.80 USD per month for 15TB of outgoing traffic. | +| Reliability | Resiliency implementation | Withstand component failures | This solution uses AWS Application Load Balancer with RPC nodes for high availability. Newly provisioned Solana nodes triggered by Auto Scaling get up and running in about 30-50 minutes. | +| | Data backup | How is data backed up? | Considering blockchain data is replicated by nodes automatically and Solana nodes sync from start within an hour, we don't use any additional mechanisms to backup the data. | | | Resource monitoring | How are workload resources monitored? | Resources are being monitored using Amazon CloudWatch dashboards. Amazon CloudWatch custom metrics are being pushed via CloudWatch Agent. | -| Performance efficiency | Compute selection | How is compute solution selected? | Compute solution is selected based on best price-performance, i.e. AWS Graviton-based Amazon EC2 instances. | +| Performance efficiency | Compute selection | How is compute solution selected? | Compute solution is selected based on best price-performance, i.e. AWS AMD-based Amazon EC2 instances. | | | Storage selection | How is storage solution selected? | Storage solution is selected based on best price-performance, i.e. gp3 Amazon EBS volumes with optimal IOPS and throughput. | -| | Architecture selection | How is the best performance architecture selected? | s5cmd tool has been chosen for Amazon S3 uploads/downloads because it gives better price-performance compared to Amazon EBS snapshots (including Fast Snapshot Restore, which can be expensive). | -| Operational excellence | Workload health | How is health of workload determined? | Health of workload is determined via AWS Application Load Balancer Target Group Health Checks, on port 8545. | -| Sustainability | Hardware & services | Select most efficient hardware for your workload | This solution uses AWS Graviton-based Amazon EC2 instances which offer the best performance per watt of energy use in Amazon EC2. | \ No newline at end of file +| | Architecture selection | How is the best performance architecture selected? | We used a combination of recommendations from the Solana community and our own testing. | +| Operational excellence | Workload health | How is health of workload determined? | Health of workload is determined via AWS Application Load Balancer Target Group Health Checks, on port 8899. | +| Sustainability | Hardware & services | Select most efficient hardware for your workload | The solution uses AMD-powered instances. There is a potential to use AWS Graviton-based Amazon EC2 instances which offer the best performance per watt of energy use in Amazon EC2. | \ No newline at end of file diff --git a/lib/solana/doc/assets/image.png b/lib/solana/doc/assets/image.png new file mode 100644 index 0000000000000000000000000000000000000000..662cf82921ad27a2378903ef93b7f624116343ef GIT binary patch literal 367816 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

(_JMshr6F0Vdw>%MKj?(drQr)o7HO(dn} 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

;G@k{)z1Tv?#e8s#M?; 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 literal 0 HcmV?d00001 diff --git a/lib/solana/ha-nodes-deploy.json b/lib/solana/ha-nodes-deploy.json index fb70e87b..6e3bb9b7 100644 --- a/lib/solana/ha-nodes-deploy.json +++ b/lib/solana/ha-nodes-deploy.json @@ -1,5 +1,5 @@ { - "solana-ha-nodes-lightrpc": { - "alburl": "internal-solan-rpcno-1KV8RF4TNOORQ-203724879.us-east-2.elb.amazonaws.com" + "solana-ha-nodes-heavyrpc": { + "alburl": "internal-solan-rpcno-977ERI6F61ZW-1849543495.us-east-2.elb.amazonaws.com" } } diff --git a/lib/solana/lib/assets/solana/node-validator-template.sh b/lib/solana/lib/assets/solana/node-consensus-template.sh similarity index 100% rename from lib/solana/lib/assets/solana/node-validator-template.sh rename to lib/solana/lib/assets/solana/node-consensus-template.sh diff --git a/lib/solana/lib/assets/user-data/node.sh b/lib/solana/lib/assets/user-data/node.sh index c4c3ba09..e6cf6051 100644 --- a/lib/solana/lib/assets/user-data/node.sh +++ b/lib/solana/lib/assets/user-data/node.sh @@ -19,12 +19,9 @@ echo "AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN=${_AUTHORIZED_WITHDRAWER_ACCOUNT_ echo "REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN=${_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN_}" >> /etc/environment echo "SOLANA_CLUSTER=${_SOLANA_CLUSTER_}" >> /etc/environment echo "LIFECYCLE_HOOK_NAME=${_LIFECYCLE_HOOK_NAME_}" >> /etc/environment -echo "AUTOSCALING_GROUP_NAME=${_AUTOSCALING_GROUP_NAME_}" >> /etc/environment +echo "ASG_NAME=${_ASG_NAME_}" >> /etc/environment source /etc/environment -# Saving just in case for future use -arch=$(uname -m) - apt-get -yqq update apt-get -yqq install awscli jq unzip python3-pip apt install unzip @@ -243,7 +240,7 @@ else sudo mv ~/validator-keypair.json /home/solana/config/validator-keypair.json fi -if [[ "$SOLANA_NODE_TYPE" == "validator" ]]; then +if [[ "$SOLANA_NODE_TYPE" == "consensus" ]]; then if [[ $VOTE_ACCOUNT_SECRET_ARN == "none" ]]; then echo "Create Vote Account Secret" sudo ./solana-keygen new --no-passphrase -o /home/solana/config/vote-account-keypair.json @@ -286,7 +283,7 @@ if [[ "$SOLANA_NODE_TYPE" == "validator" ]]; then sudo mv ~/vote-account-keypair.json /home/solana/config/vote-account-keypair.json fi -mv /opt/solana/node-validator-template.sh /home/solana/bin/validator.sh +mv /opt/solana/node-consensus-template.sh /home/solana/bin/validator.sh fi if [[ "$SOLANA_NODE_TYPE" == "lightrpc" ]]; then @@ -353,9 +350,9 @@ sudo chmod +x /opt/syncchecker.sh (crontab -l; echo "*/1 * * * * /opt/syncchecker.sh >/tmp/syncchecker.log 2>&1") | crontab - crontab -l -# Signaling Autoscaling Gropup's lifecucle hook to complete +# Signaling Autoscaling Gropup's lifecycle hook to complete TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id) -aws autoscaling complete-lifecycle-action --lifecycle-action-result CONTINUE --instance-id $INSTANCE_ID --lifecycle-hook-name "$LIFECYCLE_HOOK_NAME" --auto-scaling-group-name "$AUTOSCALING_GROUP_NAME" --region $AWS_REGION +aws autoscaling complete-lifecycle-action --lifecycle-action-result CONTINUE --instance-id $INSTANCE_ID --lifecycle-hook-name "$LIFECYCLE_HOOK_NAME" --auto-scaling-group-name "$ASG_NAME" --region $AWS_REGION echo "All Done!!" \ No newline at end of file diff --git a/lib/solana/lib/config/solanaConfig.interface.ts b/lib/solana/lib/config/solanaConfig.interface.ts index 4c4fc72a..f8dd2e3f 100644 --- a/lib/solana/lib/config/solanaConfig.interface.ts +++ b/lib/solana/lib/config/solanaConfig.interface.ts @@ -1,7 +1,7 @@ import * as configTypes from "../../../constructs/config.interface"; export type SolanaCluster = "mainnet-beta" | "testnet" | "devnet"; -export type SolanaNodeConfiguration = "validator" | "lightrpc" | "heavyrpc"; +export type SolanaNodeConfiguration = "consensus" | "lightrpc" | "heavyrpc"; export interface SolanaDataVolumeConfig extends configTypes.DataVolumeConfig { } diff --git a/lib/solana/lib/ha-nodes-stack.ts b/lib/solana/lib/ha-nodes-stack.ts index acd2ba3c..8db993ea 100644 --- a/lib/solana/lib/ha-nodes-stack.ts +++ b/lib/solana/lib/ha-nodes-stack.ts @@ -75,8 +75,8 @@ export class SolanaHANodesStack extends cdk.Stack { throw new Error("ARM_64 is not yet supported"); } - if (nodeConfiguration === "validator") { - throw new Error("Validator node configuration is not yet supported for HA setup"); + if (nodeConfiguration === "consensus") { + throw new Error("Consensus node configuration is not yet supported for HA setup"); } // Use Ubuntu 20.04 LTS image for amd64. Find more: https://discourse.ubuntu.com/t/finding-ubuntu-images-with-the-aws-ssm-parameter-store/15507 @@ -105,7 +105,7 @@ export class SolanaHANodesStack extends cdk.Stack { _REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN_: constants.NoneValue, _SOLANA_CLUSTER_: solanaCluster, _LIFECYCLE_HOOK_NAME_: lifecycleHookName, - _AUTOSCALING_GROUP_NAME_: autoScalingGroupName, + _ASG_NAME_: autoScalingGroupName, }); // Setting up the nodse using generic High Availability (HA) Node constract diff --git a/lib/solana/lib/single-node-stack.ts b/lib/solana/lib/single-node-stack.ts index f1c507bf..e7685c8b 100644 --- a/lib/solana/lib/single-node-stack.ts +++ b/lib/solana/lib/single-node-stack.ts @@ -120,6 +120,7 @@ export class SolanaSingleNodeStack extends cdk.Stack { _REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN_: registrationTransactionFundingAccountSecretARN, _SOLANA_CLUSTER_: solanaCluster, _LIFECYCLE_HOOK_NAME_: constants.NoneValue, + _ASG_NAME_: constants.NoneValue, }); node.instance.addUserData(modifiedInitNodeScript); diff --git a/lib/solana/sample-configs/.env-sample-validator b/lib/solana/sample-configs/.env-sample-consensus similarity index 89% rename from lib/solana/sample-configs/.env-sample-validator rename to lib/solana/sample-configs/.env-sample-consensus index f35e4f7e..55a3656c 100644 --- a/lib/solana/sample-configs/.env-sample-validator +++ b/lib/solana/sample-configs/.env-sample-consensus @@ -8,7 +8,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" -SOLANA_NODE_CONFIGURATION="validator" # All options: "validator", "lightrpc", "heavyrpc" +SOLANA_NODE_CONFIGURATION="consensus" # All options: "consensus", "lightrpc", "heavyrpc" SOLANA_VERSION="1.16.2" # Current required version of Solana SOLANA_INSTANCE_TYPE="r6a.8xlarge" @@ -25,12 +25,12 @@ SOLANA_ACCOUNTS_VOL_IOPS="6000" # Max IOPS for EBS volumes (not ap SOLANA_ACCOUNTS_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") # Secrets configuration SOLANA_NODE_IDENTITY_SECRET_ARN="none" # Optional. The ARN of the secret in AWS Secrets Manager with the node identity key pair. In case you want to provision a node but keep the old identity. -SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. -SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. -SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for validator node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation +SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. +SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. +SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for consensus node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation ## HA nodes configuration ## SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="60" # Time enough to initialize the instance -SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="60" # Time sufficient enough for a node do sync +SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="10" # Time sufficient enough for a node do sync diff --git a/lib/solana/sample-configs/.env-sample-heavyrpc b/lib/solana/sample-configs/.env-sample-heavyrpc index 91af0fcf..1feb79b5 100644 --- a/lib/solana/sample-configs/.env-sample-heavyrpc +++ b/lib/solana/sample-configs/.env-sample-heavyrpc @@ -8,7 +8,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" -SOLANA_NODE_CONFIGURATION="heavyrpc" # All options: "validator", "lightrpc", "heavyrpc" +SOLANA_NODE_CONFIGURATION="heavyrpc" # All options: "consensus", "lightrpc", "heavyrpc" SOLANA_VERSION="1.16.2" # Current required version of Solana SOLANA_INSTANCE_TYPE="x2idn.16xlarge" @@ -25,12 +25,11 @@ SOLANA_ACCOUNTS_VOL_IOPS="0" # Max IOPS for EBS volumes (not ap SOLANA_ACCOUNTS_VOL_THROUGHPUT="0" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") # Secrets configuration SOLANA_NODE_IDENTITY_SECRET_ARN="none" # Optional. The ARN of the secret in AWS Secrets Manager with the node identity key pair. In case you want to provision a node but keep the old identity. -SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. -SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. -SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for validator node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation +SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. +SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. +SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for consensus node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation ## HA nodes configuration ## SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 -SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="80" # Time enough to initialize the instance -SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="80" # Time sufficient enough for a node do sync - +SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="70" # Time enough to initialize the instance +SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="10" # Time sufficient enough for a node do sync \ No newline at end of file diff --git a/lib/solana/sample-configs/.env-sample-lightrpc b/lib/solana/sample-configs/.env-sample-lightrpc index 2031bfa0..d9a6e71b 100644 --- a/lib/solana/sample-configs/.env-sample-lightrpc +++ b/lib/solana/sample-configs/.env-sample-lightrpc @@ -8,7 +8,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" -SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "validator", "lightrpc", "heavyrpc" +SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "consensus", "lightrpc", "heavyrpc" SOLANA_VERSION="1.16.2" # Current required version of Solana SOLANA_INSTANCE_TYPE="r6a.8xlarge" @@ -25,12 +25,12 @@ SOLANA_ACCOUNTS_VOL_IOPS="6000" # Max IOPS for EBS volumes (not ap SOLANA_ACCOUNTS_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") # Secrets configuration SOLANA_NODE_IDENTITY_SECRET_ARN="none" # Optional. The ARN of the secret in AWS Secrets Manager with the node identity key pair. In case you want to provision a node but keep the old identity. -SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. -SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for validator node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. -SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for validator node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation +SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. +SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. +SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for consensus node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation ## HA nodes configuration ## SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="60" # Time enough to initialize the instance -SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="60" # Time sufficient enough for a node do sync +SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="10" # Time sufficient enough for a node do sync diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 5f785047..db0f97fc 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -57,7 +57,7 @@ const config = { // Replace with your project's social card image: 'img/docusaurus-social-card.jpg', navbar: { - title: '🔰 Node Runners', + title: '❒-❒-❒ Node Runners', items: [ { type: 'doc', diff --git a/website/package.json b/website/package.json index bd50357d..a118195f 100644 --- a/website/package.json +++ b/website/package.json @@ -1,6 +1,6 @@ { - "name": "my-website", - "version": "0.0.0", + "name": "aws-blockchain-node-runners", + "version": "1.0.0", "private": true, "scripts": { "docusaurus": "docusaurus", From 9ddfc6b464cbbbccaa3747d92a3055c5bbb1c05a Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Fri, 6 Oct 2023 13:14:54 +1100 Subject: [PATCH 04/12] [WIP] Solana added tests --- lib/solana/lib/ha-nodes-stack.ts | 1 + lib/solana/test/.env-test | 53 +++-- lib/solana/test/common-stack.test.ts | 62 ++---- ...s-stack.test.ts => ha-nodes-stack.test.ts} | 204 ++++++++---------- lib/solana/test/single-node-stack.test.ts | 144 +++++++++++++ lib/solana/test/sync-node-stack.test.ts | 161 -------------- 6 files changed, 282 insertions(+), 343 deletions(-) rename lib/solana/test/{rpc-nodes-stack.test.ts => ha-nodes-stack.test.ts} (54%) create mode 100644 lib/solana/test/single-node-stack.test.ts delete mode 100644 lib/solana/test/sync-node-stack.test.ts diff --git a/lib/solana/lib/ha-nodes-stack.ts b/lib/solana/lib/ha-nodes-stack.ts index 8db993ea..265bcd17 100644 --- a/lib/solana/lib/ha-nodes-stack.ts +++ b/lib/solana/lib/ha-nodes-stack.ts @@ -113,6 +113,7 @@ export class SolanaHANodesStack extends cdk.Stack { const rpcNodes = new HANodesConstruct (this, "rpc-nodes", { instanceType, dataVolumes: [dataVolume, accountsVolume], + rootDataVolumeDeviceName: "/dev/sda1", machineImage: ec2.MachineImage.fromSsmParameter(ubuntu204stableImageSsmName), role: instanceRole, vpc, diff --git a/lib/solana/test/.env-test b/lib/solana/test/.env-test index 1e775251..4d888e5e 100644 --- a/lib/solana/test/.env-test +++ b/lib/solana/test/.env-test @@ -1,29 +1,36 @@ -############################################################## -# Example configuration for Ethereum nodes runner app on AWS # -############################################################## +############################################################# +# Example configuration for Solana nodes runner app on AWS # +############################################################# -# Set the AWS account is and region for your environment +## Set the AWS account is and region for your environment ## AWS_ACCOUNT_ID="1234567890" AWS_REGION="us-east-2" -# Common configuration parameters -CLIENT_COMBINATION="geth-lighthouse-mainnet" # All options: "besu-teku-mainnet" | "geth-lighthouse-mainnet" | "erigon-lighthouse-mainnet" | "erigon-prysm-mainnet" | "nethermind-teku-mainnet" +## Common configuration parameters ## +SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" +SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "consensus", "lightrpc", "heavyrpc" +SOLANA_VERSION="1.16.2" # Current required version of Solana -# Sync node configuration -ETH_SYNC_INSTANCE_TYPE="m6g.2xlarge" -ETH_SYNC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used -ETH_SYNC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 -ETH_SYNC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families -ETH_SYNC_DATA_VOL_IOPS="6000" # Max IOPS for EBS volumes (not applicable for "instance-store") -ETH_SYNC_DATA_VOL_THROUGHPUT="400" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +SOLANA_INSTANCE_TYPE="r6a.8xlarge" +SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used +# Data volume configuration +SOLANA_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +SOLANA_DATA_VOL_SIZE="2000" # Current required data size to keep both smapshot archive and unarchived version of it +SOLANA_DATA_VOL_IOPS="12000" # Max IOPS for EBS volumes (not applicable for "instance-store") +SOLANA_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +# Accounts volume configuration +SOLANA_ACCOUNTS_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families +SOLANA_ACCOUNTS_VOL_SIZE="500" # Current required data size to keep both smapshot archive and unarchived version of it +SOLANA_ACCOUNTS_VOL_IOPS="6000" # Max IOPS for EBS volumes (not applicable for "instance-store") +SOLANA_ACCOUNTS_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") +# Secrets configuration +SOLANA_NODE_IDENTITY_SECRET_ARN="none" # Optional. The ARN of the secret in AWS Secrets Manager with the node identity key pair. In case you want to provision a node but keep the old identity. +SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. +SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. +SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for consensus node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation + +## HA nodes configuration ## +SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 +SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="60" # Time enough to initialize the instance +SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="10" # Time sufficient enough for a node do sync -# RPC nodes configuration -ETH_RPC_INSTANCE_TYPE="m7g.2xlarge" -ETH_RPC_CPU_TYPE="ARM_64" # IMPORTANT: Make sure the CPU type matches the instance type used -ETH_RPC_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 -ETH_RPC_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="10" # Time enough to initialize the instance and start downloading snpashots -ETH_RPC_HA_NODES_HEARTBEAT_DELAY_MIN="60" # Time sufficient enough for a node do download snapshot, from S3 bucket, start clients, and finish sycning the delta -ETH_RPC_DATA_VOL_SIZE="3072" # Minimum values in Gibibytes: nethermind-teku: 2048, geth-lighthouse: 2048, besu-teku: 2048, erigon-lighthouse: 3072 -ETH_RPC_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families -ETH_RPC_DATA_VOL_IOPS="8000" # Max IOPS for EBS volumes (not applicable for "instance-store") -ETH_RPC_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") diff --git a/lib/solana/test/common-stack.test.ts b/lib/solana/test/common-stack.test.ts index 8f10e9a7..b20f4459 100644 --- a/lib/solana/test/common-stack.test.ts +++ b/lib/solana/test/common-stack.test.ts @@ -3,58 +3,20 @@ import * as cdk from "aws-cdk-lib"; import * as dotenv from 'dotenv'; dotenv.config({ path: './test/.env-test' }); import * as config from "../lib/config/solanaConfig"; -import { EthCommonStack } from "../lib/common-stack"; +import { SolanaCommonStack } from "../lib/common-stack"; -describe("EthCommonStack", () => { +describe("SolanaCommonStack", () => { test("synthesizes the way we expect", () => { const app = new cdk.App(); - // Create the EthCommonStack. - const ethCommonStack = new EthCommonStack(app, "eth-common", { + // Create the SolanaCommonStack. + const solanaCommonStack = new SolanaCommonStack(app, "solana-common", { env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, - stackName: `eth-nodes-common`, + stackName: `solana-nodes-common`, }); // Prepare the stack for assertions. - const template = Template.fromStack(ethCommonStack); - - // Has Snapshot S3 bucket. - template.hasResourceProperties("AWS::S3::Bucket", { - BucketName: Match.stringLikeRegexp("eth-snapshots*"), - AccessControl: "Private", - BucketEncryption: { - ServerSideEncryptionConfiguration: [ - { - ServerSideEncryptionByDefault: { - SSEAlgorithm: "AES256" - } - } - ] - }, - PublicAccessBlockConfiguration: { - BlockPublicAcls: true, - BlockPublicPolicy: true, - IgnorePublicAcls: true, - RestrictPublicBuckets: true - } - }); - // Has VPC endpoint for S3. - template.hasResourceProperties("AWS::EC2::VPCEndpoint", { - ServiceName: { - "Fn::Join": [ - "", - [ - "com.amazonaws.", - { - "Ref": "AWS::Region" - }, - ".s3" - ] - ] - }, - VpcEndpointType: "Gateway", - VpcId: Match.stringLikeRegexp("vpc-*") - }); + const template = Template.fromStack(solanaCommonStack); // Has EC2 instance role. template.hasResourceProperties("AWS::IAM::Role", { @@ -70,6 +32,18 @@ describe("EthCommonStack", () => { ] }, ManagedPolicyArns: [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/SecretsManagerReadWrite" + ] + ] + }, { "Fn::Join": [ "", diff --git a/lib/solana/test/rpc-nodes-stack.test.ts b/lib/solana/test/ha-nodes-stack.test.ts similarity index 54% rename from lib/solana/test/rpc-nodes-stack.test.ts rename to lib/solana/test/ha-nodes-stack.test.ts index fa7e6fea..c835a5f5 100644 --- a/lib/solana/test/rpc-nodes-stack.test.ts +++ b/lib/solana/test/ha-nodes-stack.test.ts @@ -3,129 +3,91 @@ import * as cdk from "aws-cdk-lib"; import * as dotenv from 'dotenv'; dotenv.config({ path: './test/.env-test' }); import * as config from "../lib/config/solanaConfig"; -import { EthRpcNodesStack } from "../lib/ha-nodes-stack"; +import { SolanaHANodesStack } from "../lib/ha-nodes-stack"; -describe("EthRpcNodesStack", () => { +describe("SolanaHANodesStack", () => { test("synthesizes the way we expect", () => { const app = new cdk.App(); - // Create the EthRpcNodesStack. - const ethRpcNodesStack = new EthRpcNodesStack(app, "eth-sync-node", { - stackName: `eth-rpc-nodes-${config.baseConfig.clientCombination}`, + // Create the SolanaHANodesStack. + const solanaHANodesStack = new SolanaHANodesStack(app, "solana-sync-node", { + stackName: `solana-ha-nodes-${config.baseNodeConfig.nodeConfiguration}`, + env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, - env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, - PolygonClientCombination: config.baseConfig.clientCombination, - instanceType: config.rpcNodeConfig.instanceType, - instanceCpuType: config.rpcNodeConfig.instanceCpuType, - numberOfNodes: config.rpcNodeConfig.numberOfNodes, - albHealthCheckGracePeriodMin: config.rpcNodeConfig.albHealthCheckGracePeriodMin, - heartBeatDelayMin: config.rpcNodeConfig.heartBeatDelayMin, - dataVolumes: config.syncNodeConfig.dataVolumes, + instanceType: config.baseNodeConfig.instanceType, + instanceCpuType: config.baseNodeConfig.instanceCpuType, + solanaCluster: config.baseNodeConfig.solanaCluster, + solanaVersion: config.baseNodeConfig.solanaVersion, + nodeConfiguration: config.baseNodeConfig.nodeConfiguration, + dataVolume: config.baseNodeConfig.dataVolume, + accountsVolume: config.baseNodeConfig.accountsVolume, + + albHealthCheckGracePeriodMin: config.haNodeConfig.albHealthCheckGracePeriodMin, + heartBeatDelayMin: config.haNodeConfig.heartBeatDelayMin, + numberOfNodes: config.haNodeConfig.numberOfNodes, }); // Prepare the stack for assertions. - const template = Template.fromStack(ethRpcNodesStack); + const template = Template.fromStack(solanaHANodesStack); // Has EC2 instance security group. template.hasResourceProperties("AWS::EC2::SecurityGroup", { GroupDescription: Match.anyValue(), VpcId: Match.anyValue(), SecurityGroupEgress: [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound traffic by default", - "IpProtocol": "-1" - } - ], - SecurityGroupIngress: [ { "CidrIp": "0.0.0.0/0", - "Description": "P2P", - "FromPort": 30303, - "IpProtocol": "tcp", - "ToPort": 30303 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "P2P", - "FromPort": 30303, - "IpProtocol": "udp", - "ToPort": 30303 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "P2P", - "FromPort": 30304, - "IpProtocol": "tcp", - "ToPort": 30304 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "P2P", - "FromPort": 30304, - "IpProtocol": "udp", - "ToPort": 30304 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "CL Client P2P", - "FromPort": 9000, - "IpProtocol": "tcp", - "ToPort": 9000 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "CL Client P2P", - "FromPort": 9000, - "IpProtocol": "udp", - "ToPort": 9000 - }, - { - "CidrIp": "1.2.3.4/5", - "Description": "CL Client API", - "FromPort": 5051, - "IpProtocol": "tcp", - "ToPort": 5051 - }, - { - "CidrIp": "1.2.3.4/5", - "Description": "CL Client API", - "FromPort": 5052, - "IpProtocol": "tcp", - "ToPort": 5052 - }, - { - "CidrIp": "1.2.3.4/5", - "Description": "EL Client RPC (Auth)", - "FromPort": 8551, - "IpProtocol": "tcp", - "ToPort": 8551 - }, - { - "CidrIp": "1.2.3.4/5", - "Description": "EL Client RPC", - "FromPort": 8545, - "IpProtocol": "tcp", - "ToPort": 8545 - }, - { - "Description": Match.anyValue(), - "FromPort": 0, - "IpProtocol": "tcp", - "SourceSecurityGroupId": Match.anyValue(), - "ToPort": 65535 + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" } + ], + SecurityGroupIngress: [ + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P protocols (gossip, turbine, repair, etc)", + "FromPort": 8801, + "IpProtocol": "tcp", + "ToPort": 8812 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P protocols (gossip, turbine, repair, etc)", + "FromPort": 8801, + "IpProtocol": "udp", + "ToPort": 8812 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "RPC port HTTP (user access needs to be restricted. Allowed access only from internal IPs)", + "FromPort": 8899, + "IpProtocol": "tcp", + "ToPort": 8899 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "RPC port WebSocket (user access needs to be restricted. Allowed access only from internal IPs)", + "FromPort": 8900, + "IpProtocol": "tcp", + "ToPort": 8900 + }, + { + "Description": "Allow access from ALB to Blockchain Node", + "FromPort": 0, + "IpProtocol": "tcp", + "SourceSecurityGroupId": Match.anyValue(), + "ToPort": 65535 + }, ] }) // Has security group from ALB to EC2. template.hasResourceProperties("AWS::EC2::SecurityGroupIngress", { Description: Match.anyValue(), - FromPort: 8545, + FromPort: 8899, GroupId: Match.anyValue(), IpProtocol: "tcp", SourceSecurityGroupId: Match.anyValue(), - ToPort: 8545, + ToPort: 8899, }) // Has launch template profile for EC2 instances. @@ -138,7 +100,7 @@ describe("EthRpcNodesStack", () => { LaunchTemplateData: { BlockDeviceMappings: [ { - "DeviceName": "/dev/xvda", + "DeviceName": "/dev/sda1", "Ebs": { "DeleteOnTermination": true, "Encrypted": true, @@ -150,34 +112,46 @@ describe("EthRpcNodesStack", () => { }, { "DeviceName": "/dev/sdf", + "Ebs": { + "DeleteOnTermination": true, + "Encrypted": true, + "Iops": 12000, + "Throughput": 700, + "VolumeSize": 2000, + "VolumeType": "gp3" + } + }, + { + "DeviceName": "/dev/sdg", "Ebs": { "DeleteOnTermination": true, "Encrypted": true, "Iops": 6000, - "Throughput": 400, - "VolumeSize": 3072, + "Throughput": 700, + "VolumeSize": 500, "VolumeType": "gp3" } - } + }, ], EbsOptimized: true, IamInstanceProfile: Match.anyValue(), ImageId: Match.anyValue(), - InstanceType:"m7g.2xlarge", + InstanceType:"r6a.8xlarge", SecurityGroupIds: [Match.anyValue()], - UserData: Match.anyValue() + UserData: Match.anyValue(), + TagSpecifications: Match.anyValue(), } }) // Has Auto Scaling Group. template.hasResourceProperties("AWS::AutoScaling::AutoScalingGroup", { - AutoScalingGroupName: `eth-rpc-nodes-${config.baseConfig.clientCombination}`, - HealthCheckGracePeriod: config.rpcNodeConfig.albHealthCheckGracePeriodMin * 60, + AutoScalingGroupName: `solana-ha-nodes-${config.baseNodeConfig.nodeConfiguration}`, + HealthCheckGracePeriod: config.haNodeConfig.albHealthCheckGracePeriodMin * 60, HealthCheckType: "ELB", DefaultInstanceWarmup: 60, MinSize: "0", MaxSize: "4", - DesiredCapacity: config.rpcNodeConfig.numberOfNodes.toString(), + DesiredCapacity: config.haNodeConfig.numberOfNodes.toString(), VPCZoneIdentifier: Match.anyValue(), TargetGroupARNs: Match.anyValue(), }); @@ -185,8 +159,8 @@ describe("EthRpcNodesStack", () => { // Has Auto Scaling Lifecycle Hook. template.hasResourceProperties("AWS::AutoScaling::LifecycleHook", { DefaultResult: "ABANDON", - HeartbeatTimeout: config.rpcNodeConfig.heartBeatDelayMin * 60, - LifecycleHookName: `eth-rpc-nodes-${config.baseConfig.clientCombination}`, + HeartbeatTimeout: config.haNodeConfig.heartBeatDelayMin * 60, + LifecycleHookName: `solana-ha-nodes-${config.baseNodeConfig.nodeConfiguration}`, LifecycleTransition: "autoscaling:EC2_INSTANCE_LAUNCHING", }); @@ -204,9 +178,9 @@ describe("EthRpcNodesStack", () => { { "CidrIp": "1.2.3.4/5", "Description": "Blockchain Node RPC", - "FromPort": 8545, + "FromPort": 8899, "IpProtocol": "tcp", - "ToPort": 8545 + "ToPort": 8899 } ], VpcId: Match.anyValue(), @@ -229,7 +203,7 @@ describe("EthRpcNodesStack", () => { }, { Key: "access_logs.s3.prefix", - Value: `eth-rpc-nodes-${config.baseConfig.clientCombination}` + Value: `solana-ha-nodes-${config.baseNodeConfig.nodeConfiguration}` } ], Scheme: "internal", @@ -252,7 +226,7 @@ describe("EthRpcNodesStack", () => { } ], LoadBalancerArn: Match.anyValue(), - Port: 8545, + Port: 8899, Protocol: "HTTP" }) @@ -260,13 +234,13 @@ describe("EthRpcNodesStack", () => { template.hasResourceProperties("AWS::ElasticLoadBalancingV2::TargetGroup", { HealthCheckEnabled: true, HealthCheckIntervalSeconds: 30, - HealthCheckPath: "/", - HealthCheckPort: "8545", + HealthCheckPath: "/health", + HealthCheckPort: "8899", HealthyThresholdCount: 3, Matcher: { HttpCode: "200-299" }, - Port: 8545, + Port: 8899, Protocol: "HTTP", TargetGroupAttributes: [ { diff --git a/lib/solana/test/single-node-stack.test.ts b/lib/solana/test/single-node-stack.test.ts new file mode 100644 index 00000000..89fd9663 --- /dev/null +++ b/lib/solana/test/single-node-stack.test.ts @@ -0,0 +1,144 @@ +import { Match, Template } from "aws-cdk-lib/assertions"; +import * as cdk from "aws-cdk-lib"; +import * as dotenv from 'dotenv'; +dotenv.config({ path: './test/.env-test' }); +import * as config from "../lib/config/solanaConfig"; +import { SolanaSingleNodeStack } from "../lib/single-node-stack"; + +describe("SolanaSingleNodeStack", () => { + test("synthesizes the way we expect", () => { + const app = new cdk.App(); + + // Create the SolanaSingleNodeStack. + const solanaSingleNodeStack = new SolanaSingleNodeStack(app, "solana-sync-node", { + stackName: `solana-single-node-${config.baseNodeConfig.nodeConfiguration}`, + env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, + + instanceType: config.baseNodeConfig.instanceType, + instanceCpuType: config.baseNodeConfig.instanceCpuType, + solanaCluster: config.baseNodeConfig.solanaCluster, + solanaVersion: config.baseNodeConfig.solanaVersion, + nodeConfiguration: config.baseNodeConfig.nodeConfiguration, + dataVolume: config.baseNodeConfig.dataVolume, + accountsVolume: config.baseNodeConfig.accountsVolume, + solanaNodeIdentitySecretARN: config.baseNodeConfig.solanaNodeIdentitySecretARN, + voteAccountSecretARN: config.baseNodeConfig.voteAccountSecretARN, + authorizedWithdrawerAccountSecretARN: config.baseNodeConfig.authorizedWithdrawerAccountSecretARN, + registrationTransactionFundingAccountSecretARN: config.baseNodeConfig.registrationTransactionFundingAccountSecretARN, + }); + + // Prepare the stack for assertions. + const template = Template.fromStack(solanaSingleNodeStack); + + // Has EC2 instance security group. + template.hasResourceProperties("AWS::EC2::SecurityGroup", { + GroupDescription: Match.anyValue(), + VpcId: Match.anyValue(), + SecurityGroupEgress: [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + SecurityGroupIngress: [ + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P protocols (gossip, turbine, repair, etc)", + "FromPort": 8801, + "IpProtocol": "tcp", + "ToPort": 8812 + }, + { + "CidrIp": "0.0.0.0/0", + "Description": "P2P protocols (gossip, turbine, repair, etc)", + "FromPort": 8801, + "IpProtocol": "udp", + "ToPort": 8812 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "RPC port HTTP (user access needs to be restricted. Allowed access only from internal IPs)", + "FromPort": 8899, + "IpProtocol": "tcp", + "ToPort": 8899 + }, + { + "CidrIp": "1.2.3.4/5", + "Description": "RPC port WebSocket (user access needs to be restricted. Allowed access only from internal IPs)", + "FromPort": 8900, + "IpProtocol": "tcp", + "ToPort": 8900 + } + ] + }) + + // Has EC2 instance with node configuration + template.hasResourceProperties("AWS::EC2::Instance", { + AvailabilityZone: Match.anyValue(), + UserData: Match.anyValue(), + BlockDeviceMappings: [ + { + DeviceName: "/dev/sda1", + Ebs: { + DeleteOnTermination: true, + Encrypted: true, + Iops: 3000, + VolumeSize: 46, + VolumeType: "gp3" + } + } + ], + IamInstanceProfile: Match.anyValue(), + ImageId: Match.anyValue(), + InstanceType: "r6a.8xlarge", + Monitoring: true, + PropagateTagsToVolumeOnCreation: true, + SecurityGroupIds: Match.anyValue(), + SubnetId: Match.anyValue(), + }) + + // Has EBS data volume. + template.hasResourceProperties("AWS::EC2::Volume", { + AvailabilityZone: Match.anyValue(), + Encrypted: true, + Iops: 12000, + MultiAttachEnabled: false, + Size: 2000, + Throughput: 700, + VolumeType: "gp3" + }) + + // Has EBS data volume attachment. + template.hasResourceProperties("AWS::EC2::VolumeAttachment", { + Device: "/dev/sdf", + InstanceId: Match.anyValue(), + VolumeId: Match.anyValue(), + }) + + // Has EBS accounts volume. + template.hasResourceProperties("AWS::EC2::Volume", { + AvailabilityZone: Match.anyValue(), + Encrypted: true, + Iops: 6000, + MultiAttachEnabled: false, + Size: 500, + Throughput: 700, + VolumeType: "gp3" + }) + + // Has EBS accounts volume attachment. + template.hasResourceProperties("AWS::EC2::VolumeAttachment", { + Device: "/dev/sdg", + InstanceId: Match.anyValue(), + VolumeId: Match.anyValue(), + }) + + // Has CloudWatch dashboard. + template.hasResourceProperties("AWS::CloudWatch::Dashboard", { + DashboardBody: Match.anyValue(), + DashboardName: `solana-single-node-${config.baseNodeConfig.nodeConfiguration}` + }) + + }); +}); \ No newline at end of file diff --git a/lib/solana/test/sync-node-stack.test.ts b/lib/solana/test/sync-node-stack.test.ts deleted file mode 100644 index dcb8bbf0..00000000 --- a/lib/solana/test/sync-node-stack.test.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { Match, Template } from "aws-cdk-lib/assertions"; -import * as cdk from "aws-cdk-lib"; -import * as dotenv from 'dotenv'; -dotenv.config({ path: './test/.env-test' }); -import * as config from "../lib/config/solanaConfig"; -import { EthSyncNodeStack } from "../lib/single-node-stack"; - -describe("EthSyncNodeStack", () => { - test("synthesizes the way we expect", () => { - const app = new cdk.App(); - - // Create the EthSyncNodeStack. - const ethSyncNodeStack = new EthSyncNodeStack(app, "eth-sync-node", { - stackName: `eth-sync-node-${config.baseConfig.clientCombination}`, - - env: { account: config.baseConfig.accountId, region: config.baseConfig.region }, - PolygonClientCombination: config.baseConfig.clientCombination, - instanceType: config.syncNodeConfig.instanceType, - instanceCpuType: config.syncNodeConfig.instanceCpuType, - dataVolumes: config.syncNodeConfig.dataVolumes, - }); - - // Prepare the stack for assertions. - const template = Template.fromStack(ethSyncNodeStack); - - // Has EC2 instance security group. - template.hasResourceProperties("AWS::EC2::SecurityGroup", { - GroupDescription: Match.anyValue(), - VpcId: Match.anyValue(), - SecurityGroupEgress: [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound traffic by default", - "IpProtocol": "-1" - } - ], - SecurityGroupIngress: [ - { - "CidrIp": "0.0.0.0/0", - "Description": "P2P", - "FromPort": 30303, - "IpProtocol": "tcp", - "ToPort": 30303 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "P2P", - "FromPort": 30303, - "IpProtocol": "udp", - "ToPort": 30303 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "P2P", - "FromPort": 30304, - "IpProtocol": "tcp", - "ToPort": 30304 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "P2P", - "FromPort": 30304, - "IpProtocol": "udp", - "ToPort": 30304 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "CL Client P2P", - "FromPort": 9000, - "IpProtocol": "tcp", - "ToPort": 9000 - }, - { - "CidrIp": "0.0.0.0/0", - "Description": "CL Client P2P", - "FromPort": 9000, - "IpProtocol": "udp", - "ToPort": 9000 - }, - { - "CidrIp": "1.2.3.4/5", - "Description": "CL Client API", - "FromPort": 5051, - "IpProtocol": "tcp", - "ToPort": 5051 - }, - { - "CidrIp": "1.2.3.4/5", - "Description": "CL Client API", - "FromPort": 5052, - "IpProtocol": "tcp", - "ToPort": 5052 - }, - { - "CidrIp": "1.2.3.4/5", - "Description": "EL Client RPC (Auth)", - "FromPort": 8551, - "IpProtocol": "tcp", - "ToPort": 8551 - }, - { - "CidrIp": "1.2.3.4/5", - "Description": "EL Client RPC", - "FromPort": 8545, - "IpProtocol": "tcp", - "ToPort": 8545 - } - ] - }) - - // Has EC2 instance with node configuration - template.hasResourceProperties("AWS::EC2::Instance", { - AvailabilityZone: Match.anyValue(), - UserData: Match.anyValue(), - BlockDeviceMappings: [ - { - DeviceName: "/dev/xvda", - Ebs: { - DeleteOnTermination: true, - Encrypted: true, - Iops: 3000, - VolumeSize: 46, - VolumeType: "gp3" - } - } - ], - IamInstanceProfile: Match.anyValue(), - ImageId: Match.anyValue(), - InstanceType: "m6g.2xlarge", - Monitoring: true, - PropagateTagsToVolumeOnCreation: true, - SecurityGroupIds: Match.anyValue(), - SubnetId: Match.anyValue(), - }) - - // Has EBS data volume. - template.hasResourceProperties("AWS::EC2::Volume", { - AvailabilityZone: Match.anyValue(), - Encrypted: true, - Iops: 6000, - MultiAttachEnabled: false, - Size: 3072, - Throughput: 400, - VolumeType: "gp3" - }) - - // Has EBS data volume attachment. - template.hasResourceProperties("AWS::EC2::VolumeAttachment", { - Device: "/dev/sdf", - InstanceId: Match.anyValue(), - VolumeId: Match.anyValue(), - }) - - // Has CloudWatch dashboard. - template.hasResourceProperties("AWS::CloudWatch::Dashboard", { - DashboardBody: Match.anyValue(), - DashboardName: `eth-sync-node-${config.baseConfig.clientCombination}` - }) - - }); -}); \ No newline at end of file From 48d26c85f8e0d5082d1eee284e770a5cc8679222 Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Fri, 6 Oct 2023 18:04:25 +1100 Subject: [PATCH 05/12] [WIP] Solana minor bug fixes --- .gitignore | 2 ++ lib/solana/.env-sample | 36 ------------------- lib/solana/README.md | 2 +- lib/solana/ha-nodes-deploy.json | 5 --- lib/solana/lib/assets/user-data/node.sh | 6 +--- lib/solana/lib/config/solanaConfig.ts | 2 +- .../sample-configs/.env-sample-consensus | 2 +- .../sample-configs/.env-sample-heavyrpc | 2 +- .../sample-configs/.env-sample-lightrpc | 2 +- lib/solana/single-node-deploy.json | 5 --- lib/solana/test/.env-test | 2 +- 11 files changed, 9 insertions(+), 57 deletions(-) delete mode 100644 lib/solana/.env-sample delete mode 100644 lib/solana/ha-nodes-deploy.json delete mode 100644 lib/solana/single-node-deploy.json diff --git a/.gitignore b/.gitignore index c0b9e18b..789a258e 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,8 @@ data-volume-snpashot*.json sync-node-deploy*.json instance-image*.json rpc-node-deploy*.json +single-node-deploy*.json +hs-node-deploy*.json *.OLD .env \ No newline at end of file diff --git a/lib/solana/.env-sample b/lib/solana/.env-sample deleted file mode 100644 index d9a6e71b..00000000 --- a/lib/solana/.env-sample +++ /dev/null @@ -1,36 +0,0 @@ -############################################################# -# Example configuration for Solana nodes runner app on AWS # -############################################################# - -## Set the AWS account is and region for your environment ## -AWS_ACCOUNT_ID="xxxxxxxxxxx" -AWS_REGION="us-east-2" - -## Common configuration parameters ## -SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" -SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "consensus", "lightrpc", "heavyrpc" -SOLANA_VERSION="1.16.2" # Current required version of Solana - -SOLANA_INSTANCE_TYPE="r6a.8xlarge" -SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used -# Data volume configuration -SOLANA_DATA_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families -SOLANA_DATA_VOL_SIZE="2000" # Current required data size to keep both smapshot archive and unarchived version of it -SOLANA_DATA_VOL_IOPS="12000" # Max IOPS for EBS volumes (not applicable for "instance-store") -SOLANA_DATA_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") -# Accounts volume configuration -SOLANA_ACCOUNTS_VOL_TYPE="gp3" # Other options: "io1" | "io2" | "gp3" | "instance-store" . IMPORTANT: Use "instance-store" option only with instance types that support that feature, like popular for node im4gn, d3, i3en, and i4i instance families -SOLANA_ACCOUNTS_VOL_SIZE="500" # Current required data size to keep both smapshot archive and unarchived version of it -SOLANA_ACCOUNTS_VOL_IOPS="6000" # Max IOPS for EBS volumes (not applicable for "instance-store") -SOLANA_ACCOUNTS_VOL_THROUGHPUT="700" # Max throughput for EBS gp3 volumes (not applicable for "io1" | "io2" | "instance-store") -# Secrets configuration -SOLANA_NODE_IDENTITY_SECRET_ARN="none" # Optional. The ARN of the secret in AWS Secrets Manager with the node identity key pair. In case you want to provision a node but keep the old identity. -SOLANA_VOTE_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. ARN of the secret in AWS Secrets Manager with the Vote Account's key pair. -SOLANA_AUTHORIZED_WITHDRAWER_ACCOUNT_SECRET_ARN="none" # Optional for consensus node type. The ARN of the secret in AWS Secrets Manager with the Authorized Withdrawer Account's key pair. -SOLANA_REGISTRATION_TRANSACTION_FUNDING_ACCOUNT_SECRET_ARN="none" # Required for consensus node type. The ARN of the secret in AWS Secrets Manager with Registration Transaction Funding Account's key pair. Needs to have sufficient SOL to pay for on-chain validator creation - -## HA nodes configuration ## -SOLANA_HA_NUMBER_OF_NODES="2" # Total number of RPC nodes to be provisioned. Default: 2 -SOLANA_HA_ALB_HEALTHCHECK_GRACE_PERIOD_MIN="60" # Time enough to initialize the instance -SOLANA_HA_NODES_HEARTBEAT_DELAY_MIN="10" # Time sufficient enough for a node do sync - diff --git a/lib/solana/README.md b/lib/solana/README.md index b3af0ba2..dc01c1a0 100644 --- a/lib/solana/README.md +++ b/lib/solana/README.md @@ -121,7 +121,7 @@ Create your own copy of `.env` file and edit it: The result should be like this (the actual balance might change): ```javascript - {"jsonrpc":"2.0","result":{"context":{"apiVersion":"1.16.2","slot":221433176},"value":12870473061872488},"id":1} + {"jsonrpc":"2.0","result":{"context":{"apiVersion":"1.16.15","slot":221433176},"value":12870473061872488},"id":1} ``` If the nodes are still starting and catching up with the chain, you will see the following response: diff --git a/lib/solana/ha-nodes-deploy.json b/lib/solana/ha-nodes-deploy.json deleted file mode 100644 index 6e3bb9b7..00000000 --- a/lib/solana/ha-nodes-deploy.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "solana-ha-nodes-heavyrpc": { - "alburl": "internal-solan-rpcno-977ERI6F61ZW-1849543495.us-east-2.elb.amazonaws.com" - } -} diff --git a/lib/solana/lib/assets/user-data/node.sh b/lib/solana/lib/assets/user-data/node.sh index e6cf6051..64eea980 100644 --- a/lib/solana/lib/assets/user-data/node.sh +++ b/lib/solana/lib/assets/user-data/node.sh @@ -1,7 +1,6 @@ #!/bin/bash set +e -# Set by generic single-node and ha-node CDK components echo "AWS_REGION=${_AWS_REGION_}" >> /etc/environment echo "ASSETS_S3_PATH=${_ASSETS_S3_PATH_}" >> /etc/environment echo "STACK_NAME=${_STACK_NAME_}" >> /etc/environment @@ -71,7 +70,6 @@ case $SOLANA_CLUSTER in esac echo "Fine tune sysctl to prepare the system for Solana" - sudo bash -c "cat >/etc/sysctl.d/20-solana-additionals.conf </tmp/syncchecker.log 2>&1") | crontab - crontab -l -# Signaling Autoscaling Gropup's lifecycle hook to complete +echo "Signaling ASG lifecycle hook to complete" TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id) aws autoscaling complete-lifecycle-action --lifecycle-action-result CONTINUE --instance-id $INSTANCE_ID --lifecycle-hook-name "$LIFECYCLE_HOOK_NAME" --auto-scaling-group-name "$ASG_NAME" --region $AWS_REGION diff --git a/lib/solana/lib/config/solanaConfig.ts b/lib/solana/lib/config/solanaConfig.ts index dbf10455..59cbd96d 100644 --- a/lib/solana/lib/config/solanaConfig.ts +++ b/lib/solana/lib/config/solanaConfig.ts @@ -27,7 +27,7 @@ export const baseNodeConfig: configTypes.SolanaBaseNodeConfig = { instanceType: new ec2.InstanceType(process.env.SOLANA_INSTANCE_TYPE ? process.env.SOLANA_INSTANCE_TYPE : "r6a.8xlarge"), instanceCpuType: process.env.SOLANA_CPU_TYPE?.toLowerCase() == "x86_64" ? ec2.AmazonLinuxCpuType.X86_64 : ec2.AmazonLinuxCpuType.ARM_64, solanaCluster: process.env.SOLANA_CLUSTER || "mainnet-beta", - solanaVersion: process.env.SOLANA_VERSION || "1.16.2", + solanaVersion: process.env.SOLANA_VERSION || "1.16.15", nodeConfiguration: process.env.SOLANA_NODE_CONFIGURATION || "lightrpc", dataVolume: { sizeGiB: process.env.SOLANA_DATA_VOL_SIZE ? parseInt(process.env.SOLANA_DATA_VOL_SIZE): 2000, diff --git a/lib/solana/sample-configs/.env-sample-consensus b/lib/solana/sample-configs/.env-sample-consensus index 55a3656c..1d891e85 100644 --- a/lib/solana/sample-configs/.env-sample-consensus +++ b/lib/solana/sample-configs/.env-sample-consensus @@ -9,7 +9,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" SOLANA_NODE_CONFIGURATION="consensus" # All options: "consensus", "lightrpc", "heavyrpc" -SOLANA_VERSION="1.16.2" # Current required version of Solana +SOLANA_VERSION="1.16.15" # Current required version of Solana SOLANA_INSTANCE_TYPE="r6a.8xlarge" SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used diff --git a/lib/solana/sample-configs/.env-sample-heavyrpc b/lib/solana/sample-configs/.env-sample-heavyrpc index 1feb79b5..0cd83615 100644 --- a/lib/solana/sample-configs/.env-sample-heavyrpc +++ b/lib/solana/sample-configs/.env-sample-heavyrpc @@ -9,7 +9,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" SOLANA_NODE_CONFIGURATION="heavyrpc" # All options: "consensus", "lightrpc", "heavyrpc" -SOLANA_VERSION="1.16.2" # Current required version of Solana +SOLANA_VERSION="1.16.15" # Current required version of Solana SOLANA_INSTANCE_TYPE="x2idn.16xlarge" SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used diff --git a/lib/solana/sample-configs/.env-sample-lightrpc b/lib/solana/sample-configs/.env-sample-lightrpc index d9a6e71b..0ce2222f 100644 --- a/lib/solana/sample-configs/.env-sample-lightrpc +++ b/lib/solana/sample-configs/.env-sample-lightrpc @@ -9,7 +9,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "consensus", "lightrpc", "heavyrpc" -SOLANA_VERSION="1.16.2" # Current required version of Solana +SOLANA_VERSION="1.16.15" # Current required version of Solana SOLANA_INSTANCE_TYPE="r6a.8xlarge" SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used diff --git a/lib/solana/single-node-deploy.json b/lib/solana/single-node-deploy.json deleted file mode 100644 index 6f96ab75..00000000 --- a/lib/solana/single-node-deploy.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "solana-single-node-heavyrpc": { - "nodeinstanceid": "i-02e19726f5fa9af2e" - } -} diff --git a/lib/solana/test/.env-test b/lib/solana/test/.env-test index 4d888e5e..1dc92f85 100644 --- a/lib/solana/test/.env-test +++ b/lib/solana/test/.env-test @@ -9,7 +9,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "consensus", "lightrpc", "heavyrpc" -SOLANA_VERSION="1.16.2" # Current required version of Solana +SOLANA_VERSION="1.16.15" # Current required version of Solana SOLANA_INSTANCE_TYPE="r6a.8xlarge" SOLANA_CPU_TYPE="x86_64" # All options: "x86_64", "ARM_64". IMPORTANT: Make sure the CPU type matches the instance type used From 83ab37bc4e3ea73ecabc75ad8ef3f60951023249 Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Fri, 13 Oct 2023 14:17:33 +1100 Subject: [PATCH 06/12] [WIP] Ajusted Solana architecture diagrams --- ...rchitecture-HA Nodes No Numbers.drawio.png | Bin 0 -> 159476 bytes ...itecture-Single Node No Numbers.drawio.png | Bin 0 -> 121996 bytes lib/solana/doc/assets/Architecture.drawio | 154 +++++++++++++++++- 3 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 lib/solana/doc/assets/Architecture-HA Nodes No Numbers.drawio.png create mode 100644 lib/solana/doc/assets/Architecture-Single Node No Numbers.drawio.png diff --git a/lib/solana/doc/assets/Architecture-HA Nodes No Numbers.drawio.png b/lib/solana/doc/assets/Architecture-HA Nodes No Numbers.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..81ff7d7767a2e3d9ed7ba66372788867f74a5bf0 GIT binary patch literal 159476 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≈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 DD6i?Y literal 0 HcmV?d00001 diff --git a/lib/solana/doc/assets/Architecture-Single Node No Numbers.drawio.png b/lib/solana/doc/assets/Architecture-Single Node No Numbers.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..cf8853b97a8f68f7e1f0a4a10ee75d1b7b065ca9 GIT binary patch literal 121996 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 H + @@ -175,4 +175,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 626b4bbf8dcd13e5642fa36db8df2851ff038750 Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Thu, 19 Oct 2023 12:06:42 +1100 Subject: [PATCH 07/12] Changed terminology from Light/Heavy to Base/Extended --- lib/solana/README.md | 6 ++-- lib/solana/doc/assets/Recommended_infra.md | 4 +-- lib/solana/doc/assets/Solana_on_AWS.md | 14 ++++---- lib/solana/doc/assets/Well_Architected.md | 4 +-- lib/solana/lib/assets/build-binaries.sh | 35 +++++++++++++++++++ lib/solana/lib/assets/user-data/node.sh | 4 +-- .../lib/config/solanaConfig.interface.ts | 2 +- lib/solana/lib/config/solanaConfig.ts | 2 +- ...nv-sample-lightrpc => .env-sample-baserpc} | 2 +- .../sample-configs/.env-sample-consensus | 2 +- ...ample-heavyrpc => .env-sample-extendedrpc} | 2 +- lib/solana/test/.env-test | 2 +- 12 files changed, 57 insertions(+), 22 deletions(-) create mode 100644 lib/solana/lib/assets/build-binaries.sh rename lib/solana/sample-configs/{.env-sample-lightrpc => .env-sample-baserpc} (96%) rename lib/solana/sample-configs/{.env-sample-heavyrpc => .env-sample-extendedrpc} (96%) diff --git a/lib/solana/README.md b/lib/solana/README.md index dc01c1a0..9fea02d1 100644 --- a/lib/solana/README.md +++ b/lib/solana/README.md @@ -1,6 +1,6 @@ # Sample AWS Blockchain Node Runner app for Solana Nodes -Solana nodes on AWS can be deployed in 3 different configurations: Consensus, Light RPC and Heavy RPC. In addition, you can choose to deploy those configurations as a single node or a highly available (HA) nodes setup. Learn more about configurations on [Solana on AWS documentation page](https://docs.solana.com/TBA) and below are the details on single node and HA deployment setups. +Solana nodes on AWS can be deployed in 3 different configurations: Consensus, RPC and RPC with secondary indexes. In addition, you can choose to deploy those configurations as a single node or a highly available (HA) nodes setup. Learn more about configurations on [Solana on AWS documentation page](https://docs.solana.com/TBA) and below are the details on single node and HA deployment setups. ## Overview of Deployment Architectures for Single and HA setups @@ -25,7 +25,7 @@ Solana nodes on AWS can be deployed in 3 different configurations: Consensus, Li ## Managing Secrets During the startup, if a node can't find the necessary identity file on the attached Root EBS volume, it generates a new one and stores it in AWS Secrets Manager. For a single-node deployment, the ARN of a secret can be provided within the `.env` configuration file with configuration and the node will pick it up. -Light RPC or Heavy RPC nodes use only 1 secret: +RPC and RPC nodes with secondary indexes use only 1 secret: - **Solana Node Identity Secret**: The identity key pair for a Solana node. @@ -70,7 +70,7 @@ Create your own copy of `.env` file and edit it: # Make sure you are in aws-blockchain-node-runners/lib/solana cd lib/solana pwd - cp ./sample-configs/.env-sample-lightrpc .env + cp ./sample-configs/.env-sample-baserpc .env nano .env ``` **NOTE:** Example configuration parameters are set in the local `.env-sample` file. You can find more examples inside `sample-configs` directory. diff --git a/lib/solana/doc/assets/Recommended_infra.md b/lib/solana/doc/assets/Recommended_infra.md index 4c36b43e..8ad9a093 100644 --- a/lib/solana/doc/assets/Recommended_infra.md +++ b/lib/solana/doc/assets/Recommended_infra.md @@ -3,5 +3,5 @@ | Usage pattern | Ideal configuration | Primary option on AWS | Data Transfer Estimates | Config reference | |---|---|---|---|---| | 1/ Consensus node | 32 vCPU, 256 GB RAM, Accounts volume: 1TB, 5K IOPS, 700 MB/s throughput, Data volume: 3TB, 10K IOPS, 700 MB/s throughput | r6a.8xlarge, Accounts volume: EBS gp3 1TB, 5K IOPS, 700 MB/s throughput, Data volume: EBS gp3 10K IOPS, 700 MB/s throughput | Proportional to the amount at stake. Between 200TB to 400TB/month | [.env-sample-consensus](../../sample-configs/.env-sample-consensus) | -| 2/ Light RPC node (no secondary indexes) | 32 vCPU, 256 GB RAM, Accounts volume: 1TB, 5K IOPS, 700 MB/s throughput, Data volume: 3TB, 12K IOPS, 700 MB/s throughput | r6a.8xlarge, Accounts volume: EBS gp3 1TB, 5K IOPS, 700 MB/s throughput Data volume: EBS gp3 12K IOPS, 700 MB/s throughput | 150-200TB/month (no staking) | [.env-sample-lightrpc](../../sample-configs/.env-sample-lightrpc) | -| 3/ Full RPC node (with all secondary indexes) | 64 vCPU, 1 TB RAM, Accounts volume: 1TB, 7K IOPS, 700 MB/s throughput, Data volume: 3TB, 16K IOPS, 700 MB/s throughput | x2idn.16xlarge, Accounts: instance storage (ephemeral NVMe volumes) 1.9 TB, Data volume: 3TB, 12K IOPS, 700 MB/s throughput | 150-200TB/month (no staking) | [.env-sample-heavyrpc](../../sample-configs/.env-sample-heavyrpc) | \ No newline at end of file +| 2/ Base RPC node (no secondary indexes) | 32 vCPU, 256 GB RAM, Accounts volume: 1TB, 5K IOPS, 700 MB/s throughput, Data volume: 3TB, 12K IOPS, 700 MB/s throughput | r6a.8xlarge, Accounts volume: EBS gp3 1TB, 5K IOPS, 700 MB/s throughput Data volume: EBS gp3 12K IOPS, 700 MB/s throughput | 150-200TB/month (no staking) | [.env-sample-baserpc](../../sample-configs/.env-sample-baserpc) | +| 3/ Extended RPC node (with all secondary indexes) | 64 vCPU, 1 TB RAM, Accounts volume: 1TB, 7K IOPS, 700 MB/s throughput, Data volume: 3TB, 16K IOPS, 700 MB/s throughput | x2idn.16xlarge, Accounts: instance storage (ephemeral NVMe volumes) 1.9 TB, Data volume: 3TB, 12K IOPS, 700 MB/s throughput | 150-200TB/month (no staking) | [.env-sample-extendedrpc](../../sample-configs/.env-sample-extendedrpc) | \ No newline at end of file diff --git a/lib/solana/doc/assets/Solana_on_AWS.md b/lib/solana/doc/assets/Solana_on_AWS.md index 77a66b85..85fe9914 100644 --- a/lib/solana/doc/assets/Solana_on_AWS.md +++ b/lib/solana/doc/assets/Solana_on_AWS.md @@ -19,27 +19,27 @@ Based on amount you have at stake, you can estimate with [community-developed ca - To run a single Consensus node on AWS, use the [Solana Node Runner CDK application](https://github.com/aws-samples/aws-blockchain-node-runners/tree/solana/lib/solana) in [AWS Blockchain Node Runners](https://aws-samples.github.io/aws-blockchain-node-runners/) and use [sample config for Consensus node](https://github.com/aws-samples/aws-blockchain-node-runners/blob/solana/lib/solana/sample-configs/.env-sample-validator). -### Light RPC nodes +### Base RPC nodes -Light RPC nodes can be used by your application to perform all RPC calls, except those that trigger scan operation to the entire account set, like [getProgramAccounts](https://docs.solana.com/api/http#getprogramaccounts) and [SPL-token-specific requests](https://docs.solana.com/api/http#gettokenaccountsbydelegate): `getTokenAccountsByDelegate`, `getTokenAccountBalance`, `getTokenAccountsByOwner`, `getTokenLargestAccounts`, and `getTokenSupply`. These node types can use the same infrastructure as the consensus nodes, but instead of validating transactions, it will expose HTTP and WebSocket endpoints for your application to interact with the node trough JSON RPC API and RPC PubSub respectively. On AWS you can use the same as with consensus node `r6a.8xlarge` EC2 instance type the same three EBS gp3 volumes: +Base RPC nodes (or just "RPC nodes") can be used by your application to perform all RPC calls, except those that trigger scan operation to the entire account set, like [getProgramAccounts](https://docs.solana.com/api/http#getprogramaccounts) and [SPL-token-specific requests](https://docs.solana.com/api/http#gettokenaccountsbydelegate): `getTokenAccountsByDelegate`, `getTokenAccountBalance`, `getTokenAccountsByOwner`, `getTokenLargestAccounts`, and `getTokenSupply`. These node types can use the same infrastructure as the consensus nodes, but instead of validating transactions, it will expose HTTP and WebSocket endpoints for your application to interact with the node trough JSON RPC API and RPC PubSub respectively. On AWS you can use the same as with consensus node `r6a.8xlarge` EC2 instance type the same three EBS gp3 volumes: - Root volume: EBS gp3 500 GB, 3K IOPS, 250 MB/s throughput, - Accounts volume: EBS gp3 500GB, 5K IOPS, 700 MB/s throughput, - Data volume: EBS gp3 2TB, 10K IOPS, 700 MB/s throughput. Data transfer costs for this node can vary depending on whether you expose the RPC endpoints to the Internet (generates more traffic to the Internet) or consume it with the same AWS Availability Zone (will cost you nothing). If you are not exposing the RPC interface for external consumption, then your node will generate about 13-15 TB of outgoing data per month per node. It is less than Consensus nodes, but can still be sufficient and better be discussed with your AWS account manager. -- To run Light RPC node on AWS, use the [Solana Node Runner CDK application](https://github.com/aws-samples/aws-blockchain-node-runners/tree/solana/lib/solana) in [AWS Blockchain Node Runners](https://aws-samples.github.io/aws-blockchain-node-runners/) and use [sample config for Light RPC node](https://github.com/aws-samples/aws-blockchain-node-runners/blob/solana/lib/solana/sample-configs/.env-sample-lightrpc). You can use both Single-node and Highly Available-node setup. +- To run RPC node on AWS, use the [Solana Node Runner CDK application](https://github.com/aws-samples/aws-blockchain-node-runners/tree/solana/lib/solana) in [AWS Blockchain Node Runners](https://aws-samples.github.io/aws-blockchain-node-runners/) and use [sample config for RPC node](https://github.com/aws-samples/aws-blockchain-node-runners/blob/solana/lib/solana/sample-configs/.env-sample-baserpc). You can use both Single-node and Highly Available-node setup. -### Heavy RPC nodes +### Extended RPC nodes with secondary indexes -Heavy RPC nodes allow you to call "heavier" RPC functions like mentioned above. To use them you need to enable extra indexes on your RPC node, which requires more hardware. At the time of writing (September 2023) it is recommended to use at least 1 TB or RAM with NVMe discs, or, on AWS an instance like `x2idn.16xlarge` which is also equipped with a physically-attached NVMe SSD [Instance Store volume](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html). The storage configurations looks like this: +RPC nodes with secondary indexes allow you to call "extended" RPC functions like mentioned above. To use them you need to enable extra indexes on your RPC node, which requires more hardware. At the time of writing (September 2023) it is recommended to use at least 1 TB or RAM with NVMe discs, or, on AWS an instance like `x2idn.16xlarge` which is also equipped with a physically-attached NVMe SSD [Instance Store volume](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html). The storage configurations looks like this: - Root volume: EBS gp3 500 GB, 3K IOPS, 250 MB/s throughput, - Accounts volume: Instance store (comes with the `x2idn.16xlarge` instance) 1.9TB, - Data volume: EBS gp3 2TB, 10K IOPS, 700 MB/s throughput. -As with the Light RPC nodes, data transfer amount may vary and the estimated amount is 15 TB of outgoing data per month per node. +As with the RPC nodes, data transfer amount may vary and the estimated amount is 15 TB of outgoing data per month per node. -- To run Heavy RPC node on AWS, use the [Solana Node Runner CDK application](https://github.com/aws-samples/aws-blockchain-node-runners/tree/solana/lib/solana) in [AWS Blockchain Node Runners](https://aws-samples.github.io/aws-blockchain-node-runners/) and use [sample config for Heavy RPC node](https://github.com/aws-samples/aws-blockchain-node-runners/blob/solana/lib/solana/sample-configs/.env-sample-heavyrpc). You can use both Single-node and Highly Available-node setup. +- To run RPC node with secondary indexes on AWS, use the [Solana Node Runner CDK application](https://github.com/aws-samples/aws-blockchain-node-runners/tree/solana/lib/solana) in [AWS Blockchain Node Runners](https://aws-samples.github.io/aws-blockchain-node-runners/) and use [sample config for RPC with secondary indexes node](https://github.com/aws-samples/aws-blockchain-node-runners/blob/solana/lib/solana/sample-configs/.env-sample-extendedrpc). You can use both Single-node and Highly Available-node setup. ### History nodes diff --git a/lib/solana/doc/assets/Well_Architected.md b/lib/solana/doc/assets/Well_Architected.md index 2c9a14d8..74a39ecd 100644 --- a/lib/solana/doc/assets/Well_Architected.md +++ b/lib/solana/doc/assets/Well_Architected.md @@ -14,8 +14,8 @@ This is the Well-Architected checklist for Solana nodes implementation of the AW | | Authorization and access control | Use instance profile with Amazon Elastic Compute Cloud (Amazon EC2) instances | This solution uses AWS Identity and Access Management (AWS IAM) role instead of IAM user. | | | | Following principle of least privilege access | In all node types, root user is not used (using special user "solana" instead). | | | Application security | Security focused development practices | cdk-nag is being used with appropriate suppressions. | -| Cost optimization | Service selection | Use cost effective resources | 1/ AMD-based instances are used for Consensus and Light RPC node to save the costs. Consider compiling Graviton-based binaries to improve costs for compute. 2/ Cost-effective EBS gp3 are preferred instead of io2. 3/ Solana nodes generate a substantial amount of outgoing data traffic, which deeds to be addressed with non-technical means like getting private agreements with AWS. | -| | Cost awareness | Estimate costs | Single Light RPC node with `r6a.8xlarge` EBS gp3 volumes about 2549 GB with On-Demand pricing will cost around US$1,596.43 per month in the US East (N. Virginia) region. More cost-optimal option with 3 year Compute Savings plan the cost goes down to $962.84 USD. Additionally, the data transfer costs can be about $1,356.80 USD per month for 15TB of outgoing traffic. | +| Cost optimization | Service selection | Use cost effective resources | 1/ AMD-based instances are used for Consensus and RPC node to save the costs. Consider compiling Graviton-based binaries to improve costs for compute. 2/ Cost-effective EBS gp3 are preferred instead of io2. 3/ Solana nodes generate a substantial amount of outgoing data traffic, which deeds to be addressed with non-technical means like getting private agreements with AWS. | +| | Cost awareness | Estimate costs | Single RPC node with `r6a.8xlarge` EBS gp3 volumes about 2549 GB with On-Demand pricing will cost around US$1,596.43 per month in the US East (N. Virginia) region. More cost-optimal option with 3 year Compute Savings plan the cost goes down to $962.84 USD. Additionally, the data transfer costs can be about $1,356.80 USD per month for 15TB of outgoing traffic. | | Reliability | Resiliency implementation | Withstand component failures | This solution uses AWS Application Load Balancer with RPC nodes for high availability. Newly provisioned Solana nodes triggered by Auto Scaling get up and running in about 30-50 minutes. | | | Data backup | How is data backed up? | Considering blockchain data is replicated by nodes automatically and Solana nodes sync from start within an hour, we don't use any additional mechanisms to backup the data. | | | Resource monitoring | How are workload resources monitored? | Resources are being monitored using Amazon CloudWatch dashboards. Amazon CloudWatch custom metrics are being pushed via CloudWatch Agent. | diff --git a/lib/solana/lib/assets/build-binaries.sh b/lib/solana/lib/assets/build-binaries.sh new file mode 100644 index 00000000..c0f07a15 --- /dev/null +++ b/lib/solana/lib/assets/build-binaries.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +source /etc/environment + +echo "Install rustc, cargo and rustfmt." +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rust-installer.sh +chmod 755 ./rust-installer.sh +./rust-installer.sh -q -y +source $HOME/.cargo/env +rustup component add rustfmt + +echo "Verifying we use the latest stable version of Rust" +rustup update + +export RUST_STABLE_VERSION=$(rustc --version | awk '{print $2}') + +echo "Installing libssl-dev, pkg-config, zlib1g-dev, protobuf etc." +apt-get update +apt-get -y install libssl-dev libudev-dev pkg-config zlib1g-dev llvm clang cmake make libprotobuf-dev protobuf-compiler + +echo "Getting the source for stable version v$SOLANA_VERSION" +wget https://github.com/solana-labs/solana/archive/refs/tags/v$SOLANA_VERSION.tar.gz +tar -xzvf v$SOLANA_VERSION.tar.gz +cd solana-$SOLANA_VERSION + +echo "Building Solana..." +./scripts/cargo-install-all.sh --validator-only . + +echo "Check solana-validator version" + +./bin/solana-validator --version + +echo "Modifying path" +echo export PATH=$PWD/bin:$PATH >> /home/ssm-user/.profile +source /home/ssm-user/.profile \ No newline at end of file diff --git a/lib/solana/lib/assets/user-data/node.sh b/lib/solana/lib/assets/user-data/node.sh index 64eea980..c48927fd 100644 --- a/lib/solana/lib/assets/user-data/node.sh +++ b/lib/solana/lib/assets/user-data/node.sh @@ -282,11 +282,11 @@ if [[ "$SOLANA_NODE_TYPE" == "consensus" ]]; then mv /opt/solana/node-consensus-template.sh /home/solana/bin/validator.sh fi -if [[ "$SOLANA_NODE_TYPE" == "lightrpc" ]]; then +if [[ "$SOLANA_NODE_TYPE" == "baserpc" ]]; then mv /opt/solana/node-light-rpc-template.sh /home/solana/bin/validator.sh fi -if [[ "$SOLANA_NODE_TYPE" == "heavyrpc" ]]; then +if [[ "$SOLANA_NODE_TYPE" == "extendedrpc" ]]; then mv /opt/solana/node-heavy-rpc-template.sh /home/solana/bin/validator.sh fi diff --git a/lib/solana/lib/config/solanaConfig.interface.ts b/lib/solana/lib/config/solanaConfig.interface.ts index f8dd2e3f..32dfbdb6 100644 --- a/lib/solana/lib/config/solanaConfig.interface.ts +++ b/lib/solana/lib/config/solanaConfig.interface.ts @@ -1,7 +1,7 @@ import * as configTypes from "../../../constructs/config.interface"; export type SolanaCluster = "mainnet-beta" | "testnet" | "devnet"; -export type SolanaNodeConfiguration = "consensus" | "lightrpc" | "heavyrpc"; +export type SolanaNodeConfiguration = "consensus" | "baserpc" | "extendedrpc"; export interface SolanaDataVolumeConfig extends configTypes.DataVolumeConfig { } diff --git a/lib/solana/lib/config/solanaConfig.ts b/lib/solana/lib/config/solanaConfig.ts index 59cbd96d..5d473c7c 100644 --- a/lib/solana/lib/config/solanaConfig.ts +++ b/lib/solana/lib/config/solanaConfig.ts @@ -28,7 +28,7 @@ export const baseNodeConfig: configTypes.SolanaBaseNodeConfig = { instanceCpuType: process.env.SOLANA_CPU_TYPE?.toLowerCase() == "x86_64" ? ec2.AmazonLinuxCpuType.X86_64 : ec2.AmazonLinuxCpuType.ARM_64, solanaCluster: process.env.SOLANA_CLUSTER || "mainnet-beta", solanaVersion: process.env.SOLANA_VERSION || "1.16.15", - nodeConfiguration: process.env.SOLANA_NODE_CONFIGURATION || "lightrpc", + nodeConfiguration: process.env.SOLANA_NODE_CONFIGURATION || "baserpc", dataVolume: { sizeGiB: process.env.SOLANA_DATA_VOL_SIZE ? parseInt(process.env.SOLANA_DATA_VOL_SIZE): 2000, type: parseDataVolumeType(process.env.SOLANA_DATA_VOL_TYPE?.toLowerCase() ? process.env.SOLANA_DATA_VOL_TYPE?.toLowerCase() : "gp3"), diff --git a/lib/solana/sample-configs/.env-sample-lightrpc b/lib/solana/sample-configs/.env-sample-baserpc similarity index 96% rename from lib/solana/sample-configs/.env-sample-lightrpc rename to lib/solana/sample-configs/.env-sample-baserpc index 0ce2222f..42859907 100644 --- a/lib/solana/sample-configs/.env-sample-lightrpc +++ b/lib/solana/sample-configs/.env-sample-baserpc @@ -8,7 +8,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" -SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "consensus", "lightrpc", "heavyrpc" +SOLANA_NODE_CONFIGURATION="baserpc" # All options: "consensus", "baserpc", "extendedrpc" SOLANA_VERSION="1.16.15" # Current required version of Solana SOLANA_INSTANCE_TYPE="r6a.8xlarge" diff --git a/lib/solana/sample-configs/.env-sample-consensus b/lib/solana/sample-configs/.env-sample-consensus index 1d891e85..da9ff3d0 100644 --- a/lib/solana/sample-configs/.env-sample-consensus +++ b/lib/solana/sample-configs/.env-sample-consensus @@ -8,7 +8,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" -SOLANA_NODE_CONFIGURATION="consensus" # All options: "consensus", "lightrpc", "heavyrpc" +SOLANA_NODE_CONFIGURATION="consensus" # All options: "consensus", "baserpc", "extendedrpc" SOLANA_VERSION="1.16.15" # Current required version of Solana SOLANA_INSTANCE_TYPE="r6a.8xlarge" diff --git a/lib/solana/sample-configs/.env-sample-heavyrpc b/lib/solana/sample-configs/.env-sample-extendedrpc similarity index 96% rename from lib/solana/sample-configs/.env-sample-heavyrpc rename to lib/solana/sample-configs/.env-sample-extendedrpc index 0cd83615..5733db4b 100644 --- a/lib/solana/sample-configs/.env-sample-heavyrpc +++ b/lib/solana/sample-configs/.env-sample-extendedrpc @@ -8,7 +8,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" -SOLANA_NODE_CONFIGURATION="heavyrpc" # All options: "consensus", "lightrpc", "heavyrpc" +SOLANA_NODE_CONFIGURATION="extendedrpc" # All options: "consensus", "baserpc", "extendedrpc" SOLANA_VERSION="1.16.15" # Current required version of Solana SOLANA_INSTANCE_TYPE="x2idn.16xlarge" diff --git a/lib/solana/test/.env-test b/lib/solana/test/.env-test index 1dc92f85..96c0677c 100644 --- a/lib/solana/test/.env-test +++ b/lib/solana/test/.env-test @@ -8,7 +8,7 @@ AWS_REGION="us-east-2" ## Common configuration parameters ## SOLANA_CLUSTER="mainnet-beta" # All options: "mainnet-beta", "testnet", "devnet" -SOLANA_NODE_CONFIGURATION="lightrpc" # All options: "consensus", "lightrpc", "heavyrpc" +SOLANA_NODE_CONFIGURATION="baserpc" # All options: "consensus", "baserpc", "extendedrpc" SOLANA_VERSION="1.16.15" # Current required version of Solana SOLANA_INSTANCE_TYPE="r6a.8xlarge" From 652dac4ec4444ca267676f7def9b5d6574c93eb2 Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Thu, 19 Oct 2023 12:08:35 +1100 Subject: [PATCH 08/12] Changed of terminology in the README --- lib/solana/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/solana/README.md b/lib/solana/README.md index 9fea02d1..995bf73f 100644 --- a/lib/solana/README.md +++ b/lib/solana/README.md @@ -1,6 +1,6 @@ # Sample AWS Blockchain Node Runner app for Solana Nodes -Solana nodes on AWS can be deployed in 3 different configurations: Consensus, RPC and RPC with secondary indexes. In addition, you can choose to deploy those configurations as a single node or a highly available (HA) nodes setup. Learn more about configurations on [Solana on AWS documentation page](https://docs.solana.com/TBA) and below are the details on single node and HA deployment setups. +Solana nodes on AWS can be deployed in 3 different configurations: Consensus, base RPC and extended RPC with secondary indexes. In addition, you can choose to deploy those configurations as a single node or a highly available (HA) nodes setup. Learn more about configurations on [Solana on AWS documentation page](https://docs.solana.com/TBA) and below are the details on single node and HA deployment setups. ## Overview of Deployment Architectures for Single and HA setups From 28486bf6b84a147ff0b2256bf1045279c8728ca1 Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Mon, 23 Oct 2023 15:42:25 +1100 Subject: [PATCH 09/12] Correcting docs to use consistent terminology --- lib/solana/README.md | 4 ++-- lib/solana/doc/assets/Solana_on_AWS.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/solana/README.md b/lib/solana/README.md index 995bf73f..760f4c86 100644 --- a/lib/solana/README.md +++ b/lib/solana/README.md @@ -17,7 +17,7 @@ Solana nodes on AWS can be deployed in 3 different configurations: Consensus, ba ![Highly Available Nodes Deployment](./doc/assets/Architecture-HANodes.drawio.png) -1. A set of Solana nodes are deployed within the [Auto Scaling Group](https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-groups.html) in the [Default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) continuously synchronizes with the rest of nodes on [Solana Clusters](https://docs.solana.com/clusters) through [Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html). +1. A set of Base or Extended RPC Solana nodes are deployed within the [Auto Scaling Group](https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-groups.html) in the [Default VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) continuously synchronizes with the rest of nodes on [Solana Clusters](https://docs.solana.com/clusters) through [Internet Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html). **Note that HA setup is not suitable for Consensus nodes.** 2. The Solana nodes are accessed by dApps or development tools internally through [Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html). JSON RPC API is not exposed to the Internet to protect nodes from unauthorized access. dApps need to handle user authentication and API protection, like [in this example for dApps on AWS](https://aws.amazon.com/blogs/architecture/dapp-authentication-with-amazon-cognito-and-web3-proxy-with-amazon-api-gateway/). 3. The Solana nodes use all required secrets locally, but store a copy in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) as secure backup. 4. The Solana nodes send various monitoring metrics for both EC2 and Solana nodes to Amazon CloudWatch. @@ -25,7 +25,7 @@ Solana nodes on AWS can be deployed in 3 different configurations: Consensus, ba ## Managing Secrets During the startup, if a node can't find the necessary identity file on the attached Root EBS volume, it generates a new one and stores it in AWS Secrets Manager. For a single-node deployment, the ARN of a secret can be provided within the `.env` configuration file with configuration and the node will pick it up. -RPC and RPC nodes with secondary indexes use only 1 secret: +Base RPC and Extended RPC nodes use only 1 secret: - **Solana Node Identity Secret**: The identity key pair for a Solana node. diff --git a/lib/solana/doc/assets/Solana_on_AWS.md b/lib/solana/doc/assets/Solana_on_AWS.md index 85fe9914..85182368 100644 --- a/lib/solana/doc/assets/Solana_on_AWS.md +++ b/lib/solana/doc/assets/Solana_on_AWS.md @@ -4,7 +4,7 @@ Running Solana nodes on AWS can help to reduce operational costs and improve rel ## Solana node configurations on AWS -There are four major use cases for running Solana nodes: consensus, “light” RPC node, “heavy” RPC node, and history node. Depending on the use case, you start your ‘solana-validator’ process with different set of parameters and might use different infrastructure configurations. Let’s review them. +There are four major use cases for running Solana nodes: Consensus, "Base” RPC node, “Extended” RPC node, and history node. Depending on the use case, you start your ‘solana-validator’ process with different set of parameters and might use different infrastructure configurations. Let’s review them. ### Consensus node From 457fdc543d64a189b2afef2b6c270368c593bc66 Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Mon, 23 Oct 2023 16:27:44 +1100 Subject: [PATCH 10/12] Added Solana to blueprints on the website --- lib/solana/README.md | 62 +++++++++++++++++++++++++------ website/docs/Blueprints/Solana.md | 9 +++++ website/docs/intro/intro.md | 2 +- 3 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 website/docs/Blueprints/Solana.md diff --git a/lib/solana/README.md b/lib/solana/README.md index 760f4c86..02b07377 100644 --- a/lib/solana/README.md +++ b/lib/solana/README.md @@ -1,6 +1,6 @@ # Sample AWS Blockchain Node Runner app for Solana Nodes -Solana nodes on AWS can be deployed in 3 different configurations: Consensus, base RPC and extended RPC with secondary indexes. In addition, you can choose to deploy those configurations as a single node or a highly available (HA) nodes setup. Learn more about configurations on [Solana on AWS documentation page](https://docs.solana.com/TBA) and below are the details on single node and HA deployment setups. +Solana nodes on AWS can be deployed in 3 different configurations: Consensus, base RPC and extended RPC with secondary indexes. In addition, you can choose to deploy those configurations as a single node or a highly available (HA) nodes setup. Learn more about configurations on [Solana on AWS documentation page](https://solana.com/developers/guides/rpc/configure-solana-rpc-on-aws) and below are the details on single node and HA deployment setups. ## Overview of Deployment Architectures for Single and HA setups @@ -22,7 +22,12 @@ Solana nodes on AWS can be deployed in 3 different configurations: Consensus, ba 3. The Solana nodes use all required secrets locally, but store a copy in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) as secure backup. 4. The Solana nodes send various monitoring metrics for both EC2 and Solana nodes to Amazon CloudWatch. -## Managing Secrets +## Additional materials + +

+ +Managing Secrets + During the startup, if a node can't find the necessary identity file on the attached Root EBS volume, it generates a new one and stores it in AWS Secrets Manager. For a single-node deployment, the ARN of a secret can be provided within the `.env` configuration file with configuration and the node will pick it up. Base RPC and Extended RPC nodes use only 1 secret: @@ -37,11 +42,54 @@ Consensus node uses up to 3 more identity secrets: - **Registration Transaction Funding Account Secret**: An account that has sufficient SOL to pay for on-chain validator creation transaction. If not present, the node provisioning script assumes the on-chain validator creation transaction was issued elsewhere and will skip it. +
+ +
+ +Well-Architected Checklist + +This is the Well-Architected checklist for Solana nodes implementation of the AWS Blockchain Node Runner app. This checklist takes into account questions from the [AWS Well-Architected Framework](https://aws.amazon.com/architecture/well-architected/) which are relevant to this workload. Please feel free to add more checks from the framework if required for your workload. + +| Pillar | Control | Question/Check | Remarks | +|:------------------------|:----------------------------------|:---------------------------------------------------------------------------------|:-----------------| +| Security | Network protection | Are there unnecessary open ports in security groups? | Please note that ports 8801 to 8812 (TCP/UDP) for Solana are open to public to support P2P protocols. We have to rely on the protection mechanisms built into the Solana validators software to protect those ports. | +| | | Traffic inspection | Traffic protection is not used in the solution. AWS Web Applications Firewall (WAF) could be implemented for traffic inspection. Additional charges will apply. | +| | Compute protection | Reduce attack surface | This solution uses Ubuntu 20.04 AMI. You may choose to run hardening scripts on it. | +| | | Enable people to perform actions at a distance | This solution uses AWS Systems Manager for terminal session, not ssh ports. | +| | Data protection at rest | Use encrypted Amazon Elastic Block Store (Amazon EBS) volumes | This solution uses encrypted Amazon EBS volumes. | +| | | Use encrypted Amazon Simple Storage Service (Amazon S3) buckets | This solution uses Amazon S3 managed keys (SSE-S3) encryption. | +| | Data protection in transit | Use TLS | The AWS Application Load balancer currently uses HTTP listener. Create HTTPS listener with self signed certificate if TLS is desired. | +| | Authorization and access control | Use instance profile with Amazon Elastic Compute Cloud (Amazon EC2) instances | This solution uses AWS Identity and Access Management (AWS IAM) role instead of IAM user. | +| | | Following principle of least privilege access | In all node types, root user is not used (using special user "solana" instead). | +| | Application security | Security focused development practices | cdk-nag is being used with appropriate suppressions. | +| Cost optimization | Service selection | Use cost effective resources | 1/ AMD-based instances are used for Consensus and RPC node to save the costs. Consider compiling Graviton-based binaries to improve costs for compute. 2/ Cost-effective EBS gp3 are preferred instead of io2. 3/ Solana nodes generate a substantial amount of outgoing data traffic, which deeds to be addressed with non-technical means like getting private agreements with AWS. | +| | Cost awareness | Estimate costs | Single RPC node with `r6a.8xlarge` EBS gp3 volumes about 2549 GB with On-Demand pricing will cost around US$1,596.43 per month in the US East (N. Virginia) region. More cost-optimal option with 3 year Compute Savings plan the cost goes down to $962.84 USD. Additionally, the data transfer costs can be about $1,356.80 USD per month for 15TB of outgoing traffic. | +| Reliability | Resiliency implementation | Withstand component failures | This solution uses AWS Application Load Balancer with RPC nodes for high availability. Newly provisioned Solana nodes triggered by Auto Scaling get up and running in about 30-50 minutes. | +| | Data backup | How is data backed up? | Considering blockchain data is replicated by nodes automatically and Solana nodes sync from start within an hour, we don't use any additional mechanisms to backup the data. | +| | Resource monitoring | How are workload resources monitored? | Resources are being monitored using Amazon CloudWatch dashboards. Amazon CloudWatch custom metrics are being pushed via CloudWatch Agent. | +| Performance efficiency | Compute selection | How is compute solution selected? | Compute solution is selected based on best price-performance, i.e. AWS AMD-based Amazon EC2 instances. | +| | Storage selection | How is storage solution selected? | Storage solution is selected based on best price-performance, i.e. gp3 Amazon EBS volumes with optimal IOPS and throughput. | +| | Architecture selection | How is the best performance architecture selected? | We used a combination of recommendations from the Solana community and our own testing. | +| Operational excellence | Workload health | How is health of workload determined? | Health of workload is determined via AWS Application Load Balancer Target Group Health Checks, on port 8899. | +| Sustainability | Hardware & services | Select most efficient hardware for your workload | The solution uses AMD-powered instances. There is a potential to use AWS Graviton-based Amazon EC2 instances which offer the best performance per watt of energy use in Amazon EC2. | +
+ +
+ +Recommended Infrastructure + +| Usage pattern | Ideal configuration | Primary option on AWS | Data Transfer Estimates | Config reference | +|---|---|---|---|---| +| 1/ Consensus node | 32 vCPU, 256 GB RAM, Accounts volume: 1TB, 5K IOPS, 700 MB/s throughput, Data volume: 3TB, 10K IOPS, 700 MB/s throughput | r6a.8xlarge, Accounts volume: EBS gp3 1TB, 5K IOPS, 700 MB/s throughput, Data volume: EBS gp3 10K IOPS, 700 MB/s throughput | Proportional to the amount at stake. Between 200TB to 400TB/month | [.env-sample-consensus](../../sample-configs/.env-sample-consensus) | +| 2/ Base RPC node (no secondary indexes) | 32 vCPU, 256 GB RAM, Accounts volume: 1TB, 5K IOPS, 700 MB/s throughput, Data volume: 3TB, 12K IOPS, 700 MB/s throughput | r6a.8xlarge, Accounts volume: EBS gp3 1TB, 5K IOPS, 700 MB/s throughput Data volume: EBS gp3 12K IOPS, 700 MB/s throughput | 150-200TB/month (no staking) | [.env-sample-baserpc](../../sample-configs/.env-sample-baserpc) | +| 3/ Extended RPC node (with all secondary indexes) | 64 vCPU, 1 TB RAM, Accounts volume: 1TB, 7K IOPS, 700 MB/s throughput, Data volume: 3TB, 16K IOPS, 700 MB/s throughput | x2idn.16xlarge, Accounts: instance storage (ephemeral NVMe volumes) 1.9 TB, Data volume: 3TB, 12K IOPS, 700 MB/s throughput | 150-200TB/month (no staking) | [.env-sample-extendedrpc](../../sample-configs/.env-sample-extendedrpc) | +
+ ## Setup Instructions ### Setup Cloud9 -We will use AWS Cloud9 to execute the subsequent commands. Follow the instructions in [Cloud9 Setup](../../doc/setup-cloud9.md) +We will use AWS Cloud9 to execute the subsequent commands. Follow the instructions in [Cloud9 Setup](../../docs/setup-cloud9.md) ### Clone this repository and install dependencies @@ -209,14 +257,6 @@ The result should be like this (the actual balance might change): ``` -## Well-Architected - -Review the [Well-Architected Checklist](./doc/assets/Well_Architected.md) for pros and cons of this solution. - -## Recommended infrastructure - -Review the [Recommended Infrastructure](./doc/assets/Recommended_infra.md) document for details. - ## Upgrades When nodes need to be upgraded or downgraded, [use blue/green pattern to do it](https://aws.amazon.com/blogs/devops/performing-bluegreen-deployments-with-aws-codedeploy-and-auto-scaling-groups/). This is not yet automated and contributions are welcome! \ No newline at end of file diff --git a/website/docs/Blueprints/Solana.md b/website/docs/Blueprints/Solana.md new file mode 100644 index 00000000..3029a84e --- /dev/null +++ b/website/docs/Blueprints/Solana.md @@ -0,0 +1,9 @@ +--- +sidebar_position: 3 +sidebar_label: Solana +--- +# + +import Readme from '../../../lib/solana/README.md'; + + \ No newline at end of file diff --git a/website/docs/intro/intro.md b/website/docs/intro/intro.md index 3eeba92e..7acca57c 100644 --- a/website/docs/intro/intro.md +++ b/website/docs/intro/intro.md @@ -10,7 +10,7 @@ Our journey began with research projects and testing conducted within AWS. As we The AWS Solutions Architects involved in this project pour their hearts into it, all while juggling their primary job responsibilities. Their passion for blockchain technology drives them to provide the best possible support for this initiative. We're excited to have you on board and look forward to making the blockchain world more accessible together! 😊 -We welcome contributions from both enthusiasts like us or established blockchain organizations, which many of our customers are. You can report bugs, create pull requests, add support for new nodes or new infrastructure configurations for existing ones. Please have a look at our [Contribution Guide](../../../CONTRIBUTING.md). +We welcome contributions from both enthusiasts like us or established blockchain organizations, which many of our customers are. You can report bugs, create pull requests, add support for new nodes or new infrastructure configurations for existing ones. Please have a look at our [Contribution Guide](https://github.com/aws-samples/aws-blockchain-node-runners/blob/solana/CONTRIBUTING.md). ## Code of Conduct This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). From d69c5953df2ce73e81864dba69afb6563d0fe0be Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Tue, 24 Oct 2023 14:05:14 +1100 Subject: [PATCH 11/12] Minor adjustments in the documentation --- lib/solana/README.md | 4 ++-- lib/solana/lib/assets/user-data/node.sh | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/solana/README.md b/lib/solana/README.md index 02b07377..1b41c651 100644 --- a/lib/solana/README.md +++ b/lib/solana/README.md @@ -113,7 +113,7 @@ We will use AWS Cloud9 to execute the subsequent commands. Follow the instructio 3. Configure your setup -Create your own copy of `.env` file and edit it: +Create your own copy of `.env` file and edit it to update with your AWS Account ID and Region: ```bash # Make sure you are in aws-blockchain-node-runners/lib/solana cd lib/solana @@ -236,7 +236,7 @@ The result should be like this (the actual balance might change): sudo cat /var/log/cloud-init-output.log ``` -3. How can I restart the Solana serice? +3. How can I restart the Solana service? ``` bash export INSTANCE_ID=$(cat single-node-deploy.json | jq -r '..|.node-instance-id? | select(. != null)') diff --git a/lib/solana/lib/assets/user-data/node.sh b/lib/solana/lib/assets/user-data/node.sh index c48927fd..56214601 100644 --- a/lib/solana/lib/assets/user-data/node.sh +++ b/lib/solana/lib/assets/user-data/node.sh @@ -346,9 +346,11 @@ sudo chmod +x /opt/syncchecker.sh (crontab -l; echo "*/1 * * * * /opt/syncchecker.sh >/tmp/syncchecker.log 2>&1") | crontab - crontab -l -echo "Signaling ASG lifecycle hook to complete" -TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") -INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id) -aws autoscaling complete-lifecycle-action --lifecycle-action-result CONTINUE --instance-id $INSTANCE_ID --lifecycle-hook-name "$LIFECYCLE_HOOK_NAME" --auto-scaling-group-name "$ASG_NAME" --region $AWS_REGION +if [[ "$LIFECYCLE_HOOK_NAME" != "none" ]]; then + echo "Signaling ASG lifecycle hook to complete" + TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") + INSTANCE_ID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id) + aws autoscaling complete-lifecycle-action --lifecycle-action-result CONTINUE --instance-id $INSTANCE_ID --lifecycle-hook-name "$LIFECYCLE_HOOK_NAME" --auto-scaling-group-name "$ASG_NAME" --region $AWS_REGION +fi echo "All Done!!" \ No newline at end of file From 4a55805006c82a5e1a261c2f03efc5e9c57b6212 Mon Sep 17 00:00:00 2001 From: Nikolay Vlasov Date: Thu, 26 Oct 2023 11:01:12 +1100 Subject: [PATCH 12/12] Solana release --- .gitignore | 2 +- docs/setup-cloud9.md | 63 ++++++++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index 789a258e..2c5e59f2 100644 --- a/.gitignore +++ b/.gitignore @@ -30,7 +30,7 @@ sync-node-deploy*.json instance-image*.json rpc-node-deploy*.json single-node-deploy*.json -hs-node-deploy*.json +ha-nodes-deploy*.json *.OLD .env \ No newline at end of file diff --git a/docs/setup-cloud9.md b/docs/setup-cloud9.md index 85b91e98..a9d93179 100644 --- a/docs/setup-cloud9.md +++ b/docs/setup-cloud9.md @@ -1,6 +1,6 @@ # AWS Cloud9 Setup -Most steps in this repository will need to be performed from a Linux command prompt. An especially convenient way of doing this is to use AWS Cloud9, a cloud-based Integrated Development Environment (IDE). Cloud9 allows you to edit source files and execute commands from an easy-to-use web interface. It comes preconfigured with many of the tools needed for software development, and because it runs in the AWS Cloud, it can be an especially easy way to access other cloud services. One other handy feature is that your Cloud9 instances automatically stop running after a configurable period of inactivity, which helps reduce costs. +Most steps in this repository will need to be performed from a Linux command prompt. An especially convenient way of doing this is to use AWS Cloud9, a cloud-based Integrated Development Environment (IDE). Cloud9 allows you to edit source files and execute commands from an easy-to-use web interface. It comes pre-configured with many of the tools needed for software development, and because it runs in the AWS Cloud, it can be an especially easy way to access other cloud services. One other handy feature is that your Cloud9 instances automatically stop running after a configurable period of inactivity, which helps reduce costs. ## Create a Cloud9 environment @@ -14,10 +14,10 @@ Create an instance profile called **Cloud9-Developer-Access** 1. Create role policy definition file - ```bash - cat < ec2-trust-policy.json +```bash +cat > ec2-trust-policy.json </ 2. Delete the instance profile and IAM role - ```bash - aws iam delete-instance-profile --instance-profile-name Cloud9-Developer-Access - aws iam delete-role --role-name Cloud9-Developer-Access - ``` +```bash +aws iam delete-instance-profile --instance-profile-name Cloud9-Developer-Access +aws iam delete-role --role-name Cloud9-Developer-Access +```