别再把 K8s 当“万能盒子”:CockroachDB、Vitess、Cassandra 到底怎么跑?

简介: 别再把 K8s 当“万能盒子”:CockroachDB、Vitess、Cassandra 到底怎么跑?

别再把 K8s 当“万能盒子”:CockroachDB、Vitess、Cassandra 到底怎么跑?

作者:Echo_Wish

很多人第一次在 Kubernetes 上部署数据库,脑子里想的都是一句话:
“数据库嘛,写个 Deployment,挂个 PVC,不就完事了?”

如果只是跑个 MySQL 测试环境,这么干问题可能不大。

但当你面对 CockroachDB、Vitess、Cassandra 这种分布式数据库时,事情就完全不一样了。

因为这时候真正的问题已经不是:

“怎么把数据库跑起来?”

而是:

“Kubernetes 到底能不能把数据库跑稳?”

这篇文章就不绕弯子,我们直接拿 CockroachDB、Vitess、Cassandra 三个典型选手,看看它们在 K8s 上到底应该怎么玩。


一、先说一个很多人容易踩的坑

Kubernetes 很擅长管理:

  • Pod
  • Service
  • Deployment
  • StatefulSet
  • ConfigMap
  • Secret
  • PVC
  • 自动重启
  • 服务发现

但 Kubernetes 并不懂数据库业务。

比如:

Pod 挂了
   ↓
K8s
   ↓
重新创建 Pod
   ↓
数据库恢复了吗?

K8s 的答案是:

“Pod 活了,我任务完成了。”

但数据库真正关心的是:

节点是否加入集群?
数据副本是否完整?
Leader 是否正常?
数据是否同步?
磁盘是否损坏?
节点是否应该重新加入?
集群是否满足 quorum?

所以我一直比较认同一个观点:

K8s 负责“容器活着”,数据库负责“数据活着”。

这两个概念千万不要混在一起。


二、为什么分布式数据库特别适合 StatefulSet?

如果你用过 Deployment,会发现它特别喜欢:

Pod A
Pod B
Pod C

哪个 Pod 死了,随便再拉一个。

但是数据库通常不是这么玩的。

例如 Cassandra:

cassandra-0
cassandra-1
cassandra-2

它们不是三个完全一样的无状态 Pod。

它们都有自己的数据。

所以我们通常使用:

kind: StatefulSet

而不是:

kind: Deployment

StatefulSet 最大的价值之一,就是给数据库提供稳定身份。

比如:

cassandra-0
cassandra-1
cassandra-2

即使:

cassandra-1

重启,它回来以后依然叫:

cassandra-1

同时还能绑定自己的:

PVC

于是就形成:

cassandra-0
   ↓
PVC-0

cassandra-1
   ↓
PVC-1

cassandra-2
   ↓
PVC-2

这才符合数据库的基本逻辑。


三、第一位选手:CockroachDB

Image

Image

Image

Image

Image

Image

CockroachDB 的定位非常有意思。

你可以简单理解成:

“看起来像 PostgreSQL,骨子里是分布式数据库。”

它对开发人员比较友好,因为使用 SQL:

CREATE DATABASE shop;

CREATE TABLE orders (
    id UUID PRIMARY KEY,
    user_id UUID,
    amount DECIMAL
);

但是数据库内部已经不是传统单机数据库那套玩法了。

数据会被拆成多个 Range,然后通过 Raft 进行副本同步。

例如:

                CockroachDB
                     |
        +------------+------------+
        |            |            |
      Node1        Node2        Node3
        |            |            |
      Range A      Range A      Range A
      Range B      Range B      Range B

一个节点挂了:

Node1 ❌

只要副本数量和 quorum 仍然满足:

Node2 ✅
Node3 ✅

整个数据库依然可以继续工作。


四、CockroachDB 在 K8s 怎么部署?

最简单的实验环境可以直接使用 StatefulSet。

