Desired State Configuration

Desired State Configuration とは

Desired State Configuration (DSC) は、PowerShell に組み込まれたツールで、コードによって Windows ホストのセットアップを定義するために使用することができます。DSC の全体的な目的は Ansible と同じですが、実行方法が異なるだけです。Ansible 2.4 からは、win_dsc モジュールが追加され、Windows ホストとのやりとりの際に、既存の DSC リソースを活用することができます。

DSC の詳細は、DSC Overview を参照してください。

ホスト要件

win_dsc モジュールを使用するには、Windows ホストに PowerShell v5.0 以降がインストールされている必要があります。サポート対象のホストはすべて、PowerShell v5.0 にアップグレードすることができます。

PowerShell の要件を満たしていれば、DSC を使用することは、win_dsc モジュールでタスクを作成するのと同じぐらい簡単です。

DSC を使用する理由

DSC と Ansible モジュールには、リソースの状態を定義して保証するという共通の目的があります。このため、DSC ファイルリソース や Ansible``win_file`` のようなリソースを使用して、同じ結果を得ることができます。どちらを使用するかは、シナリオによって異なります。

DSC リソースで Ansible モジュールを使用する理由:

  • ホストが PowerShell v5.0 をサポートしていない、または簡単にアップグレードできない

  • DSC リソースは、Ansible モジュールに存在する機能を提供しない。たとえば、win_regedit は REG_NONE のプロパティータイプを管理できますが、DSC の Registry リソースでは管理できません。

  • DSC のリソースはチェックモードのサポートが限られているが、Ansible モジュールの中にはより優れたチェック機能を持つものがある

  • DSC リソースでは差分モードがサポートされないが、一部の Ansible モジュールではサポートされる

  • カスタムリソースでは、事前にホスト上で追加のインストール手順を実行する必要があるが、Ansible モジュールは Ansible に組み込まれている

  • Ansible モジュールが機能する DSC リソースにバグがある

Ansible モジュールで DSC リソースを使用する理由:

  • Ansible モジュールは、DSC リソースに存在する機能をサポートしていない

  • 利用可能な Ansible モジュールがない

  • 既存の Ansible モジュールにバグがある

つまるところ、タスクが DSC で実行されるか Ansible モジュールで実行されるかは重要ではありません。重要なのは、タスクが正しく実行され、Playbook が読めることです。Ansible よりも DSC の方を使用した経験があり、それで必要なことができるのであれば、そのタスクには DSC を使用すると良いでしょう。

DSC の使用方法

win_dsc モジュールは、管理しているリソースに応じて変化するように、フリーフォームのオプションを取り入れています。組み込まれているリソースのリストは、resources を参照してください。

Registry リソースを例にとると、これは Microsoft が文書化したDSCの定義です。

Registry [string] #ResourceName
{
    Key = [string]
    ValueName = [string]
    [ Ensure = [string] { Enable | Disable }  ]
    [ Force =  [bool]   ]
    [ Hex = [bool] ]
    [ DependsOn = [string[]] ]
    [ ValueData = [string[]] ]
    [ ValueType = [string] { Binary | Dword | ExpandString | MultiString | Qword | String }  ]
}

タスクを定義する際には、使用する DSC リソースを resource_name に設定する必要があります。この場合、resource_nameRegistry に設定する必要があります。module_version はインストールされている DSC リソースの特定のバージョンを参照することができますが、空白にするとデフォルトで最新バージョンになります。その他のオプションは KeyValueName のようにリソースを定義するためのパラメーターになります。タスクのオプションは大文字小文字を区別しませんが、DSC リソースのオプションと Ansible の``win_dsc`` のオプションを区別しやすくするために、大文字小文字をそのままにしておくことが推奨されます。

上記の DSC レジストリーリソースの Ansible タスクバージョンは、以下のようになります。

- name: Use win_dsc module with the Registry DSC resource
  win_dsc:
    resource_name: Registry
    Ensure: Present
    Key: HKEY_LOCAL_MACHINE\SOFTWARE\ExampleKey
    ValueName: TestValue
    ValueData: TestData

Ansible 2.8 より、win_dsc モジュールは、Ansible からの入力オプションを DSC 定義で自動的に検証します。つまり、オプション名が間違っていたり、必須オプションが設定されていなかったり、値が有効な選択肢でなかったりすると、Ansible は失敗します。Ansible を冗長レベル 3 以上 (-vvv) で実行した場合、戻り値には、指定された resource_name に基づいて可能な呼び出しオプションが含まれます。以下は、上記の Registry タスクの呼び出し出力の例です。

