以下の内容はhttps://tech.guitarrapc.com/entry/2016/08/03/045127より取得しました。


PowerShell 5.0 (WMF5) における PULL Server 構築時のPSDesiredStateConfiguration_1.0 問題

最新情報

2016/8/6 WMF5.1 Previewで本件が修正されました。Windows 10 Anniversary Updateから確認ができます。

WMF5においては、ワークアラウンドを利用するしかないのでご注意ください。

以前の状況

WMF5がリリースされて数か月たちました。そろそろ皆様の環境もPowerShell 5.0に置き換わったころではないでしょうか? 特にDSCに関しては、これまでCIM Methodを直接たたかなくては操作ができなかった部分はCmdletで置き換えられています。また、ConfigurationIdも撤廃され、PULL ServerからPULL Nodeへのmof document配信も格段に楽になりました。

と、いいこと尽くめならいいのですが、まだまだ発展途上の技術です。バグも多くあります。ことごとく踏み抜いて対処してきましたが、1つ皆様の投票 (Vote) ご協力いただきたい事案があります。PowerShell TeamからUser Voiceを依頼されたので挙げましたが、投票数によって優先順位が変わるためPULL Serverをお使いの(予定も含めて)方はぜひスターください。

https://Windowsserver.uservoice.com/forums/301869-powershell/suggestions/15496698-minimumcompatibleversion-cause-cannot-find-module

概要

DSCをPULLで組んでおいたとしましょう。PULLクライアントがPULLサーバーからUpdate-DscConfigurationや定期Consistency Checkで最新mofを取得したときに、以下のエラーがおこりえます。

Cannot find module PSDesiredStateConfiguration_1.0 from the server https://DSCPull:8080/PSDSCPullServer.svc/Modules(ModuleName='PSDesiredStateConfiguration',ModuleVersion='1.0')/ModuleContent";

日本語でも、同様の意味で PSDesiredStateConfiguration_1.0 を PULL Server から 取得できません という内容です。

このエラーが出たが最後、このPULLクライアントは対処しない限り、Consistency Checkが実行できなくなります。つらい。

どのようなときにおこるのか

初めに、WMF5にしようとしている方が不安に思わないよう条件を明示します。

  • WMF4では起こりません
  • WMF5でもWMF4と全く同じConfigurationを使っていると起こりません

つまりタダのアップグレードなら発生しません。やったね。必ずしも起こるわけではなく、次の条件を満たしたときに発生します。

  • PULLクライアントがPULLサーバーからモジュールを取得する
  • Configurationで、PSDesiredStateConfigurationリソースを利用している
  • MinimumCompatibleVersionが2.0になっている

端的に言うと次の状況をすべて満たしたときに必ず発生します。

  • Import-DscResource -ModuleName PSDesiredStateConfiguration -ModuleVersion 1.1を明示していない
  • WMF 5で追加されたConfigurationのプロパティ、例えばPsDscRunAsCredentialを使う
  • PSDesiredStateConfigurationのいずれかのリソースを利用している
  • PSDesiredStateConfiguration以外のカスタムリソースを併用している
  • Configurationをネストしている
  • PULLモードを利用したPULLクライアントを利用している

何が問題なのか

少し説明しましょう。

Import-DscResource -ModuleName PSDesiredStateConfiguration -ModuleVersion 1.1を明示していない

PowerShell DSCを使っている方の多くは数10のConfigurationを用意して、それぞれで様々なリソースを利用するでしょう。しかし、Configurationで利用するリソースは、Import-DscResourceを使ってインポートしないと利用できません。*1

また、リソースはどんどんアップデートされるので、PULL Serverに最新リソースだけ配置することで、Import-DscResourceでリソースのバージョンを明示せず最新版のみを自動的に使うようにするのではないでしょうか。*2

ここはいいのです。当然のユーザーシナリオです。

問題の始まりは、 WMF5 にはPSDesiredStateConfiguration 1.1 しかないにも関わらず、Import-DscResource -ModuleName PSDesiredStateConfigurationをしただけ/あるいは明示しなかった場合、mof document は ModuleVersion 1.0 となる ことにあります。

