1. ホーム
  2. アッキー

ROSを使ってワンクリックでデータディスクの作成、パーティション設定、フォーマット、マウントが可能

2022-03-21 12:46:44

あらゆるアプリケーションには、データを保存する必要があります。AliCloud ECSは、ユーザーのニーズに合わせて、通常のクラウドディスク、効率的なクラウドディスク、SSDのクラウドディスクの3種類のデータディスクを提供します。ECSコンソールは、各インスタンスに最大4つの空のデータディスクを作成したり、既存のデータディスクのスナップショットを基にデータ付きクラウドディスクを4つ生成したりすることができます。ただし、上記の方法で生成されたデータ用クラウドディスクは直接使用することができず、ユーザーがECSインスタンスにログインして手動で設定する必要があります。これは、複数のECSインスタンスを導入しているユーザーにとって、多くの手作業が必要であり、エラーが発生しやすいという問題があります。

この記事では、リソースオーケストレーションに基づいてデータディスクをワンクリックで作成し、それを ユーザーデータ データディスクのパーティション分割、フォーマット、マウントを自動的に行う便利な方法です。

データディスクの作成

データディスクを作成する方法は2つあります。

  1. ECSインスタンスの属性として

    ディスクマッピング

    DiskMappingsはリスト型のプロパティで、リストの各項目はデータディスクの定義を表し、ユーザーはディスク名、サイズ、タイプ、およびソースsnapshotIdを指定することができます。

  2. スタックのリソースとして、ディスクリソースは対応するECSに関連付けられます。

    ALIYUN::ECS::Disk

    このようなリソースをテンプレートに指定することは、ディスクを作成する必要があることを意味し、ユーザーはディスク名、サイズ、ドメイン、ソースsnapshotIdなどを指定することになります。

    ALIYUN::ECS::DiskAttachment

    どのデータディスクをどのECSインスタンスと関連付けるかを指定します。指定する属性は、ALIYUN::ECS::DiskのIdとECSインスタンスのIdが必要です。

    上記のソースデータ付きクラウドディスクの作成方法に関わらず、ソースデータディスクのスナップショットは、作成するデータディスクと同じドメインにある必要があります。

UserDataでデータディスクを扱う

ROSにはUserDataという仕組みがあり、ECSの作成時に初めて起動する際に、ECSの設定や初期化作業を行うUserDataスクリプトを指定することができます。ユーザは、必要に応じて自由にUserDataスクリプトを書くことができます。以下では、ROSとUserData機構を使ってデータディスクを作成し、ワンクリックで自動的にパーティション、フォーマット、マウントを行う方法を具体的に2つの簡単な例で説明します。

UserDataフッターは空のデータディスクを処理する

この例では、ECSインスタンスを作成し、インスタンス用に2つの空のデータディスクを作成し、インスタンスをAliCloudの専用ネットワークに置き、その後のアクセスのためにインスタンスにエラスティックIPを割り当てます。ROSがどのようにデータディスクを作成するかを説明するためにDiskMappingsインスタンスプロパティを使用しており、この例ではデータディスクの名前とサイズを定義しています。UserDataに簡単なスクリプトが割り当てられており、まずfdiskコマンドでディスクを分割し、次にext4でディスクをフォーマットし、最後にディスクをマウントし、最後にECSが起動するたびにディスクが適切にマウントされるように/etc/fstabを構成しています。この例では、ユーザーは TotalDataDisk によってデータディスクの数を指定し、MountPoint によってデータディスクのマウントポイントを指定します。また、ROSのWaitConditionリソースを指定してUserDataスクリプトの結果を取得しています。WaitConditionの使用方法は、以下のページに記載されています。 こちら . 最終的なテンプレートは以下の通りです。

