diff --git a/.gitignore b/.gitignore index 640c410..69b0d86 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +apache-cassandra + +data + # Ignore the .env files containing environment variables .env .env.cassandra1 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b950918 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +# Use the official Cassandra 4.1.3 image +FROM cassandra:4.1.3 + +# Environment variables to configure Cassandra +ENV CASSANDRA_CLUSTER_NAME=TestCluster +ENV CASSANDRA_NUM_TOKENS=256 +ENV CASSANDRA_DC=DC1 +ENV CASSANDRA_RACK=RAC1 + +# Create directory for dump files +RUN mkdir -p /dump + +# Copy the CQL script to create the keyspace and tables +COPY data/dev_keyspace_schema.cql /docker-entrypoint-initdb.d/dev_keyspace_schema.cql + +# Copy the setup script +COPY scripts/setup.sh /setup.sh +RUN chmod +x /setup.sh + +# Set the entrypoint +ENTRYPOINT ["/setup.sh"] + +# Expose Cassandra ports +EXPOSE 7000 7001 7199 9042 9160 + +# Add health check +HEALTHCHECK --interval=30s --timeout=10s --retries=5 CMD cqlsh -e "DESCRIBE KEYSPACES" || exit 1 diff --git a/README.md b/README.md new file mode 100644 index 0000000..38f17f6 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +dump: + +dump requires nodetool +in prod, nodetool is in /usr/bin/ + +in dev environment, cassandra has been installed manually and nodetool is not in the path + +* dev should be aliegned to prod + + + +# DOCKER + +aggiungere a /etc/host l'entry: + +127.0.0.1 cassandra + +start composer: +`docker compose up --build` + +check status: +`docker exec -it cassandra-cassandra-1 nodetool status` + + +run a single service: +* cassandra1: `docker-compose up cassandra-cassandra1 --build` +* cassandra2: `docker-compose up cassandra-cassandra2 --build` +* ,... + +open bash on server + +* cassandra1: `docker exec -it cassandra-cassandra1 /bin/sh` +* cassandra2: `docker exec -it cassandra-cassandra2 /bin/sh` +* cassandra3: `docker exec -it cassandra-cassandra3 /bin/sh` + + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d36fdf0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,74 @@ +version: '3.8' + +services: + cassandra1: + build: . + container_name: cassandra1 + env_file: + - .env + environment: + - CASSANDRA_BROADCAST_ADDRESS=cassandra1 + - PRIMARY_NODE=true + volumes: + - ./data/dumps/node1:/dump + - ./data/volumes/node1:/var/lib/cassandra + - ./logs/node1:/var/log/cassandra + ports: + - "9042:9042" + networks: + - cassandra-net + healthcheck: + test: ["CMD", "cqlsh", "-e", "DESCRIBE KEYSPACES"] + interval: 30s + timeout: 10s + retries: 5 + + cassandra2: + build: . + container_name: cassandra2 + env_file: + - .env + environment: + - CASSANDRA_BROADCAST_ADDRESS=cassandra2 + - PRIMARY_NODE=false + volumes: + - ./data/dumps/node2:/dump + - ./data/volumes/node2:/var/lib/cassandra + - ./logs/node2:/var/log/cassandra + networks: + - cassandra-net + depends_on: + cassandra1: + condition: service_healthy + healthcheck: + test: ["CMD", "cqlsh", "-e", "DESCRIBE KEYSPACES"] + interval: 30s + timeout: 10s + retries: 5 + + cassandra3: + build: . + container_name: cassandra3 + env_file: + - .env + environment: + - CASSANDRA_BROADCAST_ADDRESS=cassandra3 + - PRIMARY_NODE=false + volumes: + - ./data/dumps/node3:/dump + - ./data/volumes/node3:/var/lib/cassandra + - ./logs/node3:/var/log/cassandra + networks: + - cassandra-net + depends_on: + cassandra2: + condition: service_healthy + healthcheck: + test: ["CMD", "cqlsh", "-e", "DESCRIBE KEYSPACES"] + interval: 30s + timeout: 10s + retries: 5 + +networks: + cassandra-net: + driver: bridge diff --git a/dump.sh b/dump.sh new file mode 100755 index 0000000..4f469df --- /dev/null +++ b/dump.sh @@ -0,0 +1,65 @@ +```sh +#!/bin/bash + +# Configuration +KEYSPACE="dev_keyspace" +LOCAL_DIR="data/dumps" +NODES=("cass-dev-01" "cass-dev-02" "cass-dev-03") +SSH_USER="alfredo.oliviero" +SNAPSHOT_PATH="/data/$KEYSPACE" +NODETOOL="/home/alfredo.oliviero/apache-cassandra-4.1.3/bin/nodetool" +CQLSH="/home/alfredo.oliviero/apache-cassandra-4.1.3/bin/cqlsh" +CQLSH_IP="10.1.28.100" + +# Function to create snapshot and copy it locally +snapshot_and_copy() { + NODE=$1 + NODE_NAME=$2 + echo "Removing old snapshots on $NODE" + ssh $SSH_USER@$NODE "$NODETOOL clearsnapshot --all -- $KEYSPACE" + + echo "Creating snapshot on $NODE" + ssh $SSH_USER@$NODE "$NODETOOL snapshot $KEYSPACE" + + # Find the snapshot path and copy it if it exists + TABLES=$(ssh $SSH_USER@$NODE "ls $SNAPSHOT_PATH") + rm -rf $LOCAL_DIR/$NODE_NAME + for TABLE in $TABLES; do + SNAPSHOT_DIR="$SNAPSHOT_PATH/$TABLE/snapshots" + if ssh $SSH_USER@$NODE "test -d $SNAPSHOT_DIR"; then + echo "Copying snapshot for table $TABLE from $NODE to $LOCAL_DIR/$NODE_NAME/$TABLE" + mkdir -p $LOCAL_DIR/$NODE_NAME/$TABLE + rsync -C -r $SSH_USER@$NODE:$SNAPSHOT_DIR/ $LOCAL_DIR/$NODE_NAME/$TABLE + else + echo "No snapshot found for table $TABLE on $NODE" + fi + done +} + +# Export keyspace schema from the first node +echo "Exporting keyspace schema for $KEYSPACE from ${NODES[0]}" +ssh $SSH_USER@${NODES[0]} "$CQLSH $CQLSH_IP -e \"DESCRIBE KEYSPACE $KEYSPACE;\"" > data/dev_keyspace_schema.cql + +# Create local directory if it doesn't exist +mkdir -p $LOCAL_DIR + +# Perform snapshot and copy for each node in parallel +NODE_INDEX=1 +for NODE in "${NODES[@]}"; do + snapshot_and_copy $NODE "node$NODE_INDEX" & + NODE_INDEX=$((NODE_INDEX + 1)) +done + +# Wait for all background jobs to finish +wait + +echo "Backup completed." + +# Display sizes of dumps +echo "Total size of each node dump directory:" +du -sh data/dumps/node1 +du -sh data/dumps/node2 +du -sh data/dumps/node3 + +echo "Total size of all dump directories:" +du -sh data/dumps/* diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100644 index 0000000..a57e1f7 --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +KEYSPACE="dev_keyspace" + +# Start Cassandra in the background +cassandra -R & + +# Wait for Cassandra to be ready +echo "Waiting for Cassandra to start..." +until cqlsh -e "SHOW HOST" > /dev/null 2>&1; do + sleep 2 +done + +if [ "$PRIMARY_NODE" = "true" ]; then + # Check if the keyspace exists + echo "Checking if keyspace $KEYSPACE exists..." + if ! cqlsh -e "DESCRIBE KEYSPACE $KEYSPACE;" > /dev/null 2>&1; then + echo "Keyspace $KEYSPACE does not exist. Creating keyspace and tables..." + cqlsh -f /docker-entrypoint-initdb.d/dev_keyspace_schema.cql + else + echo "Keyspace $KEYSPACE already exists. Skipping creation." + fi +fi + +# Copy snapshots to the Cassandra data directory +echo "Copying snapshots..." +cp -r $DUMP_DIR/* /var/lib/cassandra/data/ + +# Import snapshots into the Cassandra data directory +echo "Importing snapshots..." +for table in $(ls $DUMP_DIR); do + nodetool import $KEYSPACE $table +done + +# Keep the container running +tail -f /dev/null