- 后端
- 数据库
- 文档数据库
【免费下载链接】FerretDB
A truly Open Source MongoDB alternative
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端口)。
流程分为三大阶段:
- 在 Leafcloud 上创建 Kubernetes 集群并配置 Cinder CSI 存储类;
- 通过 PostgreSQL Operator 创建 PostgreSQL 集群并初始化用户与数据库;
- 部署 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通过secretKeyRef从ferretdb-secret读取,避免明文写死在清单中; - 连接串拼接:
FERRETDB_POSTGRESQL_URL使用 Kubernetes 环境变量展开语法$(POSTGRES_USERNAME)、$(POSTGRES_PASSWORD),指向hippo-ha:5432/ferretdb——hippo-ha是 PGO 为集群提供的高可用 Service 名称; - Service:
ferretdb-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恒为FerretDB,timezone恒为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 7hferretdbPod 为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 4d8hFerretDB 服务地址为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_path为ferretdb:
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_eb5f499b即testing集合),另有_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"表示字段类型(如int、string、array、object、objectId),$k列出键顺序,数组元素类型记录在"i"中,嵌套对象类型记录在"$s"子结构中。这种“文档 + 类型元数据”的存储设计让 FerretDB 能够在保留 BSON 类型信息(如区分整数与字符串)的同时,充分利用 PostgreSQL 的 JSONB 索引与查询能力。
小结
至此,你已在 Leafcloud 上完成了一套完整的 FerretDB 部署链路:
- 用 OpenStack CLI 在 Leafcloud 创建高可用 Kubernetes 集群,并配置
cinder-csi默认存储类; - 用 Crunchy Data PostgreSQL Operator 部署带持久化存储与自动备份的 PostgreSQL 集群;
- 在 PostgreSQL 中创建用户与数据库,通过 Kubernetes
Secret安全传递密码; - 部署 FerretDB Deployment 与 Service,用
mongosh完成连接与基本读写; - 通过 PostgreSQL 侧查看
_jsonb数据,理解 FerretDB 的文档存储模型。
FerretDB 与 MongoDB 协议兼容,这意味着你可以继续使用现有的工具链与框架;而 Leafcloud + PostgreSQL Operator 的组合则提供了生产可用的持久化卷、自动备份、自动伸缩、连接池与监控等能力。关于 FerretDB 更多的配置项(如--postgresql-url、--listen-addr、FERRETDB_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
相关推荐
JDK HotSpot 反汇编插件 hsdis:Capstone、LLVM、binutils 三大后端的构建与使用实战指南
JDK HotSpot 反汇编插件 hsdis:Capstone、LLVM、binutils 三大后端的构建与使用实战指南 本文围绕 JDK 仓库中的 hsdi
后端数据库文档数据库在 Kubernetes 上通过 StackGres Operator 部署 FerretDB 的完整实战指南
在 Kubernetes 上通过 StackGres Operator 部署 FerretDB 的完整实战指南 本文是一篇围绕 FerretDB + Stack
后端数据库文档数据库使用 KubeDB 托管 PostgreSQL 在 Kubernetes 上部署 FerretDB 实战指南
使用 KubeDB 托管 PostgreSQL 在 Kubernetes 上部署 FerretDB 实战指南 FerretDB 是一款开源文档数据库,它在 Po
后端数据库文档数据库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考