2.2. 集群设置

本节介绍准备、安装和设置第一个 CouchDB 2.x/3.x 集群所需的一切。

2.2.1. 端口和防火墙

CouchDB 使用以下端口

端口号

协议

推荐绑定

用途

5984

tcp

按需,默认情况下为 localhost

所有 HTTP API 请求的标准集群端口

4369

tcp

localhost 用于单节点安装。如果集群化,则为私有接口

Erlang 端口映射守护进程 (epmd)

高于 1024 的随机数(见下文)

tcp

私有接口

与集群中其他 CouchDB 节点通信

在集群模式下,CouchDB 使用端口 5984,就像在独立配置中一样。在 CouchDB 3.x 中,以前在 CouchDB 2.x 中使用的端口 5986 已被删除。以前在该端口可访问的所有端点现在都可以在 /_node/{node-name}/... 层次结构下通过主 5984 端口访问。

CouchDB 使用 Erlang 本地集群功能来实现集群安装。Erlang 使用 TCP 端口 4369 (EPMD) 来查找其他节点,因此所有服务器都必须能够在该端口上相互通信。在 Erlang 集群中,所有节点都以网状网络配置连接到所有其他节点。

然后,在该机器上运行的每个 Erlang 应用程序(如 CouchDB)都会使用自动分配的端口与其他节点通信。是的,这意味着随机端口。这显然不适用于防火墙,但可以强制 Erlang 应用程序使用特定端口范围。

本文档将使用 TCP 9100-9200 范围,但该范围过大。如果您的机器上只运行一个 Erlang 应用程序,则该范围可以限制为单个端口:9100-9100,因为 Erlang 分配的端口仅用于入站连接。在开发集群场景中,在单台机器上运行的三个 CouchDB 节点将需要此范围内的三个端口。

警告

如果您将分发端口暴露给互联网或任何其他不受信任的网络,那么唯一保护您的就是 Erlang cookie

2.2.2. 配置和测试与 Erlang 的通信

2.2.2.1. 使 CouchDB 使用正确的 IP|FQDN 和开放端口

在文件 etc/vm.args 中,将行 -name [email protected] 更改为 -name couchdb@<reachable-ip-address|fully-qualified-domain-name>,它定义了节点的名称。每个节点都必须有一个标识符,以便远程系统可以与其通信。节点名称的格式为 <name>@<reachable-ip-address|fully-qualified-domain-name>

名称部分可以在所有节点上都是 couchdb,除非您在同一服务器上运行多个 CouchDB 节点,并且这些节点具有相同的 IP 地址或域名。在这种情况下,我们建议使用 couchdb1couchdb2 等名称。

节点名称的第二部分必须是其他节点可以用来访问该节点的标识符 - 可能是节点的完全限定域名 (FQDN) 或节点的 IP 地址。FQDN 是首选,这样您就可以重新编号节点的 IP 地址,而不会对集群造成干扰。(这在云托管环境中很常见。)

警告

使用 /etc/hostslibresolv 的技巧不适用于 Erlang。要么正确设置 DNS 并使用完全限定域名,要么使用 IP 地址。DNS 和 FQDN 是首选。

稍后更改名称比较麻烦(例如移动分片),因此您需要设置一次,并且无需更改。

打开 etc/vm.args(在所有节点上),并添加 -kernel inet_dist_listen_min 9100-kernel inet_dist_listen_max 9200,如下所示

-name ...
-setcookie ...
...
-kernel inet_dist_listen_min 9100
-kernel inet_dist_listen_max 9200

同样,一个小范围就可以了,如果每台机器上只运行一个 CouchDB 节点,则可以缩小到单个端口(将两者都设置为 9100)。

2.2.2.2. 确认节点之间的连接

对于此测试,您需要 2 台具有工作主机名的服务器。我们称它们为 server1.test.com 和 server2.test.com。它们分别位于 192.168.0.1192.168.0.2

在 server1.test.com 上

erl -name [email protected] -setcookie 'brumbrum' -kernel inet_dist_listen_min 9100 -kernel inet_dist_listen_max 9200

然后在 server2.test.com 上

