教程:使用 Amazon SDK for .NET 管理 Amazon EC2 Spot 实例
您可以使用 Amazon SDK for .NET,通过 C# 代码管理 Amazon EC2 Spot 实例。利用开发工具包,您可以使用 Amazon EC2 API 创建 Spot 实例请求、确定满足请求的时间、删除请求以及标识创建的实例。
本教程提供执行这些任务的代码以及可本地或在 Amazon 上运行的示例应用程序。它包含一个示例项目,可将该项目部署到 Amazon Lambda 的 .NET Core 2.1 运行时。
有关 Spot 实例使用情况和最佳实践的更多信息,请参阅 Amazon EC2 用户指南中的 Spot 实例。
Prerequisites
要完成以下步骤,您需要命令行终端或 Shell,以便运行命令。在单独的数据块中列出了命令和预期输出:
aws --version
您应看到以下输出:
aws-cli/2.0.57 Python/3.7.4 Darwin/19.6.0 exe/x86_64
对于长命令,使用转义字符 (\
) 将命令拆分为多行。
在 Linux 和 macOS 中,可使用您首选的外壳程序和程序包管理器。在 Windows 10 中,您可以 安装 Windows Subsystem for Linux
本教程使用开发人员指南的 GitHub 存储库中的代码。该存储库还包含执行其过程所需的帮助程序脚本和配置文件。克隆 github.com/awsdocs/aws-lambda-developer-guide
要使用示例代码,您需要以下工具:
-
Amazon CLI – 要将示例应用程序部署到 Amazon,请安装 Amazon CLI。在本地运行示例代码时,Amazon CLI 还会向该代码提供凭证。
-
.NET Core CLI – 要对代码进行本地运行和测试,请安装 .NET Core SDK 2.1
。 -
Lambda .NET Core Global Tool – 要为 Lambda 构建部署程序包,请安装带有 .NET Core CLI 的 .NET Core Global Tool
。 dotnet tool install -g Amazon.Lambda.Tools
本教程中的代码可管理启动 Amazon EC2 实例的 Spot 请求。要本地运行代码,您需要具有开发工具包凭证并有权使用以下 API。
-
ec2:RequestSpotInstance
-
ec2:GetSpotRequestState
-
ec2:CancelSpotRequest
-
ec2:TerminateInstances
要在 Amazon 中运行示例应用程序,您需要 Lambda 使用权限与以下服务:
标准费用适用于每项服务。
查看代码
在 sample-apps/ec2-spot
Function
类包含一个 FunctionHandler
方法,该方法调用其他方法来创建 Spot 请求、检查其状态并进行清理。它在静态构造函数中使用 Amazon SDK for .NET 创建 Amazon EC2 客户端,以便能够在整个类中使用它。
例 Function.cs – FunctionHandler
using Amazon.EC2; ... public class Function {
private static AmazonEC2Client ec2Client;
static Function() { AWSSDKHandler.RegisterXRayForAllServices(); ec2Client = new AmazonEC2Client(); } public async Task<string> FunctionHandler(Dictionary<string, string> input, ILambdaContext context) { // More AMI IDs: amazon-linux-2/release-notes/ // us-east-2 HVM EBS-Backed 64-bit Amazon Linux 2 string ami = "ami-09d9edae5eb90d556"; string sg = "default"; InstanceType type = InstanceType.T3aNano; string price = "0.003"; int count = 1; var requestSpotInstances = await RequestSpotInstance(ami, sg, type, price, count); var spotRequestId = requestSpotInstances.SpotInstanceRequests[0].SpotInstanceRequestId;
RequestSpotInstance
方法可创建 Spot 实例请求。
例 Function.cs – RequestSpotInstance
using Amazon; using Amazon.Util; using Amazon.EC2; using Amazon.EC2.Model; ... public async Task<RequestSpotInstancesResponse> RequestSpotInstance( string amiId, string securityGroupName, InstanceType instanceType, string spotPrice, int instanceCount) { var request = new RequestSpotInstancesRequest(); var launchSpecification = new LaunchSpecification(); launchSpecification.ImageId = amiId; launchSpecification.InstanceType = instanceType; launchSpecification.SecurityGroups.Add(securityGroupName); request.SpotPrice = spotPrice; request.InstanceCount = instanceCount; request.LaunchSpecification = launchSpecification; RequestSpotInstancesResponse response = await ec2Client.RequestSpotInstancesAsync(request); return response; } ...
接下来,您需要等待直至 Spot 请求进入 Active
状态,然后继续到最后一步。要确定 Spot 请求的状态,请使用 DescribeSpotInstanceRequests 方法来获取要监视的 Spot 请求 ID 的状态。
public async Task<SpotInstanceRequest> GetSpotRequest(string spotRequestId) { var request = new DescribeSpotInstanceRequestsRequest(); request.SpotInstanceRequestIds.Add(spotRequestId); var describeResponse = await ec2Client.DescribeSpotInstanceRequestsAsync(request); return describeResponse.SpotInstanceRequests[0]; }
最后一步是清除您的请求和实例。重要的是,要取消所有未完成的请求并终止所有实例。只取消请求不会终止您的实例,这意味着您需要继续为它们支付费用。如果您终止了实例,那么 Spot 请求可能会被取消,但在某些情况下,例如,如果您使用的是持久请求,那么只终止实例是不足以停止请求的,以至于这些请求会重新执行。因此,最好的做法是取消所有活跃的请求并终止所有正在运行的实例。
您使用 CancelSpotInstanceRequests 方法来取消 Spot 请求。以下示例演示了如何取消 Spot 请求。
public async Task CancelSpotRequest(string spotRequestId) { Console.WriteLine("Canceling request " + spotRequestId); var cancelRequest = new CancelSpotInstanceRequestsRequest(); cancelRequest.SpotInstanceRequestIds.Add(spotRequestId); await ec2Client.CancelSpotInstanceRequestsAsync(cancelRequest); }
您可使用 TerminateInstances 方法终止实例。
public async Task TerminateSpotInstance(string instanceId) { Console.WriteLine("Terminating instance " + instanceId); var terminateRequest = new TerminateInstancesRequest(); terminateRequest.InstanceIds = new List<string>() { instanceId }; try { var terminateResponse = await ec2Client.TerminateInstancesAsync(terminateRequest); } catch (AmazonEC2Exception ex) { // Check the ErrorCode to see if the instance does not exist. if ("InvalidInstanceID.NotFound" == ex.ErrorCode) { Console.WriteLine("Instance {0} does not exist.", instanceId); } else { // The exception was thrown for another reason, so re-throw the exception. throw; } } }
本地运行代码
在本地计算机上运行代码以创建 Spot 实例请求。满足请求后,代码将删除请求并终止实例。
运行应用程序代码
-
导航到
ec2Spot.Tests
目录。cd test/ec2Spot.Tests
-
使用 .NET CLI 运行项目的单元测试。
dotnet test
您应看到以下输出:
Starting test execution, please wait... sir-x5tgs5ij open open open open open active Canceling request sir-x5tgs5ij Terminating instance i-0b3fdff0e12e0897e Complete Test Run Successful. Total tests: 1 Passed: 1 Total time: 7.6060 Seconds
单元测试调用 FunctionHandler 方法来创建 Spot 实例请求、监控它并进行清理。它是在 xUnit.net
部署应用程序
在 Lambda 中运行代码作为创建无服务器应用程序的起点。
部署和测试应用程序
-
将您的区域设置为
us-east-2
。export AWS_DEFAULT_REGION=us-east-2
-
为部署构件创建存储桶。
./create-bucket.sh
您应看到以下输出:
make_bucket: lambda-artifacts-63d5cbbf18fa5ecc
-
创建部署程序包并部署应用程序。
./deploy.sh
您应看到以下输出:
Amazon Lambda Tools for .NET Core applications (3.3.0) Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet Executing publish command ... Created publish archive (ec2spot.zip) Lambda project successfully packaged: ec2spot.zip Uploading to ebd38e401cedd7d676d05d22b76f0209 1305107 / 1305107.0 (100.00%) Successfully packaged artifacts and wrote output template to file out.yaml. Run the following command to deploy the packaged template aws cloudformation deploy --template-file out.yaml --stack-name <YOUR STACK NAME> Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - ec2-spot
-
打开 Lambda 控制台的 Applications(应用程序)页面
。 -
在 Resources (资源) 下,选择 function (函数)。
-
选择 Test (测试) 并从默认模板创建测试事件。
-
再次选择 Test (测试) 以调用该函数。
查看日志和追踪信息以了解 Spot 请求 ID 以及对 Amazon EC2 的调用的顺序。
要查看服务映射,请打开 X-Ray 控制台中的 Service map(服务映射)页面
在服务映射中选择一个节点,然后选择 View traces (查看跟踪) 以查看跟踪列表。从列表中选择跟踪以查看函数对 Amazon EC2 进行的调用的时间线。
清除
本教程中提供的代码旨在创建和删除 Spot 实例请求,并终止它们启动的实例。但是,如果出现错误,可能不会自动清理请求和实例。在 Amazon EC2 控制台中查看 Spot 请求和实例。
确认已清理 Amazon EC2 资源
-
在 Amazon EC2 控制台中打开 Spot Requests(Spot 请求)页面
。 -
验证请求的状态是否为 Cancelled (已取消)。
-
在 Capacity (容量) 列中选择实例 ID 以查看实例。
-
验证实例的状态是 Terminated (已终止) 还是 Shutting down (正在关闭)。
要清理示例函数和支持资源,请删除其 Amazon CloudFormation 堆栈以及您创建的构件存储桶。
./cleanup.sh
您应看到以下输出:
Delete deployment artifacts and bucket (lambda-artifacts-63d5cbbf18fa5ecc)?y delete: s3://lambda-artifacts-63d5cbbf18fa5ecc/ebd38e401cedd7d676d05d22b76f0209 remove_bucket: lambda-artifacts-63d5cbbf18fa5ecc
不会自动删除函数的日志组。您可以在 CloudWatch Logs 控制台