版本控制与 CI/CD
概述
现代软件开发离不开版本控制和持续集成/持续部署(CI/CD)。本文涵盖 Git 工作流、GitHub Actions、Docker 容器化和 Kubernetes 基础。
1. Git 版本控制
1.1 Git 核心概念
工作区 (Working Directory)
│ git add
▼
暂存区 (Staging Area / Index)
│ git commit
▼
本地仓库 (Local Repository)
│ git push
▼
远程仓库 (Remote Repository)
1.2 分支模型
Git Flow
gitGraph
commit id: "init"
branch develop
checkout develop
commit id: "feat-start"
branch feature/login
checkout feature/login
commit id: "login-impl"
commit id: "login-test"
checkout develop
merge feature/login id: "merge-login"
branch release/1.0
checkout release/1.0
commit id: "bugfix"
checkout main
merge release/1.0 id: "v1.0" tag: "v1.0"
checkout develop
merge release/1.0 id: "sync"
| 分支 | 用途 | 生命周期 |
|---|---|---|
main |
生产环境代码 | 永久 |
develop |
开发集成 | 永久 |
feature/* |
新功能开发 | 临时 |
release/* |
发布准备 | 临时 |
hotfix/* |
紧急修复 | 临时 |
Trunk-Based Development
main ──●──●──●──●──●──●──●──●──
│ │ │
└─●─┘ └──●──┘ └─●─┘
短命分支(< 1-2 天)
- 主干始终保持可部署状态
- 分支生命周期极短(几小时到一两天)
- 依赖特性开关(Feature Flags)隐藏未完成功能
- 适合 CI/CD 成熟的团队
1.3 Merge vs Rebase
Merge:创建合并提交,保留完整历史
git checkout main
git merge feature/login
# 创建一个合并提交
Rebase:将分支的提交"移植"到目标分支上
git checkout feature/login
git rebase main
# 将 feature 的提交重放到 main 之上
git checkout main
git merge feature/login # fast-forward
| 方式 | 历史 | 优势 | 劣势 |
|---|---|---|---|
| Merge | 非线性 | 保留真实历史 | 历史混乱 |
| Rebase | 线性 | 历史清晰 | 改写历史,协作需谨慎 |
1.4 Cherry-pick
将特定提交应用到其他分支:
git checkout main
git cherry-pick abc1234 # 将某个提交应用到 main
git cherry-pick abc..def # 应用一个范围
使用场景:将 hotfix 从 main 同步到 develop,或选择性地移植功能。
2. GitHub Actions
2.1 Workflow 基本结构
# .github/workflows/ci.yml
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
PYTHON_VERSION: '3.11'
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Cache dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest --cov=src tests/
- name: Upload coverage
uses: codecov/codecov-action@v4
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install ruff
- run: ruff check src/
deploy:
needs: [test, lint]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy to production
run: ./deploy.sh
2.2 常用 Actions
| Action | 用途 |
|---|---|
actions/checkout |
检出代码 |
actions/setup-python |
配置 Python |
actions/setup-node |
配置 Node.js |
actions/cache |
缓存依赖 |
docker/build-push-action |
构建推送 Docker 镜像 |
peaceiris/actions-gh-pages |
部署到 GitHub Pages |
3. Docker
3.1 核心概念
Dockerfile → docker build → Image → docker run → Container
(配方) (镜像) (运行实例)
| 概念 | 类比 | 说明 |
|---|---|---|
| Image | 类 | 只读模板,包含应用和依赖 |
| Container | 实例 | Image 的运行实例,可读写 |
| Dockerfile | 蓝图 | 定义如何构建 Image |
| Registry | 仓库 | 存储和分发 Image(如 Docker Hub) |
3.2 Dockerfile 最佳实践
# 多阶段构建
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
FROM python:3.11-slim AS runtime
# 非 root 用户
RUN useradd --create-home appuser
USER appuser
WORKDIR /app
COPY --from=builder /root/.local /home/appuser/.local
COPY . .
ENV PATH=/home/appuser/.local/bin:$PATH
EXPOSE 8000
HEALTHCHECK CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
优化技巧:
- 利用构建缓存:先 COPY 依赖文件,再 COPY 源码
- 多阶段构建减小镜像体积
- 使用
.dockerignore排除不需要的文件 - 选择
slim或alpine基础镜像
3.3 Docker Compose
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
volumes:
pgdata:
4. Kubernetes 基础
4.1 核心概念
| 概念 | 说明 |
|---|---|
| Pod | 最小部署单元,包含一个或多个容器 |
| Service | 为 Pod 提供稳定的网络访问 |
| Deployment | 管理 Pod 的副本、更新、回滚 |
| ConfigMap/Secret | 配置和敏感信息管理 |
| Namespace | 资源隔离的虚拟集群 |
| Ingress | HTTP/HTTPS 外部访问入口 |
4.2 基本资源定义
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: myapp:v1.0
ports:
- containerPort: 8000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8000
type: ClusterIP
4.3 滚动更新
# 更新镜像版本
kubectl set image deployment/web-app web=myapp:v2.0
# 查看更新状态
kubectl rollout status deployment/web-app
# 回滚
kubectl rollout undo deployment/web-app
5. CI/CD 完整流水线
graph LR
A[代码提交] --> B[CI: 构建]
B --> C[CI: 测试]
C --> D[CI: 代码质量]
D --> E[CD: 构建镜像]
E --> F[CD: 推送 Registry]
F --> G{环境}
G -->|staging| H[部署 Staging]
H --> I[集成测试]
I --> J[人工审批]
J --> K[部署 Production]
G -->|直接| K
style A fill:#f9f
style K fill:#bfb
5.1 完整示例:GitHub Actions + Docker + K8s
name: Deploy Pipeline
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: |
pip install -r requirements.txt
pytest tests/
- name: Build Docker image
run: |
docker build -t myregistry/myapp:${{ github.sha }} .
- name: Push to registry
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker push myregistry/myapp:${{ github.sha }}
- name: Deploy to Kubernetes
uses: azure/k8s-deploy@v5
with:
manifests: k8s/
images: myregistry/myapp:${{ github.sha }}
6. 最佳实践
Git 规范
- 提交信息:使用 Conventional Commits(
feat:,fix:,docs:,refactor:) - 分支保护:main 分支要求 PR + Code Review + CI 通过
- 签名提交:GPG 签名重要提交
CI/CD 原则
- 快速反馈:测试应在 10 分钟内完成
- 不可变制品:同一个构建产物部署到所有环境
- 基础设施即代码:所有配置版本化管理
- 渐进式发布:金丝雀发布、蓝绿部署
与其他主题的关系
- 参见 测试与质量保障,理解自动化验证如何成为持续集成的核心输入
- 参见 全栈开发,理解前后端协作时如何管理分支、构建和部署
- 参见 云服务,理解镜像仓库、容器部署和云环境交付链路
- 参见 软件工程概述,理解版本控制与交付流程在软件生命周期中的位置
参考文献
- "Pro Git" - Scott Chacon & Ben Straub
- GitHub Actions 官方文档
- Docker 官方文档
- Kubernetes 官方文档