5

I'm working on some automation scripts to bootstrap my application and will be using an auto-scaling group in AWS to spin up/down EC2 instances for my application.

I need to be able to re-create a consistent name for the machine that follows a pattern: MYAPP001, MYAPP002, MYAPP003.

The Question

Is there a way to query meta-data during the user-data bootstrapping phase to determine that this machine that just came up is 002 in the group?

If I can determine this, then I can rename the machine to MYAPP002.

Scenario to Help Explain

Imagine a 3rd-party service that expects machines to be named MYAPP001, MYAPP002, MYAPP003. In this software, it's OK for a machine to go offline and come back online later with a different IP address. However, you cannot have two different machines talk to this software at the same time with the same host name.

Timothy Khouri
  • 157
  • 2
  • 8
  • Did anyone find solution of this problem. I also used meta data to get instance index but instances spinning up same time are getting same index. – surbhi Feb 11 '20 at 18:23

4 Answers4

2

The documentation says that it's possible: Example: AMI Launch Index Value.

$ TOKEN=$(curl -X PUT "http://169.254.169.254/latest/meta-data/api/token"-H "X-aws-ec2-metadata-token-ttl-seconds: 21600") \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/ami-launch-index
Neil
  • 2,345
  • 8
  • 35
  • 44
-1

Are you certain that this information is even available via the API? The best I can think of would be to query the launch times of all of the running instances and then work out which is the "newest".

I have to say, though, that you're doing it wrong if you are relying on any machine-specific state in your autoscaling group. Your deployment method and application should be built such that all ASG instances are exactly the same, even their hostname. Needing to assign a specific hostname for some technical reason will come back to haunt you.

See this as an opportunity to refactor things such that you don't need to do this. Build your app such that the ASG can create and destroy instances as it needs, without you needing to worry about what it calls each host.


As a thought experiment, let's think this a bit througher. Say you instantiate an ASG with three instances: ASG[01,02,03]. At some point in the future, ASG02 has problems and gets terminated. The ASG creates a new instance to replace it, which is now ASG04. So now you have ASG[01,03,04]. Is that what you're intending? Why do you need this information? As mentioned above, if you're doing things right, you don't need this information, or shouldn't anyway. If you're just doing it for human-readable purposes or so that you can keep track of things better, just let it go and trust the ASG to do its thing.

