statefulset 部署 cassandra 仅适用于验证环境,因其缺乏自动故障自愈、扩缩容和配置变更能力;生产环境应选用 k8ssandra,但其 operator 初始化失败多因 crd 缺失、rbac 权限不足或 storageclass 不匹配。

直接上结论:别用裸 StatefulSet 部署生产级 Cassandra,它扛不住配置变更、节点扩缩容和故障自愈;K8ssandra 是目前最接近开箱即用的方案,但它的 operator 依赖 CRD 和 RBAC 权限,初始化失败多半卡在这两步。
StatefulSet 部署 Cassandra 为什么只适合验证环境
StatefulSet 确实能跑起一个三节点 cassandra ring,但它把所有“集群智能”推给了配置脚本和人工干预。比如 CASSANDRA_SEEDS 必须硬编码成 cassandra-0.cassandra.default.svc.cluster.local,一旦 Pod 重建或网络策略变化,新节点根本连不上种子——不是报 Unable to gossip with any seeds,就是卡在 JOINING 状态。
常见错误现象:
- Pod 一直 Pending,
kubectl describe pod cassandra-0显示FailedScheduling: 0/3 nodes are available: 3 node(s) didn't match Pod's node affinity/selector(因为没配topologySpreadConstraints或 storageClassName 不匹配) - Pod Running 但
cqlsh cassandra-0.cassandra.default.svc.cluster.local连不上,查日志发现BindException: Address already in use(多个容器复用同一 hostPort 或 volume mount 路径冲突) - 扩容到 4 副本后,
nodetool status只显示 3 个 UP 节点,第 4 个始终是DN(StatefulSet 不会自动触发nodetool rebuild或更新seeds列表)
真正要用 StatefulSet,你得自己写 initContainer 注入 seed provider、用 preStop 执行 nodetool drain、挂载 configmap 并监听热重载——这些工作量已逼近写一个简易 operator。
K8ssandra Operator 初始化失败的三个高频原因
K8ssandra 的核心是 cass-operator,它通过 CassandraDatacenter CR 控制集群生命周期。但安装时最容易栽在权限和依赖上:
-
CustomResourceDefinition没装全:运行kubectl get crd | grep cassandra,必须看到cassandradatacenters.cassandra.datastax.com、cassandrapermissions.cassandra.datastax.com等至少 5 个 CRD;少一个,kubectl apply -f k8ssandra.yaml就静默失败 - RBAC 权限不足:operator 默认用
system:serviceaccount:k8ssandra:cass-operator账号运行,但如果你改了 namespace,必须同步更新ClusterRoleBinding中的namespace字段,否则 operator 日志里全是Forbidden: unable to list pods - StorageClass 名字不一致:K8ssandra Helm chart 默认用
standard,但 Minikube 是standard-rwo,EKS 是gp3;不改storageConfig.storageClassName,PVC 永远 Pending
验证是否就绪:kubectl -n k8ssandra get cassandradatacenter 应返回 Ready 状态;如果卡在 Provisioning,先看 kubectl -n k8ssandra logs deploy/cass-operator。
针对 Kubernetes 仪表板和 Web UI 的浏览器自动化。适用于与 Kubernetes Dashboard、Grafana、ArgoCD UI 或其他 Web 界面交互。需要设置 MCP_BROWSER_ENABLED=true。
备份与恢复必须绕开 Medusa 的 S3 认证陷阱
K8ssandra 自带 medusa 做备份,但它默认走 IAM Role(AWS)或 service account annotation(GCP),本地 Minikube 或私有云容易卡在认证环节。最稳的方式是显式传入 access key:
apiVersion: cassandra.datastax.com/v1beta1
kind: CassandraBackup
metadata:
name: full-backup
spec:
datacenter: dc1
type: full
storageProperties:
storageProvider: s3
bucketName: my-cassandra-backups
region: us-east-1
keyFile: /etc/medusa/secrets/credentials
# 注意:这个路径必须和 medusa container 中的 volumeMount 严格一致
关键点:
-
keyFile对应的 Secret 必须用kubectl create secret generic medusa-secrets --from-file=credentials=./aws-creds创建,且文件内容格式为[default]\naws_access_key_id = XXX\naws_secret_access_key = YYY - 不要用
medusa restore命令行手动恢复——Operator 会接管 PVC 生命周期,直接删掉旧 Pod 让它重建,新 Pod 启动时自动拉取最新备份 - Medusa 备份默认不包含
systemkeyspace,恢复后需手动nodetool repair system,否则下次重启可能无法选举
Stargate API 网关的端口暴露方式选错等于白装
Stargate 提供 REST / GraphQL / Schema API,但它默认只绑定 localhost:8080。想从集群外访问,不能只改 Service 类型为 LoadBalancer:
- 用 NodePort:必须在
StargateDatacenterCR 中显式设置serviceTemplate.type: NodePort,否则 Stargate Pod 内的容器仍监听 127.0.0.1 - 用 Ingress:需要额外加注解
nginx.ingress.kubernetes.io/upstream-vhost: "localhost:8080",因为 Stargate 校验 Host header - 最简验证法:先
kubectl port-forward svc/stargate 8080:8080 -n k8ssandra,再curl -X POST http://localhost:8080/v2/keyspaces看是否返回空数组——通了再往外暴露
真正麻烦的是 TLS 终止位置:如果 TLS 在 Ingress 层终结,Stargate 收到的是 HTTP 请求,但它的 health check 默认发 HTTPS,得关掉 stargate.spec.healthCheck.enabled: false 或改用 HTTP 探针。
Operator 模式不是银弹——它把运维逻辑代码化了,但也意味着你得读懂它的 reconcile 循环行为。比如修改 CassandraDatacenter.spec.size 后,operator 不会立刻滚动更新,而是等当前节点完成 nodetool cleanup 才扩下一个;这个等待时间可能长达几十分钟,监控不到位的话,会误判为卡死。










