Назад | Перейти на главную страницу

Как сделать IP-адрес известным в обоих экземплярах в шаблоне Amazon CloudFormation

У меня есть несколько экземпляров в шаблоне Amazon CloudFormation, и я пытаюсь связать их вместе через UserData, то есть сообщать друг другу IP-адрес другой машины.

Шаблон выглядит примерно так:

"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"] } ] ] }
            ] ]
             } }
  }
},

Amazon CloudFormation отказывается обрабатывать эту CloudFormation и сообщает, что не может обрабатывать циклическую зависимость между двумя экземплярами.

Есть ли способ обойти это, не создавая что-то самостоятельно. Т.е. Я хотел бы иметь UserData в обоих экземплярах, который отражает IP-адрес другой машины, без последующего изменения UserData вручную.

Я действительно нашел способ сделать это только с помощью шаблонов Cloud Formation, используя ElasticIP.

Я создаю ElasticIP (в этом случае вы не можете напрямую назначить его экземпляру!)

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

Затем я ссылаюсь на этот IP-адрес в UserData.

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

Сервер может напрямую ссылаться на клиента

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

А позже я связываю Elastic с реальным сервером, чтобы Cloud Formation правильно обрабатывал зависимости:

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

Готово! Теперь у меня есть два экземпляра, которым известен IP-адрес другого узла.

Единственным недостатком является то, что трафик теперь осуществляется через общедоступный IP-адрес, что требует затрат на трафик и, вероятно, является менее безопасным.

Обновление: теперь я столкнулся с описанной проблемой Вот, не уверен, смогу ли я здесь обойти эту проблему.

Вы можете достичь своей цели высокого уровня, но не с указанными вами ограничениями (то есть, включая необработанные IP-адреса в пользовательских данных для обоих экземпляров). Простая причина:

  • Пользовательские данные должны быть указаны до запуска экземпляра.

  • IP-адрес неизвестен до тех пор, пока экземпляр не будет запущен.

CloudFormation может запустить один экземпляр и предоставить свой IP-адрес второму экземпляру, но не обоим сразу (циклическая зависимость).

Есть несколько подходов и технологий, которые можно использовать для решения этой двусторонней связи. На высоком уровне:

  • Вы можете передать IP-адрес A в B, затем попросить B связаться с A и сообщить ему свой IP-адрес (будьте осторожны с безопасностью).

  • Вы можете сохранить IP-адрес каждого экземпляра во внешнем хранилище (например, Route53, SimpleDB), а затем каждый будет запрашивать это внешнее хранилище при запуске, чтобы найти своего партнера.

РЕКОМЕНДАЦИЯ

Вот простой подход, который можно использовать с CloudFormation и надежными сервисами AWS:

  1. Настройте домен (размещенную зону) в Route53. Он может быть полностью отделен от любого общедоступного домена, который вы в настоящее время используете, хотя, если вы уже используете Route53, вы можете подключить эту функцию к тому же домену.

  2. В шаблоне CloudFormation сгенерируйте уникальное имя для каждого экземпляра, возможно, на основе имени текущего стека CloudFormation (например, «MYSTACK-server-a.example.com» и «MYSTACK-server-b.example.com»)

  3. В шаблоне CloudFormation передайте имена экземпляров на каждый сервер в их соответствующих пользовательских данных.

  4. Добавьте в шаблон CloudFormation директивы, чтобы внедрить эти новые DNS-имена (наборы записей) в Route53, сопоставив их с IP-адресами экземпляров.

CloudFormation запустит экземпляры, передавая пользовательские данные. Когда экземплярам будут назначены IP-адреса, CloudFormation сопоставит их с именами хостов в Route53 DNS. Затем ваши экземпляры могут использовать имена хостов для поиска друг друга.

Если вашим экземплярам нужно найти своих партнеров во время запуска, им нужно будет продолжать опрашивать DNS, пока партнер не перейдет в рабочее состояние и не получит IP-адрес. Будьте осторожны при использовании программного обеспечения, в котором кэшируется «промах» DNS.