使用密钥文件身份验证部署自管理分片集群
Overview
在分片集群上执行访问权限控制需要配置:
对于本教程,分片集群的每个节点必须 使用相同的内部身份验证机制和设置。这意味着,在集群中的每个 mongos
和 mongod
上实施内部身份验证。
以下教程使用密钥文件启用内部身份验证。
实施内部身份验证还可实施用户访问控制。 要连接到副本集, mongosh
等客户端需要使用用户帐户。 请参阅访问控制。
CloudManager 和 OpsManager
如果您使用 Cloud Manager 或 Ops Manager 管理部署,请参阅相应的 Cloud Manager 手册或 Ops Manager 手册来执行身份验证。
Considerations
重要
要避免因 IP 地址变更而更新配置,请使用 DNS 主机名而非 IP 地址。在配置副本集成员或分片集群成员时,使用 DNS 主机名而非 IP 地址尤为重要。
在水平分割网络配置下,请使用主机名而非 IP 地址来配置集群。从 MongoDB 5.0 开始,仅配置了 IP 地址的节点将无法通过启动验证,因而不会启动。
IP 绑定
密钥文件安全
密钥文件是最低限度的安全手段,也最适合测试或开发环境。对于生产环境,建议使用 x.509 证书。
访问控制
本教程仅介绍在 admin
数据库上创建最少数量的管理用户。在用户身份验证方面,本教程使用默认的 SCRAM 身份验证机制。质询响应安全机制最适合测试或开发环境。对于生产环境,建议使用 x.509 证书或自管理 LDAP 代理身份验证(仅用于 MongoDB Enterprise)或自管理部署上的 Kerberos 身份验证(仅用于 MongoDB Enterprise)。
如需详细了解为特定认证机制创建用户,请参阅特定认证机制页面。
请参阅➤ 配置基于角色的访问控制,了解用户创建和管理的最佳实践。
用户(User)
通常,要为分片集群创建用户,请连接到 mongos
并添加分片集群用户。
不过,某些维护操作要求直接连接到分片集群中的特定分片。要执行这些操作,您必须直接连接到分片,并以分片本地管理用户身份进行身份验证。
分片本地用户仅存在于特定分分片,并且只能用于特定于分片的维护和配置。 您无法使用分片本地用户连接到mongos
。
本教程要求创建分片集群用户,但包括添加分片本地用户的可选步骤。
有关更多信息,请参阅自托管部署中的用户安全文档。
操作系统
本教程使用 mongod
和 mongos
程序。Windows 用户应改用 mongod.exe
和 mongos.exe
程序。
开始之前
从MongoDB 8.0开始,您可以使用directShardOperations
角色执行需要直接对分片执行命令的分片操作。
警告
使用directShardOperations
角色运行命令可能会导致集群停止正常工作,并可能导致数据损坏。 仅将directShardOperations
角色用于维护目的或在MongoDB支持的指导下使用。 执行完维护操作后,请停止使用directShardOperations
角色。
使用密钥文件访问控制来部署分片集群
以下过程涉及如何创建一个新的分片集群,此集群由 mongos
、配置服务器和两个分片组成。
重要
要避免因 IP 地址变更而更新配置,请使用 DNS 主机名而非 IP 地址。在配置副本集成员或分片集群成员时,使用 DNS 主机名而非 IP 地址尤为重要。
在水平分割网络配置下,请使用主机名而非 IP 地址来配置集群。从 MongoDB 5.0 开始,仅配置了 IP 地址的节点将无法通过启动验证,因而不会启动。
创建密钥文件
在使用密钥文件身份验证时,分片集群中的每个 mongod
或 mongos
实例将密钥文件内容作为共享密码,以对部署中的其他节点进行身份验证。仅具有正确密钥文件的 mongod
或 mongos
实例可以加入分片集群。
注意
用于内部成员身份验证的密钥文件使用 YAML 格式,允许在密钥文件中包含多个密钥。YAML 格式接受以下任一形式:
单个密钥字符串(与早期版本相同)
键字符串序列
YAML 格式与使用文本文件格式的现有单密钥文件兼容。
密钥长度必须在 6 到 1,024 个字符之间,并且只能包含 base64 集合中的字符。分片集群的所有节点必须共享至少一个通用的密钥。
注意
在 UNIX 系统上,密钥文件不得具有群组或全局权限。在 Windows 系统中,不检查密钥文件权限。
您可以选择任何方法生成密钥文件。例如,以下操作使用 openssl
生成复杂的伪随机 1024 字符串以用作共享密码。然后,它使用 chmod
更改文件权限,仅为文件所有者提供读取权限:
openssl rand -base64 756 > <path-to-keyfile> chmod 400 <path-to-keyfile>
有关使用密钥文件的更多详细信息和要求,请参阅密钥文件。
分发密钥文件
将密钥文件复制到每台托管分片集群成员的服务器上。确保运行 mongod
或 mongos
实例的用户是文件的所有者并且可以访问密钥文件。
避免将密钥文件存储在可以轻松与托管 mongod
或 mongos
实例的硬件断开连接的存储介质上,例如 USB 驱动器或联网存储设备。
创建配置服务器副本集
以下步骤部署配置服务器副本集。
请在生产部署中部署至少包含三个节点的配置服务器副本集。可创建单节点副本集进行测试。
启动配置服务器副本集的每个mongod
。 包括keyFile
设置。 keyFile
设置在自管理部署中实施自管理内部/成员身份验证和基于角色的访问控制。
您可以通过配置文件或命令行指定 mongod
设置。
配置文件
如果使用配置文件,请将 security.keyFile
设置为密钥文件的路径,将 sharding.clusterRole
设置为 configsvr
,并将 replication.replSetName
设置为所需的配置服务器副本集名称。
security: keyFile: <path-to-keyfile> sharding: clusterRole: configsvr replication: replSetName: <setname>
根据配置要求包括其他选项。例如,如果您希望远程客户端连接到部署,或者部署节点运行在不同的主机上,请指定 net.bindIp
设置。
启动 mongod
,同时指定 --config
选项和配置文件的路径。
mongod --config <path-to-config-file>
命令行
如果使用命令行参数,请使用 --keyFile
、--configsvr
和 --replSet
参数启动 mongod
。
mongod --keyFile <path-to-keyfile> --configsvr --replSet <setname> --dbpath <path>
根据配置要求包括其他选项。例如,如果希望远程客户端连接到您的部署,或是您的部署成员运行在不同主机上,请指定 --bind_ip
。
rs.initiate()
方法启动副本集,可以获取可选的副本集配置文档。 在副本集配置文档中,包括:
有关副本集配置文档的更多信息,请参阅自管理副本集配置。
使用 rs.initiate()
方法和配置文档启动副本集:
rs.initiate( { _id: "myReplSet", configsvr: true, members: [ { _id : 0, host : "cfg1.example.net:27019" }, { _id : 1, host : "cfg2.example.net:27019" }, { _id : 2, host : "cfg3.example.net:27019" } ] } )
配置服务器副本集 (CSRS) 启动并运行后,继续创建分片副本集。
创建分片副本集
对于生产部署,请使用至少包含三个成员的副本集。出于测试目的,可创建单成员副本集。
这些步骤包括添加分片本地用户的可选过程。现在执行这些步骤可确保每个分片都有用户可以执行分片级别的维护。
在启用访问控制的情况下启动启动副本集的每个节点。
运行带有keyFile
参数的mongod
会在自管理部署中实施自管理内部/成员身份验证和基于角色的访问控制。
使用配置文件或命令行启动副本集中的每个 mongod
。
配置文件
如果使用配置文件,请将 security.keyFile
选项设置为密钥文件的路径,将 replication.replSetName
选项设置为副本集的所需名称,将 sharding.clusterRole
选项设置为 shardsvr
。
security: keyFile: <path-to-keyfile> sharding: clusterRole: shardsvr replication: replSetName: <replSetName> storage: dbPath: <path>
根据配置要求包括其他选项。例如,如果您希望远程客户端连接到部署,或者部署节点运行在不同的主机上,请指定 net.bindIp
设置。
启动 mongod
,同时指定 --config
选项和配置文件的路径。
mongod --config <path-to-config-file>
命令行
如果使用命令行选项,在启动组件时,请指定 --keyFile
、replSet
和 --shardsvr
参数,如以下示例所示:
mongod --keyFile <path-to-keyfile> --shardsvr --replSet <replSetName> --dbpath <path>
根据配置要求包括其他选项。例如,如果希望远程客户端连接到您的部署,或是您的部署成员运行在不同主机上,请指定 --bind_ip
。
启动新副本集。
从 mongosh
中运行 rs.initiate()
方法。
rs.initiate()
可以接受一个可选的副本集配置文档。在复制集配置文档中,包括:
_id
字段设置为在replication.replSetName
或--replSet
选项中指定的副本集名称。members
数组,为副本集的每个节点包含一个文档。
以下示例会启动一个三节点副本集。
rs.initiate( { _id : "myReplSet", members: [ { _id : 0, host : "s1-mongo1.example.net:27018" }, { _id : 1, host : "s1-mongo2.example.net:27018" }, { _id : 2, host : "s1-mongo3.example.net:27018" } ] } )
rs.initiate()
触发选举,并选出一名节点担任主节点。
在继续之前连接到主节点。使用 rs.status()
查找主节点。
创建分片本地用户管理员(可选)。
重要
创建第一个用户后,本地主机异常就不再可用。
第一个用户必须拥有创建其他用户的特权,如具备 userAdminAnyDatabase
的用户。这样可以确保在自管理部署中的本地主机异常关闭后,您可以创建更多用户。
如果至少一个用户没有创建用户的权限,一旦本地主机异常关闭,您可能无法使用创建或修改具有新特权的用户,因此无法访问必要的操作。
使用 db.createUser()
方法添加用户。该用户应在 admin
数据库中至少拥有 userAdminAnyDatabase
角色。
您必须连接到主节点才能创建用户。
以下示例在 admin
数据库上创建具有 userAdminAnyDatabase
角色的用户 fred
。
重要
密码应随机、长且复杂,以确保系统安全并防止或延迟恶意访问。
提示
您可以将 passwordPrompt()
方法与各种用户身份验证/管理方法/命令结合使用,以提示输入密码,而不是直接在方法/命令调用中指定密码。不过,您仍然可以像使用早期版本的 mongo
shell 一样直接指定密码。
admin = db.getSiblingDB("admin") admin.createUser( { user: "fred", pwd: passwordPrompt(), // or cleartext password roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] } )
根据提示输入密码。有关内置角色以及与数据库管理相关操作的完整列表,请参阅数据库用户角色。
以分片本地用户管理员身份进行身份验证(可选)。
对 admin
数据库进行身份验证。
在 mongosh
中,使用 db.auth()
进行身份验证。例如,以下身份验证为用户管理员 fred
:
提示
您可以将 passwordPrompt()
方法与各种用户身份验证/管理方法/命令结合使用,以提示输入密码,而不是直接在方法/命令调用中指定密码。不过,您仍然可以像使用早期版本的 mongo
shell 一样直接指定密码。
db.getSiblingDB("admin").auth("fred", passwordPrompt()) // or cleartext password
或者,使用 -u <username>
、-p <password>
和 --authenticationDatabase
参数将新的 mongosh
实例连接到副本集主节点。
mongosh -u "fred" -p --authenticationDatabase "admin"
创建分片本地集群管理员(可选)。
分片本地集群管理员用户具有 clusterAdmin
角色,可提供允许访问复制操作的权限。
有关与副本集操作相关的角色的完整列表,请参阅集群管理角色。
在 admin
数据库中创建集群管理员用户并分配 clusterAdmin
角色:
提示
您可以将 passwordPrompt()
方法与各种用户身份验证/管理方法/命令结合使用,以提示输入密码,而不是直接在方法/命令调用中指定密码。不过,您仍然可以像使用早期版本的 mongo
shell 一样直接指定密码。
db.getSiblingDB("admin").createUser( { "user" : "ravi", "pwd" : passwordPrompt(), // or cleartext password roles: [ { "role" : "clusterAdmin", "db" : "admin" } ] } )
根据提示输入密码。
请参阅集群管理角色,获取与副本集和分片集群操作相关的内置角色的完整清单。
将mongos
连接到分片集群
将mongos
连接到集群
使用配置文件或命令行参数启动 mongos
,指定密钥文件。
配置文件
如果使用配置文件,请将 security.keyFile
设置为密钥文件的路径,将 sharding.configDB
设置为副本集名称和至少一个采用 <replSetName>/<host:port>
格式的副本集成员。
security: keyFile: <path-to-keyfile> sharding: configDB: <configReplSetName>/cfg1.example.net:27019,cfg2.example.net:27019,...
根据配置要求包括其他选项。例如,如果您希望远程客户端连接到部署,或者部署节点运行在不同的主机上,请指定 net.bindIp
设置。
启动 mongos
,同时指定 --config
选项和配置文件的路径。
mongos --config <path-to-config>
命令行
如果使用命令行参数,则启动 mongos
,并指定 --keyFile
和 --configdb
参数。
mongos --keyFile <path-to-keyfile> --configdb <configReplSetName>/cfg1.example.net:27019,cfg2.example.net:27019,...
根据配置要求包括其他选项。例如,如果希望远程客户端连接到您的部署,或是您的部署成员运行在不同主机上,请指定 --bind_ip
。
创建用户管理员。
重要
创建第一个用户后,本地主机异常就不再可用。
第一个用户必须拥有创建其他用户的特权,如具备 userAdminAnyDatabase
的用户。这样可以确保在自管理部署中的本地主机异常关闭后,您可以创建更多用户。
如果至少一个用户没有创建用户的权限,则一旦 Localhost Exception 关闭,您将无法创建或修改用户,因此可能无法执行必要的操作。
使用 db.createUser()
方法添加用户。该用户应在 admin
数据库中至少拥有 userAdminAnyDatabase
角色。
重要
密码应随机、长且复杂,以确保系统安全并防止或延迟恶意访问。
以下示例在 admin
数据库上创建 fred
用户:
提示
您可以将 passwordPrompt()
方法与各种用户身份验证/管理方法/命令结合使用,以提示输入密码,而不是直接在方法/命令调用中指定密码。不过,您仍然可以像使用早期版本的 mongo
shell 一样直接指定密码。
admin = db.getSiblingDB("admin") admin.createUser( { user: "fred", pwd: passwordPrompt(), // or cleartext password roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] } )
有关内置角色和与数据库管理操作相关的角色的完整列表,请参阅数据库用户角色。
以用户管理员身份进行身份验证。
使用 db.auth()
以用户管理员身份进行身份验证,才能创建其他用户:
提示
您可以将 passwordPrompt()
方法与各种用户身份验证/管理方法/命令结合使用,以提示输入密码,而不是直接在方法/命令调用中指定密码。不过,您仍然可以像使用早期版本的 mongo
shell 一样直接指定密码。
db.getSiblingDB("admin").auth("fred", passwordPrompt()) // or cleartext password
根据提示输入密码。
或者,使用-u <username>
、 -p <password>
和--authenticationDatabase "admin"
参数将新的mongosh
会话连接到目标副本集节点。 您必须使用自托管部署中的本地主机异常来连接到mongos
。
mongosh -u "fred" -p --authenticationDatabase "admin"
创建集群管理的管理用户
集群管理员用户具有 clusterAdmin
角色,该角色可授予对复制和分片操作的访问权限。
在 admin
数据库中创建 clusterAdmin
用户。
以下示例在admin
数据库上创建用户ravi
。
重要
密码应随机、长且复杂,以确保系统安全并防止或延迟恶意访问。
提示
您可以将 passwordPrompt()
方法与各种用户身份验证/管理方法/命令结合使用,以提示输入密码,而不是直接在方法/命令调用中指定密码。不过,您仍然可以像使用早期版本的 mongo
shell 一样直接指定密码。
db.getSiblingDB("admin").createUser( { "user" : "ravi", "pwd" : passwordPrompt(), // or cleartext password roles: [ { "role" : "clusterAdmin", "db" : "admin" } ] } )
请参阅集群管理角色,获取与副本集和分片集群操作相关的内置角色的完整清单。
创建其他用户(可选)。
创建用户以允许客户端连接和访问权限分分片集群。 有关可用的内置角色,例如 read
和 ,请参阅readWrite
数据库用户角色 。您可能还需要其他管理用户。 有关用户的更多信息,请参阅自托管部署中的用户。
要创建其他用户,必须以具有 userAdminAnyDatabase
或 userAdmin
角色的用户身份进行身份验证。
向集群添加分片
要继续,您必须连接到 mongos
,并以分片集群的集群管理员用户身份进行身份验证。
注意
这是分片集群的集群管理员,而不是 分片本地集群管理员。
若要将每个分片添加到集群,请使用 sh.addShard()
方法。如果分片是副本集,请指定副本集的名称,然后指定该副本集的节点。在生产部署中,所有分片都应是副本集。
以下操作将单个分片副本集添加到该集群中:
sh.addShard( "<replSetName>/s1-mongo1.example.net:27017")
以下操作是在集群中添加独立 mongod
分片的示例:
sh.addShard( "s1-mongo1.example.net:27017")
重复这些步骤,直到集群包含所有分片。此时,分片集群对集群以及每个分片集群组件之间的内部通信实施访问控制。
将集合分片
要继续,您必须连接到 mongos
,并以分片集群的集群管理员用户身份进行身份验证。
注意
这是分片集群的集群管理员,而不是 分片本地集群管理员。
要对集合进行分片,请使用sh.shardCollection()
方法。您必须指定集合的完整命名空间和包含分片键的文档。
您选择的分片键会影响分片效率,以及您利用某些分片功能(例如区域)的能力。请参阅选择分片键中列出的选择注意事项。
如果集合已包含数据,则必须先使用 db.collection.createIndex()
方法在分片键上创建索引,然后再使用 shardCollection()
。
如果集合为空,MongoDB 会将索引创建为sh.shardCollection()
的一部分。
以下是 sh.shardCollection()
方法的示例:
sh.shardCollection("<database>.<collection>", { <key> : <direction> } )
后续步骤
创建用户以允许客户端连接到分片集群,并与之交互。
有关用于创建只读和读写用户的基本内置角色,请参阅数据库用户角色。
x.509 内部身份验证
有关使用 x.509 进行内部身份验证的详细信息,请参阅使用 x.509 证书对托理 MongoDB 进行成员身份验证。
要从密钥文件内部身份验证升级到 x. 509内部身份验证,请参阅将自管理MongoDB从密钥文件身份验证升级到 x。 509身份验证。