Desired State Configurationを試した

Azure

Desired State Configration(DSC)とは

PowerShellを使ったIaC構成管理の仕組みで、
カスタムスクリプト拡張機能のように命令型ではなく宣言型でミドルウェア以上の構成を定義できるものです。(Ansible的なやつ)
カスタムスクリプト拡張機能は1回実行して終わりの「スクリプト自動実行機能」的な位置づけでしたが、DSCで構成定義したものはドリフト検出(定義した構成と違う状態になったことを検知する)などができます。

DSCの特徴

PowerShellで構成情報を定義するという点が特徴です。

今回試した方法では以下の流れで実装できました。

これはあくまでDSCのざっくりとした動作を確認するための手順で、実際には「Azure マシンの構成」や「Nano Server」というものを使って構成する手順が推奨されているようです。

Windows 用 Desired State Configuration (DSC) の概要 - PowerShell
この記事では、Windows 用 PowerShell Desired State Configuration (DSC) の使用を開始する方法について説明します。

<今回の実装フロー>
1.手元で構成情報を.ps1で定義し、zip化
2.zip化したファイルをBLOBストレージにアップロード
3.Azure VMのデプロイとDSC拡張機能のトリガーでBLOBストレージから構成用zipファイルをダウンロード
4.作成したVM上でzipを解凍し、ps1ファイルをコンパイルしMOFファイルを生成
  ※MOF (Managed Object Format) :CIM (Common Information Model) の標準形式で記述された構成ファイル。DSCエンジンが実行できるファイル形式で、ps1をコンパイルすると生成される。
5.VM上のDSC拡張機能がMOFファイルに従って役割のインストールや設定変更などを実行する。

また、本来DSCにはpushモードとpullモードがあります。
pushモード:VMへの構成ファイルなどのpushをトリガーに最新化する
pullモード:VMが定期的に構成ファイルをpullして状態が最新であるかをチェックする。構成情報と現在の設定値に乖離がある場合は「ドリフト検出」を行い通知することも可能です。

DSCの注意点

PowerShellで実行されることもあり、WindowsServerが実質的な対象範囲になっているようです。

依然はDSC for Linuxとして開発されていましたが、現在はサポートが終了しているように見えます。

DSC for Linux リソース - PowerShell
DSC for Linux リソース

少し調べてみましたがWindowsはDSCで、LinuxはAnsibleでやってるというような内容が散見されたので、LinuxサーバーをDSCでコネコネしている人はあんまいなさそう。

DSCを使ってIISのWebサーバーを構築してみる

百聞は一見に如かずなので、まずは適当に試してみようと思います。

今回はDSCを使ってIISのWebサーバーを構築します。

全体の流れ

上述した通り実装のフローは以下の通り

  1. VMをデプロイするためのBicepファイル準備(割愛)
  2. DSCを定義する構成ファイル(ps1ファイル)の準備
  3. ストレージアカウントを用意して、事前に作ったスクリプトなどをzip化してアップロード
  4. VM構成のBicepで、ストレージアカウントからzipをダウンロードしてDSC拡張機能を使うよう定義
  5. デプロイ実行

ps1ファイルの準備

構成を定義するps1ファイルを作成します。

ps1と言いつつ宣言的に記述でき、後にVM側でコンパイルするために使われます。

ConfigureIIS.ps1
# PowerShell DSC Configuration for IIS Web Server
# This script configures IIS and deploys web content to Azure VM from Blob Storage

