Azure の仮想ネットワーク(VNet)内サブネットを削除しようとしたとき、「serviceAssociationLinks/AppServiceLink により使用中のため削除できない」とブロックされるケースが増えています。実際にはサブネット上のリソースをすべて削除しているのに解消せず、ポータルや CLI で何度試しても先に進めない…。本記事では、その原因となる Service Association Link(SAL) を Azure CLI で安全に消去し、サブネットを削除できるようにする具体的な手順を詳しく解説します。
Azure VNet サブネットが AppServiceLink で削除できない現象
まず、問題となるエラーメッセージを整理します。Azure ポータルからサブネットを削除しようとすると、次のようなメッセージが表示されることがあります。
Subnet <サブネット名> is in use by
.../serviceAssociationLinks/AppServiceLink
and cannot be deleted.
Subnet is in use by resources. Please remove them before deleting this subnet.
CLI から削除した場合も同様で、
az network vnet subnet delete ...
> Subnet is in use and cannot be deleted
> ... serviceAssociationLinks/AppServiceLink ...
といった趣旨のエラーが返ってきます。
しかし実際には、以下のように一通り確認しても原因が見つからないことがあります。
- 仮想マシン、NIC、NAT ゲートウェイなどはすべて削除済み
- プライベート エンドポイントも存在しない
- ルート テーブル / NSG もサブネットから切り離し済み
- App Service からの VNet 統合もポータル上は無効になっている
それでもなお serviceAssociationLinks/AppServiceLink が残っているため、サブネットの削除だけができない――これが本記事で扱う問題です。
原因:App Service の VNet 統合が残した Service Association Link(SAL)
この症状の正体は、App Service の仮想ネットワーク統合(VNet Integration)が内部的に作成する Service Association Link(SAL) の「残骸」です。
App Service で VNet 統合を設定すると、対象のサブネットには以下のような SAL が自動的に作成されます。
| 項目 | 内容 |
|---|---|
| リソース種別 | Service Association Link (SAL) |
| 識別子 | serviceAssociationLinks/AppServiceLink |
| 役割 | App Service からサブネットへのルーティング・トンネル等の関連付けを保持 |
| 可視性 | ポータル上からは直接見えない(ネットワーク関連の内部オブジェクト) |
通常は、App Service 側で「VNet 統合の削除(切断)」を行うと、この SAL も同時に削除されます。しかし、以下のようなパターンでは SAL だけがサブネット側に残ってしまう場合があります。
- App Service を先に削除し、その後に VNet やサブネットを削除しようとした
- プラン変更やスロット構成などを繰り返す中で、VNet 統合情報が不整合な状態になった
- サブスクリプション移行やリージョン変更など、大きな構成変更の途中で統合を解除した
この「孤立した SAL(orphaned SAL)」が残っている限り、Azure 側は「まだ App ServiceLink から利用中」と判断し、サブネットの削除を許可しません。
解決策の概要:未使用の VNet 統合を purge する
この問題に対して、Azure では 未使用の VNet 統合(orphaned SAL)を一括で削除する API が用意されています。
Azure CLI の az rest コマンドから以下のエンドポイントを叩くことで、指定したサブネットに紐づく未使用の VNet 統合(SAL)を purge(消去)できます。
az rest \
--method POST \
--uri "/subscriptions/<サブスクリプションID>/providers/Microsoft.Web/locations/<リージョン>/purgeUnusedVirtualNetworkIntegration?api-version=2024-04-01" \
--body "{'subnetResourceId': '<サブネットのリソースID>'}"
成功すると、レスポンスには以下のようなメッセージが含まれます。
"message": "Purged unused virtual network integration."
この状態になれば、Azure ポータルからも CLI からも、サブネット削除が行えるようになります。
事前準備:権限・環境・前提条件
コマンドを実行する前に、以下のポイントを確認しておきましょう。
必要な権限(RBAC)
少なくとも、対象サブスクリプションまたは対象リソース グループに対して 共同作成者(Contributor)以上 のロールが必要です。
AuthorizationFailedエラーが発生する場合は、RBAC の設定を確認する- 管理者に依頼して一時的に Contributor 権限を付与してもらう
Azure CLI のログインとコンテキスト
# Azure にログイン
az login
# 対象サブスクリプションを選択
az account set --subscription <サブスクリプションID>
Microsoft.Web リソース プロバイダーの登録
まだ登録されていない環境では、以下を事前に実行します。
az provider register --namespace Microsoft.Web
登録が完了していないと、purgeUnusedVirtualNetworkIntegration 呼び出し時にエラーとなる場合があります。
リージョン名は「表示名」ではなく API 名を使う
URI で指定する <リージョン> は、Azure リージョンの API 名 を使用します。
| ポータルの表示名 | API 名(URI で使う値) |
|---|---|
| Japan East | japaneast |
| Japan West | japanwest |
| North Europe | northeurope |
| East US | eastus |
誤って「Japan East」などの表示名を入れてしまうと、LocationNotFound などのエラーが返ってきます。
サブネットのリソース ID を取得する
purge API には、対象サブネットの リソース ID を渡す必要があります。Azure CLI から簡単に取得できます。
az network vnet subnet show \
-g <リソースグループ名> \
--vnet-name <VNet名> \
-n <サブネット名> \
--query id -o tsv
実行すると、次のような形式の文字列が返ってきます。
/subscriptions/<subId>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>/subnets/<subnet>
この値を、後で <サブネットのリソースID> としてそのまま利用します。
未使用 VNet 統合(SAL)の purge コマンド詳細
ここで、メインとなるコマンドの構成要素を整理します。
az rest \
--method POST \
--uri "/subscriptions/<サブスクリプションID>/providers/Microsoft.Web/locations/<リージョン>/purgeUnusedVirtualNetworkIntegration?api-version=2024-04-01" \
--body "{'subnetResourceId': '<サブネットのリソースID>'}"
| パラメーター | 説明 |
|---|---|
--method POST | HTTP の POST メソッドで API を呼び出す指定 |
--uri | purgeUnusedVirtualNetworkIntegration API のエンドポイント URI |
<サブスクリプションID> | 対象 VNet が存在するサブスクリプションの ID |
<リージョン> | VNet が存在するリージョンの API 名(例: japaneast) |
api-version=2024-04-01 | API のバージョン。指定がないとエラーになるので必須 |
--body | JSON 形式のリクエストボディ。subnetResourceId にサブネットのリソース ID を指定 |
--body の JSON 文字列中ではシングルクォートを使っていますが、必要に応じて環境に合わせてダブルクォートへ変更しても構いません(PowerShell など)。
PowerShell から実行する場合の例
Windows 環境で PowerShell を利用する場合は、クォートの扱いに注意します。例えば次のように書き換えると安定します。
$subnetId = "/subscriptions/<subId>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>/subnets/<subnet>"
az rest `
--method POST `
--uri "/subscriptions/<サブスクリプションID>/providers/Microsoft.Web/locations/<リージョン>/purgeUnusedVirtualNetworkIntegration?api-version=2024-04-01" `
--body "{""subnetResourceId"": ""$subnetId""}"
purge 実行後にサブネットを削除する
purge が成功すると、レスポンスメッセージに次のような文言が含まれます。
"message": "Purged unused virtual network integration."
この状態になったら、改めてサブネット削除を実行します。
ポータルから削除する場合
- 対象の仮想ネットワークを開く
- 該当のサブネットを選択
- 「削除」をクリックし、確認ダイアログに従って削除
Azure CLI から削除する場合
az network vnet subnet delete \
-g <リソースグループ名> \
--vnet-name <VNet名> \
-n <サブネット名>
以前まで出ていた serviceAssociationLinks/AppServiceLink 関連のエラーが出ず、正常に削除が完了すれば成功です。
それでも削除できないときに確認すべきポイント
SAL を purge してもサブネットが削除できない場合は、別の要因で「使用中」とみなされている可能性があります。代表的なチェックポイントをまとめます。
| チェック対象 | 確認内容 |
|---|---|
| プライベート エンドポイント | サブネットに紐づく Private Endpoint が残っていないか |
| NAT ゲートウェイ | サブネットに NAT Gateway が関連付けられていないか |
| ルート テーブル | カスタム ルート テーブルがサブネットに関連付いていないか |
| ネットワーク セキュリティ グループ | NSG がサブネットにアタッチされたままになっていないか |
| 仮想マシン / NIC | サブネット内の IP を使用している NIC が残っていないか |
| App Service 側の VNet 統合 | まだ有効な VNet 統合が残っていないか(App から統合を削除したか) |
特に、App Service 側でまだ VNet 統合が有効なままの場合、先にアプリごとに「VNet 統合の切断」を行う必要があります。その上で、改めて purge → 削除の手順を試してください。
よくあるエラーと対処方法
purge コマンド実行時やサブネット削除時に遭遇しやすいエラーと、その対処のヒントをまとめます。
| エラーの種類 | 想定される原因 | 対処の方向性 |
|---|---|---|
AuthorizationFailed | 実行ユーザーに必要な RBAC 権限がない | サブスクリプション / リソースグループで Contributor 以上の権限を付与する |
LocationNotFound | <リージョン> にポータルの表示名を使っている | japaneast / eastus など API 名に修正する |
BadRequest / Invalid subnetResourceId | subnetResourceId の文字列が正しくない、または対象サブネットが存在しない | az network vnet subnet show で再取得し、そのままコピペする |
ResourceNotFound | 指定した VNet/サブネット・サブスクリプションが誤っている、または既に削除済み | サブスクリプション ID / リソース グループ / VNet 名 / サブネット名を再確認する |
既存のワークアラウンドでは解決しないケースとの違い
この問題は、一般的な「サブネットが削除できない」トラブルシューティングではなかなか解決できないのが厄介なポイントです。
- ポータルで見えるリソースはすべて削除済み
- ネットワーク ウォッチャーなどで依存関係を見ても、何も残っていないように見える
- それでも
serviceAssociationLinks/AppServiceLinkのせいで削除できない
つまり、「見えないところに SAL が残っている」ことが本質的な原因であり、App Service 用の専用 API(purgeUnusedVirtualNetworkIntegration) を呼び出さない限り取り除けない、という点がポイントです。
サポート プランがあればマイクロソフト サポートに調査を依頼することもできますが、本記事の手順を使えば、自分自身で安全にクリーンアップを完了できます。
SAL が残りやすいシナリオと再発防止策
実務で SAL が残りがちなパターンと、それを避けるための運用上のポイントをいくつか挙げておきます。
App Service を先に削除してしまうケース
「もう使わないから」と App Service を先に削除し、その後にネットワーク構成(VNet やサブネット)を片付けようとすると、SAL だけが取り残されることがあります。
- VNet 統合が有効な App Service を削除する前に、VNet 統合を明示的に無効化する
- VNet 統合をまとめて管理する運用ルール(命名規則やドキュメント)を作っておく
検証環境・一時的な環境の乱立
検証用の App Service や VNet を短いサイクルで作成・削除していると、うっかり VNet 統合を切り忘れたままアプリを削除してしまう確率が上がります。
- 「環境クリーンアップ手順」の中に「App Service の VNet 統合解除」を明記する
- 定期的に VNet 統合の状態を棚卸しし、不要な統合を先に解消しておく
サブスクリプション / VNet 移行時の注意点
サブスクリプションや VNet 単位での移行や再構築を行う場合も、SAL の取り残しが発生しやすいタイミングです。
- 移行前に App Service 側の VNet 統合をすべて洗い出す
- 統合を解除 → SAL が残る場合は purge を実行 → その後に VNet/サブネットを削除するという順序を徹底する
実務で使えるチェックリスト
最後に、同様のトラブルに遭遇したときにすぐ使えるチェックリストをまとめます。
サブネット削除前の確認チェックリスト
- サブネットに紐づく VM / NIC / プライベート エンドポイント / NAT ゲートウェイが残っていないか
- サブネットにルート テーブル / NSG が関連付いていないか
- App Service 側で VNet 統合が有効なアプリが残っていないか
App Service VNet 統合関連のチェック
- App Service ポータルで「ネットワーク」→「VNet 統合」を確認し、不要な統合は削除したか
- 統合を削除した後もサブネットが削除できない場合は、SAL が残っていないか疑う
- SAL が疑われる場合、本記事の
purgeUnusedVirtualNetworkIntegrationを実行する
purge コマンド実行後の確認
- レスポンスに
"Purged unused virtual network integration."が含まれているか - サブネット削除を再度実施し、エラーが解消しているか
- 同様の構成を持つ他のサブネットがあれば、同じ手順で事前にクリーンアップしておく
まとめ:AppServiceLink で削除できないサブネットは SAL の purge で解決できる
Azure の VNet サブネットが serviceAssociationLinks/AppServiceLink により削除できない場合、その原因はほぼ確実に App Service の VNet 統合が残した孤立した Service Association Link(SAL) です。
本記事で紹介したように、Azure CLI の az rest から purgeUnusedVirtualNetworkIntegration API を呼び出し、対象サブネットのリソース ID を指定して purge を実行することで、この SAL を安全に除去できます。成功メッセージ "Purged unused virtual network integration." を確認した後であれば、ポータルや CLI からサブネットを問題なく削除できるようになります。
サポート プランがない環境でも、自力でこの問題を解消できる手段として非常に有用です。今後、Azure App Service の VNet 統合を使ったネットワーク設計を行う際には、「削除時は必ず VNet 統合解除 → SAL purge → サブネット削除」という流れを意識しておくことで、同様のトラブルを未然に防げるでしょう。

コメント