在 AWS 部署脚本中调用 169.254.169.254/latest/meta-data/instance-id 失败

Call to 169.254.169.254/latest/meta-data/instance-id fails in AWS deployment script

我正在使用一些基于 http://blog.brianbeach.com/2014/07/setting-hostname-in-syspreped-ami.html 的脚本来将从 AMI 创建的新 windows 实例的主机名设置为实例的名称标签。而不是 HKLM:\System\Setup 指向 windeploy.exe,它运行一个运行这个的脚本:

$InstanceName = 'WebServerNew'

Try 
{
    Start-Transcript -Path D:\WebServerUtility\SysPrep\Windeploy.log -Append
    Write-Host "Discovering instance identity from meta-data web service"
    $InstanceId = (Invoke-RestMethod 'http://169.254.169.254/latest/meta-data/instance-id').ToString()
    $AvailabilityZone = (Invoke-RestMethod 'http://169.254.169.254/latest/meta-data/placement/availability-zone').ToString()
    $Region = $AvailabilityZone.Substring(0,$AvailabilityZone.Length-1)

    Write-Host "Getting Tags for the instance"
    $Tags = Get-EC2Tag -Filters @{Name='resource-id';Value=$InstanceId} -Region $Region
    $InstanceName = ($Tags | Where-Object {$_.Key -eq 'Name'}).Value
    Write-Host "`tFound Instance Name: $InstanceName"    
}
Catch
{
    Write-Host $_
    $InstanceName = 'WebServerError'
}

try
{ 
    If($InstanceName -ne $null) {
          Write-Host "Setting the machine name to $InstanceName"
          $AnswerFilePath = "C:\Windows\Panther\unattend.xml"
          $AnswerFile = [xml](Get-Content -Path $AnswerFilePath) 
          $ns = New-Object System.Xml.XmlNamespaceManager($AnswerFile.NameTable)
          $ns.AddNamespace("ns", $AnswerFile.DocumentElement.NamespaceURI)
          $ComputerName = $AnswerFile.SelectSingleNode('/ns:unattend/ns:settings[@pass="specialize"]/ns:component[@name="Microsoft-Windows-Shell-Setup"]/ns:ComputerName', $ns)
          $ComputerName.InnerText = $InstanceName
          $AnswerFile.Save($AnswerFilePath)
    }
}
Catch
{
    Write-Host $_
}
Finally
{
    Stop-Transcript
}

然后它调用 WinDeploy.exe 来完成专业化。

问题是行

    Write-Host "Discovering instance identity from meta-data web service"
    $InstanceId = (Invoke-RestMethod 'http://169.254.169.254/latest/meta-data/instance-id').ToString()

失败 "Unable to connect to the remote server"。

知道为什么它无法连接到那个吗?

看起来很奇怪…… URL 看起来是正确的。让我们尝试调试它。让我们隔离问题并查看它的脚本问题还是其他问题。

  1. 尝试远程登录 169.254.169.254 80

是否显示已连接

  1. 也可以在浏览器上尝试 http://169.254.169.254/latest/meta-data/instance-id 并查看输出..

另外,尝试运行系统初始化后的脚本...可能是脚本运行ning的时间;此本地 IP 未初始化。

每次系统启动时; EC2 将自定义路由添加到主网络适配器以在连接多个 NIC 时启用以下 IP 地址:169.254.169.254。你的这个脚本在连接 NIC 之前被执行。因此问题。

你的脚本非常适合我。

问题是您的实例上的某些东西阻止了对该 IP 地址的访问,例如防火墙。

检查您的系统配置,看看 Windows 防火墙是否阻止了访问,或者是否安装了阻止它的任何其他安全软件。

尝试 Invoke-RestMethod 'http://google.com' 也是一个很好的测试。

您需要将此添加到脚本的顶部:

Start-Service -Name 'Dhcp'
route add 169.254.169.254 MASK 255.255.255.255 0.0.0.0

触发脚本时,DHCP 客户端停止。那就是你没有IP的原因。

并且您还需要添加到 meta-data 服务的路由。 Sysprep 删除那些路由。

DHCP 已启动,但未间歇性地为接口分配 IP,下面是完成此操作的解决方法