erl -name [email protected] -setcookie 'brumbrum' -kernel inet_dist_listen_min 9100 -kernel inet_dist_listen_max 9200
对命令的解释
  • erl Erlang shell。

  • -name [email protected] Erlang 节点的名称及其 IP 地址或 FQDN。

  • -setcookie 'brumbrum' 节点相互连接时使用的“密码”。

  • -kernel inet_dist_listen_min 9100 范围内的最低端口。

  • -kernel inet_dist_listen_max 9200 范围内的最高端口。

这给了我们 2 个 Erlang shell。shell1 在 server1 上,shell2 在 server2 上。现在连接它们。输入以下内容,确保以句点 (.) 结束行

在 shell1 中

net_kernel:connect_node('[email protected]').

这将连接到名为 car 的节点,该节点位于名为 192.168.0.2 的服务器上。

如果返回 true,则您有一个 Erlang 集群,并且防火墙已打开。这意味着这两台服务器上的两个 CouchDB 节点将能够成功地相互通信。如果您得到 false 或根本没有得到任何东西,那么您的防火墙、DNS 或设置存在问题。请重试。

如果您担心防火墙问题,或者稍后在连接集群的所有节点时遇到问题,请在所有服务器对之间重复上述测试,以确认连接和系统配置正确。

2.2.3. 准备将 CouchDB 节点加入集群

在您可以添加节点以形成集群之前,您必须让它们监听集群中其他节点可以访问的 IP 地址。您还应该确保在将节点加入集群之前,一些关键设置在所有节点上都相同。

我们建议您现在设置的设置(在将节点加入集群之前)是

  1. etc/vm.args 设置,如 前两节 中所述

  2. 至少一个 服务器管理员 用户(和密码)

  3. 将节点的集群接口(端口 5984)绑定到可访问的 IP 地址

  4. 一致的 UUID。UUID 用于在复制时识别集群。如果此值在集群中的所有节点上不一致,则复制可能会被迫将更改提要倒带到零,从而导致过度的内存、CPU 和网络使用。

  5. 一致的 httpd secret。密钥用于计算和评估 cookie 和代理身份验证,应一致设置,以避免不必要的重复会话 cookie 请求。

从 CouchDB 3.0 开始,当使用下面描述的设置 API 端点时,步骤 4 和 5 会自动为您执行。

如果您使用配置管理工具(如 Chef、Ansible、Puppet 等),那么您可以在 .ini 文件中放置这些设置,并在提前将它们分发到所有节点。如果您使用此方法,请确保预先加密密码(从测试实例中剪切和粘贴最容易),以避免 CouchDB 重新写入文件。

如果您没有使用配置管理,或者只是第一次尝试使用 CouchDB,请在每个服务器上运行一次以下命令来执行上述步骤 2-4。请务必将 password 更改为安全的密码,并且在所有节点上使用相同的密码。您可能需要在每个节点上本地运行这些命令;如果是这样,请将以下内容中的 <server-IP|FQDN> 替换为 127.0.0.1

# First, get two UUIDs to use later on. Be sure to use the SAME UUIDs on all nodes.
curl http://<server-IP|FQDN>:5984/_uuids?count=2

# CouchDB will respond with something like:
#   {"uuids":["60c9e8234dfba3e2fdab04bf92001142","60c9e8234dfba3e2fdab04bf92001cc2"]}
# Copy the provided UUIDs into your clipboard or a text editor for later use.
# Use the first UUID as the cluster UUID.
# Use the second UUID as the cluster shared http secret.

# Create the admin user and password:
curl -X PUT http://<server-IP|FQDN>:5984/_node/_local/_config/admins/admin -d '"password"'

# Now, bind the clustered interface to all IP addresses available on this machine
curl -X PUT http://<server-IP|FQDN>:5984/_node/_local/_config/chttpd/bind_address -d '"0.0.0.0"'

# If not using the setup wizard / API endpoint, the following 2 steps are required:
# Set the UUID of the node to the first UUID you previously obtained:
curl -X PUT http://<server-IP|FQDN>:5984/_node/_local/_config/couchdb/uuid -d '"FIRST-UUID-GOES-HERE"'

# Finally, set the shared http secret for cookie creation to the second UUID:
curl -X PUT http://<server-IP|FQDN>:5984/_node/_local/_config/chttpd_auth/secret -d '"SECOND-UUID-GOES-HERE"'

2.2.4. 集群设置向导