例如:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: cockroachdb
spec:
  serviceName: cockroachdb
  replicas: 3
  selector:
    matchLabels:
      app: cockroachdb

  template:
    metadata:
      labels:
        app: cockroachdb

    spec:
      containers:
        - name: cockroachdb
          image: cockroachdb/cockroach:v25.2.0

          command:
            - "/cockroach/cockroach"

          args:
            - "start"
            - "--insecure"
            - "--join=cockroachdb-0.cockroachdb,cockroachdb-1.cockroachdb,cockroachdb-2.cockroachdb"
            - "--advertise-addr=$(POD_NAME)"

          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name

          ports:
            - containerPort: 26257
            - containerPort: 8080

          volumeMounts:
            - name: data
              mountPath: /cockroach/cockroach-data

  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 100Gi

然后:

kubectl apply -f cockroachdb.yaml

检查:

kubectl get pods

应该能看到:

cockroachdb-0
cockroachdb-1
cockroachdb-2

进入 Pod:

kubectl exec -it cockroachdb-0 -- ./cockroach sql --insecure

然后:

SHOW DATABASES;

就可以开始干活了。


五、但是,生产环境千万别直接照抄

上面的:

--insecure

只是为了方便演示。

生产环境你应该考虑:

TLS
RBAC
Secret
NetworkPolicy
备份
监控
资源限制
PodDisruptionBudget
TopologySpreadConstraints

尤其是:

TopologySpreadConstraints

这个东西非常重要。

你不能出现:

Node-A
 ├── cockroach-0
 ├── cockroach-1
 └── cockroach-2

然后 Node-A:

宕机

三个数据库一起没了。

真正合理的是:

K8s Node-A
 └── cockroach-0

K8s Node-B
 └── cockroach-1

K8s Node-C
 └── cockroach-2

分布式数据库最大的敌人,不是 Pod 挂掉,而是你把所有副本放到了同一个故障域。


六、第二位选手:Vitess

Image

Image

Image

Image

Vitess 和 CockroachDB 完全不是一路人。

如果说:

CockroachDB 是“重新设计了一套分布式数据库”。

那么:

Vitess 更像是“把 MySQL 改造成能够横向扩展的数据库平台”。

这也是 Vitess 特别有意思的地方。

假设你有一个巨大的 MySQL:

MySQL
  |
  +-- 10TB 数据
  +-- 100000 QPS
  +-- CPU 爆炸

怎么办?

Vitess 可以把数据库拆成:

                 Vitess
                    |
          +---------+---------+
          |         |         |
       shard-0   shard-1   shard-2
          |         |         |
        MySQL     MySQL     MySQL

例如:

user_id % 3

决定数据去哪。

user_id = 100
100 % 3 = 1

进入:

shard-1

这样就实现水平扩展。


七、Vitess 的核心不是 MySQL,而是“中间层”

Vitess 里面有几个特别重要的组件。

可以简单理解:

Application
     |
     v
   VTGate
     |
     +---------+
     |         |
  VTTablet  VTTablet
     |         |
   MySQL      MySQL

应用程序通常不直接访问 MySQL。

而是:

Application
     ↓
VTGate
     ↓
Shard
     ↓
MySQL

VTGate 会帮助你:

  • 路由 SQL
  • 找 Shard
  • 连接池管理
  • 故障切换
  • 读写路由

所以应用侧甚至可以继续使用:

MySQL Driver

而不用把整个业务推翻重写。

这就是 Vitess 最大的吸引力。


八、Vitess 在 K8s 中尤其适合 Operator

如果自己手写 Vitess 的 StatefulSet,你很快就会发现:

“这玩意儿怎么这么多组件?”

所以生产环境更推荐使用 Vitess Operator 或官方生态提供的 Kubernetes 管理方式。

你最终管理的不是简单的:

Deployment

而更像是:

VitessCluster

然后由 Operator 帮你处理:

VTGate
VTTablet
MySQL
Topology
Backup
Failover

这就是 Kubernetes Operator 真正有价值的地方:

把数据库专家的运维经验,写成 Kubernetes Controller。


九、第三位选手:Cassandra

Image

Image

Image

Image

Image

Cassandra 又是另一种思路。

它特别适合:

海量数据
高写入
高并发
多节点
多数据中心

例如:

IoT
日志
用户行为
时序数据
推荐系统

Cassandra 的核心特点之一就是:

没有传统意义上的单一 Master。

你可以把它理解成:

Node1 ←→ Node2
 ↑        ↓
 ↓        ↑
