Postgres 星期二第 5 期:“PostgreSQL 和 Kubernetes。 持续集成/持续交付。 测试自动化”

Postgres 星期二第 5 期:“PostgreSQL 和 Kubernetes。 持续集成/持续交付。 测试自动化”

去年年底,俄罗斯 PostgreSQL 社区又举办了一场直播 #RuPostgres其间,其联合创始人 Nikolai Samokhvalov 与 Flant 技术总监 Dmitry Stolyarov 讨论了 Kubernetes 背景下的 DBMS。

我们正在发布本次讨论主要部分的记录,并在 社区 YouTube 频道 完整视频已发布:

数据库和 Kubernetes

NA:我们今天不讨论 VACUUM 和 CHECKPOINT。 我们想谈谈 Kubernetes。 我知道你有多年的经验。 我观看了您的视频,甚至重新观看了其中一些视频...让我们开门见山:为什么在 K8s 中使用 Postgres 或 MySQL?

DS: 这个问题没有也不可能有明确的答案。 但总的来说,这是简单和方便......潜力。 每个人都想要托管服务。

NA: 怎样 RDS,只在家里?

DS:是的:像 RDS 一样,可以在任何地方。

NA: “任何地方”都是一个很好的观点。 在大公司中,一切都位于不同的地方。 那么,如果是一家大公司,为什么不采用现成的解决方案呢? 例如,Nutanix 有自己的开发,其他公司(VMware...)也有相同的“RDS,仅限国内”。

DS:但我们正在讨论一个单独的实现,它仅在某些条件下起作用。 如果我们谈论 Kubernetes,那么就有各种各样的基础设施(可以在 K8s 中)。 本质上,这是云 API 的标准......

NA: 还是免费的!

DS: 没那么重要。 对于不是很大的市场部分来说,自由度很重要。 还有一些重要的事情......你可能还记得这份报告“数据库和 Kubernetes“?

NA:是的。

DS: 我意识到收到的信息非常含糊。 有些人认为我是在说:“伙计们,让我们将所有数据库放入 Kubernetes 中!”,而其他人则认为这些都是糟糕的自行车。 但我想说的是完全不同的话:“看看正在发生什么,存在什么问题以及如何解决它们。 我们现在应该使用 Kubernetes 数据库吗? 生产? 好吧,只要你喜欢……做某些事情。 但对于开发者来说,我可以说我推荐它。 对于开发人员来说,创建/删除环境的活力非常重要。”

NS:开发者是指所有非生产环境吗? 分期、质量检查…

DS:如果我们谈论的是性能支架,那么可能不会,因为那里的要求是特定的。 如果我们谈论的是需要非常大的数据库来进行暂存的特殊情况,那么可能不会......如果这是一个静态的、长期存在的环境,那么将数据库位于 K8s 中有什么好处?

NA: 没有任何。 但是我们在哪里可以看到静态环境呢? 静态环境明天就会过时。

DS:分期可以是静态的。 我们有客户...

NA: 是的,我也有一个。 如果您有 10 TB 数据库和 200 GB 暂存,这就是一个大问题......

DS: 我有一个非常酷的案例! 在登台时,有一个可以进行更改的产品数据库。 还有一个按钮:“推出到生产环境”。 这些更改 - 增量 - 在生产中添加(似乎它们只是通过 API 同步)。 这是一个非常奇特的选择。

NA:我见过硅谷的初创公司使用 RDS 甚至 Heroku - 这些都是 2-3 年前的故事 - 他们将转储下载到他们的笔记本电脑上。 因为数据库仍然只有80 GB,而且笔记本电脑上还有空间。 然后他们为每个人购买额外的磁盘,这样他们就有3个数据库来进行不同的开发。 事情也是这样发生的。 我还看到他们并不害怕将产品复制到舞台中——这很大程度上取决于公司。 但我也看到他们很害怕,而且往往没有足够的时间和手。 但在我们继续这个主题之前,我想听听 Kubernetes。 我是否正确理解尚未有人使用产品?

DS:我们的产品中有小型数据库。 我们正在谈论数十 GB 的容量和非关键服务,我们懒得为其制作副本(并且没有这种需要)。 并且前提是Kubernetes下有正常的存储。 该数据库在虚拟机中运行 - 有条件地在存储系统之上的 VMware 中。 我们把它放在 PV 现在我们可以将其从一台机器转移到另一台机器。

