news 2026/9/24 15:59:40

在 Leafcloud 上使用 Kubernetes 与 PostgreSQL Operator 部署运行 FerretDB 的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 Leafcloud 上使用 Kubernetes 与 PostgreSQL Operator 部署运行 FerretDB 的完整指南
  • 后端
  • 数据库
  • 文档数据库

【免费下载链接】FerretDB

A truly Open Source MongoDB alternative

项目地址:https://gitcode.com/gh_mirrors/fe/FerretDB
点击查看免费下载

FerretDB 是一款真正开源的 MongoDB 替代方案,它以 PostgreSQL 作为后端存储,让开发者可以继续使用熟悉 MongoDB 生态的工具与协议,同时摆脱厂商锁定。本文以 FerretDB 官方博客指南为主线,完整讲解如何在 Leafcloud(基于 OpenStack Magnum 的环保型云基础设施)上,借助 Kubernetes 和 Crunchy Data PostgreSQL Operator,从零搭建一套可生产的 FerretDB 运行环境——涵盖 Kubernetes 集群创建、PostgreSQL 集群初始化、FerretDB 部署与连通性验证,并结合仓库源码解析连接配置的底层细节。

读完本文,你将掌握一套可复制的“云上 FerretDB + PostgreSQL”落地路径,并理解 FerretDB 如何通过FERRETDB_POSTGRESQL_URL等环境变量接入 PostgreSQL,以及数据在 PostgreSQL 中的实际存储形态。

方案总览

本指南的整体技术栈如下:

  • Leafcloud:提供分布式、节能的云基础设施,通过 OpenStack Magnum 项目管理并部署容器集群;
  • Kubernetes:承载 FerretDB 与 PostgreSQL 集群的容器编排平台;
  • Crunchy Data PostgreSQL Operator(PGO):在 Kubernetes 上创建高可靠 PostgreSQL 集群,并提供持久化存储、自动备份、连接池等能力;
  • FerretDB:以 PostgreSQL 为后端的 MongoDB 协议兼容层,对外提供 MongoDB Wire Protocol 监听(默认27017端口)。

流程分为三大阶段:

  1. 在 Leafcloud 上创建 Kubernetes 集群并配置 Cinder CSI 存储类;
  2. 通过 PostgreSQL Operator 创建 PostgreSQL 集群并初始化用户与数据库;
  3. 部署 FerretDB Deployment 与 Service,最后用mongosh验证连通性并做基本读写。

前置条件

开始之前,请确认以下条件:

  • 已安装kubectl,用于连接并操作 Kubernetes 集群;
  • 拥有一个 Leafcloud 账户,且账户内有足够的配额(volume)来运行集群;
  • 具备基本的 Linux 命令行、Kubernetes 与 PostgreSQL 使用经验。

在 Leafcloud 上创建 Kubernetes 集群

Leafcloud 使用 OpenStack Magnum 项目来管理和部署容器集群,因此本阶段我们全程使用 OpenStack CLI 操作。

安装 OpenStack CLI

在本地环境(示例为 Debian/Ubuntu)安装 OpenStack 命令行客户端与 Magnum 客户端:

sudo apt update -y sudo apt install -y python3-pip python3-dev -y sudo apt install virtualenv -y virtualenv -p python3 openstack_venv source openstack_venv/bin/activate pip install --upgrade pip pip install python-openstackclient pip install python-magnumclient

配置 Leafcloud 账户

登录 Leafcloud 账户,下载 OpenStack RC 文件(其中包含命令行客户端所需的环境变量),将文件内容保存为:

~/leafcloudopenrc.sh

然后加载配置,并按提示输入账户密码:

source ~leafcloudopenrc.sh

验证 CLI 是否能够访问账户资源:

openstack server list

如果出现认证错误,重新执行source ~/leafcloudopenrc.sh并确认密码输入正确。

选择集群模板并创建集群

Leafcloud 提供可直接使用的集群模板,查看模板列表:

openstack coe cluster template list

本指南选用K8s-ha-v1.21.2-template-v2.0-rc3模板,因为它自带 Kubernetes OpenStack 自动伸缩(autoscaling)、容器与主机使用的加密 Cinder 卷(持久卷声明 PVC),以及高可用负载均衡器。

使用该模板创建集群。--keypair参数指定的密钥对会被集成到主机中,从而获得 root SSH 访问权限(默认用户为core):

openstack coe cluster create my-k8s-cluster --cluster-template k8s-ha-v1.21.2-template-v2.0-rc3 --keypair <keypair>

集群创建可能需要几分钟,通过如下命令查看进度:

openstack coe cluster list

当集群状态从CREATE_IN_PROGRESS变为CREATE_COMPLETE时,安装完成。

获取集群配置并连接 kubectl

获取集群的 kubeconfig:

openstack coe cluster config my-k8s-cluster

这会在主目录下载一个名为config的文件。kubectl依赖它来连接 Kubernetes 集群,同一终端会话内后续所有kubectl命令都会使用该配置,直到被重置或更换:

export KUBECONFIG=/home/<username>/config

确认集群节点可达:

kubectl get nodes -o wide

配置 Cinder CSI 存储类

FerretDB 与 PostgreSQL 都需要持久化存储。创建storageclass.yaml,将 Cinder CSI 设为默认存储类,以便后续 PVC(持久卷声明)自动使用:

kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: cinder-csi annotations: storageclass.kubernetes.io/is-default-class: 'true' provisioner: cinder.csi.openstack.org

应用该存储类:

kubectl apply -f storageclass.yaml

创建 PostgreSQL 集群

FerretDB 以 PostgreSQL 为存储后端,因此接下来借助 Crunchy Data 的 PostgreSQL Operator(PGO,版本 5.4.0,通过 kustomize 安装)创建生产可用的 PostgreSQL 集群。

安装 PostgreSQL Operator

首先将 postgres-operator-examples 仓库克隆到本地(按需 fork 后使用你自己的 GitHub 用户名):

YOUR_GITHUB_UN="<your GitHub username>" git clone --depth 1 "git@github.com:${YOUR_GITHUB_UN}/postgres-operator-examples.git" cd postgres-operator-examples

使用默认配置安装 PGO(可根据需要自行修改):

kubectl apply -k kustomize/install/namespace kubectl apply --server-side -k kustomize/install/default

该过程会生成名为postgres-operator的命名空间,并创建 PGO 部署所需的全部对象。

监控安装进度:

kubectl -n postgres-operator get pods \ --selector=postgres-operator.crunchydata.com/control-plane=postgres-operator \ --field-selector=status.phase=Running

当 PGO Pod 健康运行时,输出类似:

NAME READY STATUS RESTARTS AGE pgo-6f664c9f44-mmptx 1/1 Running 0 10s

配置 PostgreSQL 集群清单

创建 PostgreSQL 集群前,修改克隆目录下的kustomize/postgres/postgres.yaml,让集群的数据卷声明使用cinder-csi存储类,容量请求为 1Gi:

apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster metadata: name: hippo spec: image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-15.3-2 postgresVersion: 15 instances: - name: instance1 dataVolumeClaimSpec: accessModes: - 'ReadWriteOnce' resources: requests: storage: 1Gi storageClassName: cinder-csi backups: pgbackrest: image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.45-2 repos: - name: repo1 volume: volumeClaimSpec: accessModes: - 'ReadWriteOnce' resources: requests: storage: 1Gi storageClassName: cinder-csi

清单要点:

  • dataVolumeClaimSpec指定 PostgreSQL 数据目录使用的 PVC 存储(此处为 1Gi 的cinder-csi卷);
  • backups.pgbackrest配置 pgBackRest 备份仓库,同样使用 1Gi 的cinder-csi卷,实现自动备份能力。

创建 PostgreSQL 集群:

kubectl apply -k kustomize/postgres

该命令会在postgres-operator命名空间创建名为hippo的 PostgreSQL 集群。跟踪集群进度:

kubectl -n postgres-operator describe postgresclusters.postgres-operator.crunchydata.com hippo

端口转发与数据库初始化

在新终端中执行端口转发,将集群内 PostgreSQL 的 5432 端口暴露到本地(若遇连接错误,先执行export KUBECONFIG=/home/<username>/config):

