← 返回首页
🔧

CI/CD基础:持续集成与部署

📂 devops ⏱ 3 min 480 words

CI/CD基础:持续集成与部署

什么是CI/CD

CI/CD是现代软件开发的核心实践,通过自动化流程提高交付效率和代码质量。

CI/CD流程设计

典型流水线

代码提交 → 代码检查 → 单元测试 → 构建 → 集成测试 → 部署测试环境 → 验收测试 → 部署生产环境

阶段定义

stages:
  - checkout: 拉取代码
  - lint: 代码规范检查
  - test: 单元测试
  - build: 构建镜像
  - scan: 安全扫描
  - deploy-staging: 部署测试环境
  - integration-test: 集成测试
  - deploy-production: 部署生产环境
  - notify: 通知

流水线配置示例

简单的CI流程

# .gitlab-ci.yml
stages:
  - test
  - build

variables:
  DOCKER_IMAGE: myapp

test:
  stage: test
  image: node:18
  script:
    - npm ci
    - npm run lint
    - npm test
  coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t $DOCKER_IMAGE:$CI_COMMIT_SHA .
    - docker tag $DOCKER_IMAGE:$CI_COMMIT_SHA $DOCKER_IMAGE:latest
    - docker push $DOCKER_IMAGE:$CI_COMMIT_SHA
    - docker push $DOCKER_IMAGE:latest
  only:
    - main

完整的CI/CD流程

# .gitlab-ci.yml
stages:
  - lint
  - test
  - build
  - deploy-staging
  - integration-test
  - deploy-production

variables:
  IMAGE: registry.example.com/myapp
  KUBE_NAMESPACE: production

lint:
  stage: lint
  image: node:18
  script:
    - npm ci
    - npm run lint

test:
  stage: test
  image: node:18
  services:
    - postgres:14
    - redis:7
  variables:
    POSTGRES_DB: test_db
    POSTGRES_USER: test
    POSTGRES_PASSWORD: test
    DATABASE_URL: postgres://test:test@postgres/test_db
    REDIS_URL: redis://redis:6379
  script:
    - npm ci
    - npm run test:unit
    - npm run test:integration
  coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t $IMAGE:$CI_COMMIT_SHA .
    - docker push $IMAGE:$CI_COMMIT_SHA
  only:
    - main

deploy-staging:
  stage: deploy-staging
  image: bitnami/kubectl:latest
  script:
    - kubectl set image deployment/myapp myapp=$IMAGE:$CI_COMMIT_SHA -n staging
    - kubectl rollout status deployment/myapp -n staging --timeout=300s
  environment:
    name: staging
  only:
    - main

integration-test:
  stage: integration-test
  image: curlimages/curl:latest
  script:
    - |
      for i in 1 2 3 4 5; do
        if curl -sf http://staging.myapp.com/health; then
          echo "Health check passed"
          exit 0
        fi
        echo "Attempt $i failed, retrying..."
        sleep 10
      done
      echo "Health check failed"
      exit 1

deploy-production:
  stage: deploy-production
  image: bitnami/kubectl:latest
  script:
    - kubectl set image deployment/myapp myapp=$IMAGE:$CI_COMMIT_SHA -n production
    - kubectl rollout status deployment/myapp -n production --timeout=600s
  environment:
    name: production
  when: manual
  only:
    - main

Jenkins Pipeline

// Jenkinsfile
pipeline {
    agent any

    environment {
        IMAGE = 'registry.example.com/myapp'
        COMMIT = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        stage('Test') {
            steps {
                sh 'npm ci'
                sh 'npm run test'
            }
        }

        stage('Build') {
            steps {
                sh "docker build -t ${IMAGE}:${COMMIT} ."
                sh "docker push ${IMAGE}:${COMMIT}"
            }
        }

        stage('Deploy') {
            when {
                branch 'main'
            }
            steps {
                sh "kubectl set image deployment/myapp myapp=${IMAGE}:${COMMIT}"
            }
        }
    }

    post {
        success {
            slackSend channel: '#devops', message: "Build succeeded: ${env.JOB_NAME}"
        }
        failure {
            slackSend channel: '#devops', message: "Build failed: ${env.JOB_NAME}"
        }
    }
}

GitHub Actions

# .github/workflows/ci-cd.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '18'
      - run: npm ci
      - run: npm run lint
      - run: npm test

  build:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/build-push-action@v5
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.sha }}

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: azure/k8s-set-context@v1
        with:
          kubeconfig: ${{ secrets.KUBE_CONFIG }}
      - run: |
          kubectl set image deployment/myapp \
            myapp=ghcr.io/${{ github.repository }}:${{ github.sha }}

流水线最佳实践

# 1. 保持流水线快速(<10分钟)
# 2. 失败时快速反馈
# 3. 使用缓存加速构建
# 4. 并行执行独立任务
# 5. 保持环境一致性
# 6. 使用密钥管理工具
# 7. 实施蓝绿/金丝雀部署

总结

CI/CD是DevOps的核心实践。选择合适的工具,设计合理的流水线,可以显著提高软件交付效率和质量。