NA:这种大小的数据库(最大 100 GB)可以在几分钟内在良好的磁盘和良好的网络上推出,对吧? 每秒 1 GB 的速度不再是奇特的东西。

DS:是的,对于线性运算来说这不是问题。

NA: 好吧,我们只需要考虑产品。 如果我们考虑将 Kubernetes 用于非生产环境,我们应该做什么? 我在扎兰多看到了 做操作符,脆脆的 锯切,还有一些其他选项。 并且有 昂格雷斯 - 这是我们来自西班牙的好朋友阿尔瓦罗:他们所做的本质上不仅仅是 操作者,以及整个分布(堆栈格雷斯),除了 Postgres 本身之外,他们还决定添加一个备份,即 Envoy 代理......

DS: 使者做什么? 专门平衡 Postgres 流量?

NA: 是的。 也就是说,他们认为:如果你采用 Linux 发行版和内核,那么常规 PostgreSQL 就是内核,他们希望制作一个云友好且在 Kubernetes 上运行的发行版。 他们将组件(备份等)放在一起并进行调试,以便它们正常工作。

DS: 很酷! 本质上,这是创建您自己的托管 Postgres 的软件。

NA:Linux发行版有一个永恒的问题:如何制作驱动程序以便支持所有硬件。 他们有在 Kubernetes 中工作的想法。 我知道,在 Zalando 运营商中,我们最近看到了与 AWS 的连接,但这已经不再很好了。 不应该与特定的基础设施有联系——那还有什么意义呢?

DS:我不知道 Zalando 到底遇到了什么情况,但在 Kubernetes 存储中,现在的存储方式是不可能使用通用方法进行磁盘备份的。 最近处于标准状态 - 最新版本 CSI规范 — 我们使快照成为可能,但它是在哪里实现的呢? 老实说,一切都还很原始……我们正在 AWS、GCE、Azure、vSphere 之上尝试 CSI,但是一旦你开始使用它,你就会发现它还没有准备好。

NA:这就是为什么我们有时必须依赖基础设施。 我认为这仍然是一个早期阶段——成长的烦恼。 问题:对于想要在 K8s 中尝试 PgSQL 的新手,您有什么建议? 也许是什么运营商?

DS:问题是 Postgres 对我们来说是 3%。 我们在 Kubernetes 中还有一个非常大的不同软件列表,我什至不会列出所有内容。 例如,弹性搜索。 运营商有很多:有些正在积极开发,有些则没有。 我们给自己制定了一个运营商应该具备的要求,这样我们才能认真对待。 在专门针对 Kubernetes 的操作符中 - 而不是在“在亚马逊条件下做某事的操作符”中......事实上,我们相当广泛(=几乎所有客户端)使用单个操作符 - 对于Redis (我们很快就会发表一篇关于他的文章).

NA: 也不适合 MySQL 吗? 我知道 Percona...因为他们现在正在研究 MySQL、MongoDB 和 Postgres,所以他们必须创建某种通用解决方案:针对所有数据库、针对所有云提供商。

DS:我们没有时间查看 MySQL 的运算符。 这不是我们现在的主要关注点。 MySQL 在独立环境下运行良好。 如果您可以启动数据库,为什么还要使用操作符...您可以使用 Postrges 启动 Docker 容器,也可以以简单的方式启动它。

NA: 也有这个问题。 根本就没有运营商吗?

DS:是的,我们 100% 的人都在没有操作员的情况下运行 PostgreSQL。 到目前为止。 我们积极使用 Prometheus 和 Redis 的操作符。 我们计划为 Elasticsearch 寻找一个 Operator——它是最“火”的一个,因为我们希望在 100% 的情况下将它安装在 Kubernetes 中。 正如我们要确保 MongoDB 也始终安装在 Kubernetes 中一样。 这里出现了某些愿望 - 有一种感觉,在这些情况下可以做一些事情。 我们甚至没有看 Postgres。 当然,我们知道有不同的选择,但实际上我们有一个独立的选择。

用于在 Kubernetes 中进行测试的数据库

NA: 让我们继续讨论测试的话题。 如何从 DevOps 的角度推出对数据库的更改。 有微服务、许多数据库,某些地方一直在发生变化。 如何保证CI/CD的正常进行,让DBMS层面一切井然有序。 你的方法是什么?