PG_CLUSTER_PRIMARY_POD=$(kubectl get pod -n postgres-operator -o name \ -l postgres-operator.crunchydata.com/cluster=hippo,postgres-operator.crunchydata.com/role=master) kubectl -n postgres-operator port-forward "${PG_CLUSTER_PRIMARY_POD}" 5432:5432

接下来按照 FerretDB 的要求配置 PostgreSQL:创建用户与密码凭据,并创建归属该用户的数据库。

生成随机密码并保存为 KubernetesSecret(脚本文件secret.sh):

#!/bin/sh PASSWORD=$(openssl rand -base64 8) kubectl -n postgres-operator create secret generic ferretdb-secret \ --from-literal=password=$PASSWORD \

执行脚本:

chmod +x secret.sh ./secret.sh

注意:以上chmod仅用于修改你自己创建的脚本文件权限,属于部署操作的一部分,不影响仓库内容。

由于 PostgreSQL 运行在 Kubernetes Pod 中,需要通过psql在 Pod 内执行 SQL。先从Secret中取出密码,再创建用户ferretuser

PASSWORD=$(kubectl -n postgres-operator get secret ferretdb-secret -o=jsonpath='{.data.password}' | base64 -d) kubectl -n postgres-operator exec -it hippo-instance1-mrpt-0 -- psql -U postgres -c "CREATE USER ferretuser WITH PASSWORD '$PASSWORD';"

其中hippo-instance1-mrpt-0是运行 PostgreSQL 实例的 Pod 名称,请用kubectl -n postgres-operator get pods查询你自己的实例名替换。

创建名为ferretdb的数据库,并将所有权限授予ferretuser

kubectl -n postgres-operator exec -it hippo-instance1-mrpt-0 -- psql -U postgres -c "CREATE DATABASE ferretdb OWNER ferretuser;"

验证用户与数据库创建成功:

kubectl -n postgres-operator exec -it hippo-instance1-mrpt-0 -- psql -U postgres -l

至此,Kubernetes 内已有一个带用户与数据库的 PostgreSQL 实例可供 FerretDB 使用。

部署 FerretDB

编写 Deployment 与 Service 清单

创建deployment.yaml,定义 FerretDB 容器、相关 MongoDB 组件、Service 配置,并通过Secret引用此前创建的ferretuser密码:

apiVersion: apps/v1 kind: Deployment metadata: name: ferretdb namespace: postgres-operator labels: app: ferretdb spec: replicas: 1 selector: matchLabels: app: ferretdb template: metadata: labels: app: ferretdb spec: containers: - name: ferretdb image: ghcr.io/ferretdb/ferretdb ports: - containerPort: 27017 env: - name: POSTGRES_USERNAME value: ferretuser - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: ferretdb-secret key: password - name: FERRETDB_POSTGRESQL_URL value: postgres://$(POSTGRES_USERNAME):$(POSTGRES_PASSWORD)@hippo-ha:5432/ferretdb --- apiVersion: v1 kind: Service metadata: name: ferretdb-service namespace: postgres-operator spec: selector: app: ferretdb ports: - name: mongo protocol: TCP port: 27017 targetPort: 27017

清单要点:

  • 镜像ghcr.io/ferretdb/ferretdb,官方生产镜像,监听 MongoDB 协议端口 27017;
  • 凭据注入POSTGRES_PASSWORD通过secretKeyRefferretdb-secret读取,避免明文写死在清单中;
  • 连接串拼接FERRETDB_POSTGRESQL_URL使用 Kubernetes 环境变量展开语法$(POSTGRES_USERNAME)$(POSTGRES_PASSWORD),指向hippo-ha:5432/ferretdb——hippo-ha是 PGO 为集群提供的高可用 Service 名称;
  • Serviceferretdb-service将集群内 27017 端口暴露给其他工作负载访问。

连接配置的源码视角

FERRETDB_POSTGRESQL_URL是 FerretDB 连接 PostgreSQL 的核心配置。从源码看,CLI 定义于 cmd/ferretdb/main.go:

  • --postgresql-url,默认值postgres://127.0.0.1:5432/postgres,环境变量对应FERRETDB_POSTGRESQL_URL
  • --postgresql-url-file,环境变量对应FERRETDB_POSTGRESQL_URL_FILE,若指定则覆盖前者。

