使用 K8ssandra 通过 MinIO 备份和恢复 Cassandra

使用 K8ssandra 通过 MinIO 备份和恢复 Cassandra

Apache Cassandra 是一种分布式 NoSQL 数据库,在开发人员社区中广受欢迎。从 Ably 到 Yelp,Cassandra 之所以得到普遍部署,是因为它能够快速处理跨 PB 数据的查询并扩展到数百或数千个节点。Cassandra 可以相对轻松地部署到任何环境,它可以无缝向上和向外扩展,并且在分布式模式下运行良好。它在存储数据方面也很灵活,可以在不影响性能和速度的情况下处理大量数据。它是开源的,因此当需要修复时,迭代周期很快,而且 Cassandra 查询语言 (CQL) 对于任何使用过 SQL 语法的人来说都很容易学习。

Cassandra 通常用于编写密集型数据模型,如指标/时间序列数据、历史查看页面、出租车跟踪等。当谈到 Cassandra 时,人们最强调的是拥有具有适当用例的正确数据模型。当然,为了获得愉快的 Cassandra 体验,请确保正确调整 JVM。

Cassandra 有几种不同的风格:

  • Apache 版本是 Cassandra 的原始开源版本,由 Meta/Facebook 开发。它具有运行 Cassandra 所需的所有核心功能,但支持是基于社区的。您必须熟悉命令行工具才能管理和操作集群。

  • Cassandra 的 Datastax 版本建立在开源之上,但侧重于企业的安全性和可支持性。例如,它提供的一个很酷的功能是 OpsCenter,这是一个基于浏览器的控制台 UI,可显示集群的状态并可用于执行操作任务。

有几种部署 Cassandra 的方法;裸机、VM、容器等。今天我们将在K8ssandra的帮助下将其部署到 Kubernetes 集群。这将为我们的 Cassandra 集群设置所有必要的脚手架,以便立即启动和运行。

无论您使用哪种方法部署 Cassandra,将其与云原生对象存储配对以充分利用它都是有意义的。MinIO 是 Cassandra/K8ssandra 的完美补充,因为它具有业界领先的性能和可扩展性。MinIO 将可扩展性和高性能相结合,使每个数据密集型工作负载都触手可及,而不仅仅是 Cassandra。MinIO 具有惊人的性能——最近的基准测试在 GET 上达到了 325 GiB/s (349 GB/s),在 PUT 上达到了 165 GiB/s (177 GB/s),只有 32 个现成的 NVMe SSD 节点。  

MinIO 被设计和构建为Kubernetes 原生和云原生,并可从 TB 无缝扩展到 EB 及更多。MinIO 租户在自己的命名空间中彼此完全隔离。通过遵循 Kubernetes 插件和操作符范例,MinIO 可以无缝地融入现有的 DevOps 实践和工具链,从而使自动化 Cassandra 备份操作成为可能。MinIO 为 Cassandra 备份提供了一个安全的家。写入 MinIO 的数据是不可变的版本化的并受纠删码保护让我们看看如何使用 MinIO 快速备份和恢复数据以最大程度地减少停机时间。


CassandraMinIO.jpeg


先决条件

在我们开始之前,您需要为我们的安装准备好一些先决条件。

  • Kubernetes 集群(Minikube、Kind 等)

在这个导览中,我们将使用 Minikube 作为我们选择的 Kubernetes 集群,但任何正确配置的 Kubernetes 集群都可以工作。

卡桑德拉

我们可以通过多种方式安装 Apache Cassandra。在此示例中,我们将使用K8ssandra以半自动方式部署 Cassandra 

配置

我们将使用以下规范部署一个简单的 Cassandra 集群,将此 yaml 保存为k8ssandra.yaml.

cassandra:
  version: "3.11.10"
  cassandraLibDirVolume:
    storageClass: local-path
    size: 5Gi
  allowMultipleNodesPerWorker: true
  heap:
  size: 1G
  newGenSize: 1G
  resources:
    requests:
      cpu: 1000m
      memory: 2Gi
    limits:
      cpu: 1000m
      memory: 2Gi
  datacenters:
  - name: dc1
    size: 1
    racks:
    - name: default
kube-prometheus-stack:
  grafana:
    adminUser: admin
    adminPassword: admin123
stargate:
  enabled: true
  replicas: 1
  heapMB: 256
  cpuReqMillicores: 200
  cpuLimMillicores: 1000
medusa:
  enabled: true
  storage: s3_compatible
  storage_properties:
      host: minio
      port: 9000
      secure: "False"
  bucketName: k8ssandra-medusa
  storageSecret: medusa-bucket-key

我们不会通过整个规范,但我们将通过下面的一些关键组件:

存储类

您可以使用几种不同的存储类,但主要要求是VOLUMEBINDINGMODE应该是WaitForFirstConsumer.

不支持默认存储类模式,所以让我们创建一个 rancherlocal-path存储类。

kubectl get storageclass

NAME                 PROVISIONER                RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
standard (default)   k8s.io/minikube-hostpath   Delete          Immediate           false                  4m33s             

kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml


namespace/local-path-storage created

serviceaccount/local-path-provisioner-service-account created

clusterrole.rbac.authorization.k8s.io/local-path-provisioner-role created

clusterrolebinding.rbac.authorization.k8s.io/local-path-provisioner-bind created

deployment.apps/local-path-provisioner created

storageclass.storage.k8s.io/local-path created

configmap/local-path-config created


现在您应该看到具有正确配置的第二个存储类

kubectl get storageclass

NAME                 PROVISIONER                RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path           rancher.io/local-path      Delete          WaitForFirstConsumer   false                  20s
standard (default)   k8s.io/minikube-hostpath   Delete          Immediate              false                  6m30s

美杜莎

Medusa 是 Apache Cassandra 生态系统的一个组成部分。Medusa 的核心是协调 Cassandra 集群的备份和恢复。

特别感兴趣的领域是:

  • host

  • port

  • storageSecret

  • bucketName

这些字段允许您连接到 MinIO 以执行备份和恢复操作。

存储秘密

存储机密是一个 Kubernetes 机密,我们将使用凭据创建它以连接到 MinIO。将以下内容放在一个名为的文件中minio-medusa-secret.yaml

apiVersion: v1
kind: Secret
metadata:
name: medusa-bucket-key
type: Opaque
stringData:
medusa_s3_credentials: |-
  [default]
  aws_access_key_id = miniok8ssandra_key
  aws_secret_access_key = miniok8ssandra_secret

  • metadata.name必须匹配storageSecret中的字段k8ssandra.yaml

  • aws_access_key_id并且aws_secret_access_key必须分别匹配 MinIO 的accessKeysecretKey

minio-medusa-secret.yaml在集群中申请资源

  • kubectl apply -f minio-medusa-secret.yaml

secret/medusa-bucket-key created

  • 验证与kubectl get secret medusa-bucket-key

NAME                TYPE     DATA   AGE
medusa-bucket-key   Opaque   1      12s

安装中

安装添加 K8ssandra Helm 存储库并更新 helm

  • 添加回购helm repo add k8ssandra https://helm.k8ssandra.io/stable

  • 验证与helm repo list

  • 运行helm repo update以拉取最新更新

使用 K8ssandra 安装 Apache Cassandra,确保存在秘密的 medusa-bucket-key。

  • helm install -f k8ssandra.yaml k8ssandra k8ssandra/k8ssandra

上面的命令应该执行以下操作:

  • 创建一个名为 的 Cassandra 集群k8ssandra

  • 将集群部署到defaultKubernetes 命名空间。

至少等待 5 分钟,直到集群完全联机。如果你运行,kubectl get pods你应该看到它们都处于运行状态。

NAME                                                 READY   STATUS             RESTARTS      AGE
k8ssandra-cass-operator-699b8c4cbc-ptbtk             1/1     Running            0             3m35s
k8ssandra-dc1-default-sts-0                          2/3     CrashLoopBackOff   4 (14s ago)   3m23s
k8ssandra-dc1-stargate-556ddcc5-8rb7v                0/1     Init:0/1           0             3m34s
k8ssandra-grafana-795f9865fc-7v9lq                   2/2     Running            0             3m35s
k8ssandra-kube-prometheus-operator-9544bb7bf-b8m6k   1/1     Running            0             3m35s
k8ssandra-medusa-operator-66d8969ff9-knkd6           1/1     Running            0             3m35s
k8ssandra-reaper-operator-77554f9458-zd5mh           1/1     Running            0             3m35s
prometheus-k8ssandra-kube-prometheus-prometheus-0    2/2     Running            0             3m31s
                                 

让我们借此机会探索调试方法。这有点超出介绍性教程的范围,但从长远来看会有所帮助。

调试

让我们描述一下 pod 看看它卡在什么上面

  • kubectl describe pod k8ssandra-dc1-default-sts-0

 

medusa:

      ……

    State:          Waiting

      Reason:       CrashLoopBackOff

    Last State:     Terminated

      Reason:       Error

      Exit Code:    1

      ……


我们可以从上面描述的输出中看到medusa容器有问题,让我们看看它logs是否可以确定问题是什么:

  • kubectl logs k8ssandra-dc1-default-sts-0 -c medusa