{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Parameters": {
    "VpcName": {
      "MaxLength": 128,
      "Description": "VPC Name",
      "Type": "String",
      "ConstraintDescription": "[2, 128] English or Chinese characters",
      "MinLength": 2
    },
    "SecurityGroupName": {
      "Description": "SecurityGroupName",
      "Type": "String"
    },
    "VpcCidrBlock": {
      "Default": "10.0.0.0/8",
      "AllowedValues": [
        "192.168.0.0/16",
        "172.16.0.0/12",
        "10.0.0.0/8"
      ],
      "Type": "String"
    },
    "Password": {
      "NoEcho": true,
      "MaxLength": 30,
      "Description": "ECS login password. ",
      "Type": "String",
      "ConstraintDescription": "8-30 characters, can contain upper and lower case letters and special characters",
      "MinLength": 8
    },
    "DiskSize": {
      "Default": 40,
      "Type": "Number"
    },
    "TotalDataDisk": {
      "Description": "The number of data disks the instance is hanging on",
      "Type": "String"
    },
    "ZoneId": {
      "Description": "Available Zone Id, <a href='#/product/cn-shenzhen/list/zoneList' target='_blank'>View Available Zones</a>",
      "Type": "String"
    },
    "DiskName": {
      "Type": "String"
    },
    "SystemDiskCategory": {
      "Default": "cloud",
      "AllowedValues": [
        "cloud",
        "cloud_efficiency",
        "cloud_ssd"
      ],
      "Description": "Disk type of system disk, normal cloud (cloud), efficient cloud (cloud_efficiency) or SSD cloud (cloud_ssd)",
      "Type": "String"
    },
    "MountPoint": {
      "Description": "Mount point of data disk",
      "Type": "String"
    },
    "DestinationCidrBloc
    "SecurityGroup": {
      "Type": "ALIYUN::ECS::SecurityGroup",
      "Properties": {
        "SecurityGroupName": {
          "Ref": "SecurityGroupName"
        },
        "VpcId": {
          "Ref": "Vpc"
        }
      }
    },
    "NewEip": {
      "Type": "ALIYUN::ECS::EIP",
      "Properties": {
        "InternetChargeType": "PayByTraffic",
        "Bandwidth": 1
      }
    },
    "SecurityGroupIngress": {
      "Type": "ALIYUN::ECS::SecurityGroupIngress",
      "Properties": {
        "SourceCidrIp": "0.0.0.0/0",
        "SecurityGroupId": {
          "Ref": "SecurityGroup"
        },
        "IpProtocol": "all",
        "NicType": "intranet",
        "PortRange": "-1/-1"
      }
    },
    "WebServer": {
      "Type": "ALIYUN::ECS::Instance",
      "Properties": {
        "IoOptimized": "optimized",
        "ImageId": "centos6u5_64_40G_cloudinit_20160427.raw",
        "SecurityGroupId": {
          "Ref": "SecurityGroup"
        },
        "Password": {
          "Ref": "Password"
        },
        "DiskMappings": [
          {
            "DiskName": {
              "Ref": "DiskName"
            },
            "Size": {
              "Ref": "DiskSize"
            }
          },
          {
            "Size": {
              "Ref": "DiskSize"
            }
          }
        ],
        "SystemDiskCategory": {
          "Ref": "SystemDiskCategory"
        },
        "UserData": {
          "Fn::Join": [
            "",
            [
              "#! /bin/sh\n",
              "logs=~/mount_logs\n",
              "i=1\n",
              "total=",
              {
                "Ref": "TotalDataDisk"
              },
              "\n",
              "mountpoint=",
              {
                "Ref": "MountPoint"
              },
              "\n",
              "while [ $i -le $total ]\n",
              "do\n",
              " j=`echo $i|awk '{printf \"%c\", 97+$i}'\n",
              "fdisk -S 56 /dev/vd$j <<ESXU\n",
              "n\n",
              "p\n",
              "1\n",
              "\n",
              "\n",
              "w\n",
              "ESXU\n",
              " echo \"/dev/vd$j is fdisked!\" >> $logs\n",
              " mkfs.ext4 /dev/vd${j}1\n",
              " if [ $? -eq 0 ];then\n",
              " echo \"/dev/vd${j}1 is formated!\" >> $logs\n",
              " fi\n",
              " touch ~/test_ftab\n",
              " mkdir $mountpoint$i\n",
              "cat << ESXU > ~/test_ftab\n",
              "/dev/vd${j}1 $mountpoint$i ext4 defaults 0 0\n",
           

ソースデータを含むデータディスクを処理するUserDataスクリプト

この例では、ソースデータのスナップショットに基づいてデータディスクを作成します。その他は上記の例と同様です。この時点で、新しいECSインスタンスのデータディスクはすでにパーティションが切られフォーマットされているので、あとはデータディスクを適切なマウントポイントにマウントするだけです。TotalDataDiskはデータディスクの数を、MountPointはデータディスクのマウントポイントを指定し、ROSのWaitConditionリソースはUserDataスクリプトの実行結果を取得するために使用されます。最終的なテンプレートはこちらです。

{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Parameters": {
    "VpcName": {
      "MaxLength": 128,
      "Description": "VPC Name",
      "Type": "String",
      "ConstraintDescription": "[2, 128] English or Chinese characters",
      "MinLength": 2
    },
    "DataDisk2SnapshotId": {
      "Description": "Create data disk 2 from this snapshot",
      "Type": "String"
    },
    "Password": {
      "NoEcho": true,
      "MaxLength": 30,
      "Description": "ECS login password. ",
      "Type": "String",
      "ConstraintDescription": "8-30 characters, can contain upper and lower case letters and special characters",
      "MinLength": 8
    },
    "DiskName": {
      "Type": "String"
    },
    "ZoneId": {
      "Description": "Available Zone Id, <a href='#/product/cn-shenzhen/list/zoneList' target='_blank'>View Available Zones</a>",
      "Type": "String"
    },
    "DestinationCidrBlock": {
      "Default": "192.168.1.0",
      "Description": "Route's target segment, e.g. 192.168.1.0/24 or 192.168.1.0",
      "Type": "String"
    },
    "MountPoint": {
      "Description": "Mount point of data disk",
      "Type": "String"
    },
    "VSwitchCidrBlock": {
      "Default": "10.0.10.0/24",
      "Description": "VSwitch network segment, this segment must belong to VPC",
      "Type": "String"
    },
    "DataDisk1SnapshotId": {
      "Description": "Create data disk 1 from this snapshot",
      "Type": "String"
    },
    "SecurityGroupName": {
      "Description": "SecurityGroupName",
      "Type": "String"
    },
    "VpcCidrBlock": {
      "Default": "10.0.0.0/8",
      "AllowedValues": [
        "192.168.0.0/16",
        "172.16.0.0/12",
        "10.0.0.0/8"
      ],
      "Type": "String"
    },
    "DiskSize": {
      "Default": 40,
      "Type": "Number"
    },
    "TotalDataDisk": {
      "Description": "The number of data disks the instance is hanging on",
      "Type": "String"
    },
    "SystemDiskCategory": {
      "Default": "cloud",
      "AllowedValues": [
        "cloud",
        "cloud_efficiency",
        "cloud_ssd"
      ],
      "Description": "Disk type of system disk, normal cloud (cloud), efficient cloud (cloud_efficiency) or SSD cloud (cloud_ssd)",
      "Type": "String"
    }
  },
  "Resources": {
    "VSwitch": {
      "Type": "ALIYUN::ECS::VSwitch",
      "Properties": {
        "CidrBlock": {
          "Ref": "VSwitchCidrBlock"
        },
        "ZoneId": {
          "Ref": "ZoneId"
        },
        "VpcId": {
          "Fn::GetAtt": [
            "Vpc",
            "VpcId"
          ]
        }
      }
    },
 
        "NicType": "intranet",
        "PortRange": "-1/-1"
      }
    },
    "WebServer": {
      "Type": "ALIYUN::ECS::Instance",
      "Properties": {
        "IoOptimized": "optimized",
        "ImageId": "centos6u5_64_40G_cloudinit_20160427.raw",
        "SecurityGroupId": {
          "Ref": "SecurityGroup"
        },
        "Password": {
          "Ref": "Password"
        },
        "DiskMappings": [
          {
            "SnapshotId": {
              "Ref": "DataDisk1SnapshotId"
            },
            "DiskName": {
              "Ref": "DiskName"
            },
            "Size": {
              "Ref": "DiskSize"
            }
          },
          {
            "SnapshotId": {
              "Ref": "DataDisk2SnapshotId"
            },
            "Size": {
              "Ref": "DiskSize"
            }
          }
        ],
        "SystemDiskCategory": {
          "Ref": "SystemDiskCategory"
        },
        "UserData": {
          "Fn::Join": [
            "",
            [
              "#! /bin/sh\n",
              "logs=~/mount_logs\n",
              "i=1\n",
              "total=",
              {
                "Ref": "TotalDataDisk"
              },
              "\n",
              "mountpoint=",
              {
                "Ref": "MountPoint"
              },
              "\n",
              "while [ $i -le $total ]\n",
              "do\n",
              " j=`echo $i|awk '{printf \"%c\", 97+$i}'\n",
              " touch ~/test_ftab\n",
              " mkdir $mountpoint$i\n",
              "cat << ESXU > ~/test_ftab\n",
              "/dev/vd${j}1 $mountpoint$i ext4 defaults 0 0\n",
              "ESXU\n",
              " cat ~/test_ftab >> /etc/fstab\n",
              " mount -a\n",
              " chmod -R 777 $mountpoint$i\n",
              " rm -rf ~/test_ftab\n",
              " echo \"/dev/vd${j}1 is mounted!\" >> $logs\n",
              " let i+=1\n",
              "done\n",
              "\n",
              {
                "Fn::GetAtt": [
                  "WaitConHandle",
                  "CurlCli"
                ]
              },
              " -d '{\"id\" : \"webserver\", \"data\" : \"mount disk\"}'\n"
            ]
          ]
        },
        "VSwitchId": {
          "Ref": "VSwitch"
        },
        "VpcId": {
          "Ref": "Vpc"
        },
        "InstanceType": "ecs.n1.small"
      }
    },
    "WaitConHandle": {
      "Type": "ALIYUN::ROS::WaitConditionHandle"
    },
    "EIPBind": {
      "Type": "ALIYUN::ECS::EIPAssociation",
      "Properties": {
        "InstanceId":

備考

上記の2つの例では、ROSスタックリソースを使用してデータディスクを作成するのではなく、DiskMappingsプロパティを使用していることに気づきました。これは、DiskMappingsがECSリソースのプロパティであるため、ブートECSが作成されるときに、データディスクはすでに作成され、ECSインスタンスに関連付けされているためです。そして、UserDataの実行により、パーティショニング、フォーマット、マウントが完了します。しかし、データディスクをROSスタックリソースとして作成した場合、ECSリソースとDiskリソースが先に作成され、ディスクとECSインスタンスの関連付けが最後に行われます。そのため、ECSインスタンスの起動時には、ディスクと対応するECSが実際には関連付けられておらず、この場合、UserDataスクリプトはディスクを見つけることができず、パーティショニング、フォーマット、およびマウントを行うことができなくなります。データディスクを使用し、UserDataで自動マウントしたい場合は、DiskMappingsを使用してデータディスクを作成することをお勧めします。