欢迎!如果你想知道 "无服务器数据库 "是什么意思?如果你发现自己在这里想知道*"无服务器数据库 "到底是什么意思,*你可能想先看看Andy Kimball的无服务器架构介绍,然后再回来和我们一起探讨。
反过来说,如果你已经在想你是如何在Kubernetes上运行无服务器数据库的?有时,我的部署需要10分钟才能完全展开,而我的眼睛是功能齐全的YAML分析器。他们认为这将是更好的!- 你来到了正确的博客文章。
撇开YAML的笑话不谈,如果你曾在Kubernetes中亲身经历过动态扩展,你可能会对我们的说法感到有点怀疑。也就是说,CockroachDB Serverless有快速的启动时间,而且我们使用了Kubernetes。继续阅读,了解我们是如何为CockroachDB Serverless部署有状态的Kubernetes工作负载的细节。
老蟑螂也能学会新花样
CockroachDB被分成两层。SQL和Key/Value(KV)存储层。SQL层负责解析、优化和执行用户的查询。KV层负责存储、检索和分发数据,同时提供Cockroach的事务性语义。
在专门的CockroachDB部署中,这两层在同一过程中进行通信。多租户部署将这种分离更进一步,将每个层分成自己的进程。这就给我们留下了一个大型的有状态的存储舱集群,作为许多无状态SQL舱的后端。
这个KV集群实际上只是一个专门的CockroachDB部署。
如果我们按照我们的说明将CockroachDB部署到Kubernetes上,我们就会有一个现成的无服务器存储层。虽然终端用户可以通过SQL直接连接到这些集群,但这并不是他们在多租户部署中的主要目的。除了SQL之外,每个CockroachDB进程都承载了一个gRPC服务。这个服务用于节点内的通信,为cockroach的一些CLI提供动力,最重要的是,它可以访问KV层。当代表用户执行SQL时,SQL pods将利用这个服务来访问或修改任何持久化的数据。
SQL pods是我们进入未知领域的地方。和存储舱一样,SQL舱仍然是CockroachDB,这次有一个稍微不同的入口。由于CockroachDB的SQL执行层的架构,SQL pods是可以水平扩展的。更具体地说,这意味着我们可以通过调整SQL pod上的资源限制和请求,或者修改分配给它们的复制数量,来很容易地控制租户体验到的服务质量。
虽然这对存储层来说也是如此,但它并不是按需进行的。在Kubernetes的意义上,SQL pods更加 "poddy"。它们完全是短暂的,按需分配。在任何时间点,可能有零个或数百个副本存在。
低延时恢复
Kubernetes用户可能已经在问,如果我们为他们创建新的pod,怎么能在一秒钟内访问租户?
那些焦急地看着吊舱为新发布的软件旋转的人知道,吊舱的启动时间可以有相当大的差异。当所需的容器镜像已经存在时,冷启动的延迟可能在10到60秒之间。对于连接到你的应用程序的数据库来说,这并不是一个理想的情况。
**在CockroachDB Serverless中,我们允许SQL Pods在无约束的状态下启动。**也就是说,这些Pod还不属于一个特定的租户。这使得我们可以将Kubernetes部署作为一个准备好并等待预热的Pod池--从而避免Pod启动时间。
每当一个租户需要连接或扩大规模时,就会从部署中提取一个pod,然后绑定到租户上。拔出过程是通过打破部署的标签选择器,并将pod的OwnerRef改为CrdbTenant资源,这是一个由我们的Kubernetes集群中的操作员进程管理的自定义资源。
重新分配OwnerRef可以确保Kubernetes在拥有的租户被删除的情况下对SQL pod进行垃圾回收。然后,部署控制器将为我们自动处理 "预热 "更多未绑定的pod。
一旦一个SQL Pod被拔出,它必须被 "盖上 "其租户的标识符。在盖章过程中,允许SQL pod作为租户向KV pod进行认证的TLS证书,将通过HTTPS端点发送给被拔出的pod。一旦SQL pod收到了证书,HTTPS端点就会关闭,并且该pod开始接受SQL连接。最后,一个新的标签,表明租户,被应用到pod上,用来路由进入的连接。这个过程只需要不到一秒钟。
Autoscaler
现在我们知道了如何通过恢复过程为租户创建SQL pod,那么我们如何知道我们需要的这种实例的数量呢?
操作员内部的自动调节器组件决定每个租户在任何时候需要的SQL pod的数量。它通过监控Kubernetes集群中每个租户的所有SQL pod的CPU负载来实现,并根据两个指标计算出所需的SQL pod的数量。
- 过去5分钟内的平均CPU使用率
- 过去5分钟内的峰值CPU使用率
我们的无服务器架构博文深入探讨了扩展的机制,所以我们在此不做详述。然而,请注意,恢复的特殊情况(即从0到1的扩展)并不由操作者处理。相反,SQL Proxy会接手。这允许暂停的租户在建立新的连接时迅速恢复。(不用担心,我们会进一步详细讨论SQL代理)。
一旦autoscaler知道要给一个给定租户分配多少pod,它就会在相应的CrdbTenant资源中更新所需的状态。
Kubernetes控制器
让我们看看autoscaler组件对CrdbTenant资源的改变如何实际应用到集群中。
就像部署工作一样,我们在CrdbTenant资源中描述一个期望的状态,运营商中的CrdbTenant控制器将以可控的速度将实际状态更新为期望状态。在我们的案例中,CrdbTenant资源的控制器将确保所需的SQL pods的数量。如果我们有太多的,调和器将试图耗尽多余的。同样地,如果我们没有足够的SQL pod,调和器将通过前面描述的冲压过程绑定更多的SQL pod。
SQL pods会经历一个耗尽的过程,而不是马上被终止,这样SQL连接可以更优雅地被终止。当我们将来开始支持连接转移时,符合条件的连接将被转移到现有的正在运行的SQL pod中,从而减少整个连接中断。一旦所有的连接都被终止,或者10分钟过去了,以先到者为准,耗费过程就会结束。
我们在这里做了一些优化,以减少SQL pods的搅动。
- 在选择要盖章的pod时,如果它们还没有被终止,我们会优先考虑处于排水状态的pod。这些pod将被放回运行状态。
- 重用现有的draining pod可以防止预热池中未被盖章的pod不断被搅动,特别是在负载波动非常频繁的情况下。
- 这也使我们能够限制Kubernetes集群中的draining pod的数量,减少该租户的整体资源使用。
- 同样地,当选择SQL pod进行排水时,我们会优先考虑CPU使用率较低的pod,而不是较高的。这使得我们在某些情况下可以减少连接的中断。
从图片上看,一个SQL pod的状态可以用下面的图来描述。
用SQL代理把它放在一起
现在我们知道了支持无服务器集群的所有基本原理,是时候看看SQL Proxy组件了。当终端用户使用CockroachDB Serverless时,SQL Proxy组件是他们的连接对象。
这个组件由Kubernetes部署支持,并允许连接被路由到相应的SQL pods上。在SQL Proxy中,存在一个租户目录组件,它存储了集群标识符与它们的SQL pod的映射关系。这个目录是通过查询Kubernetes API服务器来填充的,为了减少API调用的数量,除了Kubernetes观察器,我们还有一个内存缓存。但是,所有这些与连接到我们的无服务器集群的体验有什么关系?
让我们通过一个无服务器集群的连接字符串的例子来深入了解一下。
postgresql://user:pass@free-tier.gcp-us-central1.cockroachlabs.cloud:26257/defaultdb?sslmode=...&options=--cluster=max-roach-35'
当我们使用上述连接字符串连接到集群时,我们实际上是在连接到Kubernetes集群中的一个SQL Proxy pod。
代理将提取通过选项参数(这里是'max-roach-35')提供的集群标识符,在租户目录上执行IP地址查询。如果有活动的SQL pods,代理将根据加权的CPU负载平衡,将SQL连接路由到其中一个。
但是,如果autoscaler已经由于没有流量而缩减了SQL pods,导致没有相应的租户可用呢?这就是我们的低延迟恢复程序的作用。代理更新相应租户的CrdbTenant资源,请求一个SQL pod。
这个操作触发了Kubernetes的调和过程,使操作者为相应的租户执行冲压过程。一旦SQL pod启动并运行,代理现在可以将初始SQL连接路由到它。我们目前正在努力通过进一步降低恢复时间来实现更好的连接体验。
总结
现在你已经看到了如何通过恢复过程为租户创建SQL pod,用autoscaler组件控制每个租户的SQL pod数量,并使用SQL Proxy与无服务器Kubernetes集群中的pod连接,现在你可以自己尝试一下了
请到cockroachlabs.cloud/signup ,并立即开始使用(永久)免费的CockroachDB无服务器账户。
如果你遇到问题,请加入我们的社区Slack频道并提问。我们也希望听到你对CockroachDB Serverless的体验--我们重视反馈,无论是正面还是负面。在未来的几个月里,我们将努力改善它,所以请注册一个账户,以获得我们的最新进展。如果你愿意帮助我们将CockroachDB提升到新的水平,我们正在招聘中。