Function Get-IP{
    $global:initializedIP=netsh interface ip show address $interfaceName | where { $_ -match "IP Address"} | %{ $_ -replace "^.*IP Address:\W*", ""}
    Write-host "`tInitialized IP: $initializedIP"
}

Function InitializeNetwork{
    $global:interfaceName = netsh interface ipv4 show interfaces | where { $_ -match "Ethernet"}| %{ $_ -replace "^.*Connected\W*",""}  
    write-host "`tInterface name: $interfaceName"
    $status = Invoke-Command -Command { netsh interface ipv4 set interface $interfaceName mtu=1460 }
    Write-host "`tInitializing $interfaceName : $status"
    Write-Host "`tStarting Service: DHCP"
    Start-Service -Name 'Dhcp'    
    $r_status = Invoke-Command -Command { route /p add 169.254.169.254 mask 255.255.255.255 0.0.0.0 if 6 metric 1}
    Write-Host "`tAdding metadata route $r_status"
}    
  
Try {
    Start-Transcript -Path C:\Temp\Windeploy.log -Append
    Write-Host "[Meta-Data] Discovering instance identity from meta-data web service"
    Set-Variable -Name "interfaceName" -value "Ethernet 2" -scope global
    Set-Variable -Name "initializedIP" -value "169.254.169.254" -scope global
    Write-Host "[Network] Initializing default network"
    InitializeNetwork
    Get-IP
    While (-not ($initializedIP -like "10.*.*.*"))
    {
        Write-Host "`tGetting IP for $interfaceName"
        Invoke-Command -Command {ipconfig /renew $interfaceName}    
        Get-IP    
    }
    
    $Global:InstanceInfo = Invoke-WebRequest 'http://169.254.169.254/latest/dynamic/instance-identity/document/' -UseBasicParsing | ConvertFrom-Json
    $AccountId = $InstanceInfo.accountId
    $AWSRegion = $InstanceInfo.region
    $InstanceId = $InstanceInfo.instanceId
    Write-Host "[Instance-Tags] Getting Tags for the instance"    
    $Tags = Get-EC2Tag -Filters @{Name='resource-id';Value=$InstanceId} -Region $AWSRegion
    Write-Host "`t$Tags"

    #Generate windows hostname with lowercase letters/numbers only if meta-data not available
    Write-Host "[ComputerName] Auto generate the default computer name." 
    $instanceName = "WIN-" + -join ((48..57) + (97..122) | Get-Random -Count 11 | % {[char]$_})
    Write-Host "`tAuto Instance Name: $InstanceName"
    If ($null -eq $Tags.Where( { $_.Key -eq "hostname" }).Value){
        $instanceName="{0}{1}" -F $Tags.Where( {($_.Key).ToLower() -eq "appcode" }).Value, $InstanceId.Remove(0,($InstanceId.Length - 9))
    }else{
        $InstanceName = ($Tags | Where-Object {$_.Key -eq 'hostname'}).Value
    }
    Write-Host "`tFound Instance Name: $InstanceName"
    If($InstanceName) {
        Write-Host "[Unattend] Setting the machine name to $InstanceName"
        $AnswerFilePath = "C:\Windows\Panther\Unattend.xml"
        $AnswerFile = [xml](Get-Content -Path $AnswerFilePath)
        $ns = New-Object System.Xml.XmlNamespaceManager($answerFile.NameTable)
        $ns.AddNamespace("ns", $AnswerFile.DocumentElement.NamespaceURI)
        $ComputerName = $AnswerFile.SelectSingleNode('/ns:unattend/ns:settings[@pass="specialize"]/ns:component[@name="Microsoft-Windows-Shell-Setup"]/ns:ComputerName', $ns)
        $ComputerName.InnerText = $InstanceName
        $AnswerFile.Save($AnswerFilePath)
        Write-host "[Unattend] ComputerName is added."
    }else{
        Write-host "[Unattend] Unable to Set Instance Name"
    }
    Write-host "[BootMGR] Setting 0 Timeout to Boot Manager"
    Invoke-Command -Command { bcdedit.exe /set "{bootmgr}" timeout 0 }    
}
Catch {
    Write-Host $_
}
Finally
{   
    Write-host "[Start-up] Starting OOBE Setup"
    Start-Process C:\windows\system32\oobe\windeploy.exe -Wait
    Stop-Transcript
}