DS: 不可能有一个答案。 有几种选择。 第一个是我们想要推出的底座的大小。 您自己提到,公司对于在开发和阶段拥有产品数据库副本有不同的态度。

NA:在GDPR的条件下,我认为他们越来越小心......我可以说在欧洲他们已经开始征收罚款。

DS:但通常您可以编写从生产中获取转储并对其进行混淆的软件。 获取生产数据(快照、转储、二进制副本...),但它是匿名的。 相反,可以有生成脚本:这些可以是固定装置,也可以只是生成大型数据库的脚本。 问题是:创建一个基础镜像需要多长时间? 部署到所需环境需要多长时间?

我们得出一个方案:如果客户端有固定的数据集(最小版本的数据库),那么我们默认使用它们。 如果我们谈论审查环境,当我们创建分支时,我们部署了应用程序的一个实例 - 我们在那里推出了一个小型数据库。 但结果很好 选项,当我们每天(晚上)从生产中获取一次转储,并使用 PostgreSQL 和 MySQL 构建一个 Docker 容器,并基于此加载数据。 如果您需要将此图像扩展数据库 50 倍,则可以非常简单且快速地完成。

NA: 简单的复制?

DS:数据直接存储在Docker镜像中。 那些。 我们有一个现成的镜像,尽管有 100 GB。 感谢 Docker 中的层,我们可以根据需要多次快速部署此映像。 这个方法虽然笨,但是效果很好。

NA:那么,当你测试时,它就在 Docker 内部发生了变化,对吧? Docker 内部的写时复制 - 扔掉它并重新开始,一切都很好。 班级! 您已经充分利用它了吗?

DS: 许久。

NA: 我们做的事情非常相似。 只是我们不使用 Docker 的写时复制,而是使用其他一种。

DS: 这不是通用的。 Docker 无处不在。

NA: 理论上是的。 但我们也有模块,您可以制作不同的模块并使用不同的文件系统。 这是多么美好的一刻啊。 从 Postgres 的角度来看,我们以不同的方式看待这一切。 现在我从 Docker 方面来看,发现一切都适合你。 但如果数据库很大,比如1TB,那么这一切都需要很长时间:晚上操作,把所有东西都塞进Docker……而如果5TB塞进Docker……或者一切都好吗?

DS:有什么区别:这些是 blob,只是位和字节。

NA:区别在于:你是通过dump和restore来做到的吗?

DS: 完全没有必要。 生成该图像的方法可以不同。

NA:对于某些客户,我们不是定期生成基础映像,而是不断更新它。 它本质上是一个副本,但它不是直接从主服务器接收数据,而是通过存档接收数据。 一个二进制存档,每天都会下载 WAL,并进行备份...然后这些 WAL 会稍有延迟(实际上是 1-2 秒)到达基础映像。 我们以任何方式从它克隆 - 现在我们默认有 ZFS。

DS:但是对于 ZFS,您只能使用一个节点。

NA: 是的。 不过ZFS还有一个神奇的地方 提交:有了它,您可以发送快照,甚至(我还没有真正测试过这一点,但是......)您可以发送两个之间的增量 PGDATA。 事实上,我们还有另一个工具,我们还没有真正考虑过用于此类任务。 PostgreSQL 有 pg_倒带,它的工作原理就像一个“智能”rsync,跳过很多你不必观看的内容,因为那里没有任何改变。 我们可以在两个服务器之间进行快速同步并以相同的方式倒回。

因此,从 DBA 的角度来看,我们正在尝试创建一种工具,使我们能够执行您所说的相同操作:我们有一个数据库,但我们想要几乎同时测试某些内容 50 次。

DS:50次表示您需要订购50个Spot实例。

NA:不,我们在一台机器上完成所有工作。

DS:但是,如果这个数据库达到 TB 级,您将如何扩展 50 倍。 她很可能需要有条件的 256 GB RAM?

NA:是的,有时您需要大量内存 - 这很正常。 但这是生活中的例子。 量产机有96核、600GB。 同时,数据库使用 32 个核心(现在有时甚至是 16 个核心)和 100-120 GB 内存。

DS: 那里可以放 50 份吗?

NA:所以只有一份副本,然后写时复制(ZFS)就可以了……我会更详细地告诉你。

例如,我们有一个 10 TB 的数据库。 他们为它制作了一个磁盘,ZFS 还将其大小压缩了 30-40%。 由于我们不进行负载测试,因此确切的响应时间对我们来说并不重要:让它慢 2 倍 - 没关系。

我们为程序员、QA、DBA 等提供机会。 在 1-2 个线程中执行测试。 例如,他们可能会进行某种迁移。 它不需要同时使用 10 个核心 - 它需要 1 个 Postgres 后端,1 个核心。 迁移将会开始——也许 自动真空 仍然会启动,然后将使用第二个核心。 我们分配了16-32个核心,所以10个人可以同时工作,没问题。

因为身体上 PGDATA 同样,事实证明我们实际上是在欺骗Postgres。 技巧是这样的:例如,同时启动 10 个 Postgres。 通常是什么问题? 他们把 共享缓冲区,比方说 25%。 因此,这是 200 GB。 您将无法启动超过三个,因为内存将耗尽。

但在某些时候我们意识到这是没有必要的:我们将shared_buffers设置为2GB。 PostgreSQL 有 有效缓存大小,实际上它是唯一影响的 计划。 我们将其设置为 0,5 TB。 即使它们实际上不存在也没关系:他制定计划就好像它们存在一样。

因此,当我们测试某种迁移时,我们可以收集所有计划 - 我们将看到它在生产中如何发生。 秒数会有所不同(更慢),但我们实际读取的数据以及计划本身(那里有什么 JOIN 等)结果与生产中完全相同。 您可以在一台机器上并行运行许多此类检查。

DS: 你不觉得这里有一些问题吗? 第一个是仅适用于 PostgreSQL 的解决方案。 这种方法是非常私人的,不是通用的。 第二个是 Kubernetes(以及云技术现在发展的一切)涉及许多节点,并且这些节点是短暂的。 在您的情况下,它是一个有状态的持久节点。 这些事情让我很矛盾。

NA:首先,我同意,这纯粹是 Postgres 的故事。 我认为如果我们有某种直接 IO 和几乎所有内存的缓冲池,这种方法将不起作用 - 计划会有所不同。 但目前我们只与 Postgres 合作,我们不考虑其他。

关于 Kubernetes。 您自己到处告诉我们,我们有一个持久数据库。 如果实例失败,主要是保住磁盘。 在这里,我们在 Kubernetes 中也拥有整个平台,并且 Postgres 的组件是独立的(尽管有一天它会在那里)。 因此,一切都是这样的:实例倒下了,但我们保存了它的PV并简单地将它连接到另一个(新的)实例,就好像什么也没发生一样。

DS:从我的角度来看,我们在 Kubernetes 中创建 Pod。 K8s - 松紧带:根据需要订购结。 任务是简单地创建一个 pod 并说它需要 X 数量的资源,然后 K8s 会自行计算出来。 但 Kubernetes 中的存储支持仍然不稳定: 1.161.17 (此版本已发布 недели 之前)这些功能仅成为测试版。

六个月到一年将会过去——它会变得或多或少稳定,或者至少会如此声明。 那么快照和调整大小的可能性就可以完全解决您的问题。 因为你有底线。 是的,它可能不是很快,但速度取决于“幕后”的内容,因为某些实现可以在磁盘子系统级别进行复制和写时复制。

NA:所有引擎(亚马逊、谷歌...)也有必要开始支持这个版本 - 这也需要一些时间。

DS: 我们还没有使用它们。 我们用我们的。

Kubernetes 本地开发

NA: 当你需要把所有的pod都安装到一台机器上,做这么一个小测试的时候,你有没有遇到过这样的愿望。 要快速获得概念证明,请查看应用程序在 Kubernetes 中运行,而无需为其专门使用一堆机器。 有Minikube,对吧?

DS:在我看来,这个案例(部署在一个节点上)完全与本地开发有关。 或者是这种模式的一些表现形式。 吃 迷你酷那里 k3s, 。 我们正在努力在 Docker 中使用 Kubernetes。 现在我们开始用它进行测试。

NA:我曾经认为这是一种将所有 Pod 包装在一个 Docker 镜像中的尝试。 但事实证明,这是完全不同的事情。 无论如何,有单独的容器、单独的 Pod——就在 Docker 中。

