Создание облачного сервера AWS с помощью Powershell

Опубликовано: 20.12.2019
Автор: Виталий Бочкарев

Создать облачный сервер AWS можно через консоль PowerShell, используя библиотеки AWS tools. Данный метод создания серверов удобен тем, что объект виртуальной машины создается по шаблону, то есть в процессе создания сервера необходимо ответить на стандартные вопросы, после чего сервер создается по аналогии со всеми остальными имеющимися серверами, созданными через этот скрипт, что дает возможность обслуживать группу таких виртуальных машин так же через сценарии администрирования.

Для работы скипта необходимо создать служебную учетную запись в консоли AWS с именем xxx_vm_deployment и следующими правами:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "ec2:*",
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}

Служебная учетная запись не должна иметь прав входа в административную консоль AWS, но должна иметь ключ доступа API (Programmatic access). Access Key Id и Secret Key от этой учетной записи необходимо выписать для последующего использования в скрипте PowerShell.

Ниже представлен скрипт создания новой виртуальной машины, в тексте которого есть комментарии для лучшего понимания механики сценария. Значения переменных и параметры развертывания можно измениить, адаптировав сценарий под свою организацию.

# Перед первым использованием этого скрипта необходимо установить модуль AWS PowerShell tools
# Используйте эти команды в консоли Powershell, запущенной от имени администратора, после чего переоткройте консоль
# Установка прокси сервера для консоли, если требуется
# netsh winhttp show proxy
# netsh winhttp set proxy "xxx.xxx.xxx.xxx:xxxx"
# Изменение политики подписывания скриптов
# Set-ExecutionPolicy RemoteSigned
# Установка модулей AWS PowerShell tools
# Install-Module -Name AWSPowerShell -Verbose -AllowClobber -Force

# Активация модуля AWS PowerShell tools
Import-Module -Name AWSPowerShell

# Значения по умолчанию для скрипта
$AccountID_Default = 123456789012
$Region_Default = 'eu-west-1'
$SubnetName_Default = "net-i-XXX-a"
$InstanceType_Default = "t3.small"

# Чтение вводных данных из консоли ввода
Write-host "Type values or press Enter to accept default ones..."

# Номер учетной записи AWS
Write-host
$AccountID_Promt = Read-Host "Account ID [$($AccountID_Default)]"
$AccountID = ($AccountID_Default, $AccountID_Promt)[[bool]$AccountID_Promt] #(If_false, If_true)[condition]

# Имя и пароль служебного пользователя от имени которого будет создаваться сервер
Write-host
Write-host ("Service account: " + "xxx_vm_deployment")
$ProfileAccessKey = "ABSDEFJHIGKLMNOPQ"      # arn:aws:iam::123456789012:user/xxx_vm_deployment
While (($ProfileSecretKey -eq $Nothing) -or ($ProfileSecretKey -eq '')) {
  $ProfileSecretKey = Read-Host "Secret key for the service account"
}

# Регион, в котором будет создаваться сервер
Write-host
$Region_Promt = Read-Host "Region [$($Region_Default)]"
$Region = ($Region_Default, $Region_Promt)[[bool]$Region_Promt] #(If_false, If_true)[condition]

# Подсеть, в которой будет создаваться сервер, группа безопасности и ключ шифрования
Write-host
$SubnetName_Promt = Read-Host "Subnet name [$($SubnetName_Default)]"
$SubnetName = ($SubnetName_Default, $SubnetName_Promt)[[bool]$SubnetName_Promt] #(If_false, If_true)[condition]
Switch ($SubnetName) {
  "net-i-XXX-a" {$SubnetID = "subnet-126b9e12"; $SecurityGroupId = "sg-124b2f12"; $KeyName = "key-i-XXX"}
  "net-i-XXX-b" {$SubnetID = "subnet-12916712"; $SecurityGroupId = "sg-124b2f12"; $KeyName = "key-i-XXX"}
  "net-i-YYY-a" {$SubnetID = "subnet-12917712"; $SecurityGroupId = "sg-12811e12"; $KeyName = "key-i-YYY"}
  "net-i-YYY-b" {$SubnetID = "subnet-12fe5c12"; $SecurityGroupId = "sg-12811e12"; $KeyName = "key-i-YYY"}
  "net-i-ZZZ-a" {$SubnetID = "subnet-12f0e912"; $SecurityGroupId = "sg-12aea612"; $KeyName = "key-i-ZZZ"}
  "net-i-ZZZ-b" {$SubnetID = "subnet-12e8f112"; $SecurityGroupId = "sg-12aea612"; $KeyName = "key-i-ZZZ"}
  Default {$SubnetID = "UNDEFINED"; Write-Host "UNDEFINED parameters" -BackgroundColor Red}
}

