
Azure Env Builder
- 55 installs
- 23 repo stars
- Updated August 4, 2026
- aktsmm/agent-skills
Azure Environment Builder is a skill that builds enterprise Azure infrastructure by generating Bicep with Azure Verified Modules and deploying apps to App Service, AKS or Container Apps.
About
An experimental (Alpha) skill for building enterprise Azure environments and deployment design. It generates Bicep using Azure Verified Modules, deploys apps to App Service, AKS or Container Apps, and designs Hub-Spoke, Web+DB, AKS and AI Foundry architectures. Its workflow interviews for requirements, fetches AVM/schema info via MCP tools, scaffolds an environment folder, writes Bicep, generates CI/CD templates and validates with what-if. Developers use it to provision Azure infrastructure as code.
- Builds Azure infrastructure by generating Bicep with Azure Verified Modules
- Designs Hub-Spoke, Web+DB, AKS and AI Foundry architecture patterns
- Scaffolds environments and validates with az deployment group what-if
Azure Env Builder by the numbers
- 55 all-time installs (skills.sh)
- Ranked #700 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
azure-env-builder capabilities & compatibility
Requires an Azure subscription; provisions real (or low-cost demo) Azure resources via Bicep
- Capabilities
- devops · ci cd
- Works with
- azure · azure devops · github · kubernetes
- Use cases
- devops · ci cd
- Runs
- Local or remote
- Pricing
- Bring your own API key
What azure-env-builder says it does
Experimental Azure environment builder for infrastructure and deployment design.
generating Bicep with AVM modules, deploying apps to App Service/AKS/Container Apps, designing Hub-Spoke/AKS/AI Foundry architectures
npx skills add https://github.com/aktsmm/agent-skills --skill azure-env-builderAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 55 |
|---|---|
| repo stars | ★ 23 |
| Last updated | August 4, 2026 |
| Repository | aktsmm/agent-skills ↗ |
What it does
Build Azure infrastructure as Bicep with AVM modules and deploy apps to App Service, AKS or Container Apps.
Who is it for?
Building enterprise Azure environments and generating Bicep with AVM modules
Skip if: Disposable validation labs (use azure-infra-validation) or read-only production troubleshooting (use azure-troubleshooting)
When should I use this skill?
Building Azure infrastructure, generating Bicep, deploying apps, or designing Hub-Spoke/AKS/AI Foundry architectures
What you get
Generated Bicep files and CI/CD templates validated with az deployment group what-if
- Bicep files
- CI/CD pipeline templates
- scaffolded environment folder
By the numbers
- 200+ Azure Verified Modules
- 5 architecture patterns (Hub-Spoke, Web+DB, AKS, AI Foundry, Proxy VM)
- 6-step workflow
Files
Azure Environment Builder
Enterprise Azure environment builder skill.
When to Use
- Azure, Bicep, infrastructure, deploy app
- Building enterprise Azure environments
- Deploying apps to App Service, AKS, or Container Apps
- Designing Hub-Spoke, AKS, or AI Foundry architectures
- Creating low-cost Azure operations demos with alerts, logs, portal steps, and minimal always-on resources
When NOT to Use
- 使い捨ての検証 lab を作って機能・制約・route 挙動を試し、cleanup まで回したいとき
- →
azure-infra-validation - 本番障害を read-only で切り分けたいとき
- →
azure-troubleshooting
Features
| Category | Capabilities |
|---|---|
| Architecture | Hub-Spoke, Web+DB, AKS, AI Foundry |
| AVM Modules | 200+ Azure Verified Modules |
| VM Init | Squid, Nginx, Docker, IIS setup |
| Config Linking | SQL/Storage/Redis, Managed ID RBAC |
| CI/CD | GitHub Actions / Azure Pipelines |
| Ops Demo | Low-cost app, alert, log, and control-plane failure patterns |
Workflow
1. Interview - Gather requirements + select architecture pattern 2. MCP Tools - Fetch latest AVM/schema info 3. Scaffold - Generate environment folder via scripts/scaffold_environment.ps1 4. Implement - Write Bicep with AVM modules + VM init 5. CI/CD - Generate pipeline templates 6. Deploy - what-if → execute
Required: MCP Tools
Run before generating Bicep code:
mcp_bicep_experim_get_bicep_best_practices
mcp_bicep_experim_list_avm_metadata
mcp_bicep_experim_get_az_resource_type_schema(azResourceType, apiVersion)
microsoft_docs_search(query: "Private Endpoint Bicep")Interview Checklist
→ [references/hearing-checklist.md](references/hearing-checklist.md)
| Item | Details |
|---|---|
| Subscription | ID or az account show |
| Environment | dev / staging / prod |
| Region | japaneast / japanwest |
| Deploy Type | Azure CLI / Bicep |
Architecture Patterns
→ [references/architecture-patterns.md](references/architecture-patterns.md)
| Pattern | Use Case |
|---|---|
| Hub-Spoke | Large enterprise |
| Web + DB | Standard web applications |
| AKS | Container microservices |
| AI Foundry | AI/ML workloads |
| Proxy VM | Private network egress control |
Commands
# Scaffold environment folder
pwsh scripts/scaffold_environment.ps1 -Environment <env> -Location <region>
# Validate
az deployment group what-if --resource-group <rg> --template-file main.bicep
# Deploy
az deployment group create --resource-group <rg> --template-file main.bicepKey References
| File | Purpose |
|---|---|
| architecture-patterns.md | Architecture patterns |
| avm-modules.md | AVM module catalog |
| vm-app-scripts.md | VM init scripts |
| app-deploy-patterns.md | App deploy patterns |
| low-cost-ops-demo.md | Low-cost operations demos |
| service-config-templates.md | Service config linking |
| cicd-templates/ | CI/CD templates |
Done Criteria
- [ ] Interview checklist completed
- [ ] MCP tools fetched latest info
- [ ] Bicep files generated
- [ ]
az deployment group what-ifsucceeded
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
## English
Copyright (c) 2025-2026 yamapan (aktsmm)
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0
International License.
You are free to:
- **Share** — copy and redistribute the material in any medium or format
- **Adapt** — remix, transform, and build upon the material
Under the following terms:
- **Attribution** — You must give appropriate credit, provide a link to the
license, and indicate if changes were made. You may do so in any reasonable manner,
but not in any way that suggests the licensor endorses you or your use.
- **NonCommercial** — You may not use the material for commercial purposes.
*(Please contact the author if you wish to use this material for commercial purposes.)*
- **ShareAlike** — If you remix, transform, or build upon the material, you must
distribute your contributions under the same license as the original.
No additional restrictions — You may not apply legal terms or technological
measures that legally restrict others from doing anything the license permits.
**AI/ML Training Restriction** — Use of this content for AI/ML training, data
mining, or other analytical purposes is prohibited without explicit permission.
Full license text: https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
---
## 日本語
Copyright (c) 2025-2026 yamapan (aktsmm)
この作品はクリエイティブ・コモンズ 表示-非営利-継承 4.0 国際ライセンスの下に提供されています。
あなたは以下の条件に従う限り、自由に:
- **共有** — どのようなメディアやフォーマットでも資料を複製・再配布できます
- **翻案** — 資料をリミックス、変形、および加工することができます
以下の条件に従ってください:
- **表示** — あなたは適切なクレジットを表示し、ライセンスへのリンクを提供し、
変更があったらその旨を示さなければなりません。これらは合理的であればどのような方法で
行っても構いませんが、許諾者があなたやあなたの利用行為を支持していると示唆するような
方法は除きます。
- **非営利** — あなたは営利目的でこの資料を利用してはなりません。
(※商用利用をご希望の場合は、別途ご連絡ください。)
- **継承** — もしあなたがこの資料をリミックス、変形、または加工した場合、
あなたはあなたの貢献部分を元の作品と同じライセンスの下で配布しなければなりません。
追加的な制約は課せません — あなたは、このライセンスが他の者に許諾することを法的に
制限するような法的条項や技術的手段を適用してはなりません。
**AI/MLトレーニング制限** — 本コンテンツをAI/MLモデルのトレーニング、データマイニング、
その他の解析目的での使用は明示的な許可なく禁止されています。
ライセンス全文: https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.ja
---
## Special Permission for Microsoft Employees / Microsoft 社員向け特別許諾
### English
Microsoft Corporation employees are granted permission to use, copy, modify, and
distribute this material for any purpose within the scope of their employment
duties at Microsoft, including internal business use and customer-facing
activities, without the NonCommercial restriction of this license.
This special permission applies only to work performed as part of official
Microsoft business activities.
### 日本語
Microsoft Corporation の社員は、Microsoft での業務の範疇において、本資料を社内業務
および顧客対応を含むあらゆる目的で使用、複製、改変、配布することが許諾されます。
この場合、本ライセンスの「非営利」制限は適用されません。
この特別許諾は、Microsoft の公式な業務活動の一環として行われる作業にのみ適用されます。
---
## Disclaimer / 免責事項
### English
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
### 日本語
本ソフトウェアは「現状のまま」で提供され、明示または黙示を問わず、商品性、
特定目的への適合性、および権利非侵害についての保証を含むがこれに限定されない、
いかなる種類の保証も伴いません。作者または著作権者は、契約行為、不法行為、
またはそれ以外であろうと、ソフトウェアに起因または関連し、あるいはソフトウェアの
使用またはその他の扱いによって生じる一切の請求、損害、その他の責任について
責任を負いません。
アプリデプロイパターン
Azure App Service、AKS、Container Apps へのアプリケーションデプロイパターン。
目次
1. App Service デプロイ 2. AKS デプロイ 3. Container Apps デプロイ 4. CI/CD 統合
---
App Service デプロイ
デプロイ方式一覧
| 方式 | 用途 | 推奨シナリオ |
|---|---|---|
| ZIP デプロイ | コードパッケージ | .NET, Node.js, Python 等 |
| コンテナデプロイ | Docker イメージ | カスタムランタイム |
| GitHub Actions | CI/CD 自動化 | 継続的デプロイ |
| スロットデプロイ | Blue-Green / Canary | 本番環境のゼロダウンタイム |
| Run From Package | 読み取り専用パッケージ実行 | 高速起動、一貫性 |
1. ZIP デプロイ (コードベース)
# ビルド & ZIP 作成
dotnet publish -c Release -o ./publish
cd publish && zip -r ../app.zip .
# Azure CLI でデプロイ
az webapp deploy \
--resource-group rg-myapp-prod \
--name app-web-prod \
--src-path app.zip \
--type zip2. コンテナデプロイ
Bicep でコンテナ App Service 構成
// App Service (Linux Container)
module appService 'br/public:avm/res/web/site:0.15.1' = {
name: 'appServiceDeployment'
params: {
name: 'app-${environment}-${location}'
kind: 'app,linux,container'
serverFarmResourceId: appServicePlan.outputs.resourceId
// コンテナ設定
siteConfig: {
linuxFxVersion: 'DOCKER|${acrName}.azurecr.io/${imageName}:${imageTag}'
acrUseManagedIdentityCreds: true // ACR への MI 認証
appSettings: [
{
name: 'WEBSITES_PORT'
value: '8080'
}
{
name: 'DOCKER_REGISTRY_SERVER_URL'
value: 'https://${acrName}.azurecr.io'
}
]
}
// Managed Identity (ACR Pull 用)
managedIdentities: {
systemAssigned: true
}
}
}
// ACR への AcrPull ロール割り当て
module acrRoleAssignment 'br/public:avm/ptn/authorization/resource-role-assignment:0.1.1' = {
name: 'acrPullRoleAssignment'
params: {
principalId: appService.outputs.systemAssignedMIPrincipalId
roleDefinitionId: '7f951dda-4ed3-4680-a7ca-43fe172d538d' // AcrPull
resourceId: acr.outputs.resourceId
}
}3. スロットデプロイ (Blue-Green)
// デプロイスロット定義
module stagingSlot 'br/public:avm/res/web/site/slot:0.4.0' = {
name: 'stagingSlotDeployment'
params: {
name: 'staging'
appServiceName: appService.outputs.name
kind: 'app,linux,container'
siteConfig: {
linuxFxVersion: 'DOCKER|${acrName}.azurecr.io/${imageName}:${newImageTag}'
}
}
}# スロットへデプロイ
az webapp deploy \
--resource-group rg-myapp-prod \
--name app-web-prod \
--slot staging \
--src-path app.zip
# スワップ(本番切り替え)
az webapp deployment slot swap \
--resource-group rg-myapp-prod \
--name app-web-prod \
--slot staging \
--target-slot production4. Run From Package
// Run From Package 設定
siteConfig: {
appSettings: [
{
name: 'WEBSITE_RUN_FROM_PACKAGE'
value: '1' // または Blob URL
}
]
}---
AKS デプロイ
デプロイ方式一覧
| 方式 | 用途 | 複雑度 | 推奨シナリオ |
|---|---|---|---|
| kubectl | 直接マニフェスト適用 | 低 | シンプルなアプリ |
| Helm | パッケージ管理 | 中 | 再利用可能なチャート |
| Kustomize | 環境別オーバーレイ | 中 | 環境差分管理 |
| GitOps | Git ベース自動同期 | 高 | 大規模運用、監査要件 |
1. kubectl 直接デプロイ
Kubernetes マニフェスト
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myacr.azurecr.io/myapp:v1.0.0
ports:
- containerPort: 8080
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: myapp-secrets
key: database-url
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: production
spec:
type: ClusterIP
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
namespace: production
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80# AKS 認証情報取得
az aks get-credentials --resource-group rg-aks-prod --name aks-prod
# デプロイ
kubectl apply -f k8s/deployment.yaml
# 確認
kubectl get pods -n production
kubectl get svc -n production2. Helm チャートデプロイ
Chart 構造
helm/myapp/
├── Chart.yaml
├── values.yaml
├── values-dev.yaml
├── values-prod.yaml
└── templates/
├── deployment.yaml
├── service.yaml
├── ingress.yaml
├── configmap.yaml
└── secret.yamlChart.yaml
apiVersion: v2
name: myapp
description: My Application Helm Chart
version: 1.0.0
appVersion: "1.0.0"values.yaml (デフォルト)
# アプリケーション設定
replicaCount: 2
image:
repository: myacr.azurecr.io/myapp
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 8080
ingress:
enabled: true
className: azure-application-gateway
annotations:
appgw.ingress.kubernetes.io/ssl-redirect: "true"
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
# 環境変数
env:
- name: ASPNETCORE_ENVIRONMENT
value: Production
# ConfigMap から読み込む設定
configMap:
enabled: true
data:
APP_CONFIG: "production"
# Secrets (外部参照推奨)
secrets:
enabled: false
# Azure Key Vault CSI Driver
keyVault:
enabled: true
name: kv-myapp-prod
tenantId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
secrets:
- name: database-connection-string
alias: DATABASE_URLvalues-prod.yaml (本番オーバーライド)
replicaCount: 5
image:
tag: v1.2.0
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "1000m"
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}
labels:
{{- include "myapp.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "myapp.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "myapp.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.targetPort }}
{{- if .Values.env }}
env:
{{- toYaml .Values.env | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- if .Values.keyVault.enabled }}
volumeMounts:
- name: secrets-store
mountPath: "/mnt/secrets-store"
readOnly: true
{{- end }}
{{- if .Values.keyVault.enabled }}
volumes:
- name: secrets-store
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: {{ include "myapp.fullname" . }}-secrets
{{- end }}# Helm デプロイ
helm upgrade --install myapp ./helm/myapp \
--namespace production \
--create-namespace \
-f ./helm/myapp/values-prod.yaml \
--set image.tag=v1.2.0
# ロールバック
helm rollback myapp 1 --namespace production
# 履歴確認
helm history myapp --namespace production3. Kustomize デプロイ
kustomize/
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ └── service.yaml
└── overlays/
├── dev/
│ ├── kustomization.yaml
│ └── patch-replicas.yaml
└── prod/
├── kustomization.yaml
└── patch-replicas.yamlbase/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
commonLabels:
app: myappoverlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: production
resources:
- ../../base
images:
- name: myacr.azurecr.io/myapp
newTag: v1.2.0
replicas:
- name: myapp
count: 5
patches:
- path: patch-replicas.yaml# Kustomize でデプロイ
kubectl apply -k kustomize/overlays/prod/4. GitOps (Flux v2)
Flux インストール
# Flux CLI インストール
curl -s https://fluxcd.io/install.sh | sudo bash
# AKS に Flux 拡張機能インストール
az k8s-extension create \
--resource-group rg-aks-prod \
--cluster-name aks-prod \
--cluster-type managedClusters \
--name flux \
--extension-type microsoft.fluxGitRepository & Kustomization
# flux-system/git-repository.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: myapp-repo
namespace: flux-system
spec:
interval: 1m
url: https://github.com/myorg/myapp-k8s
ref:
branch: main
secretRef:
name: github-token
---
# flux-system/kustomization.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: myapp-production
namespace: flux-system
spec:
interval: 5m
path: ./kustomize/overlays/prod
prune: true
sourceRef:
kind: GitRepository
name: myapp-repo
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: myapp
namespace: production---
Container Apps デプロイ
Bicep でアプリデプロイ
// Container Apps 環境
module containerAppsEnv 'br/public:avm/res/app/managed-environment:0.8.1' = {
name: 'containerAppsEnvDeployment'
params: {
name: 'cae-${environment}-${location}'
logAnalyticsWorkspaceResourceId: logAnalytics.outputs.resourceId
infrastructureSubnetId: subnet.outputs.resourceId
}
}
// Container App
module containerApp 'br/public:avm/res/app/container-app:0.12.0' = {
name: 'containerAppDeployment'
params: {
name: 'ca-myapp-${environment}'
environmentResourceId: containerAppsEnv.outputs.resourceId
// コンテナ設定
containers: [
{
name: 'myapp'
image: '${acrName}.azurecr.io/myapp:${imageTag}'
resources: {
cpu: json('0.5')
memory: '1Gi'
}
env: [
{
name: 'DATABASE_URL'
secretRef: 'database-url'
}
{
name: 'REDIS_URL'
secretRef: 'redis-url'
}
]
}
]
// スケール設定
scaleMinReplicas: 1
scaleMaxReplicas: 10
scaleRules: [
{
name: 'http-scaling'
http: {
metadata: {
concurrentRequests: '100'
}
}
}
]
// Ingress 設定
ingressExternal: true
ingressTargetPort: 8080
ingressTransport: 'auto'
// シークレット
secrets: {
secureList: [
{
name: 'database-url'
keyVaultUrl: '${keyVault.properties.vaultUri}secrets/database-url'
identity: 'system'
}
{
name: 'redis-url'
keyVaultUrl: '${keyVault.properties.vaultUri}secrets/redis-url'
identity: 'system'
}
]
}
// Managed Identity
managedIdentities: {
systemAssigned: true
}
// Dapr 設定 (オプション)
dapr: {
enabled: true
appId: 'myapp'
appPort: 8080
appProtocol: 'http'
}
}
}az containerapp コマンド
# イメージ更新
az containerapp update \
--resource-group rg-myapp-prod \
--name ca-myapp-prod \
--image myacr.azurecr.io/myapp:v1.2.0
# リビジョン確認
az containerapp revision list \
--resource-group rg-myapp-prod \
--name ca-myapp-prod \
--output table
# トラフィック分割 (Canary)
az containerapp ingress traffic set \
--resource-group rg-myapp-prod \
--name ca-myapp-prod \
--revision-weight myapp--v1=90 myapp--v2=10---
CI/CD 統合
GitHub Actions - App Service
# .github/workflows/deploy-appservice.yml
name: Deploy to App Service
on:
push:
branches: [main]
paths: ["src/**"]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# ビルド
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"
- name: Build and publish
run: |
dotnet publish -c Release -o ./publish
cd publish && zip -r ../app.zip .
# Azure ログイン
- uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
# デプロイ (スロット)
- name: Deploy to staging slot
run: |
az webapp deploy \
--resource-group ${{ vars.RESOURCE_GROUP }} \
--name ${{ vars.APP_NAME }} \
--slot staging \
--src-path app.zip
# スワップ
- name: Swap to production
run: |
az webapp deployment slot swap \
--resource-group ${{ vars.RESOURCE_GROUP }} \
--name ${{ vars.APP_NAME }} \
--slot staging \
--target-slot productionGitHub Actions - AKS
# .github/workflows/deploy-aks.yml
name: Deploy to AKS
on:
push:
branches: [main]
paths: ["src/**", "helm/**"]
env:
ACR_NAME: myacr
IMAGE_NAME: myapp
CLUSTER_NAME: aks-prod
RESOURCE_GROUP: rg-aks-prod
jobs:
build:
runs-on: ubuntu-latest
outputs:
image_tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
# ACR ログイン
- name: Login to ACR
run: az acr login --name ${{ env.ACR_NAME }}
# Docker ビルド & プッシュ
- name: Build and push
id: meta
run: |
IMAGE_TAG="${{ env.ACR_NAME }}.azurecr.io/${{ env.IMAGE_NAME }}:${{ github.sha }}"
docker build -t $IMAGE_TAG .
docker push $IMAGE_TAG
echo "tags=$IMAGE_TAG" >> $GITHUB_OUTPUT
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
# AKS 認証
- name: Get AKS credentials
run: |
az aks get-credentials \
--resource-group ${{ env.RESOURCE_GROUP }} \
--name ${{ env.CLUSTER_NAME }}
# Helm デプロイ
- name: Deploy with Helm
run: |
helm upgrade --install myapp ./helm/myapp \
--namespace production \
--create-namespace \
-f ./helm/myapp/values-prod.yaml \
--set image.tag=${{ github.sha }} \
--wait --timeout 5m
# デプロイ確認
- name: Verify deployment
run: |
kubectl rollout status deployment/myapp -n production
kubectl get pods -n production -l app=myappGitHub Actions - Container Apps
# .github/workflows/deploy-containerapp.yml
name: Deploy to Container Apps
on:
push:
branches: [main]
env:
ACR_NAME: myacr
IMAGE_NAME: myapp
CONTAINERAPP_NAME: ca-myapp-prod
RESOURCE_GROUP: rg-myapp-prod
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
# ACR ビルド (サーバーサイドビルド)
- name: Build on ACR
run: |
az acr build \
--registry ${{ env.ACR_NAME }} \
--image ${{ env.IMAGE_NAME }}:${{ github.sha }} \
.
# Container App 更新
- name: Update Container App
run: |
az containerapp update \
--resource-group ${{ env.RESOURCE_GROUP }} \
--name ${{ env.CONTAINERAPP_NAME }} \
--image ${{ env.ACR_NAME }}.azurecr.io/${{ env.IMAGE_NAME }}:${{ github.sha }}
# リビジョン確認
- name: Check revision
run: |
az containerapp revision list \
--resource-group ${{ env.RESOURCE_GROUP }} \
--name ${{ env.CONTAINERAPP_NAME }} \
--output table---
設定連携チェックリスト
App Service デプロイ時
| 項目 | 確認内容 |
|---|---|
| ACR 認証 | Managed Identity + AcrPull ロール |
| App Settings | Key Vault 参照または環境変数 |
| Connection Strings | SQL/Redis/Storage の接続文字列 |
| Startup Command | コンテナ起動コマンド |
| Health Check | /health エンドポイント設定 |
AKS デプロイ時
| 項目 | 確認内容 |
|---|---|
| ACR 統合 | az aks update --attach-acr |
| Namespace | 環境別 namespace 分離 |
| Secrets | Key Vault CSI Driver または Sealed Secrets |
| Ingress | AGIC または Nginx Ingress |
| Pod Identity | Workload Identity 設定 |
| HPA | CPU/メモリ/カスタムメトリクス |
Container Apps デプロイ時
| 項目 | 確認内容 |
|---|---|
| Environment | VNet 統合、Log Analytics 接続 |
| Secrets | Key Vault 参照 |
| Scale Rules | HTTP / CPU / KEDA |
| Dapr | サイドカー有効化 |
| Revision Mode | Single / Multiple |
アーキテクチャパターン
実践的な Azure 複合構成パターン集。MCP ツールで最新情報を取得してから使用すること。
目次
1. Landing Zone (Hub-Spoke) 2. Web + DB (3 層アーキテクチャ) 3. コンテナ基盤 (AKS / Container Apps) 4. AI/ML 基盤 5. データ分析基盤 6. プロキシ/ゲートウェイ VM
---
1. Landing Zone (Hub-Spoke)
概要
エンタープライズ向けネットワーク基盤。Hub VNet に共有サービス(Firewall, Bastion, VPN)を配置し、Spoke VNet とピアリング。
AVM モジュール
// Hub ネットワーク
module hubNetwork 'br/public:avm/ptn/network/hub-networking:0.5.0' = {
name: 'hubNetworkDeployment'
params: {
hubVirtualNetworks: {
hub1: {
addressPrefixes: ['10.0.0.0/16']
subnets: {
AzureFirewallSubnet: { addressPrefix: '10.0.1.0/26' }
AzureBastionSubnet: { addressPrefix: '10.0.2.0/26' }
GatewaySubnet: { addressPrefix: '10.0.3.0/26' }
}
}
}
}
}
// Azure Firewall
module firewall 'br/public:avm/res/network/azure-firewall:0.9.2' = {
name: 'firewallDeployment'
params: {
name: 'afw-hub-${environment}'
virtualNetworkResourceId: hubNetwork.outputs.hubVirtualNetworkResourceIds.hub1
publicIPAddressObject: {
name: 'pip-afw-hub-${environment}'
}
}
}
// Bastion
module bastion 'br/public:avm/res/network/bastion-host:0.8.2' = {
name: 'bastionDeployment'
params: {
name: 'bas-hub-${environment}'
virtualNetworkResourceId: hubNetwork.outputs.hubVirtualNetworkResourceIds.hub1
}
}設定値連携
| Hub リソース | 連携先 Spoke | 連携内容 |
|---|---|---|
| Azure Firewall | UDR | 0.0.0.0/0 → Firewall Private IP |
| Private DNS Zone | VNet Link | Spoke VNet への DNS 解決 |
| Log Analytics | Diagnostic Settings | 全リソースのログ収集先 |
---
2. Web + DB (3 層アーキテクチャ)
概要
App Service + SQL Database の典型的な Web アプリ構成。Private Endpoint で閉域化可能。
AVM モジュール
// App Service Plan
module appServicePlan 'br/public:avm/res/web/serverfarm:0.5.0' = {
name: 'appServicePlanDeployment'
params: {
name: 'asp-${workloadName}-${environment}'
skuName: 'P1v3'
kind: 'Linux'
}
}
// Web App
module webApp 'br/public:avm/res/web/site:0.19.4' = {
name: 'webAppDeployment'
params: {
name: 'app-${workloadName}-${environment}'
serverFarmResourceId: appServicePlan.outputs.resourceId
siteConfig: {
linuxFxVersion: 'DOTNETCORE|8.0'
appSettings: [
// SQL 接続文字列は Key Vault 参照
{ name: 'ConnectionStrings__DefaultConnection', value: '@Microsoft.KeyVault(VaultName=${keyVaultName};SecretName=sql-connection-string)' }
]
}
privateEndpoints: enablePrivateEndpoint ? [
{
subnetResourceId: subnetId
privateDnsZoneGroup: {
privateDnsZoneGroupConfigs: [
{ privateDnsZoneResourceId: privateDnsZoneId }
]
}
}
] : []
}
}
// SQL Server + Database
module sqlServer 'br/public:avm/res/sql/server:0.21.1' = {
name: 'sqlServerDeployment'
params: {
name: 'sql-${workloadName}-${environment}'
administratorLogin: 'sqladmin'
administratorLoginPassword: sqlAdminPassword
databases: [
{
name: 'sqldb-${workloadName}-${environment}'
skuName: 'S1'
}
]
privateEndpoints: enablePrivateEndpoint ? [
{
subnetResourceId: subnetId
privateDnsZoneGroup: {
privateDnsZoneGroupConfigs: [
{ privateDnsZoneResourceId: sqlPrivateDnsZoneId }
]
}
}
] : []
}
}設定値連携
| ソース | ターゲット | 連携内容 |
|---|---|---|
| SQL Server | Web App | 接続文字列 (Key Vault 経由) |
| App Insights | Web App | InstrumentationKey |
| Storage | Web App | Blob 接続文字列 |
---
3. コンテナ基盤
3.1 Azure Container Apps
// Container Apps Environment
module containerAppsEnv 'br/public:avm/res/app/managed-environment:0.11.3' = {
name: 'containerAppsEnvDeployment'
params: {
name: 'cae-${workloadName}-${environment}'
logAnalyticsWorkspaceResourceId: logAnalyticsId
infrastructureSubnetId: containerAppsSubnetId
}
}
// Container App
module containerApp 'br/public:avm/res/app/container-app:0.19.0' = {
name: 'containerAppDeployment'
params: {
name: 'ca-${workloadName}-${environment}'
environmentResourceId: containerAppsEnv.outputs.resourceId
containers: [
{
name: 'main'
image: '${acrName}.azurecr.io/${imageName}:${imageTag}'
resources: {
cpu: json('0.5')
memory: '1Gi'
}
env: [
{ name: 'DATABASE_URL', secretRef: 'db-connection' }
]
}
]
secrets: {
secureList: [
{ name: 'db-connection', keyVaultUrl: '${keyVaultUri}secrets/db-connection', identity: managedIdentityId }
]
}
}
}3.2 Azure Kubernetes Service (AKS)
// AKS Cluster
module aksCluster 'br/public:avm/res/container-service/managed-cluster:0.11.1' = {
name: 'aksClusterDeployment'
params: {
name: 'aks-${workloadName}-${environment}'
primaryAgentPoolProfiles: [
{
name: 'systempool'
mode: 'System'
count: 3
vmSize: 'Standard_D4s_v5'
vnetSubnetResourceId: aksSubnetId
}
]
agentPoolProfiles: [
{
name: 'userpool'
mode: 'User'
count: 3
vmSize: 'Standard_D8s_v5'
vnetSubnetResourceId: aksSubnetId
}
]
networkPlugin: 'azure'
networkPolicy: 'azure'
enablePrivateCluster: true
aadProfile: {
managed: true
enableAzureRbac: true
}
}
}---
4. AI/ML 基盤
概要
Azure AI Foundry (旧 Azure Machine Learning) を中心とした AI 開発環境。
AVM モジュール
// AI Foundry
module aiFoundry 'br/public:avm/ptn/ai-ml/ai-foundry:0.6.0' = {
name: 'aiFoundryDeployment'
params: {
name: 'aif-${workloadName}-${environment}'
projectName: 'project-${workloadName}'
// Cognitive Services (OpenAI) を自動作成
cognitiveServicesAccountName: 'cog-${workloadName}-${environment}'
cognitiveServicesDeployments: [
{ name: 'gpt-4o', model: { name: 'gpt-4o', version: '2024-08-06' }, sku: { name: 'Standard', capacity: 10 } }
{ name: 'text-embedding-3-large', model: { name: 'text-embedding-3-large', version: '1' }, sku: { name: 'Standard', capacity: 10 } }
]
storageAccountName: 'st${workloadName}${environment}'
keyVaultName: 'kv-${workloadName}-${environment}'
}
}OpenAI Service 単体
// Azure OpenAI
module openai 'br/public:avm/res/cognitive-services/account:0.14.1' = {
name: 'openaiDeployment'
params: {
name: 'oai-${workloadName}-${environment}'
kind: 'OpenAI'
customSubDomainName: 'oai-${workloadName}-${environment}'
deployments: [
{
name: 'gpt-4o'
model: { format: 'OpenAI', name: 'gpt-4o', version: '2024-08-06' }
sku: { name: 'Standard', capacity: 10 }
}
]
privateEndpoints: enablePrivateEndpoint ? [
{ subnetResourceId: subnetId }
] : []
}
}---
5. データ分析基盤
Synapse Analytics
// Synapse Workspace
module synapse 'br/public:avm/res/synapse/workspace:0.14.2' = {
name: 'synapseDeployment'
params: {
name: 'syn-${workloadName}-${environment}'
defaultDataLakeStorageAccountResourceId: storageAccountId
defaultDataLakeStorageFilesystem: 'synapse'
sqlAdministratorLogin: 'synadmin'
sqlAdministratorLoginPassword: sqlAdminPassword
managedVirtualNetwork: 'default'
}
}Microsoft Fabric (Capacity)
// Fabric Capacity
module fabricCapacity 'br/public:avm/res/fabric/capacity:0.1.2' = {
name: 'fabricCapacityDeployment'
params: {
name: 'fab${workloadName}${environment}'
skuName: 'F2'
administrationMembers: [
adminPrincipalId
]
}
}---
6. プロキシ/ゲートウェイ VM
6.1 Squid Proxy VM
// Squid Proxy VM
module squidVm 'br/public:avm/res/compute/virtual-machine:0.21.0' = {
name: 'squidVmDeployment'
params: {
name: 'vm-squid-${environment}'
vmSize: 'Standard_B2ms'
imageReference: {
publisher: 'Canonical'
offer: '0001-com-ubuntu-server-jammy'
sku: '22_04-lts-gen2'
version: 'latest'
}
osType: 'Linux'
osDisk: {
diskSizeGB: 64
managedDisk: { storageAccountType: 'Premium_LRS' }
}
nicConfigurations: [
{
ipConfigurations: [
{ subnetResourceId: subnetId }
]
enableIPForwarding: true
}
]
adminUsername: 'azureuser'
adminPassword: adminPassword
// cloud-init で Squid 自動インストール
customData: loadFileAsBase64('../../scripts/vm-init/squid-init.yaml')
// または CustomScriptExtension
extensionCustomScriptConfig: {
enabled: true
fileData: [
{ uri: 'https://raw.githubusercontent.com/yourrepo/scripts/squid-setup.sh' }
]
settings: {
commandToExecute: 'bash squid-setup.sh --allowed-networks "10.0.0.0/8,172.16.0.0/12"'
}
}
}
}6.2 Nginx リバースプロキシ VM
// Nginx Reverse Proxy VM
module nginxVm 'br/public:avm/res/compute/virtual-machine:0.21.0' = {
name: 'nginxVmDeployment'
params: {
name: 'vm-nginx-${environment}'
vmSize: 'Standard_B2ms'
imageReference: {
publisher: 'Canonical'
offer: '0001-com-ubuntu-server-jammy'
sku: '22_04-lts-gen2'
version: 'latest'
}
osType: 'Linux'
nicConfigurations: [
{
ipConfigurations: [
{
subnetResourceId: subnetId
publicIPAddressResourceId: publicIpId
}
]
}
]
adminUsername: 'azureuser'
disablePasswordAuthentication: true
publicKeys: [
{ path: '/home/azureuser/.ssh/authorized_keys', keyData: sshPublicKey }
]
// cloud-init で Nginx + Let's Encrypt 自動設定
customData: loadFileAsBase64('../../scripts/vm-init/nginx-init.yaml')
}
}---
設定値連携のベストプラクティス
1. Key Vault 経由の接続文字列管理
// SQL 接続文字列を Key Vault に格納
module sqlConnectionSecret 'br/public:avm/res/key-vault/vault/secret:0.1.0' = {
name: 'sqlConnectionSecretDeployment'
params: {
keyVaultName: keyVault.outputs.name
name: 'sql-connection-string'
value: 'Server=tcp:${sqlServer.outputs.fullyQualifiedDomainName},1433;Database=${databaseName};Authentication=Active Directory Managed Identity;'
}
}
// App Service から参照
var appSettings = [
{
name: 'ConnectionStrings__DefaultConnection'
value: '@Microsoft.KeyVault(SecretUri=${sqlConnectionSecret.outputs.secretUri})'
}
]2. Managed Identity による認証
// User Assigned Managed Identity
module identity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.3' = {
name: 'identityDeployment'
params: {
name: 'id-${workloadName}-${environment}'
}
}
// SQL Server への RBAC 付与
module sqlRoleAssignment 'br/public:avm/res/authorization/role-assignment/rg-scope:0.1.1' = {
name: 'sqlRoleAssignmentDeployment'
params: {
roleDefinitionId: '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' // SQL DB Contributor
principalId: identity.outputs.principalId
}
}3. Private DNS Zone の一元管理
// Private Link 用 DNS ゾーンを一括作成
module privateDnsZones 'br/public:avm/ptn/network/private-link-private-dns-zones:0.7.1' = {
name: 'privateDnsZonesDeployment'
params: {
location: 'global'
virtualNetworkLinks: [
{ virtualNetworkResourceId: hubVnetId }
{ virtualNetworkResourceId: spokeVnetId }
]
}
}---
次のステップ
1. VM アプリケーションスクリプト - Squid, Nginx 等の初期化スクリプト 2. サービス設定テンプレート - 連携設定のテンプレート 3. AVM モジュール一覧 - 推奨モジュールカタログ
AVM (Azure Verified Modules) カタログ
Azure Verified Modules の推奨モジュール一覧。MCP ツール mcp_bicep_experim_list_avm_metadata で最新版を確認すること。
使用方法
// Bicep Registry から直接参照
module example 'br/public:avm/res/storage/storage-account:0.31.0' = {
name: 'exampleDeployment'
params: { ... }
}---
カテゴリ別モジュール一覧
🌐 ネットワーク
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/network/virtual-network | VNet | 0.7.2 |
avm/res/network/virtual-network/subnet | サブネット | 0.1.3 |
avm/res/network/network-security-group | NSG | 0.5.2 |
avm/res/network/application-gateway | App Gateway | 0.7.2 |
avm/res/network/azure-firewall | Azure Firewall | 0.9.2 |
avm/res/network/bastion-host | Bastion | 0.8.2 |
avm/res/network/nat-gateway | NAT Gateway | 2.0.0 |
avm/res/network/load-balancer | Load Balancer | 0.7.0 |
avm/res/network/private-endpoint | Private Endpoint | 0.11.1 |
avm/res/network/private-dns-zone | Private DNS | 0.8.0 |
avm/res/network/dns-zone | Public DNS | 0.5.4 |
avm/res/network/public-ip-address | Public IP | 0.10.0 |
avm/res/network/route-table | UDR | 0.5.0 |
avm/res/network/virtual-network-gateway | VPN/ER Gateway | 0.10.0 |
avm/res/network/express-route-circuit | ExpressRoute | 0.8.0 |
avm/res/network/ddos-protection-plan | DDoS Protection | 0.3.2 |
avm/ptn/network/hub-networking | Hub-Spoke パターン | 0.5.0 |
avm/ptn/network/private-link-private-dns-zones | PL DNS 一括作成 | 0.7.1 |
💻 コンピュート
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/compute/virtual-machine | VM | 0.21.0 |
avm/res/compute/virtual-machine-scale-set | VMSS | 0.11.0 |
avm/res/compute/availability-set | 可用性セット | 0.2.3 |
avm/res/compute/disk | Managed Disk | 0.6.0 |
avm/res/compute/gallery | Compute Gallery | 0.9.4 |
avm/res/compute/image | VM Image | 0.3.3 |
avm/ptn/virtual-machine-images/azure-image-builder | AIB パターン | 0.2.2 |
📦 コンテナ
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/container-registry/registry | ACR | 0.9.3 |
avm/res/container-service/managed-cluster | AKS | 0.11.1 |
avm/res/app/managed-environment | Container Apps Env | 0.11.3 |
avm/res/app/container-app | Container App | 0.19.0 |
avm/res/app/job | Container App Job | 0.7.1 |
avm/res/container-instance/container-group | ACI | 0.7.0 |
avm/ptn/aca-lza/hosting-environment | ACA Landing Zone | 0.6.1 |
🌍 Web
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/web/serverfarm | App Service Plan | 0.5.0 |
avm/res/web/site | Web App / Functions | 0.19.4 |
avm/res/web/static-site | Static Web Apps | 0.9.3 |
avm/res/web/hosting-environment | App Service Env | 0.4.1 |
avm/res/cdn/profile | CDN / Front Door | 0.16.1 |
avm/res/api-management/service | API Management | 0.13.0 |
🗄️ データベース
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/sql/server | SQL Server | 0.21.1 |
avm/res/sql/server/database | SQL Database | 0.2.1 |
avm/res/sql/managed-instance | SQL MI | 0.4.0 |
avm/res/db-for-postgre-sql/flexible-server | PostgreSQL | 0.15.1 |
avm/res/db-for-my-sql/flexible-server | MySQL | 0.10.0 |
avm/res/document-db/database-account | Cosmos DB | 0.18.0 |
avm/res/document-db/mongo-cluster | MongoDB vCore | 0.4.2 |
avm/res/cache/redis | Redis Cache | 0.16.4 |
avm/res/cache/redis-enterprise | Redis Enterprise | 0.5.0 |
📊 ストレージ
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/storage/storage-account | Storage Account | 0.31.0 |
avm/res/storage/storage-account/blob-service/container | Blob Container | 0.3.2 |
avm/res/storage/storage-account/file-service/share | File Share | 0.1.2 |
avm/res/net-app/net-app-account | Azure NetApp Files | 0.12.0 |
avm/res/elastic-san/elastic-san | Elastic SAN | 0.5.0 |
🤖 AI / ML
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/cognitive-services/account | Cognitive Services / OpenAI | 0.14.1 |
avm/res/machine-learning-services/workspace | ML Workspace | 0.13.0 |
avm/res/search/search-service | AI Search | 0.12.0 |
avm/ptn/ai-ml/ai-foundry | AI Foundry パターン | 0.6.0 |
avm/ptn/ai-platform/baseline | AI Platform 基盤 | 0.7.1 |
📈 監視
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/operational-insights/workspace | Log Analytics | 0.14.2 |
avm/res/insights/component | App Insights | 0.7.1 |
avm/res/insights/action-group | Action Group | 0.8.0 |
avm/res/insights/metric-alert | Metric Alert | 0.4.1 |
avm/res/insights/data-collection-rule | DCR | 0.10.0 |
avm/res/insights/diagnostic-setting | Diagnostic Settings | 0.1.4 |
avm/ptn/azd/monitoring | 監視パターン | 0.2.1 |
🔐 セキュリティ
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/key-vault/vault | Key Vault | 0.13.3 |
avm/res/managed-identity/user-assigned-identity | Managed Identity | 0.4.3 |
avm/ptn/security/security-center | Defender for Cloud | 0.1.1 |
avm/res/aad/domain-service | Entra Domain Services | 0.5.0 |
🔄 統合
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/event-hub/namespace | Event Hubs | 0.14.0 |
avm/res/service-bus/namespace | Service Bus | 0.16.0 |
avm/res/event-grid/topic | Event Grid Topic | 0.9.1 |
avm/res/logic/workflow | Logic App | 0.5.3 |
avm/res/data-factory/factory | Data Factory | 0.11.0 |
🔧 DevOps
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/dev-ops-infrastructure/pool | Managed DevOps Pool | 0.7.0 |
avm/ptn/dev-ops/cicd-agents-and-runners | CI/CD エージェント | 0.3.1 |
avm/res/automation/automation-account | Automation Account | 0.17.1 |
🏢 ガバナンス
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/ptn/lz/sub-vending | サブスクリプション発行 | 0.5.2 |
avm/ptn/authorization/policy-assignment | ポリシー割り当て | 0.5.3 |
avm/ptn/authorization/role-assignment | ロール割り当て | 0.2.4 |
avm/res/management/management-group | 管理グループ | 0.1.2 |
avm/res/consumption/budget | 予算アラート | 0.3.8 |
💾 バックアップ / DR
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/res/recovery-services/vault | Recovery Services Vault | 0.11.1 |
avm/res/data-protection/backup-vault | Backup Vault | 0.13.0 |
---
パターンモジュール (ptn)
複数リソースを組み合わせた複合パターン:
| モジュール | 説明 | 最新バージョン |
|---|---|---|
avm/ptn/network/hub-networking | Hub-Spoke ネットワーク | 0.5.0 |
avm/ptn/aca-lza/hosting-environment | ACA Landing Zone | 0.6.1 |
avm/ptn/app-service-lza/hosting-environment | App Service LZ | 0.1.1 |
avm/ptn/ai-ml/ai-foundry | AI Foundry | 0.6.0 |
avm/ptn/lz/sub-vending | サブスクリプション発行 | 0.5.2 |
avm/ptn/azd/container-apps-stack | Container Apps スタック | 0.3.0 |
avm/ptn/data/private-analytical-workspace | 分析ワークスペース | 0.1.2 |
---
使用例
VM + カスタムスクリプト
module vm 'br/public:avm/res/compute/virtual-machine:0.21.0' = {
name: 'vmDeployment'
params: {
name: 'vm-app-${environment}'
vmSize: 'Standard_D4s_v5'
imageReference: {
publisher: 'Canonical'
offer: '0001-com-ubuntu-server-jammy'
sku: '22_04-lts-gen2'
version: 'latest'
}
osType: 'Linux'
nicConfigurations: [
{
ipConfigurations: [
{ subnetResourceId: subnetId }
]
}
]
adminUsername: 'azureuser'
disablePasswordAuthentication: true
publicKeys: [
{ path: '/home/azureuser/.ssh/authorized_keys', keyData: sshPublicKey }
]
// cloud-init でアプリ初期化
customData: loadFileAsBase64('scripts/vm-init/app-init.yaml')
}
}Private Endpoint 付き Storage
module storage 'br/public:avm/res/storage/storage-account:0.31.0' = {
name: 'storageDeployment'
params: {
name: 'st${workloadName}${environment}'
skuName: 'Standard_LRS'
kind: 'StorageV2'
privateEndpoints: [
{
subnetResourceId: subnetId
service: 'blob'
privateDnsZoneGroup: {
privateDnsZoneGroupConfigs: [
{ privateDnsZoneResourceId: blobPrivateDnsZoneId }
]
}
}
]
}
}---
最新情報の取得
# MCP ツールで最新バージョンを確認
mcp_bicep_experim_list_avm_metadata# Azure Pipelines - Bicep デプロイパイプライン
#
# このパイプラインは Bicep テンプレートを Azure にデプロイします。
# 使用方法: プロジェクトの azure-pipelines.yml としてコピー
#
# 前提条件:
# 1. Azure Service Connection (例: 'azure-service-connection')
# 2. Variable Group 'azure-deploy-vars' with:
# - RESOURCE_GROUP
# - AZURE_SUBSCRIPTION_ID
trigger:
branches:
include:
- main
paths:
include:
- "env/**/bicep/**"
pr:
branches:
include:
- main
paths:
include:
- "env/**/bicep/**"
# パイプラインパラメータ
parameters:
- name: environment
displayName: "Target Environment"
type: string
default: "dev"
values:
- dev
- staging
- prod
- name: deployMode
displayName: "Deploy Mode"
type: string
default: "validate"
values:
- validate
- what-if
- deploy
variables:
# Variable Group から読み込み
- group: azure-deploy-vars
# パイプライン変数
- name: bicepPath
value: "env/${{ parameters.environment }}/bicep"
- name: templateFile
value: "main.bicep"
- name: parametersFile
value: "parameters/${{ parameters.environment }}.json"
- name: serviceConnection
value: "azure-service-connection"
stages:
# ========================================
# Stage 1: 検証
# ========================================
- stage: Validate
displayName: "Validate Bicep"
jobs:
- job: ValidateBicep
displayName: "Lint and Validate"
pool:
vmImage: "ubuntu-latest"
steps:
# チェックアウト
- checkout: self
displayName: "Checkout repository"
# Azure CLI タスク - Bicep バージョン確認
- task: AzureCLI@2
displayName: "Check Bicep version"
inputs:
azureSubscription: $(serviceConnection)
scriptType: "bash"
scriptLocation: "inlineScript"
inlineScript: |
az bicep version
az bicep upgrade
# Bicep Lint
- task: AzureCLI@2
displayName: "Lint Bicep template"
inputs:
azureSubscription: $(serviceConnection)
scriptType: "bash"
scriptLocation: "inlineScript"
inlineScript: |
echo "##[section]Linting Bicep template..."
az bicep build \
--file $(bicepPath)/$(templateFile) \
--stdout > /dev/null
echo "##[section]Lint passed!"
# ARM テンプレート検証
- task: AzureCLI@2
displayName: "Validate ARM template"
inputs:
azureSubscription: $(serviceConnection)
scriptType: "bash"
scriptLocation: "inlineScript"
inlineScript: |
echo "##[section]Validating deployment..."
az deployment group validate \
--resource-group $(RESOURCE_GROUP) \
--template-file $(bicepPath)/$(templateFile) \
--parameters @$(bicepPath)/$(parametersFile)
echo "##[section]Validation passed!"
# ========================================
# Stage 2: What-If プレビュー
# ========================================
- stage: WhatIf
displayName: "What-If Preview"
dependsOn: Validate
condition: |
and(
succeeded(),
or(
eq(variables['Build.Reason'], 'PullRequest'),
eq('${{ parameters.deployMode }}', 'what-if')
)
)
jobs:
- job: WhatIfAnalysis
displayName: "Run What-If"
pool:
vmImage: "ubuntu-latest"
steps:
- checkout: self
- task: AzureCLI@2
displayName: "Run What-If Analysis"
inputs:
azureSubscription: $(serviceConnection)
scriptType: "bash"
scriptLocation: "inlineScript"
inlineScript: |
echo "##[section]Running What-If analysis..."
echo "Environment: ${{ parameters.environment }}"
echo "Resource Group: $(RESOURCE_GROUP)"
echo ""
az deployment group what-if \
--resource-group $(RESOURCE_GROUP) \
--template-file $(bicepPath)/$(templateFile) \
--parameters @$(bicepPath)/$(parametersFile) \
--out table
# ========================================
# Stage 3: デプロイ (Dev)
# ========================================
- stage: DeployDev
displayName: "Deploy to Dev"
dependsOn: Validate
condition: |
and(
succeeded(),
eq('${{ parameters.environment }}', 'dev'),
eq('${{ parameters.deployMode }}', 'deploy'),
ne(variables['Build.Reason'], 'PullRequest')
)
jobs:
- deployment: DeployToDev
displayName: "Deploy to Dev Environment"
pool:
vmImage: "ubuntu-latest"
environment: "dev"
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: AzureCLI@2
displayName: "Deploy Bicep template"
inputs:
azureSubscription: $(serviceConnection)
scriptType: "bash"
scriptLocation: "inlineScript"
inlineScript: |
DEPLOYMENT_NAME="deploy-$(Build.BuildNumber)"
echo "##[section]Deploying to Dev..."
echo "Deployment Name: $DEPLOYMENT_NAME"
az deployment group create \
--name $DEPLOYMENT_NAME \
--resource-group $(RESOURCE_GROUP) \
--template-file $(bicepPath)/$(templateFile) \
--parameters @$(bicepPath)/$(parametersFile) \
--output table
echo "##[section]Deployment completed!"
# ========================================
# Stage 4: デプロイ (Staging)
# ========================================
- stage: DeployStaging
displayName: "Deploy to Staging"
dependsOn: Validate
condition: |
and(
succeeded(),
eq('${{ parameters.environment }}', 'staging'),
eq('${{ parameters.deployMode }}', 'deploy'),
ne(variables['Build.Reason'], 'PullRequest')
)
jobs:
- deployment: DeployToStaging
displayName: "Deploy to Staging Environment"
pool:
vmImage: "ubuntu-latest"
environment: "staging"
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: AzureCLI@2
displayName: "Deploy Bicep template"
inputs:
azureSubscription: $(serviceConnection)
scriptType: "bash"
scriptLocation: "inlineScript"
inlineScript: |
DEPLOYMENT_NAME="deploy-$(Build.BuildNumber)"
az deployment group create \
--name $DEPLOYMENT_NAME \
--resource-group $(RESOURCE_GROUP) \
--template-file $(bicepPath)/$(templateFile) \
--parameters @$(bicepPath)/$(parametersFile) \
--output table
# ========================================
# Stage 5: デプロイ (Production)
# ========================================
- stage: DeployProd
displayName: "Deploy to Production"
dependsOn: Validate
condition: |
and(
succeeded(),
eq('${{ parameters.environment }}', 'prod'),
eq('${{ parameters.deployMode }}', 'deploy'),
ne(variables['Build.Reason'], 'PullRequest')
)
jobs:
- deployment: DeployToProd
displayName: "Deploy to Production Environment"
pool:
vmImage: "ubuntu-latest"
# 本番環境は承認が必要
environment: "production"
strategy:
runOnce:
deploy:
steps:
- checkout: self
# バックアップ作成 (オプション)
- task: AzureCLI@2
displayName: "Export current state"
inputs:
azureSubscription: $(serviceConnection)
scriptType: "bash"
scriptLocation: "inlineScript"
inlineScript: |
echo "##[section]Exporting current resource state..."
az deployment group list \
--resource-group $(RESOURCE_GROUP) \
--query "[?properties.provisioningState=='Succeeded'].{name:name,timestamp:properties.timestamp}" \
--output table
- task: AzureCLI@2
displayName: "Deploy Bicep template"
inputs:
azureSubscription: $(serviceConnection)
scriptType: "bash"
scriptLocation: "inlineScript"
inlineScript: |
DEPLOYMENT_NAME="deploy-$(Build.BuildNumber)"
echo "##[section]Deploying to Production..."
echo "⚠️ This is a production deployment!"
az deployment group create \
--name $DEPLOYMENT_NAME \
--resource-group $(RESOURCE_GROUP) \
--template-file $(bicepPath)/$(templateFile) \
--parameters @$(bicepPath)/$(parametersFile) \
--output table
echo "##[section]Production deployment completed!"
# 結果出力
- task: AzureCLI@2
displayName: "Output deployment result"
inputs:
azureSubscription: $(serviceConnection)
scriptType: "bash"
scriptLocation: "inlineScript"
inlineScript: |
echo "===================================="
echo "✅ Production Deployment Successful"
echo "===================================="
echo "Resource Group: $(RESOURCE_GROUP)"
echo "Subscription: $(AZURE_SUBSCRIPTION_ID)"
echo ""
echo "Portal: https://portal.azure.com/#@/resource/subscriptions/$(AZURE_SUBSCRIPTION_ID)/resourceGroups/$(RESOURCE_GROUP)/overview"
# ============================================================
# セットアップ手順
# ============================================================
#
# 1. Azure Service Connection 作成
# Project Settings > Service connections > New > Azure Resource Manager
# 名前: azure-service-connection
#
# 2. Variable Group 作成
# Pipelines > Library > + Variable group
# 名前: azure-deploy-vars
# 変数:
# - RESOURCE_GROUP: リソースグループ名
# - AZURE_SUBSCRIPTION_ID: サブスクリプション ID
#
# 3. Environment 作成と承認設定
# Pipelines > Environments
# - dev (承認なし)
# - staging (任意)
# - production (承認必須)
#
# 4. パイプライン作成
# Pipelines > New pipeline > Azure Repos Git
# このファイルを選択
# GitHub Actions - Azure Bicep デプロイワークフロー
#
# このワークフローは Bicep テンプレートを Azure にデプロイします。
# 使用方法: プロジェクトの .github/workflows/ にコピーして使用
#
# 前提条件:
# 1. AZURE_CREDENTIALS シークレット (JSON形式のサービスプリンシパル)
# 2. vars.RESOURCE_GROUP 変数
# 3. vars.AZURE_SUBSCRIPTION_ID 変数 (オプション)
name: Deploy Azure Environment
on:
push:
branches: [main]
paths:
- "env/**/bicep/**"
- ".github/workflows/deploy-azure.yml"
pull_request:
branches: [main]
paths:
- "env/**/bicep/**"
workflow_dispatch:
inputs:
environment:
description: "Target environment"
required: true
default: "dev"
type: choice
options:
- dev
- staging
- prod
deploy_mode:
description: "Deploy mode"
required: true
default: "validate"
type: choice
options:
- validate
- what-if
- deploy
# 同時実行を制限(環境ごとに1つのデプロイのみ)
concurrency:
group: deploy-${{ github.event.inputs.environment || 'dev' }}
cancel-in-progress: false
env:
# デフォルト設定(必要に応じて変更)
BICEP_PATH: env/${{ github.event.inputs.environment || 'dev' }}/bicep
TEMPLATE_FILE: main.bicep
PARAMETERS_FILE: parameters/${{ github.event.inputs.environment || 'dev' }}.json
jobs:
# ========================================
# 1. Bicep 検証ジョブ
# ========================================
validate:
name: Validate Bicep
runs-on: ubuntu-latest
outputs:
bicep_version: ${{ steps.bicep.outputs.version }}
steps:
# チェックアウト
- name: Checkout repository
uses: actions/checkout@v4
# Azure CLI ログイン
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
# Bicep CLI バージョン確認
- name: Check Bicep version
id: bicep
run: |
az bicep version
echo "version=$(az bicep version --query 'value' -o tsv)" >> $GITHUB_OUTPUT
# Bicep ファイルの存在確認
- name: Check template exists
run: |
if [ ! -f "${{ env.BICEP_PATH }}/${{ env.TEMPLATE_FILE }}" ]; then
echo "::error::Template file not found: ${{ env.BICEP_PATH }}/${{ env.TEMPLATE_FILE }}"
exit 1
fi
# Bicep Lint (構文チェック)
- name: Lint Bicep template
run: |
az bicep build \
--file ${{ env.BICEP_PATH }}/${{ env.TEMPLATE_FILE }} \
--stdout > /dev/null
# ARM テンプレート検証
- name: Validate ARM template
run: |
az deployment group validate \
--resource-group ${{ vars.RESOURCE_GROUP }} \
--template-file ${{ env.BICEP_PATH }}/${{ env.TEMPLATE_FILE }} \
--parameters @${{ env.BICEP_PATH }}/${{ env.PARAMETERS_FILE }}
# ========================================
# 2. What-If プレビュージョブ
# ========================================
what-if:
name: What-If Preview
needs: validate
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.event.inputs.deploy_mode == 'what-if'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
# What-If 実行(変更内容のプレビュー)
- name: Run What-If
id: whatif
run: |
az deployment group what-if \
--resource-group ${{ vars.RESOURCE_GROUP }} \
--template-file ${{ env.BICEP_PATH }}/${{ env.TEMPLATE_FILE }} \
--parameters @${{ env.BICEP_PATH }}/${{ env.PARAMETERS_FILE }} \
--out table
# PR にコメント追加 (PR の場合のみ)
- name: Comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const output = `## 🔍 What-If Preview
**Environment:** \`${{ github.event.inputs.environment || 'dev' }}\`
**Resource Group:** \`${{ vars.RESOURCE_GROUP }}\`
What-If analysis completed. Check the job logs for detailed changes.
<details>
<summary>Deployment Info</summary>
- Template: \`${{ env.BICEP_PATH }}/${{ env.TEMPLATE_FILE }}\`
- Parameters: \`${{ env.BICEP_PATH }}/${{ env.PARAMETERS_FILE }}\`
</details>`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
# ========================================
# 3. デプロイジョブ
# ========================================
deploy:
name: Deploy to Azure
needs: validate
runs-on: ubuntu-latest
if: |
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
github.event.inputs.deploy_mode == 'deploy'
# 環境の保護ルールを使用する場合はここで指定
environment:
name: ${{ github.event.inputs.environment || 'dev' }}
url: https://portal.azure.com/#@/resource/subscriptions/${{ vars.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ vars.RESOURCE_GROUP }}/overview
outputs:
deployment_name: ${{ steps.deploy.outputs.deployment_name }}
outputs: ${{ steps.deploy.outputs.outputs }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
# デプロイ実行
- name: Deploy Bicep template
id: deploy
run: |
DEPLOYMENT_NAME="deploy-$(date +%Y%m%d-%H%M%S)"
echo "deployment_name=$DEPLOYMENT_NAME" >> $GITHUB_OUTPUT
# デプロイ実行
OUTPUTS=$(az deployment group create \
--name $DEPLOYMENT_NAME \
--resource-group ${{ vars.RESOURCE_GROUP }} \
--template-file ${{ env.BICEP_PATH }}/${{ env.TEMPLATE_FILE }} \
--parameters @${{ env.BICEP_PATH }}/${{ env.PARAMETERS_FILE }} \
--query 'properties.outputs' \
--output json)
echo "outputs=$OUTPUTS" >> $GITHUB_OUTPUT
# デプロイ結果をサマリーに出力
- name: Create deployment summary
run: |
echo "## ✅ Deployment Successful" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Environment | ${{ github.event.inputs.environment || 'dev' }} |" >> $GITHUB_STEP_SUMMARY
echo "| Resource Group | ${{ vars.RESOURCE_GROUP }} |" >> $GITHUB_STEP_SUMMARY
echo "| Deployment Name | ${{ steps.deploy.outputs.deployment_name }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🔗 Links" >> $GITHUB_STEP_SUMMARY
echo "- [Azure Portal](https://portal.azure.com/#@/resource/subscriptions/${{ vars.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ vars.RESOURCE_GROUP }}/overview)" >> $GITHUB_STEP_SUMMARY
# ========================================
# 4. 通知ジョブ (オプション)
# ========================================
notify:
name: Notify
needs: [validate, deploy]
runs-on: ubuntu-latest
if: always() && needs.deploy.result != 'skipped'
steps:
# Slack 通知 (オプション - 使用する場合は SLACK_WEBHOOK シークレットを設定)
- name: Notify Slack
if: ${{ secrets.SLACK_WEBHOOK != '' }}
run: |
STATUS=${{ needs.deploy.result == 'success' && '✅ Success' || '❌ Failed' }}
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"Azure Deployment $STATUS\\nEnvironment: ${{ github.event.inputs.environment || 'dev' }}\\nRun: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}" \
${{ secrets.SLACK_WEBHOOK }}
# ============================================================
# セットアップ手順
# ============================================================
#
# 1. サービスプリンシパル作成
# az ad sp create-for-rbac --name "github-actions-sp" --role Contributor \
# --scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group} \
# --sdk-auth
#
# 2. GitHub Secrets 設定
# - AZURE_CREDENTIALS: 上記コマンドの出力 JSON
#
# 3. GitHub Variables 設定
# - RESOURCE_GROUP: 対象リソースグループ名
# - AZURE_SUBSCRIPTION_ID: サブスクリプション ID
#
# 4. 環境保護ルール (推奨)
# Settings > Environments で prod 環境に承認者を設定
CI/CD テンプレート
Azure Bicep デプロイ用の CI/CD パイプラインテンプレート。
テンプレート一覧
| ファイル | プラットフォーム | 用途 |
|---|---|---|
| github-actions.yml | GitHub Actions | GitHub リポジトリ用 |
| azure-pipelines.yml | Azure DevOps | Azure DevOps リポジトリ用 |
機能比較
| 機能 | GitHub Actions | Azure Pipelines |
|---|---|---|
| Bicep Lint | ✅ | ✅ |
| ARM 検証 | ✅ | ✅ |
| What-If プレビュー | ✅ | ✅ |
| 環境別デプロイ | ✅ | ✅ |
| 承認ゲート | ✅ | ✅ |
| PR コメント | ✅ | ❌ |
| Slack 通知 | ✅ | ❌ (拡張可能) |
| パイプライン変数 | ✅ | ✅ |
クイックスタート
GitHub Actions
# 1. ワークフローファイルをコピー
mkdir -p .github/workflows
cp references/cicd-templates/github-actions.yml .github/workflows/deploy-azure.yml
# 2. シークレット設定
gh secret set AZURE_CREDENTIALS < service-principal.json
# 3. 変数設定
gh variable set RESOURCE_GROUP --body "rg-myapp-prod"
gh variable set AZURE_SUBSCRIPTION_ID --body "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"Azure Pipelines
# 1. パイプラインファイルをコピー
cp references/cicd-templates/azure-pipelines.yml azure-pipelines.yml
# 2. Azure DevOps で設定
# - Service Connection 作成
# - Variable Group 作成
# - Environment 作成サービスプリンシパル作成
# Contributor ロールでサービスプリンシパル作成
az ad sp create-for-rbac \
--name "cicd-deployment-sp" \
--role Contributor \
--scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group} \
--sdk-auth
# 出力例 (これを AZURE_CREDENTIALS シークレットに設定)
{
"clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"clientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
...
}環境保護ルール (推奨)
GitHub
1. Settings > Environments 2. 「New environment」で prod 作成 3. 「Required reviewers」で承認者を追加
Azure DevOps
1. Pipelines > Environments 2. production 環境を選択 3. 「Approvals and checks」で承認者を追加
ブランチ戦略
main (protected)
├── PR マージ時に dev 自動デプロイ
│
feature/*
├── PR 作成時に What-If プレビュー
│
release/*
└── staging/prod への手動デプロイトラブルシューティング
よくあるエラー
| エラー | 原因 | 解決策 |
|---|---|---|
AuthorizationFailed | SP の権限不足 | Contributor ロールを確認 |
ResourceGroupNotFound | RG が存在しない | 先に RG を作成するか Subscription スコープに変更 |
InvalidTemplate | Bicep 構文エラー | az bicep build でローカル検証 |
DeploymentQuotaExceeded | デプロイ履歴上限 | 古いデプロイを削除 |
デバッグコマンド
# デプロイ履歴確認
az deployment group list --resource-group {rg} --query "[].{name:name,state:properties.provisioningState,time:properties.timestamp}" --output table
# 失敗したデプロイの詳細
az deployment group show --resource-group {rg} --name {deployment-name} --query "properties.error"
# リソースグループの現在状態
az resource list --resource-group {rg} --output table環境定義テンプレート
環境フォルダ (Az-env/<environment>/) を構成するためのテンプレート。
基本情報
| 項目 | 値 |
| ------------------ | ---------------------------- |
| 環境名 | |
| リソースグループ | |
| Azure リージョン | |
| サブスクリプション | |
| デプロイ方式 | Bicep / Azure CLI |
| スコープ | ResourceGroup / Subscription |構成概要
| カテゴリ | リソース | SKU | 備考 |
|---|---|---|---|
| 監視 | |||
| ネットワーク | |||
| コンピュート | |||
| データ | |||
| セキュリティ | |||
| DR |
→ ヒアリング詳細: hearing-checklist.md → Bicep パターン: resource-patterns.md
フォルダ構造
Az-env/<environment>/
├── README.md # この環境の概要
├── bicep/
│ ├── main.bicep # メインテンプレート
│ ├── main.bicepparam # パラメータファイル
│ └── modules/ # モジュール (オプション)
├── config/
│ └── parameters.json # 環境固有の値
└── scripts/
├── deploy.ps1 # デプロイスクリプト
└── validate.ps1 # 検証スクリプト接続パターン
- [ ] パブリック
- [ ] 閉域 (Private Endpoint)
- [ ] ハイブリッド (VPN / ExpressRoute)
高可用性・DR
| 項目 | 設定 |
|---|---|
| ゾーン冗長 | Yes / No |
| ストレージ冗長 | LRS / GRS / ZRS |
| バックアップ | Azure Backup / 手動 |
| DR サイト |
命名規則
| リソース種別 | パターン | 例 |
|---|---|---|
| Resource Group | rg-<env>-<region>-<purpose> | rg-prod-jpe-web |
| Virtual Network | vnet-<env>-<region> | vnet-prod-jpe |
| Storage Account | st<purpose><env>### | stwebprod001 |
| AKS | aks-<env>-<region> | aks-prod-jpe |
使い方
1. このテンプレートを Az-env/<environment>/README.md にコピー 2. hearing-checklist.md でヒアリング実施 3. resource-patterns.md から Bicep パターンを参照 4. bicep/ フォルダにテンプレートを配置 5. 検証 & デプロイ実行
ヒアリングチェックリスト
Azure 環境構築時に確認すべき項目一覧。
目次
1. 基本情報 2. ネットワーク 3. コンピュート 4. データ・ストレージ 5. 監視・可観測性 6. セキュリティ 7. DR・バックアップ
---
基本情報
- [ ] Azure サブスクリプション ID: \_\_\_
- [ ] Azure AD テナント: \_\_\_
- [ ] 環境名: [ ] dev [ ] staging [ ] prod [ ] その他: \_\_\_
- [ ] リージョン: [ ] japaneast [ ] japanwest [ ] その他: \_\_\_
- [ ] デプロイ方式: [ ] Bicep [ ] Azure CLI
- [ ] スコープ: [ ] ResourceGroup [ ] Subscription
- [ ] 命名規則: \_\_\_
- [ ] タグ要件: \_\_\_---
ネットワーク
接続パターン
- [ ] パブリック (インターネット経由)
- [ ] 閉域 (Private Endpoint)
- [ ] ハイブリッド (VPN / ExpressRoute)VNet 構成
- [ ] 新規 VNet 作成
- CIDR: **_._**.**_._**/\_\_\_
- [ ] 既存 VNet 接続
- VNet 名: \_\_\_
- [ ] Hub-Spoke 構成
- [ ] VNet PeeringPrivate Endpoint
必要なサービス:
- [ ] Storage Account
- [ ] SQL Database
- [ ] Key Vault
- [ ] Container Registry
- [ ] Cosmos DB
- [ ] その他: \_\_\_ハイブリッド接続
- [ ] VPN Gateway
- SKU: [ ] VpnGw1 [ ] VpnGw2 [ ] VpnGw2AZ
- [ ] Active-Active
- [ ] P2S (Point-to-Site)
- [ ] ExpressRoute Gateway
- SKU: [ ] Standard [ ] HighPerf [ ] UltraPerf
- [ ] Virtual WANセキュリティ
- [ ] Azure Firewall: [ ] Basic [ ] Standard [ ] Premium
- [ ] Azure Bastion: [ ] Basic [ ] Standard [ ] Premium
- [ ] DDoS Protection Plan
- [ ] NSG ルール要件: \_\_\_負荷分散
- [ ] Azure Load Balancer (L4)
- [ ] Application Gateway (L7)
- [ ] WAF 必要
- [ ] Azure Front Door
- [ ] Traffic Manager→ MCP で最新スキーマ取得:
mcp_bicep_experim_get_az_resource_type_schema(azResourceType: "Microsoft.Network/virtualNetworks")
microsoft_code_sample_search(query: "VNet Bicep", language: "bicep")---
コンピュート
IaaS
- [ ] Virtual Machine
- OS: [ ] Windows [ ] Linux
- SKU: \_\_\_
- 台数: \_\_\_
- [ ] Availability Zone
- [ ] Availability Set
- [ ] VMSS
- 最小: **_ 最大: _**
- [ ] Autoscale
- [ ] Azure Virtual DesktopPaaS
- [ ] App Service
- SKU: [ ] Basic [ ] Standard [ ] Premium
- [ ] デプロイスロット
- [ ] VNet 統合
- [ ] Function App
- プラン: [ ] Consumption [ ] Premium [ ] Dedicated
- [ ] Container Apps
- [ ] Static Web Appsコンテナ
- [ ] AKS
- [ ] Private Cluster
- ノード数: \_\_\_
- [ ] Autoscale
- [ ] ACR
- SKU: [ ] Basic [ ] Standard [ ] Premium
- [ ] ACI→ MCP で最新スキーマ取得:
mcp_bicep_experim_get_az_resource_type_schema(azResourceType: "Microsoft.Web/sites")
mcp_bicep_experim_get_az_resource_type_schema(azResourceType: "Microsoft.ContainerService/managedClusters")---
データ・ストレージ
SQL
- [ ] Azure SQL Database
- SKU: [ ] Basic [ ] Standard [ ] Premium [ ] vCore
- [ ] Serverless
- [ ] ゾーン冗長
- [ ] SQL Managed Instance
- [ ] PostgreSQL Flexible Server
- [ ] MySQL Flexible ServerNoSQL
- [ ] Cosmos DB
- API: [ ] NoSQL [ ] MongoDB [ ] Cassandra [ ] Gremlin
- 容量: [ ] Serverless [ ] Provisioned [ ] Autoscale
- [ ] Redis Cache
- SKU: [ ] Basic [ ] Standard [ ] Premiumストレージ
- [ ] Storage Account
- SKU: [ ] Standard_LRS [ ] Standard_GRS [ ] Premium_LRS
- [ ] Blob [ ] Files [ ] Queue [ ] Table
- [ ] Data Lake Gen2
- [ ] Private Endpoint分析
- [ ] Synapse Analytics
- [ ] Data Factory
- [ ] Databricks
- [ ] Event Hubs→ MCP で最新スキーマ取得:
mcp_bicep_experim_get_az_resource_type_schema(azResourceType: "Microsoft.Storage/storageAccounts")
mcp_bicep_experim_get_az_resource_type_schema(azResourceType: "Microsoft.DocumentDB/databaseAccounts")---
監視・可観測性
- [ ] Log Analytics Workspace
- 保持日数: \_\_\_ 日
- [ ] Azure Monitor Workspace (Prometheus)
- [ ] Application Insights
- [ ] Azure Managed Grafana
- [ ] Microsoft Sentinel
- [ ] アラートルール: \_\_\_→ MCP で最新スキーマ取得:
mcp_bicep_experim_get_az_resource_type_schema(azResourceType: "Microsoft.OperationalInsights/workspaces")
microsoft_code_sample_search(query: "Log Analytics Workspace Bicep", language: "bicep")---
セキュリティ
- [ ] Key Vault
- [ ] RBAC モード
- [ ] Private Endpoint
- [ ] Managed Identity
- [ ] SystemAssigned
- [ ] UserAssigned
- [ ] Azure AD 認証
- [ ] Defender for Cloud---
DR・バックアップ
- [ ] Azure Backup
- 対象: [ ] VM [ ] SQL [ ] Files
- [ ] Site Recovery
- DR リージョン: \_\_\_
- [ ] Geo レプリケーション
- [ ] Storage GRS
- [ ] SQL Geo-Replica
- [ ] Cosmos DB Multi-region---
使い方
1. 該当項目にチェックを入れる 2. 必要な値を記入 3. MCP ツールで最新スキーマを取得 4. Bicep 実装に進む
Low-cost Azure operations demo patterns
Use these patterns when building demo environments for Azure operations, RCA, alert response, or assistant-driven investigation. Prefer cheap, disposable resources and explicit manual setup artifacts over assuming everything can be automated by CLI.
Design defaults
- Start with 1 demo resource group + 1 minimal app + 1-2 alerts + short-retention logs.
- Prefer Azure Container Apps Consumption for low-cost app demos, especially when App Service plan creation fails because regional or subscription VM quota is unavailable.
- Avoid always-on VMs, AKS, and always-on databases unless the demo specifically requires runtime compute.
- Tag demo resource groups and resources with
purpose,costProfile,owner, anddemoso cleanup is obvious. - Keep Log Analytics retention short and avoid verbose logs or high-frequency alert rules.
App hosting choice
| Constraint | Preferred pattern |
|---|---|
| Lowest idle cost | Container Apps Consumption with minReplicas: 0 and maxReplicas: 1 |
App Service quota error such as Current Limit (Total VMs): 0 | Switch to Container Apps Consumption instead of retrying regions repeatedly |
| Stable enterprise web app demo | App Service if quota and plan cost are acceptable |
| Kubernetes-specific demo | AKS only when Kubernetes behavior is the point |
Operations demo scenarios
- App RCA: make the app return HTTP 500 and emit a distinctive log string so logs, metrics, configuration, and recent changes can be correlated.
- Control-plane network issue: reproduce path problems without VMs by using NSG deny rules, a UDR with a missing NVA next hop, orphan Private DNS records, or missing Private DNS VNet links.
- Alert response: create only 1-2 Azure Monitor alerts and scope response flows to the demo resource group, alert name, and severity.
- Review-mode remediation: start with Reader or review/approval mode. Use autonomous remediation only for verified non-production actions.
- Knowledge / runbook: include known failures, expected root causes, safe mitigations, and escalation text as reusable Markdown.
Portal and connector work
If the workflow involves portal-only configuration, OAuth, admin consent, Teams, Outlook, incident platform connectors, or managed agent setup, do not claim CLI-only completion. Produce setup artifacts instead:
setup-portal.md: portal steps, consent points, resource scopes, and manual verificationprompts.md: prompts for resource discovery, RCA, network analysis, daily Teams summary, and weekly Outlook summarydemo-commands.ps1: traffic generation, failure-mode toggles, and cleanup commandsdeployment-result.json: resource names, endpoints, active failure mode, and cleanup hints
For outbound Teams or Outlook demos, avoid forwarding raw alerts. Send a summarized RCA with impact, evidence, and recommended action.
Done criteria
- [ ] Cost-driving always-on resources are justified or avoided
- [ ] App hosting choice accounts for quota and idle cost
- [ ] Manual portal / OAuth / consent steps are captured when automation is not reliable
- [ ] Demo failure modes are reversible and cleanup is documented
- [ ] Microsoft Learn or pricing references are captured in final deliverables when claims depend on current product behavior
リソースパターン
#microsoft.docs.mcp 公式サンプルから抽出した Bicep パターン。
目次
1. 監視・可観測性 2. ネットワーク 3. コンピュート 4. DR・バックアップ 5. データサービス
---
監視・可観測性
Log Analytics Workspace
Source: https://learn.microsoft.com/en-us/azure/azure-monitor/logs/quick-create-workspace
// Log Analytics Workspace の作成
@description('Log Analytics workspace name')
param workspaceName string
@description('Pricing tier (PerGB2018 recommended)')
param sku string = 'PerGB2018'
@description('Location')
param location string = resourceGroup().location
@description('Data retention in days')
param retentionInDays int = 30
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
name: workspaceName
location: location
properties: {
sku: {
name: sku
}
retentionInDays: retentionInDays
features: {
searchVersion: 1
}
}
}
output workspaceId string = logAnalyticsWorkspace.id
output customerId string = logAnalyticsWorkspace.properties.customerIdDiagnostic Settings (Activity Log)
Source: https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/scenarios-monitoring#diagnostic-settings
// サブスクリプションレベルの診断設定
targetScope = 'subscription'
@description('Log Analytics workspace resource ID')
param logAnalyticsWorkspaceId string
var activityLogDiagnosticSettingsName = 'export-activity-log'
resource subscriptionActivityLog 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
name: activityLogDiagnosticSettingsName
properties: {
workspaceId: logAnalyticsWorkspaceId
logs: [
{ category: 'Administrative', enabled: true }
{ category: 'Security', enabled: true }
{ category: 'ServiceHealth', enabled: true }
{ category: 'Alert', enabled: true }
{ category: 'Recommendation', enabled: true }
{ category: 'Policy', enabled: true }
{ category: 'Autoscale', enabled: true }
{ category: 'ResourceHealth', enabled: true }
]
}
}---
ネットワーク
ExpressRoute Gateway
Source: https://learn.microsoft.com/en-us/azure/expressroute/quickstart-create-expressroute-vnet-bicep
// ExpressRoute 回線 + ゲートウェイ構成
@description('ExpressRoute Gateway SKU')
@allowed(['Standard', 'HighPerformance', 'UltraPerformance', 'ErGw1AZ', 'ErGw2AZ', 'ErGw3AZ'])
param gatewaySku string = 'HighPerformance'
@description('Virtual network name')
param vnetName string
@description('Gateway subnet prefix (must be /27 or larger)')
param gatewaySubnetPrefix string = '10.10.10.224/27'
@description('Location')
param location string = resourceGroup().location
// VNet は既存を参照
resource vnet 'Microsoft.Network/virtualNetworks@2023-09-01' existing = {
name: vnetName
}
resource gatewayPublicIP 'Microsoft.Network/publicIPAddresses@2023-09-01' = {
name: '${vnetName}-ergw-pip'
location: location
sku: {
name: 'Standard'
tier: 'Regional'
}
properties: {
publicIPAllocationMethod: 'Static'
}
}
resource gateway 'Microsoft.Network/virtualNetworkGateways@2023-09-01' = {
name: '${vnetName}-ergw'
location: location
properties: {
ipConfigurations: [
{
name: 'gwIPconf'
properties: {
privateIPAllocationMethod: 'Dynamic'
subnet: {
id: resourceId('Microsoft.Network/virtualNetworks/subnets', vnetName, 'GatewaySubnet')
}
publicIPAddress: {
id: gatewayPublicIP.id
}
}
}
]
gatewayType: 'ExpressRoute'
sku: {
name: gatewaySku
tier: gatewaySku
}
vpnType: 'RouteBased'
}
}
output gatewayName string = gateway.nameVPN Gateway (Site-to-Site)
Source: https://learn.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-howto-site-to-site-resource-manager-cli
// VPN Gateway for S2S connection
@description('VPN Gateway SKU')
@allowed(['VpnGw1', 'VpnGw2', 'VpnGw2AZ', 'VpnGw3', 'VpnGw3AZ'])
param vpnGatewaySku string = 'VpnGw2AZ'
@description('Virtual network name')
param vnetName string
@description('Location')
param location string = resourceGroup().location
resource vpnGatewayPip 'Microsoft.Network/publicIPAddresses@2023-09-01' = {
name: '${vnetName}-vpngw-pip'
location: location
sku: {
name: 'Standard'
}
zones: ['1', '2', '3']
properties: {
publicIPAllocationMethod: 'Static'
}
}
resource vpnGateway 'Microsoft.Network/virtualNetworkGateways@2023-09-01' = {
name: '${vnetName}-vpngw'
location: location
properties: {
gatewayType: 'Vpn'
vpnType: 'RouteBased'
sku: {
name: vpnGatewaySku
tier: vpnGatewaySku
}
ipConfigurations: [
{
name: 'vpngwipconfig'
properties: {
privateIPAllocationMethod: 'Dynamic'
subnet: {
id: resourceId('Microsoft.Network/virtualNetworks/subnets', vnetName, 'GatewaySubnet')
}
publicIPAddress: {
id: vpnGatewayPip.id
}
}
}
]
enableBgp: false
}
}---
コンピュート
AKS (Private Cluster)
Source: https://learn.microsoft.com/en-us/azure/aks/private-clusters
// AKS Private Cluster
@description('AKS cluster name')
param clusterName string = 'aksprivate'
@description('Location')
param location string = resourceGroup().location
@description('Kubernetes version')
param kubernetesVersion string = '1.30'
@description('Node count')
param nodeCount int = 3
@description('Node size')
param nodeSize string = 'Standard_D4s_v3'
resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-02-01' = {
name: clusterName
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
dnsPrefix: clusterName
kubernetesVersion: kubernetesVersion
networkProfile: {
networkPlugin: 'azure'
}
apiServerAccessProfile: {
enablePrivateCluster: true
}
agentPoolProfiles: [
{
name: 'systempool'
count: nodeCount
vmSize: nodeSize
mode: 'System'
enableAutoScaling: true
minCount: 1
maxCount: 5
}
]
}
}
output clusterFqdn string = aksCluster.properties.fqdnContainer Apps Environment
Source: https://learn.microsoft.com/en-us/azure/container-apps/managed-identity-image-pull
// Container Apps Environment with Log Analytics
@description('Environment name')
param environmentName string
@description('Log Analytics workspace name')
param logAnalyticsName string
@description('Location')
param location string = resourceGroup().location
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
name: logAnalyticsName
location: location
properties: {
retentionInDays: 30
sku: {
name: 'PerGB2018'
}
}
}
resource appEnvironment 'Microsoft.App/managedEnvironments@2024-03-01' = {
name: environmentName
location: location
properties: {
appLogsConfiguration: {
destination: 'log-analytics'
logAnalyticsConfiguration: {
customerId: logAnalyticsWorkspace.properties.customerId
sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
}
}
}
}
output environmentId string = appEnvironment.idApp Service (Linux)
Source: https://learn.microsoft.com/en-us/azure/app-service/provision-resource-bicep
// App Service on Linux
@description('Web app name')
param webAppName string = uniqueString(resourceGroup().id)
@description('App Service plan SKU')
param sku string = 'P1v3'
@description('Runtime stack')
param linuxFxVersion string = 'DOTNETCORE|8.0'
@description('Location')
param location string = resourceGroup().location
var appServicePlanName = toLower('asp-${webAppName}')
resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
name: appServicePlanName
location: location
kind: 'linux'
sku: {
name: sku
}
properties: {
reserved: true // Linux の場合は true
}
}
resource appService 'Microsoft.Web/sites@2023-12-01' = {
name: webAppName
location: location
properties: {
serverFarmId: appServicePlan.id
httpsOnly: true
siteConfig: {
linuxFxVersion: linuxFxVersion
minTlsVersion: '1.2'
ftpsState: 'Disabled'
}
}
identity: {
type: 'SystemAssigned'
}
}
output appUrl string = 'https://${appService.properties.defaultHostName}'---
DR・バックアップ
Recovery Services Vault
Source: https://learn.microsoft.com/en-us/azure/site-recovery/quickstart-create-vault-bicep
// Recovery Services Vault for Azure Backup & Site Recovery
@description('Vault name')
param vaultName string
@description('Enable Cross Region Restore')
param enableCRR bool = true
@description('Storage redundancy type')
@allowed(['LocallyRedundant', 'GeoRedundant'])
param vaultStorageType string = 'GeoRedundant'
@description('Location')
param location string = resourceGroup().location
resource recoveryServicesVault 'Microsoft.RecoveryServices/vaults@2022-02-01' = {
name: vaultName
location: location
sku: {
name: 'RS0'
tier: 'Standard'
}
properties: {}
}
resource vaultStorageConfig 'Microsoft.RecoveryServices/vaults/backupstorageconfig@2022-02-01' = {
parent: recoveryServicesVault
name: 'vaultstorageconfig'
properties: {
storageModelType: vaultStorageType
crossRegionRestoreFlag: enableCRR
}
}
output vaultId string = recoveryServicesVault.idVault Diagnostic Settings
Source: https://learn.microsoft.com/en-us/azure/azure-monitor/platform/resource-manager-diagnostic-settings
// Recovery Services Vault with diagnostic settings
@description('Recovery Services vault name')
param vaultName string
@description('Log Analytics workspace ID')
param workspaceId string
resource vault 'Microsoft.RecoveryServices/vaults@2021-08-01' existing = {
name: vaultName
}
resource vaultDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
name: '${vaultName}-diag'
scope: vault
properties: {
workspaceId: workspaceId
logs: [
{ category: 'CoreAzureBackup', enabled: true }
{ category: 'AddonAzureBackupJobs', enabled: true }
{ category: 'AddonAzureBackupAlerts', enabled: true }
{ category: 'AddonAzureBackupPolicy', enabled: true }
{ category: 'AddonAzureBackupStorage', enabled: true }
{ category: 'AddonAzureBackupProtectedInstance', enabled: true }
]
logAnalyticsDestinationType: 'Dedicated'
}
}---
Azure CLI 参考コマンド
# リソースグループ作成
az group create --name $RG_NAME --location $LOCATION
# AKS Private Cluster 作成
az aks create \
--resource-group $RG_NAME \
--name myPrivateCluster \
--enable-private-cluster \
--network-plugin azure \
--generate-ssh-keys
# VPN Gateway 作成
az network vnet-gateway create \
--name MyVnetGateway \
--resource-group $RG_NAME \
--vnet MyVnet \
--gateway-type Vpn \
--vpn-type RouteBased \
--sku VpnGw2AZ
# Recovery Services Vault 作成
az backup vault create \
--resource-group $RG_NAME \
--name myRecoveryVault \
--location $LOCATION---
データサービス
Azure SQL Database
Source: https://learn.microsoft.com/en-us/azure/azure-sql/database/single-database-create-bicep-quickstart
// Azure SQL Database (シンプル構成)
@description('SQL Server name')
param serverName string = uniqueString('sql', resourceGroup().id)
@description('SQL Database name')
param sqlDBName string = 'SampleDB'
@description('Location')
param location string = resourceGroup().location
@description('Administrator login')
param administratorLogin string
@description('Administrator password')
@secure()
param administratorLoginPassword string
// SQL Server
resource sqlServer 'Microsoft.Sql/servers@2022-05-01-preview' = {
name: serverName
location: location
properties: {
administratorLogin: administratorLogin
administratorLoginPassword: administratorLoginPassword
}
}
// SQL Database
resource sqlDB 'Microsoft.Sql/servers/databases@2022-05-01-preview' = {
parent: sqlServer
name: sqlDBName
location: location
sku: {
name: 'Standard'
tier: 'Standard'
}
}Azure SQL Database with Private Endpoint
Source: https://learn.microsoft.com/en-us/azure/private-link/create-private-endpoint-bicep
// Private Endpoint 付き SQL Database
@description('SQL administrator login')
param sqlAdministratorLogin string
@secure()
param sqlAdministratorLoginPassword string
@description('Location')
param location string = resourceGroup().location
var sqlServerName = 'sqlserver${uniqueString(resourceGroup().id)}'
var privateDnsZoneName = 'privatelink${environment().suffixes.sqlServerHostname}'
var privateEndpointName = 'sqlPrivateEndpoint'
// SQL Server (Public Network Access 無効)
resource sqlServer 'Microsoft.Sql/servers@2021-11-01-preview' = {
name: sqlServerName
location: location
properties: {
administratorLogin: sqlAdministratorLogin
administratorLoginPassword: sqlAdministratorLoginPassword
version: '12.0'
publicNetworkAccess: 'Disabled'
}
}
// Private Endpoint
resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = {
name: privateEndpointName
location: location
properties: {
subnet: {
id: subnet.id
}
privateLinkServiceConnections: [
{
name: privateEndpointName
properties: {
privateLinkServiceId: sqlServer.id
groupIds: ['sqlServer']
}
}
]
}
}
// Private DNS Zone
resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
name: privateDnsZoneName
location: 'global'
}Azure Cosmos DB
Source: https://learn.microsoft.com/en-us/azure/cosmos-db/manage-with-bicep
// Cosmos DB Account (Autoscale構成)
@description('Cosmos DB account name')
param accountName string = 'sql-${uniqueString(resourceGroup().id)}'
@description('Location')
param location string = resourceGroup().location
@description('Primary region')
param primaryRegion string
@description('Secondary region')
param secondaryRegion string
@description('Database name')
param databaseName string
@description('Container name')
param containerName string
@description('Max autoscale throughput')
@minValue(1000)
@maxValue(1000000)
param autoscaleMaxThroughput int = 1000
var locations = [
{ locationName: primaryRegion, failoverPriority: 0, isZoneRedundant: false }
{ locationName: secondaryRegion, failoverPriority: 1, isZoneRedundant: false }
]
// Cosmos DB Account
resource account 'Microsoft.DocumentDB/databaseAccounts@2022-05-15' = {
name: toLower(accountName)
kind: 'GlobalDocumentDB'
location: location
properties: {
consistencyPolicy: { defaultConsistencyLevel: 'Session' }
locations: locations
databaseAccountOfferType: 'Standard'
enableAutomaticFailover: true
}
}
// Database
resource database 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2022-05-15' = {
parent: account
name: databaseName
properties: {
resource: { id: databaseName }
}
}
// Container with Autoscale
resource container 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2022-05-15' = {
parent: database
name: containerName
properties: {
resource: {
id: containerName
partitionKey: { paths: ['/myPartitionKey'], kind: 'Hash' }
indexingPolicy: {
indexingMode: 'consistent'
includedPaths: [{ path: '/*' }]
excludedPaths: [{ path: '/_etag/?' }]
}
}
options: {
autoscaleSettings: { maxThroughput: autoscaleMaxThroughput }
}
}
}Azure Cache for Redis
Source: https://learn.microsoft.com/en-us/azure/redis/redis-cache-bicep-provision
// Azure Cache for Redis
@description('Redis cache name')
param redisCacheName string = 'redisCache-${uniqueString(resourceGroup().id)}'
@description('Location')
param location string = resourceGroup().location
@description('SKU: Basic, Standard, Premium')
@allowed(['Basic', 'Standard', 'Premium'])
param redisCacheSKU string = 'Standard'
@description('SKU Family: C = Basic/Standard, P = Premium')
@allowed(['C', 'P'])
param redisCacheFamily string = 'C'
@description('Cache size (0-6 for C family, 1-5 for P family)')
@allowed([0, 1, 2, 3, 4, 5, 6])
param redisCacheCapacity int = 1
resource redisCache 'Microsoft.Cache/redis@2023-08-01' = {
name: redisCacheName
location: location
properties: {
enableNonSslPort: false
minimumTlsVersion: '1.2'
sku: {
capacity: redisCacheCapacity
family: redisCacheFamily
name: redisCacheSKU
}
redisConfiguration: {
'aad-enabled': 'true'
}
}
}
output redisHostName string = redisCache.properties.hostNameAzure Managed Redis (Enterprise)
Source: https://learn.microsoft.com/en-us/azure/redis/redis-cache-bicep-provision
// Azure Managed Redis (Enterprise)
@description('Redis cache name')
param redisCacheName string = 'redisCache-${uniqueString(resourceGroup().id)}'
@description('Location')
param location string = resourceGroup().location
resource redisEnterprise 'Microsoft.Cache/redisEnterprise@2024-05-01-preview' = {
name: redisCacheName
location: location
sku: { name: 'Balanced_B5' }
identity: { type: 'None' }
properties: { minimumTlsVersion: '1.2' }
}
resource redisEnterpriseDatabase 'Microsoft.Cache/redisEnterprise/databases@2024-05-01-preview' = {
name: 'default'
parent: redisEnterprise
properties: {
clientProtocol: 'Encrypted'
port: 10000
clusteringPolicy: 'OSSCluster'
evictionPolicy: 'NoEviction'
persistence: { aofEnabled: false, rdbEnabled: false }
}
}---
MCP ツール活用例
最新のスキーマ・サンプルを取得する:
# リソース型のスキーマを取得
mcp_bicep_experim_get_az_resource_type_schema(
azResourceType="Microsoft.ContainerService/managedClusters"
)
# 公式 Bicep サンプルを検索
mcp_microsoft_docs_microsoft_code_sample_search(
query="AKS private cluster Bicep",
language="bicep"
)
# Azure Verified Modules を検索
mcp_bicep_experim_list_avm_metadata()---
参考リンク
レビューチェックリスト
一般
- [ ] 環境名とリソース命名が命名規約に従っている
- [ ]
env/<environment>/README.mdに目的・スコープ・手順が記載されている - [ ] 認証情報・シークレットがハードコードされていない
- [ ] タグ (環境/プロジェクト/コストセンター) が設定されている
Azure CLI 方式
- [ ]
deploy.ps1に対象リソースグループ / サブスクリプションが明示されている - [ ]
-WhatIf/ dry-run の結果が確認済み - [ ] ログ / 出力が
env/<environment>/logs/に保存されている
Bicep 方式
- [ ]
az bicep buildでエラーなくビルドできる - [ ]
az bicep lintで警告がない (または理由が明記) - [ ] パラメータファイルにデフォルトが設定され、必須項目が明確
- [ ]
what-ifの結果が確認済みで、意図しないリソース削除がない - [ ] 公式サンプル (MCP) を参考にしている
ネットワーク
- [ ] VNet / サブネット設計が要件を満たしている
- [ ] Private Endpoint が必要なリソースに設定されている
- [ ] NSG / UDR が適切に設定されている
- [ ] DNS 設定 (Private DNS Zone) が正しい
データサービス
- [ ] SQL Database: TDE / 監査設定が有効
- [ ] Cosmos DB: パーティションキー設計が適切
- [ ] Redis: TLS 1.2 以上、AAD 認証が有効
- [ ] バックアップ / リテンション設定が要件を満たす
コンピュート
- [ ] AKS: プライベートクラスター設定 (必要な場合)
- [ ] Container Apps: VNet 統合 (必要な場合)
- [ ] App Service: VNet 統合 + Private Endpoint
監視・可観測性
- [ ] Log Analytics Workspace が作成されている
- [ ] Diagnostic Settings が主要リソースに設定
- [ ] アラートルールが定義されている
セキュリティ
- [ ] Managed Identity (User-Assigned 推奨) が設定されている
- [ ] Key Vault 参照でシークレット管理
- [ ] 最低限の RBAC ロールで権限設計されている
- [ ] Microsoft Defender for Cloud の推奨事項を確認
DR・バックアップ
- [ ] Recovery Services Vault が設定 (必要な場合)
- [ ] バックアップポリシーが要件を満たす
- [ ] Geo 冗長 / ゾーン冗長の設定が適切
- [ ] Recovery Services vault / Backup Vault を作る場合、soft delete retention と削除時の運用手順(保護停止、backup data 削除、container unregister、soft-deleted instance の purge 待ち)を README または運用メモに記載している
ドキュメント
- [ ] 手順の再現性が確認できる
- [ ] 変更ログ / 履歴が追跡可能 (コミットや README の更新)
- [ ] 次のアクションまたは改善点が記載されている
- [ ] アーキテクチャ図が含まれている (推奨)
VM アプリケーションスクリプト
VM 作成時に cloud-init または CustomScriptExtension で実行するアプリケーション初期化スクリプト集。
目次
1. Squid Proxy 2. Nginx リバースプロキシ 3. Docker + Docker Compose 4. Windows IIS 5. 共通ユーティリティ
---
使用方法
cloud-init (Linux)
// Bicep で cloud-init を使用
module vm 'br/public:avm/res/compute/virtual-machine:0.21.0' = {
params: {
customData: loadFileAsBase64('scripts/vm-init/squid-init.yaml')
}
}CustomScriptExtension (Linux/Windows)
module vm 'br/public:avm/res/compute/virtual-machine:0.21.0' = {
params: {
extensionCustomScriptConfig: {
enabled: true
fileData: [
{ uri: 'https://raw.githubusercontent.com/yourrepo/scripts/setup.sh' }
]
settings: {
commandToExecute: 'bash setup.sh --param value'
}
}
}
}---
1. Squid Proxy
squid-init.yaml (cloud-init)
#cloud-config
# Squid Proxy Server 初期化スクリプト
# 用途: フォワードプロキシサーバー(閉域ネットワークからのインターネットアクセス)
package_update: true
package_upgrade: true
packages:
- squid
- apache2-utils # htpasswd 用
write_files:
# Squid 設定ファイル
- path: /etc/squid/squid.conf
content: |
# === Squid Proxy Configuration ===
# Generated by azure-env-builder
# ポート設定
http_port 3128
# ACL 定義
acl localnet src 10.0.0.0/8
acl localnet src 172.16.0.0/12
acl localnet src 192.168.0.0/16
acl SSL_ports port 443
acl Safe_ports port 80 443 8080
acl CONNECT method CONNECT
# Azure サービスエンドポイント許可
acl azure_endpoints dstdomain .azure.com
acl azure_endpoints dstdomain .microsoft.com
acl azure_endpoints dstdomain .windows.net
acl azure_endpoints dstdomain .azure-api.net
# アクセス制御
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localnet
http_access deny all
# キャッシュ設定
cache_mem 256 MB
maximum_object_size 50 MB
cache_dir ufs /var/spool/squid 1000 16 256
# ログ設定
access_log /var/log/squid/access.log squid
cache_log /var/log/squid/cache.log
# プライバシー
forwarded_for off
request_header_access Via deny all
request_header_access X-Forwarded-For deny all
# パフォーマンス
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 20% 4320
permissions: "0644"
runcmd:
# Squid 初期化
- squid -z
- systemctl enable squid
- systemctl restart squid
# ファイアウォール設定
- ufw allow 3128/tcp
- echo "Squid proxy installed and running on port 3128" > /var/log/cloud-init-complete.logsquid-setup.sh (CustomScriptExtension)
#!/bin/bash
# Squid Proxy Setup Script
# Usage: bash squid-setup.sh --allowed-networks "10.0.0.0/8,172.16.0.0/12" --proxy-port 3128
set -e
# === パラメータ解析 ===
ALLOWED_NETWORKS="10.0.0.0/8"
PROXY_PORT="3128"
while [[ "$#" -gt 0 ]]; do
case $1 in
--allowed-networks) ALLOWED_NETWORKS="$2"; shift ;;
--proxy-port) PROXY_PORT="$2"; shift ;;
*) echo "Unknown parameter: $1"; exit 1 ;;
esac
shift
done
echo "=== Installing Squid Proxy ==="
apt-get update
apt-get install -y squid
# ACL 生成
ACL_LINES=""
IFS=',' read -ra NETWORKS <<< "$ALLOWED_NETWORKS"
for network in "${NETWORKS[@]}"; do
ACL_LINES+="acl allowed_net src $network\n"
done
# 設定ファイル生成
cat > /etc/squid/squid.conf << EOF
http_port ${PROXY_PORT}
# 許可ネットワーク
$(echo -e "$ACL_LINES")
acl SSL_ports port 443
acl Safe_ports port 80 443 8080
acl CONNECT method CONNECT
# Azure サービス
acl azure dstdomain .azure.com .microsoft.com .windows.net
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow allowed_net
http_access deny all
cache_mem 256 MB
forwarded_for off
EOF
# サービス再起動
systemctl enable squid
systemctl restart squid
echo "=== Squid Proxy Ready on port ${PROXY_PORT} ==="---
2. Nginx リバースプロキシ
nginx-init.yaml (cloud-init)
#cloud-config
# Nginx Reverse Proxy + Let's Encrypt 初期化スクリプト
package_update: true
package_upgrade: true
packages:
- nginx
- certbot
- python3-certbot-nginx
write_files:
# 基本設定
- path: /etc/nginx/sites-available/reverse-proxy
content: |
# === Nginx Reverse Proxy Configuration ===
upstream backend {
# バックエンドサーバー (Bicep から動的に設定)
server 10.0.1.10:8080;
keepalive 32;
}
server {
listen 80;
server_name _;
# Let's Encrypt 認証用
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# HTTPS へリダイレクト
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name _;
# SSL 設定 (Let's Encrypt で後から更新)
ssl_certificate /etc/nginx/ssl/default.crt;
ssl_certificate_key /etc/nginx/ssl/default.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# セキュリティヘッダー
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# プロキシ設定
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
}
# ヘルスチェック
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
permissions: "0644"
runcmd:
# SSL 自己署名証明書 (初期用)
- mkdir -p /etc/nginx/ssl
- openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/default.key -out /etc/nginx/ssl/default.crt -subj "/CN=localhost"
- mkdir -p /var/www/certbot
# サイト有効化
- ln -sf /etc/nginx/sites-available/reverse-proxy /etc/nginx/sites-enabled/
- rm -f /etc/nginx/sites-enabled/default
- nginx -t
- systemctl enable nginx
- systemctl restart nginxnginx-setup.sh (CustomScriptExtension)
#!/bin/bash
# Nginx Reverse Proxy Setup
# Usage: bash nginx-setup.sh --backend "10.0.1.10:8080" --domain "example.com" --email "admin@example.com"
set -e
BACKEND="localhost:8080"
DOMAIN=""
EMAIL=""
while [[ "$#" -gt 0 ]]; do
case $1 in
--backend) BACKEND="$2"; shift ;;
--domain) DOMAIN="$2"; shift ;;
--email) EMAIL="$2"; shift ;;
*) echo "Unknown parameter: $1"; exit 1 ;;
esac
shift
done
echo "=== Installing Nginx ==="
apt-get update
apt-get install -y nginx certbot python3-certbot-nginx
# 設定ファイル生成
cat > /etc/nginx/sites-available/reverse-proxy << EOF
upstream backend {
server ${BACKEND};
keepalive 32;
}
server {
listen 80;
server_name ${DOMAIN:-_};
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
mkdir -p /var/www/certbot
ln -sf /etc/nginx/sites-available/reverse-proxy /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl enable nginx
systemctl restart nginx
# Let's Encrypt (ドメイン指定時のみ)
if [[ -n "$DOMAIN" && -n "$EMAIL" ]]; then
certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos -m "$EMAIL"
fi
echo "=== Nginx Reverse Proxy Ready ==="---
3. Docker + Docker Compose
docker-init.yaml (cloud-init)
#cloud-config
# Docker + Docker Compose 初期化スクリプト
package_update: true
package_upgrade: true
packages:
- apt-transport-https
- ca-certificates
- curl
- gnupg
- lsb-release
runcmd:
# Docker リポジトリ追加
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
- apt-get update
- apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# azureuser を docker グループに追加
- usermod -aG docker azureuser
# Docker サービス有効化
- systemctl enable docker
- systemctl start docker
# Azure CLI インストール (ACR 認証用)
- curl -sL https://aka.ms/InstallAzureCLIDeb | bash
# Docker ログイン設定 (Managed Identity)
- az login --identity
- echo "Docker installed and ready" > /var/log/cloud-init-complete.log
write_files:
# Docker daemon 設定
- path: /etc/docker/daemon.json
content: |
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2"
}
permissions: "0644"docker-compose-app.yaml (サンプル)
# サンプル Docker Compose ファイル
# /opt/app/docker-compose.yaml として配置
version: "3.8"
services:
web:
image: ${ACR_NAME}.azurecr.io/${APP_NAME}:${IMAGE_TAG:-latest}
ports:
- "8080:8080"
environment:
- DATABASE_URL=${DATABASE_URL}
- REDIS_URL=${REDIS_URL}
- APPINSIGHTS_INSTRUMENTATIONKEY=${APPINSIGHTS_KEY}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
redis:
image: redis:alpine
restart: unless-stopped
volumes:
- redis-data:/data
volumes:
redis-data:---
4. Windows IIS
iis-setup.ps1 (CustomScriptExtension)
# IIS + ASP.NET Core Hosting Bundle インストール
# Usage: powershell -ExecutionPolicy Unrestricted -File iis-setup.ps1 -DotNetVersion "8.0" -AppPoolName "MyApp"
param(
[string]$DotNetVersion = "8.0",
[string]$AppPoolName = "DefaultAppPool",
[string]$SiteName = "Default Web Site",
[string]$AppPath = "C:\inetpub\wwwroot"
)
Write-Host "=== Installing IIS and ASP.NET Core ===" -ForegroundColor Cyan
# IIS インストール
Install-WindowsFeature -Name Web-Server -IncludeManagementTools
Install-WindowsFeature -Name Web-Asp-Net45
Install-WindowsFeature -Name Web-WebSockets
# ASP.NET Core Hosting Bundle ダウンロード
$hostingBundleUrl = "https://download.visualstudio.microsoft.com/download/pr/hosting-bundle-$DotNetVersion-latest.exe"
$hostingBundlePath = "$env:TEMP\hosting-bundle.exe"
Write-Host "Downloading ASP.NET Core Hosting Bundle..." -ForegroundColor Yellow
Invoke-WebRequest -Uri $hostingBundleUrl -OutFile $hostingBundlePath
# サイレントインストール
Start-Process -FilePath $hostingBundlePath -ArgumentList "/quiet /norestart" -Wait -NoNewWindow
# IIS 再起動
net stop was /y
net start w3svc
# アプリケーションプール設定
Import-Module WebAdministration
if (-not (Test-Path "IIS:\AppPools\$AppPoolName")) {
New-WebAppPool -Name $AppPoolName
}
Set-ItemProperty "IIS:\AppPools\$AppPoolName" -Name managedRuntimeVersion -Value ""
Set-ItemProperty "IIS:\AppPools\$AppPoolName" -Name startMode -Value "AlwaysRunning"
# ファイアウォール設定
New-NetFirewallRule -DisplayName "HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
New-NetFirewallRule -DisplayName "HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
Write-Host "=== IIS Ready ===" -ForegroundColor Green---
5. 共通ユーティリティ
common-init.yaml (cloud-init ベース)
#cloud-config
# 共通初期化スクリプト (Linux)
# すべての VM に適用する基本設定
package_update: true
package_upgrade: true
packages:
- curl
- wget
- jq
- unzip
- htop
- vim
- git
# Azure CLI インストール
runcmd:
- curl -sL https://aka.ms/InstallAzureCLIDeb | bash
# Azure Monitor Agent 用の準備
- mkdir -p /var/log/azure
# タイムゾーン設定
- timedatectl set-timezone Asia/Tokyo
# スワップ設定
- fallocate -l 2G /swapfile
- chmod 600 /swapfile
- mkswap /swapfile
- swapon /swapfile
- echo '/swapfile none swap sw 0 0' >> /etc/fstab
write_files:
# 便利なエイリアス
- path: /etc/profile.d/custom-aliases.sh
content: |
alias ll='ls -la'
alias az-login='az login --identity'
alias k='kubectl'
permissions: "0644"---
Bicep での使用例
// Squid Proxy VM デプロイ
module squidVm 'br/public:avm/res/compute/virtual-machine:0.21.0' = {
name: 'squidVmDeployment'
params: {
name: 'vm-squid-${environment}'
vmSize: 'Standard_B2ms'
imageReference: {
publisher: 'Canonical'
offer: '0001-com-ubuntu-server-jammy'
sku: '22_04-lts-gen2'
version: 'latest'
}
osType: 'Linux'
nicConfigurations: [
{
ipConfigurations: [
{ subnetResourceId: proxySubnetId }
]
enableIPForwarding: true
}
]
adminUsername: 'azureuser'
disablePasswordAuthentication: true
publicKeys: [
{ path: '/home/azureuser/.ssh/authorized_keys', keyData: sshPublicKey }
]
// cloud-init で Squid 自動インストール
customData: loadFileAsBase64('../../scripts/vm-init/squid-init.yaml')
}
}
// UDR で Squid 経由にルーティング
module routeTable 'br/public:avm/res/network/route-table:0.5.0' = {
name: 'routeTableDeployment'
params: {
name: 'rt-via-squid-${environment}'
routes: [
{
name: 'to-internet-via-squid'
addressPrefix: '0.0.0.0/0'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: squidVm.outputs.privateIPAddress
}
]
}
}Related skills
FAQ
What must run before generating Bicep?
Fetch latest AVM/schema info via the required MCP tools (bicep best practices, AVM metadata, resource type schema) before generating Bicep code.
What architecture patterns does it support?
Hub-Spoke, Web+DB, AKS, AI Foundry and Proxy VM for private network egress control.