
我们经常遇到Apache Cassandra数据库,以及在基于Kubernetes的基础架构的框架内对其进行操作的需求。 在本文中,我们将分享我们对将Cassandra迁移到K8的必要步骤,标准和现有解决方案(包括操作员的概述)的看法。
“谁能控制一个女人就能应付国家”
谁是卡桑德拉? 它是一种分布式存储系统,旨在管理大量数据,同时提供高可用性而不会出现单点故障。 该项目几乎不需要冗长的介绍,因此我仅给出Cassandra的主要功能,这些功能在特定文章的上下文中是相关的:
- Cassandra用Java编写。
- Cassandra拓扑包括几个级别:
- 节点-一个已部署的Cassandra实例;
- 机架-位于一个数据中心的一组Cassandra实例,由任何属性结合在一起;
- 数据中心-位于一个数据中心中的所有Cassandra实例组的总数;
- 群集-所有数据中心的集合。
- Cassandra使用IP地址来标识主机。
- 为了提高读取和写入操作的速度,Cassandra将部分数据存储在RAM中。
现在将实际潜力转移到Kubernetes。
迁移清单
在谈到将Cassandra迁移到Kubernetes时,我们希望通过此举可以更加方便地进行管理。 为此需要什么,对此有什么帮助?
1.数据存储
如前所述,
Cassanda的部分数据存储在RAM中的
Memtable中 。 但是还有另一部分数据以
SSTable的形式保存到磁盘中。 向该数据添加实体
日志日志 -所有也保存到磁盘的事务的记录。
卡桑德拉写交易方案在Kubernetes中,我们可以使用PersistentVolume来存储数据。 得益于完善的机制,每年在Kubernetes中处理数据变得更加容易。
对于使用Cassandra的每个吊舱,我们将分配PersistentVolume重要的是要注意,Cassandra本身就意味着数据复制,为此提供了内置的机制。 因此,如果要从大量节点构建Cassandra集群,则无需使用Ceph或GlusterFS之类的分布式系统来存储数据。 在这种情况下,使用
本地持久性磁盘或挂载
hostPath
将数据存储在主机磁盘上是合乎逻辑的。
另一个问题是,是否要为每个功能分支创建一个单独的开发环境。 在这种情况下,正确的方法是增加一个Cassandra节点,并将数据存储在分布式存储中,即 提及的Ceph和GlusterFS将是您的选择。 然后,开发人员将确保即使Kuberntes集群的节点之一丢失,他也不会丢失测试数据。
2.监控
Prometheus实际上是在Kubernetes中进行监视的一种非替代选择
(我们在相应的报告中对此进行了详细讨论) 。 Cassandra如何与Prometheus的公制出口商合作? 而且,对于Grafana而言,合适的仪表板在某种程度上甚至更重要吗?
Grafana中Cassandra的图形外观示例只有两个导出器:
jmx_exporter和
cassandra_exporter 。
我们为自己选择了第一个,因为:
- JMX Exporter正在成长和发展,而Cassandra Exporter尚未获得适当的社区支持。 Cassandra Exporter仍然不支持大多数版本的Cassandra。
- 您可以通过添加
-javaagent:<plugin-dir-name>/cassandra-exporter.jar=--listen=:9180
标志将其作为javaagent运行-javaagent:<plugin-dir-name>/cassandra-exporter.jar=--listen=:9180
。 - 对他来说,有一个足够的仪表板与Cassandra Exporter不兼容。
3. Kubernetes原语的选择
根据Cassandra集群的上述结构,我们将尝试将其中描述的所有内容转换为Kubernetes术语:
- Cassandra节点→荚
- 卡桑德拉机架→StatefulSet
- Cassandra数据中心→来自StatefulSets的池
- 卡桑德拉群集→???
事实证明,缺少一些额外的实体来一次管理整个Cassandra集群。 但是,如果不存在某些内容,我们可以创建它! Kubernetes有一个专用的资源定义引擎,称为“
自定义资源定义” 。
宣布用于日志和警报的其他资源但是,“自定义资源”本身并不意味着任何事情:您需要一个
控制器 。 您可能不得不求助于
Kubernetes运营商的帮助...
4.豆荚的识别
上面的观点,我们同意一个Cassandra节点等于Kubernetes中的一个pod。 但是pod的IP地址每次都会不同。 而且,Cassandra中的节点标识正是基于IP地址进行的。事实证明,每次删除Pod之后,Cassandra群集将添加一个新节点。
有一个出路,甚至没有:
- 我们可以通过主机标识符(唯一标识Cassandra实例的UUID)或IP地址来保存记录,并将所有这些保存在某些结构/表中。 该方法有两个主要缺点:
- 当两个节点同时掉落时出现竞争状况的风险。 升级后,Cassandra节点将同时从表中为自己请求IP地址,并争夺同一资源。
- 如果Cassandra节点丢失了数据,我们将不再能够识别它。
- 第二种解决方案看起来像是一个小技巧,但是尽管如此:我们可以为每个Cassandra节点使用ClusterIP创建服务。 此实现存在的问题:
- 如果Cassandra集群中有很多节点,我们将不得不创建很多服务。
- ClusterIP功能是通过iptables实现的。 如果Cassandra群集具有许多(1000个甚至100个?)节点,可能会出现问题。 尽管基于IPVS的平衡可以解决此问题。
- 第三种解决方案是通过启用
hostNetwork: true
设置,将节点的网络用于Cassandra节点,而不是专用的pod网络。 此方法施加了某些限制:
- 替换节点。 新主机必须具有与前一主机相同的IP地址(在像AWS,GCP这样的云中,这几乎是不可能的);
- 使用群集节点的网络,我们开始争夺网络资源。 因此,在一个群集节点上使用Cassandra放置一个以上的Pod将是一个问题。
5.备份
我们希望按计划保留一个Cassandra节点的完整数据版本。 Kubernetes提供了使用
CronJob的便利机会,但是在这里Cassandra可以将
操纵杆插入车轮。
让我提醒您,Cassandra存储在内存中的部分数据。 要进行完整备份,您需要将数据从内存(
Memtables )传输到磁盘(
SSTables )。 此时,Cassandra节点停止接受连接,从而完全从集群关闭。
之后,将删除备份(
快照 )并
保存方案(
密钥空间 )。 然后事实证明,仅备份并不能给我们任何好处:您需要保存Cassandra节点负责的数据标识符-这些是特殊标记。
令牌分发以识别负责Cassandra节点的数据在
此链接中可以找到从Kubernetes中的Google删除Cassandra的示例脚本。 脚本不考虑的唯一一点是在删除快照之前将数据转储到节点。 也就是说,不针对当前状态执行备份,而是针对较早的状态执行备份。 但这有助于避免使节点失效,这似乎很合逻辑。
set -eu if [[ -z "$1" ]]; then info "Please provide a keyspace" exit 1 fi KEYSPACE="$1" result=$(nodetool snapshot "${KEYSPACE}") if [[ $? -ne 0 ]]; then echo "Error while making snapshot" exit 1 fi timestamp=$(echo "$result" | awk '/Snapshot directory: / { print $3 }') mkdir -p /tmp/backup for path in $(find "/var/lib/cassandra/data/${KEYSPACE}" -name $timestamp); do table=$(echo "${path}" | awk -F "[/-]" '{print $7}') mkdir /tmp/backup/$table mv $path /tmp/backup/$table done tar -zcf /tmp/backup.tar.gz -C /tmp/backup . nodetool clearsnapshot "${KEYSPACE}"
bash脚本示例,用于从单个Cassandra节点删除备份Kubernetes中Cassandra的现成解决方案
他们目前在Kubernetes中使用什么来部署Cassandra,哪些最适合给定的需求?
1. StatefulSet或Helm Chart解决方案
使用基本的StatefulSets启动Cassandra集群是一个不错的选择。 使用Helm chart和Go模板,可以为用户提供用于部署Cassandra的灵活界面。
通常,这可以正常工作...直到发生意外情况-例如,某个节点出现故障。 标准的Kubernetes工具根本无法考虑所有上述功能。 此外,这种方法在如何扩展以更复杂的使用方面非常有限:节点替换,备份,还原,监视等。
代表:
两种图表都同样好,但是容易出现上述问题。
2.基于Kubernetes运营商的解决方案
此类选项更为有趣,因为它们提供了广泛的群集管理功能。 与其他任何数据库一样,要设计Cassandra语句,良好的模式应类似于Sidecar <-> Controller <-> CRD:
设计正确的Cassandra语句中的节点管理图考虑现有的运营商。
1. instaclustr的Cassandra-operator
- Github
- 意愿:阿尔法
- 许可证:Apache 2.0
- 实现于:Java
这确实是来自提供Cassandra托管部署的公司的非常有前途且发展迅速的项目。 如上所述,它使用可以通过HTTP接受命令的Sidecar容器。 它是用Java编写的,因此有时它缺少更高级的客户端库功能。 另外,操作员不支持一个数据中心使用不同的机架。
但是,操作员具有监视支持,使用CRD进行高级群集管理,甚至有关删除备份的文档等优势。
2. Jetstack的导航器
- Github
- 意愿:阿尔法
- 许可证:Apache 2.0
- 实施于:Golang
有关部署“ DB-as-a-Service”的声明。 当前支持两个数据库:Elasticsearch和Cassandra。 它具有一些有趣的解决方案,例如通过RBAC对数据库的访问控制(为此,提出了自己的单独的navigator-apiserver)。 一个值得关注的有趣项目,但是最后一次提交是在一年半之前完成的,这显然降低了它的潜力。
3. vgkowski的Cassandra-operator
- Github
- 意愿:阿尔法
- 许可证:Apache 2.0
- 实施于:Golang
他们并不认为这是“认真的”,因为对存储库的最后一次提交是一年多以前的。 运营商开发被放弃了:声明为受支持的Kubernetes的最新版本是1.9。
4. Rook的Cassandra-operator
- Github
- 意愿:阿尔法
- 许可证:Apache 2.0
- 实施于:Golang
一个发展速度不如我们期望的运营商。 它具有经过深思熟虑的CRD结构,用于管理集群,解决了使用带有ClusterIP的Service识别节点的问题(相同的“ hack”)……但仅此而已。 现在没有现成的监视和备份功能(顺便说一句,我们
开始进行
自我监视)。 有趣的一点是,使用此运算符,您还可以部署ScyllaDB。
注意:我们在其中一个项目中使用了该运算符并进行了少量修改。 在整个操作过程中(约4个月),操作员的工作没有任何问题。5.橙色的CassKop
- Github
- 意愿:阿尔法
- 许可证:Apache 2.0
- 实施于:Golang
列表中最年轻的运算符:第一次提交是在2019年5月23日进行的。 他已经拥有了我们列表中的大量功能,这些功能的更多详细信息可以在项目存储库中找到。 运算符基于流行的sdk。 支持开箱即用的监视。 与其他运算符的主要区别是使用
了CassKop插件 ,
该插件以Python实现并用于Cassandra节点之间的通信。
结论
将Cassandra移植到Kubernetes的方法和可能的选择不言而喻:这个主题是有需求的。
在此阶段,您可以自行承担以上风险之一,并承担风险:没有一个开发人员保证在生产环境中解决方案的100%工作。 但是现在,许多产品看起来很有希望在开发平台中尝试使用它们。
我认为将来这个船上的女人一定要走!
聚苯乙烯
另请参阅我们的博客: