在本教程中,您将使用Atlas定时触发器,通过以编程方式调用Atlas Administration API来自动执行集群管理任务。
本教程包括以下过程:
初始设置:创建对现有Atlas项目具有 权限的
Project Owner服务帐户,将服务帐户凭证存储为值和密钥,然后创建可重用的函数,使用这些凭证调用更新一个集群项目端点。注意
如果您更愿意使用API密钥而不是服务帐户来向具有 权限的Atlas Administration API进行身份验证,则可以将
Project OwnerAPI公钥和私钥另存为值和密钥,以便在本教程的函数中使用。
所需权限
Project Owner要完成本教程,您需要一个对MongoDB Atlas项目具有 访问权限的用户。
初始设置
此初始设立只需完成一次,并允许您在此页面上创建计划触发器以自动执行集群管理任务。在执行本教程之前,请确保您的MongoDB Atlas项目至少有一个集群。此过程执行以下设立任务:
为Atlas服务帐户创建并保存凭证,触发器将使用该档案来调用Atlas Administration API,并对现有Atlas项目具有
Project Owner权限。创建一个名为
getAuthHeaders的可重用函数,该函数使用服务帐户凭证生成访问权限令牌,并返回适当的身份验证标头以调用Atlas Administration API。
创建服务帐户。
要创建一个服务帐户,您的触发器可以使用该帐户来调用对现有Atlas项目具有Project Owner 权限的Atlas Administration API :
在 Atlas 中,转到 Users 页面。
如果尚未显示,组织从导航栏中的Organizations菜单。
单击 Identity & Access 部分下侧边栏中的 All Projects,然后选择所需的项目。
单击 Security 部分下侧边栏中的 Project Identity & Access。
单击Create ApplicationService Account 。
输入服务帐户信息。
名称:服务帐户的名称。 (例如,
TriggersServiceAccount)描述:(可选)服务帐户的描述。 (例如,用于Atlas Functions 调用Atlas Administration API的服务帐号。)
服务帐户权限:
Project Owner
单击 Create(连接)。
这会创建服务帐户,并自动将其添加到具有
Organization Member权限的项目的父组织。配置 API Access List。
如果要限制哪些IP地址可以使用此服务帐户调用Atlas Administration API ,请将IP地址添加到 API Access List。
注意
如果为您的组织启用了 Require IP Access List for the Atlas Administration API,或者您在服务帐户的 API Access List 中添加了任何IP地址,则每个Atlas Administration API请求都必须通过IP访问列表检查。
Atlas Triggers和函数从一设立特定的出站IP地址发送传出HTTP请求。启用定时触发器能够调用Atlas Administration API和其他外部服务,您必须将这些IP地址添加到服务帐户的 API Access List 中。
有关Atlas Function 使用的出站IP地址的完整列表,请参阅函数安全出站IP访问。您必须单独添加每个IP解决。
将服务帐户凭证存储为值和密钥。
创建以下值和密钥来存储您的服务帐户凭证:
AtlasClientId包含服务帐户客户端ID的值。AtlasClientSecret包含服务帐户客户端密钥的密钥。AtlasClientSecret链接到密钥的值。这样,您就可以访问权限函数中的客户端密钥值,同时仍将其安全地存储为密钥。
在 Atlas 中,前往 Triggers 页面。
如果尚未显示,请从导航栏上的 Organizations 菜单中选择包含项目的组织。
如果尚未显示,请从导航栏的 Projects 菜单中选择您的项目。
在侧边栏中,单击 Streaming Data 标题下的 Triggers。
会显示触发器页面。
导航至 Values 页面。
单击 Linked App Service: Triggers(管理员)链接。
在侧边栏中,单击 Build 标题下的 Values。
将客户端ID存储在值中。
单击 Create a Value
输入
AtlasClientId作为 Value Name。选择 Value 类型。
选择Custom Content选项并输入客户端ID。
注意
您必须以带引号的字符串值形式输入客户端ID (
"<clientId>")。单击 Save(连接)。
将客户端密钥存储在密钥中并将其链接到值。
注意
无法直接访问密钥值,因此您必须创建链接到该密钥的第二个值。
单击 Create a Value(连接)。
输入
AtlasClientSecret作为 Value Name。选择 Value 类型。
选择 Link to Secret 选项。
输入
AtlasClientSecret并单击 Create "AtlasClientSecret" 为密钥值命名。将客户端密钥粘贴到密钥名称下方显示的 Client Secret字段中。
单击 Save 以创建密钥和值。
创建getAuthHeaders 函数。
要创建可重用的函数,该函数使用服务帐户凭证检索访问权限令牌并返回适当的身份验证标头以调用Atlas Administration API:
导航至 Functions 页面。
在侧边栏中,单击 Build 标题下的 Functions。
单击 Create a Function(连接)。
默认显示 Settings标签页。
输入
getAuthHeaders作为函数的 Name。将 Private 设置为
true。此函数只能由本教程中的其他函数调用。将 Settings标签页中的其他配置选项保留为默认值。
定义函数代码。
单击 Function Editor标签页并粘贴以下代码以定义函数:
1 /* 2 * Generate API request headers with a new Service Account Access Token. 3 */ 4 exports = async function getAuthHeaders() { 5 6 // Get stored credentials 7 clientId = context.values.get("AtlasClientId"); 8 clientSecret = context.values.get("AtlasClientSecret"); 9 10 // Throw an error if credentials are missing 11 if (!clientId || !clientSecret) { 12 throw new Error("Authentication credentials not found. Set AtlasClientId/AtlasClientSecret (service account auth credentials)."); 13 } 14 15 // Define the argument for the HTTP request to get the access token 16 const tokenUrl = "https://cloud.mongodb.com/api/oauth/token"; 17 const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString("base64"); 18 19 const arg = { 20 url: tokenUrl, 21 headers: { 22 "Authorization": [ `Basic ${credentials}` ], 23 "Content-Type": [ "application/x-www-form-urlencoded" ] 24 }, 25 body: "grant_type=client_credentials" 26 } 27 28 // The response body is a BSON.Binary object; parse it to extract the access token 29 const response = await context.http.post(arg); 30 const tokenData = JSON.parse(response.body.text()); 31 const accessToken = tokenData.access_token; 32 33 // Define the Accept header with the resource version from env var or default to latest stable 34 const resourceVersion = context.environment.ATLAS_API_VERSION || "2025-03-12"; 35 const acceptHeader = `application/vnd.atlas.${resourceVersion}+json`; 36 37 // Return the access token as headers for future API calls 38 return { 39 headers: { 40 "Authorization": [ `Bearer ${accessToken}` ], 41 "Accept": [ acceptHeader ], 42 "Accept-Encoding": [ "bzip, deflate" ], 43 "Content-Type": [ "application/json" ] 44 } 45 }; 46 }
创建modifyCluster 函数。
要创建一个可重用函数来封装“在一个项目中更新一个集群”端点,请执行以下操作:
在 Functions 页面中,单击 Create a Function。
默认显示 Settings标签页。
输入
modifyCluster作为函数的 Name。将 Private 设置为
true。此函数只能由本教程中的其他函数调用。将 Settings标签页中的其他配置选项保留为默认值。
定义函数代码。
单击 Function Editor标签页并粘贴以下代码以定义函数:
1 /* 2 * Modifies the cluster as defined by the `body` parameter. 3 * See https://www.mongodb.com/zh-cn/docs/atlas/reference/api-resources-spec/v2/#tag/Clusters/operation/updateCluster 4 */ 5 exports = async function(projectID, clusterName, body) { 6 7 // Easy testing from the console 8 if (projectID === "Hello world!") { 9 projectID = "<projectId>"; 10 clusterName = "<clusterName>"; 11 body = { paused: false }; 12 } 13 14 // Retrieve headers to authenticate with a new access token, and define the request URL for the Atlas API endpoint 15 const authHeaders = await context.functions.execute("getAuthHeaders"); 16 const requestUrl = `https://cloud.mongodb.com/api/atlas/v2/groups/${projectID}/clusters/${clusterName}`; 17 18 // Build the argument for the HTTP request to the Atlas API to modify the cluster 19 const arg = { 20 url: requestUrl, 21 headers: authHeaders.headers, 22 body: JSON.stringify(body) 23 }; 24 25 // The response body is a BSON.Binary object; parse it and return the modified cluster description 26 const response = await context.http.patch(arg); 27 if (response.body) { 28 return EJSON.parse(response.body.text()); 29 } else { 30 throw new Error(`No response body returned from Atlas API. Status code: ${response.status}`); 31 } 32 }; 注意
在函数编辑器中测试代码。
当您在 Testing Console 中运行函数时,Function Editor 会自动提供
"Hello world!"作为第一个参数。此代码会测试该输入,并在收到"Hello world!"时为参数提供值。要使用自己的输入测试函数,请将以下占位符值替换为您自己的信息:
<projectId><clusterName>在
body参数中,提供一个有效负载,其中包含您要对集群进行的修改。示例代码包含暂停集群的有效负载。
按计划暂停和恢复集群
此过程创建定时触发器,以便每天晚上自动暂停集群,并在每个工作日早上恢复集群。这对于不需要在工作时间之外运行的非生产集群,或者您想要按安排自动暂停和恢复的任何集群非常有用。
创建pauseClusters 函数。
在 Atlas 中,前往 Triggers 页面。
如果尚未显示,请从导航栏上的 Organizations 菜单中选择包含项目的组织。
如果尚未显示,请从导航栏的 Projects 菜单中选择您的项目。
在侧边栏中,单击 Streaming Data 标题下的 Triggers。
会显示触发器页面。
导航至Functions页面
单击 Linked App Service: Triggers(管理员)链接。
在侧边栏中,单击 Build 标题下的 Functions。
单击 Create a Function(连接)。
默认显示 Settings标签页。
输入
pauseClusters作为函数的 Name。将 Private 设置为
true。在本教程中,此函数只会由pauseClusters触发器调用。将 Settings标签页中的其他配置选项保留为默认值。
定义函数代码。
单击 Function Editor标签页并粘贴以下代码以定义函数:
1 /* 2 * Iterates over the provided projects and clusters, pausing those clusters. 3 */ 4 exports = async function () { 5 6 // Supply project IDs and cluster names to pause 7 const projectIDs = [ 8 { 9 id: "<projectIdA>", 10 names: [ "<clusterNameA>", "<clusterNameB>" ] 11 }, 12 { 13 id: "<projectIdB>", 14 names: [ "<clusterNameC>" ] 15 } 16 ]; 17 18 // Set desired state 19 const body = { paused: true }; 20 21 // Pause each cluster and log the response 22 for (const project of projectIDs) { 23 for (const cluster of project.names) { 24 const result = await context.functions.execute( 25 "modifyCluster", 26 project.id, 27 cluster, 28 body, 29 ); 30 console.log("Cluster " + cluster + ": " + EJSON.stringify(result)); 31 } 32 } 33 34 return "Clusters Paused"; 35 }; 将
projectIDs大量替换为您自己的项目和集群名称。
创建pauseClusters 定时触发器。
在 Functions 页面中,单击 Build 标题下侧边栏中的 Triggers,导航到 Triggers 页面。
单击 Create a Trigger 打开触发器配置页面。
如果已有触发器,请单击 Add a Trigger
配置触发器设置。
在 Trigger Details 中,设立以下配置:
设置值触发器类型
預定
进度表类型
重新启用时跳过事件
打开。这可以防止触发器在禁用触发器时排队的计划上执行。
eventType
函数。从下拉列表中选择
pauseClusters函数。触发器名称
pauseClusters单击 Save 以创建触发器。
现在,您的测试集群将在每天晚上美国东部时间下午 6 自动暂停。
创建resumeClusters 函数。
将
pauseClusters函数复制到名为resumeClusters的新函数中。在 Function Editor标签页中,在函数代码中将
paused状态更新为false:1 /* 2 * Iterates over the provided projects and clusters, resuming those clusters. 3 */ 4 exports = async function () { 5 6 // Supply project IDs and cluster names to resume 7 const projectIDs = [ 8 { 9 id: "<projectIdA>", 10 names: [ "<clusterNameA>", "<clusterNameB>" ] 11 }, 12 { 13 id: "<projectIdB>", 14 names: [ "<clusterNameC>" ] 15 } 16 ]; 17 18 // Set desired state 19 const body = { paused: false }; 20 21 // Resume each cluster and log the response 22 for (const project of projectIDs) { 23 for (const cluster of project.names) { 24 const result = await context.functions.execute( 25 "modifyCluster", 26 project.id, 27 cluster, 28 body, 29 ); 30 console.log("Cluster " + cluster + ": " + EJSON.stringify(result)); 31 } 32 } 33 34 return "Clusters Resumed"; 35 };
按计划扩展集群
此过程创建定时触发器,以便在高峰时段自动扩展集群,并在高峰时段自动缩减集群。这对于具有可预测使用模式的集群非常有用,在这些集群中,您希望在工作负载增加之前主动扩展,然后再扩展以节省成本。
创建scaleClusterUp 函数。
在 Atlas 中,前往 Triggers 页面。
如果尚未显示,请从导航栏上的 Organizations 菜单中选择包含项目的组织。
如果尚未显示,请从导航栏的 Projects 菜单中选择您的项目。
在侧边栏中,单击 Streaming Data 标题下的 Triggers。
会显示触发器页面。
导航至Functions页面
单击 Linked App Service: Triggers(管理员)链接。
在侧边栏中,单击 Build 标题下的 Functions。
单击 Create a Function(连接)。
默认显示 Settings标签页。
输入
scaleClusterUp作为函数的 Name。将 Private 设置为
true。在本教程中,此函数只会由scaleClusterUp触发器调用。将 Settings标签页中的其他配置选项保留为默认值。
定义函数代码。
在 Create Function 页面中,单击 Function Editor标签页并粘贴以下代码以定义函数:
1 /* 2 * Scales a single cluster up to a larger instance size. 3 * This example scales an AWS cluster up to M30 in region US_EAST_1. 4 */ 5 exports = async function() { 6 // Supply project ID and cluster name... 7 const projectID = "<projectId>"; 8 const clusterName = "<clusterName>"; 9 10 // Set the desired instance size and topology... 11 const body = { 12 replicationSpecs: [ 13 { 14 regionConfigs: [ 15 { 16 electableSpecs: { 17 instanceSize: "M30", // for example, larger tier 18 nodeCount: 3 19 }, 20 priority: 7, 21 providerName: "AWS", 22 regionName: "US_EAST_1" 23 } 24 ] 25 } 26 ] 27 }; 28 29 // Scale up the cluster and log the response 30 const result = await context.functions.execute( 31 "modifyCluster", 32 projectID, 33 clusterName, 34 body 35 ); 36 console.log(EJSON.stringify(result)); 37 38 return clusterName + " scaled up"; 39 }; 将
<projectId>和<clusterName>占位符替换为您自己的项目ID和集群名称,并根据您自己的拓扑结构调整regionConfigs大量。
创建scaleClusterUp 定时触发器。
在 Functions 页面中,单击 Build 标题下侧边栏中的 Triggers,导航到 Triggers 页面。
单击 Create a Trigger 打开触发器配置页面。
如果已有触发器,请单击 Add a Trigger
配置触发器设置。
在 Trigger Details 中,设立以下配置:
设置值触发器类型
預定
进度表类型
重新启用时跳过事件
打开。这可以防止触发器在禁用触发器时排队的计划上执行。
eventType
函数。从下拉列表中选择
pauseClusters函数。触发器名称
scaleClusterUp单击 Save 以创建触发器。
现在,您的测试集群将在每天早上 8 AM 美国东部时间自动扩展。
创建scaleClusterDown 函数。
将
scaleClusterUp函数复制到名为scaleClusterDown的新函数中。在 Function Editor标签页中,粘贴并调整以下代码,将集群扩展到指定配置:
1 /* 2 * Scales a single cluster down to a smaller instance size. 3 * This example scales an AWS cluster down to M10 in region US_EAST_1. 4 */ 5 exports = async function() { 6 const projectID = "<projectId>"; 7 const clusterName = "<clusterName>"; 8 9 const body = { 10 replicationSpecs: [ 11 { 12 regionConfigs: [ 13 { 14 electableSpecs: { 15 instanceSize: "M10", // for example, smaller tier 16 nodeCount: 3 17 }, 18 priority: 7, 19 providerName: "AWS", 20 regionName: "US_EAST_1" 21 } 22 ] 23 } 24 ] 25 }; 26 27 // Scale down the cluster and log the response 28 const result = await context.functions.execute( 29 "modifyCluster", 30 projectID, 31 clusterName, 32 body 33 ); 34 console.log(EJSON.stringify(result)); 35 36 return clusterName + " scaled down"; 37 }; 将
<projectId>和<clusterName>占位符替换为您自己的项目ID和集群名称,并根据您自己的拓扑结构调整regionConfigs大量。
可选辅助函数
可以从 Triggers 函数编辑器测试运行以下辅助函数,以列出组织中的项目和集群,从而指定要在本教程中的函数中定位的集群。您还可以从其他函数调用这些函数,以通过编程方式检索此信息。
getProjects() 调用“返回所有项目”端点以返回组织中的所有项目。
1 /* 2 * Returns an array of the projects in the organization 3 * See https://mongodb.com/zh-cn/docs/atlas/reference/api/project-get-all/ 4 * 5 * Returns an array of objects, e.g. 6 * 7 * { 8 * "clusterCount": { 9 * "$numberInt": "1" 10 * }, 11 * "created": "2021-05-11T18:24:48Z", 12 * "id": "609acbef1b76b53fcd37c8e1", 13 * "links": [ 14 * { 15 * "href": "https://cloud.mongodb.com/api/atlas/v1.0/groups/609acbef1b76b53fcd37c8e1", 16 * "rel": "self" 17 * } 18 * ], 19 * "name": "mg-training-sample", 20 * "orgId": "5b4e2d803b34b965050f1835" 21 * } 22 * 23 */ 24 exports = async function() { 25 26 // Retrieve headers to authenticate with a new access token, and define the request URL for the Atlas API endpoint 27 const authHeaders = await context.functions.execute("getAuthHeaders"); 28 const requestUrl = `https://cloud.mongodb.com/api/atlas/v2/groups`; 29 30 // Build the argument for the HTTP request to the Atlas API to get all projects in the organization 31 const arg = { 32 url: requestUrl, 33 headers: authHeaders.headers 34 }; 35 36 // The response body is a BSON.Binary object; parse it and return the `results` array, which contains the list of projects for the organization 37 response = await context.http.get(arg); 38 return EJSON.parse(response.body.text()).results; 39 };
getProjectClusters(<projectId>) 调用“返回一个项目中的所有集群”端点以返回具有指定项目ID 的项目中的所有集群。
1 /* 2 * Returns an array of the clusters for the supplied project ID. 3 * See https://mongodb.com/zh-cn/docs/atlas/reference/api/clusters-get-all/ 4 * 5 * Returns an array of objects. See the API documentation for details. 6 * 7 */ 8 exports = async function(projectId) { 9 10 if (projectId == "Hello world!") { // Easy testing from the console 11 projectId = "<projectId>" 12 } 13 14 // Retrieve headers to authenticate with a new access token, and define the request URL for the Atlas API endpoint 15 const authHeaders = await context.functions.execute("getAuthHeaders"); 16 const requestUrl = `https://cloud.mongodb.com/api/atlas/v2/groups/${projectId}/clusters`; 17 18 // Build the argument for the HTTP request to the Atlas API to get all clusters in the project 19 const arg = { 20 url: requestUrl, 21 headers: authHeaders.headers 22 }; 23 24 // The response body is a BSON.Binary object; parse it and return the `results` array, which contains the list of clusters for the project 25 response = await context.http.get(arg); 26 return EJSON.parse(response.body.text()).results; 27 };
将占位符 <projectId> 替换为您自己的项目ID。