I'm in a bit of a pickle here. I have a specific application (one that I cannot modify) which I need to automatically deploy on 3 AWS EC2 instances using CloudFormation, and I need all 3 of them to be aware of each other as they boot up, or at least before any traffic hits them.
In short, what needs to happen is that as the machines spin up, they need to each run a local command (a windows shell script) that includes the hostnames or IPs of all 3 machines. Imagine something like:
c:\>node startReplication.js server1.aws.com,server2.aws.com,server3.aws.com What makes this tougher is that I cannot use static IPs or names, I need this to be completely dynamic for each stack. I also cannot use any non-AWS-native tools such as Chef or Terraform or any other 3rd party, for reasons too irrelevant to specify here. Everything must be done via native AWS services.
I've tried doing something like this:
"UserData" : { "Fn::Base64" : { "Fn::Join" : [ ",", [ { "Fn::GetAtt" : [ "server1", "PublicDnsName" ] }, { "Fn::GetAtt" : [ "server2", "PublicDnsName" ] }, { "Fn::GetAtt" : [ "server3", "PublicDnsName" ] } ] } } To only pass in the dns names, haven't even reached the point of figuring out how to actually run a script/command - but already this fails due to a circular reference.
What I understand is that CloudFormation looks at these references as dependencies - so to reference "server1" I need it to be created, but if all 3 machines need all 3 references, I've hit a brick wall.
I'm not experienced enough with AWS (actually, not at all) to figure out an alternative path for this, but I had some theoretical ideas which you might be able to confirm, or suggest one of your own:
- Have each machine register itself to some external place - such as an S3 bucket, AWS Config, SQS and so on.. And when CF is done, run a lambda that uses that data to somehow initiate a shell script on all 3 machines.
- Maybe CF has a way of running a shell script when all instances are created (using a Wait?) and their DNS names are available?
- Developing some kind of agent service to run on all machines, have one that will get references to the other two using UserDataand then have it send that information to the other two to trigger said script
- Maybe running cf-initfrom a node process launched withuserdatascript to get this information and pass it on to subsequent scripts that need to run (not sure if that's how cf-init works and if it happens after all 3 machines have dns names allocated)
I want to avoid an overly complicated or convoluted solution as I've got both limited knowledge and limited time (isn't that the recipe for success nowadays?)
I hope I've made the issue clear enough. Thanks in advance!
