in Desenvolvimento

Amazon EC2 + PowerShell

Uma das grandes vantagens da computação em nuvem é a flexibilidade de recursos, com ela é possível pagar por um determinando recurso somente ao utiliza-lo. Como já disse em um post anterior (Amazon S3 + PowerShell) a Amazon possui excelentes soluções em cloud computing, entre elas está a Amazon Elastic Compute Cloud (EC2), que consiste em um serviço de computação, extremamente flexível, na qual é possível criar e gerenciar maquinas virtuais (instâncias), com várias features, e em vários locais do mundo.

Essa flexilidade nos permite criar ambientes de testes e de produção bem escaláveis, caso algum recurso não seja mais necessário é possivel desaloca-lo ou para-lo, com isso o custo de infra-estrutura será proporcional ao uso.

Onde trabalho temos alguns ambientes de testes, stage, homologação e produção em diversos locais, um deles é na Amazon EC2. os Ambientes de testes não precisam ficar com todas as instancias ligadas 24horas por dia, mais sim durante o horário de trabalho, é muti simples entrar no painel de controle da AWS e iniciar ou parar uma instancia, mais pensando em automatização fiz dois scripts com PowerShell que utiliza o SDK da Amazon para iniciar e parar instancias na EC2.

Scripts

Para começar vamos precisar fazer download do SDK da Amazon para .NET, eu poderia ter feito um programa com C# utilizando o SDK da Amazon, mas como a idéia é utilizar e aprender a usar PowerShell, utilizei ele para escrever um script que inicia uma lista de instancias, e outro que para uma lista de instancias.

Iniciando

O script para iniciar as instancias começa adicionando referencia ao SDK da amazon e possui uma listas com os ID’s das instancias que serão iniciadas, o ip que será alocado(caso necessário), outra configuração importante é a url de endpoint do local onde as instancias estão:

Add-Type -Path "C:\Program Files (x86)\AWS SDK for .NET\bin\AWSSDK.dll"

$instancias = New-Object System.Collections.Generic.List[System.Collections.Hashtable]

$instancias.Add(@{"maquina" = "i-xxxxx"; "ip" = ""; endpoint= "https://ec2.sa-east-1.amazonaws.com/"})
##$instancias.Add(@{"maquina" = "i-xxxxx"; "ip" = "111.111.1.11"; endpoint= "https://ec2.sa-east-1.amazonaws.com/"})
##$instancias.Add(@{"maquina" = "i-xxxxx"; "ip" = "111.111.1.11"; endpoint= "https://ec2.sa-east-1.amazonaws.com/"})
##$instancias.Add(@{"maquina" = "i-xxxxx"; "ip" = "111.111.1.11"; endpoint= "https://ec2.sa-east-1.amazonaws.com/"})

$secretKeyID="Secret key"
$secretAccessKeyID="Acces key"

##Urls de endpoint
##US East (Northern Virginia) Region	ec2.us-east-1.amazonaws.com	HTTP and HTTPS
##US West (Oregon) Region	ec2.us-west-2.amazonaws.com	HTTP and HTTPS
##US West (Northern California) Region	ec2.us-west-1.amazonaws.com	HTTP and HTTPS
##EU (Ireland) Region	ec2.eu-west-1.amazonaws.com	HTTP and HTTPS
##Asia Pacific (Singapore) Region	ec2.ap-southeast-1.amazonaws.com	HTTP and HTTPS
##Asia Pacific (Tokyo) Region	ec2.ap-northeast-1.amazonaws.com	HTTP and HTTPS
##South America (Sao Paulo) Region	ec2.sa-east-1.amazonaws.com	HTTP and HTTPS

foreach ($item in $instancias)
{
    $config = New-Object Amazon.EC2.AmazonEC2Config
    $config.WithServiceURL($item.endpoint)
    $client = [Amazon.AWSClientFactory]::CreateAmazonEC2Client($secretAccessKeyID,$secretKeyID,$config)
    $request = New-Object Amazon.EC2.Model.StartInstancesRequest
    $request.WithInstanceId($item.maquina)
    $client.StartInstances($request)

    if($item.ip.Length -gt 0)
    {
        $associateRequest= New-Object Amazon.EC2.Model.AssociateAddressRequest
        $associateRequest.WithInstanceId($item.maquina)
        $associateRequest.WithPublicIp($item.ip)

        $client.AssociateAddress($associateRequest)

    }
}

Parando

Já o script que para uma lista de instancias é quase igual, somente o objeto e a requisição com o $client é diferente:

Add-Type -Path "C:\Program Files (x86)\AWS SDK for .NET\bin\AWSSDK.dll"

$instancias = New-Object System.Collections.Generic.List[System.Collections.Hashtable]

$instancias.Add(@{"maquina" = "i-xxxxx"; "ip" = ""; endpoint= "https://ec2.sa-east-1.amazonaws.com/"})
##$instancias.Add(@{"maquina" = "i-xxxxx"; "ip" = "111.111.1.11"; endpoint= "https://ec2.sa-east-1.amazonaws.com/"})
##$instancias.Add(@{"maquina" = "i-xxxxx"; "ip" = "111.111.1.11"; endpoint= "https://ec2.sa-east-1.amazonaws.com/"})
##$instancias.Add(@{"maquina" = "i-xxxxx"; "ip" = "111.111.1.11"; endpoint= "https://ec2.sa-east-1.amazonaws.com/"})

$secretKeyID="Secret key"
$secretAccessKeyID="Acces key"

##Urls de endpoint
##US East (Northern Virginia) Region	ec2.us-east-1.amazonaws.com	HTTP and HTTPS
##US West (Oregon) Region	ec2.us-west-2.amazonaws.com	HTTP and HTTPS
##US West (Northern California) Region	ec2.us-west-1.amazonaws.com	HTTP and HTTPS
##EU (Ireland) Region	ec2.eu-west-1.amazonaws.com	HTTP and HTTPS
##Asia Pacific (Singapore) Region	ec2.ap-southeast-1.amazonaws.com	HTTP and HTTPS
##Asia Pacific (Tokyo) Region	ec2.ap-northeast-1.amazonaws.com	HTTP and HTTPS
##South America (Sao Paulo) Region	ec2.sa-east-1.amazonaws.com	HTTP and HTTPS

foreach ($item in $instancias)
{
    $config = New-Object Amazon.EC2.AmazonEC2Config
    $config.WithServiceURL($item.endpoint)
    $client = [Amazon.AWSClientFactory]::CreateAmazonEC2Client($secretAccessKeyID,$secretKeyID,$config)

    $request = New-Object Amazon.EC2.Model.StopInstancesRequest
    $request.WithInstanceId($item.maquina)

    $client.StopInstances($request)
}

Com esses dois scripts é possivel criar tarefas agendadas que iniciam e param as instancias na EC2, para isso é só criar uma tarefa agendada com o seguinte comando: PowerShell “C:/pathdoscript/nome-do-script.ps1”

Caso o script apresente erro de segurança ao executar, é necessário habilitar a execução de scripts na maquina, abra um prompt do PowerShell e utilize o seguinte comando:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

Os scripts e outros estão disponiveis no meu GitHub

https://gist.github.com/3030382
https://gist.github.com/3030388

Espero que este post seja útil,

estou a disposição para dúvidas, críticas e sugestões.

abs

Rodolfo