Azure に、Windows Server 2016 TP3 の仮想マシンを 2 台構築し、それをローカルから Invoke-Command でワークグループクラスターを構築しようとした際の思い出を。
リモートでコマンドを実行するためにいろいろと設定していたり、並列で実行できる個所を直列で実行していたりと「それ、ぎたぱそせんせーの valentia つかえばよかったのでは」と思う方もいるかもしれませんが、必要な設定を自分で試して勉強しておきたかったので、えっちらおっちら、一つずつやってみました。
今回は、以下のような環境に対して、ワークグループクラスターを設定しています。
Azureの仮想マシンへリモートでコマンドを投げる で証明書を取り込んでコマンドを実行する方法を紹介されていますが、今回は省エネで「-SkipCACheck」で実行しています。
Azure の仮想マシンにたいしては、SSL を使用した WinRM の接続ができますが、使用されている証明書は自己署名のものですので、証明書をローカルストアに取り込んでいない場合は、Invoke-Command で UseSSL を使用するだけでは、以下のようなエラーとなりますので、これを証明書を取り込まずに回避するために、SkipCACheck を指定しています。
本来は証明書を取り込んだ方がよいかと思いますが、今回は検証のためオプション設定で回避しています。
[hogehoge.cloudapp.net] リモート サーバー hogehoge.cloudapp.net への接続に失敗し、次のエラー メッセージが返されました: 宛先のコンピューター (hogehoge.cloudapp.net:18752) のサーバー証明書に次のエラーがあります:
SSL 証明書が不明の証明機関によって署名されています。詳細については、about_Remote_Troubleshooting のヘルプ トピックを参照してください。
+ CategoryInfo : OpenError: (hogehoge.cloudapp.net:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : 12175,PSSessionStateBroken
それでは、WSFC-01/02 にコマンドを実行して、クラスターの役割を追加したいと思います。
実行したコマンドがこちらです。
$script = { if((Get-WindowsFeature -Name Failover-Clustering).InstallState -ne "Installed"){ Install-WindowsFeature -Name Failover-Clustering -IncludeManagementTools }else{ Write-Output "Failover-Clustering Feature has Installed" } $PSFile = "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\FailoverClusters\Microsoft.FailoverClusters.PowerShell.psm1" if(Test-Path $PSFile){ $PSFileACL = (Get-ACL -Path $PSFile) $CurrentACL = New-Object -TypeName System.Security.Principal.NTAccount($PSFileACL.Owner) $AdminACL = New-Object -TypeName System.Security.Principal.NTAccount("BUILTIN\Administrators") $AdminFull = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule($AdminACL, [System.Security.AccessControl.FileSystemRights]::FullControl, [System.Security.AccessControl.InheritanceFlags]::None , [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow) $PSFileACL.SetOwner($AdminACL) $PSFileacl.AddAccessRule($AdminFull) Set-ACL -Path $PSFile -AclObject $PSFileACL Copy-Item $PSFile "$(Split-Path -Path $PSFile -Parent)\$([System.IO.Path]::GetFileNameWithoutExtension($PSFile))_old.psm1" $PSContent = Get-Content $PSFile $PSContent[73] = @' $Message = $Message + " - cmdlet was cancelled" '@ $PSContent[95] = @' ShowError("Wrong OS Version - Need at least Windows Server 2012 R2 or Windows 8.1. You are running '" + $OS.Name + "'") '@ Set-Content -Path $PSFile -Value $PSContent -Encoding Unicode $PSFileACL.SetOwner($CurrentACL) Set-ACL -Path $PSFile -AclObject $PSFileACL }else{ Write-Output "$PSFile not existing" } } $cred = Get-Credential $Port = @(18752,52631) $Port | foreach{Invoke-Command -ComputerName hogehoge.cloudapp.net -Port $_ -UseSSL -Credential $cred -SessionOption (New-PSSessionOption -SkipCACheck) -ScriptBlock $script}
今回は、両サーバーともに同じアカウント名/パスワードで展開していますので、資格情報は手抜きで同じものを設定しています。
今回は英語のシステムロケール環境で実行しているため「Microsoft.FailoverClusters.PowerShell.psm1」の編集は不要なのですが、備忘録として入れてあります。
# TP3 特有の不具合かと思いますので、RTM したらいらないはずですが。
実行が終わると、両サーバーにクラスターの役割がインストールされた状態となります。
# オンプレミスのワークグループ環境で、SSL を使用しないで実行する場合は、「Set-Itemwsman:localhost\client\trustedhosts -value * -Force」のような TrustedHosts の設定も考慮する必要があるかと。
ワークグループクラスターでは DNS による両ノードの名前解決が必要となるため、DNS サフィックスの設定等が必要となりますが、Azure の仮想マシンで使用されている DHCP では DNS サフィックスも配布されており、名前解決がコンピューター名だけで実行できますので、DNS 関係についてひとまずデフォルトで進めています。
DNS サフィックスは以下のようなコマンドで確認できるかと。
$port | foreach{Invoke-Command -ComputerName hogehoge.cloudapp.net -Port $_ -UseSSL -Credential $cred -SessionOption (New-PSSessionOption -SkipCACheck) -ScriptBlock {Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "DNSDOmain <> NULL"}}
次にワークグループ環境でクラスターを構築します。
Azure 上でクラスターを構築する場合、DHCP で CNO を作成してしまうと、IP アドレスがローカルのアドレスと重複してしまい、IP のリソースをオンラインにすることができません。
そのため、現状、Azure で WSFC を構築する場合、クラスターで使用する IP アドレスは、未使用のものを固定で割り当てる必要があります。
Azure のコマンドレットを使用して未使用の IP アドレスを取得する場合は以下のようなコマンドを使用すると取得できるかと。
$StaticIP = (Test-AzureStaticVNetIP -VNetName "<仮想ネットワーク名>" -IPAddress 10.0.0.0).AvailableAddresses[0]
今回は、未使用なものを自分で設定して割り当ててしまいます。
それでは、以下のコマンドを実行してみます。
$StaticIP = "10.0.0.6" $Node = @("WSFC-01", "WSFC-02") $Session = New-PSSession -ComputerName hogehoge.cloudapp.net -Port $Port[0] -UseSSL -Credential $cred -SessionOption (New-PSSessionOption -SkipCACheck) Invoke-Command -Session $Session -ScriptBlock {New-Cluster -Name WSFC-CAP -StaticAddress $args[0] -node $args[1] -AdministrativeAccessPoint Dns} -ArgumentList $StaticIP,$Node
このコマンドでは、以下のようなエラーになるかと。
There was an error adding node ‘WSFC-02’ to the cluster
You do not have administrative privileges on the server ‘WSFC-02.HOGEHOGE.m3.internal.cloudapp.net’.
Attempted to perform an unauthorized operation.
+ CategoryInfo : PermissionDenied: (:) [New-Cluster], ClusterCmdletException
+ FullyQualifiedErrorId : UnauthorizedAccess,Microsoft.FailoverClusters.PowerShell.NewClusterCommand
+ PSComputerName : hogehoge.cloudapp.net
ポイントとなるのは、「You do not have administrative privileges」ですね。
「WSFC-01」 に対して、クラスターの新規作成のコマンドを実行していますが、クラスターに含めるノードである 「WSFC-02」 に対してのアクセスをしようとした際の資格情報でエラーとなっています。
今回は同一のユーザー名/パスワードでアクセスできる環境にしているのですが、WSFC-01 → WSFC-02 にアクセスする際のセカンドホップ (マルチホップ) でエラーになっていますね。
以下の情報を参考にして回避します。
Windows PowerShell: 次ホップを実行する
Enable PowerShell "Second-Hop" Functionality with CredSSP
Enabling Multihop Remoting
PowerShell の実行先のサーバー (WSFC-01) に対して、以下を実行します。
$Script = { Enable-WSManCredSSP -Role Server -Force } Invoke-Command -ComputerName hogehoge.cloudapp.net -Port $Port[0] -UseSSL -Credential $cred -SessionOption (New-PSSessionOption -SkipCACheck) -ScriptBlock $script
次に、PowreShell を実行している環境で以下を実行します。
Enable-WSManCredSSP -Role Client -DelegateComputer hogehoge.cloudapp.net -Force
PowerShell を実行している環境 (クライアント) で上記のコマンドを実行していない場合、
New-PSSession : [hogehoge.cloudapp.net] リモート サーバー hogehoge.cloudapp.net への接続に失敗し、次のエラー メッセージが返されました: WinRM クライアントは要求を処理できません。 現在のクライアント構成では、CredSSP 認証が無効にされています。 クライアント構成を変更して、もう一度要求してください。 CredSSP 認証はサーバー構成でも有効になっている必要があります。 また、グループ ポリシーを編集して、ターゲット コンピューターへの資格情報の委任を許可する必要があります。
gpedit.msc を使用して、[コンピューターの構成] -> [管理用テンプレート] -> [システム] -> [資格情報の委任] -> [新しい資格情報の委任を許可する] ポリシーを確認してください。 このポリシーが有効になっており、ターゲット コンピューターの適切な SPN を使用して構成されている必要があります。 たとえば、ターゲット コンピューター名が "myserver.domain.com" の場合、SPN は WSMAN/myserver.domain.com または WSMAN/*.domain.com のどちらかです。詳細に
ついては、about_Remote_Troubleshooting のヘルプ トピックを参照してください。
というようなメッセージが表示され、「-Authentication Credssp」は使用することができませんので、PowerShell を実行する側 / 実行される側の両方で設定をしておく必要があります。
これで、「-Authentication Credssp」を使用して接続する準備の一段階目が整いましたので、以下のコマンドを実行してみます。
$StaticIP = "10.0.0.6" $Node = @("WSFC-01", "WSFC-02") $Session = New-PSSession -ComputerName hogehoge.cloudapp.net -Port $Port[0] -UseSSL -Credential $cred -SessionOption (New-PSSessionOption -SkipCACheck) -Authentication Credssp Invoke-Command -Session $Session -ScriptBlock {New-Cluster -Name WSFC-CAP -StaticAddress $args[0] -node $args[1] -AdministrativeAccessPoint Dns} -ArgumentList $StaticIP,$Node
ここまでの設定で、エラーメッセージが以下のように変わるのですが、まだ実行することができないかと。
New-PSSession : [hogehoge.cloudapp.net] リモート サーバー hogehoge.cloudapp.net への接続に失敗し、次のエラー メッセージが返されました: WinRM クライアントは要求を処理できません。このユーザー資格情報をこのターゲット コンピューターに委任することは、ターゲット コンピューターが信頼されていないため、コンピューター ポリシーにより許可されません。 ターゲット コンピューターの ID を検証可能にするには、有効な証明書を使用するよう次のコマンドで WSMAN サービスを構成してください:
winrm set winrm/config/service ‘@{CertificateThumbprint="<拇印>"}’ または、イベント ビューアーを使用し、WSMAN/<コンピューターの FQDN> という SPN を作成できなかったことを示すイベントを確認してください。このイベントが記録されていた場合は、setspn.exe を使用して手動で SPN を作成できます。 該当する SPN が存在するにもかかわらず CredSSP で Kerberos を使用してターゲット コンピューターの ID を検証できない場合、ユーザー資格情報
をターゲット コンピューターに委任できるようにするには、gpedit.msc を使用し、[コンピューターの構成] -> [管理用テンプレート] -> [システム] -> [資格情報の委任] -> [NTLM のみのサーバー認証で新しい資格情報を許可する] ポリシーを確認してください。 このポリシーが有効になっており、ターゲット コンピューターの適切な SPN を使用して構成されている必要があります。 たとえば、ターゲット コンピューター名が "myserver.domain.com" の場合、SPN は WSMAN/myserver.domain.
com または WSMAN/*.domain.com のいずれかです。 これらの変更を行ってから、要求を再試行してください。詳細については、about_Remote_Troubleshooting のヘルプ トピックを参照してください。
最後の設定として、「NTLM のみのサーバー認証で新しい資格情報の委任を許可する」の設定を行います。
Setup WinRM & CredSSP
ポリシーとしては、「コンピューターの構成」→「管理用テンプレート」→「システム」→「資格情報の委任」の中にあるのですが、今回はレジストリを直接編集で。
# 今回は事前に登録されていないことを前提に設定をしていますが、本来は valentia で設定されているように、既存の登録も考慮する必要があります。
New-Item registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation\AllowFreshCredentialsWhenNTLMOnly New-ItemProperty registry::HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation\AllowFreshCredentialsWhenNTLMOnly -Name 1 -Value WSMAN/hogehoge.cloudapp.net -Type String
これで、以下のコマンドを実行してクラスターを構築することができるようになります。
$StaticIP = "10.0.0.6" $Node = @("WSFC-01", "WSFC-02") $Session = New-PSSession -ComputerName hogehoge.cloudapp.net -Port $Port[0] -UseSSL -Credential $cred -SessionOption (New-PSSessionOption -SkipCACheck) -Authentication Credssp Invoke-Command -Session $Session -ScriptBlock {New-Cluster -Name WSFC-CAP -StaticAddress $args[0] -node $args[1] -AdministrativeAccessPoint Dns} -ArgumentList $StaticIP,$Node
現状、CNO の IP アドレスを DNS に登録することができないため、クラスター名のリソースをオンラインにするのが失敗した状態になります。
その回避として、以下のコマンドを実行して、クラスター名のリソースをオフラインにしておきます。
Invoke-Command -ComputerName hogehoge.cloudapp.net -Port $Port[0] -UseSSL -Credential $cred -SessionOption (New-PSSessionOption -SkipCACheck) -ScriptBlock {Stop-ClusterResource -Name "Cluster Name"}
NIC のプロパティで DNS の登録を無効にすると仮想マシンのネットワークがダウンしてしまうようで、今のところ、コンピューター名リソースをオンラインにした状態で、DNS / NETBIOS のステータスチェックを回避するのが難しそうでした。
コンピューター名リソース以外はワークグループクラスターの基本的な部分は構築できそうでしたので、2016 が RTM した段階で、この辺の情報も出てくるかもしれないですね。