changed: [2016] => {
    "changed": true,
    "invocation": {
        "module_args": {
            "DependsOn": null,
            "Ensure": "Present",
            "Force": null,
            "Hex": null,
            "Key": "HKEY_LOCAL_MACHINE\\SOFTWARE\\ExampleKey",
            "PsDscRunAsCredential_password": null,
            "PsDscRunAsCredential_username": null,
            "ValueData": [
                "TestData"
            ],
            "ValueName": "TestValue",
            "ValueType": null,
            "module_version": "latest",
            "resource_name": "Registry"
        }
    },
    "module_version": "1.1",
    "reboot_required": false,
    "verbose_set": [
        "Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = ResourceSet,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.",
        "An LCM method call arrived from computer SERVER2016 with user sid S-1-5-21-3088887838-4058132883-1884671576-1105.",
        "[SERVER2016]: LCM:  [ Start  Set      ]  [[Registry]DirectResourceAccess]",
        "[SERVER2016]:                            [[Registry]DirectResourceAccess] (SET) Create registry key 'HKLM:\\SOFTWARE\\ExampleKey'",
        "[SERVER2016]:                            [[Registry]DirectResourceAccess] (SET) Set registry key value 'HKLM:\\SOFTWARE\\ExampleKey\\TestValue' to 'TestData' of type 'String'",
        "[SERVER2016]: LCM:  [ End    Set      ]  [[Registry]DirectResourceAccess]  in 0.1930 seconds.",
        "[SERVER2016]: LCM:  [ End    Set      ]    in  0.2720 seconds.",
        "Operation 'Invoke CimMethod' complete.",
        "Time taken for configuration job to complete is 0.402 seconds"
    ],
    "verbose_test": [
        "Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = ResourceTest,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.",
        "An LCM method call arrived from computer SERVER2016 with user sid S-1-5-21-3088887838-4058132883-1884671576-1105.",
        "[SERVER2016]: LCM:  [ Start  Test     ]  [[Registry]DirectResourceAccess]",
        "[SERVER2016]:                            [[Registry]DirectResourceAccess] Registry key 'HKLM:\\SOFTWARE\\ExampleKey' does not exist",
        "[SERVER2016]: LCM:  [ End    Test     ]  [[Registry]DirectResourceAccess] False in 0.2510 seconds.",
        "[SERVER2016]: LCM:  [ End    Set      ]    in  0.3310 seconds.",
        "Operation 'Invoke CimMethod' complete.",
        "Time taken for configuration job to complete is 0.475 seconds"
    ]
}

invocation.module_args キーは、設定された実際の値と、設定されなかった他の可能な値を表示します。DSC プロパティーのデフォルト値は表示されず、Ansible タスクで設定された値のみが表示されます。*_password オプションは、セキュリティー上の理由から出力ではマスクされます。他に機密性の高いモジュールオプションがある場合は、タスクに no_log: True を設定して、すべてのタスク出力がログに記録されないようにしてください。

プロパティータイプ

各 DSC リソースプロパティーには、それに関連付けられたタイプがあります。Ansible は、実行時に定義されたオプションを正しいタイプに変換しようとします。[string][bool] のような単純なタイプでは、これは単純な操作ですが、[PSCredential] や配列 ([string[]] など) のような複雑なタイプでは、特定のルールが必要です。

PSCredential

[PSCredential] オブジェクトは認証情報を安全な方法で保存するために使用されますが、Ansible にはこれを JSON でシリアル化する方法がありません。DSC PSCredential プロパティーを設定するには、そのパラメーターの定義に、ユーザ名とパスワードをそれぞれ _username_password をサフィックスにした 2 つのエントリーを追加する必要があります。たとえば、以下のようになります。

PsDscRunAsCredential_username: '{{ ansible_user }}'
PsDscRunAsCredential_password: '{{ ansible_password }}'

SourceCredential_username: AdminUser
SourceCredential_password: PasswordForAdminUser

注釈

2.8 より古いバージョンの Ansible では、Ansible のタスク定義に no_log: true を設定して、使用する認証情報がログファイルまたはコンソールの出力に保存されないようにする必要があります。

[PSCredential] は、DSC リソースの MOF 定義において``EmbeddedInstance("MSFT_Credential")`` と共に定義されます。

CimInstance タイプ

[CimInstance] オブジェクトは、DSC がそのリソースで定義されたカスタムクラスに基づいてディクショナリーオブジェクトを格納するために使用されます。[CimInstance] を取り込む値を YAML で定義することは、YAML でディクショナリーを定義することと同じです。たとえば、Ansible で``[CimInstance]`` の値を定義する場合は、以下のようになります。

