これは、アドベントカレンダー5日目の記事です。
4日目は、DSCの2つのモード PUSH、PULL と利用シーンを説明しました。
今日はDSCのエンジンについてずらっとみてみましょう。シンプルですが大事な機能なので抑えておきましょう。 [:contents]
Local Configuration Manager
DSCのエンジンは、 Local Configuration Manager (以下LCM)と呼びます。
DSCの挙動や現在の構成、定期実行などはすべてこのLCMが制御しているので一般にDSCのエンジンと称されます。
今回は、LCMについて以下を見ていきます。
- LCMのパラメータ状態を調べる
- LCMのパラメータを設定する
- MOFの競合を避ける方法
- v4とv5 (Preview) のパラメータ比較
LCM のパラメータ状態を調べる
まず現在のLCMにどんなパラメータが設定されているのか確認できないと話しになりません。管理者権限のPowerShellでGet-DscLocalConfigurationManagerを実行することでLCMに設定されている状態を確認できます。
Get-DscLocalConfigurationManager
PowerShell 4.0
まずはPowerShell 4.0の、何も設定していないLCM状態を見てみましょう。
$PSVersionTable Name Value ---- ----- PSVersion 4.0 WSManStackVersion 3.0 SerializationVersion 1.1.0.1 CLRVersion 4.0.30319.34014 BuildVersion 6.3.9600.17090 PSCompatibleVersions {1.0, 2.0, 3.0, 4.0} PSRemotingProtocolVersion 2.2 $ Get-DscLocalConfigurationManager AllowModuleOverwrite : False CertificateID : ConfigurationID : ConfigurationMode : ApplyAndMonitor ConfigurationModeFrequencyMins : 30 Credential : DownloadManagerCustomData : DownloadManagerName : RebootNodeIfNeeded : False RefreshFrequencyMins : 15 RefreshMode : PUSH PSComputerName :
これは、まだ何も構成していないWindows Server 2012 R2での実行結果です。
RefreshMode にある通り、PUSH モードがデフォルトです。
PowerShell v5 November Preview
PowerShell v5では、DSCが現在抱えるバグと使い勝手の悪さが改善されます。その肝になるポイントがLCMにも表れています。
最新のWMF5 November Previewで何も設定していないLCM状態をみてみましょう。
$PSVersionTable Name Value ---- ----- PSVersion 5.0.9814.0 WSManStackVersion 3.0 SerializationVersion 1.1.0.1 CLRVersion 4.0.30319.34014 BuildVersion 6.4.9814.0 PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} PSRemotingProtocolVersion 2.2 $ Get-DscLocalConfigurationManager AllowModuleOverWrite : False CertificateID : ConfigurationDownloadManagers : {} ConfigurationID : ConfigurationMode : ApplyAndMonitor ConfigurationModeFrequencyMins : 30 Credential : DebugMode : False DownloadManagerCustomData : DownloadManagerName : LCMCompatibleVersions : {1.0, 2.0} LCMState : Ready LCMVersion : 2.0 MaxPendingConfigRetryCount : StatusRetentionTimeInDays : 7 PartialConfigurations : {} RebootNodeIfNeeded : False RefreshFrequencyMins : 30 RefreshMode : PUSH ReportManagers : {} ResourceModuleManagers : {} PSComputerName :
細かいパラメータの意味を紹介する前に、LCMのパラメータを設定する方法を紹介します。
LCMのパラメータを設定する
LCMの設定には、コンフィグレーション構文を用います。*1
コンフィグレーション構文自体の説明は後日行うので、RebootIfNeededのパラメータだけRebootIfNeededからRebootIfNeededにする構成を書いてみましょう。
コードは次のようになります。
Configuration LCM { Node localhost { LocalConfigurationManager { RebootNodeIfNeeded = $true } } }
どうですか? Key/Valueで宣言されており、なんとなくでもやろうとしていることがわかります。
これを、自分自身のLCMに適用する流れを見てみましょう。
MOFの生成
コンフィグレーションを実行(コンパイル)してMOFファイルを生成します。
コードは次のようにLCM -OutputPath LCMを追加しました。
Configuration LCM { Node localhost { LocalConfigurationManager { RebootNodeIfNeeded = $true } } } LCM -OutputPath LCM
コンフィグレーションの実行は、 Configurationの後ろに書いた名称を指定します。(今回はLCMというコンフィグレーション名)
実行時のパラメータ-OutputPathに指定した値がポイントです。(今回はLCMを指定)
-OutputPathに指定した任意のパスがMOFファイルの生成先となります。
今回の場合、-OutputPathに指定した-OutputPathで現在のパスにフォルダが自動的に作成され、 Nodeに指定した名称の MOFファイル をフォルダ内に生成します。(-OutputPathが生成されました)
Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2014/12/05 23:41 826 localhost.meta.mof
meta.mofファイルは特殊なMOFファイルなのですが、説明は後述します。
MOF の適用
MOFファイルが生成できたら、対象のノード(今回は自分自身)のCIMに設定を指示します。
この時使うのが、Set-DscLocalConfigurationManager Cmdletです。状態取得がGetで、状態設定がSetです。
コードには、 Set-DscLocalConfigurationManager -Path LCMを追加しました。
Configuration LCM { Node localhost { LocalConfigurationManager { RebootNodeIfNeeded = $true } } } LCM -OutputPath LCM Set-DscLocalConfigurationManager -Path LCM
これで、コンフィグレーションがlocalhost(つまり自分)に設定されました。
LCM設定結果の確認
結果が変わったことを確認しましょう。
$ Get-DscLocalConfigurationManager AllowModuleOverwrite : False CertificateID : ConfigurationID : ConfigurationMode : ApplyAndMonitor ConfigurationModeFrequencyMins : 30 Credential : DownloadManagerCustomData : DownloadManagerName : RebootNodeIfNeeded : True RefreshFrequencyMins : 15 RefreshMode : PUSH PSComputerName :
コンフィグレーションで指定した通り変化しました。
| 変更前 | 変更後 |
|---|---|
RebootNodeIfNeeded : False |
RebootNodeIfNeeded : False |
これでLCMの構成は完了です。LocalConfiguration Managerの構成は、指定したパラメータのみ変更され他は維持されることを覚えておいて下さい。
リモートノードへの適用
自分自身でないノードが対象の場合は当然認証を渡す必要があります。(ADに参加しているサーバー同士なら不要です)
認証の渡し方には、2つ選択肢があります。
- CIMセッションの利用
- Credentialに認証を渡す
見ていきましょう。
CIMセッションの利用
CIMには、WSManを使ったリモートマネジメントプロトコルがあることは用語で説明しました。
以下のコードでCIMセッションを使ってリモートノード(10.0.0.10) にLCM設定が可能です。Set-DSCLocalConfigurationManagerの実行時にCredentialへ認証を渡してもいいのですが、valentiaを使っていない環境ではCIMを使うことを推奨します。*2
Configuration LCM { Node 10.0.0.10 { LocalConfigurationManager { RebootNodeIfNeeded = $true } } } LCM -OutputPath LCM $cim = New-CimSession -Credential (Get-Credential) -ComputerName 10.0.0.10 Set-DscLocalConfigurationManager -Path LCM -CimSession $cim
Credential に認証を渡す
認証方式を接続時に変更するなど特殊な操作をしない場合は、CIMセッションを一々作らずとも直接-Credentialに認証情報を渡すことも可能です。
Configuration LCM { Node 10.0.0.10 { LocalConfigurationManager { RebootNodeIfNeeded = $true } } } LCM -OutputPath LCM Set-DscLocalConfigurationManager -Path LCM -Credential (Get-Credential) -ComputerName 10.0.0.10
MOFの競合を避ける方法
リモートホストにLCMを適用する時には、Nodeに対象(リモートホストのIPやホスト名)を指定することで、コンフィグレーション実行時にノード名でMOFファイルが生成されます。
Set-DscLocalConfigurationManager実行時に、Set-DscLocalConfigurationManagerにMOFファイルを生成したフォルダを指定すると、「フォルダに存在するMOFファイルの中からノード名を含むMOFファイルが合致したものを適用」します。
Set-DscLocalConfigurationManager実行時に、Set-DscLocalConfigurationManagerやSet-DscLocalConfigurationManagerにMOFと合致するノードを指定することはとても大事です。
ComputerName を指定しなかった場合
Configuration LCM { Node 10.0.0.10 { LocalConfigurationManager { RebootNodeIfNeeded = $true } } } LCM -OutputPath LCM Set-DscLocalConfigurationManager -Path LCM -Credential (Get-Credential)
-Pathに存在する「全MOFファイル名のホスト」に対してLCMの適用します。
localhostだけにしか常にLCM設定をしないのなら問題ありません。が、もし以前に他ノードのMOFファイルを生成してあった場合は、Set-DscLocalConfigurationManager実行時に意図しないノードにもMOFの適用を試みることになります。
意図しない動作とならないように、MOFの競合に注意してください。
ComputerName を指定した場合
Configuration LCM { Node 10.0.0.10 { LocalConfigurationManager { RebootNodeIfNeeded = $true } } } LCM -OutputPath LCM Set-DscLocalConfigurationManager -Path LCM -Credential (Get-Credential) -ComputerName 10.0.0.10
-Pathに指定したフォルダから「Computer名に指定した名称のMOFファイルを探して」ノードに設定を試みます。
実行対象が限定されるので、大事大事。
無用な混乱を防ぐため
MOFがコンフィグレーションの実行で生成されるので、MOFの競合を意識しないとMOF地獄になります。
MOFの競合を避けるには、いくつかの手法があります。
Set-DSCLocalConfigurationManager実行後にMOFファイルを消すようにする- MOFファイルの生成先を(コンフィグレーションの
-OutputPath)をホストごとに指定して競合をさける Set-DscLocalConfigurationManagerを、DSCサーバーからノードに実行するのではなく、対象ノード自身で実行する
謎社の場合
LCMの構成時には、3を利用しています。
まっさらなインスタンスを生成時に、そのホスト自身に必要なLCMコンフィグレーションを自動的にダウンロード、実行することでMOFの競合が避けられます。
これにより、Nodeには常にlocalhostを指定するだけ、構成もシンプルに保つことができます。
他にも、valentiaを使うことで3を実現できます。
v4 と v5 (Preview) のパラメータ比較
LCMの状態確認、パラメータ設定方法がわかったところで、どんなパラメータがあるのかを見てみましょう。
LCMにはいくつかのパラメータがありますが、PUSHとPULLでは影響するものが違います。
今回の記事では、最新のv4とv5 Previewについて、LCMパラメータの有無(ある場合はデフォルト値)、PUSH/PULLそれぞれへの影響を比較していきます。
パラメータが存在しない場合は、-としておきます。
| LCM Parameter Name | v4 | v5 Nov Preview | PUSH | PULL |
|---|---|---|---|---|
| AllowModuleOverWrite | False | False | x | o |
| CertificateID | null | null | o | o |
| ConfigurationDownloadManagers | - | {} | x | o |
| ConfigurationID | null | null | x | o |
| ConfigurationMode | ApplyAndMonitor | ApplyAndMonitor | x | o |
| ConfigurationModeFrequencyMins | 30 | 30 | x | o |
| Credential | null | null | x | o |
| DebugMode | - | False | o | o |
| DownloadManagerCustomData | null | null | x | o |
| DownloadManagerName | - | null | x | o |
| LCMCompatibleVersions | - | {1.0, 2.0} | o | o |
| LCMState | - | Ready | o | o |
| LCMVersion | - | 2.0 | o | o |
| MaxPendingConfigRetryCount | - | null | o | o |
| StatusRetentionTimeInDays | - | 7 | o | o |
| PartialConfigurations | - | {} | x | o |
| RebootNodeIfNeeded | False | False | o | o |
| RefreshFrequencyMins | 30 | 30 | x | o |
| RefreshMode | PUSH | PUSH | o | o |
| ReportManagers | - | {} | x | o |
| ResourceModuleManagers | - | {} | x | o |
| PSComputerName | 実行された対象PCが表示 | 実行された対象PCが表示 | - | - |
どうでしょうか?
- LCMのバージョンなど多くの新パラメータがv5 (Preview)で追加
- PUSHに影響するパラメータは少ない
- PULLには全パラメータが影響
それでは、PUSH/PULL両方に影響するパラメータ、PUSH向けのパラメータ、PULL向けのパラメータを見ていきましょう。
なお、PowerShell 4.0におけるパラメータは以前 @ITへ寄稿した記事にある程度まとめています。今回も、改めてさらっと触れます。
https://www.atmarkit.co.jp/ait/articles/1407/24/news131.html
PUSH/PULL 両方に影響するパラメータ
まずは、PUSHとPULLの両方に影響するものがどれか見ておきましょう。
CertificateID
CertificateIDには。ノード/サーバーが利用する証明書の Thumbprintを指定します。
一般にパスワードなどは機密情報とされるのはご存知の通りです。広く使われる暗号化手法が証明書を利用した「信頼の担保」と「ハッシュ値による暗号化/復号化」です。
Windowsも証明書を利用した暗号化/復号化が一般的に用いられており、DSCでも[PSCredential]などは証明書で暗号化するのがベストプラクティスです。
DSCで利用される証明書の指定をするのが、CertificateIDです。
サンプルだと、こんなデータですね。*3
1847HFN47RGILJA3423ZEQR82346YS8UOIFW24K4
DebugMode (v5 で追加)
設定可能な値は、[bool]です。 DSCの動作モードをデバッグにするか、しないかの設定です。
- Trueを指定してデバッグにすることで、PUSHでノードに対してコンフィグレーションを適用する際にデバッグが可能
- パフォーマンス面などから、デバッグ時以外は FALSE にしておく
LCMState (v5 で追加)
ReadOnlyのパラメータです。設定はできません。
LCMは常に1つの状態しか持ちません。状態は、新しい構成を受付可能な アイドル状態と、構成を適用/取得中のビジー状態を遷移しています。
アイドル -> ビジー -> アイドル -> ビジー....
PowerShell 4.0におけるDSCでは、LCMの状態がビジーな最中にLCMへ問い合わせをすると必ず例外が吐かれます。結果、ノードだけでなく自分自身のLCMの状態を把握することも困難というさいてーな状態が発生しえます。*4
v5においては、LCMにLCMStateを持つことで、ビジーかどうかが判定可能になります。これはかなりプライオリティの高い問題なので大変重要です。
LCMVersion (v5 で追加 / 最新のv4 でもみれたり)
ReadOnlyのパラメータです。設定はできません。
3日ほど前に起動したWindows Server 2012 R2で、これまでになかったLCMVersionが取得できていました。*5そのためv5からではない。
LCMのバージョンは、DSCのコンフィグレーションの記述、LCMの持つパラメータの判断材料となります。
StatusRetentionTimeInDays (v5 で追加)
まだ詳細が公開されていないパラメータです。
名前からするとLCMの状態がロテートする間隔(日) のようですが。
RebootNodeIfNeeded
コンフィグレーションを実施した時に、リソースによっては適用時に再起動を求めるフラグを指定していることがあります。
RebootNodeIfNeededには[bool]で値を指定可能です。
- Trueを指定すると、コンフィグレーションの再起動が求められた場合に再起動
- Falseを指定すると、自動的な再起動を抑止
RefreshMode
設定可能な値は、PUSHかPUSHです。
そのノードのLCMが、PULLとして挙動するか、PUSHとして挙動するかはここに依存します。
- PUSHを指定するとPUSHモード
- PULLを指定するとPULLモード
RefreshModeの変更は、Set-DscLocalConfigurationManagerを実行するだけではだめで、Windows Management Instrumentationサービスの再起動が必要です。
さくっと行うなら、以下のサービス再起動を利用しましょう。
Get-Service Winmgmt | Restart-Service -Force
PULL に影響するパラメータ
続いてPULLでのみ影響するパラメータを見ていきます。
Credential
設定可能な値は、[PSCredential]です。
Credentialは、ノードがPULLサーバーに問い合わせする時、利用する認証情報となります。 PULLのDSCサーバーが、対象のノードを制限する時に使う認証と思ってください。 個人的には、認証よりIPアドレス制限などもっと根本で制御するか組み合わせます。Webサーバーのベストプラクティスと同様ですね。
AllowModuleOverWrite
設定可能な値は、[bool]です。 PUSHモードでは、コンフィグレーションで利用するリソースをコンフィグレーションの実施前に自分でそのノードに置いておく必要があります。そのためこのパラメータは関係しません。 一方でPULLモードでは、ノードはコンフィグレーションを実施する前に必要なリソース(PowerShellモジュールとしてかかれています)を一緒に取得します。
もっと新しいモジュールがサーバーに存在した場合、
- Trueを設定すると、ノードはサーバーから最新のモジュールを取得
- Falseを設定すると、ノードはサーバーから最新のモジュールを取得しない
このパラメーターは、最新のモジュールがあった場合はそれを取得する便利な機能です。 が、v4では挙動が怪しく、モジュールの最新バージョンを取得時にエラーが多発します。このバグは、v5で修正されています。
ConfigurationDownloadManagers/ResourceModuleManagers/ReportManagers (v5 で追加)
設定可能な値は、[CIMInstance[]]です。
v4とv6の大きな違いの1つに、これまでv4ではノードが参照できたPULLサーバーは1つでしたが、これを役割ごとに分割、複数対応しました。
以下に分割されています。
- ConfigurationDownloadManagers : ノードが取得する、コンフィグレーションのDSCサーバー
- ResourceModuleManagers : ノードが取得する、コンフィグレーションに利用するモジュールの先DSCサーバー
- ReportManagers : コンフィグレーションの設定結果のレポート先サーバーDSCサーバー
ですが、まだ詳細の設定方法が公開されていません。
ConfigurationID
設定可能な値は、[String]です。(GUID形式で指定します)
PULLモードのノードは、DSCサーバーにてどの「あるべき状態」のMOFファイルファイルを取得すればいいのか判断します。
ノードは、MOFファイルをDSCサーバーにリクエストする時、ConfigurationIDを使います。

