ansible从1.7的测试版开始支持windows版本了,本人不是专业搞运维的,我是搞开发的,小小的研究了一下通过ansible连接远程linux和windows进行一系列的操作!
本文主要是说明一下通过ansible连接windows的配置详解,我发现国内讲解的ansible连接windows的资源挺少的,研究了3、4天都没搞定,最后我还是通过翻墙,去国外的网页才找到解决方法的,真心不容易啊(本人菜鸟,大神勿喷)! 我也只是想自己记下来,方便自己,方便大家!言归正传...
windows上需要把powershell从2.0升级到3.0以上,这是官网说的!下面是升级的脚本,首先启动powershell必须是用超管权限启动,然后 set-ExecutionPolicy RemoteSigned ,以后才能正确执行下面的脚本(脚本随便放哪都行,找到放置的对应路径就行)
# Powershell script to upgrade a PowerShell 2.0 system to PowerShell 3.0
# based on http://occasionalutility.blogspot.com/2013/11/everyday-powershell-part-7-powershell.html
#
# some Ansible modules that may use Powershell 3 features, so systems may need
# to be upgraded. This may be used by a sample playbook. Refer to the windows
# documentation on docs.ansible.com for details.
#
# - hosts: windows
# tasks:
# - script: upgrade_to_ps3.ps1
# Get version of OS
# 6.0 is 2008
# 6.1 is 2008 R2
# 6.2 is 2012
# 6.3 is 2012 R2
if ($PSVersionTable.psversion.Major -ge 3)
{
write-host "Powershell 3 Installed already; You don't need this"
Exit
}
$powershellpath = "C:\powershell"
function download-file
{
param ([string]$path, [string]$local)
$client = new-object system.net.WebClient
$client.Headers.Add("user-agent", "PowerShell")
$client.downloadfile($path, $local)
}
if (!(test-path $powershellpath))
{
New-Item -ItemType directory -Path $powershellpath
}
# .NET Framework 4.0 is necessary.
#if (($PSVersionTable.CLRVersion.Major) -lt 2)
#{
# $DownloadUrl = "http://download.microsoft.com/download/B/A/4/BA4A7E71-2906-4B2D-A0E1-80CF16844F5F/dotNetFx45_Full_x86_x64.exe"
# $FileName = $DownLoadUrl.Split('/')[-1]
# download-file $downloadurl "$powershellpath\$filename"
# ."$powershellpath\$filename" /quiet /norestart
#}
#You may need to reboot after the .NET install if so just run the script again.
# If the Operating System is above 6.2, then you already have PowerShell Version > 3
if ([Environment]::OSVersion.Version.Major -gt 6)
{
write-host "OS is new; upgrade not needed."
Exit
}
$osminor = [environment]::OSVersion.Version.Minor
$architecture = $ENV:PROCESSOR_ARCHITECTURE
if ($architecture -eq "AMD64")
{
$architecture = "x64"
}
else
{
$architecture = "x86"
}
if ($osminor -eq 1)
{
$DownloadUrl = "http://download.microsoft.com/download/E/7/6/E76850B8-DA6E-4FF5-8CCE-A24FC513FD16/Windows6.1-KB2506143-" + $architecture + ".msu"
}
elseif ($osminor -eq 0)
{
$DownloadUrl = "http://download.microsoft.com/download/E/7/6/E76850B8-DA6E-4FF5-8CCE-A24FC513FD16/Windows6.0-KB2506146-" + $architecture + ".msu"
}
else
{
# Nothing to do; In theory this point will never be reached.
Exit
}
$FileName = $DownLoadUrl.Split('/')[-1]
download-file $downloadurl "$powershellpath\$filename"
write-host "$powershellpath\$filename"
Start-Process -FilePath "$powershellpath\$filename" -ArgumentList /quiet
执行完了之后,需要重启电脑(自动),然后可以使用get-host查看是否成功升级!
如果升级成功,继续执行下面的配置winrm的脚本
# Configure a Windows host for remote management with Ansible
# -----------------------------------------------------------
#
# This script checks the current WinRM/PSRemoting configuration and makes the
# necessary changes to allow Ansible to connect, authenticate and execute
# PowerShell commands.
#
# Set $VerbosePreference = "Continue" before running the script in order to
# see the output messages.
#
# Written by Trond Hindenes <trond@hindenes.com>
# Updated by Chris Church <cchurch@ansible.com>
#
# Version 1.0 - July 6th, 2014
# Version 1.1 - November 11th, 2014
Param (
[string]$SubjectName = $env:COMPUTERNAME,
[int]$CertValidityDays = 365,
$CreateSelfSignedCert = $true
)
Function New-LegacySelfSignedCert
{
Param (
[string]$SubjectName,
[int]$ValidDays = 365
)
$name = New-Object -COM "X509Enrollment.CX500DistinguishedName.1"
$name.Encode("CN=$SubjectName", 0)
$key = New-Object -COM "X509Enrollment.CX509PrivateKey.1"
$key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
$key.KeySpec = 1
$key.Length = 1024
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
$key.MachineContext = 1
$key.Create()
$serverauthoid = New-Object -COM "X509Enrollment.CObjectId.1"
$serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
$ekuoids = New-Object -COM "X509Enrollment.CObjectIds.1"
$ekuoids.Add($serverauthoid)
$ekuext = New-Object -COM "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
$ekuext.InitializeEncode($ekuoids)
$cert = New-Object -COM "X509Enrollment.CX509CertificateRequestCertificate.1"
$cert.InitializeFromPrivateKey(2, $key, "")
$cert.Subject = $name
$cert.Issuer = $cert.Subject
$cert.NotBefore = (Get-Date).AddDays(-1)
$cert.NotAfter = $cert.NotBefore.AddDays($ValidDays)
$cert.X509Extensions.Add($ekuext)
$cert.Encode()
$enrollment = New-Object -COM "X509Enrollment.CX509Enrollment.1"
$enrollment.InitializeFromRequest($cert)
$certdata = $enrollment.CreateRequest(0)
$enrollment.InstallResponse(2, $certdata, 0, "")
# Return the thumbprint of the last installed cert.
Get-ChildItem "Cert:\LocalMachine\my"| Sort-Object NotBefore -Descending | Select -First 1 | Select -Expand Thumbprint
}
# Setup error handling.
Trap
{
$_
Exit 1
}
$ErrorActionPreference = "Stop"
# Detect PowerShell version.
If ($PSVersionTable.PSVersion.Major -lt 3)
{
Throw "PowerShell version 3 or higher is required."
}
# Find and start the WinRM service.
Write-Verbose "Verifying WinRM service."
If (!(Get-Service "WinRM"))
{
Throw "Unable to find the WinRM service."
}
ElseIf ((Get-Service "WinRM").Status -ne "Running")
{
Write-Verbose "Starting WinRM service."
Start-Service -Name "WinRM" -ErrorAction Stop
}
# WinRM should be running; check that we have a PS session config.
If (!(Get-PSSessionConfiguration -Verbose:$false) -or (!(Get-ChildItem WSMan:\localhost\Listener)))
{
Write-Verbose "Enabling PS Remoting."
Enable-PSRemoting -Force -ErrorAction Stop
}
Else
{
Write-Verbose "PS Remoting is already enabled."
}
# Make sure there is a SSL listener.
$listeners = Get-ChildItem WSMan:\localhost\Listener
If (!($listeners | Where {$_.Keys -like "TRANSPORT=HTTPS"}))
{
# HTTPS-based endpoint does not exist.
If (Get-Command "New-SelfSignedCertificate" -ErrorAction SilentlyContinue)
{
$cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME -CertStoreLocation "Cert:\LocalMachine\My"
$thumbprint = $cert.Thumbprint
}
Else
{
$thumbprint = New-LegacySelfSignedCert -SubjectName $env:COMPUTERNAME
}
# Create the hashtables of settings to be used.
$valueset = @{}
$valueset.Add('Hostname', $env:COMPUTERNAME)
$valueset.Add('CertificateThumbprint', $thumbprint)
$selectorset = @{}
$selectorset.Add('Transport', 'HTTPS')
$selectorset.Add('Address', '*')
Write-Verbose "Enabling SSL listener."
New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset
}
Else
{
Write-Verbose "SSL listener is already active."
}
# Check for basic authentication.
$basicAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where {$_.Name -eq "Basic"}
If (($basicAuthSetting.Value) -eq $false)
{
Write-Verbose "Enabling basic auth support."
Set-Item -Path "WSMan:\localhost\Service\Auth\Basic" -Value $true
}
Else
{
Write-Verbose "Basic auth is already enabled."
}
# Configure firewall to allow WinRM HTTPS connections.
$fwtest1 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS"
$fwtest2 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" profile=any
If ($fwtest1.count -lt 5)
{
Write-Verbose "Adding firewall rule to allow WinRM HTTPS."
netsh advfirewall firewall add rule profile=any name="Allow WinRM HTTPS" dir=in localport=5986 protocol=TCP action=allow
}
ElseIf (($fwtest1.count -ge 5) -and ($fwtest2.count -lt 5))
{
Write-Verbose "Updating firewall rule to allow WinRM HTTPS for any profile."
netsh advfirewall firewall set rule name="Allow WinRM HTTPS" new profile=any
}
Else
{
Write-Verbose "Firewall rule already exists to allow WinRM HTTPS."
}
# Test a remoting connection to localhost, which should work.
$httpResult = Invoke-Command -ComputerName "localhost" -ScriptBlock {$env:COMPUTERNAME} -ErrorVariable httpError -ErrorAction SilentlyContinue
$httpsOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$httpsResult = New-PSSession -UseSSL -ComputerName "localhost" -SessionOption $httpsOptions -ErrorVariable httpsError -ErrorAction SilentlyContinue
If ($httpResult -and $httpsResult)
{
Write-Verbose "HTTP and HTTPS sessions are enabled."
}
ElseIf ($httpsResult -and !$httpResult)
{
Write-Verbose "HTTP sessions are disabled, HTTPS session are enabled."
}
ElseIf ($httpResult -and !$httpsResult)
{
Write-Verbose "HTTPS sessions are disabled, HTTP session are enabled."
}
Else
{
Throw "Unable to establish an HTTP or HTTPS remoting session."
}
Write-Verbose "PS Remoting has been successfully configured for Ansible."
执行成功之后,在执行 winrm quickconfig或winrm qc 查看winrm是否开启成功!(网络必须设置私密网络--比如是家庭网络,不要是公共网络,在网络中心设置)
1 | WinRM service is already running on this machine. |
2 | WinRM is already set up for remote management on this computer. |
PS
C:\Users\Administrator> winrm
set
winrm/config/service/auth
'@{Basic="true"}'
结果:
Auth Basic = true Kerberos = true Negotiate = true Certificate = false CredSSP = false CbtHardeningLevel = Relaxed
在执行:
PS C:\Users\Administrator> winrm set winrm/config/service '@{AllowUnencrypted="true"}' Service RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD) MaxConcurrentOperations = 4294967295 MaxConcurrentOperationsPerUser = 1500 EnumerationTimeoutms = 240000 MaxConnections = 300 MaxPacketRetrievalTimeSeconds = 120 AllowUnencrypted = true Auth Basic = true Kerberos = true Negotiate = true Certificate = false CredSSP = false CbtHardeningLevel = Relaxed DefaultPorts HTTP = 5985 HTTPS = 5986 IPv4Filter = * IPv6Filter = * EnableCompatibilityHttpListener = false EnableCompatibilityHttpsListener = false CertificateThumbprint AllowRemoteAccess = true
最后查看:
PS C:\Users\Administrator> winrm get winrm/config Config MaxEnvelopeSizekb = 500 MaxTimeoutms = 60000 MaxBatchItems = 32000 MaxProviderRequests = 4294967295 Client NetworkDelayms = 5000 URLPrefix = wsman AllowUnencrypted = false Auth Basic = true Digest = true Kerberos = true Negotiate = true Certificate = true CredSSP = false DefaultPorts HTTP = 5985 HTTPS = 5986 TrustedHosts = * Service RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD) MaxConcurrentOperations = 4294967295 MaxConcurrentOperationsPerUser = 1500 EnumerationTimeoutms = 240000 MaxConnections = 300 MaxPacketRetrievalTimeSeconds = 120 AllowUnencrypted = true Auth Basic = true Kerberos = true Negotiate = true Certificate = false CredSSP = false CbtHardeningLevel = Relaxed DefaultPorts HTTP = 5985 HTTPS = 5986 IPv4Filter = * IPv6Filter = * EnableCompatibilityHttpListener = false EnableCompatibilityHttpsListener = false CertificateThumbprint AllowRemoteAccess = true Winrs AllowRemoteShellAccess = true IdleTimeout = 7200000 MaxConcurrentUsers = 10 MaxShellRunTime = 2147483647 MaxProcessesPerShell = 25 MaxMemoryPerShellMB = 1024 MaxShellsPerUser = 30至此,windows上设置完成了!
Linux ansible的设置:
Linux上需要装pip install http://github.com/diyan/pywinrm/archive/master.zip
#egg=pywinrm
执行:sed
-i.bak
'90s/exc\.args\[0\]/exc/'
/usr/lib/python2.7/site-packages/ansible/runner/connection_plugins/winrm.py
或
sed
-i.bak
'90s/exc\.args\[0\]/exc/'
/Library/Python/2.7/site-packages/ansible/runner/connection_plugins/winrm.py
我执行的是上面的。
ansible方面的inventory设定为以下的指定(ansible的hosts文件):
[windows] ec2_windows ansible_ssh_host=54.64.xxx.xxx ansible_ssh_user=Administrator ansible_ssh_pass=XXXXXXXXX ansible_ssh_port=5985 ansible_connection=winrm或者
192.168.1.202
[ windows:vars]
ansible_ssh_user=Administrator
ansible_ssh_pass=zlhXXX
ansible_connection=winrm
至于端口号:默认是5986的是https的 5985是http的。
执行:
ansible -m win_ping ec2_windows -vvvv (这是第一种配置的执行方法)
ansible windows -m win_ping -vvvv(这是第二种的执行方法)
执行结果是:
<192.168.1.202> ESTABLISH WINRM CONNECTION FOR USER: Administrator on PORT 5985 TO 192.168.1.202 <192.168.1.202> WINRM CONNECT: transport=plaintext endpoint=https://192.168.1.202:5986/wsman <192.168.1.202> REMOTE_MODULE win_ping <192.168.1.202> EXEC (New-Item -Type Directory -Path $env:temp -Name "ansible-tmp-1444796031.59-153566134111940").FullName | Write-Host -Separator ''; <192.168.1.202> WINRM EXEC 'PowerShell' ['-NoProfile', '-NonInteractive', '-EncodedCommand', 'KABOAGUAdwAtAEkAdABlAG0AIAAtAFQAeQBwAGUAIABEAGkAcgBlAGMAdABvAHIAeQAgAC0AUABhAHQAaAAgACQAZQBuAHYAOgB0AGUAbQBwACAALQBOAGEAbQBlACAAIgBhAG4AcwBpAGIAbABlAC0AdABtAHAALQAxADQANAA0ADcAOQA2ADAAMwAxAC4ANQA5AC0AMQA1ADMANQA2ADYAMQAzADQAMQAxADEAOQA0ADAAIgApAC4ARgB1AGwAbABOAGEAbQBlACAAfAAgAFcAcgBpAHQAZQAtAEgAbwBzAHQAIAAtAFMAZQBwAGEAcgBhAHQAbwByACAAJwAnADsA'] <192.168.1.202> WINRM RESULT <Response code 0, out "C:\Users\Administrat", err ""> <192.168.1.202> PUT /tmp/tmp8PjxZU TO C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1444796031.59-153566134111940\\win_ping <192.168.1.202> WINRM PUT /tmp/tmp8PjxZU to C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1444796031.59-153566134111940\\win_ping.ps1 (offset=0 size=2030) <192.168.1.202> WINRM PUT /tmp/tmp8PjxZU to C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1444796031.59-153566134111940\\win_ping.ps1 (offset=2030 size=2030) <192.168.1.202> WINRM PUT /tmp/tmp8PjxZU to C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1444796031.59-153566134111940\\win_ping.ps1 (offset=4060 size=2030) <192.168.1.202> WINRM PUT /tmp/tmp8PjxZU to C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1444796031.59-153566134111940\\win_ping.ps1 (offset=6090 size=443) <192.168.1.202> PUT /tmp/tmpghzyfZ TO C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1444796031.59-153566134111940\\arguments <192.168.1.202> WINRM PUT /tmp/tmpghzyfZ to C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1444796031.59-153566134111940\\arguments (offset=0 size=2) <192.168.1.202> EXEC PowerShell -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -File C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1444796031.59-153566134111940\\win_ping.ps1 C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1444796031.59-153566134111940\\arguments; Remove-Item "C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1444796031.59-153566134111940\" -Force -Recurse; <192.168.1.202> WINRM EXEC 'PowerShell' ['-NoProfile', '-NonInteractive', '-EncodedCommand', 'UABvAHcAZQByAFMAaABlAGwAbAAgAC0ATgBvAFAAcgBvAGYAaQBsAGUAIAAtAE4AbwBuAEkAbgB0AGUAcgBhAGMAdABpAHYAZQAgAC0ARQB4AGUAYwB1AHQAaQBvAG4AUABvAGwAaQBjAHkAIABVAG4AcgBlAHMAdAByAGkAYwB0AGUAZAAgAC0ARgBpAGwAZQAgAEMAOgBcAFUAcwBlAHIAcwBcAEEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIAXABBAHAAcABEAGEAdABhAFwATABvAGMAYQBsAFwAVABlAG0AcABcAGEAbgBzAGkAYgBsAGUALQB0AG0AcAAtADEANAA0ADQANwA5ADYAMAAzADEALgA1ADkALQAxADUAMwA1ADYANgAxADMANAAxADEAMQA5ADQAMABcAFwAdwBpAG4AXwBwAGkAbgBnAC4AcABzADEAIABDADoAXABVAHMAZQByAHMAXABBAGQAbQBpAG4AaQBzAHQAcgBhAHQAbwByAFwAQQBwAHAARABhAHQAYQBcAEwAbwBjAGEAbABcAFQAZQBtAHAAXABhAG4AcwBpAGIAbABlAC0AdABtAHAALQAxADQANAA0ADcAOQA2ADAAMwAxAC4ANQA5AC0AMQA1ADMANQA2ADYAMQAzADQAMQAxADEAOQA0ADAAXABcAGEAcgBnAHUAbQBlAG4AdABzADsAIABSAGUAbQBvAHYAZQAtAEkAdABlAG0AIAAiAEMAOgBcAFUAcwBlAHIAcwBcAEEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIAXABBAHAAcABEAGEAdABhAFwATABvAGMAYQBsAFwAVABlAG0AcABcAGEAbgBzAGkAYgBsAGUALQB0AG0AcAAtADEANAA0ADQANwA5ADYAMAAzADEALgA1ADkALQAxADUAMwA1ADYANgAxADMANAAxADEAMQA5ADQAMABcACIAIAAtAEYAbwByAGMAZQAgAC0AUgBlAGMAdQByAHMAZQA7AA=='] <192.168.1.202> WINRM RESULT <Response code 0, out "{ "changed": f", err ""> 192.168.1.202 | success >> { "changed": false, "ping": "pong" }
哈哈 OK,成功了!
希望可以给很多一些帮助吧!(本人第一次发的博客,还请多多指点!)