ARM Template の書き方 その5 SqlVirtualMachine

  • SQLServer
  • VirtualMachine
  • AzureDataBase
  • AzureResourceManager
  • sqlVirtualMachines とは

    VirtualMachine 上の SQLServer です

    VirtualMachine 上に SQLServer がインストールする作業をコンソールや ARM Template で行えるようにしたのが sqlVirtualMachines です。

    メリットは自動パッチ適用、自動バックアップの設定などがコンソールや ARM Template で設定できるところです。いちいち、サーバーの中に入って設定する必要がありません。

    今回は、そういったことも ARM Template でも可能ですという内容となります。ただ、ARM Template を使って VirtualMachine に SQLServer をインストールしようとする人は少ないのではないかと思います。

    コンソール

    「Azure SQL」というサービスの中に SQL virtual machines がありまして、コンソールからでも構築が可能です。

    arm-template-sqlvirtualmachine-01

    左の2種類、SQL Database と Managed Instance についての解説は「Azure SQL Database のサービス概要」で書いておりますので、よかったら見てみてください。

    Microsoft.SqlVirtualMachine

    "Microsoft.SqlVirtualMachine/sqlVirtualMachines" とは、既存の VirtualMachine に SQLServer をインストールする ARM の提供する機能の一つです。

    使ってみた感想としては、正直なところ、洗練されている機能とは言い難いです。

    sqlVirtualMachines の仕組み

    SQL IaaS Agent

    sqlVirtualMachines を利用するためには前提として、SQLServer をインストールするサーバー(Virtual Machine)に専用のエージェント(SQL IaaS Agent)を導入する必要があります。

    arm-template-sqlvirtualmachine-08

    上記のように、コンソールや Template から ARM を介して、サーバーリクエストが送信されます。そして、サーバーにインストールされている SQL IaaS Agent が "NT Service\SQLIaaSExtensionQuery" という sysadmin 権限が付与されているサーバーログインを使って処理を行います。

    arm-template-sqlvirtualmachine-10

    やってみる

    クイックスタートの罠

    私のやり方が間違っていたのか詳しくは分かりませんが、クイックスタートに掲載されているテンプレート作成をそのまま実行すると、失敗してしまいました。作成後の SQL VirtualMachine 画面において以下のようなメッセージが表示されます。

    SqlVirtualMachine

    SQL virtual machine management operations are disabled because SQL extension cannot be found or might not be installed properly on the virtual machine.

    対象のサーバーに SQL IaaS Agent がいないよ、と言われています。そこで、後から修正を加えてテンプレートを作り直すことになりました。

    SQL IaaS Agent の有無

    クイックスタートで作ったテンプレートからデプロイした結果と、私が修正を加えたテンプレートでデプロイした結果において、SQL IaaS Agent が新たにインストールされているのが分かります。

    sqlvirtualmachine11sqlvirtualmachine12

    おかげ様で2、3日ハマってしまうことになりましたが、SQL IaaS Agent や ARM Template の書き方について理解が深まりましたので良かったと思っています。

    Microsoft.Compute/virtualMachines/extensions の ARM Template の書き方

    SQL IaaS Agent のインストール方法

    SqlVirtualMachine を構築するためには、前提として SQL IaaS Agent のインストールが必要です。そして、そのインストール方法は以下の "type" をテンプレートで定義することで実現できます。

    • "Microsoft.Compute/virtualMachines/extensions"

    対象のサーバー(VirtualMachine)に "extensions" を適用すれば、 SQL IaaS Agent がインストールされます。

    Microsoft.Compute/virtualMachines/extensions のサンプル

    {
      "comments": "Virtual Machine",
      "name": "[variables('virtualMachines').vm01.name]",
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2019-07-01",
      "location": "[variables('location')]",
      "dependsOn": [
        "[variables('resourceID').nic01]",
        "[variables('resourceID').vm01dataDisk01]",
        "[variables('resourceID').vm01dataDisk02]",
        "[variables('resourceID').vm01dataDisk03]"
      ],
      "tags": "[variables('tags')]",
      "properties": {
        "osProfile": {
          "computerName": "[variables('virtualMachines').vm01.computerName]",
          "adminUsername": "[variables('virtualMachines').vm01.adminUsername]",
          "adminPassword": "[parameters('adminPassword')]",
          "windowsConfiguration": {
            "provisionVmAgent": true,
            "enableAutomaticUpdates": true,
            "timeZone": "Tokyo Standard Time"
          }
        },
        "hardwareProfile": {
          "vmSize": "Standard_DS2_v2"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "MicrosoftSQLServer",
            // az vm image list-offers -l eastus -p MicrosoftSQLServer -o table
            "offer": "sql2019-ws2019",
            "sku": "standard",
            "version": "latest"
          },
          "osDisk": {
            // Cannot attach an existing OS disk if the VM is created from a platform, user or a shared gallery image.
            "name": "[variables('virtualMachines').vm01.osDiskName]",
            "osType": "Windows",
            "diskSizeGB": 128,
            "caching": "ReadWrite",
            "createOption": "FromImage",
            "managedDisk": {
              "storageAccountType": "StandardSSD_LRS"
            }
          },
          "dataDisks": [
            // start --> diskmgmt.msc (Disk Management wizard)
            {
              "lun": 0,
              "name": "[variables('virtualMachines').vm01.dataDiskName01]",
              "managedDisk": {
                "id": "[variables('resourceID').vm01dataDisk01]"
              },
              "createOption": "Attach",
              "caching": "ReadWrite"
            },
            {
              "lun": 1,
              "name": "[variables('virtualMachines').vm01.dataDiskName02]",
              "managedDisk": {
                "id": "[variables('resourceID').vm01dataDisk02]"
              },
              "createOption": "Attach",
              "caching": "ReadWrite"
            },
            {
              "lun": 2,
              "name": "[variables('virtualMachines').vm01.dataDiskName03]",
              "managedDisk": {
                "id": "[variables('resourceID').vm01dataDisk03]"
              },
              "createOption": "Attach",
              "caching": "ReadWrite"
            }
          ]
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "properties": {
                "primary": true
              },
              "id": "[variables('resourceID').nic01]"
            }
          ]
        },
        "diagnosticsProfile": {
          "bootDiagnostics": {
            "enabled": true,
            "storageUri": "[reference(variables('resourceID').storage01, '2019-06-01').primaryEndpoints['blob']]"
          }
        }
      },
      "resources": [
        {
          // SQL Server IaaS Agent 拡張機能追加
          "type": "Microsoft.Compute/virtualMachines/extensions",
          "apiVersion": "2020-06-01",
          "name": "[variables('virtualMachines').vm01.SqlIaaSAgent]",
          "location": "[variables('location')]",
          "dependsOn": [
            "[variables('resourceID').vm01]"
          ],
          "properties": {
            "type": "SqlIaaSAgent",
            "publisher": "Microsoft.SqlServer.Management",
            // Get-AzVmImagePublisher -Location eastus | Get-AzVMExtensionImageType | Get-AzVMExtensionImage
            "typeHandlerVersion": "2.0",
            "autoUpgradeMinorVersion": true,
            "settings": {
              "AutoTelemetrySettings": {
                "Region": "[variables('location')]"
              }
            }
          }
        }
      ]
    }

    extensions の書き方 注意事項

    書き方に困るポイントは以下になるかと思います。

    項目名 書き方
    1 name "VirtualMachine の name"/"extensions の name"
    例) "sqlvm01/SqlIaaSAgent01"
    2 properties.type SqlIaaSAgent
    3 properties.publisher Microsoft.SqlServer.Management
    4 properties.typeHandlerVersion 2.0 ※1
    5 properties.settings 必須項目で null は許可されません。とりあえず、Region だけ指定しています。

    SqlIaaSAgent バージョンは以下のコマンドで判断できます。

    Get-AzVmImagePublisher -Location eastus | Get-AzVMExtensionImageType | Get-AzVMExtensionImage

    上記のように、特別な設定はせず extensions を設定することで、対象の VirtualMachine に SQLIaaSAgent がインストールされます。

    SqlVirtualMachine の ARM Template の書き方

    私はこのテンプレートをデプロイするにあたって、数々のエラーを出してしまいました。下記のサンプルテンプレート内に、エラー回避のためのコメントを残しております。併せてご確認ください。

    サンプル

    {
        "comments": "SQL Server on Virtual Machine",
        // sqlVirtualMachines name is same as the virtual machine name provided on VirtualMachineResourceId property.
        "name": "[variables('virtualMachines').vm01.name]",
        "type": "Microsoft.SqlVirtualMachine/sqlVirtualMachines",
        "apiVersion": "2017-03-01-preview",
        "dependsOn": [
        "[variables('resourceID').SqlIaaSAgent01]"
        ],
        "location": "[variables('location')]",
        "tags": "[variables('tags')]",
        "properties": {
            "virtualMachineResourceId": "[variables('resourceID').vm01]",
            // sqlImageOffer is same as the Virtual Machine imageReference.
            "sqlImageOffer": "sql2019-ws2019",
            "sqlServerLicenseType": "PAYG",
            "sqlManagement": "Full",  // required by autoBackupSettings,autoPatchingSettings
            "sqlImageSku": "standard",
            "autoPatchingSettings": {
                "enable": true,
                "dayOfWeek": "Monday",
                "maintenanceWindowStartingHour": 1,  // int
                "maintenanceWindowDuration": 60  // 30 - 180
            },
            "autoBackupSettings": {
                // https://docs.microsoft.com/ja-jp/azure/azure-sql/virtual-machines/windows/automated-backup
                // require storageAccountUrl & storageAccessKey
                "enable": true,
                "enableEncryption": false,
                "backupScheduleType": "Manual",
                "retentionPeriod": 7,
                "backupSystemDbs": true,
                "storageAccountUrl": "[reference(variables('resourceID').storage01, '2019-06-01').primaryEndpoints['blob']]",
                "storageAccessKey": "[listKeys(variables('resourceID').storage01,'2019-06-01').keys[0].value]"
                // "Manual" require the following
                ,"fullBackupFrequency": "Daily", // or "Weekly"
                "fullBackupStartTime": 18,
                "fullBackupWindowHours": 2,
                "logBackupFrequency": 30
            },
            "serverConfigurationsManagementSettings": {
                "sqlConnectivityUpdateSettings": {
                "connectivityType": "PRIVATE",
                "port": 1433,
                "sqlAuthUpdateUserName": "[variables('sqlVirtualMachines').sqlonvm01.sqlAuthUpdateUserName]",
                "sqlAuthUpdatePassword": "[parameters('adminPassword')]"
                }
            },
            "storageConfigurationSettings": {
                "sqlDataSettings": {
                "luns": [
                    0
                ],
                // Value cannot be null. Parameter name: path
                // https://gitmemory.com/issue/terraform-providers/terraform-provider-azurerm/7481/686282403
                "defaultFilePath": "F:\\MSsql\\Data"
                },
                "sqlLogSettings": {
                "luns": [
                    1
                ],
                "defaultFilePath": "L:\\MSsql\\Logs"
                },
                "sqlTempDbSettings": {
                "luns": [
                    2
                ],
                "defaultFilePath": "T:\\MSsql\\TempDB"
                },
                "diskConfigurationType": "NEW",
                "storageWorkloadType": "GENERAL"
            }
        }
    }

    SqlVirtualMachine の書き方 注意事項

    書き方に困るポイントは以下になるかと思います。

    項目名 書き方
    1 name インストール対象の VirtualMachine と同じ名前をセットする。
    2 dependsOn extensions の ResourceID を指定する場合は以下を参考ください。
    resourceId('Microsoft.Compute/virtualMachines/extensions','vm-name','extensions-name')
    3 properties.sqlManagement 自動バックアップ、自動パッチ適用を使う場合は、"Full" を指定する。
    4 properties.autoPatchingSettings 実行時間の指定が特殊、maintenanceWindowStartingHour=開始時間(1なら1時開始、23なら23時開始)となる。
    5 properties.autoBackupSettings Weekly を指定した場合、設定した翌日の曜日が自動的にバックアップを実行する曜日となる。
    6 properties.storageConfigurationSettings diskConfigurationType は NEW にしておく。

    デプロイ後のコンソール画面

    デプロイが上手くいくと以下のように、コンソールから各種設定が参照できるようになります。もちろん、編集も可能です。

    title

    title

    title

    最後に

    Azure 上で SQLServer の細かいアーキテクチャや動作を確認するときは、VirtualMachine 上の SQLServer があると便利です。

    従量課金で利用できますし、tempDB をデフォルトの Dドライブから別のドライブへ移動させておけば、割り当て解除の VirtualMachine の停止を行っても停止中は課金されず、データも消えないので良いですね。

  • SQLServer
  • VirtualMachine
  • AzureDataBase
  • AzureResourceManager