CouchDB 2.x/3.x 在 Fauxton Web 管理界面中提供了一个方便的集群设置向导。对于首次集群设置和实验,这是您的最佳选择。

强烈建议集群中的最小节点数为 3。有关更多说明,请参阅本文档的集群理论部分。

在安装并启动集群中的所有节点后,确保所有节点都可访问,并且完成了上述预配置步骤,请访问 Fauxton 的 http://<server1>:5984/_utils#setup。系统会要求您将 CouchDB 设置为单节点实例或设置集群。

单击“设置集群”后,系统会再次要求您提供管理员凭据,然后要求您按 IP 地址添加节点。要获取更多节点,请对每个节点执行相同的安装过程,并使用同一台机器执行设置过程。在添加节点之前,请务必指定要添加到集群中的节点总数。

现在,在设置向导中输入每个节点的 IP 地址或 FQDN,确保您还输入了之前设置的服务器管理员用户名和密码。

添加完所有节点后,单击“设置”,Fauxton 将为您完成集群配置。

要检查所有节点是否已正确加入,请访问每个节点上的 http://<server-IP|FQDN>:5984/_membership。返回的列表应显示集群中的所有节点。

cluster_nodes 部分是预期节点的列表;all_nodes 部分是实际连接节点的列表。请确保这两个列表匹配。

现在,您的集群已准备就绪!您可以向任何一个节点发送请求,所有三个节点都将像您使用单个 CouchDB 集群一样进行响应。

对于适当的生产环境设置,您现在将在集群前面设置一个 HTTP 反向代理,用于负载平衡和 SSL 终止。我们推荐使用 HAProxy,但也可以使用其他代理。示例配置可在最佳实践部分找到。

2.2.5. 集群设置 API

如果您希望手动配置 CouchDB 集群,CouchDB 会公开 _cluster_setup 端点以供此目的。在安装和初始设置/配置后,我们可以设置集群。在每个节点上,我们需要运行以下命令来设置节点。

curl -X POST -H "Content-Type: application/json" http://admin:[email protected]:5984/_cluster_setup -d '{"action": "enable_cluster", "bind_address":"0.0.0.0", "username": "admin", "password":"password", "node_count":"3"}'

之后,我们可以将所有节点连接在一起。选择一个节点作为“设置协调节点”以在其上运行所有这些命令。此“设置协调节点”仅管理设置,并要求所有其他节点能够看到它,反之亦然。它除了设置过程之外没有其他特殊用途;CouchDB 在集群中没有“主节点”的概念。

设置无法与不可用的节点一起使用。所有节点必须在线并正确预配置,才能开始集群设置过程。

要将节点加入集群,请对要添加的每个节点运行以下命令。

curl -X POST -H "Content-Type: application/json" http://admin:password@<setup-coordination-node>:5984/_cluster_setup -d '{"action": "enable_cluster", "bind_address":"0.0.0.0", "username": "admin", "password":"password", "port": 5984, "node_count": "3", "remote_node": "<remote-node-ip>", "remote_current_user": "<remote-node-username>", "remote_current_password": "<remote-node-password>" }'
curl -X POST -H "Content-Type: application/json" http://admin:password@<setup-coordination-node>:5984/_cluster_setup -d '{"action": "add_node", "host":"<remote-node-ip>", "port": <remote-node-port>, "username": "admin", "password":"password"}'

这将把这两个节点连接在一起。继续对要添加到集群中的每个节点运行上述命令。完成后,运行以下命令以完成集群设置并添加系统数据库。

curl -X POST -H "Content-Type: application/json" http://admin:password@<setup-coordination-node>:5984/_cluster_setup -d '{"action": "finish_cluster"}'

验证安装

curl http://admin:password@<setup-coordination-node>:5984/_cluster_setup

响应

{"state":"cluster_finished"}

验证所有集群节点是否已连接

curl http://admin:password@<setup-coordination-node>:5984/_membership

响应

如果集群已启用并且 all_nodescluster_nodes 列表不匹配,请使用 curl 通过 PUT /_node/_local/_nodes/couchdb@<reachable-ip-address|fully-qualified-domain-name> 添加节点,并通过 DELETE /_node/_local/_nodes/couchdb@<reachable-ip-address|fully-qualified-domain-name> 删除节点。

您的 CouchDB 集群现已设置完成。