官网配置文档还说明了连接细节:

  • FerretDB 使用 pgx v5 库连接 PostgreSQL,URL 支持的查询参数与默认值以 pgx 文档为准;
  • pool_min_conns未设置时为 10、pool_max_conns未设置时为 50;
  • application_name恒为FerretDBtimezone恒为UTC

同时注意:FerretDB 自身的认证完全依赖 PostgreSQL 的认证机制(默认开启,详见 website/docs/security/authentication.md),客户端连接时提供的用户名密码会转发给 PostgreSQL 校验。因此部署时FERRETDB_POSTGRESQL_URL中携带的账号必须是 PostgreSQL 中真实存在的用户。

应用清单并验证

应用 Deployment:

kubectl apply -f deployment.yaml

确认当前路径下有deployment.yaml文件。查看 Pod 运行状态:

kubectl get pods -n postgres-operator NAME READY STATUS RESTARTS AGE ferretdb-86c45849d-bd6tq 1/1 Running 0 6h hippo-backup-6shl-qf9mf 0/1 Completed 0 6h hippo-instance1-mrpt-0 4/4 Running 0 7h hippo-repo-host-0 2/2 Running 0 7h pgo-6f664c9f44-mmptx 1/1 Running 0 7h

ferretdbPod 为Running状态,说明容器已正常启动。

查看 Service 以获取 FerretDB 的集群内访问地址:

kubectl get svc -n postgres-operator NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ferretdb-service ClusterIP 10.254.17.193 <none> 27017/TCP 4d8h hippo-ha ClusterIP 10.254.153.218 <none> 5432/TCP 4d8h hippo-ha-config ClusterIP None <none> <none> 4d8h hippo-pods ClusterIP None <none> <none> 4d8h hippo-primary ClusterIP None <none> 5432/TCP 4d8h hippo-replicas ClusterIP 10.254.33.136 <none> 5432/TCP 4d8h

FerretDB 服务地址为10.254.17.193:27017(以你的实际输出为准)。

使用 mongosh 连接 FerretDB

启动一个临时的mongosh容器:

kubectl -n postgres-operator run mongosh --image=rtsp/mongosh --rm -it -- bash

连接 FerretDB 实例(用户名密码需与前面设置的 PostgreSQL 凭据一致):

mongosh "mongodb://ferretuser:<password>@{FERRETDB SVC}/ferretdb?authMechanism=PLAIN"

兼容性提示:原指南使用了authMechanism=PLAIN。需要注意的是,FerretDB v2.x 已不再支持PLAIN认证机制(参见 website/docs/migration/migrating-from-v1.md 与 website/docs/troubleshooting/overview.md)。若连接报错提示PLAIN机制未启用,请移除 URI 中的authMechanism=PLAIN参数重试。当前 v2 版本在客户端侧支持SCRAM-SHA-256认证,且同样依赖 PostgreSQL 中的真实用户凭据。

获取ferretuser的密码:

kubectl get secret ferretdb-secret -n postgres-operator -o jsonpath='{.data.password}' | base64 --decode

成功连接后,即可开始使用 FerretDB。

基本使用示例

插入与查询文档

testing集合批量插入文档:

db.testing.insertMany([ { a: 23, b: 'b', c: [1, 5], d: { a: 1 } }, { a: 1, b: 34, c: '1', d: [3, 5] } ])

读取全部文档:

db.testing.find()[ ({ _id: ObjectId('64ca02e119e6b74d10806107'), a: 23, b: 'b', c: [1, 5], d: { a: 1 } }, { _id: ObjectId('64ca02e119e6b74d10806107'), a: 1, b: 34, c: '1', d: [3, 5] }) ]

FerretDB 自动为每个文档生成_id(ObjectId),文档字段与 MongoDB 行为保持一致。

FerretDB 如何在 PostgreSQL 中存储数据

FerretDB 并不将文档逐字段映射为关系表,而是将整份 BSON 文档序列化后存入 JSONB 列。在另一终端连接 PostgreSQL 集群:

kubectl exec -it hippo-instance1-mrpt-0 -n postgres-operator -- psql -U postgres