EEAA
  • 108,414
  • 18
  • 172
  • 242
  • I'm not sure if the API offers this info, hence my question. If I knew that information I wouldn't have asked :) The second part though is a bit naive though as there are several 3rd party systems, architectures, etc. that require unique names. For example (please don't get caught up in the examples) - you can't join the same Active Directory domain with duplicate computer names... Chef server requires unique Node names... etc. - Again, don't get caught up in the examples - the question remains: *is this possible in AWS*? – Timothy Khouri Jul 16 '17 at 17:16
  • 1
    I would solve this by setting each host's name to its instance ID. That is guaranteed to be unique within your account. – EEAA Jul 16 '17 at 17:35
  • The host names are already random by AWS - however they need to follow a particular pattern. I realize that I need to explain the scenario in my question more clearly. Thanks for the feedback so far. – Timothy Khouri Jul 16 '17 at 18:58
  • The instances **must** have meaningful names so you have some reasonable and intuitive way to login to them without having to resort to an obscure IP address. Why is there so much pushback against this? Am I the only person who's ever had to login to instances inside an autoscale group? We can put a man on the moon. We can figure out how to dynamically name instances. – Cerin Apr 22 '19 at 17:24
-1

OK, it took some Googling and then spinning up some instances in AWS, remoting in and testing. Here is the (very simple) answer thanks to AWS:

http://169.254.169.254/latest/meta-data/ami-launch-index

That's it. That returns a "zero-based" index of the launch order. Here is the documentation from Amazon and they give a good use-case as to why you would need this:

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#AMI-launch-index-examples

Here is the PowerShell script I'm using to get my machine names:

$index = (Invoke-WebRequest "http://169.254.169.254/latest/meta-data/ami-launch-index").Content

$name = "MYAPP" + ([Int]::Parse($index) + 1).ToString("000")

Sadly, this is not proving super successful as my auto-scale group created 2 instances and both say they are "index # 0" - I'll keep working at it and adjust the answer with my findings.

Timothy Khouri
  • 157
  • 2
  • 8
  • 1
    I think you're on the right track with this, but you'll want to verify what happens with the launch index if an instance fails and is replaced. – Michael - sqlbot Jul 17 '17 at 02:21
  • I'm not sure if you found a workaround for this, but Autoscaling groups always return launch index of 0 for all nodes. That is by design. – blueben Dec 19 '17 at 19:21
  • It's inappropriate to link to your private dynamic instances on Stackoverflow. – Cerin Apr 22 '19 at 17:26
  • Yep, ami-launch-index only works for CloudFormation stacks and similar - all ASG instances are supposed to be fully identical, so there might not be any non-hacky workable approach. @Cerin That specific IP is the link-local address for accessing instance metadata from within any EC2 instance. Please give users the benefit of the doubt instead of assuming incompetence. – Backgammon Apr 29 '19 at 22:07
-1

you can rename the servers by keeping a common tag name like "appserver" and adding the numbers to this string during runtime.

!Sub '$Env=''${Environment}'''
                - '    $instanceid = Get-EC2InstanceMetadata -Category InstanceId'
                - !Sub '$tag_Name=''${Name}'''
                - '    $Dev=901'
                - '    $Test=801'
                - '    $Prod=101'
                - '    if($Env -eq "dev"){$StartVal = $Dev}'
                - '    if($Env -eq "test"){$StartVal = $Test}'
                - '    if($Env -eq "prod"){$StartVal = $Prod}'
                - '    Start-Sleep -s ((Get-Random -Minimum 1 -Maximum 10) + (Get-Random -Minimum 1 -Maximum 10))'
                - '    Start-Sleep -s ((Get-Random -Minimum 1 -Maximum 10) + (Get-Random -Minimum 1 -Maximum 10))'
                - '    Start-Sleep -s ((Get-Random -Minimum 1 -Maximum 10) + (Get-Random -Minimum 1 -Maximum 10))'
                - '    Start-Sleep -s ((Get-Random -Minimum 1 -Maximum 10) + (Get-Random -Minimum 1 -Maximum 10))'
                - '    Start-Sleep -s ((Get-Random -Minimum 1 -Maximum 10) + (Get-Random -Minimum 1 -Maximum 10))'
                - '    Start-Sleep -s ((Get-Random -Minimum 1 -Maximum 10) + (Get-Random -Minimum 1 -Maximum 10))'
                - '    Start-Sleep -s ((Get-Random -Minimum 1 -Maximum 10) + (Get-Random -Minimum 1 -Maximum 10))'
                - '    $a=@(Get-EC2Tag -Filter @{Name="key";Value="Name"},@{Name="resource-type";Value="instance"})'
                - '    $b = @()'
                - '    foreach( $item in $a){'
                - '      if($item.Value -match $tag_Name){'
                - '        $item.Value=$item.Value.substring($item.Value.length - 3, 3)'
                - '        $b += $item.Value'
                - '      }'
                - '    }'
                - '    Write-Host $b'
                - '    if($b -eq $null){'
                - '      $StartVal=$StartVal'
                - '    }'
                - '    else {'
                - '      foreach( $item in $b){'
                - '        if($b -contains $StartVal){'
                - '            $StartVal = $StartVal+1  '
                - '        }'
                - '        else {$StartVal=$StartVal}'
                - '      }'
                - '    }'
                - '    Write-Host $StartVal'
                - '    $tag_Name += $StartVal'
                - '    Write-Host $tag_Name'
                - '    $tag = New-Object Amazon.EC2.Model.Tag'
                - '    $tag.Key = "Name"'
                - '    $tag.Value = $tag_Name'
                - '    New-EC2Tag -Resource $instanceid -Tag $tag'
                - '    $newcomputername = $tag_Name'
Jenny D
  • 27,358
  • 21
  • 74
  • 110