[2022-07-06 14:06:18,778] DEBUG: Starting new HTTP connection (1): minio:9000
...
socket.gaierror: [Errno -2] Name or service not known
...

啊哈!似乎连接到 MinIO 服务时出现问题。这是有道理的,因为我们没有minio在集群中运行任何名为 running 的服务。

$ kubectl get service

NAME                                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                 AGE
k8ssandra-dc1-additional-seed-service   ClusterIP   None            <none>        <none>                                                  3h26m
k8ssandra-dc1-all-pods-service          ClusterIP   None            <none>        9042/TCP,8080/TCP,9103/TCP                              3h26m
k8ssandra-dc1-service                   ClusterIP   None            <none>        9042/TCP,9142/TCP,8080/TCP,9103/TCP,9160/TCP            3h26m
k8ssandra-dc1-stargate-service          ClusterIP   10.110.1.67     <none>        8080/TCP,8081/TCP,8082/TCP,8084/TCP,8085/TCP,9042/TCP   3h27m
k8ssandra-grafana                       ClusterIP   10.100.244.68   <none>        80/TCP                                                  3h27m
k8ssandra-kube-prometheus-operator      ClusterIP   10.96.25.118    <none>        443/TCP                                                 3h27m
k8ssandra-kube-prometheus-prometheus    ClusterIP   10.104.105.81   <none>        9090/TCP                                                3h27m
k8ssandra-reaper-reaper-service         ClusterIP   10.98.35.86     <none>        8080/TCP                                                3h26m
k8ssandra-seed-service                  ClusterIP   None            <none>        <none>                                                  3h26m
kubernetes                              ClusterIP   10.96.0.1       <none>        443/TCP                                                 5h3m
prometheus-operated                     ClusterIP   None            <none>        9090/TCP                                                3h26m                                                                              

提示:如果您遇到任何备份/恢复问题并且需要额外的调试信息,您可以在 medusa 容器中找到大部分详细信息。

最小IO

正如我们发现的那样,要启动 medusa 容器,我们需要先让 MinIO 在线。我们也将使用 Helm 来设置 MinIO。

安装中

安装添加 MinIO Helm 存储库并更新 helm

  • 添加回购helm repo add minio https://helm.min.io/

  • 验证与helm repo list

  • 运行helm repo update以拉取最新更新

使用 helm 命令安装 MinIO:

  • helm install --set accessKey=miniok8ssandra_key,secretKey=miniok8ssandra_secret,defaultBucket.enabled=true,defaultBucket.name=k8ssandra-medusa minio minio/minio

  • accessKey并且secretKey必须分别匹配aws_access_key_idaws_secret_access_key中的minio-medusa-secret.yaml.

  • defaultBucket.name必须bucketName匹配k8ssandra.yaml

上面的命令将执行以下操作:

  • 创建名为 的部署和服务minio

  • 将 MinIO 部署到defaultKubernetes 命名空间。

如果您等待几分钟并运行 kubectl get pods,您应该会看到所有这些都处于Running状态。但是如果你和我一样没有耐心,想看到美杜莎容器快点上来,直接删掉k8ssandra-dc1-default-sts-0 pod

  • kubectl delete pod k8ssandra-dc1-default-sts-0

大约一分钟后,您应该会看到所有的 pod 都在运行:

kubectl get po
NAME                                                 READY   STATUS    RESTARTS   AGE
k8ssandra-cass-operator-699b8c4cbc-s7qqz             1/1     Running   0          3h46m
k8ssandra-dc1-default-sts-0                          3/3     Running   0          3h34m
k8ssandra-dc1-stargate-556ddcc5-mz2fp                1/1     Running   0          3h46m
k8ssandra-grafana-795f9865fc-95pwc                   2/2     Running   0          3h46m
k8ssandra-kube-prometheus-operator-9544bb7bf-f6nxb   1/1     Running   0          3h46m
k8ssandra-medusa-operator-66d8969ff9-svbbw           1/1     Running   0          3h46m
k8ssandra-reaper-679fd4fc7d-lbjhw                    1/1     Running   0          3h33m
k8ssandra-reaper-operator-77554f9458-zkdcl           1/1     Running   0          3h46m
minio-5fb8f49576-l2s7l                               1/1     Running   0          3h37m
prometheus-k8ssandra-kube-prometheus-prometheus-0    2/2     Running   0          3h46m                            


验证桶

我们如何检查 Medusa 是否能够连接到 MinIO?那么有一个非常简单的方法。如果我们转发 MinIO 控制台并登录,我们应该会看到一个名为k8ssandra-medusa.

  • kubectl port-forward service/minio 39000:9000

  • 使用浏览器,转到http://localhost:39000

  • accessKey分别使用和用户名和密码登录secretKey

  • 如果您看到桶,则 Medusa 能够成功连接到 MinIO。


