기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
Amazon EC2 스팟 인스턴스 자습서
이 자습서에서는를 사용하여 Amazon EC2 스팟 인스턴스 AWS SDK for .NET 를 관리하는 방법을 보여줍니다.
개요
스팟 인스턴스를 사용하면 미사용 Amazon EC2 용량을 온디맨드 가격보다 저렴하게 요청할 수 있습니다. 이렇게 하면 중단될 수 있는 애플리케이션에 대한 EC2 비용이 크게 절감될 수 있습니다.
다음은 스팟 인스턴스 요청 및 사용 방법의 전반적인 요약입니다.
-
지불하고자 하는 최고 가격을 지정하는 스팟 인스턴스 요청을 생성합니다.
-
요청이 이행되면 다른 Amazon EC2 인스턴스와 마찬가지로 인스턴스를 실행합니다.
-
원하는 기간만큼 인스턴스를 실행한 다음 종료합니다. 단, 스팟 가격이 변경되어 인스턴스가 자동으로 종료되는 경우는 예외입니다.
-
더 이상 필요하지 않은 스팟 인스턴스 요청을 정리하여 스팟 인스턴스가 더 이상 생성되지 않도록 합니다.
여기까지 스팟 인스턴스의 대략적 개요였습니다. 스팟 인스턴스를 더 잘 이해하려면 Amazon EC2 사용 설명서의 스팟 인스턴스를 참조하세요.
이 자습서 소개
이 자습서를 따르면 AWS SDK for .NET 를 사용하여 다음을 수행합니다.
-
스팟 인스턴스 요청 생성
-
스팟 인스턴스 요청이 이행된 시점 확인
-
스팟 인스턴스 요청 취소
-
연결된 인스턴스 종료
다음 섹션에서는 이 예제의 코드 조각과 기타 정보를 제공합니다. 예제의 전체 코드는 코드 조각 뒤에 표시되며, 그대로 빌드하고 실행할 수 있습니다.
사전 조건
APIs 및 사전 조건에 대한 자세한 내용은 상위 섹션()을 참조하세요Amazon EC2 작업.
필요한 내용 수집
스팟 인스턴스 요청을 생성하려면 몇 가지 사항이 필요합니다.
-
인스턴스 수와 인스턴스 유형입니다. 선택할 수 있는 인스턴스 유형은 여러 가지가 있습니다. 자세한 내용은 Amazon EC2 사용 설명서의 Amazon Word 인스턴스 유형을 참조하세요. EC2 인스턴스 유형 세부 정보
및 인스턴스 유형 탐색 기를 참조하세요. 이 자습서에서 기본 수는 1입니다.
-
인스턴스를 생성하는 데 사용할 Amazon Machine Image(AMI)입니다. AMIs에 대한 자세한 내용은 Amazon Word 사용 설명서의 Amazon Machine Images(AMIs)를 참조하세요. EC2 특히 AMI 찾기 및 공유 AMIs를 참조하세요.
-
인스턴스 시간당 지불하려는 최고 가격입니다. Amazon EC2 요금 페이지에서
모든 인스턴스 유형(온디맨드 인스턴스 및 스팟 인스턴스 모두)의 요금을 확인할 수 있습니다. 이 자습서의 기본 가격은 나중에 설명합니다.
-
인스턴스에 원격으로 연결하려는 경우 적절한 구성 및 리소스를 갖춘 보안 그룹을 사용합니다. 이에 대한 설명은 Amazon EC2에서 보안 그룹 작업에 나와 있으며 필요한 정보를 수집하고 인스턴스에 연결하는 방법에 대한 자세한 내용은 Amazon EC2 인스턴스 시작에 나와 있습니다. 쉽게 설명하기 위해 이 자습서에서는 모든 새 AWS 계정에 있는 default라는 보안 그룹을 사용합니다.
스팟 인스턴스를 요청하기 위한 접근 방식에는 여러 가지가 있습니다. 다음은 일반적인 전략입니다.
-
온디맨드 요금보다 저렴한 요금으로 요청하세요.
-
결과 계산 값을 기준으로 요청하세요.
-
가능한 한 빨리 컴퓨팅 용량을 획득하도록 요청하세요.
다음 설명은 Amazon EC2 사용 설명서의 스팟 인스턴스 요금 기록을 참조합니다.
실행하는 데 몇 시간 또는 며칠이 걸리는 일괄 처리 작업이 있습니다. 그러나 시작 및 종료 시점은 유연하게 선택할 수 있습니다. 그 작업을 온디맨드 인스턴스보다 적은 비용으로 완료할 수 있는지 확인하고 싶다면
Amazon EC2 콘솔 또는 Amazon Word Word를 사용하여 인스턴스 유형에 대한 스팟 가격 기록을 검사합니다EC2API. 특정 가용 영역에서 원하는 인스턴스 유형의 가격 내역을 분석하였다면 요청에 사용할 수 있는 다른 방법이 두 가지 있습니다.
-
일회적인 스팟 인스턴스 요청이 이행되고 해당 작업을 완료하기에 충분한 연속적 컴퓨팅 시간 동안 실행될 가능성이 높을 것이라는 기대로 스팟 가격 범위의 상단(여전히 온디맨드 가격보다는 낮음)에서 요청을 지정합니다.
-
가격 범위의 하단에서 요청을 지정하고 영구 요청을 통해 시간이 지남에 따라 시작되는 여러 인스턴스를 결합하는 계획을 세울 수도 있습니다. 인스턴스는 합계 시간 동안 충분히 실행되어 훨씬 더 낮은 총 비용으로도 작업을 완료합니다.
실행할 데이터 처리 작업이 있는 경우 작업 당사자는 그 작업의 결과가 지니는 가치를 충분히 이해하여 컴퓨팅 비용 측면에서 그 결과의 가치가 얼마나 되는지 알 수 있습니다.
해당 인스턴스 유형의 스팟 가격 내역을 분석한 후 컴퓨팅 시간의 비용이 해당 작업의 결과가 지니는 가치보다 더 많지 않은 가격을 선택합니다. 영구 요청을 생성하여 스팟 가격이 요청 가격까지 또는 그 이하로 변동하는 과정에서 간헐적으로 실행되도록 합니다.
온디맨드 인스턴스를 통해서는 사용할 수 없는 추가 용량이 예기치 않게 단기간 동안 필요한 경우가 있습니다. 이때는 해당 인스턴스 유형의 스팟 가격 내역을 분석한 후 과거의 최고 가격보다 높은 가격을 선택함으로써 요청이 신속하게 이행되고 완료될 때까지 컴퓨팅이 지속될 수 있는 가능성을 크게 높입니다.
필요한 사항을 수집하고 전략을 선택했으면 스팟 인스턴스를 요청할 준비가 된 것입니다. 이 자습서에서는 기본 스팟 인스턴스 최고 가격이 온디맨드 가격(이 자습서의 경우 0.003 USD)과 동일하게 설정됩니다. 이 방법으로 가격을 설정하면 요청이 이행될 가능성이 극대화됩니다.
스팟 인스턴스 요청 생성
다음 코드 조각은 이전에 수집한 요소를 사용하여 스팟 인스턴스 요청을 생성하는 방법을 보여줍니다.
이 주제의 끝 부분에 있는 예제에서는 사용 중인 이 코드 조각을 보여줍니다.
// // Method to create a Spot Instance request private static async Task<SpotInstanceRequest> CreateSpotInstanceRequest( IAmazonEC2 ec2Client, string amiId, string securityGroupName, InstanceType instanceType, string spotPrice, int instanceCount) { var launchSpecification = new LaunchSpecification{ ImageId = amiId, InstanceType = instanceType }; launchSpecification.SecurityGroups.Add(securityGroupName); var request = new RequestSpotInstancesRequest{ SpotPrice = spotPrice, InstanceCount = instanceCount, LaunchSpecification = launchSpecification }; RequestSpotInstancesResponse result = await ec2Client.RequestSpotInstancesAsync(request); return result.SpotInstanceRequests[0]; }
이 메서드에서 반환되는 중요한 값은 반환된 SpotInstanceRequest 객체의 SpotInstanceRequestId
멤버에 포함된 스팟 인스턴스 요청 ID입니다.
스팟 인스턴스 요청 상태 확인
다음 코드 조각은 스팟 인스턴스 요청에 대한 정보를 가져오는 방법을 보여줍니다. 이 정보를 사용하여 스팟 인스턴스 요청이 이행될 때까지 계속 기다릴지 여부와 같은 코드의 특정 결정을 내릴 수 있습니다.
이 주제의 끝 부분에 있는 예제에서는 사용 중인 이 코드 조각을 보여줍니다.
// // Method to get information about a Spot Instance request, including the status, // instance ID, etc. // It gets the information for a specific request (as opposed to all requests). private static async Task<SpotInstanceRequest> GetSpotInstanceRequestInfo( IAmazonEC2 ec2Client, string requestId) { var describeRequest = new DescribeSpotInstanceRequestsRequest(); describeRequest.SpotInstanceRequestIds.Add(requestId); DescribeSpotInstanceRequestsResponse describeResponse = await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest); return describeResponse.SpotInstanceRequests[0]; }
이 메서드는 인스턴스 ID, 상태 및 상태 코드와 같은 스팟 인스턴스 요청에 대한 정보를 반환합니다. 스팟 인스턴스 요청의 상태 코드에 대한 자세한 내용은 Amazon EC2 사용 설명서의 스팟 요청 상태를 참조하세요.
스팟 인스턴스 요청 정리
스팟 인스턴스를 더 이상 요청할 필요가 없는 경우, 미해결 요청을 모두 취소하여 해당 요청이 다시 처리되지 않도록 하는 것이 중요합니다. 다음 코드 조각은 스팟 인스턴스 요청을 취소하는 방법을 보여줍니다.
이 주제의 끝 부분에 있는 예제에서는 사용 중인 이 코드 조각을 보여줍니다.
// // Method to cancel a Spot Instance request private static async Task CancelSpotInstanceRequest( IAmazonEC2 ec2Client, string requestId) { var cancelRequest = new CancelSpotInstanceRequestsRequest(); cancelRequest.SpotInstanceRequestIds.Add(requestId); await ec2Client.CancelSpotInstanceRequestsAsync(cancelRequest); }
스팟 인스턴스 정리
불필요한 비용을 피하려면 스팟 인스턴스 요청으로 시작된 인스턴스를 모두 종료하는 것이 중요합니다. 스팟 인스턴스를 취소하는 것만으로는 인스턴스가 종료되지 않는데, 이는 인스턴스에 대해 계속해서 비용이 부과됨을 뜻합니다. 다음 코드 조각은 활성 스팟 인스턴스의 인스턴스 식별자를 획득한 후 인스턴스를 종료하는 방법을 보여줍니다.
이 주제의 끝 부분에 있는 예제에서는 사용 중인 이 코드 조각을 보여줍니다.
// // Method to terminate a Spot Instance private static async Task TerminateSpotInstance( IAmazonEC2 ec2Client, string requestId) { var describeRequest = new DescribeSpotInstanceRequestsRequest(); describeRequest.SpotInstanceRequestIds.Add(requestId); // Retrieve the Spot Instance request to check for running instances. DescribeSpotInstanceRequestsResponse describeResponse = await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest); // If there are any running instances, terminate them if( (describeResponse.SpotInstanceRequests[0].Status.Code == "request-canceled-and-instance-running") || (describeResponse.SpotInstanceRequests[0].State == SpotInstanceState.Active)) { TerminateInstancesResponse response = await ec2Client.TerminateInstancesAsync(new TerminateInstancesRequest{ InstanceIds = new List<string>(){ describeResponse.SpotInstanceRequests[0].InstanceId } }); foreach (InstanceStateChange item in response.TerminatingInstances) { Console.WriteLine($"\n Terminated instance: {item.InstanceId}"); Console.WriteLine($" Instance state: {item.CurrentState.Name}\n"); } } }
전체 코드
다음 코드 예제는 앞에서 설명한 메서드를 호출하여 스팟 인스턴스 요청을 생성 및 취소하고 스팟 인스턴스를 종료합니다.
NuGet 패키지:
프로그래밍 요소:
-
네임스페이스 Amazon.EC2
클래스 AmazonEC2Client
클래스 InstanceType
using System; using System.Threading; using System.Threading.Tasks; using System.Collections.Generic; using Amazon.EC2; using Amazon.EC2.Model; namespace EC2SpotInstanceRequests { class Program { static async Task Main(string[] args) { // Some default values. // These could be made into command-line arguments instead. var instanceType = InstanceType.T1Micro; string securityGroupName = "default"; string spotPrice = "0.003"; int instanceCount = 1; // Parse the command line arguments if((args.Length != 1) || (!args[0].StartsWith("ami-"))) { Console.WriteLine("\nUsage: EC2SpotInstanceRequests ami"); Console.WriteLine(" ami: the Amazon Machine Image to use for the Spot Instances."); return; } // Create the Amazon EC2 client. var ec2Client = new AmazonEC2Client(); // Create the Spot Instance request and record its ID Console.WriteLine("\nCreating spot instance request..."); var req = await CreateSpotInstanceRequest( ec2Client, args[0], securityGroupName, instanceType, spotPrice, instanceCount); string requestId = req.SpotInstanceRequestId; // Wait for an EC2 Spot Instance to become active Console.WriteLine( $"Waiting for Spot Instance request with ID {requestId} to become active..."); int wait = 1; var start = DateTime.Now; while(true) { Console.Write("."); // Get and check the status to see if the request has been fulfilled. var requestInfo = await GetSpotInstanceRequestInfo(ec2Client, requestId); if(requestInfo.Status.Code == "fulfilled") { Console.WriteLine($"\nSpot Instance request {requestId} " + $"has been fulfilled by instance {requestInfo.InstanceId}.\n"); break; } // Wait a bit and try again, longer each time (1, 2, 4, ...) Thread.Sleep(wait); wait = wait * 2; } // Show the user how long it took to fulfill the Spot Instance request. TimeSpan span = DateTime.Now.Subtract(start); Console.WriteLine($"That took {span.TotalMilliseconds} milliseconds"); // Perform actions here as needed. // For this example, simply wait for the user to hit a key. // That gives them a chance to look at the EC2 console to see // the running instance if they want to. Console.WriteLine("Press any key to start the cleanup..."); Console.ReadKey(true); // Cancel the request. // Do this first to make sure that the request can't be re-fulfilled // once the Spot Instance has been terminated. Console.WriteLine("Canceling Spot Instance request..."); await CancelSpotInstanceRequest(ec2Client, requestId); // Terminate the Spot Instance that's running. Console.WriteLine("Terminating the running Spot Instance..."); await TerminateSpotInstance(ec2Client, requestId); Console.WriteLine("Done. Press any key to exit..."); Console.ReadKey(true); } // // Method to create a Spot Instance request private static async Task<SpotInstanceRequest> CreateSpotInstanceRequest( IAmazonEC2 ec2Client, string amiId, string securityGroupName, InstanceType instanceType, string spotPrice, int instanceCount) { var launchSpecification = new LaunchSpecification{ ImageId = amiId, InstanceType = instanceType }; launchSpecification.SecurityGroups.Add(securityGroupName); var request = new RequestSpotInstancesRequest{ SpotPrice = spotPrice, InstanceCount = instanceCount, LaunchSpecification = launchSpecification }; RequestSpotInstancesResponse result = await ec2Client.RequestSpotInstancesAsync(request); return result.SpotInstanceRequests[0]; } // // Method to get information about a Spot Instance request, including the status, // instance ID, etc. // It gets the information for a specific request (as opposed to all requests). private static async Task<SpotInstanceRequest> GetSpotInstanceRequestInfo( IAmazonEC2 ec2Client, string requestId) { var describeRequest = new DescribeSpotInstanceRequestsRequest(); describeRequest.SpotInstanceRequestIds.Add(requestId); DescribeSpotInstanceRequestsResponse describeResponse = await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest); return describeResponse.SpotInstanceRequests[0]; } // // Method to cancel a Spot Instance request private static async Task CancelSpotInstanceRequest( IAmazonEC2 ec2Client, string requestId) { var cancelRequest = new CancelSpotInstanceRequestsRequest(); cancelRequest.SpotInstanceRequestIds.Add(requestId); await ec2Client.CancelSpotInstanceRequestsAsync(cancelRequest); } // // Method to terminate a Spot Instance private static async Task TerminateSpotInstance( IAmazonEC2 ec2Client, string requestId) { var describeRequest = new DescribeSpotInstanceRequestsRequest(); describeRequest.SpotInstanceRequestIds.Add(requestId); // Retrieve the Spot Instance request to check for running instances. DescribeSpotInstanceRequestsResponse describeResponse = await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest); // If there are any running instances, terminate them if( (describeResponse.SpotInstanceRequests[0].Status.Code == "request-canceled-and-instance-running") || (describeResponse.SpotInstanceRequests[0].State == SpotInstanceState.Active)) { TerminateInstancesResponse response = await ec2Client.TerminateInstancesAsync(new TerminateInstancesRequest{ InstanceIds = new List<string>(){ describeResponse.SpotInstanceRequests[0].InstanceId } }); foreach (InstanceStateChange item in response.TerminatingInstances) { Console.WriteLine($"\n Terminated instance: {item.InstanceId}"); Console.WriteLine($" Instance state: {item.CurrentState.Name}\n"); } } } } }
추가 고려 사항
-
자습서를 실행한 후에는 Amazon EC2 콘솔
에 로그인하여 스팟 인스턴스 요청이 취소되었고 스팟 인스턴스 가 종료되었는지 확인하는 것이 좋습니다.