# Выбор операционной системы
Write-host
$OSName = $Nothing
Write-Host "Operating system name:"
Write-Host "  0 - Custom image"
Write-Host "  1 - Microsoft Windows Server 2012 R2"
Write-Host "  2 - Microsoft Windows Server 2016"
Write-Host "  3 - Microsoft Windows Server 2016 with SQL Server 2017 Standard"
Write-Host "  4 - Ubuntu Server 16.04 LTS"
Write-Host "  5 - Ubuntu Server 18.04 LTS"
Write-Host "  6 - CentOS 7"
Write-Host "  7 - Red Hat Enterprise Linux 7.4"
Write-Host "  8 - Red Hat Enterprise Linux 8"
While (-not ($OSName -match '^[0-8]{1}$')) {$OSName = Read-Host "Type number"}
Write-host
Switch ($OSName) {
  0 {$ImageId = Read-Host "Type image id (ex. ami-0927c25b5177ff0de)"}
  1 {$ImageId = "ami-0927c25b5177ff0de"}
  2 {$ImageId = "ami-0bd191f9766bc39f7"}
  3 {$ImageId = "ami-0072f890142adec24";
     Write-Host "For MS SQL Server you have to choose VM type with 4 cores and more" -ForegroundColor Black -BackgroundColor Yellow}
  4 {$ImageId = "ami-03ef731cc103c9f09"}
  5 {$ImageId = "ami-02df9ea15c1778c9c"}
  6 {$ImageId = "ami-0ff760d16d9497662"}
  7 {$ImageId = "ami-bb9a6bc2"}
  8 {$ImageId = "ami-04facb3ed127a2eb6"}
  Default {$ImageId = "UNDEFINED"; Write-Host "UNDEFINED parameters" -BackgroundColor Red}
}

# Размер виртуальной машины
Write-host
$VMSize = $Nothing
Write-Host "Instance type:"
Write-Host "  0 - Custom type"
Write-Host "  1 - t3.micro   (2 cores, 1 GB RAM)"
Write-Host "  2 - t3.small   (2 cores, 2 GB RAM)"
Write-Host "  3 - t3.medium  (2 cores, 4 GB RAM)"
Write-Host "  4 - t3.large   (2 cores, 8 GB RAM)"
Write-Host "  5 - t3.xlarge  (4 cores, 16 GB RAM)"
Write-Host "  6 - t3.2xlarge (8 cores, 32 GB RAM)"
Write-Host "  7 - m5.large   (2 cores, 8 GB RAM)"
Write-Host "  8 - m5.xlarge  (4 cores, 16 GB RAM)"
While (-not ($VMSize -match '^[0-8]{1}$')) {$VMSize = Read-Host "Type number"}
Write-host
Switch ($VMSize) {
  0 {$InstanceType = Read-Host "Type vm type id (ex. r5.xlarge)"}
  1 {$InstanceType = "t3.micro"}
  2 {$InstanceType = "t3.small"}
  3 {$InstanceType = "t3.medium"}
  4 {$InstanceType = "t3.large"}
  5 {$InstanceType = "t3.xlarge"}
  6 {$InstanceType = "t3.2xlarge"}
  7 {$InstanceType = "m5.large"}
  8 {$InstanceType = "m5.xlarge"}
  Default {$InstanceType = "UNDEFINED"; Write-Host "UNDEFINED parameters" -BackgroundColor Red}
}

