Como tornar o endereço IP conhecido nas duas instâncias em um modelo do Amazon CloudFormation

3

Eu tenho várias instâncias em um modelo do Amazon CloudFormation e estou tentando conectá-las por meio do UserData, ou seja, informar um ao outro o endereço IP da outra máquina.

O modelo é algo como isto:

"Instance1" : {
  "Type" : "AWS::EC2::Instance",
    ...
    "UserData" : { 
        "Fn::Base64" : { 
        "Fn::Join" : [ "\n", [ 
            { "Fn::Join" : [ "=", [ "Instance2", { "Fn::GetAtt" : [ "Instance2" , "PrivateIp"] } ] ] }
            ] ]
             } }
  }
},
"Instance2" : {
  "Type" : "AWS::EC2::Instance",
    ...
    "UserData" : { 
        "Fn::Base64" : { 
        "Fn::Join" : [ "\n", [ 
            { "Fn::Join" : [ "=", [ "Instance1", { "Fn::GetAtt" : [ "Instance1" , "PrivateIp"] } ] ] }
            ] ]
             } }
  }
},

O Amazon CloudFormation se recusa a lidar com esse CloudFormation e relata que não pode manipular a dependência circular entre as duas instâncias.

Existe uma maneira de contornar isso sem ter que construir algo por conta própria. Ou seja Eu gostaria de ter UserData em ambas as instâncias, que reflete o endereço IP da outra máquina, sem posteriormente ter que carregar manualmente o UserData.

    
por centic 12.03.2013 / 15:20

2 respostas

4

Na verdade, descobri uma maneira de fazer isso apenas com modelos de formação em nuvem usando o ElasticIPs.

Eu criei um ElasticIP (você não pode atribuí-lo diretamente a uma instância neste caso!)

"ServerEIP" : {
 "Type" : "AWS::EC2::EIP",
 "Properties" : {
 }
},

Em seguida, faço referência a esse IP no UserData

"Client" : {
   ...
        "UserData" : { 
            { "Fn::Join" : [ "=", [ "Server", { "Ref" : "ServerEIP" } ] ] }

O servidor pode referenciar diretamente o cliente

"Server" : {
  "Type" : "AWS::EC2::Instance",
    ...
"UserData" : { 
        ...
            { "Fn::Join" : [ "=", [ "Client", { "Fn::GetAtt" : [ "Client" , "PrivateIp"] } ] ] },

Mais tarde, associo o Elastic ao servidor real para que o Cloud Formation manipule as dependências corretamente:

"ServerIPAssoc" : {
     "Type" : "AWS::EC2::EIPAssociation",
     "Properties" : {
         "InstanceId" : { "Ref" : "Server" },
         "EIP" : { "Ref" : "ServerEIP" }
     }
 },

Feito! Agora tenho duas instâncias que conhecem o endereço IP do outro nó.

A única desvantagem é que o tráfego agora é feito através de um endereço IP público, incorrendo em custos de tráfego e sendo provavelmente menos seguro.

Atualização: agora me deparo com o problema descrito aqui , não tenho certeza se posso resolver este problema aqui.

    
por 14.03.2013 / 09:49
1

Você pode atingir sua meta de alto nível, mas não com as restrições listadas (isto é, incluindo os endereços IP brutos nos dados do usuário para as duas instâncias). A razão simples é:

  • Os dados do usuário devem ser especificados antes que a instância seja iniciada.

  • O endereço IP não é conhecido até que a instância seja iniciada.

O CloudFormation pode iniciar uma instância e fornecer seu endereço IP à segunda instância, mas não as duas ao mesmo tempo (dependência circular).

Existem várias abordagens que você pode adotar e tecnologias que você poderia usar para resolver essa comunicação bidirecional. Em alto nível:

  • Você poderia passar o endereço IP de A para B, ter B contact A e informar o endereço IP (tenha cuidado com a segurança).

  • Você pode armazenar o endereço IP de cada instância no armazenamento externo (por exemplo, Route53, SimpleDB) e, em seguida, cada um consultaria o armazenamento externo na inicialização para localizar o parceiro.

RECOMENDAÇÃO

Veja uma abordagem simples que pode ser usada com o CloudFormation e serviços confiáveis da AWS:

  1. Configure um domínio (zona hospedada) no Route53. Isso pode ser completamente separado de qualquer domínio público que você usa atualmente, mas se você já estiver usando o Route53, poderá conectar essa funcionalidade ao mesmo domínio.

  2. Em seu modelo do CloudFormation, gere um nome exclusivo para cada instância, talvez com base no nome atual da pilha do CloudFormation (por exemplo, "MYSTACK-server-a.example.com" e "MYSTACK-server-b.example .com ")

  3. No modelo do CloudFormation, passe os nomes das instâncias para cada servidor em seus respectivos dados de usuário.

  4. Adicione diretivas ao modelo do CloudFormation para injetar esses novos nomes DNS (conjuntos de registros) no Route53, mapeando-os para os endereços IP das instâncias.

O CloudFormation iniciará as instâncias, transmitindo os dados do usuário. Quando endereços IP forem atribuídos às instâncias, o CloudFormation os mapeará para os nomes de host no DNS Route53. Suas instâncias podem usar os nomes de host para encontrar um ao outro.

Se as suas instâncias precisarem encontrar seus parceiros no momento da inicialização, elas precisarão continuar pesquisando o DNS até que o parceiro seja movido para o estado em execução e tenha recebido um endereço IP. Tenha cuidado ao usar o software em que um DNS "miss" está em cache.

    
por 12.03.2013 / 18:55