4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

背景

会社において、月の請求で三桁万円の高額請求が発生した。

理由はと言えば、provisioned model を意識せずにデプロイしていた、という話。

本来であれば、コスト管理で予算設定しておいてアラーム通知で即検知、の流れなんですが・・
コスト管理権限が制約されていた為に、気付けなかった、という :sweat:

ということで、サブスクリプションのデプロイ状況を調べる script を用意してみた記録

サブスクリプションで制限してしまう場合は、policy で

Provisioned のデプロイを制限する方法
{
    "policyRule": {
        "if": {
            "allOf": [
                {
                    "field": "type",
                    "equals": "Microsoft.CognitiveServices/accounts/deployments"
                },
                {
                    "field": "Microsoft.CognitiveServices/accounts/deployments/sku.name",
                    "equals": "ProvisionedManaged"
                }
            ]
        },
        "then": {
            "effect": "Deny"
        }
    }
}

出力イメージ

この sku 部分を確認すればよい筈

サブスクリプション名 サブスクリプション ID リソースグループ名 リソース名 モデル名 SKU バージョン デプロイメント名
Visual Studio Professional サブスクリプション {subscription ID} {resource group} {resource name} gpt-4o GlobalStandard 2024-05-13 gpt-4o-deployment

script

  • $output_file に指定したファイルに、markdown の表として出力
  • 自分のアクセスできるサブスクリプション内の、OpenAI リソースにおける、デプロイモデルを一覧化
OpenAI model check
# 初期設定
$output_file = "result_DeploymentModels.md"
$defaultSubscription = az account show --query "id" -o tsv

# 出力ファイルの存在をチェックし、存在しない場合は新規作成
if (-Not (Test-Path -Path $output_file)) {
    New-Item -Path $output_file -ItemType File
} else {
    Set-Content -Path $output_file -Value $null
}

# ヘッダー行を追加
Add-Content -Path $output_file -Value "| サブスクリプション名 | サブスクリプション ID | リソースグループ名 | リソース名 | モデル名 | SKU | バージョン | デプロイメント名 |"
Add-Content -Path $output_file -Value "| --- | --- | --- | --- | --- | --- | --- | --- |"

# 現在のAzureサブスクリプションリストを取得
$subscriptions = az account list --query "[].{Name:name, Id:id}" -o tsv

foreach ($subscription in $subscriptions) {
    $subscriptionDetails = $subscription -split "`t"
    $subscriptionName = $subscriptionDetails[0]
    $subscriptionId = $subscriptionDetails[1]

    try {
        # サブスクリプションを設定
        az account set --subscription $subscriptionId

        Write-Host "サブスクリプションを確認中: $subscriptionName ($subscriptionId)"

        # OpenAIサービスリソースのリストを取得
        $resources = az cognitiveservices account list --query "[?kind=='OpenAI'].{Name:name, ResourceGroup:resourceGroup}" -o tsv

        if (-not $resources) {
            Write-Host "対象のサブスクリプションにOpenAIリソースがありません: $subscriptionId"
            Add-Content -Path $output_file -Value "| $subscriptionName | $subscriptionId | - | OpenAI リソースがありません | - | - | - | - |"
        } else {
            foreach ($resource in $resources) {
                $resourceDetails = $resource -split "`t"
                $resourceName = $resourceDetails[0]
                $resourceGroup = $resourceDetails[1]

                Write-Host "リソースを確認中: $resourceName (リソースグループ: $resourceGroup)"

                try {
                    # リソースのデプロイメント情報を取得
                    $deployments = az cognitiveservices account deployment list --name $resourceName --resource-group $resourceGroup --output json

                    $deployments = $deployments | ConvertFrom-Json

                    if (-not $deployments) {
                        Add-Content -Path $output_file -Value "| $subscriptionName | $subscriptionId | $resourceGroup | $resourceName | デプロイ無し | - | - | - |"
                    } else {
                        foreach ($deployment in $deployments) {
                            $deploymentName = $deployment.name
                            $modelName = $deployment.properties.model.name
                            $modelVersion = $deployment.properties.model.version
                            $skuName = $deployment.sku.name

                            Add-Content -Path $output_file -Value "| $subscriptionName | $subscriptionId | $resourceGroup | $resourceName | $modelName | $skuName | $modelVersion | $deploymentName |"
                        }
                    }
                } catch {
                    $errorMsg = "デプロイメント情報の取得中にエラーが発生しました。"
                    Write-Host "$errorMsg リソース: $resourceName (リソースグループ: $resourceGroup)"
                    Add-Content -Path $output_file -Value "| $subscriptionName | $subscriptionId | $resourceGroup | $resourceName | デプロイメント情報取得エラー | - | - | - |"
                }
            }
        }
    } catch {
        $errorMsg = "サブスクリプションの設定中にエラーが発生しました。"
        Write-Host "$errorMsg サブスクリプション: $subscriptionId"
        Add-Content -Path $output_file -Value "| $subscriptionName | $subscriptionId | - | - | エラー | - | - | - |"
    }
}

az account set --subscription $defaultSubscription
Write-Host "デプロイ済みモデル情報が $output_file に保存されました。"

あとがき

まぁ、コストはオープンにしないと、コスト意識なんて育たないよねっていう良い例かなと思う。

そういう意味で、給料も経費も全部見える化してしまえば、
給料泥棒なんて減るんじゃないの?って思ってる。

とはいえ、年を重ねて楽をして稼ぎたいっていう上位層が多いんだろうなぁ・・とも

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?