# Имя виртуальной машины (только в консоли AWS, а не внутри операционной системы)
Write-host
$VirtualMachineName = $Nothing
While (($VirtualMachineName -eq $Nothing) -or ($VirtualMachineName -eq '')) {
    $VirtualMachineName = Read-Host "Virtual machine name (ex. wsXXX001)"
}

# Ответственный за виртуальную машину
Write-host
$Responsible = $Nothing
While (($Responsible -eq $Nothing) -or ($Responsible -eq '')) {
    $Responsible = Read-Host "Responsible person (ex. Bochkarev Vitaly)"
}

# Описание виртуальной машины
Write-host
$Description = $Nothing
While (($Description -eq $Nothing) -or ($Description -eq '')) {
    $Description = Read-Host "Server description (ex. AWS AGC Domain controller PROD)"
}

# Назначение виртуальной машины
Write-host
$Purpose = $Nothing
Write-Host "Server purpose:"
Write-Host "  1 - PROD"
Write-Host "  2 - TEST"
Write-Host "  3 - DEV"
While (-not ($Purpose -match '^[1-3]{1}$')) {$Purpose = Read-Host "Type number"}
Switch ($Purpose) {
  1 {$VirtualMachinePurpose = "PROD"}
  2 {$VirtualMachinePurpose = "TEST"}
  3 {$VirtualMachinePurpose = "DEV"}
  Default {$VirtualMachinePurpose = "UNDEFINED"; Write-Host "UNDEFINED parameters" -BackgroundColor Red}
}

# Заполнение меток для виртуальной машины собранными данными
$VmTags = @()
$VolumeTags = @()

$NameTag = New-Object Amazon.EC2.Model.Tag
$DescriptionTag = New-Object Amazon.EC2.Model.Tag
$PurposeTag = New-Object Amazon.EC2.Model.Tag
$ResponsibleTag = New-Object Amazon.EC2.Model.Tag

$NameTag.Key        = "Name"; $NameTag.Value = $VirtualMachineName
$DescriptionTag.Key = "Description"; $DescriptionTag.Value = $Description
$PurposeTag.Key     = "Purpose"; $PurposeTag.Value = $VirtualMachinePurpose
$ResponsibleTag.Key = "Responsible"; $ResponsibleTag.Value = $Responsible

$VmTags += $NameTag
$VmTags += $DescriptionTag     
$VmTags += $PurposeTag
$VmTags += $ResponsibleTag

$VolumeTags += $NameTag
$VolumeTags += $ProjectTag
$VolumeTags += $ResponsibleTag

# Развертывание виртуальной машины
$InstancePreInstance = New-EC2Instance -ImageId $ImageId -MinCount 1 -MaxCount 1 -KeyName $KeyName `
    -SecurityGroupId $SecurityGroupId -InstanceType $InstanceType -SubnetId $SubnetID `
    -AccessKey $ProfileAccessKey -SecretKey $ProfileSecretKey

# Получение идентификатора созданного сервера
$Reservation = New-Object 'collections.generic.list[string]'
$Reservation.add($InstancePreInstance.ReservationId)
$FilterReservation = New-Object Amazon.EC2.Model.Filter -Property @{Name = "reservation-id"; Values = $reservation}
$InstanceId = ((Get-EC2Instance -Filter $FilterReservation).Instances).InstanceId

# Заполнение меток созданного сервера и вывод в консоль информации о сервере
If ($InstanceId -ne $Nothing) {
    # Tagging the VM
    New-EC2Tag -ResourceId $InstanceId -Tags $VmTags
    $Volumes = (Get-EC2Instance -InstanceId $InstanceId).Instances.BlockDeviceMappings.Ebs
    ForEach ($Volume in $Volumes) {
        New-EC2Tag -ResourceId $Volume.VolumeId -Tags $VolumeTags
    }
    (Get-EC2Instance -InstanceId $InstanceId).Instances | FL InstanceId, InstanceType, PrivateIpAddress
} Else {
    Write-Host "Error" -BackgroundColor Red
}