Skip to content

Commit d9cd827

Browse files
committed
Add tablets demo with UI
1 parent 70f8557 commit d9cd827

25 files changed

+1223
-1
lines changed

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
# ScyllaDB 1 million operations/second DEMOs
22

3-
This repository contains Terraform configuration files for setting up a 1 million operations/second DEMO with different flavours of ScyllaDB:
3+
Set up 1 million operations/second DEMO with different flavours of ScyllaDB:
44
* [1 million operations/second with ScyllaDB Cloud](/scylladb-cloud)
55
* [1 million operations/second with ScyllaDB Enterprise](/scylladb-enterprise)
66

7+
Scale a cluster from 3 to 6 nodes with Tablets enabled:
8+
* [ScyllaDB Tablets DEMO on AWS](/tablets-scaling)
9+
710
## Usage
811
1. Clone the repository
912
```

tablets-scaling/README.md

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# ScyllaDB Tablets DEMO
2+
This project walks you through the following scenario:
3+
1. Starting off with 3 ScyllaDB nodes
4+
1. Spike in the number of requests
5+
1. Add 3 additional ScyllaDB nodes to handle requests
6+
1. Request volume goes down
7+
1. Remove 3 nodes
8+
9+
## Requirements
10+
* AWS account
11+
* [Terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)
12+
* [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html)
13+
* Python
14+
15+
## Usage
16+
1. Clone the repository
17+
```
18+
git clone https://github.com/scylladb/1m-ops-demo.git
19+
cd 1m-ops-demo/tablets/scaling
20+
```
21+
1. Set your variables in `variables.tf`
22+
1. Set up EC2 instances on AWS (takes 4+ minutes)
23+
```bash
24+
terraform init
25+
terraform plan
26+
terraform apply
27+
```
28+
1. Start Python server
29+
30+
Install requirements in a new environment, and start the server:
31+
```
32+
virtualenv env
33+
source env/bin/activate
34+
pip install -r requirements.txt
35+
python app.py
36+
```
37+
38+
Output:
39+
```
40+
* Serving Flask app 'app'
41+
* Debug mode: off
42+
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
43+
* Running on all addresses (0.0.0.0)
44+
* Running on http://127.0.0.1:5000
45+
* Running on http://192.168.0.47:5000
46+
```
47+
1. Open the DEMO UI
48+
```
49+
http://127.0.0.1:5000
50+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
- name: Start cluster
3+
hosts: original_cluster
4+
become: True
5+
6+
tasks:
7+
- name: Start ScyllaDB Service
8+
ansible.builtin.systemd_service:
9+
name: scylla-server.service
10+
state: started
11+
12+
- name: Waiting for CQL port readiness
13+
wait_for:
14+
port: 9042
15+
host: 127.0.0.1
16+
connect_timeout: 3
17+
delay: 3
18+
sleep: 10
19+
timeout: 1200
20+
state: present
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
- name: Restore snapshot
3+
hosts: original_cluster[0]
4+
become: True
5+
tasks:
6+
- name: Create schema
7+
ansible.builtin.shell: 'cqlsh -f /home/ubuntu/schema.cql'
8+
- name: Restore snapshot
9+
ansible.builtin.shell: bash /home/ubuntu/restore_snapshot.sh
10+
- name: Nodetool refresh
11+
ansible.builtin.shell: 'nodetool refresh keyspace1 standard1'
12+

tablets-scaling/ansible/3_stress.yml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
- name: Start loader
3+
hosts: stress
4+
become: True
5+
6+
tasks:
7+
- name: Start CQL Stress
8+
ansible.builtin.systemd_service:
9+
name: cql-stress.service
10+
state: started
11+
daemon_reload: True
12+
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
- name: Scale out
3+
hosts: scale_out
4+
become: True
5+
6+
tasks:
7+
- name: Start ScyllaDB Service
8+
ansible.builtin.systemd_service:
9+
name: scylla-server.service
10+
state: started
11+
12+
- name: Waiting for CQL port readiness
13+
wait_for:
14+
port: 9042
15+
host: 127.0.0.1
16+
connect_timeout: 3
17+
delay: 3
18+
sleep: 10
19+
timeout: 1200
20+
state: present
21+
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
- name: Stop loader
3+
hosts: stress
4+
become: True
5+
6+
tasks:
7+
- name: Stop CQL Stress
8+
ansible.builtin.systemd_service:
9+
name: cql-stress.service
10+
state: stopped
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
- name: Scale in
3+
hosts: scale_out
4+
become: True
5+
6+
tasks:
7+
- name: Decommission node
8+
ansible.builtin.shell:
9+
cmd: nodetool decommission
10+
11+
- name: Stop ScyllaDB
12+
ansible.builtin.systemd_service:
13+
name: scylla-server.service
14+
state: stopped
15+
16+
- name: Wipe data-dir
17+
ansible.builtin.shell:
18+
cmd: 'rm -fr /var/lib/scylla/data/* ; find /var/lib/scylla -type f -delete'
19+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
sudo apt-get install unzip
4+
cd /var/lib/scylla/data/keyspace1/standard1-*/upload
5+
wget https://scylla-devrel.s3.us-east-2.amazonaws.com/tablets-sample-data/scylla.zip
6+
unzip scylla.zip
7+
rm scylla.zip
8+
sudo chown -R scylla:scylla *

