tech.guitarrapc.cóm

Technical updates

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-modulewindowsserver.uservoice.com

目次

概要

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 とわかります。

gist.github.com

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

gist.github.com

コンパイルされた mof の PSDesiredStateConfiguration の下にある、ModuleVersion を見てください。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 を使うと指定したユーザープロファイルで動作します。素晴らしいプロパティです。使いどころによっては、これまでのプロファイルを横断する方法をとらなくて済むので最高ですが、まさかこんな落とし穴が。

gist.github.com

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

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

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

tech.guitarrapc.com

github.com

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

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

Configurationをネストしている

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

gist.github.com

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

単純な Configuration

gist.github.com

PsDscRunAsCredentialの利用

gist.github.com

同一 Configuration での指定

gist.github.com

PSDesiredStateConfiguration のみの ネスト

gist.github.com

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 になるのでこれでも回避できます。

gist.github.com

方法4. ネストを避ける

なるほどありえない。

根本解決の手段

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

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

まとめ

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

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

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

よろしくお願いします。

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

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

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

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