deployment-documentation
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDeployment Documentation
部署文档
Overview
概述
Create comprehensive deployment documentation covering infrastructure setup, CI/CD pipelines, deployment procedures, and rollback strategies.
创建涵盖基础设施搭建、CI/CD流水线、部署流程以及回滚策略的全面部署文档。
When to Use
适用场景
- Deployment guides
- Infrastructure documentation
- CI/CD pipeline setup
- Configuration management
- Container orchestration
- Cloud infrastructure docs
- Release procedures
- Rollback procedures
- 部署指南
- 基础设施文档
- CI/CD流水线搭建
- 配置管理
- 容器编排
- 云基础设施文档
- 发布流程
- 回滚流程
Deployment Guide Template
部署指南模板
markdown
undefinedmarkdown
undefinedDeployment Guide
部署指南
Overview
概述
This document describes the deployment process for [Application Name].
Deployment Methods:
- Manual deployment (emergency only)
- Automated CI/CD (preferred)
- Blue-green deployment
- Canary deployment
Environments:
- Development: https://dev.example.com
- Staging: https://staging.example.com
- Production: https://example.com
本文档描述了[应用名称]的部署流程。
部署方式:
- 手动部署(仅用于紧急情况)
- 自动化CI/CD(推荐方式)
- 蓝绿部署
- 金丝雀部署
环境:
- 开发环境:https://dev.example.com
- 预发布环境:https://staging.example.com
- 生产环境:https://example.com
Prerequisites
前置条件
Required Tools
所需工具
bash
undefinedbash
undefinedInstall required tools
安装所需工具
brew install node@18
brew install postgresql@14
brew install redis
brew install docker
brew install kubectl
brew install helm
brew install aws-cli
undefinedbrew install node@18
brew install postgresql@14
brew install redis
brew install docker
brew install kubectl
brew install helm
brew install aws-cli
undefinedAccess Requirements
访问权限要求
- GitHub repository access
- AWS console access (IAM user with deployment policy)
- Kubernetes cluster access (kubeconfig)
- Docker Hub credentials
- Datadog API key (monitoring)
- PagerDuty access (on-call)
- GitHub仓库访问权限
- AWS控制台访问权限(带有部署策略的IAM用户)
- Kubernetes集群访问权限(kubeconfig)
- Docker Hub凭证
- Datadog API密钥(监控)
- PagerDuty访问权限(值班)
Environment Variables
环境变量
bash
undefinedbash
undefined.env.production
.env.production
NODE_ENV=production
DATABASE_URL=postgresql://user:pass@db.example.com:5432/prod
REDIS_URL=redis://cache.example.com:6379
API_KEY=your-api-key
JWT_SECRET=your-jwt-secret
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=...
---NODE_ENV=production
DATABASE_URL=postgresql://user:pass@db.example.com:5432/prod
REDIS_URL=redis://cache.example.com:6379
API_KEY=your-api-key
JWT_SECRET=your-jwt-secret
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=...
---CI/CD Pipeline
CI/CD流水线
GitHub Actions Workflow
GitHub Actions工作流
yaml
undefinedyaml
undefined.github/workflows/deploy.yml
.github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [main]
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm test
- run: npm run lint
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v1
- name: Build and push Docker image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/app:$IMAGE_TAG .
docker push $ECR_REGISTRY/app:$IMAGE_TAG
docker tag $ECR_REGISTRY/app:$IMAGE_TAG $ECR_REGISTRY/app:latest
docker push $ECR_REGISTRY/app:latestdeploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configure kubectl
uses: azure/k8s-set-context@v3
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Deploy to Kubernetes
env:
IMAGE_TAG: ${{ github.sha }}
run: |
kubectl set image deployment/app \
app=your-registry/app:$IMAGE_TAG \
-n production
kubectl rollout status deployment/app -n production
- name: Notify Datadog
run: |
curl -X POST "https://api.datadoghq.com/api/v1/events" \
-H "DD-API-KEY: ${{ secrets.DATADOG_API_KEY }}" \
-d '{
"title": "Deployment to Production",
"text": "Deployed version ${{ github.sha }}",
"tags": ["environment:production", "service:app"]
}'
- name: Notify Slack
if: always()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Deployment ${{ job.status }}: ${{ github.sha }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
---name: Deploy to Production
on:
push:
branches: [main]
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm test
- run: npm run lint
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v1
- name: Build and push Docker image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/app:$IMAGE_TAG .
docker push $ECR_REGISTRY/app:$IMAGE_TAG
docker tag $ECR_REGISTRY/app:$IMAGE_TAG $ECR_REGISTRY/app:latest
docker push $ECR_REGISTRY/app:latestdeploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configure kubectl
uses: azure/k8s-set-context@v3
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Deploy to Kubernetes
env:
IMAGE_TAG: ${{ github.sha }}
run: |
kubectl set image deployment/app \
app=your-registry/app:$IMAGE_TAG \
-n production
kubectl rollout status deployment/app -n production
- name: Notify Datadog
run: |
curl -X POST "https://api.datadoghq.com/api/v1/events" \
-H "DD-API-KEY: ${{ secrets.DATADOG_API_KEY }}" \
-d '{
"title": "Deployment to Production",
"text": "Deployed version ${{ github.sha }}",
"tags": ["environment:production", "service:app"]
}'
- name: Notify Slack
if: always()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Deployment ${{ job.status }}: ${{ github.sha }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
---Docker Configuration
Docker配置
Dockerfile
Dockerfile
dockerfile
undefineddockerfile
undefinedMulti-stage build for optimization
Multi-stage build for optimization
FROM node:18-alpine AS builder
WORKDIR /app
FROM node:18-alpine AS builder
WORKDIR /app
Copy package files
Copy package files
COPY package*.json ./
COPY package*.json ./
Install dependencies
Install dependencies
RUN npm ci --only=production
RUN npm ci --only=production
Copy source code
Copy source code
COPY . .
COPY . .
Build application
Build application
RUN npm run build
RUN npm run build
Production stage
Production stage
FROM node:18-alpine
FROM node:18-alpine
Security: Run as non-root user
Security: Run as non-root user
RUN addgroup -g 1001 -S nodejs &&
adduser -S nodejs -u 1001
adduser -S nodejs -u 1001
WORKDIR /app
RUN addgroup -g 1001 -S nodejs &&
adduser -S nodejs -u 1001
adduser -S nodejs -u 1001
WORKDIR /app
Copy built application from builder
Copy built application from builder
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/package*.json ./
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/package*.json ./
Switch to non-root user
Switch to non-root user
USER nodejs
USER nodejs
Expose port
Expose port
EXPOSE 3000
EXPOSE 3000
Health check
Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD node healthcheck.js
CMD node healthcheck.js
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD node healthcheck.js
CMD node healthcheck.js
Start application
Start application
CMD ["node", "dist/server.js"]
undefinedCMD ["node", "dist/server.js"]
undefineddocker-compose.yml
docker-compose.yml
yaml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:password@db:5432/app
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
restart: unless-stopped
healthcheck:
test: ["CMD", "node", "healthcheck.js"]
interval: 30s
timeout: 3s
retries: 3
db:
image: postgres:14-alpine
environment:
- POSTGRES_DB=app
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
restart: unless-stopped
volumes:
postgres_data:
redis_data:yaml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:password@db:5432/app
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
restart: unless-stopped
healthcheck:
test: ["CMD", "node", "healthcheck.js"]
interval: 30s
timeout: 3s
retries: 3
db:
image: postgres:14-alpine
environment:
- POSTGRES_DB=app
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
restart: unless-stopped
volumes:
postgres_data:
redis_data:Kubernetes Deployment
Kubernetes部署
Deployment Manifest
部署清单
yaml
undefinedyaml
undefinedk8s/deployment.yaml
k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: production
labels:
app: app
version: v1
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
version: v1
spec:
containers:
- name: app
image: your-registry/app:latest
imagePullPolicy: Always
ports:
- containerPort: 3000
name: http
env:
- name: NODE_ENV
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: redis-url
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
apiVersion: v1
kind: Service
metadata:
name: app
namespace: production
spec:
selector:
app: app
ports:
- port: 80 targetPort: 3000 type: ClusterIP
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app
namespace: production
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- example.com secretName: app-tls rules:
- host: example.com
http:
paths:
- path: / pathType: Prefix backend: service: name: app port: number: 80
---apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: production
labels:
app: app
version: v1
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
version: v1
spec:
containers:
- name: app
image: your-registry/app:latest
imagePullPolicy: Always
ports:
- containerPort: 3000
name: http
env:
- name: NODE_ENV
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: redis-url
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
apiVersion: v1
kind: Service
metadata:
name: app
namespace: production
spec:
selector:
app: app
ports:
- port: 80 targetPort: 3000 type: ClusterIP
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app
namespace: production
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- example.com secretName: app-tls rules:
- host: example.com
http:
paths:
- path: / pathType: Prefix backend: service: name: app port: number: 80
---Deployment Procedures
部署流程
1. Pre-Deployment Checklist
1. 部署前检查清单
- All tests passing
- Code review approved
- Security scan passed
- Database migrations ready
- Rollback plan documented
- Monitoring dashboard ready
- Team notified
- Maintenance window scheduled (if needed)
- 所有测试通过
- 代码评审已批准
- 安全扫描通过
- 数据库迁移已准备好
- 回滚计划已记录
- 监控仪表板已就绪
- 团队已收到通知
- 维护窗口已安排(如有需要)
2. Deployment Steps
2. 部署步骤
bash
undefinedbash
undefined1. Tag release
1. 标记版本
git tag -a v1.2.3 -m "Release v1.2.3"
git push origin v1.2.3
git tag -a v1.2.3 -m "Release v1.2.3"
git push origin v1.2.3
2. Build Docker image
2. 构建Docker镜像
docker build -t your-registry/app:v1.2.3 .
docker tag your-registry/app:v1.2.3 your-registry/app:latest
docker push your-registry/app:v1.2.3
docker push your-registry/app:latest
docker build -t your-registry/app:v1.2.3 .
docker tag your-registry/app:v1.2.3 your-registry/app:latest
docker push your-registry/app:v1.2.3
docker push your-registry/app:latest
3. Run database migrations
3. 运行数据库迁移
kubectl exec -it deployment/app -n production -- npm run db:migrate
kubectl exec -it deployment/app -n production -- npm run db:migrate
4. Deploy to Kubernetes
4. 部署到Kubernetes
kubectl apply -f k8s/
kubectl set image deployment/app app=your-registry/app:v1.2.3 -n production
kubectl apply -f k8s/
kubectl set image deployment/app app=your-registry/app:v1.2.3 -n production
5. Wait for rollout
5. 等待部署完成
kubectl rollout status deployment/app -n production
kubectl rollout status deployment/app -n production
6. Verify deployment
6. 验证部署
kubectl get pods -n production
kubectl logs -f deployment/app -n production
kubectl get pods -n production
kubectl logs -f deployment/app -n production
7. Smoke test
7. 冒烟测试
undefinedundefined3. Post-Deployment Verification
3. 部署后验证
bash
undefinedbash
undefinedCheck pod status
检查Pod状态
kubectl get pods -n production -l app=app
kubectl get pods -n production -l app=app
Check logs for errors
检查日志是否有错误
kubectl logs -f deployment/app -n production --tail=100
kubectl logs -f deployment/app -n production --tail=100
Check metrics
检查指标
Run smoke tests
运行冒烟测试
npm run test:smoke:production
npm run test:smoke:production
Verify in monitoring
在监控系统中验证
- Check Datadog dashboard
- 查看Datadog仪表板
- Check error rates
- 检查错误率
- Check response times
- 检查响应时间
- Check resource usage
- 检查资源使用情况
---
---Rollback Procedures
回滚流程
Automatic Rollback
自动回滚
bash
undefinedbash
undefinedRollback to previous version
回滚到上一个版本
kubectl rollout undo deployment/app -n production
kubectl rollout undo deployment/app -n production
Rollback to specific revision
回滚到指定版本
kubectl rollout undo deployment/app -n production --to-revision=2
kubectl rollout undo deployment/app -n production --to-revision=2
Check rollback status
检查回滚状态
kubectl rollout status deployment/app -n production
undefinedkubectl rollout status deployment/app -n production
undefinedManual Rollback
手动回滚
bash
undefinedbash
undefined1. Identify last working version
1. 确定最后可用版本
kubectl rollout history deployment/app -n production
kubectl rollout history deployment/app -n production
2. Deploy previous version
2. 部署上一个版本
kubectl set image deployment/app
app=your-registry/app:v1.2.2
-n production
app=your-registry/app:v1.2.2
-n production
kubectl set image deployment/app
app=your-registry/app:v1.2.2
-n production
app=your-registry/app:v1.2.2
-n production
3. Rollback database migrations (if needed)
3. 回滚数据库迁移(如有需要)
kubectl exec -it deployment/app -n production --
npm run db:migrate:undo
npm run db:migrate:undo
kubectl exec -it deployment/app -n production --
npm run db:migrate:undo
npm run db:migrate:undo
4. Verify rollback
4. 验证回滚
kubectl get pods -n production
curl https://example.com/health
---kubectl get pods -n production
curl https://example.com/health
---Blue-Green Deployment
蓝绿部署
bash
undefinedbash
undefined1. Deploy green environment
1. 部署绿色环境
kubectl apply -f k8s/deployment-green.yaml
kubectl apply -f k8s/deployment-green.yaml
2. Wait for green to be ready
2. 等待绿色环境就绪
kubectl rollout status deployment/app-green -n production
kubectl rollout status deployment/app-green -n production
3. Test green environment
3. 测试绿色环境
4. Switch traffic to green
4. 将流量切换到绿色环境
kubectl patch service app -n production
-p '{"spec":{"selector":{"version":"green"}}}'
-p '{"spec":{"selector":{"version":"green"}}}'
kubectl patch service app -n production
-p '{"spec":{"selector":{"version":"green"}}}'
-p '{"spec":{"selector":{"version":"green"}}}'
5. Monitor for issues
5. 监控是否有问题
If issues: Switch back to blue
若出现问题:切换回蓝色环境
kubectl patch service app -n production
-p '{"spec":{"selector":{"version":"blue"}}}'
-p '{"spec":{"selector":{"version":"blue"}}}'
kubectl patch service app -n production
-p '{"spec":{"selector":{"version":"blue"}}}'
-p '{"spec":{"selector":{"version":"blue"}}}'
6. If successful: Remove blue deployment
6. 若部署成功:删除蓝色环境部署
kubectl delete deployment app-blue -n production
---kubectl delete deployment app-blue -n production
---Monitoring & Alerting
监控与告警
Health Check Endpoints
健康检查端点
javascript
// healthcheck.js
const http = require('http');
const options = {
host: 'localhost',
port: 3000,
path: '/health',
timeout: 2000
};
const healthCheck = http.request(options, (res) => {
if (res.statusCode === 200) {
process.exit(0);
} else {
process.exit(1);
}
});
healthCheck.on('error', () => {
process.exit(1);
});
healthCheck.end();javascript
// healthcheck.js
const http = require('http');
const options = {
host: 'localhost',
port: 3000,
path: '/health',
timeout: 2000
};
const healthCheck = http.request(options, (res) => {
if (res.statusCode === 200) {
process.exit(0);
} else {
process.exit(1);
}
});
healthCheck.on('error', () => {
process.exit(1);
});
healthCheck.end();Monitoring Checklist
监控检查清单
- CPU usage < 70%
- Memory usage < 80%
- Error rate < 1%
- Response time p95 < 500ms
- Database connections healthy
- Redis connections healthy
- All pods running
- No pending deployments
- CPU使用率 < 70%
- 内存使用率 < 80%
- 错误率 < 1%
- P95响应时间 < 500ms
- 数据库连接正常
- Redis连接正常
- 所有Pod运行正常
- 无待处理部署任务
Infrastructure as Code
基础设施即代码
Terraform Configuration
Terraform配置
hcl
undefinedhcl
undefinedmain.tf
main.tf
provider "aws" {
region = "us-east-1"
}
resource "aws_ecs_cluster" "main" {
name = "app-cluster"
}
resource "aws_ecs_service" "app" {
name = "app-service"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
desired_count = 3
load_balancer {
target_group_arn = aws_lb_target_group.app.arn
container_name = "app"
container_port = 3000
}
}
resource "aws_ecs_task_definition" "app" {
family = "app"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "512"
memory = "1024"
container_definitions = jsonencode([
{
name = "app"
image = "your-registry/app:latest"
essential = true
portMappings = [
{
containerPort = 3000
protocol = "tcp"
}
]
environment = [
{
name = "NODE_ENV"
value = "production"
}
]
}
])
}
undefinedprovider "aws" {
region = "us-east-1"
}
resource "aws_ecs_cluster" "main" {
name = "app-cluster"
}
resource "aws_ecs_service" "app" {
name = "app-service"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
desired_count = 3
load_balancer {
target_group_arn = aws_lb_target_group.app.arn
container_name = "app"
container_port = 3000
}
}
resource "aws_ecs_task_definition" "app" {
family = "app"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "512"
memory = "1024"
container_definitions = jsonencode([
{
name = "app"
image = "your-registry/app:latest"
essential = true
portMappings = [
{
containerPort = 3000
protocol = "tcp"
}
]
environment = [
{
name = "NODE_ENV"
value = "production"
}
]
}
])
}
undefinedBest Practices
最佳实践
✅ DO
✅ 推荐做法
- Use infrastructure as code
- Implement CI/CD pipelines
- Use container orchestration
- Implement health checks
- Use rolling deployments
- Have rollback procedures
- Monitor deployments
- Document emergency procedures
- Use secrets management
- Implement blue-green or canary deployments
- 使用基础设施即代码
- 实现CI/CD流水线
- 使用容器编排
- 配置健康检查
- 使用滚动部署
- 制定回滚流程
- 监控部署过程
- 记录应急流程
- 使用密钥管理
- 实现蓝绿或金丝雀部署
❌ DON'T
❌ 不推荐做法
- Deploy directly to production
- Skip testing before deploy
- Forget to backup before migrations
- Deploy without rollback plan
- Skip monitoring after deployment
- Hardcode credentials
- Deploy during peak hours (unless necessary)
- 直接部署到生产环境
- 部署前跳过测试
- 迁移前忘记备份
- 部署时无回滚计划
- 部署后跳过监控
- 硬编码凭证
- 在高峰时段部署(除非必要)