# index.html.md # Charmed Apache Cassandra documentation #### WARNING The charm is under active development and is not yet published on Charmhub. APIs, configuration options, and integration endpoints may change. Charmed Apache Cassandra is an open-source **Juju charm** that automates the deployment, scaling, configuration and operations of [Apache Cassandra](https://cassandra.apache.org/) clusters across clouds, virtual machines and bare metal, using the [Juju](https://juju.is/) orchestration framework. [Apache Cassandra](https://cassandra.apache.org/) is a free and open-source database management system designed to handle large volumes of data across multiple commodity servers, providing high availability with no single point of failure. The charm aims to simplify Cassandra operations from [Day 0 to Day 2](https://codilime.com/blog/day-0-day-1-day-2-the-software-lifecycle-in-the-cloud-age/), offering secure defaults, integration interfaces, and lifecycle automation. ## In this documentation This documentation contains only basic information and will be expanded later. - **Tutorial** takes you step-by-step from bootstrapping a controller to deploying, securing, and scaling a cluster. - **How-to guides** cover deploying and scaling a cluster, enabling TLS encryption, and setting up monitoring. - **Reference** contains contact information. ## How this documentation is organized This documentation uses the [Diátaxis](https://diataxis.fr/) documentation structure. - The Tutorial takes you step-by-step through the initial Charmed Apache Cassandra setup and usage. - How-to guides assume you have basic familiarity with Apache Cassandra and Juju. ## Project and community Charmed Apache Cassandra is a member of the Ubuntu family. It’s an open source project that warmly welcomes community contributions, suggestions, fixes and constructive feedback. - [Juju](https://juju.is/) - [Charmhub](https://charmhub.io/) - [Apache Cassandra](https://cassandra.apache.org/) - [Canonical Data solutions](https://canonical.com/data) - [Report issues](https://github.com/canonical/cassandra-operator/issues) - [Contribute](https://github.com/canonical/cassandra-operator/blob/main/CONTRIBUTING.md) ## License and trademarks Apache®, Apache Cassandra®, and the Apache Cassandra logo are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. The Charmed Apache Cassandra operator is free software, distributed under the Apache Software License, version 2.0. See [LICENSE](https://github.com/canonical/cassandra-operator/blob/main/LICENSE) for more information. # index.html.md # How-to guides These guides provide step-by-step instructions for common operational tasks with Charmed Apache Cassandra. ## Deployment - [How to deploy Charmed Apache Cassandra](https://canonical.com/data/cassandra/docs/latest//how-to/deploy.md) - Deploy a cluster and connect to it with `cqlsh` ## Operations - [How to manage units](https://canonical.com/data/cassandra/docs/latest//how-to/manage-units.md) - Scale the cluster up and down and verify the cluster topology ## Security - [How to enable TLS encryption](https://canonical.com/data/cassandra/docs/latest//how-to/encryption.md) - Enable TLS encryption for secure communications between nodes - [How to manage passwords](https://canonical.com/data/cassandra/docs/latest//how-to/manage-passwords.md) - Retrieve and rotate the `operator` password ## Observability - [How to set up monitoring](https://canonical.com/data/cassandra/docs/latest//how-to/monitoring.md) - Set up monitoring with the Canonical Observability Stack (COS) # index.html.md # How to deploy Charmed Apache Cassandra This guide walks you through deploying the **IAAS/VM** operator with the Juju CLI and verifying the deployment by connecting to the cluster. You will: 1. Set up a Juju controller 2. Set up a Juju model 3. Deploy Charmed Apache Cassandra 4. Verify the deployment by connecting to the cluster If you already have a Juju controller and a Juju model, you can skip the associated steps. ## Juju controller setup Make sure you have a Juju controller accessible from your local environment using the [Juju client snap](https://snapcraft.io/juju). List available controllers: ```shell juju list-controllers ``` Make sure that the controller’s back-end cloud is **not** Kubernetes-based. To retrieve the cloud list: ```shell juju list-clouds ``` To switch to another controller if needed: ```shell juju switch ``` If there are no suitable controllers, create a new one: ```shell juju bootstrap ``` where `` is the cloud to deploy the controller to (for example, `localhost` for a LXD cloud). For more information on how to set up a new cloud, see the [How to manage clouds](https://canonical.com/juju/docs/juju-cli/latest/howto/manage-clouds/index.html) guide in Juju documentation. ## Juju model setup Switch to an existing Juju model: ```shell juju switch ``` Or create a new Juju model: ```shell juju add-model ``` ## Deploy Charmed Apache Cassandra #### NOTE Charmed Apache Cassandra is still under active development and is only available on the `5/edge` channel. Due to the lack of a stable release it is not yet recommended for production environments. To deploy Charmed Apache Cassandra: ```shell juju deploy cassandra -n --config profile= --channel 5/edge ``` The charm supports two profiles: * `production` (default) — tunes Cassandra for maximum performance, allocating up to 8 GB RAM per unit for the Java heap. More RAM might be needed for read caches, bloom filters, etc. * `testing` — minimises resource requirements for very small, non-production test and staging clusters To maintain high availability of the data, `3+` units are recommended. #### WARNING Typical `production` profile servers need at least 32 GB of ECC RAM per unit. See [Apache Cassandra documentation](https://cassandra.apache.org/doc/stable/cassandra/managing/operating/hardware.html) for more details. To change the profile on a running deployment: ```shell juju config cassandra profile=testing ``` Monitor the status of the deployment: ```shell watch juju status ``` During bootstrap, units briefly show maintenance and waiting statuses such as `installing Cassandra`, `waiting for Cassandra to start`, and `waiting for cluster to start`. The deployment should be complete once all the units show `active` and `idle` status. ## Test by connecting Authentication is enabled by default. To retrieve the password for the default `operator` user: ```shell juju show-secret --reveal "cassandra-peers..app" --format json \ | jq -r '.[].content.Data."operator-password"' ``` Once you have the password, connect to the cluster. Install `cqlsh` locally: ```shell sudo snap install cqlsh ``` Then connect to the cluster: ```shell cqlsh -u operator -p "" ``` Alternatively, the `charmed-cassandra` snap bundles the same client as `charmed-cassandra.cqlsh`.
Output example ```text [cqlsh 5.0.1 | Cassandra 5.0.5 | CQL spec 3.4.7 | Native protocol v5] Use HELP for help. operator@cqlsh> ``` If you want to test it further, run some commands in the cqlsh prompt: ```text operator@cqlsh> CREATE KEYSPACE hello ... WITH replication = { ... 'class': 'SimpleStrategy', ... 'replication_factor': 1 ... }; operator@cqlsh> DESCRIBE KEYSPACE hello; CREATE KEYSPACE hello WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'} AND durable_writes = true; ```
# index.html.md # How to set up monitoring This guide includes step-by-step instructions on how to set up monitoring with the [Canonical Observability Stack](https://charmhub.io/topics/canonical-observability-stack). Additionally, the charm provides integration with the [Canonical Observability Stack](https://documentation.ubuntu.com/observability/). ## Enable monitoring Deploy the `cos-lite` bundle in a Kubernetes environment. This can be done by following the [deployment tutorial](https://documentation.ubuntu.com/observability/track-3.0/tutorial/cos-lite-microk8s-sandbox/). Since the Charmed Apache Cassandra is deployed directly on a cloud infrastructure environment, it is needed to offer the endpoints of the COS relations. The [offers-overlay](https://github.com/canonical/cos-lite-bundle/blob/main/overlays/offers-overlay.yaml) can be used, and this step is shown in the COS tutorial. #### NOTE If you use [microk8s](https://microk8s.io/) with the strictly confined Juju snap, make sure to install the **strictly confined** microk8s snap (e.g. from the `1.35-strict/stable` channel). The classic microk8s snap is not supported by Juju. ### Offer interfaces via the COS controller Switch to COS K8s environment and offer COS interfaces to be cross-model related with Charmed Apache Cassandra VM model: ```shell juju switch : juju offer grafana:grafana-dashboard grafana-dashboards juju offer loki:logging loki-logging juju offer prometheus:receive-remote-write prometheus-receive-remote-write ``` ### Consume offers via the Apache Cassandra model Switch back to the Charmed Apache Cassandra model, find offers and relate with them: ```shell juju switch : juju find-offers : ``` A similar output should appear, if `k8s` is the K8s controller name and `COS` the model where `cos-lite` has been deployed: ```shell Store URL Access Interfaces k8s admin/cos.grafana-dashboards admin grafana_dashboard:grafana-dashboard k8s admin/cos.loki-logging admin loki_push_api:logging k8s admin/cos.prometheus-receive-remote-write admin prometheus-receive-remote-write:receive-remote-write ... ``` Consume offers to be reachable in the current model: ```shell juju consume :admin/.prometheus-receive-remote-write juju consume :admin/.loki-logging juju consume :admin/.grafana-dashboards ``` Now, deploy `grafana-agent` (subordinate charm) and relate it with Charmed Apache Cassandra: ```shell juju deploy grafana-agent juju integrate cassandra:cos-agent grafana-agent ``` Finally, relate `grafana-agent` with consumed COS offers: ```shell juju integrate grafana-agent grafana-dashboards juju integrate grafana-agent loki-logging juju integrate grafana-agent prometheus-receive-remote-write ``` Wait for all components to settle down on a `active/idle` state on both models, e.g. `` and ``. After this is complete, the monitoring COS stack should be up and running and ready to be used. ### Connect Grafana web interface To connect to the Grafana web interface, follow the [Browse dashboards](https://documentation.ubuntu.com/observability/track-3.0/tutorial/cos-lite-microk8s-sandbox/#browse-dashboards) section of the “Getting started with COS Lite on MicroK8s” tutorial. ```shell juju run grafana/leader get-admin-password --model : ``` ## Alerts and dashboards This guide shows you how to integrate an existing set of rules and/or dashboards to your Charmed Apache Cassandra deployment to be consumed with the [Canonical Observability Stack (COS)](https://documentation.ubuntu.com/observability/). To do so, we will sync resources stored in a git repository to COS Lite. ### Prerequisites Deploy the `cos-lite` bundle in a Kubernetes environment and integrate Charmed Apache Cassandra to the COS offers, as shown in the [How to Enable Monitoring](#how-to-monitoring-enable-monitoring) guide. This guide will refer to the models that charms are deployed into as: * `` for the model containing observability charms (and deployed on K8s) * `` for the model containing Charmed Apache Cassandra and other optional charms (e.g. TLS-certificates operators, `grafana-agent`, `data-integrator`, etc.). ### Create a repository with a custom monitoring setup Create an empty git repository, or in an existing one, save your alert rules and dashboard models under the ``, `` and `` folders. If you want a primer to rule writing, refer to the [Prometheus documentation](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/). Then, push your changes to the remote repository. ### Deploy the COS configuration charm Deploy the [COS configuration](https://charmhub.io/cos-configuration-k8s) charm in the `` model: ```shell juju deploy cos-configuration-k8s cos-config \ --config git_repo= \ --config git_branch= ``` The COS configuration charm keeps the monitoring stack in sync with our repository, by forwarding resources to Prometheus, Loki and Grafana. Refer to the [documentation](https://charmhub.io/cos-configuration-k8s/configure) for all configuration options, including how to access a private repository.
\\\\ Adding, updating or deleting an alert rule or a dashboard in the repository will be reflected in the monitoring stack. #### NOTE You need to manually refresh `cos-config`’s local repository with the *sync-now* action if you do not want to wait for the next [update-status event](https://documentation.ubuntu.com/juju/3.6/reference/hook/#update-status) to pull the latest changes. ### Forward the rules and dashboards The path to the resource folders can be set after deployment: ```shell juju config cos-config \ prometheus_alert_rules_path= \ loki_alert_rules_path= \ grafana_dashboards_path= ``` Then, integrate the charm with the COS operators to forward the rules and dashboards: ```shell juju integrate cos-config:prometheus-config prometheus:metrics-endpoint juju integrate cos-config:grafana-dashboards grafana:grafana-dashboard juju integrate cos-config:loki-config loki:logging ``` After this is complete, the monitoring COS stack should be up and ready to fire alerts based on our rules. As for the dashboards, they should be available in the Grafana interface. ### Pre‑built dashboards and alerting rules This repository already contains a set of ready‑to‑use monitoring assets: * **Grafana dashboard:** `src/grafana_dashboards/grafana-dashboard.json` * **Loki alerting rules:** `src/alert_rules/loki/loki_alerts.yaml` * **Prometheus alerting rules:** `src/alert_rules/prometheus/prometheus_alerts.yaml` Point the corresponding `*_path` configuration options to these files (or their parent directories) if you would like COS to pick them up automatically. ### Conclusion In this guide, we enabled monitoring on a Charmed Apache Cassandra deployment and integrated alert rules and dashboards by syncing a git repository to the COS stack. # index.html.md # How to enable TLS encryption This guide includes step-by-step instructions on how to enable TLS encryption for peer-to-peer and client-to-node communication in a Charmed Apache Cassandra cluster. This charm implements the **Requirer** side of the [tls-certificates](https://charmhub.io/integrations/tls-certificates) relation. Therefore, any charm implementing the **Provider** side could be used. All units within a cluster share the same CA certificate file, but each unit has a distinct private key. ## Prerequisites For this guide, we will need an active Charmed Apache Cassandra application. Follow the [How to deploy Charmed Apache Cassandra](https://canonical.com/data/cassandra/docs/latest//how-to/deploy.md#how-to-deploy) guide to set up the environment. ## Enable TLS encryption for peer-to-peer communication To enable peer-to-peer TLS encryption, you should first deploy a TLS certificates Provider charm. For this guide, we will be using the `self-signed-certificates` charm. #### WARNING Using self-signed certificates is not recommended for production systems. Instead follow your organisations best-practices for managing TLS certificates. Please refer to [this post](https://charmhub.io/topics/security-with-x-509-certificates) for an overview of the TLS certificates Providers charms and some guidance on how to choose the right charm for your use case. To deploy the `self-signed-certificates` application: ```shell juju deploy self-signed-certificates --channel=edge --config ca-common-name="Test CA" ``` To enable peer-to-peer TLS encryption with Charmed Apache Cassandra, integrate the Charmed Apache Cassandra application to the `tls-certificates` provider application via the `peer-certificates` relation interface: ```shell juju integrate cassandra:peer-certificates self-signed-certificates ``` While certificates are being issued and distributed, units show waiting and maintenance statuses such as `waiting for internal TLS setup` and `waiting for peer tls rotation to complete`. Once the process completes, units return to `active/idle`. ## Enable TLS encryption for client-to-node communication To enable client-to-node TLS encryption, integrate the Charmed Apache Cassandra application to the `tls-certificates` provider application via the `client-certificates` relation interface: ```shell juju integrate cassandra:client-certificates self-signed-certificates ``` While certificates are being issued and distributed, units show waiting and maintenance statuses such as `waiting for TLS setup` and `waiting for client tls rotation to complete`. Once the process completes, units return to `active/idle`. ## Connect to the cluster Authentication is enabled by default. To retrieve the password for the default `operator` user: ```shell juju show-secret --reveal "cassandra-peers..app" --format json \ | jq -r '.[].content.Data."operator-password"' ``` ### Verify client TLS First, attempt to connect **without specifying TLS certificates**: ```shell cqlsh -u operator -p "" ``` This should result in an error: ```text Warning: Using a password on the command line interface can be insecure. Recommendation: use the credentials file to securely provide the password. Connection error: ('Unable to connect to any servers', {':9042': ConnectionResetError(104, 'Connection reset by peer')}) ``` This confirms that Apache Cassandra requires a secure TLS connection. ### Retrieving the root CA Fetch the root CA from the self-signed certificate operator: ```shell juju run self-signed-certificates/0 get-ca-certificate --format json \ | jq -r '."self-signed-certificates/0".results."ca-certificate"' > ca.cert ``` The CA needs to be used to verify the certificate provided by the Apache Cassandra servers in the TLS handshake. ### Connecting using `cqlsh` First of all, install the `charmed-cassandra` snap in the local environment ```shell sudo snap install charmed-cassandra --edge ``` The `charmed-cassandra` snap bundles also the `cqlsh` client to be used to connect to the Apache Cassandra endpoint. Since the snap is strictly confined, the `ca.cert` file needs to be copied to a location that is readable by the snap processes, e.g. `/var/snap/charmed-cassandra/current/etc/cassandra/` where configuration files are generally stored. In the same location, also create a `cqlshrc` configuration file for `cqlsh`: ```ini [authentication] username = operator password = [connection] hostname = port = 9042 [ssl] certfile = /var/snap/charmed-cassandra/current/etc/cassandra/ca.cert validate = true ``` #### NOTE Make sure the `cqlshrc` file is only readable by your user, otherwise `cqlsh` will refuse to use the credentials stored in it: ```shell sudo chown $USER /var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc sudo chmod 600 /var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc ``` Connect to Apache Cassandra with: ```shell charmed-cassandra.cqlsh --ssl --cqlshrc /var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc ``` The `cqlsh` client should connect and show the prompt where CQL queries can be run. ## (Optional) Rotate certificates When the TLS certificates Provider charm renews the certificates (for example, when they are close to expiry, or when the CA is rotated), the Cassandra charm picks up the new certificates automatically. During the rotation, units show maintenance statuses such as `waiting for peer tls rotation to complete` or `waiting for client tls rotation to complete`, and return to `active/idle` once the new certificates are in place. No manual action is required. ## Disable TLS encryption To disable TLS encryption, remove the relations with the `tls-certificates` provider application: ```shell juju remove-relation cassandra:peer-certificates self-signed-certificates juju remove-relation cassandra:client-certificates self-signed-certificates ``` #### NOTE Removing the relations causes a rolling restart of the units as they switch back to unencrypted communication. # index.html.md # How to manage units This guide includes step-by-step instructions on how to scale a Charmed Apache Cassandra cluster by adding or removing units, and how to verify the cluster topology. For general Juju unit management process, see the [Juju documentation](https://canonical.com/juju/docs/juju-cli/3.6/howto/manage-units/). The charm automates most of the node management operations, ensuring that the cluster topology remains consistent and data is replicated correctly. ## Scaling ### Add units To scale-out the Charmed Apache Cassandra application, add more units: ```shell juju add-unit cassandra -n ``` See the `juju add-unit` [command reference](https://canonical.com/juju/docs/juju-cli/latest/reference/juju-cli/list-of-juju-cli-commands/add-unit/). The implementation of `add-unit` allows adding multiple units at once, but unit initialization occurs one at a time: each new unit bootstraps and joins the cluster before the next one starts. Expect the total time to grow linearly with the number of added units. Monitor the progress with: ```shell juju status ``` New units show `waiting for cluster to start` while they join, and become `active/idle` once they are full members of the cluster. ### Remove units To decrease the number of Apache Cassandra nodes, remove some existing units from the Charmed Apache Cassandra application: ```shell juju remove-unit ``` See the `juju remove-unit` [command reference](https://canonical.com/juju/docs/juju-cli/latest/reference/juju-cli/list-of-juju-cli-commands/remove-unit/). #### NOTE Only one unit can be removed at a time. Support for removing multiple units simultaneously is not yet available. #### CAUTION Before removing a unit, check the replication factor of your keyspaces. If removing the unit brings the number of nodes below the replication factor of a keyspace, that keyspace may become unavailable or lose data. A Cassandra cluster is also called a *ring*: a peer-to-peer set of nodes where every node is equal and can serve the same functionality as any other. For more details, see the [Cassandra architecture documentation](https://cassandra.apache.org/doc/latest/cassandra/architecture/dynamo.html). During removal, the charm decommissions the node: data stored on the removed unit is streamed to the remaining nodes before the node leaves the ring, so no data is lost. ## Admin utility scripts Apache Cassandra ships with the `nodetool` utility to do various administrative tasks such as checking the cluster status, draining a node, or repairing keyspaces. The most important commands are exposed via the [Charmed Apache Cassandra snap](https://snapcraft.io/charmed-cassandra), accessible via `charmed-cassandra.nodetool `. To run the commands, you need to provide authentication information. The `nodetool` credentials are stored on every unit and can be used by running the commands within the unit itself, e.g. via the `juju ssh` command: ```shell juju ssh cassandra/0 sudo snap run charmed-cassandra.nodetool \ -u charmed-operator -pw "$(juju show-secret --reveal cassandra-peers.cassandra.app --format json | jq -r '.[].content.Data."nodetool-password"')" \ status ``` #### NOTE The `nodetool` username is always `charmed-operator` — a separate internal user, distinct from the `operator` CQL user used to connect with `cqlsh`. The password is stored in the `nodetool-password` field of the `cassandra-peers` application secret. ### Cluster status To check the state of the Cassandra ring, run `charmed-cassandra.nodetool status` on any unit: ```shell juju ssh cassandra/0 sudo snap run charmed-cassandra.nodetool \ -u charmed-operator -pw "$(juju show-secret --reveal cassandra-peers.cassandra.app --format json | jq -r '.[].content.Data."nodetool-password"')" \ status ``` The output lists every node in the cluster with its state (`UN` means up and normal), address, and load: ```text Datacenter: datacenter1 ======================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 10.166.144.10 1.2 MiB 16 100.0% 1f3f0e1e-... rack1 UN 10.166.144.11 1.1 MiB 16 100.0% 9a2b7c4d-... rack1 UN 10.166.144.12 1.3 MiB 16 100.0% 5e8d1a2c-... rack1 ``` ### Recover from a lost node If a unit’s machine is lost or permanently fails, remove the unit with `juju remove-unit` as above. The charm also automatically removes nodes that are down and unknown to the cluster, and repairs the `system_auth` keyspace to keep authentication data consistent across the remaining nodes. # index.html.md # How to manage passwords This guide shows how to retrieve the current password for the default `operator` user and how to rotate it. Authentication is enabled by default in Charmed Apache Cassandra. The charm automatically generates the initial password and stores it in a Juju secret. ## Prerequisites * A running Charmed Apache Cassandra deployment — see [How to deploy Charmed Apache Cassandra](https://canonical.com/data/cassandra/docs/latest//how-to/deploy.md#how-to-deploy). ## Retrieve the operator password The password for the default `operator` user is stored in the application secret of the `cassandra-peers` relation: ```shell juju show-secret --reveal "cassandra-peers..app" --format json \ | jq -r '.[].content.Data."operator-password"' ``` ## Rotate the operator password The charm supports password rotation for the default `operator` user by leveraging **Juju secrets**. 1. Check the current password: ```shell juju show-secret --reveal cassandra-peers.cassandra.app | grep operator # operator-password: a474ikLqA7KscI49zuH1O03bDTI42yJX ``` 2. Create a new Juju secret with the updated password: ```shell juju add-secret mypass operator=abcd123456 # secret:d2te3fe3rarc4b9fuj70 ``` 3. Grant Cassandra access to the new secret: ```shell juju grant-secret mypass cassandra ``` 4. Update Cassandra to use the new secret: ```shell juju config cassandra system-users=secret:d2te3fe3rarc4b9fuj70 ``` 5. Verify that the password has been rotated: ```shell juju show-secret --reveal cassandra-peers.cassandra.app | grep operator # operator-password: abcd123456 ``` #### NOTE Once rotated, all clients must use the new password to connect. # index.html.md # Contact #### NOTE This charm and its documentation are work in progress (WIP). Communication channels may evolve as the project matures. Stay connected with the Charmed Apache Cassandra team and the broader Canonical Data & Juju communities. See below for our contact information. Contact Canonical Data Platform team in [Matrix](https://matrix.to/#/#charmhub-data-platform:ubuntu.com). Report your ideas/issues on GitHub: - Charm issues: [https://github.com/canonical/cassandra-operator/issues](https://github.com/canonical/cassandra-operator/issues) - Snap packaging: [https://github.com/canonical/charmed-cassandra-snap/issues](https://github.com/canonical/charmed-cassandra-snap/issues) When filing an issue, please include: - Charm / packaging artifact version - Juju version & substrate (cloud / VM / LXD / Kubernetes) - Reproduction steps & expected vs actual behavior - Logs or relevant command output (`juju status`, `juju debug-log`) where possible ## Useful links More resources: - [Canonical Data Fabric](https://ubuntu.com/data/) - [Git sources](https://github.com/canonical/cassandra-operator) - [Canonical Data on Launchpad](https://launchpad.net/~data-platform) - [Canonical Data on Matrix](https://matrix.to/#/#charmhub-data-platform:ubuntu.com) # index.html.md # 1. Set up the environment This is a part of the [Charmed Apache Cassandra Tutorial](https://canonical.com/data/cassandra/docs/latest//tutorial/index.md). For this tutorial, we need to set up the environment with two main components, plus some extra command-line tooling: - [LXD](https://github.com/canonical/lxd) - a system container and virtual machine manager that provides the local cloud our cluster runs on - [Juju](https://github.com/juju/juju) - lets us deploy and manage Charmed Apache Cassandra and related applications - [jq](https://github.com/jqlang/jq) - a command-line JSON processor used to parse command output ## Prepare the cloud The fastest, simplest way to get started with Charmed Apache Cassandra is to set up a local LXD cloud. Each Cassandra node runs inside an LXD container managed by Juju. While this tutorial covers the basics of LXD, you can [learn more about LXD here](https://canonical.com/lxd/docs/stable-5.21/). LXD comes pre-installed on Ubuntu 24.04 LTS. Verify that LXD is installed by entering the command `which lxd`. This will output `/snap/bin/lxd` or, on some systems, `/usr/sbin/lxd`. Although LXD is already installed, we need to run `lxd init` to perform post-installation tasks. For this tutorial the default parameters are preferred, and the network bridge should be set to have no IPv6 addresses since Juju does not support IPv6 addresses with LXD: ```shell lxd init --auto lxc network set lxdbr0 ipv6.address none ``` You can list all LXD containers by entering the command `lxc list`. At this point of the tutorial none should exist, so you will only see this output: ```text +------+-------+------+------+------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +------+-------+------+------+------+-----------+ ``` ## Install and prepare Juju [Juju](https://juju.is/) is an Operator Lifecycle Manager (OLM) for clouds, bare metal, LXD and Kubernetes. We will use it to deploy and manage Charmed Apache Cassandra. As with LXD, Juju is installed from a snap package: ```shell sudo snap install juju --channel 3.6/stable ``` Install `jq`, a JSON processor used to parse Juju output in later steps: ```shell sudo snap install jq ``` ## Bootstrap a Juju controller Juju already has built-in knowledge of LXD and how it works, so there is no additional cloud setup needed. A Juju controller will be created, which will in turn manage the operations of Charmed Apache Cassandra. All we need to do is bootstrap a Juju controller named `overlord` onto the `localhost` (LXD) cloud. This bootstrapping process can take several minutes depending on the resources available on your machine: ```shell juju bootstrap localhost overlord ``` The Juju controller runs inside its own LXD container. To verify this, check the list of containers: ```shell lxc list ```
Output example ```text +---------------+---------+-----------------------+------+-----------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +---------------+---------+-----------------------+------+-----------+-----------+ | juju- | RUNNING | 10.166.144.1 (eth0) | | CONTAINER | 0 | +---------------+---------+-----------------------+------+-----------+-----------+ ``` where `` is a unique combination of numbers and letters such as `9d7e4e-0`.
## Create a model A controller can manage multiple models. A model hosts applications such as Charmed Apache Cassandra. Create a model named `tutorial`: ```shell juju add-model tutorial ``` Check the status of the model you just created: ```shell juju status ```
Output example ```text Model Controller Cloud/Region Version SLA Timestamp tutorial overlord localhost/localhost 3.6.29 unsupported 12:10:54Z Model "admin/tutorial" is empty. ```
With the environment ready, we can move on to deploying Charmed Apache Cassandra. # index.html.md # 4. Integrate with a client application This is a part of the [Charmed Apache Cassandra Tutorial](https://canonical.com/data/cassandra/docs/latest//tutorial/index.md). The recommended way to create and manage client users is through another charm: the [Data Integrator Charm](https://charmhub.io/data-integrator). This lets us encode users directly in the Juju model, and generate scoped credentials and a dedicated keyspace automatically using a relation, without ever touching the admin `operator` user. #### NOTE Relations, which the Juju documentation also calls [integrations](https://canonical.com/juju/docs/juju-cli/3.6/reference/relation/), let two charms exchange information and interact with one another. Creating a relation between Charmed Apache Cassandra and the Data Integrator automatically generates a username and password, creates a keyspace, and assigns the relevant permissions on that keyspace. This is the simplest way to create and manage client users in Charmed Apache Cassandra. ## The Data Integrator charm The [Data Integrator charm](https://charmhub.io/data-integrator) is a bare-bones charm for the central management of database and messaging users. It supports many data products (Apache Cassandra, MongoDB, MySQL, PostgreSQL, Apache Kafka, OpenSearch, and more) with a consistent and robust user experience. Deploy the Data Integrator and tell it which keyspace to request through the `keyspace-name` configuration option: ```shell juju deploy data-integrator --config keyspace-name=tutorial_app ``` The charm starts in a `blocked` state with a message such as `Please relate the data-integrator with the desired product`. This is expected, as it has nothing to integrate with yet. To create the user and keyspace, integrate the Data Integrator with Charmed Apache Cassandra: ```shell juju integrate data-integrator cassandra ``` Wait for the status to become `active`/`idle` using `watch juju status --color`.
Output example ```text Model Controller Cloud/Region Version SLA Timestamp tutorial overlord localhost/localhost 3.6.29 unsupported 13:02:41Z App Version Status Scale Charm Channel Rev Exposed Message cassandra 5.0.5 active 3 cassandra 5/edge 42 no data-integrator active 1 data-integrator latest/stable 362 no self-signed-certificates active 1 self-signed-certificates 1/stable 317 no Unit Workload Agent Machine Public address Ports Message cassandra/0* active idle 0 10.166.144.10 9042/tcp cassandra/1 active idle 1 10.166.144.11 9042/tcp cassandra/2 active idle 2 10.166.144.12 9042/tcp data-integrator/0* active idle 3 10.166.144.13 self-signed-certificates/0* active idle 4 10.166.144.14 ```
## Retrieve the credentials Once the integration is set, retrieve the generated credentials with the `get-credentials` action: ```shell juju run data-integrator/leader get-credentials ``` This outputs something like: ```yaml cassandra: endpoints: 10.166.144.10,10.166.144.11,10.166.144.12 password: 3xHk9fRpQ2vLmN8sT4wZ tls-ca: |- -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- username: user_6xRzpv4iGLMqVsok_relation_6 ok: "True" ``` Note the values for `username`, `password`, and `endpoints`. These credentials belong to a user that is scoped to the `tutorial_app` keyspace only. This is exactly how a real client application would obtain its credentials, and because the user is scoped, it cannot touch data in other keyspaces or perform cluster-wide administration. #### NOTE Because TLS is enabled from the previous chapter, the credentials also include a `tls-ca` field (shown truncated above) carrying the CA a client needs to trust the cluster. ## Rotate or remove the user Credentials are managed entirely through the relation. To rotate them, remove and re-add the integration: ```shell juju remove-relation data-integrator cassandra juju integrate data-integrator cassandra ``` Running `get-credentials` again returns a new username and password. To remove the user and its access entirely, simply remove the relation: ```shell juju remove-relation data-integrator cassandra ``` #### NOTE Removing the relation revokes the generated user, but it does not delete the keyspace or any data in it. The `tutorial_app` keyspace remains in the cluster until you drop it explicitly. ## What’s next? The Data Integrator shows how client applications receive scoped credentials. In the next section we will switch to the admin `operator` user and use `cqlsh` directly to create our own keyspace and work with data, giving us full control over the replication factor for the scaling exercises that follow. # index.html.md # Tutorial The Charmed Apache Cassandra Operator delivers automated operations management from [Day 0 to Day 2](https://codilime.com/blog/day-0-day-1-day-2-the-software-lifecycle-in-the-cloud-age/) on the [Apache Cassandra](https://cassandra.apache.org/) distributed database. It is an open source, end-to-end, production-ready data platform [on top of Juju](https://juju.is/). As a first step, this tutorial shows you how to get Charmed Apache Cassandra up and running, but it does not stop there. Through this tutorial you will learn a range of operations, from deploying a cluster to enabling TLS encryption, integrating client applications, working with data using the `cqlsh` command-line client, and scaling the cluster in and out while keeping your data safe. This tutorial targets the **VM** charm `cassandra` running on a local LXD cloud. #### NOTE Charmed Apache Cassandra is under active development and is currently published on the `5/edge` channel only. It is not yet recommended for production environments. In this tutorial, we will walk through how to: - Set up your local environment using LXD and Juju, and bootstrap a controller - Deploy Charmed Apache Cassandra with only a few commands - Enable TLS encryption for peer-to-peer and client-to-node communication - Create a scoped client user automatically through a relation with the Data Integrator charm - Create a keyspace and read and write data using the `cqlsh` client - Scale the cluster out and in, and confirm that data is replicated and preserved - Clean up your environment safely While this tutorial intends to guide and teach you as you deploy Charmed Apache Cassandra, it will be most beneficial if you already have familiarity with: - Basic Unix shell commands - General database concepts such as replication, keyspaces, and user management ## Minimum requirements Before we start, make sure your machine meets the following requirements: - Ubuntu 24.04 LTS (Noble) or later - 8 GB of RAM - 2 CPU cores - At least 20 GB of available storage - Access to the internet for downloading the required snaps and charms #### NOTE This tutorial uses the `testing` profile, which tunes Cassandra for a minimal resource footprint so that a multi-node cluster fits comfortably on a single developer machine. Production deployments should use the default `production` profile on dedicated hosts. ## Step-by-step guide Here is an overview of the steps required, with links to the individual tutorials that deal with each one: - [Set up the environment](https://canonical.com/data/cassandra/docs/latest//tutorial/environment.md#tutorial-environment) - [Deploy Charmed Apache Cassandra](https://canonical.com/data/cassandra/docs/latest//tutorial/deploy.md#tutorial-deploy) - [Enable encryption](https://canonical.com/data/cassandra/docs/latest//tutorial/enable-encryption.md#tutorial-enable-encryption) - [Integrate with a client application](https://canonical.com/data/cassandra/docs/latest//tutorial/integrate-with-client-applications.md#tutorial-integrate-with-client-applications) - [Manage data with cqlsh](https://canonical.com/data/cassandra/docs/latest//tutorial/manage-data.md#tutorial-manage-data) - [Scale your cluster](https://canonical.com/data/cassandra/docs/latest//tutorial/scale.md#tutorial-scale) - [Clean up your environment](https://canonical.com/data/cassandra/docs/latest//tutorial/cleanup.md#tutorial-cleanup) # index.html.md # 2. Deploy Apache Cassandra This is a part of the [Charmed Apache Cassandra Tutorial](https://canonical.com/data/cassandra/docs/latest//tutorial/index.md#tutorial-index). To deploy Charmed Apache Cassandra, all you need to do is run the following command, which fetches [Apache Cassandra](https://charmhub.io/cassandra) from [Charmhub](https://charmhub.io/) and deploys it to your model. For this tutorial we will deploy a cluster of three nodes using the `testing` profile, which keeps the resource footprint small. Three or more nodes are recommended to keep data highly available: ```shell juju deploy cassandra -n 3 --config profile=testing --channel 5/edge ``` Juju will now fetch Charmed Apache Cassandra and begin deploying it to your LXD cloud. You can track the progress by running: ```shell watch juju status --color ``` During bootstrap, units pass through several transient maintenance and waiting statuses, such as `installing Cassandra`, `waiting for internal TLS setup`, `waiting for cluster to start`, `waiting for Cassandra to start`, and `repairing system_auth keyspace`. This process can take several minutes depending on the resources available on your machine. Wait until all units show `active`/`idle` status:
Output example ```text Model Controller Cloud/Region Version SLA Timestamp tutorial overlord localhost/localhost 3.6.29 unsupported 12:31:09Z App Version Status Scale Charm Channel Rev Exposed Message cassandra 5.0.5 active 3 cassandra 5/edge 42 no Unit Workload Agent Machine Public address Ports Message cassandra/0* active idle 0 10.166.144.10 9042/tcp cassandra/1 active idle 1 10.166.144.11 9042/tcp cassandra/2 active idle 2 10.166.144.12 9042/tcp Machine State Address Inst id Base AZ Message 0 started 10.166.144.10 juju-9d7e4e-0 ubuntu@24.04 Running 1 started 10.166.144.11 juju-9d7e4e-1 ubuntu@24.04 Running 2 started 10.166.144.12 juju-9d7e4e-2 ubuntu@24.04 Running ```
To exit the `watch` screen, press `Ctrl+C`. Each node exposes the Apache Cassandra native transport protocol on port `9042`, which is the port `cqlsh` and client applications use to connect. ## Access the cluster Authentication is enabled by default. The charm automatically generates a password for the built-in `operator` user and stores it in a Juju secret. All sensitive configuration data used by Charmed Apache Cassandra, such as passwords and TLS certificates, is stored in Juju secrets. See the [Juju secrets documentation](https://canonical.com/juju/docs/juju-cli/3.6/reference/secret/) for more information. The `operator` password lives in the application secret of the `cassandra-peers` relation. The secret label follows the pattern `cassandra-peers..app`, so for our `cassandra` application it is `cassandra-peers.cassandra.app`. Retrieve the password with: ```shell juju show-secret --reveal cassandra-peers.cassandra.app --format json \ | jq -r '.[].content.Data."operator-password"' ``` This prints the current `operator` password, for example: ```text a474ikLqA7KscI49zuH1O03bDTI42yJX ``` Make note of this value, we will use it to connect in the next steps. ## Connect with cqlsh `cqlsh` is the official command-line client for Apache Cassandra. The [`charmed-cassandra`](https://snapcraft.io/charmed-cassandra) snap bundles `cqlsh` (as well as the `nodetool` admin utility we use later), so install it locally: ```shell sudo snap install charmed-cassandra --edge ``` Retrieve the address of a unit (here `cassandra/0`) with `juju show-unit`, parsing it out with `jq` and storing it in a variable: ```shell CASSANDRA_IP=$(juju show-unit cassandra/0 --format json | jq -r '."cassandra/0"."public-address"') ``` Connect as the `operator` user, passing in that address: ```shell charmed-cassandra.cqlsh "$CASSANDRA_IP" -u operator -p "" ```
Output example ```text [cqlsh 6.1.0 | Cassandra 5.0.5 | CQL spec 3.4.7 | Native protocol v5] Use HELP for help. operator@cqlsh> ```
You now have an interactive CQL shell connected to the cluster. To confirm the cluster is healthy, list the keyspaces that ship with Cassandra: ```text operator@cqlsh> DESCRIBE KEYSPACES; system_auth system_schema system system_distributed system_views system_traces system_virtual_schema ``` Leave the shell for now by typing `exit`: ```text operator@cqlsh> exit ``` ## What’s next? So far we have connected over an unencrypted channel. In a real deployment, traffic between nodes and between clients and nodes should be encrypted. In the next section we will enable TLS encryption across the cluster. # index.html.md # 3. Enable encryption This is a part of the [Charmed Apache Cassandra Tutorial](https://canonical.com/data/cassandra/docs/latest//tutorial/index.md). [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security) encrypts data exchanged between applications, securing it as it travels over the network. Typically, enabling TLS within a highly available database, and between the database and its clients, requires domain-specific knowledge and a high level of expertise. Fortunately, that knowledge has been encoded into Charmed Apache Cassandra, so configuring TLS requires minimal effort on your end. Juju relations are particularly useful for enabling TLS. Charmed Apache Cassandra implements the **Requirer** side of the [tls-certificates](https://charmhub.io/integrations/tls-certificates) relation, so any charm implementing the **Provider** side can supply certificates. The relation centralises certificate management, handling provisioning, requests, and renewal, and lets you use different providers such as self-signed certificates or external services like Let’s Encrypt. Charmed Apache Cassandra supports two separate TLS channels, each exposed as its own relation endpoint: - `peer-certificates` - encrypts peer-to-peer traffic between the nodes in the cluster - `client-certificates` - encrypts client-to-node traffic, for example connections from `cqlsh` #### NOTE In this tutorial we distribute [self-signed certificates](https://en.wikipedia.org/wiki/Self-signed_certificate) signed by a single root CA. This is for testing and demonstration only. Self-signed certificates are not recommended for a production cluster. For guidance on choosing a provider, see the [Security with X.509 certificates](https://charmhub.io/topics/security-with-x-509-certificates) page. ## Deploy a certificate provider Before enabling TLS on Charmed Apache Cassandra, deploy the `self-signed-certificates` charm: ```shell juju deploy self-signed-certificates --channel 1/stable --config ca-common-name="Tutorial CA" ``` Wait for the charm to settle into an `active`/`idle` state, as shown by `juju status`. ## Enable peer-to-peer encryption To encrypt traffic between the cluster nodes, integrate Charmed Apache Cassandra with the certificate provider over the `peer-certificates` endpoint: ```shell juju integrate cassandra:peer-certificates self-signed-certificates ``` While certificates are being issued and distributed, units show waiting and maintenance statuses such as `waiting for internal TLS setup` and `waiting for peer tls rotation to complete`. Once the process completes, the units return to `active`/`idle`. ## Enable client-to-node encryption To encrypt traffic between clients and the cluster, integrate over the `client-certificates` endpoint: ```shell juju integrate cassandra:client-certificates self-signed-certificates ``` Again the units briefly show statuses such as `waiting for TLS setup` and `waiting for client tls rotation to complete` before returning to `active`/`idle`. ## Reconnect with cqlsh over SSL Now that client-to-node encryption is enabled, the cluster rejects plaintext connections. If you try to connect the way we did in the previous chapter, it fails: ```shell charmed-cassandra.cqlsh "$CASSANDRA_IP" -u operator -p "" ``` ```text Connection error: ('Unable to connect to any servers', {'10.166.144.10:9042': ConnectionResetError(104, 'Connection reset by peer')}) ``` This confirms that Apache Cassandra now requires a secure TLS connection. ### Retrieve the root CA `cqlsh` needs the root CA to verify the certificate the Cassandra nodes present during the TLS handshake. Fetch it from the `self-signed-certificates` charm. Since the `charmed-cassandra` snap is strictly confined, the CA must live in a location the snap can read. Write it directly into the snap’s configuration directory: ```shell juju run self-signed-certificates/0 get-ca-certificate --format json \ | jq -r '."self-signed-certificates/0".results."ca-certificate"' \ | sudo tee /var/snap/charmed-cassandra/current/etc/cassandra/ca.cert ``` ### Create a cqlshrc file In the same directory, create a `cqlshrc` configuration file that tells `cqlsh` which credentials to use and where to find the CA. Retrieve the `operator` password again if you need it: ```shell juju show-secret --reveal cassandra-peers.cassandra.app --format json \ | jq -r '.[].content.Data."operator-password"' ``` Then create `/var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc` with the following content, substituting the password and the `` address captured earlier: ```ini [authentication] username = operator password = [connection] hostname = port = 9042 [ssl] certfile = /var/snap/charmed-cassandra/current/etc/cassandra/ca.cert validate = true ``` `cqlsh` refuses to use a `cqlshrc` that other users can read, so restrict its permissions to your user only: ```shell sudo chown $USER /var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc sudo chmod 600 /var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc ``` ### Connect Connect to the cluster over TLS by pointing `cqlsh` at the `cqlshrc` file and passing the `--ssl` flag: ```shell charmed-cassandra.cqlsh --ssl \ --cqlshrc /var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc ```
Output example ```text [cqlsh 6.1.0 | Cassandra 5.0.5 | CQL spec 3.4.7 | Native protocol v5] Use HELP for help. operator@cqlsh> ```
The connection now succeeds over an encrypted channel. The `hostname` set in `cqlshrc` is the default target, but you can always connect to a specific node by passing its address as a positional argument, which is handy once the cluster has more nodes: ```shell charmed-cassandra.cqlsh --ssl "$CASSANDRA_IP" \ --cqlshrc /var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc ``` Leave the shell with `exit`. We will reuse this `cqlshrc` file for every `cqlsh` command in the rest of the tutorial. #### NOTE If you ever want to go back to unencrypted connections, remove the relations with `juju remove-relation cassandra:client-certificates self-signed-certificates` and `juju remove-relation cassandra:peer-certificates self-signed-certificates`. This triggers a rolling restart as the units switch back to plaintext communication. ## What’s next? The cluster is now secured. In the next section we will integrate a client application to generate a scoped user and a dedicated keyspace automatically through a relation. # index.html.md # 7. Clean up your environment This is a part of the [Charmed Apache Cassandra Tutorial](https://canonical.com/data/cassandra/docs/latest//tutorial/index.md). In this tutorial we deployed Charmed Apache Cassandra, enabled TLS encryption, integrated a client application, worked with data using `cqlsh`, and scaled the cluster in and out. This final section shows how to tear everything down safely. ## Remove the tutorial model #### CAUTION Removing a Juju model destroys every application in it along with their storage. This deletes all the data we created. Only do this when you are finished with the tutorial. To remove Charmed Apache Cassandra and everything else in the `tutorial` model: ```shell juju destroy-model tutorial --destroy-storage --no-prompt ``` This removes all applications in the model (Charmed Apache Cassandra, the Data Integrator, and the self-signed certificates provider). Your Juju controller and any other models remain intact for future use. ## (Optional) Remove the client snap If you no longer need the `cqlsh` and `nodetool` clients locally, remove the `charmed-cassandra` snap. This also removes the `ca.cert` and `cqlshrc` files we created under its configuration directory: ```shell sudo snap remove charmed-cassandra --purge ``` ## (Optional) Remove Juju and the cloud If you do not need Juju anymore and want to free up additional resources, you can remove the Juju controller and Juju itself. #### CAUTION Removing the Juju controller as shown below means you lose access to any other applications and models hosted on it. Check the list of controllers: ```shell juju controllers ``` Remove the controller created in this tutorial: ```shell juju destroy-controller overlord --destroy-all-models --destroy-storage ``` To remove Juju altogether: ```shell sudo snap remove juju --purge ``` ### Clean up LXD If you also want to remove the LXD containers and free up all resources, list any remaining containers: ```shell lxc list ``` Delete unnecessary containers: ```shell lxc delete --force ``` If you want to uninstall LXD completely: ```shell sudo snap remove lxd --purge ``` #### WARNING Only remove LXD if you are not using it for other purposes. LXD may be managing other containers or virtual machines on your system. ## What’s next? In this tutorial we deployed Apache Cassandra, secured it with TLS, created users and data, and scaled the cluster while keeping data safe. If you are looking for what to do next, you can: - Read the [how-to guides](https://canonical.com/data/cassandra/docs/latest//how-to/index.md#how-to-index) for deploying, scaling, securing, and monitoring a cluster - Explore other Charmed offerings from [Canonical’s Data Platform team](https://canonical.com/data) - [Report](https://github.com/canonical/cassandra-operator/issues) any problems you encountered - [Give us your feedback](https://matrix.to/#/#charmhub-data-platform:ubuntu.com) - [Contribute to the code base](https://github.com/canonical/cassandra-operator) # index.html.md # 6. Scale your cluster This is a part of the [Charmed Apache Cassandra Tutorial](https://canonical.com/data/cassandra/docs/latest//tutorial/index.md). One of the main reasons to run Apache Cassandra is its ability to scale horizontally while keeping data available. In this section we scale the cluster out, confirm the data we wrote earlier has been replicated to the new node, add more data, then scale back in and confirm nothing was lost. A Cassandra cluster is also called a *ring*: a peer-to-peer set of nodes where every node is equal. When nodes are added or removed, the charm drives the operation while Apache Cassandra itself automatically redistributes (streams) the data, so the ring stays balanced and the replication factor is honoured. ## Inspect the ring The `nodetool` utility reports the state of the ring. It uses a separate internal user, `charmed-operator`, whose password is in the `nodetool-password` field of the `cassandra-peers` secret. Run it on any unit through `juju ssh`: ```shell juju ssh cassandra/0 sudo snap run charmed-cassandra.nodetool \ -u charmed-operator -pw "$(juju show-secret --reveal cassandra-peers.cassandra.app --format json | jq -r '.[].content.Data."nodetool-password"')" \ status ```
Output example ```text Datacenter: datacenter1 ======================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 10.166.144.10 120.5 KiB 16 100.0% 1f3f0e1e-... rack1 UN 10.166.144.11 118.9 KiB 16 100.0% 9a2b7c4d-... rack1 UN 10.166.144.12 121.2 KiB 16 100.0% 5e8d1a2c-... rack1 ```
`UN` means the node is **U**p and in the **N**ormal state. With three nodes and a replication factor of `3`, each node owns `100.0%` of the data. ## Scale out Add a fourth node to the cluster: ```shell juju add-unit cassandra -n 1 ``` Monitor the progress with `watch juju status --color`. The new unit shows `waiting for cluster to start` while it bootstraps and joins the ring, then becomes `active`/`idle`. As it joins, Cassandra streams data to it automatically.
Output example ```text App Version Status Scale Charm Channel Rev Exposed Message cassandra 5.0.5 active 4 cassandra 5/edge 42 no Unit Workload Agent Machine Public address Ports Message cassandra/0* active idle 0 10.166.144.10 9042/tcp cassandra/1 active idle 1 10.166.144.11 9042/tcp cassandra/2 active idle 2 10.166.144.12 9042/tcp cassandra/3 active idle 5 10.166.144.15 9042/tcp ```
Run `nodetool status` again, and you will see the fourth node in the ring, carrying its own share of the load, which confirms that data was streamed to it: ```shell juju ssh cassandra/0 sudo snap run charmed-cassandra.nodetool \ -u charmed-operator -pw "$(juju show-secret --reveal cassandra-peers.cassandra.app --format json | jq -r '.[].content.Data."nodetool-password"')" \ status ```
Output example ```text Datacenter: datacenter1 ======================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 10.166.144.10 135.1 KiB 16 73.8% 1f3f0e1e-... rack1 UN 10.166.144.11 132.7 KiB 16 76.2% 9a2b7c4d-... rack1 UN 10.166.144.12 134.4 KiB 16 74.9% 5e8d1a2c-... rack1 UN 10.166.144.15 98.3 KiB 16 75.1% b7c3f9a1-... rack1 ```
With four nodes and a replication factor of `3`, each node now owns roughly `75%` of the data instead of `100%`. ## Verify data was replicated To prove the new node serves our data, connect `cqlsh` **directly to the new node’s address** by passing it as a positional argument (this overrides the `hostname` in `cqlshrc`). Capture the new unit’s address the same way as before: ```shell NEW_CASSANDRA_IP=$(juju show-unit cassandra/3 --format json | jq -r '."cassandra/3"."public-address"') ``` ```shell charmed-cassandra.cqlsh --ssl "$NEW_CASSANDRA_IP" \ --cqlshrc /var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc ``` Read the rows we wrote earlier: ```text operator@cqlsh> SELECT * FROM tutorial.members; id | name | race ----+---------+-------- 1 | frodo | hobbit 2 | gandalf | maia 3 | aragorn | human (3 rows) ``` The data we inserted on a three-node cluster is now available from the brand-new fourth node. ## Add more data While still connected (to any node), insert another row: ```text operator@cqlsh> INSERT INTO tutorial.members (id, name, race) VALUES (4, 'legolas', 'elf'); operator@cqlsh> SELECT * FROM tutorial.members; id | name | race ----+---------+-------- 1 | frodo | hobbit 2 | gandalf | maia 3 | aragorn | human 4 | legolas | elf (4 rows) ``` Leave the shell with `exit`. ## Scale in Now remove the fourth node. The charm *decommissions* it, streaming its data to the remaining nodes before it leaves the ring, so no data is lost: ```shell juju remove-unit cassandra/3 ``` #### CAUTION Before removing a unit, check the replication factor of your keyspaces. If removing a unit would bring the number of nodes below a keyspace’s replication factor, that keyspace may lose data or become unavailable. Here we go from four nodes back to three, which still satisfies our replication factor of `3`. #### NOTE Only one unit can be removed at a time. During removal, units show statuses related to decommissioning while data is streamed off the departing node. Wait for the cluster to return to three `active`/`idle` units, then check the ring again. The fourth node is gone and the three remaining nodes again own `100.0%` of the data: ```shell juju ssh cassandra/0 sudo snap run charmed-cassandra.nodetool \ -u charmed-operator -pw "$(juju show-secret --reveal cassandra-peers.cassandra.app --format json | jq -r '.[].content.Data."nodetool-password"')" \ status ``` ## Verify data was preserved Connect to one of the remaining nodes and read the table: ```shell charmed-cassandra.cqlsh --ssl "$CASSANDRA_IP" \ --cqlshrc /var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc ``` ```text operator@cqlsh> SELECT * FROM tutorial.members; id | name | race ----+---------+-------- 1 | frodo | hobbit 2 | gandalf | maia 3 | aragorn | human 4 | legolas | elf (4 rows) ``` All four rows are still there, including the one we added while the cluster had four nodes. Scaling in preserved the data. Leave the shell with `exit`. ## What’s next? You have now scaled the cluster out and in while keeping your data safe. In the final section we will clean up the environment. # index.html.md # 5. Manage data with cqlsh This is a part of the [Charmed Apache Cassandra Tutorial](https://canonical.com/data/cassandra/docs/latest//tutorial/index.md). In this section we use the admin `operator` user and the `cqlsh` client to create a keyspace, define a table, and write and read some data. We keep this `cqlsh` session handy for the scaling exercises in the next chapter. All the commands below connect over TLS using the `cqlshrc` file we created in the [encryption chapter](https://canonical.com/data/cassandra/docs/latest//tutorial/enable-encryption.md#tutorial-enable-encryption). Open a shell: ```shell charmed-cassandra.cqlsh --ssl \ --cqlshrc /var/snap/charmed-cassandra/current/etc/cassandra/cqlshrc ``` You should land at the `operator@cqlsh>` prompt. ## Create a keyspace A keyspace is the top-level container for data in Cassandra, roughly analogous to a database in a relational system. Crucially, the keyspace defines how data is replicated across the nodes in the cluster through its *replication factor*. Create a keyspace called `tutorial` with a replication factor of `3`. With three nodes in the cluster, this means every node holds a full copy of the data: ```text operator@cqlsh> CREATE KEYSPACE tutorial ... WITH replication = { ... 'class': 'SimpleStrategy', ... 'replication_factor': 3 ... }; ``` Confirm it was created: ```text operator@cqlsh> DESCRIBE KEYSPACE tutorial; CREATE KEYSPACE tutorial WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '3'} AND durable_writes = true; ``` #### NOTE Setting the replication factor equal to the number of nodes is convenient for this tutorial because it guarantees that each node holds every row. In production you typically keep the replication factor fixed (for example, `3`) while the cluster grows, so that data is spread across a subset of nodes rather than copied to all of them. ## Create a table Switch into the new keyspace and create a simple table to store a list of members of the Fellowship: ```text operator@cqlsh> USE tutorial; operator@cqlsh:tutorial> CREATE TABLE members ( ... id int PRIMARY KEY, ... name text, ... race text ... ); ``` ## Add data Insert a few rows: ```text operator@cqlsh:tutorial> INSERT INTO members (id, name, race) VALUES (1, 'frodo', 'hobbit'); operator@cqlsh:tutorial> INSERT INTO members (id, name, race) VALUES (2, 'gandalf', 'maia'); operator@cqlsh:tutorial> INSERT INTO members (id, name, race) VALUES (3, 'aragorn', 'human'); ``` ## Read data Read the rows back: ```text operator@cqlsh:tutorial> SELECT * FROM members; id | name | race ----+---------+-------- 1 | frodo | hobbit 2 | gandalf | maia 3 | aragorn | human (3 rows) ``` #### NOTE `SELECT *` without a `WHERE` clause scans every partition across the whole cluster. It is fine on this tiny tutorial table, but on a production deployment it is an expensive operation that should be avoided. Real queries normally restrict the rows they read, for example with `WHERE id = 1`. The data is now stored in the cluster and, thanks to the replication factor of `3`, replicated to every node. We can demonstrate this with the `CONSISTENCY ALL` setting, which forces a read to contact *every* replica and only succeed if they all respond. Since each node holds a full copy, the read still returns all three rows: ```text operator@cqlsh:tutorial> CONSISTENCY ALL; Consistency level set to ALL. operator@cqlsh:tutorial> SELECT * FROM members; id | name | race ----+---------+-------- 1 | frodo | hobbit 2 | gandalf | maia 3 | aragorn | human (3 rows) ``` Reset the consistency level back to the default before moving on: ```text operator@cqlsh:tutorial> CONSISTENCY QUORUM; Consistency level set to QUORUM. ``` Leave the shell with `exit`. ## What’s next? In the next section we will scale the cluster out and confirm that our data is automatically replicated to the new node, add more data, then scale back in and confirm that nothing is lost. # index.html.md # Tutorial The Charmed Apache Cassandra Operator delivers automated operations management from [Day 0 to Day 2](https://codilime.com/blog/day-0-day-1-day-2-the-software-lifecycle-in-the-cloud-age/) on the [Apache Cassandra](https://cassandra.apache.org/) distributed database. It is an open source, end-to-end, production-ready data platform [on top of Juju](https://juju.is/). As a first step, this tutorial shows you how to get Charmed Apache Cassandra up and running, but it does not stop there. Through this tutorial you will learn a range of operations, from deploying a cluster to enabling TLS encryption, integrating client applications, working with data using the `cqlsh` command-line client, and scaling the cluster in and out while keeping your data safe. This tutorial targets the **VM** charm `cassandra` running on a local LXD cloud. #### NOTE Charmed Apache Cassandra is under active development and is currently published on the `5/edge` channel only. It is not yet recommended for production environments. In this tutorial, we will walk through how to: - Set up your local environment using LXD and Juju, and bootstrap a controller - Deploy Charmed Apache Cassandra with only a few commands - Enable TLS encryption for peer-to-peer and client-to-node communication - Create a scoped client user automatically through a relation with the Data Integrator charm - Create a keyspace and read and write data using the `cqlsh` client - Scale the cluster out and in, and confirm that data is replicated and preserved - Clean up your environment safely While this tutorial intends to guide and teach you as you deploy Charmed Apache Cassandra, it will be most beneficial if you already have familiarity with: - Basic Unix shell commands - General database concepts such as replication, keyspaces, and user management ## Minimum requirements Before we start, make sure your machine meets the following requirements: - Ubuntu 24.04 LTS (Noble) or later - 8 GB of RAM - 2 CPU cores - At least 20 GB of available storage - Access to the internet for downloading the required snaps and charms #### NOTE This tutorial uses the `testing` profile, which tunes Cassandra for a minimal resource footprint so that a multi-node cluster fits comfortably on a single developer machine. Production deployments should use the default `production` profile on dedicated hosts.