Cassandra on Kubernetes
This guide covers deploying Apache Cassandra on Kubernetes using StatefulSets and operators.
Deployment Options
Section titled “Deployment Options”| Option | Complexity | Features | Best For |
|---|---|---|---|
| StatefulSet | Medium | Basic orchestration | Simple deployments |
| K8ssandra | Low | Full-featured operator | Production |
| Cass-operator | Medium | DataStax operator | Enterprise |
| Custom Helm | Medium | Flexible | Custom requirements |
StatefulSet Deployment
Section titled “StatefulSet Deployment”Basic StatefulSet
Section titled “Basic StatefulSet”apiVersion: apps/v1kind: StatefulSetmetadata: name: cassandra labels: app: cassandraspec: serviceName: cassandra replicas: 3 selector: matchLabels: app: cassandra template: metadata: labels: app: cassandra spec: terminationGracePeriodSeconds: 1800 containers: - name: cassandra image: cassandra:4.1 ports: - containerPort: 7000 name: intra-node - containerPort: 7001 name: tls-intra-node - containerPort: 7199 name: jmx - containerPort: 9042 name: cql resources: limits: cpu: "2" memory: 4Gi requests: cpu: "1" memory: 2Gi securityContext: capabilities: add: - IPC_LOCK lifecycle: preStop: exec: command: - /bin/sh - -c - nodetool drain env: - name: MAX_HEAP_SIZE value: 1G - name: HEAP_NEWSIZE value: 256M - name: CASSANDRA_SEEDS value: "cassandra-0.cassandra.default.svc.cluster.local" - name: CASSANDRA_CLUSTER_NAME value: "K8sCluster" - name: CASSANDRA_DC value: "DC1" - name: CASSANDRA_RACK value: "Rack1" - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP readinessProbe: exec: command: - /bin/bash - -c - /ready-probe.sh initialDelaySeconds: 15 timeoutSeconds: 5 volumeMounts: - name: cassandra-data mountPath: /var/lib/cassandra volumeClaimTemplates: - metadata: name: cassandra-data spec: accessModes: ["ReadWriteOnce"] storageClassName: fast resources: requests: storage: 100GiHeadless Service
Section titled “Headless Service”apiVersion: v1kind: Servicemetadata: name: cassandra labels: app: cassandraspec: ports: - port: 9042 name: cql clusterIP: None selector: app: cassandraClient Service
Section titled “Client Service”apiVersion: v1kind: Servicemetadata: name: cassandra-client labels: app: cassandraspec: ports: - port: 9042 name: cql selector: app: cassandraK8ssandra Operator
Section titled “K8ssandra Operator”Installation
Section titled “Installation”# Add Helm repositoryhelm repo add k8ssandra https://helm.k8ssandra.io/stablehelm repo update
# Install operatorhelm install k8ssandra-operator k8ssandra/k8ssandra-operator -n k8ssandra-operator --create-namespaceAxonOps K8ssandra Integration
Section titled “AxonOps K8ssandra Integration”AxonOps provides production-ready container images that combine Apache Cassandra with K8ssandra Management API and AxonOps monitoring, optimized for Kubernetes deployments.
Components
Section titled “Components”| Component | Description |
|---|---|
| Apache Cassandra 5.0.x | Database engine (versions 5.0.1 – 5.0.7) |
| K8ssandra Management API | Operational control interface |
| AxonOps Agent | Monitoring and management integration |
| cqlai | Modern CQL shell |
| jemalloc | Optimized memory allocator |
Image Versioning
Section titled “Image Versioning”Images use a three-component versioning scheme for full immutability:
{CASSANDRA}-v{K8SSANDRA_API}-{AXONOPS}Example: 5.0.7-v0.1.110-1.0.0
Production Deployments
Pin to specific immutable versions rather than floating latest tags. Digest-based references provide cryptographic guarantees against supply chain attacks.
Required Configuration
Section titled “Required Configuration”| Variable | Description |
|---|---|
AXON_AGENT_KEY | AxonOps API authentication key |
AXON_AGENT_ORG | Organization identifier |
AXON_AGENT_HOST | Server endpoint (default: agents.axonops.cloud) |
Quick Start
Section titled “Quick Start”- Install K8ssandra Operator using the provided script
- Configure AxonOps credentials as environment variables
- Deploy using the example cluster configuration
Documentation and Examples
Section titled “Documentation and Examples”For detailed deployment instructions, configuration options, and production best practices:
Repository: github.com/axonops/axonops-containers/tree/development/k8ssandra
The repository includes:
- Installation scripts for K8ssandra Operator
- Example cluster configurations
- CI/CD workflows for building custom images
- Security scanning and verification procedures
K8ssandraCluster Resource
Section titled “K8ssandraCluster Resource”apiVersion: k8ssandra.io/v1alpha1kind: K8ssandraClustermetadata: name: production-clusterspec: cassandra: serverVersion: "4.1.3" datacenters: - metadata: name: dc1 size: 3 storageConfig: cassandraDataVolumeClaimSpec: storageClassName: fast accessModes: - ReadWriteOnce resources: requests: storage: 500Gi config: jvmOptions: heapSize: 8G resources: requests: cpu: 2 memory: 16Gi limits: cpu: 4 memory: 16Gi stargate: size: 2 reaper: autoScheduling: enabled: true medusa: storageProperties: storageProvider: s3 bucketName: cassandra-backupsStorage Configuration
Section titled “Storage Configuration”Storage Classes
Section titled “Storage Classes”# AWS EBSapiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: fastprovisioner: ebs.csi.aws.comparameters: type: gp3 iops: "3000" throughput: "125"volumeBindingMode: WaitForFirstConsumerallowVolumeExpansion: true
---# GCPapiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: fastprovisioner: pd.csi.storage.gke.ioparameters: type: pd-ssdvolumeBindingMode: WaitForFirstConsumerallowVolumeExpansion: true
---# AzureapiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: fastprovisioner: disk.csi.azure.comparameters: skuName: Premium_LRSvolumeBindingMode: WaitForFirstConsumerallowVolumeExpansion: truePod Disruption Budget
Section titled “Pod Disruption Budget”apiVersion: policy/v1kind: PodDisruptionBudgetmetadata: name: cassandra-pdbspec: maxUnavailable: 1 selector: matchLabels: app: cassandraAnti-Affinity Rules
Section titled “Anti-Affinity Rules”spec: template: spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - cassandra topologyKey: kubernetes.io/hostname preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - cassandra topologyKey: topology.kubernetes.io/zoneScaling
Section titled “Scaling”Scale Up
Section titled “Scale Up”# Scale StatefulSetkubectl scale statefulset cassandra --replicas=5
# Or edit the resourcekubectl edit statefulset cassandraScale Down
Section titled “Scale Down”# Decommission node firstkubectl exec cassandra-4 -- nodetool decommission
# Wait for streaming to completekubectl exec cassandra-4 -- nodetool netstats
# Then scale downkubectl scale statefulset cassandra --replicas=4Monitoring
Section titled “Monitoring”Prometheus Integration
Section titled “Prometheus Integration”apiVersion: monitoring.coreos.com/v1kind: ServiceMonitormetadata: name: cassandraspec: selector: matchLabels: app: cassandra endpoints: - port: metrics interval: 15sBest Practices
Section titled “Best Practices”Resource Management
Section titled “Resource Management”resources: requests: cpu: "2" memory: "8Gi" limits: cpu: "4" memory: "8Gi" # Same as request for predictable performanceHealth Checks
Section titled “Health Checks”readinessProbe: exec: command: - /bin/bash - -c - "nodetool status | grep -E '^UN\\s+${POD_IP}'" initialDelaySeconds: 90 periodSeconds: 30 timeoutSeconds: 10
livenessProbe: exec: command: - /bin/bash - -c - "nodetool info" initialDelaySeconds: 120 periodSeconds: 30 timeoutSeconds: 10Next Steps
Section titled “Next Steps”- AWS Deployment - EKS specifics
- GCP Deployment - GKE specifics
- Operations - Kubernetes operations