# [CimInstance]AuthenticationInfo == MSFT_xWebAuthenticationInformation
AuthenticationInfo:
  Anonymous: false
  Basic: true
  Digest: false
  Windows: true

上記の例では、CIM インスタンスは、クラス MSFT_xWebAuthenticationInformation の表現です。このクラスは、AnonymousBasicDigestWindows という 4 つのブール変数を受け入れます。[CimInstance] で使用するキーは、それが表現するクラスによって異なります。使用できるキーと各キーの値のタイプについては、リソースのドキュメントを参照してください。クラスの定義は、通常、<resource name>.schema.mof にあります。

HashTable タイプ

[HashTable] オブジェクトもディクショナリーですが、定義できる/しなければならない厳密な鍵のセットがありません。[CimInstance] のように、YAML で通常のディクショナリー値のように定義します。[HashTable]] は、DSC リソースの MOF 定義において EmbeddedInstance("MSFT_KeyValuePair") と共に定義されます。

配列

[string[]][UInt32[]] のような単純なタイプの配列は、リストまたはコンマ区切りの文字列として定義され、それらがタイプにキャストされます。リストを使用すると、DSC エンジンに渡す前に win_dsc モジュールで値が手動で解析されないため、推奨されます。たとえば、Ansible で単純なタイプの配列を定義するには、次のようにします。

# [string[]]
ValueData: entry1, entry2, entry3
ValueData:
- entry1
- entry2
- entry3

# [UInt32[]]
ReturnCode: 0,3010
ReturnCode:
- 0
- 3010

[CimInstance[]] (ディクショナリーの配列) のような複雑なタイプの配列は、次の例のように定義できます。

# [CimInstance[]]BindingInfo == MSFT_xWebBindingInformation
BindingInfo:
- Protocol: https
  Port: 443
  CertificateStoreName: My
  CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
  HostName: DSCTest
  IPAddress: '*'
  SSLFlags: 1
- Protocol: http
  Port: 80
  IPAddress: '*'

上記の例は、MSFT_xWebBindingInformation クラスの 2 つの値のある配列です。[CimInstance[]] を定義すると、リソースドキュメントを参照して、定義で使用するキーを確認してください。

日時

[DateTime] オブジェクトは、ISO 8601 の日時フォーマットで日付と時間を表す DateTime 文字列です。[DateTime] フィールドの値は、文字列が Windows ホストに適切にシリアライズされるように、YAML で引用する必要があります。以下は、Ansible で``[DateTime]`` の値を定義する方法の例です。

# As UTC-0 (No timezone)
DateTime: '2019-02-22T13:57:31.2311892+00:00'

# As UTC+4
DateTime: '2019-02-22T17:57:31.2311892+04:00'

# As UTC-4
DateTime: '2019-02-22T09:57:31.2311892-04:00'

上記のすべての値は、UTCの 日付時刻が 2019 年 2 月 22 日午後 1 時 57 分 31 秒 2311892 ミリ秒であることと同じです。

別のユーザーとして実行

デフォルトでは、DSC は各リソースを、Ansible がモジュールの実行に使用するアカウントではなく、SYSTEM アカウントとして実行します。つまり、HKEY_CURRENT_USER のレジストリーハイブのように、ユーザープロファイルに基づいて動的に読み込まれるリソースは、SYSTEM のプロファイルで読み込まれます。PsDscRunAsCredential は、DSC エンジンが別のアカウントで実行されるように、すべての DSC リソースに設定することができるパラメーターです。PsDscRunAsCredential はタイプが PSCredential なので、サフィックス _username と``_password`` で定義されています。

レジストリーリソースタイプを例として使用し、Ansible ユーザーの HKEY_CURRENT_USER ハイブにアクセスするタスクを定義する方法を説明します。

- name: Use win_dsc with PsDscRunAsCredential to run as a different user
  win_dsc:
    resource_name: Registry
    Ensure: Present
    Key: HKEY_CURRENT_USER\ExampleKey
    ValueName: TestValue
    ValueData: TestData
    PsDscRunAsCredential_username: '{{ ansible_user }}'
    PsDscRunAsCredential_password: '{{ ansible_password }}'
  no_log: true

カスタムの DSC リソース

DSC のリソースは、Microsoft の組み込みオプションに限定されません。カスタムモジュールをインストールすることで、通常では利用できない他のリソースを管理することができます。

カスタムの DSC リソースの見つけ方

PSGallery を使用すると、カスタムリソースと、それを Windows ホストにインストールする方法に関するドキュメントを見つけることができます。

