Azure REST APIを使ってApp Serviceを作成してみた

2022.04.03

いわさです。

普段はAzureリソースを作成する際はAzureポータルかAzure CLIを使って操作しています。
REST APIで操作出来ることを知ってはいたのですが、実際に試したことがなかったのでリファレンスを行ったり来たりしながら試してみました。

今回はプラットフォームはLinux、ランタイムはPHP 7.4のApp Serviceを作成してみます。
環境として、クライアントはmacOSを使っていて、Azure CLIセットアップ済みです。

この記事の内容としては、初めてREST APIでAzureリソースを操作するような、基本的な内容になっています。

やってみる

流れは以下です。

  • 認証
  • リソースグループ作成
  • App Serviceプラン作成
  • App Service作成

認証

パイプラインなどで自動化をする際は、以下のようにデプロイ用のサービスプリンシパルを作成しておくのが定石のようです。

本日はREST APIを試すだけなので認証部分はaz loginでブラウザから人の手で認証します。

$ az login
The default web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`.

認証できたら、REST APIで使用するアクセストークンを取得します。

$ az account get-access-token
{
  "accessToken": "<hogehoge-accesstoken>",
  "expiresOn": "2022-04-03 10:03:28.000000",
  "subscription": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "tenant": "11111111-2222-3333-4444-555555555555",
  "tokenType": "Bearer"
}

この後の手順で、accessTokenを使います。

リソースグループ作成

リソースグループ作成のリファレンスはこちらです。

 リージョンとリソース名だけ指定します。
URLにサブスクリプションIDが含まれているので、アクセストークン取得時のsubscriptionなどに置き換えてください。

Request

$ curl -X PUT "https://management.azure.com/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourcegroups/20220403restapi?api-version=2021-04-01" -d '
{
    "location": "Japan East"
}' -H "Content-Type: application/json" -H "Authorization: Bearer <hogehoge-accesstoken>"

ここでのポイントというよりREST API全般としてですが、Content-TypeヘッダーとAuthorizationヘッダーは必須になっています。
指定していない場合はそれぞれ以下のようなエラーとなります。

Content-Typeなし

{
    "error": {
        "code": "UnsupportedMediaType",
        "message": "The content media type 'application/x-www-form-urlencoded' is not supported. Only 'application/json' is supported."
    }
}

Authorizationなし

{
    "error": {
        "code": "AuthenticationFailed",
        "message": "Authentication failed. The 'Authorization' header is missing."
    }
}

App Sericeプラン作成

App Serivceをホストするためのプランを先に作成しましょう。

$ curl -X PUT "https://management.azure.com/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/20220403restapi/providers/Microsoft.Web/serverfarms/iwasa0403restapp-plan?api-version=2021-02-01" -d '
{
    "location": "Japan East",
    "sku": {
        "name": "B1"
    },
    "properties": {
        "reserved": true
    }
}' -H "Content-Type: application/json" -H "Authorization: Bearer <hogehoge-accesstoken>"

ここでのポイントとしては、properties.reservedを指定することでしょうか。
trueを指定するとプラットフォームがLinux、falseあるいは省略でWindowsになります。

私はここに気づかずに、参考にエクスポートしていたARMテンプレートから、kindで指定するものかと勘違いして、以下のようなリクエストを最初送ってしまい、Windows環境を作ってしまっていました。

Windows環境が作られてしまう

$ curl -X PUT "https://management.azure.com/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/20220403restapi/providers/Microsoft.Web/serverfarms/iwasa0403restapp-plan?api-version=2021-02-01" -d '
{
    "location": "Japan East",
    "sku": {
        "name": "B1"
    },
    "kind": "linux"
}' -H "Content-Type: application/json" -H "Authorization: Bearer <hogehoge-accesstoken>"

余談ですが、最初F1で作成しようとして以下のエラーとなり、サブスクリプション内で1リージョンあたりのLinuxのF1プランを作成出来るのが1つまでだとこの時学びました。
作成しようとすると以下のエラーが発生します。

{
    "Code": "Unauthorized",
    "Message": "This subscription has reached the limit of 1 Free Linux app service plan(s) it can create in this region. Please choose a different sku or region.",
    "Target": null,
    "Details": [
        {
            "Message": "This subscription has reached the limit of 1 Free Linux app service plan(s) it can create in this region. Please choose a different sku or region."
        },
        {
            "Code": "Unauthorized"
        },
        {
            "ErrorEntity": {
                "ExtendedCode": "52041",
                "MessageTemplate": "This subscription has reached the limit of {0} Free Linux app service plan(s) it can create in this region. Please choose a different sku or region.",
                "Parameters": [
                    "1"
                ],
                "Code": "Unauthorized",
                "Message": "This subscription has reached the limit of 1 Free Linux app service plan(s) it can create in this region. Please choose a different sku or region."
            }
        }
    ],
    "Innererror": null
}

App Service作成

最後に、App SerivceプランにApp Serviceを載せます。

% curl -X PUT "https://management.azure.com/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/20220403restapi/providers/Microsoft.Web/sites/iwasa0403restapp?api-version=2021-02-01" -d '
{
    "location": "Japan East",
    "properties": {
        "serverFarmId": "/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/20220403restapi/providers/Microsoft.Web/serverfarms/iwasa0403restapp-plan",
        "siteConfig": {
            "linuxFxVersion": "PHP|7.4"
        }
    }
}' -H "Content-Type: application/json" -H "Authorization: Bearer <hogehoge-accesstoken>"

ポイントとしては、siteConfig.linuxFxVersionでランタイムを指定していることくらいでしょうか。
ここでは上記しか設定していないのですが、このpropertiesには様々な設定があり、省略すると色々とデフォルトで動いている状態になります。実際に環境を構築する際にはどのパラメータでどういう設定がされているか、既定値は何になるのかを知っておく必要がありそうです。

ちなみに、前述のとおり当初誤ってWindowsでApp Serviceプランを作成してしまってまして、その場合はlinuxFxVersionで以下のエラーが発生しました。エラーメッセージでは"invalidだぞ"という内容までだったのでWindowsでプラン作ってることにすぐには気づきませんでしたので、参考までに載せておきます。

{
    "Code": "BadRequest",
    "Message": "The parameter LinuxFxVersion has an invalid value.",
    "Target": null,
    "Details": [
        {
            "Message": "The parameter LinuxFxVersion has an invalid value."
        },
        {
            "Code": "BadRequest"
        },
        {
            "ErrorEntity": {
                "ExtendedCode": "01007",
                "MessageTemplate": "The parameter {0} has an invalid value.",
                "Parameters": [
                    "LinuxFxVersion"
                ],
                "Code": "BadRequest",
                "Message": "The parameter LinuxFxVersion has an invalid value."
            }
        }
    ],
    "Innererror": null
}

PHPの動作を軽く確認

最後に、デプロイされたApp Serviceなどを確認して終わりましょう。

App ServiceプランはLinuxでデプロイされていますね。

App ServiceはPHP 7.4で構成されています。

AzureポータルからWebSSHで環境にアクセスしてみます。

  _____                               
  /  _  \ __________ _________   ____  
 /  /_\  \___   /  |  \_  __ \_/ __ \ 
/    |    \/    /|  |  /|  | \/\  ___/ 
\____|__  /_____ \____/ |__|    \___  >
        \/      \/                  \/ 
A P P   S E R V I C E   O N   L I N U X

Documentation: http://aka.ms/webapp-linux
PHP quickstart: https://aka.ms/php-qs
PHP version : 7.4.24
Note: Any data outside '/home' is not persisted
root@57a7ee32754e:/home# ps -x
  PID TTY      STAT   TIME COMMAND
    1 ?        SNs    0:00 /bin/sh /opt/startup/startup.sh
   24 ?        SNs    0:00 /usr/sbin/sshd
   30 ?        SN     0:00 apache2 -DFOREGROUND
   48 ?        SNs    0:00 sshd: root@pts/0
   50 pts/0    SNs    0:00 -bash
   53 pts/0    RN+    0:00 ps -x

Apacheが動いていますね。
PHP 8だとNginxになります。

/home/site/wwwrootに適当なスクリプトを作ってみましょう。

root@57a7ee32754e:/home/site/wwwroot# cat index.php 
<?php echo 'Hello World'; ?>

ハロー。うまくいきました。

さいごに

本日は普段私が使い慣れていない、Azure REST APIでApp Serviceを作成してみました。
cURLを使ったのもあり、Azure CLIなどは使いやすいなと感じました。しかしREST APIで構築出来ると、別途モジュールの無い環境でも汎用的にHTTPでリソースの操作が出来るようになるので、使えるようにはなっておきたいですね。