Skip to content

Commit

Permalink
Deploy Bootstrap and add Metrics (#38)
Browse files Browse the repository at this point in the history
* deploy bootstrap validator

* wip. added bootstrap service. need lb service

* deploy and wait for validator ready. need readme update

* update readme. update progress. fix selector bug

* add metrics

* clean up
  • Loading branch information
gregcusack authored May 1, 2024
1 parent 576851d commit da24112
Show file tree
Hide file tree
Showing 7 changed files with 475 additions and 16 deletions.
12 changes: 6 additions & 6 deletions PROGRESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@
- [ ] RPC nodes
- [ ] Client
- [ ] Create & Deploy Replica Set
- [ ] Bootstrap
- [x] Bootstrap
- [ ] Validator (regular)
- [ ] RPC nodes
- [ ] Client
- [ ] Create & Deploy Services
- [ ] Bootstrap
- [x] Bootstrap
- [ ] Validator (regular)
- [ ] RPC nodes
- [ ] Client
- [ ] Check Bootstrap is deployed and running
- [ ] Build and deploy Load Balancer (sits in front of bootstrap and RPC nodes)
- [x] Check Bootstrap is deployed and running
- [x] Build and deploy Load Balancer (sits in front of bootstrap and RPC nodes)
- [ ] Add metrics
- [ ] Bootstrap
- [x] Bootstrap
- [ ] Validator (regular)
- [ ] RPC nodes
- [ ] Client
Expand Down Expand Up @@ -69,7 +69,7 @@ Above, we start with bootstrap, and then we do validators (regular), and then we
- Use command line flags to set type of client, tx-count, etc

- [ ] Add in kubernetes deployment flags
- [ ] CPU/Memory Requests
- [x] CPU/Memory Requests
- [ ] Node Affinity -> Regions
- [ ] Node Affinity -> Node Type (Equinix/Lumen)

Expand Down
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,52 @@ cargo run --bin cluster --
--tag <docker-image-tag> # e.g. v1
--base-image <base-image> # e.g. ubuntu:20.04
--image-name <docker-image-name> # e.g. cluster-image
```

## Metrics
1) Setup metrics database:
```
cd scripts/
./init-metrics -c <database-name> <metrics-username>
# enter password when promted
```
2) add the following to your `cluster` command from above
```
--metrics-host https://internal-metrics.solana.com # need the `https://` here
--metrics-port 8086
--metrics-db <database-name> # from (1)
--metrics-username <metrics-username> # from (1)
--metrics-password <metrics-password> # from (1)
```


## Kubernetes Cheatsheet
Create namespace:
```
kubectl create ns <namespace>
```

Delete namespace:
```
kubectl delete ns <namespace>
```

Get running pods:
```
kubectl get pods -n <namespace>
```

Get pod logs:
```
kubectl logs -n <namespace> <pod-name>
```

Exec into pod:
```
kubectl exec -it -n <namespace> <pod-name> -- /bin/bash
```

Get information about pod:
```
kubectl describe pod -n <namespace> <pod-name>
```
102 changes: 102 additions & 0 deletions scripts/init-metrics.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env bash
set -e

here=$(dirname "$0")

# https://gist.github.com/cdown/1163649
urlencode() {
declare s="$1"
declare l=$((${#s} - 1))
for i in $(seq 0 $l); do
declare c="${s:$i:1}"
case $c in
[a-zA-Z0-9.~_-])
echo -n "$c"
;;
*)
printf '%%%02X' "'$c"
;;
esac
done
}

usage() {
exitcode=0
if [[ -n "$1" ]]; then
exitcode=1
echo "Error: $*"
fi
cat <<EOF
usage: $0 [-e] [-d] [-c database_name] [username]
Creates a testnet dev metrics database
username InfluxDB user with access to create a new database
-c Manually specify a database to create, rather than read from config file
-d Delete the database instead of creating it
-e Assume database already exists and SOLANA_METRICS_CONFIG is
defined in the environment already
EOF
exit $exitcode
}

useEnv=false
delete=false
createWithoutConfig=false
host="https://internal-metrics.solana.com:8086"
while getopts ":hdec:" opt; do
case $opt in
h)
usage
exit 0
;;
c)
createWithoutConfig=true
netBasename=$OPTARG
;;
d)
delete=true
;;
e)
useEnv=true
;;
*)
usage "unhandled option: $OPTARG"
;;
esac
done
shift $((OPTIND - 1))

if $useEnv; then
[[ -n $SOLANA_METRICS_CONFIG ]] ||
usage "SOLANA_METRICS_CONFIG is not defined in the environment"
else
username=$1
[[ -n "$username" ]] || usage "username not specified"

read -rs -p "InfluxDB password for $username: " password
[[ -n $password ]] || { echo "Password not specified"; exit 1; }
echo

password="$(urlencode "$password")"

query() {
echo "$*"
set -x
curl -XPOST \
"$host/query?u=${username}&p=${password}" \
--data-urlencode "q=$*"
}

query "DROP DATABASE \"$netBasename\""
! $delete || exit 0
query "CREATE DATABASE \"$netBasename\""
query "ALTER RETENTION POLICY autogen ON \"$netBasename\" DURATION 7d"
query "GRANT READ ON \"$netBasename\" TO \"ro\""
query "GRANT WRITE ON \"$netBasename\" TO \"scratch_writer\""

SOLANA_METRICS_CONFIG="host=$host,db=$netBasename,u=scratch_writer,p=topsecret"
fi

exit 0
56 changes: 52 additions & 4 deletions src/k8s_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use {
apps::v1::{ReplicaSet, ReplicaSetSpec},
core::v1::{
Container, EnvVar, PodSecurityContext, PodSpec, PodTemplateSpec, Probe,
ResourceRequirements, Secret, Volume, VolumeMount,
ResourceRequirements, Secret, Service, ServicePort, ServiceSpec, Volume,
VolumeMount,
},
},
apimachinery::pkg::{api::resource::Quantity, apis::meta::v1::LabelSelector},
Expand All @@ -20,10 +21,10 @@ pub enum SecretType {
File { path: PathBuf },
}

fn build_secret(name: &str, data: BTreeMap<String, ByteString>) -> Secret {
fn build_secret(name: String, data: BTreeMap<String, ByteString>) -> Secret {
Secret {
metadata: ObjectMeta {
name: Some(name.to_string()),
name: Some(name),
..Default::default()
},
data: Some(data),
Expand All @@ -32,7 +33,7 @@ fn build_secret(name: &str, data: BTreeMap<String, ByteString>) -> Secret {
}

pub fn create_secret(
secret_name: &str,
secret_name: String,
secrets: BTreeMap<String, SecretType>,
) -> Result<Secret, Box<dyn Error>> {
let data = secrets
Expand Down Expand Up @@ -119,3 +120,50 @@ pub fn create_replica_set(
..Default::default()
})
}

pub fn create_service(
service_name: String,
namespace: String,
label_selector: BTreeMap<String, String>,
is_load_balancer: bool,
) -> Service {
Service {
metadata: ObjectMeta {
name: Some(service_name),
namespace: Some(namespace),
..Default::default()
},
spec: Some(ServiceSpec {
selector: Some(label_selector),
type_: if is_load_balancer {
Some("LoadBalancer".to_string())
} else {
None
},
cluster_ip: if is_load_balancer {
None
} else {
Some("None".to_string())
},
ports: Some(vec![
ServicePort {
port: 8899, // RPC Port
name: Some("rpc-port".to_string()),
..Default::default()
},
ServicePort {
port: 8001, //Gossip Port
name: Some("gossip-port".to_string()),
..Default::default()
},
ServicePort {
port: 9900, //Faucet Port
name: Some("faucet-port".to_string()),
..Default::default()
},
]),
..Default::default()
}),
..Default::default()
}
}
Loading

0 comments on commit da24112

Please sign in to comment.