本エントリではPowerShell Core 6.1のPowerShell Remotingにおける改善点について解説します。
元ネタは上記のDocsで、現在こちらに対するまとめを作成しているのですが、PowerShell Remotingについては少しボリュームが増えたので本エントリで先出しします。
コンテナ向けPowerShell Directの改善
PowerShell Direct
PowerShell DirectはWindows10/Windows Server 2016以降で利用でき、ホストから仮想マシンおよびコンテナへネットワークを介さず直接接続する機能になります。
利用可能なホストOSではリモート操作系のコマンドレットに-VMName
、-VMId
、-VMGuid
、-ContainerId
のパラメーターが付いており、これらのパラメーターを指定することで直接ゲストに接続します。
# VM向けPowerShell Directの例 Invoke-Command -VMName TestVM -ScriptBlock { $PSVersionTable } -Credential $cred # コンテナ向けPowerShell Directの例 Invoke-Command -ContainerId 78438d708b648217899f600c3a0ac72b36814714a8a19d2f4bc03fbb08936519 -ScriptBlock { $PSVersionTable }
仕組みとしては、対VMの場合はHyper-V Socketを使った通信を行い、対コンテナの場合はHost Compute Service(HCS)のAPI(例えばHcsCreateProcess
など)を使ってコンテナ内部のPowerShellを起動したプロセス間通信を行っています。
PowerShell Core 6.1での改善
ここまでをふまえてPowerShell Core 6.1での改善点について説明します。
PowerShell Core 6.0までは対コンテナ向けのPowerShell Directで起動するPowerShellのプロセスはpowershell.exe
で決め打ちされていました。
対してPowerShell Core 6.1では、最初にpwsh.exe
の起動を試みpwsh.exe
が無ければpowershell.exe
を起動する様に改善されています。
例としてWindows Server 2019*1で以下のコマンドを試してみます。
予めdockerをインストールし、PowerShell Core 6.1をインストール済みのWindows Server Containerが起動された状態です。*2
# 起動しているコンテナの確認 docker ps # コンテナIDの取得 # ※起動しているコンテナが1つだけの前提 $containerId = (docker inspect $(docker ps -q) | ConvertFrom-Json).Id # PowerShell Directによるリモートコマンド実行 Invoke-Command -ContainerId $containerId -ScriptBlock { $PSVersionTable.PSVersion }
Windows PowerShellからこのコマンドを実行すると、結果のバージョンが5.1
とWindows PowerShell(powershell.exe
)が実行されていることが分かります。
対してPowerShell Core 6.1から実行すると、結果のバージョンが6.1.0
とPowerShell Core(pwsh.exe
)が起動され改善されていることがわかります。
ちなみに、対VMのPowerShell Directはこれまで通りデフォルト指定ではWindows PowerShellとの通信になり、PowerShell Coreと通信する場合は-ConfigurationName
パラメーターを明示してやる必要があります。
こちらについては次項で説明します。
余談1
PowerShell Core 6.1のリリースバージョンではコンテナ接続に関するバグ(#5794)があるため、この機能を試すには最新のmasterから自分でビルドする必要があります。
おそらく次のリリース(PowerShell Core 6.1.1)に取り込まれると思いますので、ビルド環境のない方はそれまでお待ちください。
【2019.04.23追記】
#5794の修正はPowerShell Core 6.2.0で反映されました。
【追記ここまで】
余談2
当初この点についてドキュメントの内容に疑念があったためIssueを上げたところ回答と改善をしてもらえました。
あまりいないとは思いますが改善前のドキュメントを見ている人向けの補足です。
PowerShell Remotingのエンドポイントがプレビュー版と分離されました
PowerShell Remotingのエンドポイント
普段意識することは少ないでしょうがPowerShell Remotingでは接続対象となるホストに接続先(エンドポイント)が存在します。
このエンドポイントはGet-PSSessionConfiguration
コマンドレットで確認でき、例えばWindows PowerShellにおいては下図の様に4つのエンドポイントがあることが分かります。*3
# 要管理者権限 # 接続される側のホストで実行する Get-PSSessionConfiguration
で、PowerShell CoreにおいてPowerShell Remotingを有効にした際のエンドポイントがどうなるかというと、バージョンによって何度か変遷しており、PowerShell Core 6.1では以下の2つのエンドポイントが作成されます。
PowerShell.6
: メジャーバージョンのみのエンドポイントPowerShell.6.x.y
: バージョンを厳密に指定したエンドポイント
Get-PSSessionConfiguration
で確認するとこんな感じです。
# 要管理者権限 # PowerShell Coreインストール時にPowerShell Remotingを有効にしてない場合に実行 Enable-PSRemoting # 接続される側のホストで実行する Get-PSSessionConfiguration
また、今後PowerShell Core 6.2に向けたプレビュー版でPowerShell Remotingを有効にした場合はプレビューバージョン向けの2つのエンドポイントが追加される予定となっています。
PowerShell.6-preview
: メジャーバージョンのみのエンドポイントPowerShell.6.x-preview.y
: バージョンを厳密に指定したエンドポイント
Name : PowerShell.6-preview PSVersion : 6.2 StartupScript : RunAsUser : Permission : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed Name : PowerShell.6.2-preview.1 PSVersion : 6.2 StartupScript : RunAsUser : Permission : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed
これにより安定版とプレビュー版のエンドポイントを分けて利用できるというのが今回の改善点になります。
接続する側の設定について
補足として接続する側について触れておきます。
接続する側はデフォルトでMicrosoft.Powershell
というエンドポイントが設定されており、これはWindows PowerShell/PowerShell Coreどちらでも変わりません。
このためPowerShell CoreからEnter-PSSession
などのコマンドレットを使ってリモート接続してもデフォルトではWindows PowerShellが利用されます。
PowerShell Coreに対してPowerShell Remotingで接続する場合は-ConfigurationName
パラメーターを使って接続するエンドポイントを明示してやる必要があります。
たとえばInvoke-Command
であれば以下の様にしてやります。
# リモートのPowerShell Core 6に接続する場合はエンドポイントを明示する $cred = Get-Credential Invoke-Command -ConputerName [Server Name] -Credential $cred -ScriptBlock { $PSVersionTable.PSVersion } -ConfigurationName 'PowerShell.6' # VM向けPowerShell Directでも同様 Invoke-Command -VMName [VM Name] -Credential $cred -ScriptBlock { $PSVersionTable.PSVersion } -ConfigurationName 'PowerShell.6'
PowerShell Remoting over SSHでuser@host:port形式の接続が可能になりました
ssh.exe
といったSSHクライアントで使われるuser@host:port
形式の接続がコマンドレットでもサポートされました。
PowerShell Remoting over SSHでは-HostName
パラメーターを使用して接続先を決めますが、ここに上記の形式を指定できます。
# Docsの例をそのまま引用 Enter-PSSession -HostName fooUser@ssh.contoso.com:2222