在 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 看起来是正确的。让我们尝试调试它。让我们隔离问题并查看它的脚本问题还是其他问题。
- 尝试远程登录 169.254.169.254 80
是否显示已连接
- 也可以在浏览器上尝试 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
}
我正在使用一些基于 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 看起来是正确的。让我们尝试调试它。让我们隔离问题并查看它的脚本问题还是其他问题。
- 尝试远程登录 169.254.169.254 80
是否显示已连接
- 也可以在浏览器上尝试 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
}