kubernetes上的ferretdb + yugabytedb(亚马逊eks):一个分布式sql的mongodb api
#postgres #mongodb #yugabytedb #eks

要为VoxxedDays Ticino准备演示,我已经在Amazon Eks上使用Yugabytedb,开源分布式SQL创建了一个Kubernetes群集,如this post中安装了。

yugabytedb具有与Cassandra兼容的API(称为YCQL)和一个与后Ql兼容的API(称为YSQL)。如果您要为MongoDB编写应用程序,该应用程序要移至SQL数据库怎么办?您可能想将其重写以从SQL功能中受益,但是,您可以同时重新编写所有功能,而是可以在FerretDB上添加MongoDB兼容的API。

让我们将其添加到我的Kubernetes群集中。这是一个测试。 FerretDB仍在早期。但是,MongoDB代理和分布式SQL数据库的这种组合也许是将来是MongoDB或DocumentDB的开源替代方法。

运行连接到yugabytedb的ferretdb

为了测试这种可能性,我将使用ferretdb/ferretdb映像whish whish运行ferretdb启动一个吊舱。我使用--listen-addr--postgresql-url的PostgreSQL连接设置了它的终点。3:

$ kubectl run --image ferretdb/ferretdb ferretdb -- \
 --listen-addr=0.0.0.0:27017 \
 --postgresql-url="postgres://yugabyte:yugabyte@yb-tservers.yb-demo-eu-west-1a.svc.cluster.local:5433/yugabyte"

pod/ferretdb created

它连接到clusterip服务yb-tservers,该连接将连接分配到一个AZ eu-west-1a中的所有Yugabytedb服务器。

我正在从mongosh shell中进行测试:


$ kubectl get pods -o wide

NAME       READY   STATUS    RESTARTS   AGE   IP              NODE                                           NOMINATED NODE   READINESS GATES
ferretdb   1/1     Running   0          11m   192.168.50.78   ip-192-168-48-228.eu-west-1.compute.internal   <none>           <none>

$ kubectl run -it --rm --restart=Never --image mongo mongosh -- \
  mongosh mongodb://192.168.50.78:27017/mongodb

Image description

我可以创建一个集合

mongodb> db.createCollection('demo');
{ ok: 1 }

在yugabytedb上创建相应的表:

Image description

它是自动分布的(碎片和复制):
Image description

我从吊舱中获得了IP地址。我将创建服务。

运行FerretDB Pods的负载平衡器

虽然代理会增加一些延迟。那么您可能需要想要更多的豆荚。我将稍后为其创建一个replicaset,但就目前而言,让我们创建一个载重器来提出这个想法:

$ kubectl expose pod ferretdb --port=27017 --target-port=27017 \
        --name=ferretdb-service --type=LoadBalancer

service/ferretdb-service exposed

我可以通过此服务测试连接:

$ kubectl run -it --rm --restart=Never --image mongo mongosh -- \
 mongosh mongodb://ferretdb-service.default.svc.cluster.local:27017/mongodb --quiet

If you don't see a command prompt, try pressing enter.
mongodb> show collections;
demo
mongodb>

我现在可以使用Internet的FerretDB端点,获取外部IP地址:

$ kubectl get services --field-selector "metadata.name=ferretdb-service" -o jsonpath='{.items[0].status.loadBalancer.ingress[0].hostname}'

abebf50dee88a462ab90d371dfdaa44f-1345053103.eu-west-1.elb.amazonaws.com

我可以通过笔记本电脑与mongosh连接:

$ mongosh mongodb://abebf50dee88a462ab90d371dfdaa44f-1345053103.eu-west-1.elb.amazonaws.com:27017/mongodb --quiet

mongodb> db.demo.insertOne({ "message": "Hello World" });
{
  acknowledged: true,
  insertedId: ObjectId("63c85f7aa3db61ccd4324a04")
}
mongodb> db.demo.findOne();
{ _id: ObjectId("63c85f7aa3db61ccd4324a04"), message: 'Hello World' }
mongodb>

部署为replicaset

现在我已经通过手动创建吊舱和服务进行了测试,我将自动化。我删除了上面创建的那些:

$ kubectl delete service ferretdb-service
service "ferretdb-service" deleted

$ kubectl delete pod ferretdb 
pod "ferretdb" deleted

这是ferretdb复制品的YAML声明:

cat > ferretdb-rs.yaml <<'YAML'
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: ferretdb
  namespace: yb-demo-eu-west-1a
  labels:
    run: ferretdb
