- 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
338 lines
9.0 KiB
Markdown
338 lines
9.0 KiB
Markdown
# 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.
|