Configuration ConfigureIIS
{
    param
    (
        [Parameter(Mandatory = $false)]
        [string]$MachineName = 'localhost',
        
        [Parameter(Mandatory = $false)]
        [string]$BlobStorageUrl = ''
    )

    Import-DscResource -ModuleName 'PSDesiredStateConfiguration'

    Node $MachineName
    {
        # Ensure IIS is installed
        WindowsFeature IIS
        {
            Ensure = 'Present'
            Name   = 'Web-Server'
        }

        # Ensure IIS Management Tools are installed
        WindowsFeature IISManagementTools
        {
            Ensure    = 'Present'
            Name      = 'Web-Mgmt-Tools'
            DependsOn = '[WindowsFeature]IIS'
        }

        # Ensure ASP.NET 4.5 is installed
        WindowsFeature ASPNET45
        {
            Ensure    = 'Present'
            Name      = 'Web-Asp-Net45'
            DependsOn = '[WindowsFeature]IIS'
        }

        # Ensure the default website directory exists
        File WebsiteDirectory
        {
            Ensure          = 'Present'
            Type            = 'Directory'
            DestinationPath = 'C:\inetpub\wwwroot'
            DependsOn       = '[WindowsFeature]IIS'
        }

        # Download and copy index.html from Blob Storage
        Script DownloadIndexHtml
        {
            GetScript  = {
                @{ Result = (Test-Path 'C:\inetpub\wwwroot\index.html') }
            }
            TestScript = {
                Test-Path 'C:\inetpub\wwwroot\index.html'
            }
            SetScript  = {
                $blobUrl = $using:BlobStorageUrl
                if ($blobUrl) {
                    Invoke-WebRequest -Uri "$blobUrl/index.html" -OutFile 'C:\inetpub\wwwroot\index.html' -UseBasicParsing
                }
            }
            DependsOn  = '[File]WebsiteDirectory'
        }

        # Download and copy style.css from Blob Storage
        Script DownloadStyleCss
        {
            GetScript  = {
                @{ Result = (Test-Path 'C:\inetpub\wwwroot\style.css') }
            }
            TestScript = {
                Test-Path 'C:\inetpub\wwwroot\style.css'
            }
            SetScript  = {
                $blobUrl = $using:BlobStorageUrl
                if ($blobUrl) {
                    Invoke-WebRequest -Uri "$blobUrl/style.css" -OutFile 'C:\inetpub\wwwroot\style.css' -UseBasicParsing
                }
            }
            DependsOn  = '[File]WebsiteDirectory'
        }
    }
}

# Note: This configuration will be compiled and packaged on the local machine,
# then deployed to Azure VM via DSC Extension

構成の書き方については以下の公式ページが参考になります。

DSC 構成 - PowerShell
DSC 構成は、特別な種類の関数を定義する PowerShell スクリプトです。
Configuration MyDscConfiguration

でDSC用の構成ファイルであることを定義します。

WindowsFeature

ここでWindowsServerの機能を呼び出しています。

今回であればIISとASP.NETのインストールを指定していますが、ADやDNSなども指定できます。

そのほかにも、Fileという始まりでドライブのファイルを操作したり、Depends onで依存関係を定義したりします。

スクリプトをBLOBストレージにアップロード

Azure StorageアカウントにスクリプトとWebサーバー用のコンテンツファイルを保存します。

Azure VMからパブリックアクセスで取ってきてサーバー側で実行しますが、この時スクリプトはzipファイルでないとダメという制約があるそうです。(ps1のままアップロードしたらエラーが出ました。)

# ConfigureIIS.ps1をzipファイルに圧縮
Compress-Archive -Path "dsc\ConfigureIIS.ps1" -DestinationPath "ConfigureIIS.zip" -Force
ストレージアカウント+コンテナの作成からアップロードまで
```powershell
# ストレージアカウントを作成(パブリックBLOBアクセスを有効化)
az storage account create `
  --name $storageAccountName `
  --resource-group $resourceGroup `
  --location $location `
  --sku Standard_LRS `
  --kind StorageV2 `
  --allow-blob-public-access true

# ストレージアカウントのIAM設定からストレージ BLOB データ共同作成者ロールを割り当て(Azure Portal作業)※反映に1~2分かかります

# コンテナを作成(パブリックアクセス許可)
az storage container create `
  --name $containerName `
  --account-name $storageAccountName `
  --public-access blob `
  --auth-mode login
```

### ファイルをBLOBストレージにアップロード