spec:
  replicas: 3
  selector:
    matchLabels:
      run: ferretdb
  template:
    metadata:
      labels:
        run: ferretdb
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: topology.kubernetes.io/zone
                operator: In
                values:
                - eu-west-1a
      containers:
      - name: ferretdb
        image: ferretdb/ferretdb
        args:
         - --listen-addr=0.0.0.0:27017
         - --postgresql-url=postgres://yugabyte:yugabyte@yb-tservers.yb-demo-eu-west-1a.svc.cluster.local:5433/yugabyte
YAML
kubectl apply -f ferretdb-rs.yaml

和LoadBalancer:

cat > ferretdb-lb.yaml <<'YAML'
apiVersion: v1
kind: Service
metadata:
  name: ferretdb-service
  namespace: yb-demo-eu-west-1a
  labels:
    run: ferretdb
spec:
  type: LoadBalancer
  selector:
   run: ferretdb
  ports:
    - protocol: TCP
      port: 27017
      targetPort: 27017
YAML
kubectl apply -f ferretdb-lb.yaml

我已经在一个AZ(eu-west-1a)中创建了它们,并连接到同一AZ中的Yugabytedb平板电脑服务器。

与Mongo或Postgres客户联系

我获得了mongoDB端点地址:

$ kubectl get services \
-o jsonpath='mongodb://{.items[0].status.loadBalancer.ingress[0].hostname}:{.items[0].spec.ports[0].port}/mongodb' \
--field-selector "metadata.name=ferretdb-service" \
-n yb-demo-eu-west-1a

mongodb://a4ee051c7cf844538b1bc90fbd3ef56a-565835635.eu-west-1.elb.amazonaws.com:27017/mongodb

使用此内容,我加载了一些示例数据:

$ curl -s https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/latest/owid-covid-latest.json |
  jq -c ".[]" |
  while read json
do
 echo "db.covid.insertOne( $json )" 
done | mongosh mongodb://a4ee051c7cf844538b1bc90fbd3ef56a-565835635.eu-west-1.elb.amazonaws.com:27017/mongodb 

Image description

现在获取PostgreSQL DB地址:

$ kubectl get services \
-o jsonpath='postgres://{.items[0].status.loadBalancer.ingress[0].hostname}:{.items[0].spec.ports[?(@.name=="tcp-ysql-port")].port}/yugabyte' \
--field-selector "metadata.name=yb-tserver-service" \
-n yb-demo-eu-west-1a

postgres://a4ee051c7cf844538b1bc90fbd3ef56a-565835635.eu-west-1.elb.amazonaws.com:5433/yugabyte

我可以与psql联系:

]$ psql postgres://a62cf0d1ce2c94b6a8fb7d169da3b75b-2104684727.eu-west-1.elb.amazonaws.com:5433
Pager usage is off.
psql (13.7, server 11.2-YB-2.17.0.0-b0)
Type "help" for help.

yugabyte=# select "_jsonb"->>'_id' as collection, "_jsonb"->>'table' as tablename 
           from mongodb."_ferretdb_database_metadata";

 collection |   tablename
------------+----------------
 demo       | demo_aefd3536
 covid      | covid_e0d7cdae
(2 rows)

yugabyte=# select count(*) from mongodb.covid_e0d7cdae;
 count
-------
   237
(1 row)

yugabyte=# select "_jsonb"->>'location' as location 
           ,("_jsonb"->>'new_cases_per_million')::numeric as new_cases_per_million 
           from mongodb.covid_e0d7cdae 
           where ("_jsonb"->>'last_updated_date')::date > now()- interval '5 days'
           order by 2 desc nulls last limit 10;

  location  | new_cases_per_million
------------+-----------------------
 Brunei     |              5449.864
 Cyprus     |              3742.158
 San Marino |              2374.592
 Italy      |              1423.841
 Uruguay    |              1096.764
 Japan      |              1022.971
 Tonga      |               963.815
 Taiwan     |               835.377
 Mauritius  |               783.391
 Ireland    |               781.986
(10 rows)

获得正确的性能还有很多事情要做。 FerretDB使用一个没有主键的单个JSONB列创建一个表,并在JSON文档的对象ID属性上添加索引。然后,Yugabytedb创建了一个内部ID来在其上分发。最好把它放在碎片钥匙中,但必须从JSON文档中删除。

Create primary key index for _id automatically #1384
一样,在FerretDB中仍在进行中。如果与ID一起添加了主键,它将成为Yugabytedb中的碎片键。另一个优化将是避免reading information_schema.columns,该information_schema.columns在yugabytedb上很慢(所有节点都必须共享目录)。这将在yugabytedb(#7745)上进行优化。如果仍然是一个可伸缩性问题,也有可能为yugabytedb提供后GrestGresQL处理程序。所有这些都是开源ðÖ©yugabytedb和ferretdb是Apache许可证2.0