PULLのDSCサーバーには、MOFにはノードに対応する[ConfigurationID].mofとそのハッシュ値を記述した[ConfigurationID].mof.checksumを設置します。
PULLのノードには、ConfigurationIDに参照するMOFの[ConfiguraionID]をLCMに設定します。
ConfigurationMode
設定可能な値は、ApplyAndAutoCorrect、ApplyAndMonitor、Applyの3つです。
4日目に詳細を書いていますのでどうぞ。
PULLでは、ノードが「あるべき状態を適用後、どのように動くのか」を3つの基準から1つ選べます...
PULLの動作モードは↓の図を参考にどうぞ。

ConfigurationModeFrequencyMins
設定可能な値は、[int]です。(最小値30)
一度DSCであるべき構成を適用すると、ノードのあるべき状態はLCMにキャッシュされます。
ConfigurationModeFrequencyMinsの間隔に従って、「LCMにキャッシュされたあるべき状態」と「現在のノードの状態」を比較します。

設定可能な最小の値は30分です。 また、ConfigurationModeFrequencyMinsの値は、後述するRefreshFrequencyMinsの倍数である必要があります。もし異なる数値を指定した場合は、自動的にRefreshFrequencyMinsに対して2倍の値になります。。
DownloadManagerCustomData
v4では、PULLサーバーとなるDSCサーバーを指定しました。 v5では、コンフィグレーションの指定やリソースの指定が分離しましたので、設定がどうなるのか少し謎です。
以下はv4での指定例です。
DownloadManagerCustomData = @{ ServerUrl = "https://Dsc.PullServer.contoso.com:8080/PSDSCPullServer/PSDSCPullServer.svc" AllowUnsecureConnection = "false" }
ServerUrl
ノードが参照するPULLサーバーエンドポイントを指定します。
AllowUnsecureConnection
[bool]を指定できます。HTTPSにはVerifyされた証明書が必要なので、Trueにするには考慮点が多く面倒です。
- false: デフォルト/推奨。 falseを指定するとHTTPS接続
- true: 指定するとHTTP接続
DownloadManagerName
設定可能な値は、WebDownloadManagerとDSCFileDownloadManagerです。 PULLモードで、ノードとDSCサーバーが通信するプロトコルには2つ方法があります。
- HTTP/HTTPS :
WebDownloadManagerを指定 - SMB :
DSCFileDownloadManagerを指定
一般に、HTTP/HTTPSは、NAT/ファイアウォールを超えることが容易なため外部エンドポイントにするとき好まれます。SMBは、NAT/ファイアウォール越えが面倒なため、内部利用のみなら、まぁ。
SMBは使えない
- HTTP/HTTPSでは、DSCサーバーでノードの構成状態など一覧が取得可能*6
- SMBでは、ノード一覧や状態を取得できない。ノードの状態把握が困難になるため
ノードの状態把握
HTTP/HTTPSならノードの状態をJSONで取得できます。 謎社ではラップ、拡張して以下のようにノードの状態を一覧取得可能にしています。
TargetName : 192.168.100.10 ConfigurationId : 1847HFN47RGILJA3423ZEQR82346YS8UOIFW24K4 ServerCheckSum : ASA4asef6DE23982A2F3C16TJS369FA9E38FE9mkhl69AAS4942234N293B5E5CB TargetCheckSum : ASA4asef6DE23982A2F3C16TJS369FA9E38FE9mkhl69AAS4942234N293B5E5CB NodeCompliant : True LastComplianceTime : 2014-12-02T13:02:13.4431237Z LastHeartbeatTime : 2014-12-02T13:02:13.4431237Z Dirty : True StatusCode : 0
PartialConfigurations (v5 で追加)
PowerShell v5からPartial Configurationが可能になります。 v4では、ノードのLCMには1台のPULLサーバーしか指定できず、また1つのコンフィグレーションを分割して取得/適用できません。