```powershell
# DSCパッケージをアップロード
az storage blob upload `
  --account-name $storageAccountName `
  --container-name $containerName `
  --name "ConfigureIIS.zip" `
  --file "ConfigureIIS.zip" `
  --auth-mode login `
  --overwrite

# Webコンテンツをアップロード
az storage blob upload `
  --account-name $storageAccountName `
  --container-name $containerName `
  --name "index.html" `
  --file "web-content\index.html" `
  --auth-mode login `
  --overwrite

az storage blob upload `
  --account-name $storageAccountName `
  --container-name $containerName `
  --name "style.css" `
  --file "web-content\style.css" `
  --auth-mode login `
  --overwrite

Azure Portalのストレージアカウント→コンテナーなどでファイルが保存されているのを確認できればOKです。

デプロイ実行

の前にDSCで取得するBLOBストレージのURLを生成します

# ストレージアカウントのエンドポイントを取得
$blobEndpoint = az storage account show `
  --name $storageAccountName `
  --resource-group $resourceGroup `
  --query "primaryEndpoints.blob" `
  --output tsv
# URLを構築
$dscPackageUrl = "${blobEndpoint}${containerName}/ConfigureIIS.zip"
$blobStorageUrl = "${blobEndpoint}${containerName}"

コマンドで実行していますが、コンテナからもコピーできます。(同じものになっているはずです)

URLを構築出来たらデプロイを実行します。

az deployment group create `
  --resource-group $resourceGroup `
  --template-file main.bicep `
  --parameters location=$location `
               vnetName=vnet-bicep `
               nsgName=nsg-bicep `
               pipName=pip-vm-bicep `
               nicName=nic-vm-bicep `
               vmName=vm-bicep `
               dataDiskName=disk-bicep `
               adminUsername=<VMユーザー名> `
               adminPassword='<VMパスワード>' `
               dscPackageUrl=$dscPackageUrl `
               blobStorageUrl=$blobStorageUrl

デプロイに10分ほどかかりました。

簡単な確認

まずはサーバーにRDPで接続します。

接続できてIISがインストール&実行されているのがわかります。

LocalServerなどで出ているエラーはClipbord Serviceが遅延スタートになっているため止まっているよというエラーで特に問題ありません。(スタートすればエラーが解消されました。)

ブラウザからも接続が確認できます。(リポジトリではNSGでTCP443解放していますが、SSL証明書は入れていないのでこっそり80解放に書き換えています)

パブリックアクセスをしてみます。

適当なindex.htmlとstyle.cssで静的Webアプリを構築しているので、Webページっぽいものが見えるはずです。

DSCに関する情報

DSCを学ぶ意義はあるか?

DSCって主流なの?学ぶ意味はあるの?と疑問になりました。

https://www.reddit.com/r/PowerShell/comments/yttjqi/is_powershell_dsc_still_worth_learning/?tl=ja
3年前の海外のQAやりとりですが、DSCはWindowsServerの構成管理としては悪くないという意見があります。

DSC v3は開発中でクロスプラットフォームになるといわれていますが、未だにプレビューの状態のようです。Microsoftがこの技術をどういう位置づけで取り扱うつもりなのかは気になりますね。(撤退気味なのか、積極的なのか)

希望状態構成 (DSC) - PowerShell
DSC は、構成をコードとして使用して IT および開発インフラストラクチャを管理できる管理プラットフォームです。

Azure マシンの構成

冒頭で少し触れましたが、Azure マシンの構成という機能があります。

Azure マシンの構成について - Azure Machine Configuration
Azure Policy によりマシン構成機能を使用して仮想マシン内の設定が監査または構成されるしくみについて説明します。

調べてみると実質的に今はこれが主流のようです。

今回の方式は実質的に構成管理の役割をはたしていなく、カスタムスクリプト拡張機能と同様に一回きりの手順になっています。

Azureマシンの構成を使うことで、設定の継続的なドリフト検出だったり、CI/CDとの統合などもできるようなので、今後触ってみたいと思います。

コメント