切换到ferretdb数据库:

postgres=# \c ferretdb You are now connected to database "ferretdb" as user "postgres".

设置search_pathferretdb

set search_path to ferretdb;

查看表结构:

ferretdb=# \dt List of relations Schema | Name | Type | Owner ----------+-----------------------------+-------+---------- ferretdb | _ferretdb_database_metadata | table | ferretdb ferretdb | testing_eb5f499b | table | ferretdb (2 rows)

可以看到:每个 MongoDB 集合对应一张 PostgreSQL 表(testing_eb5f499btesting集合),另有_ferretdb_database_metadata元数据表。查看表内容:

ferretdb=# table testing_eb5f499b; _jsonb -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- {"a": 23, "b": "b", "c": [1, 5], "d": {"a": 1}, "$s": {"p": {"a": {"t": "int"}, "b": {"t": "string"}, "c": {"i": [{"t": "int"}, {"t": "int"}], "t": "array"}, "d": {"t": "object", "$s": {"p": {"a": {"t": "int"}}, "$k": ["a"]}}, "_id": {"t": "objectId"}}, "$k": ["_id", "a", "b", "c", "d"]}, "_id": "64ca02e119e6b74d10806107"} {"a": 1, "b": 34, "c": "1", "d": [3, 5], "$s": {"p": {"a": {"t": "int"}, "b": {"t": "int"}, "c": {"t": "string"}, "d": {"i": [{"t": "int"}, {"t": "int"}], "t": "array"}, "_id": {"t": "objectId"}}, "$k": ["_id", "a", "b", "c", "d"]}, "_id": "64ca02e119e6b74d10806108"} (2 rows)

_jsonb列中的每个值都是一份完整的 BSON 文档 JSON 表示,其中内嵌的$s字段记录了文档的 Schema 信息:"t"表示字段类型(如intstringarrayobjectobjectId),$k列出键顺序,数组元素类型记录在"i"中,嵌套对象类型记录在"$s"子结构中。这种“文档 + 类型元数据”的存储设计让 FerretDB 能够在保留 BSON 类型信息(如区分整数与字符串)的同时,充分利用 PostgreSQL 的 JSONB 索引与查询能力。

小结

至此,你已在 Leafcloud 上完成了一套完整的 FerretDB 部署链路:

  1. 用 OpenStack CLI 在 Leafcloud 创建高可用 Kubernetes 集群,并配置cinder-csi默认存储类;
  2. 用 Crunchy Data PostgreSQL Operator 部署带持久化存储与自动备份的 PostgreSQL 集群;
  3. 在 PostgreSQL 中创建用户与数据库,通过 KubernetesSecret安全传递密码;
  4. 部署 FerretDB Deployment 与 Service,用mongosh完成连接与基本读写;
  5. 通过 PostgreSQL 侧查看_jsonb数据,理解 FerretDB 的文档存储模型。

FerretDB 与 MongoDB 协议兼容,这意味着你可以继续使用现有的工具链与框架;而 Leafcloud + PostgreSQL Operator 的组合则提供了生产可用的持久化卷、自动备份、自动伸缩、连接池与监控等能力。关于 FerretDB 更多的配置项(如--postgresql-url--listen-addrFERRETDB_AUTH等)可参阅 website/docs/configuration/flags.md;Kubernetes 上的通用部署模板可参阅 website/docs/installation/ferretdb/kubernetes.md;认证机制与用户创建详见 website/docs/security/authentication.md。

  • 后端
  • 数据库
  • 文档数据库

【免费下载链接】FerretDB

A truly Open Source MongoDB alternative

项目地址:https://gitcode.com/gh_mirrors/fe/FerretDB
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 15:52:34

PRQL 的 from 数据源:指定关系、别名与特殊标识符的完整指南

PRQL 的 from 数据源&#xff1a;指定关系、别名与特殊标识符的完整指南 【免费下载链接】prql PRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement 项目地址: https://gitcode.com/gh_mirrors/pr/prql from 是 PRQL 管…

作者头像 李华
网站建设 2026/9/24 15:47:41

EMC测试必懂:PK、QP、AV三种检波方式原理与实战应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华