文章目录
- 项目地址
- [一、Azure Boards](#一、Azure Boards)
-
- [1.1 Scrum 结构](#1.1 Scrum 结构)
-
- [1. 创建Epic](#1. 创建Epic)
- [2. 创建features](#2. 创建features)
- [3. 添加items](#3. 添加items)
- [4. 总结](#4. 总结)
- 二、Pipeline
-
- [2.1 流程](#2.1 流程)
-
- [1. Feature分支开发](#1. Feature分支开发)
- [2. PR合并到dev分支](#2. PR合并到dev分支)
- [3. CI/CD 部署到 Dev 环境(自动)](#3. CI/CD 部署到 Dev 环境(自动))
- [4. 发布准备](#4. 发布准备)
- [5. 提交生产版本(合并到 main 并打 Tag)](#5. 提交生产版本(合并到 main 并打 Tag))
- [6. 部署到生产环境(CD)](#6. 部署到生产环境(CD))
- [7. 总结](#7. 总结)
- [2.2 一个完整的aks部署](#2.2 一个完整的aks部署)
- 三、APIM
项目地址
- 教程作者:
- 教程地址:
- 代码仓库地址:
-
所用到的框架和插件:
dbt
airflow
一、Azure Boards
1.1 Scrum 结构

1. 创建Epic
- Epic是核心业务模块名称,例如,用户管理,商品和类目管理,支付系统,后台管理,消息和通知服务
2. 创建features
-
添加feauture,需要关联Epic,feature主要是Epic下的功能,例如,在Epic是用户管理模块下,feature是 用户注册和登录,身份和权限认证,用户资料管理,用户角色管理
Epic: 用户与账户管理
├── Feature: 用户注册与登录
├── Feature: 用户资料管理
├── Feature: 地址管理
├── Feature: 权限与角色管理
├── Feature: 通知偏好设置
├── Feature: 第三方登录(可选)
├── Feature: 登录日志与安全审计
└── Feature: 实名认证(可选)

3. 添加items
- 添加一个feature下的items,这里举例feature是用户注册和登录功能
- 添加最小的item这里是
创建用户注册的api功能
,并且将该item连接到他的父类Feature下

- 创建一个tasks, 在上面的页面下,添加新的links,为Child,例如创建用户注册api需要的table,需要的controller等

- 创建多个tasks在一个item下

4. 总结
以上的任务一般是Devops团队或者Leader用来创建,作为开发只需要关注,Work Items下分配给自己的任务

二、Pipeline
2.1 流程
[Feature 分支开发]
↓
[Pull Request ➜ develop 分支]
↓ (自动 CI: 构建 + 单测 + 静态分析)
[合并 develop ➜ Dev 环境自动部署]
↓
[功能验收后 ➜ 创建 release 分支]
↓ (CI: 全流程 + 安全扫描 + E2E测试)
[合并 release ➜ main + tag ➜ 触发生产部署]
↓
[生产环境部署 + 审批 + 蓝绿发布 + 监控]
1. Feature分支开发
- 从dev分支拉去代码到本地
- 进行本地开发和测试
- 完成后提交代码远程feature分支
2. PR合并到dev分支
- 创建pull request
- Review 通过后合并
- 自动触发CI:
①恢复依赖(dotnet restore/npm install)
②编译环境(dotnet build/npm run build)
③单元测试
④SonarQube 分析
3. CI/CD 部署到 Dev 环境(自动)
- YAML pipeline 检测到 develop 分支更新,自动触发
①构建发布包
②可选 Docker 镜像构建并推送 ACR
③部署至 Azure Dev 环境(App Service 或 AKS Dev 命名空间)
④环境变量通过 Azure Key Vault 注入
4. 发布准备
- 功能开发完成后,从 develop 创建 release 分支
- 触发完整 CI 流程:
①单元测试
②静态分析(Sonar)
③安全漏洞扫描(Snyk, CodeQL)
④集成测试
⑤E2E 自动化测试(Playwright / Selenium)
5. 提交生产版本(合并到 main 并打 Tag)
- 触发 main 分支生产部署流程
- CI 构建发布包 → 存入 Artifact
- 自动或手动部署 Production
- 启用审批流程(部署前审核)
支持:
蓝绿部署(App Service deployment slots)
滚动更新(AKS)
6. 部署到生产环境(CD)
- 审批通过后,部署至生产环境:
- 环境名称:Production
- 审批人:Tech Lead / PM
步骤:
恢复变量
应用 Key Vault 中的连接字符串等密钥
部署
可回滚上一个构建版本(Azure Pipelines 支持)
7. 总结
类型 | 工具 | 用途 |
---|---|---|
CI | Azure Pipelines / GitHub Actions | 编译、测试、发布 Artifact |
CD | Azure Release / multi-stage YAML | 多环境部署 |
静态分析 | SonarQube | C# / JS 代码规范和复杂度分析 |
安全扫描 | Snyk / CodeQL | 检测依赖和代码漏洞 |
Secret 管理 | Azure Key Vault | 安全存储数据库连接字符串等 |
基础设施 IaC | Terraform / Bicep | 管理 Redis、Cosmos、App Service |
测试 | MSTest / xUnit / Playwright | 单测、集成测试、E2E |
审批 | Azure DevOps Environments | 生产前手动批准发布 |
2.2 一个完整的aks部署
-
部署product服务到aks
trigger:
branches:
include:
- dev
- qa
- uat
- staging
- prodresources:
- repo: self
variables:
- name: dockerRegistryServiceConnection
value: '525b95a9-e717-4679-b26e-222b52619223'
- name: imageRepository
value: 'products-microservice'
- name: containerRegistry
value: 'harshaecommerceregistry.azurecr.io'
- name: dockerfilePath
value: '(Build.SourcesDirectory)/ProductsMicroService.API/Dockerfile' - name: tag value: '(Build.BuildId)'
- name: linuxImageName
value: 'ubuntu-latest'
- name: windowsImageName
value: 'windows-latest'
- name: imageRepository
value: products-microservice
- name: aksClusterName
value: 'ecommerce-aks-cluster'
- name: devAksServiceConnectionName
value: 'dev-ecommerce-aks-cluster-dev-1728475525366'
- name: qaAksServiceConnectionName
value: 'qa-ecommerce-aks-cluster-qa-1728475742545'
- name: uatAksServiceConnectionName
value: 'uat-ecommerce-aks-cluster-uat-1728475843682'
- name: stagingAksServiceConnectionName
value: 'staging-ecommerce-aks-cluster-staging-1728475932481'
- name: prodAksServiceConnectionName
value: 'prod-ecommerce-aks-cluster-prod-1728475982025'
- name: devKubernetesNamespace
value: 'dev'
- name: qaKubernetesNamespace
value: 'qa'
- name: uatKubernetesNamespace
value: 'uat'
- name: stagingKubernetesNamespace
value: 'staging'
- name: prodKubernetesNamespace
value: 'prod'stages:
-
stage: Build
displayName: Build and push stage
jobs:- job: Build
displayName: Docker Build
pool:
vmImage: $(linuxImageName)
steps:- task: Docker@2
displayName: Build and push an image to container registry
inputs:
command: buildAndPush
repository: (imageRepository) dockerfile: (dockerfilePath)
containerRegistry: (dockerRegistryServiceConnection) tags: | (tag)
buildContext: $(Build.SourcesDirectory)
- task: Docker@2
- job: Build
-
stage: Test
displayName: Test and publish results stage
jobs:- job: RunTest
displayName: Run Unit tests
pool:
vmImage: $(windowsImageName)
steps:-
checkout: self
displayName: Checkout source code -
task: NuGetToolInstaller@1
displayName: Install NuGetTool -
task: NuGetCommand@2
displayName: Restore NuGet Packages
inputs:
command: 'restore'
restoreSolution: '**/*.sln' -
task: MSBuild@1
displayName: Build solution
inputs:
solution: '**/*.sln'
msbuildArchitecture: 'x64'
platform: 'Any CPU'
configuration: 'Debug' -
task: VSTest@3
displayName: Test solution
inputs:
testSelector: 'testAssemblies'
testAssemblyVer2: |
\ProductsUnitTests.dll
!*TestAdapter.dll
!**\obj**
searchFolder: '$(System.DefaultWorkingDirectory)'
runTestsInIsolation: true
codeCoverageEnabled: true
-
- job: RunTest
-
stage: DeployToDev
displayName: Deploy to Dev
dependsOn: Test
condition: and(succeeded('Build'), eq(variables['Build.SourceBranch'], 'refs/heads/dev'))jobs:
-
deployment: DeploymentToDev
displayName: Deployment to Dev Environment
environment: dev
strategy:
runOnce:
deploy:
steps:
- checkout: self
displayName: Checkout source code- script: | echo "Listing contents of k8s" ls -l $(Build.SourcesDirectory)/k8s/dev displayName: 'List Files in k8s/dev Directory' - script: | find $(Build.SourcesDirectory)/k8s/dev -type f \( -name "*.yaml" -o -name "*.yml" \) -exec sed -i 's/__TAG__/$(tag)/g' {} + displayName: 'Replace image tag in all deployment files' - task: Kubernetes@1 displayName: Deploy to dev namespace in kubernetes inputs: kubernetesServiceEndpoint: $(devAksServiceConnectionName) kubernetesCluster: $(aksClusterName) namespace: $(devKubernetesNamespace) command: apply arguments: '-f $(Build.SourcesDirectory)/k8s/dev/.'
-
-
stage: DeployToQA
displayName: Deploy to QA
dependsOn: Test
condition: and(succeeded('Build'), eq(variables['Build.SourceBranch'], 'refs/heads/qa'))jobs:
-
deployment: DeploymentToQA
displayName: Deployment to QA Environment
environment: qa
strategy:
runOnce:
deploy:
steps:
- checkout: self
displayName: Checkout source code- script: | echo "Listing contents of k8s" ls -l $(Build.SourcesDirectory)/k8s/qa displayName: 'List Files in k8s/qa Directory' - script: | find $(Build.SourcesDirectory)/k8s/qa -type f \( -name "*.yaml" -o -name "*.yml" \) -exec sed -i 's/__TAG__/$(tag)/g' {} + displayName: 'Replace image tag in all deployment files' - task: Kubernetes@1 displayName: Deploy to qa namespace in kubernetes inputs: kubernetesServiceEndpoint: $(qaAksServiceConnectionName) kubernetesCluster: $(aksClusterName) namespace: $(qaKubernetesNamespace) command: apply arguments: '-f $(Build.SourcesDirectory)/k8s/qa/.'
-
-
stage: DeployToUAT
displayName: Deploy to UAT
dependsOn: Test
condition: and(succeeded('Build'), eq(variables['Build.SourceBranch'], 'refs/heads/uat'))jobs:
-
deployment: DeploymentToUAT
displayName: Deployment to UAT Environment
environment: uat
strategy:
runOnce:
deploy:
steps:
- checkout: self
displayName: Checkout source code- script: | echo "Listing contents of k8s" ls -l $(Build.SourcesDirectory)/k8s/uat displayName: 'List Files in k8s/uat Directory' - script: | find $(Build.SourcesDirectory)/k8s/uat -type f \( -name "*.yaml" -o -name "*.yml" \) -exec sed -i 's/__TAG__/$(tag)/g' {} + displayName: 'Replace image tag in all deployment files' - task: Kubernetes@1 displayName: Deploy to uat namespace in kubernetes inputs: kubernetesServiceEndpoint: $(uatAksServiceConnectionName) kubernetesCluster: $(aksClusterName) namespace: $(uatKubernetesNamespace) command: apply arguments: '-f $(Build.SourcesDirectory)/k8s/uat/.'
-
-
stage: DeployToStaging
displayName: Deploy to Staging
dependsOn: Test
condition: and(succeeded('Build'), eq(variables['Build.SourceBranch'], 'refs/heads/staging'))jobs:
-
deployment: DeploymentToStaging
displayName: Deployment to Staging Environment
environment: staging
strategy:
runOnce:
deploy:
steps:
- checkout: self
displayName: Checkout source code- script: | echo "Listing contents of k8s" ls -l $(Build.SourcesDirectory)/k8s/staging displayName: 'List Files in k8s/staging Directory' - script: | find $(Build.SourcesDirectory)/k8s/staging -type f \( -name "*.yaml" -o -name "*.yml" \) -exec sed -i 's/__TAG__/$(tag)/g' {} + displayName: 'Replace image tag in all deployment files' - task: Kubernetes@1 displayName: Deploy to staging namespace in kubernetes inputs: kubernetesServiceEndpoint: $(stagingAksServiceConnectionName) kubernetesCluster: $(aksClusterName) namespace: $(stagingKubernetesNamespace) command: apply arguments: '-f $(Build.SourcesDirectory)/k8s/staging/.'
-
-
stage: DeployToProduction
displayName: Deploy to Production
dependsOn: Test
condition: and(succeeded('Build'), eq(variables['Build.SourceBranch'], 'refs/heads/prod'))jobs:
-
deployment: DeploymentToProduction
displayName: Deployment to Production Environment
environment: prod
strategy:
runOnce:
deploy:
steps:
- checkout: self
displayName: Checkout source code- script: | echo "Listing contents of k8s" ls -l $(Build.SourcesDirectory)/k8s/prod displayName: 'List Files in k8s/prod Directory' - script: | find $(Build.SourcesDirectory)/k8s/prod -type f \( -name "*.yaml" -o -name "*.yml" \) -exec sed -i 's/__TAG__/$(tag)/g' {} + displayName: 'Replace image tag in all deployment files' - task: Kubernetes@1 displayName: Deploy to prod namespace in kubernetes inputs: kubernetesServiceEndpoint: $(prodAksServiceConnectionName) kubernetesCluster: $(aksClusterName) namespace: $(prodKubernetesNamespace) command: apply arguments: '-f $(Build.SourcesDirectory)/k8s/prod/.'
-
三、APIM
- Azure Api Management是外部的API Gateway
- 程序内部的API Gateway