Node3 ←→ Node4

节点之间共同维护集群状态。

所以它非常适合横向扩展。


十、Cassandra 为什么特别适合 StatefulSet?

因为 Cassandra 非常依赖节点身份和数据目录。

典型结构:

cassandra-0
cassandra-1
cassandra-2
cassandra-3

每个节点:

Pod
 ↓
PVC
 ↓
SSTable

例如:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: cassandra
spec:
  serviceName: cassandra
  replicas: 3

  selector:
    matchLabels:
      app: cassandra

  template:
    metadata:
      labels:
        app: cassandra

    spec:
      containers:
        - name: cassandra
          image: cassandra:5.0

          ports:
            - containerPort: 9042

          env:
            - name: CASSANDRA_CLUSTER_NAME
              value: "prod-cluster"

            - name: CASSANDRA_DC
              value: "dc1"

          volumeMounts:
            - name: data
              mountPath: /var/lib/cassandra

  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes:
          - ReadWriteOnce

        resources:
          requests:
            storage: 200Gi

部署:

kubectl apply -f cassandra.yaml

查看:

kubectl get pods -l app=cassandra

进入节点:

kubectl exec -it cassandra-0 -- cqlsh

查看集群:

nodetool status

你会看到类似:

Datacenter: dc1

Status=Up/Down
State=Normal/Leaving/Joining

UN  cassandra-0
UN  cassandra-1
UN  cassandra-2

十一、三个数据库到底有什么区别?

如果把它们放在一张桌子上:

数据库 核心定位 适合场景
CockroachDB 分布式 SQL 金融、交易、SaaS
Vitess MySQL 扩展平台 大型互联网业务
Cassandra 分布式 NoSQL 海量写入、IoT、日志

更直白一点:

想要 SQL + 分布式?

考虑:

CockroachDB

已经有大量 MySQL?

考虑:

Vitess

数据量巨大、写入量恐怖?

考虑:

Cassandra

十二、真正生产环境,别只盯着 Pod

这是我觉得最容易被忽略的地方。

很多人的数据库监控是:

kubectl get pods

看到:

3/3 Running

然后:

“稳了。”

实际上可能:

Pod:Running
数据库:异常

例如:

PVC 磁盘快满
数据库副本不同步
Leader 频繁切换
GC 爆炸
网络延迟升高

K8s 全都可能告诉你:

Running

所以真正生产环境至少要建立:

Kubernetes
      ↓
Prometheus
      ↓
Grafana
      ↓
Database Metrics

例如监控:

CPU
Memory
Disk
Disk IO
Network
QPS
Latency
Replication
Compaction
Errors
Connections

数据库监控不能只看:

Pod Running

十三、还有一个非常容易被忽略的问题:备份

很多人觉得:

“我用了 3 副本,所以不用备份。”

这是一个非常危险的想法。

假设:

Node1
Node2
Node3

数据都有三份。

然后某个管理员:

kubectl delete pvc --all

你会发现:

三份数据
↓
一起没了

副本解决的是:

节点故障。

备份解决的是:

人为误删、逻辑错误、灾难恢复。

两者完全不是一个东西。


十四、我更建议这样设计

生产环境可以考虑:

                    Internet
                       |
                    Ingress
                       |
                    Service
                       |
              +--------+--------+
              |                 |
           App Pod           App Pod
              |                 |
              +--------+--------+
                       |
                    Database
                       |
        +--------------+--------------+
        |              |              |
      Node-A         Node-B         Node-C
        |              |              |
      DB-0           DB-1           DB-2
        |              |              |
      PVC-A          PVC-B          PVC-C

再往上:

Prometheus
    ↓
Grafana

旁边再放:

Backup
  ↓
Object Storage

例如:

S3 / MinIO / OSS

最终形成:

业务
 ↓
K8s
 ↓
分布式数据库
 ↓
PVC
 ↓
Backup
 ↓
对象存储

这才是比较完整的生产体系。


十五、最后聊聊:K8s 到底适不适合跑数据库?

我的观点非常明确:

适合,但绝不是“部署一个 StatefulSet 就完事”。

Kubernetes 最大的价值并不是:

kubectl apply

而是把:

部署
扩容
故障恢复
服务发现
配置管理
监控
滚动升级
资源隔离

这些东西统一起来。

但是数据库本身的:

数据一致性
副本
Leader
Quorum
分片
故障转移
备份
恢复

仍然需要数据库自己解决。

所以真正成熟的架构应该是:

Kubernetes
     +
Operator
     +
StatefulSet
     +
Persistent Volume
     +
Monitoring
     +
Backup
     +
Database Native HA

而不是:

Kubernetes
     +
PVC
     =
数据库高可用

这两个结论,看起来只差几个组件,实际上差的是整个运维思维。


写在最后

CockroachDB、Vitess、Cassandra,其实代表了三种完全不同的数据库发展路线:

CockroachDB
     ↓
重新设计分布式 SQL

Vitess
     ↓
让 MySQL 走向水平扩展

Cassandra
     ↓
为海量数据和高吞吐而生

而 Kubernetes 更像是一个“基础设施操作系统”。

它可以帮你管理这些数据库,但它不会替你理解数据库。

所以如果你准备把分布式数据库放进 K8s,我建议先问自己三个问题:

第一,我为什么需要分布式数据库?

第二,我到底需要分片,还是需要副本?

第三,如果整个 Kubernetes 集群明天没了,我的数据怎么回来?

尤其是第三个问题。

很多所谓的“高可用架构”,平时看起来一个比一个漂亮,真正遇到故障的时候才发现:

Pod 是自动拉起来了,但数据呢?

这才是 K8s 上跑数据库真正值得思考的地方。

我是 Echo_Wish,一个喜欢把复杂技术掰开揉碎聊给你听的运维人。

如果只记住今天的一句话,我希望是:

K8s 能帮你把数据库“跑起来”,但只有数据库架构、存储、备份和故障恢复体系,才能让它真正“跑得住”。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
4天前
|
消息中间件 缓存 监控
流量一上来就扛不住?别硬撑了,该降级就降级!
流量一上来就扛不住?别硬撑了,该降级就降级!
38 0
|
29天前
|
运维 监控 NoSQL
事故复盘不是写检讨,而是让团队变强的一次机会
事故复盘不是写检讨,而是让团队变强的一次机会
115 1
|
1月前
|
消息中间件 运维 Cloud Native
Kafka / Pulsar 数据越来越多,磁盘却越来越小?聊聊实时流平台的容量与回溯
Kafka / Pulsar 数据越来越多,磁盘却越来越小?聊聊实时流平台的容量与回溯
144 6
|
1月前
|
人工智能 运维 安全
运维别只盯着服务器:真正危险的,是你日志里的那些数据
运维别只盯着服务器:真正危险的,是你日志里的那些数据
105 1
|
1月前
|
SQL 分布式计算 大数据
大数据成本为什么越跑越高?别急着加机器,Spot + 队列调度可能省下一半
大数据成本为什么越跑越高?别急着加机器,Spot + 队列调度可能省下一半
97 2
|
1月前
|
SQL 运维 分布式计算
数据越多越乱?真正让大数据平台失控的,可能不是数据,而是“没人知道数据是什么”
数据越多越乱?真正让大数据平台失控的,可能不是数据,而是“没人知道数据是什么”
127 1
|
1月前
|
运维 监控 NoSQL
别再写“演练方案”了:真正靠谱的 Incident Playbook,应该能直接跑起来
别再写“演练方案”了:真正靠谱的 Incident Playbook,应该能直接跑起来
80 0
|
1月前
|
运维 监控 BI
SLO到底怎么定?复杂系统千万别一上来就拍脑袋定99.99%
SLO到底怎么定?复杂系统千万别一上来就拍脑袋定99.99%
141 0
|
1月前
|
存储 Prometheus 监控
Prometheus 监控越跑越胖?别急着加硬盘,TSDB 压缩才是关键
Prometheus 监控越跑越胖?别急着加硬盘,TSDB 压缩才是关键
168 0
|
1月前
|
数据采集 SQL BI
DataOps 真不是“把数据跑起来”:真正难的是出了问题,你能不能找到锅在哪
DataOps 真不是“把数据跑起来”:真正难的是出了问题,你能不能找到锅在哪
97 0

热门文章

最新文章