チュートリアル: Ansible を使用して Azure Virtual Machine Scale Sets のカスタム イメージを更新する

重要

この記事のサンプル プレイブックを実行するには、Ansible 2.8 (以降) が必要です。

Azure Virtual Machine Scale Sets は、負荷分散が行われる同一の VM のグループを構成するための Azure 機能です。 スケール セットに追加コストはなく、仮想マシンから構築されます。 ユーザーは、VM インスタンス、ロード バランサー、マネージド ディスク ストレージなど、基本的なコンピューティング リソースに対してのみ支払います。 スケール セットには、アプリケーションの実行とスケーリングを行うための管理レイヤーと自動化レイヤーがあります。 代わりに手動で個々 の VM を作成し管理できます。 ただし、スケール セットの使用には、2 つの主な利点があります。 それらは Azure に組み込まれ、アプリケーションのニーズを満たすように自動的に仮想マシンを拡大縮小します。

VM がデプロイされたら、アプリに必要なソフトウェアを使用して VM を構成します。 この構成タスクを VM ごとに行う代わりに、カスタム イメージを作成することができます。 カスタム イメージは、インストールされているソフトウェアを含む既存の VM のスナップショットです。 スケール セットを構成するときに、そのスケール セットの VM に使用するイメージを指定します。 カスタム イメージを使用することにより、各 VM インスタンスはご使用のアプリに対して同じように構成されます。 場合によっては、スケール セットのカスタム イメージの更新が必要になることがあります。 そのタスクがこのチュートリアルの焦点です。

この記事では、次のことについて説明します。

  • HTTPD を使用して 2 つの VM を構成する
  • 既存の VM からカスタム イメージを作成する
  • イメージからスケール セットを作成する
  • カスタム イメージを更新する

前提条件

  • Azure サブスクリプション:Azure サブスクリプションをお持ちでない場合は、開始する前に無料アカウントを作成してください。

2 つの VM を構成する

このセクションのプレイブック コードは、HTTPD が両方にインストールされた 2 つの仮想マシンを作成します。

各 VM の index.html ページには、次のようにテスト文字列が表示されます。

  • 最初の VM には値 Image A が表示される
  • 2 番目の VM には値 Image B が表示される

この文字列は、異なるソフトウェアを使用した各 VM の構成を模倣するように意図されています。

サンプル プレイブックを取得するには、次の 2 つの方法があります。

  • プレイブックをダウンロードして、create_vms.yml に保存する。

  • create_vms.yml という名前で新しいファイルを作成します。 次のコードを新しいファイルに挿入します。

- name: Create two VMs (A and B) with HTTPS
  hosts: localhost
  connection: local
  vars:
    vm_name: vmforimage
    admin_username: testuser
    admin_password: Pass123$$$abx!
    location: eastus
  tasks:
  - name: Create a resource group
    azure_rm_resourcegroup:
      name: "{{ resource_group }}"
      location: "{{ location }}"

  - name: Create virtual network
    azure_rm_virtualnetwork:
      resource_group: "{{ resource_group }}"
      name: "{{ vm_name }}"
      address_prefixes: "10.0.0.0/16"

  - name: Create subnets for VM A and B
    azure_rm_subnet:
      resource_group: "{{ resource_group }}"
      virtual_network: "{{ vm_name }}"
      name: "{{ vm_name }}"
      address_prefix: "10.0.1.0/24"

  - name: Create Network Security Group that allows HTTP
    azure_rm_securitygroup:
      resource_group: "{{ resource_group }}"
      name: "{{ vm_name }}"
      rules:
        - name: HTTP
          protocol: Tcp
          destination_port_range: 80
          access: Allow
          priority: 1002
          direction: Inbound

  - name: Create public IP addresses for VM A and B
    azure_rm_publicipaddress:
      resource_group: "{{ resource_group }}"
      allocation_method: Static
      name: "{{ vm_name }}_{{ item }}"
    loop:
      - A
      - B
    register: pip_output

  - name: Create virtual network inteface cards for VM A and B
    azure_rm_networkinterface:
      resource_group: "{{ resource_group }}"
      name: "{{ vm_name }}_{{ item }}"
      virtual_network: "{{ vm_name }}"
      subnet: "{{ vm_name }}"
      public_ip_name: "{{ vm_name }}_{{ item }}"
      security_group: "{{ vm_name }}"
    loop:
      - A
      - B

  - name: Create VM A and B
    azure_rm_virtualmachine:
      resource_group: "{{ resource_group }}"
      name: "{{ vm_name }}{{ item }}"
      admin_username: "{{ admin_username }}"
      admin_password: "{{ admin_password }}"
      vm_size: Standard_B1ms
      network_interfaces: "{{ vm_name }}_{{ item }}"
      image:
        offer: UbuntuServer
        publisher: Canonical
        sku: 16.04-LTS
        version: latest
    loop:
      - A
      - B

  - name: Create VM Extension
    azure_rm_virtualmachineextension:
      resource_group: "{{ resource_group }}"
      name: testVMExtension
      virtual_machine_name: "{{ vm_name }}{{ item }}"
      publisher: Microsoft.Azure.Extensions
      virtual_machine_extension_type: CustomScript
      type_handler_version: 2.0
      auto_upgrade_minor_version: true
      settings: {"commandToExecute": "sudo apt-get -y install apache2"}
    loop:
      - A
      - B

  - name: Create VM Extension
    azure_rm_virtualmachineextension:
      resource_group: "{{ resource_group }}"
      name: testVMExtension
      virtual_machine_name: "{{ vm_name }}{{ item }}"
      publisher: Microsoft.Azure.Extensions
      virtual_machine_extension_type: CustomScript
      type_handler_version: 2.0
      auto_upgrade_minor_version: true
      settings: {"commandToExecute": "printf '<html><body><h1>Image {{ item }}</h1></body></html>' >> index.html; sudo cp index.html /var/www/html/"}
    loop:
      - A
      - B

  - debug:
      msg: "Public IP Address A: {{ pip_output.results[0].state.ip_address }}"

  - debug:
      msg: "Public IP Address B: {{ pip_output.results[1].state.ip_address }}"