Find-DscResource コマンドレットを使用して、カスタムリソースを検索することもできます。以下に例を示します。

# Find all DSC resources in the configured repositories
Find-DscResource

# Find all DSC resources that relate to SQL
Find-DscResource -ModuleName "*sql*"

注釈

Microsoft が開発した DSC リソースで、x で始まるものは、実験的なリソースであり、サポートがないことを意味しています。

カスタムリソースのインストール

DSC リソースをホストにインストールする方法は 3 つあります。

  • Install-Module コマンドレットを手動で使用

  • Ansibleモジュール win_psmodule を使用

  • モジュールを手動で保存して別のホストにコピー

以下は、win_psmodule を使用して xWebAdministration リソースをインストールする例です。

- name: Install xWebAdministration DSC resource
  win_psmodule:
    name: xWebAdministration
    state: present

インストールすると、win_dsc モジュールは、resource_name オプションでリソースを参照することで、リソースを使用できるようになります。

上記の最初の 2 つの方法は、ホストがインターネットにアクセスできる場合にのみ機能します。ホストがインターネットにアクセスできない場合は、まずインターネットにアクセスできる別のホスト上で上記の方法を使用してモジュールをインストールし、それをコピーする必要があります。モジュールをローカルのファイルパスに保存するには、次の PowerShell コマンドレットを実行します。

Save-Module -Name xWebAdministration -Path C:\temp

これにより、C:\temp の中に``xWebAdministration`` フォルダーが作成され、このフィルダーはどのホストにもコピーできるようになります。PowerShell がこのオフラインリソースを見るためには、環境変数 PSModulePath で設定されたディレクトリーにコピーされている必要があります。ほとんどの場合は、この変数を通じてパス C:\Program Files\WindowsPowerShell\Module が設定されますが、win_path モジュールを使用して異なるパスを追加することができます。

zip ファイルの展開

- name: Extract a zip file
  win_dsc:
    resource_name: Archive
    Destination: C:\temp\output
    Path: C:\temp\zip.zip
    Ensure: Present

ディレクトリーの作成

- name: Create file with some text
  win_dsc:
    resource_name: File
    DestinationPath: C:\temp\file
    Contents: |
        Hello
        World
    Ensure: Present
    Type: File

- name: Create directory that is hidden is set with the System attribute
  win_dsc:
    resource_name: File
    DestinationPath: C:\temp\hidden-directory
    Attributes: Hidden,System
    Ensure: Present
    Type: Directory

Azure の操作

- name: Install xAzure DSC resources
  win_psmodule:
    name: xAzure
    state: present

- name: Create virtual machine in Azure
  win_dsc:
    resource_name: xAzureVM
    ImageName: a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-201409.01-en.us-127GB.vhd
    Name: DSCHOST01
    ServiceName: ServiceName
    StorageAccountName: StorageAccountName
    InstanceSize: Medium
    Windows: true
    Ensure: Present
    Credential_username: '{{ ansible_user }}'
    Credential_password: '{{ ansible_password }}'

IIS Web サイトのセットアップ

- name: Install xWebAdministration module
  win_psmodule:
    name: xWebAdministration
    state: present

- name: Install IIS features that are required
  win_dsc:
    resource_name: WindowsFeature
    Name: '{{ item }}'
    Ensure: Present
  loop:
  - Web-Server
  - Web-Asp-Net45

- name: Setup web content
  win_dsc:
    resource_name: File
    DestinationPath: C:\inetpub\IISSite\index.html
    Type: File
    Contents: |
      <html>
      <head><title>IIS Site</title></head>
      <body>This is the body</body>
      </html>
    Ensure: present

- name: Create new website
  win_dsc:
    resource_name: xWebsite
    Name: NewIISSite
    State: Started
    PhysicalPath: C:\inetpub\IISSite\index.html
    BindingInfo:
    - Protocol: https
      Port: 8443
      CertificateStoreName: My
      CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
      HostName: DSCTest
      IPAddress: '*'
      SSLFlags: 1
    - Protocol: http
      Port: 8080
      IPAddress: '*'
    AuthenticationInfo:
      Anonymous: false
      Basic: true
      Digest: false
      Windows: true

参考

Ansible Playbook

Playbook の概要

Ansible のヒントと裏技

Playbook のヒントと裏技

List of Windows Modules

Windows 固有のモジュールリスト (すべて PowerShell に実装)

User Mailing List

ご質問はございますか。Google Group をご覧ください。

リアルタイムチャット

Ansible チャットチャンネルへの参加方法