의 버전 4(V4) SDK for .NET 는 미리 보기 중입니다! 미리 보기에서이 새 버전에 대한 정보를 보려면 AWS SDK for .NET (버전 4 미리 보기) 개발자 안내서를 참조하세요.
SDK의 V4는 미리 보기 상태이므로 콘텐츠는 변경될 수 있습니다.
기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
Amazon EC2 인스턴스 시작
이 예제에서는 SDK for .NET 를 사용하여 동일한 Amazon Machine Image(AMI)에서 하나 이상의 동일하게 구성된 Amazon EC2 인스턴스를 시작하는 방법을 보여줍니다. 애플리케이션은 사용자가 제공한 여러 입력을 사용하여 EC2 인스턴스를 시작한 다음 “Pending” 상태가 아닐 때까지 인스턴스를 모니터링합니다.
(선택 사항) 인스턴스에 연결에 설명된 대로 EC2 인스턴스가 실행될 때 EC2 인스턴스에 원격으로 연결할 수 있습니다.
주의
EC2-Classic은 2022년 8월 15일에 사용 중지되었습니다. EC2-Classic에서 VPC로 마이그레이션하는 것이 좋습니다. 자세한 내용은 블로그 게시물 EC2-Classic Networking is Retiring – Here's How to Prepare
다음 섹션에서는 이 예제의 코드 조각과 기타 정보를 제공합니다. 예제의 전체 코드는 코드 조각 뒤에 표시되며, 그대로 빌드하고 실행할 수 있습니다.
필요한 내용 수집
EC2 인스턴스를 시작하려면 몇 가지 사항이 필요합니다.
-
인스턴스가 시작될 VPC의 기존 서브넷 ID입니다. Amazon VPC 콘솔
에 로그인하는 것도 이를 찾거나 생성하는 쉬운 방법이지만, CreateSubnetAsync 및 DescribeSubnetsAsync 메서드를 사용하여 프로그래밍 방식으로 가져올 수도 있습니다. 참고
이 파라미터를 제공하지 않으면 계정의 기본 VPC에서 새 인스턴스가 시작됩니다.
-
인스턴스가 시작될 VPC에 속하는 기존 보안 그룹의 ID입니다. 자세한 내용은 Amazon EC2 에서 보안 그룹 작업 단원을 참조하십시오.
-
새 인스턴스에 연결하려면 앞서 언급한 보안 그룹에 포트 22에서의 SSH 트래픽(Linux 인스턴스) 또는 포트 3389에서의 RDP 트래픽(Windows 인스턴스)을 허용하는 적절한 인바운드 규칙이 있어야 합니다. 이를 수행하는 방법은 해당 주제의 끝 부분에 있는 추가 고려 사항을 포함하여 보안 그룹 업데이트을 참조하세요.
-
인스턴스를 생성하는 데 사용되는 Amazon Machine Image(AMI)입니다. AMI에 대한 자세한 내용은 Amazon EC2 사용 설명서의 Amazon 머신 이미지(AMIs)를 참조하세요. Amazon EC2 특히 AMI 및 공유 AMI 찾기를 AMIs.
-
새 인스턴스에 연결하는 데 사용되는 기존 EC2 키 페어의 이름입니다. 자세한 내용은 Amazon EC2 키 페어로 작업 단원을 참조하십시오.
-
앞서 언급한 EC2 키 페어의 프라이빗 키가 포함된 PEM 파일의 이름입니다. PEM 파일은 인스턴스에 원격으로 연결할 때 사용됩니다.
인스턴스 시작
다음 코드 조각은 EC2 인스턴스를 시작합니다.
이 주제의 끝 부분에 있는 예제에서는 사용 중인 이 코드 조각을 보여줍니다.
//
// Method to launch the instances
// Returns a list with the launched instance IDs
private static async Task<List<string>> LaunchInstances(
IAmazonEC2 ec2Client, RunInstancesRequest requestLaunch)
{
var instanceIds = new List<string>();
RunInstancesResponse responseLaunch =
await ec2Client.RunInstancesAsync(requestLaunch);
Console.WriteLine("\nNew instances have been created.");
foreach (Instance item in responseLaunch.Reservation.Instances)
{
instanceIds.Add(item.InstanceId);
Console.WriteLine($" New instance: {item.InstanceId}");
}
return instanceIds;
}
인스턴스 모니터링
다음 코드 조각은 “Pending” 상태가 아닐 때까지 인스턴스를 모니터링합니다.
이 주제의 끝 부분에 있는 예제에서는 사용 중인 이 코드 조각을 보여줍니다.
Instance.State.Code
속성의 유효한 값은 InstanceState 클래스를 참조하세요.
//
// Method to wait until the instances are running (or at least not pending)
private static async Task CheckState(IAmazonEC2 ec2Client, List<string> instanceIds)
{
Console.WriteLine(
"\nWaiting for the instances to start." +
"\nPress any key to stop waiting. (Response might be slightly delayed.)");
int numberRunning;
DescribeInstancesResponse responseDescribe;
var requestDescribe = new DescribeInstancesRequest{
InstanceIds = instanceIds};
// Check every couple of seconds
int wait = 2000;
while(true)
{
// Get and check the status for each of the instances to see if it's past pending.
// Once all instances are past pending, break out.
// (For this example, we are assuming that there is only one reservation.)
Console.Write(".");
numberRunning = 0;
responseDescribe = await ec2Client.DescribeInstancesAsync(requestDescribe);
foreach(Instance i in responseDescribe.Reservations[0].Instances)
{
// Check the lower byte of State.Code property
// Code == 0 is the pending state
if((i.State.Code & 255) > 0) numberRunning++;
}
if(numberRunning == responseDescribe.Reservations[0].Instances.Count)
break;
// Wait a bit and try again (unless the user wants to stop waiting)
Thread.Sleep(wait);
if(Console.KeyAvailable)
break;
}
Console.WriteLine("\nNo more instances are pending.");
foreach(Instance i in responseDescribe.Reservations[0].Instances)
{
Console.WriteLine($"For {i.InstanceId}:");
Console.WriteLine($" VPC ID: {i.VpcId}");
Console.WriteLine($" Instance state: {i.State.Name}");
Console.WriteLine($" Public IP address: {i.PublicIpAddress}");
Console.WriteLine($" Public DNS name: {i.PublicDnsName}");
Console.WriteLine($" Key pair name: {i.KeyName}");
}
}
전체 코드
이 섹션에는 이 예제에 대한 관련 참조와 전체 코드가 나와 있습니다.
NuGet 패키지:
프로그래밍 요소:
-
네임스페이스 Amazon.EC2
클래스 AmazonEC2Client
클래스 InstanceType
-
네임스페이스 Amazon.EC2.Model
클래스 Instance
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;
namespace EC2LaunchInstance
{
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Class to launch an EC2 instance
class Program
{
static async Task Main(string[] args)
{
// Parse the command line and show help if necessary
var parsedArgs = CommandLine.Parse(args);
if(parsedArgs.Count == 0)
{
PrintHelp();
return;
}
// Get the application arguments from the parsed list
string groupID =
CommandLine.GetArgument(parsedArgs, null, "-g", "--group-id");
string ami =
CommandLine.GetArgument(parsedArgs, null, "-a", "--ami-id");
string keyPairName =
CommandLine.GetArgument(parsedArgs, null, "-k", "--keypair-name");
string subnetID =
CommandLine.GetArgument(parsedArgs, null, "-s", "--subnet-id");
if( (string.IsNullOrEmpty(groupID) || !groupID.StartsWith("sg-"))
|| (string.IsNullOrEmpty(ami) || !ami.StartsWith("ami-"))
|| (string.IsNullOrEmpty(keyPairName))
|| (!string.IsNullOrEmpty(subnetID) && !subnetID.StartsWith("subnet-")))
CommandLine.ErrorExit(
"\nOne or more of the required arguments is missing or incorrect." +
"\nRun the command with no arguments to see help.");
// Create an EC2 client
var ec2Client = new AmazonEC2Client();
// Create an object with the necessary properties
RunInstancesRequest request = GetRequestData(groupID, ami, keyPairName, subnetID);
// Launch the instances and wait for them to start running
var instanceIds = await LaunchInstances(ec2Client, request);
await CheckState(ec2Client, instanceIds);
}
//
// Method to put together the properties needed to launch the instance.
private static RunInstancesRequest GetRequestData(
string groupID, string ami, string keyPairName, string subnetID)
{
// Common properties
var groupIDs = new List<string>() { groupID };
var request = new RunInstancesRequest()
{
// The first three of these would be additional command-line arguments or similar.
InstanceType = InstanceType.T1Micro,
MinCount = 1,
MaxCount = 1,
ImageId = ami,
KeyName = keyPairName
};
// Properties specifically for EC2 in a VPC.
if(!string.IsNullOrEmpty(subnetID))
{
request.NetworkInterfaces =
new List<InstanceNetworkInterfaceSpecification>() {
new InstanceNetworkInterfaceSpecification() {
DeviceIndex = 0,
SubnetId = subnetID,
Groups = groupIDs,
AssociatePublicIpAddress = true
}
};
}
// Properties specifically for EC2-Classic
else
{
request.SecurityGroupIds = groupIDs;
}
return request;
}
//
// Method to launch the instances
// Returns a list with the launched instance IDs
private static async Task<List<string>> LaunchInstances(
IAmazonEC2 ec2Client, RunInstancesRequest requestLaunch)
{
var instanceIds = new List<string>();
RunInstancesResponse responseLaunch =
await ec2Client.RunInstancesAsync(requestLaunch);
Console.WriteLine("\nNew instances have been created.");
foreach (Instance item in responseLaunch.Reservation.Instances)
{
instanceIds.Add(item.InstanceId);
Console.WriteLine($" New instance: {item.InstanceId}");
}
return instanceIds;
}
//
// Method to wait until the instances are running (or at least not pending)
private static async Task CheckState(IAmazonEC2 ec2Client, List<string> instanceIds)
{
Console.WriteLine(
"\nWaiting for the instances to start." +
"\nPress any key to stop waiting. (Response might be slightly delayed.)");
int numberRunning;
DescribeInstancesResponse responseDescribe;
var requestDescribe = new DescribeInstancesRequest{
InstanceIds = instanceIds};
// Check every couple of seconds
int wait = 2000;
while(true)
{
// Get and check the status for each of the instances to see if it's past pending.
// Once all instances are past pending, break out.
// (For this example, we are assuming that there is only one reservation.)
Console.Write(".");
numberRunning = 0;
responseDescribe = await ec2Client.DescribeInstancesAsync(requestDescribe);
foreach(Instance i in responseDescribe.Reservations[0].Instances)
{
// Check the lower byte of State.Code property
// Code == 0 is the pending state
if((i.State.Code & 255) > 0) numberRunning++;
}
if(numberRunning == responseDescribe.Reservations[0].Instances.Count)
break;
// Wait a bit and try again (unless the user wants to stop waiting)
Thread.Sleep(wait);
if(Console.KeyAvailable)
break;
}
Console.WriteLine("\nNo more instances are pending.");
foreach(Instance i in responseDescribe.Reservations[0].Instances)
{
Console.WriteLine($"For {i.InstanceId}:");
Console.WriteLine($" VPC ID: {i.VpcId}");
Console.WriteLine($" Instance state: {i.State.Name}");
Console.WriteLine($" Public IP address: {i.PublicIpAddress}");
Console.WriteLine($" Public DNS name: {i.PublicDnsName}");
Console.WriteLine($" Key pair name: {i.KeyName}");
}
}
//
// Command-line help
private static void PrintHelp()
{
Console.WriteLine(
"\nUsage: EC2LaunchInstance -g <group-id> -a <ami-id> -k <keypair-name> [-s <subnet-id>]" +
"\n -g, --group-id: The ID of the security group." +
"\n -a, --ami-id: The ID of an Amazon Machine Image." +
"\n -k, --keypair-name - The name of a key pair." +
"\n -s, --subnet-id: The ID of a subnet. Required only for EC2 in a VPC.");
}
}
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Class that represents a command line on the console or terminal.
// (This is the same for all examples. When you have seen it once, you can ignore it.)
static class CommandLine
{
//
// Method to parse a command line of the form: "--key value" or "-k value".
//
// Parameters:
// - args: The command-line arguments passed into the application by the system.
//
// Returns:
// A Dictionary with string Keys and Values.
//
// If a key is found without a matching value, Dictionary.Value is set to the key
// (including the dashes).
// If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
// where "N" represents sequential numbers.
public static Dictionary<string,string> Parse(string[] args)
{
var parsedArgs = new Dictionary<string,string>();
int i = 0, n = 0;
while(i < args.Length)
{
// If the first argument in this iteration starts with a dash it's an option.
if(args[i].StartsWith("-"))
{
var key = args[i++];
var value = key;
// Check to see if there's a value that goes with this option?
if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
parsedArgs.Add(key, value);
}
// If the first argument in this iteration doesn't start with a dash, it's a value
else
{
parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
n++;
}
}
return parsedArgs;
}
//
// Method to get an argument from the parsed command-line arguments
//
// Parameters:
// - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
// - defaultValue: The default string to return if the specified key isn't in parsedArgs.
// - keys: An array of keys to look for in parsedArgs.
public static string GetArgument(
Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
{
string retval = null;
foreach(var key in keys)
if(parsedArgs.TryGetValue(key, out retval)) break;
return retval ?? defaultReturn;
}
//
// Method to exit the application with an error.
public static void ErrorExit(string msg, int code=1)
{
Console.WriteLine("\nError");
Console.WriteLine(msg);
Environment.Exit(code);
}
}
}
추가 고려 사항
-
EC2 인스턴스의 상태를 확인할 때 DescribeInstancesRequest 객체의
Filter
속성에 필터를 추가할 수 있습니다. 이 기술을 사용하면 요청을 특정 인스턴스(예: 특정 사용자 지정 태그가 있는 인스턴스)로 제한할 수 있습니다.
-
간략하게 나타내기 위해 일부 속성에는 일반적인 값이 지정되었습니다. 대신 프로그래밍 방식으로 또는 사용자 입력을 통해 이러한 속성 중 일부 또는 전체를 결정할 수 있습니다.
-
RunInstancesRequest 객체의
MinCount
및MaxCount
속성에 사용할 수 있는 값은 대상 가용 영역과 해당 인스턴스 유형에 허용되는 최대 인스턴스 수에 따라 결정됩니다. 자세한 내용은 Amazon EC2 일반 FAQ의 Amazon EC2에서 실행할 수 있는 인스턴스 수는 몇 개입니까를 참조하세요.
-
이 예제와 다른 인스턴스 유형을 사용하려면 선택할 수 있는 여러 인스턴스 유형이 있습니다. 자세한 내용은 Amazon EC2 사용 설명서의 Amazon EC2 인스턴스 유형을 참조하세요. Amazon EC2 인스턴스 유형 세부 정보
및 인스턴스 유형 탐색기도 참조하세요 .
-
인스턴스를 시작할 때 IAM 역할을 인스턴스에 연결할 수도 있습니다. 이렇게 하려면
Name
속성이 IAM 역할의 이름으로 설정된 IamInstanceProfileSpecification 객체를 생성해야 합니다. 그런 다음 해당 객체를 RunInstancesRequest 객체의IamInstanceProfile
속성에 추가합니다.참고
IAM 역할이 연결된 EC2 인스턴스를 시작하려면 IAM 사용자의 구성에 특정 권한이 포함되어야 합니다. 필요한 권한에 대한 자세한 내용은 Amazon EC2 사용 설명서의 IAM 역할을 인스턴스에 전달할 수 있는 사용자 권한 부여를 참조하세요.
(선택 사항) 인스턴스에 연결
인스턴스가 실행된 후에는 적절한 원격 클라이언트를 사용하여 인스턴스에 원격으로 연결할 수 있습니다. Linux 및 Windows 인스턴스 모두에 대해 인스턴스의 퍼블릭 IP 주소 또는 퍼블릭 DNS 이름이 필요합니다. 또한 다음 항목이 필요합니다.
Linux 인스턴스의 경우
SSH 클라이언트를 사용하여 Linux 인스턴스에 연결할 수 있습니다. 보안 그룹 업데이트에 설명된 대로 인스턴스를 시작할 때 사용한 보안 그룹이 포트 22에서의 SSH 트래픽을 허용하는지 확인합니다.
또한 인스턴스를 시작하는 데 사용한 키 페어의 비공개 부분, 즉 PEM 파일도 필요합니다.
자세한 내용은 Amazon EC2 사용 설명서의 Linux 인스턴스에 연결을 참조하세요.
Windows 인스턴스의 경우
RDP 클라이언트를 사용하여 인스턴스에 연결할 수 있습니다. 보안 그룹 업데이트에 설명된 대로 인스턴스를 시작할 때 사용한 보안 그룹이 포트 3389에서의 RDP 트래픽을 허용하는지 확인합니다.
또한 관리자 암호가 필요합니다. 다음 예제 코드를 사용하여 이를 얻을 수 있습니다. 이 코드에는 인스턴스 ID와 인스턴스 시작에 사용된 키 페어의 비공개 부분, 즉 PEM 파일이 필요합니다.
자세한 내용은 Amazon EC2 사용 설명서의 Windows 인스턴스에 연결을 참조하세요.
주의
이 예제 코드는 인스턴스의 일반 텍스트 관리자 암호를 반환합니다.
NuGet 패키지:
프로그래밍 요소:
-
네임스페이스 Amazon.EC2
클래스 AmazonEC2Client
-
네임스페이스 Amazon.EC2.Model
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.EC2;
using Amazon.EC2.Model;
namespace EC2GetWindowsPassword
{
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Class to get the Administrator password of a Windows EC2 instance
class Program
{
static async Task Main(string[] args)
{
// Parse the command line and show help if necessary
var parsedArgs = CommandLine.Parse(args);
if(parsedArgs.Count == 0)
{
PrintHelp();
return;
}
// Get the application arguments from the parsed list
string instanceID =
CommandLine.GetArgument(parsedArgs, null, "-i", "--instance-id");
string pemFileName =
CommandLine.GetArgument(parsedArgs, null, "-p", "--pem-filename");
if( (string.IsNullOrEmpty(instanceID) || !instanceID.StartsWith("i-"))
|| (string.IsNullOrEmpty(pemFileName) || !pemFileName.EndsWith(".pem")))
CommandLine.ErrorExit(
"\nOne or more of the required arguments is missing or incorrect." +
"\nRun the command with no arguments to see help.");
// Create the EC2 client
var ec2Client = new AmazonEC2Client();
// Get and display the password
string password = await GetPassword(ec2Client, instanceID, pemFileName);
Console.WriteLine($"\nPassword: {password}");
}
//
// Method to get the administrator password of a Windows EC2 instance
private static async Task<string> GetPassword(
IAmazonEC2 ec2Client, string instanceID, string pemFilename)
{
string password = string.Empty;
GetPasswordDataResponse response =
await ec2Client.GetPasswordDataAsync(new GetPasswordDataRequest{
InstanceId = instanceID});
if(response.PasswordData != null)
{
password = response.GetDecryptedPassword(File.ReadAllText(pemFilename));
}
else
{
Console.WriteLine($"\nThe password is not available for instance {instanceID}.");
Console.WriteLine($"If this is a Windows instance, the password might not be ready.");
}
return password;
}
//
// Command-line help
private static void PrintHelp()
{
Console.WriteLine(
"\nUsage: EC2GetWindowsPassword -i <instance-id> -p pem-filename" +
"\n -i, --instance-id: The name of the EC2 instance." +
"\n -p, --pem-filename: The name of the PEM file with the private key.");
}
}
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Class that represents a command line on the console or terminal.
// (This is the same for all examples. When you have seen it once, you can ignore it.)
static class CommandLine
{
//
// Method to parse a command line of the form: "--key value" or "-k value".
//
// Parameters:
// - args: The command-line arguments passed into the application by the system.
//
// Returns:
// A Dictionary with string Keys and Values.
//
// If a key is found without a matching value, Dictionary.Value is set to the key
// (including the dashes).
// If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
// where "N" represents sequential numbers.
public static Dictionary<string,string> Parse(string[] args)
{
var parsedArgs = new Dictionary<string,string>();
int i = 0, n = 0;
while(i < args.Length)
{
// If the first argument in this iteration starts with a dash it's an option.
if(args[i].StartsWith("-"))
{
var key = args[i++];
var value = key;
// Check to see if there's a value that goes with this option?
if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
parsedArgs.Add(key, value);
}
// If the first argument in this iteration doesn't start with a dash, it's a value
else
{
parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
n++;
}
}
return parsedArgs;
}
//
// Method to get an argument from the parsed command-line arguments
//
// Parameters:
// - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
// - defaultValue: The default string to return if the specified key isn't in parsedArgs.
// - keys: An array of keys to look for in parsedArgs.
public static string GetArgument(
Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
{
string retval = null;
foreach(var key in keys)
if(parsedArgs.TryGetValue(key, out retval)) break;
return retval ?? defaultReturn;
}
//
// Method to exit the application with an error.
public static void ErrorExit(string msg, int code=1)
{
Console.WriteLine("\nError");
Console.WriteLine(msg);
Environment.Exit(code);
}
}
}
정리
EC2 인스턴스가 더 이상 필요하지 않은 경우 Amazon EC2 인스턴스 종료의 설명에 따라 인스턴스를 삭제하십시오.