DS: 是的。 还有一个相当有趣的模仿,但意思是这样的......我们有一个用于部署的实用程序 - 韦尔夫。 我们想让它成为条件模式 werf up:“给我本地 Kubernetes。” 然后在那里运行条件 werf follow。 然后,开发人员将能够编辑 IDE,系统中将启动一个进程来查看更改并重建映像,将它们重新部署到本地 K8s。 这就是我们想要尝试解决当地发展问题的方式。

K8s现实中的快照和数据库克隆

NA:如果我们回到写时复制。 我注意到云也有快照。 他们的工作方式不同。 例如,在 GCP 中:您在美国东海岸有一个多 TB 的实例。 您定期拍摄快照。 您从快照中获取西海岸磁盘的副本 - 几分钟内一切准备就绪,它运行得非常快,只需将缓存填充到内存中即可。 但这些克隆(快照)是为了“提供”新卷。 当您需要创建大量实例时,这很酷。

但对于测试,在我看来,快照,你在 Docker 中谈论的或者我在 ZFS、btrfs 甚至 LVM 中谈论的...... - 它们允许你不在一台机器上创建真正的新数据。 在云中,您每次仍然需要为它们付费,并且等待的不是几秒钟,而是几分钟(在这种情况下 惰性加载,可能是手表)。

相反,您可以在一两秒内获取这些数据,运行测试并将其丢弃。 这些快照解决不同的问题。 在第一种情况下 - 扩展并获取新的副本,在第二种情况下 - 用于测试。

DS: 我不同意。 让卷克隆正常工作是云的任务。 我没有看过他们的实现,但我知道我们如何在硬件上做到这一点。 我们有 Ceph,它允许任何物理卷(RBD) 说 克隆 并在几十毫秒内获得具有相同特征的第二卷, IOPS'阿米等你需要明白,里面有一个棘手的写时复制。 为什么云不应该做同样的事情呢? 我确信他们正在尝试以某种方式做到这一点。

NA:但是他们仍然需要几秒钟、几十秒钟来启动一个实例,将 Docker 引入那里,等等。

DS:为什么需要引发整个实例? 我们有一个具有 32 个核心、16 个核心的实例,它可以容纳其中 - 例如,四个。 当我们订购第五个时,该实例已经被提升,然后它将被删除。

NA:是的,有趣的是,Kubernetes 却是一个不同的故事。 我们的数据库不是K8s,我们有一个实例。 但克隆一个多 TB 的数据库只需要不超过两秒的时间。

DS: 这很棒。 但我最初的观点是,这不是一个通用的解决方案。 是的,这很酷,但它仅适用于 Postgres,并且仅适用于一个节点。

NA:它不仅适用于 Postgres:正如我所描述的,这些计划仅适用于 Postgres。 但如果我们不关心计划,只需要所有数据进行功能测试,那么这适用于任何 DBMS。

DS:很多年前我们对 LVM 快照做了类似的事情。 这是一个经典。 这种方法被非常积极地使用。 有状态节点只是一种痛苦。 因为你不应该丢弃它们,你应该永远记住它们......

NA:您认为这里有混合动力的可能性吗? 假设有状态是某种 Pod,它适用于多个人(许多测试人员)。 我们只有一个卷,但由于文件系统的原因,克隆是本地的。 如果 Pod 掉落,但磁盘仍然存在,则 Pod 会升起,计算有关所有克隆的信息,再次拾起所有内容并说:“这是在这些端口上运行的克隆,请继续使用它们。”

DS:从技术上讲,这意味着在 Kubernetes 中,它是一个 pod,我们在其中运行许多 Postgres。

NA: 是的。 他有一个限制:假设同时与他一起工作的人不超过 10 人。 如果您需要 20 个,我们将启动第二个此类吊舱。 我们将完全克隆它,收到第二个完整卷后,它将具有相同的 10 个“薄”克隆。 难道你没有看到这个机会吗?

DS:我们需要在这里添加安全问题。 这种类型的组织意味着这个 pod 具有很高的特权(能力),因为它可以对文件系统执行非标准操作......但我重复一遍:我相信在中期他们将修复 Kubernetes 中的存储,并且在云,他们将用体积来修复整个故事 - 一切都会“正常”。 将会调整大小、克隆……有一个卷 - 我们说:“在此基础上创建一个新卷”,一分半钟后我们就得到了我们需要的东西。