myrg を自分のリソース グループ名に置き換えて、ansible-playbook コマンドを使用してプレイブックを実行します。

ansible-playbook create-vms.yml --extra-vars "resource_group=myrg"

プレイブックの debug セクションのため、ansible-playbook コマンドは各 VM の IP アドレスを表示します。 これらの IP アドレスを後で使用するためにコピーします。

Virtual machine IP addresses

2 つの VM に接続する

このセクションでは、各 VM に接続します。 前のセクションで述べたように、文字列 Image AImage B は、異なる構成を持つ 2 つの個別の VM を持つことを模倣します。

次のように、前のセクションの IP アドレスを使用して両方の VM に接続します。

Screenshot from virtual machine A

Screenshot from virtual machine B

各 VM からイメージを作成する

この時点で、若干異なる構成 (それらの index.html ファイル) を持つ 2 つの VM があります。

このセクションのプレイブック コードは、次のような各 VM のカスタム イメージを作成します。

  • image_vmforimageA - ホーム ページに Image A を表示する VM 用に作成されたカスタム イメージ。
  • image_vmforimageB - ホーム ページに Image B を表示する VM 用に作成されたカスタム イメージ。

サンプル プレイブックを取得するには、次の 2 つの方法があります。

  • プレイブックをダウンロードして、capture-images.yml に保存する。

  • capture-images.yml という名前で新しいファイルを作成します。 次のコードを新しいファイルに挿入します。

- name: Capture VM Images
  hosts: localhost
  connection: local
  vars:
    vm_name: vmforimage
  tasks:

  - name: Stop and generalize VMs
    azure_rm_virtualmachine:
      resource_group: "{{ resource_group }}"
      name: "{{ vm_name }}{{ item }}"
      generalized: yes
    loop:
      - A
      - B

  - name: Create an images from a VMs
    azure_rm_image:
      resource_group: "{{ resource_group }}"
      name: "image_{{ vm_name }}{{ item }}"
      source: "{{ vm_name }}{{ item }}"
    loop:
      - A
      - B

myrg を自分のリソース グループ名に置き換えて、ansible-playbook コマンドを使用してプレイブックを実行します。

ansible-playbook capture-images.yml --extra-vars "resource_group=myrg"

イメージ A を使用してスケール セットを作成する

このセクションでは、プレイブックを使用して次の Azure リソースを構成します。

  • パブリック IP アドレス
  • Load Balancer
  • image_vmforimageA を参照するスケール セット

サンプル プレイブックを取得するには、次の 2 つの方法があります。

  • プレイブックをダウンロードして、create-vmss.yml に保存する。

  • create-vmss.yml という名前で新しいファイルを作成します。 次のコードを新しいファイルに挿入します。

---
- hosts: localhost
  vars:
    vmss_name: vmsstest
    location: eastus
    admin_username: vmssadmin
    admin_password: User123!!!abc
    vm_name: vmforimage
    image_name: "image_vmforimageA"

  tasks:

    - name: Create public IP address
      azure_rm_publicipaddress:
        resource_group: "{{ resource_group }}"
        allocation_method: Static
        name: "{{ vmss_name }}"
      register: pip_output

    - name: Create a load balancer
      azure_rm_loadbalancer:
        name: "{{ vmss_name }}lb"
        location: "{{ location }}"
        resource_group: "{{ resource_group }}"
        public_ip: "{{ vmss_name }}"
        probe_protocol: Tcp
        probe_port: 80
        probe_interval: 10
        probe_fail_count: 3
        protocol: Tcp
        load_distribution: Default
        frontend_port: 80
        backend_port: 80
        idle_timeout: 4
        natpool_frontend_port_start: 50000
        natpool_frontend_port_end: 50040
        natpool_backend_port: 22
        natpool_protocol: Tcp

    - name: Create a scale set
      azure_rm_virtualmachinescaleset:
        resource_group: "{{ resource_group }}"
        name: "{{ vmss_name }}"
        vm_size: Standard_DS1_v2
        admin_username: "{{ admin_username }}"
        admin_password: "{{ admin_password }}"
        ssh_password_enabled: true
        capacity: 2
        virtual_network_name: "{{ vm_name }}"
        subnet_name: "{{ vm_name }}"
        upgrade_policy: Manual
        tier: Standard
        managed_disk_type: Standard_LRS
        os_disk_caching: ReadWrite
        image:
          name: "{{ image_name }}"
          resource_group: "{{ resource_group }}"
        load_balancer: "{{ vmss_name }}lb"

    - debug:
        msg: "Scale set public IP address: {{ pip_output.state.ip_address }}"