順に見てみましょう。まず、Get-DscResourceをすると、PSDesiredStateConfiguration1.1 とわかります。

https://gist.github.com/guitarrapc/e067c965ca0af4ce7184ab493b2595f0

次に、PSDesiredStateConfigurationのWindowsFeatureリソースを使った簡単なConfigurationを書き、mofにコンパイルすると次の結果が得られます。

https://gist.github.com/guitarrapc/17c0697243d0d48b1fbfe93eb20a59dc

コンパイルされたmofのPSDesiredStateConfigurationの下にある、PSDesiredStateConfigurationを見てください。1.0になっていますね。

通常のリソースでは、mofで利用したリソースのバージョンが出力されます。たとえば、一覧にあったGraniResourceは3.7.8.1なのでImport-DscResource -ModuleName GraniResourceとするとModuleVersionは3.7.8.1がmofにも出ます。当然です。ここを見てPULLノードはサーバーに取得依頼するモジュールバージョンを決定しているので、mofのModuleVersionは、Configurationからmofをコンパイル時に利用したバージョンと厳密に一致するです。

WMF 5 で追加された Configuration のプロパティ、例えばPsDscRunAsCredentialを使う

先ほどのModuleVersionの明示がなくても、MinimumCompatibleVersionが1.0のうちは問題ありません。1.0はつまりWMF4と同様の機能しか使っていないことを示します。この場合、「PSDesiredStateConfigurationに限ってModuleVersionが1.0とPULLクライアントに存在しなくてもPULLServerに問い合わせへ行かずエラーが発生しない」という挙動をします。

しかし、MinimumCompatibleVersionが2.0になると話は変わります。「PSDesiredStateConfigurationも、他のリソース同様にPULLクライアントに無いModuleVersion 1.0が提示されたため、PULLServerに問い合わせますが、PULL ServerもWMF5なので1.1のモジュールしかなくエラーで終わる」という挙動に変わり、PULLクライアントが永遠にPULLを開始できない状況になります。

さて、MinimumCompatibleVersionが2.0になる条件が、WMF5で追加されたConfigurationの追加プロパティ、「PsDscRunAsCredentialを使う」などといったことです。通常DSCの実行はSYSTEMアカウントですが、PsDscRunAsCredential を使うと指定したユーザープロファイルで動作します。素晴らしいプロパティです。使いどころによっては、これまでのプロファイルを横断する方法をとらなくて済むので最高ですが、まさかこんな落とし穴が。

https://gist.github.com/guitarrapc/74824d0f89db0254e45fc43c33b688d0

なお、PSDesiredStateConfigurationリソースでPsDscRunAsCredentialを使うと、ModuleVersionが0.0になり問題は回避できます。ただし、無駄に指定が必要ですが。

PSDesiredStateConfiguration のいずれかのリソースを利用している

問題は、PSDesiredStateConfigurationと、そのほかのカスタムリソースの併用で起こります。さて、先日の記事でも書きましたが、xPSDesiredStateConfigurationモジュールは、ビルトインのPSDesiredStateConfigurationモジュールの機能も移植して機能改善を高品質、高速に回そうとしています。

https://tech.guitarrapc.com/entry/2016/06/29/015813

https://github.com/PowerShell/xPSDesiredStateConfiguration

さて、今回の問題はPSDesiredStateConfiguraionのリソースを使うと発生します。この中でPSDesiredStateConfiguraionを除いて*3 xPSDesiredStateConfigurationモジュールのxリソースに置き換えられます。

逆にいうと、Fileリソースを利用している場合は、遭遇してしまう可能性があるということです。

Configurationをネストしている

これまでの条件をすべて満たすConfigurationのネストで発生します。具体的には次のようなものです。

https://gist.github.com/guitarrapc/fdb37527d4a97a8042e8cd7c971ce4ac

ここまでの事例のいずれかのみを満たすだけなら問題は発生しません。

単純なConfiguration

