# Invoice Master - 部署指南 **版本**: v3.0 **目标平台**: Azure **运行时**: .NET 8 **日期**: 2026-02-03 --- ## 1. 架构概览 ### 1.1 多会计系统架构部署图 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ Azure Sweden Central │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ Azure Container Apps Environment │ │ │ │ │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌───────────────┐ │ │ │ │ │ Frontend App │ │ Backend API │ │ Worker │ │ │ │ │ │ (Static Web) │ │ (FastAPI) │ │ (Background) │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ Vercel/Azure │ │ CPU: 1 vCPU │ │ CPU: 0.5 │ │ │ │ │ │ Static Web │ │ Memory: 2 GiB │ │ Memory: 1GiB │ │ │ │ │ │ │ │ Replicas: 1-5 │ │ Replicas: 1-3│ │ │ │ │ └─────────────────┘ └─────────────────┘ └───────────────┘ │ │ │ │ │ │ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ │ │ Azure Application Gateway (WAF) │ │ │ │ │ │ SSL Termination │ │ │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────┐ ┌─────────────────────────────────────────┐ │ │ │ PostgreSQL Flexible │ │ Azure Cache for Redis │ │ │ │ Server │ │ │ │ │ │ - SKU: Standard_B1ms │ │ - SKU: Basic C1 │ │ │ │ - Storage: 32 GB │ │ - Memory: 1 GB │ │ │ │ - Backup: 7 days │ │ │ │ │ │ - accounting_ │ │ - Multi-provider cache │ │ │ │ connections table │ │ │ │ │ └─────────────────────────┘ └─────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ Azure Blob Storage │ │ │ │ - Tier: Hot │ │ │ │ - Redundancy: LRS │ │ │ │ - Invoice PDFs (multi-tenant) │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ Azure Key Vault │ │ │ │ - Encryption Keys │ │ │ │ - Fortnox Client Credentials │ │ │ │ - Visma Client Credentials (future) │ │ │ │ - Hogia Client Credentials (future) │ │ │ │ - Provider-specific configs │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ### 1.2 多会计系统配置 ``` ┌─────────────────────────────────────────────────────────────────┐ │ Key Vault Secrets Structure │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Global Secrets: │ │ ├── jwt-secret │ │ ├── encryption-key │ │ ├── db-password │ │ └── ocr-api-key │ │ │ │ Provider-Specific Secrets: │ │ ├── fortnox-client-id │ │ ├── fortnox-client-secret │ │ ├── fortnox-redirect-uri │ │ ├── visma-client-id (future) │ │ ├── visma-client-secret (future) │ │ └── visma-redirect-uri (future) │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 2. 前置要求 ### 2.1 工具安装 ```bash # Azure CLI curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash # Terraform wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list sudo apt update && sudo apt install terraform # kubectl (可选) az aks install-cli ``` ### 2.2 Azure 登录 ```bash # 登录 Azure az login # 设置订阅 az account set --subscription "Your Subscription Name" # 创建 Service Principal (用于 Terraform) az ad sp create-for-rbac --name "invoice-master-terraform" --role Contributor \ --scopes /subscriptions/{subscription-id} ``` --- ## 3. 基础设施部署 ### 3.1 Terraform 配置 ```bash cd infrastructure/terraform # 初始化 terraform init # 创建变量文件 cat > terraform.tfvars < ago(1h) | where OperationName contains "accounting" | summarize count(), avg(DurationMs) by Provider = tostring(CustomDimensions.provider) | order by count_ desc // 查看 Provider 错误率 AppExceptions | where TimeGenerated > ago(1h) | where ProblemId contains "fortnox" or ProblemId contains "visma" | summarize count() by Provider = tostring(CustomDimensions.provider), bin(TimeGenerated, 5m) | render timechart ``` ### 7.3 告警规则 ```bash # 创建 CPU 使用率告警 az monitor metrics alert create \ --name "High CPU Alert" \ --resource-group rg-invoice-master-prod \ --scopes $(az containerapp show --name ca-invoice-master-api --resource-group rg-invoice-master-prod --query id -o tsv) \ --condition "avg cpu percentage > 80" \ --window-size 5m \ --evaluation-frequency 1m \ --action $(az monitor action-group show --name ag-invoice-master --resource-group rg-invoice-master-prod --query id -o tsv) # 创建 Provider API 错误告警 az monitor metrics alert create \ --name "Provider API Errors" \ --resource-group rg-invoice-master-prod \ --scopes $(az monitor app-insights component show --name ai-invoice-master-prod --resource-group rg-invoice-master-prod --query id -o tsv) \ --condition "count exceptions > 10" \ --window-size 5m \ --evaluation-frequency 1m ``` --- ## 8. 备份策略 ### 8.1 数据库备份 ```bash # 配置自动备份 (已在 Terraform 中配置) # 手动备份 az postgres flexible-server backup create \ --name manual-backup-$(date +%Y%m%d) \ --server-name psql-invoice-master-prod \ --resource-group rg-invoice-master-prod # 备份 accounting_connections 表 (关键) pg_dump "host=psql-invoice-master-prod.postgres.database.azure.com user=dbadmin dbname=invoice_master sslmode=require" \ --table=accounting_connections \ --table=invoices \ --table=users > critical_tables_backup.sql ``` ### 8.2 Blob Storage 备份 ```bash # 启用版本控制 az storage account blob-service-properties update \ --account-name stinvoicemasterprod \ --enable-versioning true # 配置生命周期策略 az storage account management-policy create \ --account-name stinvoicemasterprod \ --policy @lifecycle-policy.json ``` --- ## 9. 安全加固 ### 9.1 网络安全 ```bash # 配置防火墙规则 az postgres flexible-server firewall-rule create \ --name AllowContainerApps \ --server-name psql-invoice-master-prod \ --resource-group rg-invoice-master-prod \ --start-ip-address 0.0.0.0 \ --end-ip-address 0.0.0.0 # 启用私有链接 (可选) ``` ### 9.2 Key Vault 访问策略 ```bash # 授予 Container Apps 访问 Key Vault 的权限 az keyvault set-policy \ --name kv-invoice-master-prod \ --object-id $(az containerapp show --name ca-invoice-master-api --resource-group rg-invoice-master-prod --query identity.principalId -o tsv) \ --secret-permissions get list # 为新的 Provider 添加 secrets 时,确保权限已配置 ``` ### 9.3 多租户数据隔离 ```sql -- 验证数据隔离 SELECT provider, COUNT(*) as connection_count FROM accounting_connections GROUP BY provider; -- 检查用户数据访问权限 SELECT u.email, ac.provider, ac.company_name FROM users u JOIN accounting_connections ac ON u.id = ac.user_id WHERE u.email = 'test@example.com'; ``` --- ## 10. 回滚策略 ### 10.1 应用回滚 ```bash # 回滚到上一个版本 az containerapp revision list \ --name ca-invoice-master-api \ --resource-group rg-invoice-master-prod az containerapp update \ --name ca-invoice-master-api \ --resource-group rg-invoice-master-prod \ --revision-suffix {previous-revision} ``` ### 10.2 数据库回滚 ```bash # 从备份恢复 az postgres flexible-server restore \ --name psql-invoice-master-prod-restored \ --resource-group rg-invoice-master-prod \ --source-server psql-invoice-master-prod \ --point-in-time "2026-02-03T10:00:00Z" # 回滚特定 Provider 的数据 (谨慎操作) DELETE FROM accounting_connections WHERE provider = 'fortnox'; ``` ### 10.3 Provider 配置回滚 ```bash # 如果新 Provider 配置出错,快速禁用 az containerapp update \ --name ca-invoice-master-api \ --resource-group rg-invoice-master-prod \ --set-env-vars "ENABLED_PROVIDERS=fortnox" ``` --- ## 11. CI/CD 配置 ### 11.1 GitHub Actions 工作流 ```yaml # .github/workflows/deploy.yml name: Deploy to Azure on: push: branches: [main] jobs: deploy-backend: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Azure Login uses: azure/login@v1 with: creds: ${{ secrets.AZURE_CREDENTIALS }} - name: Build and Push run: | az acr build --registry ${{ secrets.ACR_NAME }} \ --image invoice-master-api:${{ github.sha }} \ ./backend - name: Deploy run: | az containerapp update \ --name ca-invoice-master-api \ --resource-group rg-invoice-master-prod \ --image ${{ secrets.ACR_NAME }}.azurecr.io/invoice-master-api:${{ github.sha }} - name: Run Migrations run: | # 使用临时容器运行 EF Core 迁移 az containerapp job create \ --name migration-job \ --resource-group rg-invoice-master-prod \ --image ${{ secrets.ACR_NAME }}.azurecr.io/invoice-master-api:${{ github.sha }} \ --command "dotnet ef database update --no-build" ``` ### 11.2 多环境部署 ```yaml # 不同环境使用不同配置 - name: Deploy to Staging if: github.ref == 'refs/heads/develop' run: | az containerapp update \ --name ca-invoice-master-api-staging \ --resource-group rg-invoice-master-staging - name: Deploy to Production if: github.ref == 'refs/heads/main' run: | az containerapp update \ --name ca-invoice-master-api \ --resource-group rg-invoice-master-prod ``` --- ## 12. 成本估算 ### 12.1 基础资源成本 | 资源 | 每月估算 (SEK) | |------|----------------| | PostgreSQL (B1ms) | ~150 | | Redis (Basic C1) | ~100 | | Container Apps | ~200-500 | | Blob Storage | ~50-200 | | Key Vault | ~30 | | Application Insights | ~100 | | **基础总计** | **~630-1,080 SEK** | ### 12.2 多会计系统额外成本 | 项目 | 每月估算 (SEK) | 说明 | |------|----------------|------| | 额外的 API 调用 | ~0-100 | 取决于 Provider 数量 | | 额外的 Redis 缓存 | ~0-50 | Provider token 缓存 | | 额外的日志存储 | ~0-100 | 多 Provider 日志 | | **额外总计** | **~0-250 SEK** | --- ## 13. 故障排除 ### 13.1 常见问题 **问题**: Container App 无法启动 ```bash # 查看日志 az containerapp logs show \ --name ca-invoice-master-api \ --resource-group rg-invoice-master-prod \ --follow ``` **问题**: Provider 认证失败 ```bash # 检查 Key Vault secrets az keyvault secret list --vault-name kv-invoice-master-prod # 验证特定 Provider 配置 curl https://api.invoice-master.app/api/v1/accounting/providers \ -H "Authorization: Bearer $TOKEN" ``` **问题**: 数据库连接失败 ```bash # 测试连接 psql "host=psql-invoice-master-prod.postgres.database.azure.com port=5432 dbname=invoice_master user=dbadmin sslmode=require" # 检查连接表 psql $DB_URL -c "SELECT provider, COUNT(*) FROM accounting_connections GROUP BY provider;" ``` ### 13.2 Provider 特定故障排除 **Fortnox OAuth 问题**: ```bash # 检查 Fortnox 连接状态 curl https://api.invoice-master.app/api/v1/accounting/fortnox/connection \ -H "Authorization: Bearer $TOKEN" # 重新授权 # 引导用户访问: https://api.invoice-master.app/api/v1/accounting/fortnox/auth/url ``` ### 13.3 健康检查 ```bash # API 健康检查 curl https://api.invoice-master.app/health # 详细健康检查 (包含 Provider 状态) curl https://api.invoice-master.app/health/detailed \ -H "Authorization: Bearer $ADMIN_TOKEN" # 预期响应: # { # "status": "healthy", # "providers": { # "fortnox": { "status": "connected", "latency_ms": 150 }, # "visma": { "status": "not_configured" } # } # } ``` --- ## 14. 维护窗口 | 任务 | 频率 | 时间 | |------|------|------| | 安全更新 | 每周 | 周日 02:00-04:00 | | 数据库备份验证 | 每月 | 第一个周日 | | Provider API 健康检查 | 每周 | 周一 | | 性能审查 | 每季度 | - | | 证书续期检查 | 每月 | - | | Provider SDK 更新检查 | 每月 | - | --- ## 15. 扩展检查清单 ### 添加新 Provider 时的部署检查清单 - [ ] 在 Key Vault 中添加 Provider credentials - [ ] 更新 Container Apps 环境变量 - [ ] 更新 DNS/防火墙规则 (如需要) - [ ] 测试 Provider 连接 - [ ] 更新监控告警规则 - [ ] 更新文档 - [ ] 通知团队 --- ## 16. 联系信息 | 角色 | 联系方式 | |------|----------| | 技术负责人 | tech@example.com | | 运维团队 | ops@example.com | | 紧急联系 | +46-xxx-xxx-xxxx | | Provider 支持 | providers@example.com | --- **文档历史:** | 版本 | 日期 | 作者 | 变更 | |------|------|------|------| | 3.0 | 2026-02-03 | Claude Code | 重构为 .NET 8 + EF Core 部署 | | 2.0 | 2026-02-03 | Claude Code | 更新为多会计系统架构 | | 1.0 | 2026-02-03 | Claude Code | 初始版本 |