myrg を自分のリソース グループ名に置き換えて、ansible-playbook コマンドを使用してプレイブックを実行します。

ansible-playbook create-vmss.yml --extra-vars "resource_group=myrg"

プレイブックの debug セクションのため、ansible-playbook コマンドはスケール セットの IP アドレスを表示します。 この IP アドレスを後で使用するためにコピーします。

Public IP Address

スケール セットに接続する

このセクションでは、スケール セットに接続します。

前のセクションの IP アドレスを使用してスケール セットに接続します。

前のセクションで述べたように、文字列 Image AImage B は、異なる構成を持つ 2 つの個別の VM を持つことを模倣します。

スケール セットは、image_vmforimageA という名前のカスタム イメージを参照します。 カスタム イメージ image_vmforimageA は、ホーム ページに Image A が表示される VM から作成されました。

その結果として、Image A を表示するホーム ページが表示されます。

The scale set is associated with the first VM.

次のセクションに進むので、ブラウザー ウィンドウは開いたままにしておきます。

スケール セットのカスタム イメージを変更して、インスタンスをアップグレードする

このセクションのプレイブック コードは、スケール セットのイメージを image_vmforimageA から image_vmforimageB に変更します。 また、このスケール セットによってデプロイされている現在のすべての仮想マシンが更新されます。

サンプル プレイブックを取得するには、次の 2 つの方法があります。

  • プレイブックをダウンロードして、update-vmss-image.yml に保存する。

  • update-vmss-image.yml という名前で新しいファイルを作成します。 次のコードを新しいファイルに挿入します。

- name: Update scale set image reference
  hosts: localhost
  connection: local
  vars:
    vmss_name: vmsstest
    image_name: image_vmforimageB
    admin_username: vmssadmin
    admin_password: User123!!!abc
  tasks:

  - name: Update scale set - second image
    azure_rm_virtualmachinescaleset:
      resource_group: "{{ resource_group }}"
      name: "{{ vmss_name }}"
      vm_size: Standard_DS1_v2
      admin_username: "{{ admin_username }}"
      admin_password: "{{ admin_password }}"
      ssh_password_enabled: true
      capacity: 3
      virtual_network_name: "{{ vmss_name }}"
      subnet_name: "{{ vmss_name }}"
      upgrade_policy: Manual
      tier: Standard
      managed_disk_type: Standard_LRS
      os_disk_caching: ReadWrite
      image:
        name: "{{ image_name }}"
        resource_group: "{{ resource_group }}"
      load_balancer: "{{ vmss_name }}lb"

  - name: List all of the instances
    azure_rm_virtualmachinescalesetinstance_facts:
      resource_group: "{{ resource_group }}"
      vmss_name: "{{ vmss_name }}"
    register: instances

  - debug:
      var: instances

  - name: manually upgrade all the instances 
    azure_rm_virtualmachinescalesetinstance:
      resource_group: "{{ resource_group }}"
      vmss_name: "{{ vmss_name }}"
      instance_id: "{{ item.instance_id }}"
      latest_model: yes
    with_items: "{{ instances.instances }}"

myrg を自分のリソース グループ名に置き換えて、ansible-playbook コマンドを使用してプレイブックを実行します。

ansible-playbook update-vmss-image.yml --extra-vars "resource_group=myrg"

ブラウザーに戻り、ページを更新します。

仮想マシンの基になるカスタム イメージが更新されているのを確認できます。

The scale set is associated with the second VM

リソースをクリーンアップする

  1. delete_rg.yml として次のコードを保存します。

    ---
    - hosts: localhost
      tasks:
        - name: Deleting resource group - "{{ name }}"
          azure_rm_resourcegroup:
            name: "{{ name }}"
            state: absent
          register: rg
        - debug:
            var: rg
    
  2. ansible-playbook コマンドを使用してプレイブックを実行します。 プレースホルダーは、削除するリソース グループの名前に置き換えます。 リソース グループ内のすべてのリソースが削除されます。

    ansible-playbook delete_rg.yml --extra-vars "name=<resource_group>"
    

    重要なポイント:

    • プレイブックの register 変数と debug セクションにより、コマンドの完了時に結果が表示されます。

次のステップ