Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deploy Bootstrap and add Metrics #38

Merged
merged 6 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit typo

Suggested change
# enter password when promted
# enter password when prompted

```
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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely doesn't need to be done in this PR, but would it be easier for maintenance for this to be done through a separate little rust binary in this repo?

Copy link
Collaborator Author

@gregcusack gregcusack May 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya i can do that. what is the benefit? Just less bash code? and since it doesn't change we can just use a binary?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I was wondering where we draw the line between RIIR and Keep It In Bash (KIIB??)... This could definitely stay as a bash script, which is why my comment was a question. Feel free to disregard!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh yes fair enough! i do like the idea of putting it in rust just to keep it somewhat uniform.

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