v5のPartial Configurationは、複数のPULLサーバーからあるべき状態を記述したコンフィグレーションをを分割して受け取ることができるようになります。*7

v5でPartial ConfigurationをLCMで設定するには、次のようにコンフィグレーションを書きます。
[DSCLocalConfigurationManager()] configuration v5PULLNodeLCMSetting { Node localhost { Settings { RefreshMode = "Pull" ConfigurationID = 'a5f86baf-f17f-4778-8944-9cc99ec9f992' RebootNodeIfNeeded = $true } ConfigurationRepositoryWeb PullSvc1 { serverURL = 'https://wmf5-1.sccloud.lab:8080/OSConfig/PSDSCPullServer.svc' AllowUnSecureConnection = $true } ConfigurationRepositoryWeb PullSvc2 { ServerURL = 'https://wmf5-2.sccloud.lab:8080/SQLConfig/PSDSCPullServer.svc' AllowUnsecureConnection = $true } PartialConfiguration OSConfig { Description = 'Configuration for the Base OS' ConfigurationSource = '[ConfigurationRepositoryWeb]PullSvc1' } PartialConfiguration SQLConfig { Description = 'Configuration for the Web Server' ConfigurationSource = '[ConfigurationRepositoryWeb]PullSvc2' DependsOn = '[PartialConfiguration]OSConfig' } } }
RefreshFrequencyMins
設定可能な値は[int](最小値15)。
ノードのLCMにキャッシュされた「あるべき構成」と、DSCサーバーであるべき状態にずれがないかをか確認して適用します。 ConfigurationModeFrequencyMinsの間隔に従って、「LCMにキャッシュされたあるべき状態」と「PULLサーバーのあるあるべき構成に変化がないか」を比較しします。

最小の値は15分です。 また、ConfigurationModeFrequencyMinsの値は、このRefreshFrequencyMinsの倍数である必要があります。
まとめ
触りなので、LCMの本体などは後日ですね!
LCMはDSCのまさにエンジンなので、把握しないでDSC使うと困ることになります。コンフィグレーションの初歩としてもLCMの設定を試してみてください。