https://gist.github.com/guitarrapc/b69d8105b1909fbbe82b3b68bed48b20

PsDscRunAsCredentialの利用

https://gist.github.com/guitarrapc/4d6d42f1c5fec2e1da33725e56ea90cb

同一Configurationでの指定

https://gist.github.com/guitarrapc/ca7e9a813685134a5e902426f9a58a9c

PSDesiredStateConfigurationのみのネスト

https://gist.github.com/guitarrapc/b55ca594afa50e75fe35a93373ed9341

PULL モードを利用した PULL クライアントを利用している

本件は、PUSHでは発生しません。PULLでのみ発生します。

一時対応 (Workaround)

問題が明確なので、一時対応も取れます。

PSDesiredStateConfiguraion を xPSDesiredStateConfiguraion で置き換える。

今後は、xPSDesiredStateConfiguraionを使うことを検討してください。WMF5なら、Import-Module xPSDesiredStateConfigurationで最新版を取得可能なのでいい感じででしょう。

唯一Fileリソースを使っている場合のみ次の方法をとって回避してください。

方法1. Import-DSCResource -ModuleName PSDesiredStateConfiguraion -ModuleVersion 1.1 を明示する

1つの方法は、先述したバージョンの明示です。これでmofのPSDesiredStateConfigurationバージョンがPULLクライアント (WMF5) の1.1と合致するので問題が回避できます。

ただし、WMF4とWMF5が混在する環境では、WMF4用のConfigurationとWMF5用のConfigurationで分ける必要があるため、後方互換性が失われます。

方法2. mof document の ModuleVersion を 0.0 に書き換える

先ほど、mofに書かれたPSDesiredStateConfiguraionのModuleVersionが1.1と言いました。実は、このModuleVersionを0.0にすると、PULLクライアントは自分が持っているリソースの最新バージョンを使おうとします。

これでいい場合は、mof生成後にパースかけて置き換えればいいでしょう。

しかし、本来mofは人が読む、操作することを前提にしていません。何しろmof生成のための糖衣構文こそがPowerShell DSCですから。本質ではないのです。

方法3. PSDesiredStateConfiguration の利用では必ず PsDscRunAsCredential を利用する

PsDscRunAsCredentialを使うと、PSDesiredStateConfigurationのModuleVersionが0.0になるのでこれでも回避できます。

https://gist.github.com/guitarrapc/c6dad2855b0efb16813b3d5c79c21e67

方法4. ネストを避ける

なるほどありえない。

根本解決の手段

mofを触るのが一番楽です。後方互換性もあります。しかし現状のImport-DscResourceはmofでModuleVersion 0.0を生成する方法を持っていません。そこで、根本解決として、Import-DscResourceImport-DscResource のパラメータ追加を提示しています。

これによって、Configurationからmofで利用するバージョンを0.0にする手段を得ることができ、柔軟性が高まる上、副作用もないはずです。

まとめ

ここまで読まれた方はまずいらっしゃらないでしょうが、これが問題の概要です。今後のConfigurationの書き心地、リソースの更新の負荷に大きくかかわるため、ぜひVoteをしていただけると嬉しいです。

https://Windowsserver.uservoice.com/forums/301869-powershell/suggestions/15496698-minimumcompatibleversion-cause-cannot-find-module

Voteが100件行けば即対応入る可能性が高いので、ぜひVoteしていただけると嬉しいです。意見などはUserVoiceに書いていただけるとPowerShell Teamに直で伝わります。

よろしくお願いします。

ちなみに私は、-ModuleVersionを明示しました。今後のWMF更新が鬱ですが仕方ない...。

*1:PSDesiredStateConfigurationに含まれる標準リソースを除く

*2:Import-DscResource -ModuleName GraniResource -ModuleVersion 3.7.8.1などと、バージョンを明示するするのは手間すぎてまずいない

*3:Groupもちょっとバグや挙動が変わるので今月のリリース待ち




以上の内容はhttps://tech.guitarrapc.com/entry/2016/08/03/045127より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14