Was this page helpful?
Caution
You're viewing documentation for an unstable version of ScyllaDB Operator. Switch to the latest stable version.
Connect via CQL¶
This page explains how to connect to a ScyllaDB cluster running on Kubernetes using CQL (Cassandra Query Language).
Authentication setup¶
For security, always enable authentication and authorization. Create a ConfigMap with the ScyllaDB configuration before deploying your cluster:
apiVersion: v1
kind: ConfigMap
metadata:
name: scylladb-config
data:
scylla.yaml: |
authenticator: PasswordAuthenticator
authorizer: CassandraAuthorizer
Reference this ConfigMap from your ScyllaCluster via scyllaConfig on each rack:
apiVersion: scylla.scylladb.com/v1
kind: ScyllaCluster
metadata:
name: scylladb
spec:
datacenter:
racks:
- name: us-east-1a
scyllaConfig: scylladb-config
# ...
After deployment, follow the Creating a Custom Superuser guide in the ScyllaDB documentation to replace the default cassandra superuser with a dedicated role.
Caution
Starting with ScyllaDB 2026.2, the default cassandra/cassandra superuser credentials are being removed. New clusters will require configuring a custom superuser via auth_superuser_name and auth_superuser_salted_password in scylla.yaml. See scylladb/scylladb#27215 for details.
Embedded cqlsh¶
Every ScyllaDB Pod includes a built-in cqlsh. This is the simplest way to run queries:
kubectl exec -it service/<cluster-name>-client -c scylla -- cqlsh -u <user>
kubectl exec -it pod/<cluster-name>-<datacenter>-<rack>-<ordinal> -c scylla -- cqlsh -u <user>
Password:
Connected to scylla at 0.0.0.0:9042
[cqlsh 6.0.32 | Scylla 2026.1.0-0.20260309.9190d42863d4 | CQL spec 3.3.1 | Native protocol v4]
Use HELP for help.
<user>@cqlsh>
Remote cqlsh with TLS¶
ScyllaDB Operator configures TLS certificates automatically. The encrypted CQL port 9142 works by default.
Prepare credentials and certificates¶
The Operator automatically creates TLS resources for each ScyllaCluster. For programmatic access using the Go driver with clusters that have dnsDomains configured, use the pre-built connection bundle from secret/<cluster-name>-local-cql-connection-configs-admin directly (see Security for details).
For cqlsh, extract the certificates and create a cqlshrc file:
Caution
The example below simplifies credential file creation for brevity. In production, create the credentials file with a text editor to avoid passwords leaking into shell history or environment variables.
Step 1: Extract certificates
kubectl -n scylla get configmap <cluster-name>-local-serving-ca \
--template='{{ index .data "ca-bundle.crt" }}' > ca.crt
kubectl -n scylla get secret <cluster-name>-local-user-admin \
-o jsonpath='{.data.tls\.crt}' | base64 -d > client.crt
kubectl -n scylla get secret <cluster-name>-local-user-admin \
-o jsonpath='{.data.tls\.key}' | base64 -d > client.key
Note
ca.crt is a copy of the serving CA bundle. When the operator reissues the serving CA, cqlsh rejects the new serving
certificate until you extract the bundle again. See Certificate rotation.
Step 2: Create a cqlshrc file
export SCYLLADB_CONFIG=/path/to/scylladb-config
mkdir -p "${SCYLLADB_CONFIG}"
cp ca.crt client.crt client.key "${SCYLLADB_CONFIG}/"
cat > "${SCYLLADB_CONFIG}/cqlshrc" <<EOF
[connection]
hostname = <cluster-name>-client.<namespace>.svc
port = 9142
ssl = true
[ssl]
certfile = ${SCYLLADB_CONFIG}/ca.crt
usercert = ${SCYLLADB_CONFIG}/client.crt
userkey = ${SCYLLADB_CONFIG}/client.key
validate = true
[authentication]
username = cassandra
password = <password>
EOF
Connect¶
cqlsh --cqlshrc="${SCYLLADB_CONFIG}/cqlshrc"
podman run -it --rm --entrypoint=cqlsh \
-v="${SCYLLADB_CONFIG}:${SCYLLADB_CONFIG}:ro,Z" \
-v="${SCYLLADB_CONFIG}/cqlshrc:/root/.cassandra/cqlshrc:ro,Z" \
docker.io/scylladb/scylla:2026.3.3
docker run -it --rm --entrypoint=cqlsh \
-v="${SCYLLADB_CONFIG}:${SCYLLADB_CONFIG}:ro" \
-v="${SCYLLADB_CONFIG}/cqlshrc:/root/.cassandra/cqlshrc:ro" \
docker.io/scylladb/scylla:2026.3.3
Driver configuration tips¶
When using a ScyllaDB or Cassandra driver in your application:
Setting |
Recommended value |
Why |
|---|---|---|
Contact points |
|
Use the discovery Service, not individual Pod IPs. The driver discovers all nodes automatically. |
Local datacenter |
Your |
Required for |
Load balancing |
Token-aware + DC-aware round robin |
Sends queries directly to the replica owning the partition. |
TLS |
Enabled, with CA verification |
Use the serving CA bundle from |
Reconnection |
Exponential backoff |
Handles node restarts during rolling updates. |
Mount TLS files in application Pods¶
Mount the serving CA bundle ConfigMap into your application Pods instead of copying it, so that they pick up a reissued serving CA. Kubernetes updates the mounted file when the ConfigMap changes.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
# ...
template:
spec:
containers:
- name: app
image: <your-app-image>
volumeMounts:
- name: scylladb-serving-ca
mountPath: /etc/scylladb/serving-ca
readOnly: true
- name: scylladb-client-certificate
mountPath: /etc/scylladb/client-certificate
readOnly: true
volumes:
- name: scylladb-serving-ca
configMap:
name: <cluster-name>-local-serving-ca
- name: scylladb-client-certificate
secret:
secretName: <client-certificate-secret-name>
Configure your driver to use /etc/scylladb/serving-ca/ca-bundle.crt as the CA, and /etc/scylladb/client-certificate/tls.crt
and /etc/scylladb/client-certificate/tls.key as the client certificate and key. The client certificate Secret has to
hold a certificate signed by the cluster’s client CA, such as the <cluster-name>-local-user-admin Secret.
Keep in mind:
Don’t mount the files with
subPath. Kubernetes doesn’t update files mounted withsubPath.Kubernetes updates mounted files with a delay, so new connections can fail for a short time after the serving CA is reissued.
Your application has to read the files again when it opens new connections. If it reads them only at startup, restart it after the serving CA is reissued.
A Pod can only mount ConfigMaps and Secrets from its own namespace. For applications in other namespaces, keep a copy of the bundle up to date instead.