tablets-scaling/app.py

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
from flask import Flask, render_template_string
2+
from flask_socketio import SocketIO
3+
import os
4+
import subprocess
5+
import configparser
6+
7+
app = Flask(__name__)
8+
socketio = SocketIO(app)
9+
10+
env = os.environ.copy()
11+
env["PYTHONUNBUFFERED"] = "1"
12+
env["ANSIBLE_FORCE_COLOR"] = "1"
13+
14+
def read_file_to_string(file_path):
15+
"""
16+
Reads the file and returns it as a string.
17+
18+
:param file_path: Path to the file
19+
:return: The contents of the file as a string
20+
"""
21+
try:
22+
with open(file_path, 'r') as file:
23+
content = file.read()
24+
return content
25+
except FileNotFoundError:
26+
print(f"Error: File not found at {file_path}")
27+
return ""
28+
except Exception as e:
29+
print(f"An error occurred: {e}")
30+
return ""
31+
32+
@app.route("/")
33+
def index():
34+
return render_template_string(read_file_to_string("index.html"))
35+
36+
# Global process variable
37+
globals()["process"] = None
38+
39+
def run_ansible_playbook(playbook_path):
40+
playbook_cmd = ["ansible-playbook", playbook_path]
41+
process = subprocess.Popen(playbook_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=ansible_folder)
42+
for line in process.stdout:
43+
socketio.emit("playbook_output", {"output": line})
44+
socketio.sleep(0)
45+
process.wait()
46+
47+
@socketio.on("original_cluster")
48+
def handle_original_cluster():
49+
run_ansible_playbook(ansible_folder + "/1_original_cluster.yml")
50+
51+
@socketio.on("sample_data")
52+
def handle_sample_data():
53+
run_ansible_playbook(ansible_folder + "/2_restore_snapshot.yml")
54+
55+
@socketio.on("start_stress")
56+
def handle_start_stress():
57+
run_ansible_playbook(ansible_folder + "/3_stress.yml")
58+
59+
@socketio.on("scale_out")
60+
def handle_scale_out():
61+
run_ansible_playbook(ansible_folder + "/4_scale_out.yml")
62+
63+
@socketio.on("stop_stress")
64+
def handle_stop_stress():
65+
run_ansible_playbook(ansible_folder + "/5_stop_stress.yml")
66+
67+
@socketio.on("scale_in")
68+
def handle_scale_in():
69+
run_ansible_playbook(ansible_folder + "/6_scale_in.yml")
70+
71+
72+
def parse_ansible_inventory(inventory_file):
73+
config = configparser.ConfigParser(allow_no_value=True)
74+
config.optionxform = str # Preserve case sensitivity
75+
76+
# Read the inventory file
77+
config.read(inventory_file)
78+
79+
inventory = {}
80+
for section in config.sections():
81+
hosts = {}
82+
for item in config.items(section):
83+
hostname, *variables = item[0].split()
84+
host_vars = dict(var.split('=') for var in variables)
85+
hosts[hostname] = host_vars
86+
inventory[section] = hosts
87+
88+
return inventory
89+
90+
if __name__ == "__main__":
91+
program_cwd = os.path.dirname(os.path.abspath(__file__))
92+
ansible_folder = os.path.join(program_cwd, "ansible")
93+
94+
socketio.run(app, host='0.0.0.0', port=5000, allow_unsafe_werkzeug=True)
95+

tablets-scaling/data.tf

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
data "aws_availability_zones" "azs" {}
2+
3+
data "aws_caller_identity" "current" {}
4+
5+
data "aws_region" "current" {}
6+
7+
data "aws_instances" "scylladb" {
8+
filter {
9+
name = "tag:Project"
10+
values = [var.custom_name]
11+
}
12+
13+
filter {
14+
name = "tag:Type"
15+
values = ["Scylla"]
16+
}
17+
}
18+
data "aws_vpc" "selected" {
19+
id = aws_vpc.custom_vpc.id
20+
}

0 commit comments

Comments
 (0)