Screen Shot 2022-07-04 at 8.58.21 PM.png



备份

为了测试备份,有几个先决条件:

  • cqlsh:用于与 Cassandra 集群交互的实用程序。

  • 我们可以水化、删除和恢复以显示功能的测试数据。

安装cqlsh

为了与 Cassandra 交互,我们将使用一个名为 cqlsh 的实用程序。

使用 pip 安装 cqlsh

  • pip3 install cqlsh

获取 Cassandra 超级用户凭据

  • kubectl get secret k8ssandra-superuser -o jsonpath="{.data.username}" | base64 --decode ; echo

  • kind kubectl get secret k8ssandra-superuser -o jsonpath="{.data.password}" | base64 --decode ; echo

为 cqlsh 打开端口转发以访问我们的 Cassandra 集群

  • kubectl port-forward svc/k8ssandra-dc1-stargate-service 8080 8081 8082 9042

登录到cqlsh

  • cqlsh -u-p

水合物数据

能够登录后,您应该会看到如下提示:

  • @cqlsh>

将以下 blob 复制并粘贴到 REPL 中,然后运行它

CREATE KEYSPACE medusa_test  WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};
USE medusa_test;
CREATE TABLE users (email text primary key, name text, state text);
insert into users (email, name, state) values ('alice@example.com', 'Alice Smith', 'TX');
insert into users (email, name, state) values ('bob@example.com', 'Bob Jones', 'VA');
insert into users (email, name, state) values ('carol@example.com', 'Carol Jackson', 'CA');
insert into users (email, name, state) values ('david@example.com', 'David Yang', 'NV');

运行上述 blob 后,让我们验证数据是否已正确输入

  • SELECT * FROM medusa_test.users;

email             | name          | state
-------------------+---------------+-------
alice@example.com |   Alice Smith |    TX
  bob@example.com |     Bob Jones |    VA
david@example.com |    David Yang |    NV
carol@example.com | Carol Jackson |    CA

(4 rows)

现在我们终于可以使用以下命令备份到 MinIO,因为这是一个小数据集,应该不会花太长时间。

  • helm install demo-backup k8ssandra/backup --set name=backup1,cassandraDatacenter.name=dc1

请务必记下本教程稍后用于恢复所需的备份名称。

验证备份的状态。如果以下命令返回时间戳,则表示备份成功。

  • kubectl get cassandrabackup backup1 -o jsonpath={.status.finishTime}

您还应该验证备份是否也在 MinIO 控制台中创建:

  • 设置端口转发kubectl port-forward service/minio 39000:9000

  • 转到 MinIO 控制台http://localhost:39000


Screen Shot 2022-07-05 at 6.42.34 PM.png



恢复

现在我们能够确认备份成功,作为 SRE/DevOps 工程师,您还需要测试以确保您能够恢复它。使用整个数据集测试还原以确保您能够还原所有内容。

删除数据

仍在cqlsh>REPL 中,删除现有数据。

  • TRUNCATE medusa_test.users;

验证数据实际上已被删除

  • SELECT * FROM medusa_test.users;

email | name | state
-------+------+-------

(0 rows)


当我们有数据时有 4 行,现在我们有 0 行。

获取备份

与我们运行备份的方式类似,我们也将使用 helm 来恢复

  • helm install demo-restore k8ssandra/restore --set name=restore-backup1,backup.name=backup1,cassandraDatacenter.name=dc1

在上面的命令中,backup.name 应该与原始备份的名称相匹配。

检查备份状态

  • kubectl get cassandrarestore restore-backup1 -o jsonpath={.status}

当您finishTime在输出中看到时,表示还原已成功完成。您可以验证这一点的另一种方法是再次获取用户列表

  • SELECT * FROM medusa_test.users;

email             | name          | state
-------------------+---------------+-------
alice@example.com |   Alice Smith |    TX
  bob@example.com |     Bob Jones |    VA
david@example.com |    David Yang |    NV
carol@example.com | Carol Jackson |    CA

(4 rows)


结论

给你!让我们回顾一下我们做了什么:

  • 我们使用 K8ssandra 将 Cassandra 部署到 Kubernetes

  • 我们部署了 MinIO 对象存储

  • 我们成功地将 Apache Cassandra 中的数据备份到 MinIO 对象存储并从中恢复。

您可以更进一步并执行灾难恢复方案,您可以从头启动一个新集群,将 Medusa 连接到 MinIO,然后开始从以前备份的数据副本恢复。试一试,让我们知道进展如何!

上一篇 下一篇