Add Azure deployment automation and documentation
- Add separate deployment pipeline (azure-pipelines-deploy.yml) for App Service deployment - Add advanced pipeline with deployment slots (azure-pipelines-slots.yml) - Restore azure-pipelines.yml to build-only (no deployment) - Add comprehensive Azure setup documentation: - AZURE-NEW-SUBSCRIPTION-SETUP.md: Complete step-by-step Azure resource setup - AZURE-RESOURCES-OVERVIEW.md: Quick reference for all Azure resources - AZURE-ACR-SHARED-SETUP.md: Guide for shared Container Registry - AZURE-ACR-NAMING-RECOMMENDATION.md: Naming recommendations for Zuyderland - AZURE-PIPELINE-DEPLOYMENT.md: Automated deployment setup guide - AZURE-PIPELINE-QUICK-REFERENCE.md: Quick reference for pipeline variables - AZURE-PIPELINES-USAGE.md: Guide for using build and deployment pipelines - Add setup script (scripts/setup-azure-resources.sh) for automated resource creation - Support for shared ACR across multiple applications
This commit is contained in:
337
docs/AZURE-PIPELINE-DEPLOYMENT.md
Normal file
337
docs/AZURE-PIPELINE-DEPLOYMENT.md
Normal file
@@ -0,0 +1,337 @@
|
||||
# Azure Pipeline Automated Deployment Guide
|
||||
|
||||
Complete guide for setting up automated deployment from Azure DevOps Pipeline to Azure App Services.
|
||||
|
||||
## 📋 Overview
|
||||
|
||||
The enhanced `azure-pipelines.yml` now includes:
|
||||
- ✅ **Build Stage**: Builds and pushes Docker images to ACR
|
||||
- ✅ **Deploy Stage**: Automatically deploys to Azure App Services
|
||||
- ✅ **Verification**: Health checks after deployment
|
||||
|
||||
## 🚀 Quick Setup
|
||||
|
||||
### Step 1: Configure Pipeline Variables
|
||||
|
||||
Update the variables in `azure-pipelines.yml`:
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
# Azure Container Registry
|
||||
acrName: 'zdlas' # Your ACR name
|
||||
repositoryName: 'cmdb-insight'
|
||||
dockerRegistryServiceConnection: 'zuyderland-cmdb-acr-connection'
|
||||
|
||||
# Azure App Service
|
||||
resourceGroup: 'rg-cmdb-insight-prod' # Your resource group
|
||||
backendAppName: 'cmdb-backend-prod' # Your backend app name
|
||||
frontendAppName: 'cmdb-frontend-prod' # Your frontend app name
|
||||
azureSubscription: 'zuyderland-cmdb-subscription' # Azure service connection
|
||||
|
||||
# Deployment
|
||||
deployToProduction: true # Set false to skip deployment
|
||||
useDeploymentSlots: false # Set true for zero-downtime deployment
|
||||
```
|
||||
|
||||
### Step 2: Create Azure Service Connection
|
||||
|
||||
You need an Azure service connection for App Service deployment:
|
||||
|
||||
1. **Go to Azure DevOps** → Your Project
|
||||
2. **Project Settings** → **Service connections** → **New service connection**
|
||||
3. Choose **Azure Resource Manager**
|
||||
4. Select:
|
||||
- **Authentication method**: Managed identity (recommended) or Service principal
|
||||
- **Azure subscription**: Your subscription
|
||||
- **Resource group**: Your resource group (optional)
|
||||
5. **Service connection name**: `zuyderland-cmdb-subscription` (match the variable name)
|
||||
6. Click **Save**
|
||||
|
||||
### Step 3: Configure Environment
|
||||
|
||||
The pipeline uses an `environment` called `production`:
|
||||
|
||||
1. **Go to Pipelines** → **Environments**
|
||||
2. Click **Create environment**
|
||||
3. Name: `production`
|
||||
4. Add **Approvals and checks** (optional):
|
||||
- **Approvals**: Require manual approval before deployment
|
||||
- **Gate**: Health checks before deployment
|
||||
|
||||
### Step 4: Run Pipeline
|
||||
|
||||
The pipeline will automatically:
|
||||
1. Build Docker images
|
||||
2. Push to ACR
|
||||
3. Deploy to App Services
|
||||
4. Verify deployment
|
||||
|
||||
**Trigger automatically on:**
|
||||
- Push to `main` branch
|
||||
- Git tags starting with `v*`
|
||||
|
||||
## 🔧 Configuration Options
|
||||
|
||||
### Enable/Disable Deployment
|
||||
|
||||
To skip deployment (only build images):
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
deployToProduction: false
|
||||
```
|
||||
|
||||
Or use pipeline variables in Azure DevOps:
|
||||
1. Go to **Pipelines** → Your pipeline → **Edit**
|
||||
2. Click **Variables**
|
||||
3. Add variable: `deployToProduction` = `false`
|
||||
|
||||
### Use Specific Image Tag
|
||||
|
||||
By default, the pipeline deploys the `latest` tag. To deploy a specific version:
|
||||
|
||||
```yaml
|
||||
# In the Deploy stage, change:
|
||||
containers: '$(acrName).azurecr.io/$(repositoryName)/backend:$(imageTag)'
|
||||
```
|
||||
|
||||
This will deploy the specific build ID instead of `latest`.
|
||||
|
||||
## 🎯 Zero-Downtime Deployment (Deployment Slots)
|
||||
|
||||
For production deployments without downtime, use deployment slots:
|
||||
|
||||
### Step 1: Create Deployment Slots
|
||||
|
||||
```bash
|
||||
# Create staging slot for backend
|
||||
az webapp deployment slot create \
|
||||
--name cmdb-backend-prod \
|
||||
--resource-group rg-cmdb-insight-prod \
|
||||
--slot staging
|
||||
|
||||
# Create staging slot for frontend
|
||||
az webapp deployment slot create \
|
||||
--name cmdb-frontend-prod \
|
||||
--resource-group rg-cmdb-insight-prod \
|
||||
--slot staging
|
||||
```
|
||||
|
||||
### Step 2: Update Pipeline for Slots
|
||||
|
||||
Create `azure-pipelines-slots.yml` (see advanced example below) or modify the existing pipeline:
|
||||
|
||||
```yaml
|
||||
- task: AzureWebAppContainer@1
|
||||
displayName: 'Deploy to Staging Slot'
|
||||
inputs:
|
||||
azureSubscription: '$(azureSubscription)'
|
||||
appName: '$(backendAppName)'
|
||||
deployToSlotOrASE: true
|
||||
resourceGroupName: '$(resourceGroup)'
|
||||
slotName: 'staging'
|
||||
containers: '$(acrName).azurecr.io/$(repositoryName)/backend:latest'
|
||||
|
||||
- task: AzureCLI@2
|
||||
displayName: 'Swap Staging to Production'
|
||||
inputs:
|
||||
azureSubscription: '$(azureSubscription)'
|
||||
scriptType: 'bash'
|
||||
scriptLocation: 'inlineScript'
|
||||
inlineScript: |
|
||||
az webapp deployment slot swap \
|
||||
--name $(backendAppName) \
|
||||
--resource-group $(resourceGroup) \
|
||||
--slot staging \
|
||||
--target-slot production
|
||||
```
|
||||
|
||||
## 📊 Pipeline Stages
|
||||
|
||||
### Stage 1: Build
|
||||
|
||||
**What it does:**
|
||||
- Builds backend Docker image
|
||||
- Builds frontend Docker image
|
||||
- Pushes both to ACR with tags: `$(Build.BuildId)` and `latest`
|
||||
|
||||
**Output:**
|
||||
- `backendImage`: Full image URL for backend
|
||||
- `frontendImage`: Full image URL for frontend
|
||||
|
||||
### Stage 2: Deploy
|
||||
|
||||
**What it does:**
|
||||
- Deploys backend container to App Service
|
||||
- Deploys frontend container to App Service
|
||||
- Restarts both App Services
|
||||
- Verifies deployment with health checks
|
||||
|
||||
**Conditions:**
|
||||
- Only runs if `deployToProduction = true`
|
||||
- Only runs if Build stage succeeded
|
||||
|
||||
### Stage 3: Verify
|
||||
|
||||
**What it does:**
|
||||
- Checks backend health endpoint (`/api/health`)
|
||||
- Checks frontend accessibility
|
||||
- Reports status
|
||||
|
||||
## 🔐 Permissions Required
|
||||
|
||||
The Azure service connection needs:
|
||||
|
||||
1. **App Service Contributor** role on:
|
||||
- Backend App Service
|
||||
- Frontend App Service
|
||||
- App Service Plan
|
||||
|
||||
2. **ACR Pull** permissions (if using Managed Identity):
|
||||
- Already configured via Managed Identity on App Services
|
||||
|
||||
### Grant Permissions
|
||||
|
||||
```bash
|
||||
# Get service principal ID from Azure DevOps service connection
|
||||
# Then grant permissions:
|
||||
|
||||
az role assignment create \
|
||||
--assignee <service-principal-id> \
|
||||
--role "Website Contributor" \
|
||||
--scope /subscriptions/<subscription-id>/resourceGroups/rg-cmdb-insight-prod
|
||||
```
|
||||
|
||||
## 🛠️ Troubleshooting
|
||||
|
||||
### Deployment Fails: "Service connection not found"
|
||||
|
||||
**Solution:**
|
||||
- Verify service connection name matches `azureSubscription` variable
|
||||
- Check service connection exists in Project Settings → Service connections
|
||||
- Verify service connection has correct permissions
|
||||
|
||||
### Deployment Fails: "App Service not found"
|
||||
|
||||
**Solution:**
|
||||
- Verify `backendAppName` and `frontendAppName` variables are correct
|
||||
- Check `resourceGroup` variable matches your resource group
|
||||
- Verify App Services exist in Azure
|
||||
|
||||
### Images Not Updating
|
||||
|
||||
**Solution:**
|
||||
- Check if images were pushed to ACR successfully
|
||||
- Verify App Service is pulling from correct ACR
|
||||
- Check container settings in App Service configuration
|
||||
- Ensure Managed Identity has ACR pull permissions
|
||||
|
||||
### Health Check Fails
|
||||
|
||||
**Solution:**
|
||||
- Wait longer (apps may need time to start)
|
||||
- Check App Service logs: `az webapp log tail`
|
||||
- Verify health endpoint exists: `/api/health`
|
||||
- Check environment variables are configured correctly
|
||||
|
||||
## 📝 Manual Deployment (Alternative)
|
||||
|
||||
If you prefer manual deployment after pipeline builds:
|
||||
|
||||
```bash
|
||||
# After pipeline builds images, manually deploy:
|
||||
|
||||
# Restart backend to pull latest image
|
||||
az webapp restart \
|
||||
--name cmdb-backend-prod \
|
||||
--resource-group rg-cmdb-insight-prod
|
||||
|
||||
# Restart frontend to pull latest image
|
||||
az webapp restart \
|
||||
--name cmdb-frontend-prod \
|
||||
--resource-group rg-cmdb-insight-prod
|
||||
```
|
||||
|
||||
## 🎯 Best Practices
|
||||
|
||||
### 1. Use Deployment Slots for Production
|
||||
|
||||
- Deploy to staging slot first
|
||||
- Test in staging
|
||||
- Swap to production when ready
|
||||
|
||||
### 2. Use Specific Tags for Production
|
||||
|
||||
Instead of `latest`, use version tags:
|
||||
```yaml
|
||||
containers: '$(acrName).azurecr.io/$(repositoryName)/backend:v1.0.0'
|
||||
```
|
||||
|
||||
### 3. Add Approvals for Production
|
||||
|
||||
Configure environment approvals:
|
||||
- Go to **Pipelines** → **Environments** → **production**
|
||||
- Add **Approvals** check
|
||||
- Require manual approval before deployment
|
||||
|
||||
### 4. Monitor Deployments
|
||||
|
||||
- Set up alerts in Application Insights
|
||||
- Monitor pipeline runs
|
||||
- Check deployment logs regularly
|
||||
|
||||
### 5. Rollback Strategy
|
||||
|
||||
If deployment fails:
|
||||
```bash
|
||||
# Rollback to previous image
|
||||
az webapp config container set \
|
||||
--name cmdb-backend-prod \
|
||||
--resource-group rg-cmdb-insight-prod \
|
||||
--docker-custom-image-name <previous-image-tag>
|
||||
```
|
||||
|
||||
## 🔄 Workflow Example
|
||||
|
||||
### Typical Development Workflow
|
||||
|
||||
1. **Developer pushes code** to `main` branch
|
||||
2. **Pipeline triggers automatically**
|
||||
3. **Build stage**: Builds and pushes images
|
||||
4. **Deploy stage**: Deploys to App Services
|
||||
5. **Verify stage**: Checks health
|
||||
6. **Application updated** - ready to use!
|
||||
|
||||
### Release Workflow
|
||||
|
||||
1. **Create release tag**: `git tag v1.0.0 && git push origin v1.0.0`
|
||||
2. **Pipeline triggers** with tag
|
||||
3. **Build stage**: Builds versioned images (`v1.0.0`)
|
||||
4. **Deploy stage**: Deploys to staging slot
|
||||
5. **Manual approval** (if configured)
|
||||
6. **Swap to production**: Zero-downtime deployment
|
||||
7. **Verify**: Health checks confirm success
|
||||
|
||||
## 📚 Related Documentation
|
||||
|
||||
- **`AZURE-NEW-SUBSCRIPTION-SETUP.md`** - Initial Azure setup
|
||||
- **`AZURE-APP-SERVICE-DEPLOYMENT.md`** - Manual deployment guide
|
||||
- **`AZURE-CONTAINER-REGISTRY.md`** - ACR setup
|
||||
- **`AZURE-DEVOPS-SETUP.md`** - Pipeline setup basics
|
||||
|
||||
## ✅ Checklist
|
||||
|
||||
- [ ] Azure service connection created
|
||||
- [ ] Pipeline variables configured
|
||||
- [ ] Environment `production` created
|
||||
- [ ] App Services exist in Azure
|
||||
- [ ] Permissions configured
|
||||
- [ ] Pipeline tested successfully
|
||||
- [ ] Deployment verified
|
||||
- [ ] Health checks passing
|
||||
|
||||
---
|
||||
|
||||
**🎉 Your automated deployment pipeline is ready!**
|
||||
|
||||
Every push to `main` will now automatically build and deploy your application.
|
||||
Reference in New Issue
Block a user