NA:我不相信一秒半秒就能处理很多 TB 数据。 在 Ceph 上,你自己做,但你谈论云。 转到云端,在 EC2 上克隆一个多 TB 的 EBS 卷,然后看看性能如何。 不会需要几秒钟。 我对他们什么时候能达到这个水平非常感兴趣。 我明白你在说什么,但我不敢苟同。

DS:好的,但我说的是中期,而不是短期。 几年来。

关于 Zalando 的 PostgreSQL 运算符

在这次会议中,来自 Zalando 的前开发人员 Alexey Klyukin 也加入其中并谈到了 PostgreSQL 算子的历史:

很高兴这个话题得到了广泛的讨论:Postgres 和 Kubernetes。 当我们 2017 年开始在 Zalando 做这件事时,这是一个每个人都想做但没有人做的话题。 每个人都已经有了 Kubernetes,但是当他们问如何使用数据库时,甚至有人喜欢 凯尔西·海塔尔宣扬K8s的人是这样说的:

“转到托管服务并使用它们,不要在 Kubernetes 中运行数据库。 否则,你的 K8 会决定,比如升级,关闭所有节点,你的数据就会飞得很远很远。”

我们决定创建一个操作符,与此建议相反,它将在 Kubernetes 中启动 Postgres 数据库。 我们有一个很好的理由 - 帕特罗尼。 这是 PostgreSQL 的自动故障转移,正确完成,即使用etcd、consul或ZooKeeper作为集群信息的存储。 这样一个存储库将为每个询问当前领导者是谁的人提供相同的信息 - 尽管事实上我们已经分发了所有内容 - 因此不会出现脑裂。 另外我们还有 Docker镜像 为了他。

总体来说,公司从内部硬件数据中心迁移到云端后,就出现了自动故障转移的需求。 云基于专有的 PaaS(平台即服务)解决方案。 它是开源的,但需要做很多工作才能启动和运行。 它被称为 STUPS.

最初,没有 Kubernetes。 更准确地说,当我们部署自己的解决方案时,K8s 已经存在,但它太原始,不适合生产。 在我看来,那是2015年或2016年。 到了 2017 年,Kubernetes 已经或多或少变得成熟了——需要迁移到那里。

我们已经有了一个 Docker 容器。 有一个使用 Docker 的 PaaS。 为什么不尝试一下 K8s? 为什么不编写自己的运算符呢? 从阿维托来到我们这里的穆拉特·卡比洛夫 (Murat Kabilov) 主动开始了这个项目——“玩”——然后这个项目就“起飞了”。

但总的来说,我想谈谈 AWS。 为什么历史上有AWS相关代码...

当您在 Kubernetes 中运行某些东西时,您需要了解 K8s 是一项正在进行中的工作。 它不断地发展、完善,甚至时不时地崩溃。 你需要密切关注 Kubernetes 中的所有变化,你需要准备好在发生事情时深入研究它并详细了解它是如何工作的——也许比你想要的更多。 原则上,这适用于运行数据库的任何平台......

因此,当我们执行该语句时,我们让 Postgres 在外部卷上运行(本例中为 EBS,因为我们在 AWS 上工作)。 数据库增长了,在某些时候需要调整它的大小:例如,EBS 的初始大小是 100 TB,数据库增长到这个大小,现在我们想让 EBS 达到 200 TB。 如何? 假设您可以在新实例上进行转储/恢复,但这将花费很长时间并涉及停机时间。

因此,我想要调整大小以扩大 EBS 分区,然后告诉文件系统使用新空间。 我们做到了,但当时 Kubernetes 没有任何用于调整大小操作的 API。 由于我们在 AWS 上工作,所以我们为其 API 编写了代码。

没有人会阻止您在其他平台上做同样的事情。 声明中没有暗示它只能在AWS上运行,并且不适用于其他一切。 总的来说,这是一个开源项目:如果有人想加速新 API 的使用,欢迎您。 吃 GitHub上、拉取请求 - Zalando 团队尝试快速响应这些请求并提升操作员。 据我所知,该项目 参加 Google Summer of Code 和其他一些类似的计划。 Zalando 正在积极致力于此。

PS奖金!

如果您对 PostgreSQL 和 Kubernetes 主题感兴趣,那么还请注意,下一个 Postgres Tuesday 是在上周举行的,我在那里与 Nikolai 进行了交谈 亚历山大·库库什金(来自 Zalando)。 其视频可用 这里.

聚苯硫醚

另请阅读我们的博客:

来源: habr.com

添加评论