deployment-stacks-2025 について
deployment-stacks-2025は、Azure Deployment Stacksのリファレンススキルです。リソースのライフサイクル管理、保護、クリーンアップ方針、運用を扱い、リソースグループ、サブスクリプション、管理グループの各スコープでデプロイを管理するAzureインフラチーム向けです。
主な機能
- 01スタック内リソースの一元管理
- 02拒否設定によるリソース保護
- 03管理対象から外す際のポリシー
- 04リソースグループ、サブスクリプション、管理グループのスコープ
- 05Azure CLIとBicepの例
活用シーン
- 01本番リソースの変更や削除を防ぐ
- 02テンプレートから除外したリソースを整理する
- 03異なるAzureスコープでインフラを管理する
- 04Azure Blueprintsからの移行を計画する
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ josiahsiegel/ claude-plugin-marketplace --skill deployment-stacks-2025インストール後、Claude Code で/deployment-stacks-2025を入力して読み込まれたか確認します。
同梱ファイルreferences/cicd-monitoring.md
詳細
Azure Deployment Stacks - 2025 GA の機能
Azure Deployment Stacks に関する完全なナレッジベースです。Azure Blueprints の後継機能であり、2024 年に GA となり、2025 年のベストプラクティスに対応しています。
概要
Azure Deployment Stacks は、Azure リソースのコレクションを単一のアトミックな単位として管理するリソースの種類です。統合されたライフサイクル管理、リソース保護、自動クリーンアップ機能を提供します。
主な機能
1. 統合されたリソース管理
- 複数のリソースを単一のエンティティとして管理
- スタック全体に対する更新、エクスポート、削除操作
- 管理対象のすべてのリソースを一元的に追跡
- 環境間で一貫したデプロイ
2. 拒否設定(リソース保護)
管理対象のリソースへの不正な変更を防止します。
- None:制限なし(デフォルト)
- DenyDelete:リソースの削除を防止
- DenyWriteAndDelete:更新と削除を防止
3. ActionOnUnmanage(クリーンアップポリシー)
テンプレートに含まれなくなったリソースの処理を制御します。
- detachAll:リソースをスタック管理から解除し、リソースは保持
- deleteAll:テンプレートに含まれないリソースを削除
- deleteResources:管理対象外のリソースを削除し、リソースグループは保持
4. 柔軟なスコープ
スタックを次のスコープにデプロイできます。
- リソースグループのスコープ
- サブスクリプションのスコープ
- 管理グループのスコープ
5. Azure Blueprints の後継
Azure Blueprints は2026 年 7 月に非推奨となる予定です。推奨される後継機能は Deployment Stacks です。
前提条件
Azure CLI のバージョン
# Requires Azure CLI 2.61.0 or later
az version
# Upgrade if needed
az upgrade
Azure PowerShell のバージョン
# Requires Azure PowerShell 12.0.0 or later
Get-InstalledModule -Name Az
Update-Module -Name Az
Deployment Stacks の作成
サブスクリプションスコープのスタック
# Create deployment stack at subscription level
az stack sub create \
--name MyProductionStack \
--location eastus \
--template-file main.bicep \
--parameters @parameters.json \
--deny-settings-mode DenyWriteAndDelete \
--deny-settings-excluded-principals <devops-service-principal-id> <admin-group-id> \
--action-on-unmanage deleteAll \
--description "Production infrastructure managed by deployment stack" \
--tags Environment=Production ManagedBy=DeploymentStack CostCenter=Engineering
# What-if analysis before deployment
az stack sub what-if \
--name MyProductionStack \
--location eastus \
--template-file main.bicep \
--parameters @parameters.json
# Create with confirmation prompt disabled
az stack sub create \
--name MyDevStack \
--location eastus \
--template-file main.bicep \
--deny-settings-mode None \
--action-on-unmanage detachAll \
--yes
リソースグループスコープのスタック
# Create resource group
az group create \
--name MyRG \
--location eastus \
--tags Environment=Production
# Create deployment stack
az stack group create \
--name MyAppStack \
--resource-group MyRG \
--template-file main.bicep \
--parameters environment=production \
--deny-settings-mode DenyDelete \
--action-on-unmanage deleteAll \
--description "Application infrastructure stack"
管理グループスコープのスタック
# Create stack at management group level
az stack mg create \
--name MyEnterpriseStack \
--management-group-id MyMgmtGroup \
--location eastus \
--template-file main.bicep \
--deny-settings-mode DenyWriteAndDelete \
--action-on-unmanage detachAll
Deployment Stack 用の Bicep テンプレート
本番環境用スタックテンプレート
// main.bicep
targetScope = 'subscription'
@description('Environment name')
@allowed([
'dev'
'staging'
'production'
])
param environment string = 'production'
@description('Primary location')
param location string = 'eastus'
@description('Secondary location for geo-replication')
param secondaryLocation string = 'westus'
// Resource naming
var namingPrefix = 'myapp-${environment}'
// Resource Group for core infrastructure
resource coreRG 'Microsoft.Resources/resourceGroups@2024-03-01' = {
name: '${namingPrefix}-core-rg'
location: location
tags: {
Environment: environment
ManagedBy: 'DeploymentStack'
Purpose: 'Core Infrastructure'
}
}
// Resource Group for data services
resource dataRG 'Microsoft.Resources/resourceGroups@2024-03-01' = {
name: '${namingPrefix}-data-rg'
location: location
tags: {
Environment: environment
ManagedBy: 'DeploymentStack'
Purpose: 'Data Services'
}
}
// Log Analytics Workspace
module logAnalytics 'modules/log-analytics.bicep' = {
name: 'logAnalyticsDeploy'
scope: coreRG
params: {
name: '${namingPrefix}-logs'
location: location
retentionInDays: environment == 'production' ? 90 : 30
}
}
// AKS Automatic Cluster
module aksCluster 'modules/aks-automatic.bicep' = {
name: 'aksClusterDeploy'
scope: coreRG
params: {
name: '${namingPrefix}-aks'
location: location
kubernetesVersion: '1.34'
workspaceId: logAnalytics.outputs.workspaceId
enableZoneRedundancy: environment == 'production'
}
}
// Container Apps Environment
module containerEnv 'modules/container-env.bicep' = {
name: 'containerEnvDeploy'
scope: coreRG
params: {
name: '${namingPrefix}-containerenv'
location: location
workspaceId: logAnalytics.outputs.workspaceId
zoneRedundant: environment == 'production'
}
}
// Azure OpenAI
module openAI 'modules/openai.bicep' = {
name: 'openAIDeploy'
scope: dataRG
params: {
name: '${namingPrefix}-openai'
location: location
deployGPT5: environment == 'production'
}
}
// Cosmos DB with geo-replication
module cosmosDB 'modules/cosmos-db.bicep' = {
name: 'cosmosDBDeploy'
scope: dataRG
params: {
name: '${namingPrefix}-cosmos'
primaryLocation: location
secondaryLocation: secondaryLocation
enableAutomaticFailover: environment == 'production'
}
}
// Key Vault
module keyVault 'modules/key-vault.bicep' = {
name: 'keyVaultDeploy'
scope: coreRG
params: {
name: '${namingPrefix}-kv'
location: location
enablePurgeProtection: environment == 'production'
}
}
// Outputs
output aksClusterName string = aksCluster.outputs.clusterName
output containerEnvId string = containerEnv.outputs.environmentId
output openAIEndpoint string = openAI.outputs.endpoint
output cosmosDBEndpoint string = cosmosDB.outputs.endpoint
output keyVaultUri string = keyVault.outputs.vaultUri
AKS Automatic モジュール
// modules/aks-automatic.bicep
@description('Cluster name')
param name string
@description('Location')
param location string
@description('Kubernetes version')
param kubernetesVersion string = '1.34'
@description('Log Analytics workspace ID')
param workspaceId string
@description('Enable zone redundancy')
param enableZoneRedundancy bool = true
resource aksCluster 'Microsoft.ContainerService/managedClusters@2025-01-01' = {
name: name
location: location
sku: {
name: 'Automatic'
tier: 'Standard'
}
identity: {
type: 'SystemAssigned'
}
properties: {
kubernetesVersion: kubernetesVersion
dnsPrefix: '${name}-dns'
enableRBAC: true
aadProfile: {
managed: true
enableAzureRBAC: true
}
networkProfile: {
networkPlugin: 'azure'
networkPluginMode: 'overlay'
networkDataplane: 'cilium'
serviceCidr: '10.0.0.0/16'
dnsServiceIP: '10.0.0.10'
}
autoScalerProfile: {
'balance-similar-node-groups': 'true'
expander: 'least-waste'
}
autoUpgradeProfile: {
upgradeChannel: 'stable'
nodeOSUpgradeChannel: 'NodeImage'
}
securityProfile: {
defender: {
securityMonitoring: {
enabled: true
}
}
workloadIdentity: {
enabled: true
}
}
oidcIssuerProfile: {
enabled: true
}
addonProfiles: {
omsagent: {
enabled: true
config: {
logAnalyticsWorkspaceResourceID: workspaceId
}
}
azurePolicy: {
enabled: true
}
}
}
zones: enableZoneRedundancy ? ['1', '2', '3'] : null
}
output clusterName string = aksCluster.name
output clusterId string = aksCluster.id
output oidcIssuerUrl string = aksCluster.properties.oidcIssuerProfile.issuerUrl
output kubeletIdentity string = aksCluster.properties.identityProfile.kubeletidentity.objectId
Deployment Stacks の管理
スタックの更新
# Update with new template version
az stack sub update \
--name MyProductionStack \
--template-file main.bicep \
--parameters @parameters.json \
--action-on-unmanage deleteAll
# Update deny settings
az stack sub update \
--name MyProductionStack \
--deny-settings-mode DenyWriteAndDelete \
--deny-settings-excluded-principals <new-principal-id>
スタックの詳細の表示
# Show stack information
az stack sub show \
--name MyProductionStack \
--output json
# List all stacks in subscription
az stack sub list --output table
# List stacks in resource group
az stack group list \
--resource-group MyRG \
--output table
スタックテンプレートのエクスポート
# Export template from deployed stack
az stack sub export \
--name MyProductionStack \
--output-file exported-stack.json
# Export and save parameters
az stack sub show \
--name MyProductionStack \
--query "parameters" \
--output json > parameters-backup.json
スタックの削除
# Delete stack and all managed resources
az stack sub delete \
--name MyProductionStack \
--action-on-unmanage deleteAll \
--yes
# Delete stack but keep resources
az stack sub delete \
--name MyProductionStack \
--action-on-unmanage detachAll \
--yes
# Delete with confirmation prompt
az stack sub delete --name MyProductionStack
拒否設定の詳細
DenyDelete モード
削除を防止しますが、更新は許可します。
az stack sub create \
--name MyStack \
--location eastus \
--template-file main.bicep \
--deny-settings-mode DenyDelete \
--deny-settings-excluded-principals \
<emergency-access-principal-id> \
<devops-service-principal-id>
使用例:
- 本番データベースの保護
- リソースの誤削除の防止
- 構成の更新の許可
DenyWriteAndDelete モード
更新と削除の両方を防止します。
az stack sub create \
--name MyStack \
--location eastus \
--template-file main.bicep \
--deny-settings-mode DenyWriteAndDelete \
--deny-settings-excluded-principals <break-glass-principal-id>
使用例:
- 不変のインフラストラクチャ
- コンプライアンス要件
- 重要な本番ワークロード
除外するプリンシパル
特定の ID に対して拒否設定を回避します。
# Get principal IDs
SERVICE_PRINCIPAL_ID=$(az ad sp show --id <app-id> --query id -o tsv)
ADMIN_GROUP_ID=$(az ad group show --group "Cloud Admins" --query id -o tsv)
# Apply with exclusions
az stack sub create \
--name MyStack \
--location eastus \
--template-file main.bicep \
--deny-settings-mode DenyWriteAndDelete \
--deny-settings-excluded-principals $SERVICE_PRINCIPAL_ID $ADMIN_GROUP_ID
ActionOnUnmanage ポリシー
detachAll
リソースはスタック管理から解除されますが、削除されません。
az stack sub create \
--name MyStack \
--location eastus \
--template-file main.bicep \
--action-on-unmanage detachAll
次の場合に使用します:
- デプロイの変更をテストする
- リソースを別のスタックに移行する
- 一時的なスタック管理
deleteAll
管理対象外のリソースをすべて削除します。
az stack sub create \
--name MyStack \
--location eastus \
--template-file main.bicep \
--action-on-unmanage deleteAll
次の場合に使用します:
- 一時的な環境(開発、テスト)
- クリーンな状態からのデプロイ
- 厳格な Infrastructure as Code の適用
deleteResources
リソースグループは保持し、リソースを削除します。
az stack sub create \
--name MyStack \
--location eastus \
--template-file main.bicep \
--action-on-unmanage deleteResources
Deployment Stacks の RBAC
組み込みロール
Azure Deployment Stack Contributor
- Deployment Stacks を管理
- 拒否割り当ての作成や削除は不可
Azure Deployment Stack Owner
- スタックを完全に管理
- 拒否割り当てを作成および削除可能
ロールの割り当て
# Assign Stack Contributor role
az role assignment create \
--assignee <user-or-service-principal-id> \
--role "Azure Deployment Stack Contributor" \
--scope /subscriptions/<subscription-id>
# Assign Stack Owner role
az role assignment create \
--assignee <admin-principal-id> \
--role "Azure Deployment Stack Owner" \
--scope /subscriptions/<subscription-id>
CI/CD、監視、監査
Deployment Stacks 用の GitHub Actions と Azure DevOps の詳細な CI/CD の例に加え、監視、監査クエリ、デプロイ履歴の確認、運用上の可観測性については、references/cicd-monitoring.md を参照してください。スタックのデプロイを本番環境向けに整備するときや、変更を監査するときに、この参照資料を読み込んでください。
Azure Blueprints からの移行
評価
- Blueprint の一覧作成:すべての Blueprint と割り当てを一覧にします
- パラメーターの文書化:パラメーターと構成をエクスポートします
- 変換の計画:Blueprint を Deployment Stacks に対応付けます
- 開発環境でのテスト:変換したテンプレートを検証します
変換手順
# 1. Export Blueprint as ARM template
# (Use Azure Portal or PowerShell)
# 2. Convert ARM to Bicep
az bicep decompile --file blueprint-template.json
# 3. Create Deployment Stack
az stack sub create \
--name ConvertedFromBlueprint \
--location eastus \
--template-file converted.bicep \
--parameters @blueprint-parameters.json \
--deny-settings-mode DenyWriteAndDelete \
--action-on-unmanage detachAll
# 4. Validate resources
az stack sub show --name ConvertedFromBlueprint
# 5. Delete Blueprint assignment (after validation)
# Remove-AzBlueprintAssignment -Name MyBlueprintAssignment
ベストプラクティス
✓ 新しいインフラストラクチャにはすべて Deployment Stacks を使用する ✓ デプロイ前に必ず what-if 分析を実行する ✓ 本番環境のスタックには DenyWriteAndDelete を使用する ✓ 拒否設定から緊急用プリンシパルを除外する ✓ スタックに Environment、CostCenter、Owner のタグを付ける ✓ 一時的な環境には deleteAll を使用する ✓ 移行シナリオには detachAll を使用する ✓ スタックのデプロイには CI/CD パイプラインを実装する ✓ アクティビティログでスタック操作を監視する ✓ スタックのアーキテクチャと依存関係を文書化する
トラブルシューティング
スタックの作成に失敗する
# Check deployment errors
az stack sub show \
--name MyStack \
--query "error" \
--output json
# Validate template
az deployment sub validate \
--location eastus \
--template-file main.bicep \
--parameters @parameters.json
拒否設定によって操作がブロックされる
# Check deny assignments
az role assignment list \
--scope /subscriptions/<subscription-id> \
--include-inherited \
--query "[?type=='Microsoft.Authorization/denyAssignments']"
# Add principal to exclusions
az stack sub update \
--name MyStack \
--deny-settings-excluded-principals <new-principal-id>
リソースが削除されない
# Check action-on-unmanage setting
az stack sub show \
--name MyStack \
--query "actionOnUnmanage" \
--output tsv
# Update to deleteAll
az stack sub update \
--name MyStack \
--action-on-unmanage deleteAll
参考資料
Deployment Stacks は、Azure インフラストラクチャのライフサイクル管理の未来です!