跳转至

第六章:CI/CD 集成

CI/CD 流程

GitOps 工作流

┌─────────────────────────────────────────────────────────────────────┐
│                      GitOps CI/CD 流程                              │
│                                                                      │
│  ┌─────────────┐     ┌─────────────┐     ┌─────────────┐           │
│  │   开发者    │────▶│   Git Repo  │────▶│    CI       │           │
│  │   提交代码  │     │   (配置)    │     │   (构建)    │           │
│  └─────────────┘     └─────────────┘     └─────────────┘           │
│                                                │                     │
│                                                │ 更新配置            │
│                                                ▼                     │
│                                          ┌─────────────┐             │
│                                          │  Git Repo   │             │
│                                          │  (Manifest) │             │
│                                          └──────┬──────┘             │
│                                                 │                     │
│                                                 │ Watch              │
│                                                 ▼                     │
│                                          ┌─────────────┐             │
│                                          │   ArgoCD    │             │
│                                          │   (同步)    │             │
│                                          └──────┬──────┘             │
│                                                 │                     │
│                                                 │ Deploy             │
│                                                 ▼                     │
│                                          ┌─────────────┐             │
│                                          │ Kubernetes  │             │
│                                          │   Cluster   │             │
│                                          └─────────────┘             │
└─────────────────────────────────────────────────────────────────────┘

GitLab CI 集成

更新镜像标签

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

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $IMAGE_TAG .
    - docker push $IMAGE_TAG

deploy:
  stage: deploy
  image: alpine/git
  script:
    # 克隆配置仓库
    - git clone https://oauth2:$GIT_TOKEN@gitlab.com/org/k8s-configs.git
    - cd k8s-configs

    # 更新镜像标签
    - sed -i "s|image:.*|image: $IMAGE_TAG|" apps/myapp/deployment.yaml

    # 提交并推送
    - git config user.name "CI Bot"
    - git config user.email "ci@example.com"
    - git add .
    - git commit -m "Update image to $CI_COMMIT_SHA"
    - git push
  only:
    - main

使用 yq 更新

deploy:
  stage: deploy
  image: mikefarah/yq:4
  script:
    - git clone https://oauth2:$GIT_TOKEN@gitlab.com/org/k8s-configs.git
    - cd k8s-configs

    # 使用 yq 更新
    - yq -i '.spec.template.spec.containers[0].image = "'$IMAGE_TAG'"' apps/myapp/deployment.yaml

    - git config user.name "CI Bot"
    - git add .
    - git commit -m "Update image to $CI_COMMIT_SHA"
    - git push

GitHub Actions 集成

更新配置

# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          push: true
          tags: ${{ secrets.REGISTRY }}/myapp:${{ github.sha }}

      - name: Update manifest
        run: |
          git clone https://x-access-token:${{ secrets.GIT_TOKEN }}@github.com/org/k8s-configs.git
          cd k8s-configs
          sed -i "s|image:.*|image: ${{ secrets.REGISTRY }}/myapp:${{ github.sha }}|" apps/myapp/deployment.yaml
          git config user.name "GitHub Actions"
          git config user.email "actions@github.com"
          git add .
          git commit -m "Update image to ${{ github.sha }}"
          git push

使用 GitHub Action

- name: Update ArgoCD
  uses: stefanprodan/kustomizer-action@v1
  with:
    version: latest
    command: set
    manifests: apps/myapp
    image: ${{ secrets.REGISTRY }}/myapp:${{ github.sha }}

ArgoCD API

同步 Application

# 获取 Token
argocd account generate-token

# 使用 API 同步
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  https://argocd.example.com/api/v1/applications/myapp/sync

CI 脚本示例

#!/bin/bash

# 设置变量
ARGOCD_SERVER="argocd.example.com"
ARGOCD_TOKEN="eyJh..."
APP_NAME="myapp"

# 同步 Application
sync_app() {
    curl -X POST \
        -H "Authorization: Bearer $ARGOCD_TOKEN" \
        "https://$ARGOCD_SERVER/api/v1/applications/$APP_NAME/sync"
}

# 等待同步完成
wait_for_sync() {
    while true; do
        STATUS=$(curl -s \
            -H "Authorization: Bearer $ARGOCD_TOKEN" \
            "https://$ARGOCD_SERVER/api/v1/applications/$APP_NAME" | \
            jq -r '.status.sync.status')

        if [ "$STATUS" == "Synced" ]; then
            echo "Sync completed"
            break
        fi

        echo "Waiting for sync..."
        sleep 5
    done
}

# 执行
sync_app
wait_for_sync

Image Updater

安装 Image Updater

# 安装
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml

配置 Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
  annotations:
    argocd-image-updater.argoproj.io/image-list: myapp=docker.io/myorg/myapp:latest
    argocd-image-updater.argoproj.io/myapp.update-strategy: latest
    argocd-image-updater.argoproj.io/myapp.allow-tags: regexp:^v[0-9]+\.[0-9]+\.[0-9]+$
    argocd-image-updater.argoproj.io/write-back-method: git
    argocd-image-updater.argoproj.io/git-branch: main
spec:
  # ...

更新策略

annotations:
  # 最新镜像
  argocd-image-updater.argoproj.io/myapp.update-strategy: latest

  # SemVer 版本
  argocd-image-updater.argoproj.io/myapp.update-strategy: semver

  # 名称模式
  argocd-image-updater.argoproj.io/myapp.update-strategy: name

  # 自定义
  argocd-image-updater.argoproj.io/myapp.update-strategy: digest

Notifications

配置通知

# argocd-notifications-cm
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: xoxb-xxx

  template.app-deployed: |
    message: |
      Application {{.app.metadata.name}} deployed successfully.
      Image: {{.app.status.summary.images}}

  trigger.on-deployed: |
    - description: Application deployed
      send:
        - app-deployed
      when: app.status.operationState.phase in ['Succeeded']

启用通知

metadata:
  annotations:
    notifications.argoproj.io/subscribe.on-deployed.slack: deployments

完整示例

GitLab CI + ArgoCD

# .gitlab-ci.yml
stages:
  - test
  - build
  - update-manifest
  - sync-argocd

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  CONFIG_REPO: https://oauth2:$GIT_TOKEN@gitlab.com/org/k8s-configs.git

test:
  stage: test
  image: node:18
  script:
    - npm ci
    - npm test

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $IMAGE_TAG .
    - docker push $IMAGE_TAG

update-manifest:
  stage: update-manifest
  image: alpine/git
  script:
    - git clone $CONFIG_REPO
    - cd k8s-configs
    - yq -i '.spec.template.spec.containers[0].image = "'$IMAGE_TAG'"' apps/myapp/deployment.yaml
    - git config user.name "GitLab CI"
    - git config user.email "ci@gitlab.com"
    - git add .
    - git commit -m "Update image to $CI_COMMIT_SHA"
    - git push
  only:
    - main

sync-argocd:
  stage: sync-argocd
  image: argoproj/argocd:latest
  script:
    - argocd login $ARGOCD_SERVER --grpc-web --auth-token $ARGOCD_TOKEN
    - argocd app sync myapp
    - argocd app wait myapp --health
  only:
    - main

GitHub Actions + ArgoCD

# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - uses: actions/checkout@v3

      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout config repo
        uses: actions/checkout@v3
        with:
          repository: org/k8s-configs
          token: ${{ secrets.GIT_TOKEN }}

      - name: Update manifest
        run: |
          yq -i '.spec.template.spec.containers[0].image = "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}"' apps/myapp/deployment.yaml
          git config user.name "GitHub Actions"
          git config user.email "actions@github.com"
          git add .
          git commit -m "Update image to ${{ github.sha }}"
          git push

      - name: Sync ArgoCD
        run: |
          curl -X POST \
            -H "Authorization: Bearer ${{ secrets.ARGOCD_TOKEN }}" \
            "${{ secrets.ARGOCD_SERVER }}/api/v1/applications/myapp/sync"

小结

本章学习了:

  • ✅ CI/CD 流程
  • ✅ GitLab CI 集成
  • ✅ GitHub Actions 集成
  • ✅ ArgoCD API
  • ✅ Image Updater
  • ✅ Notifications
  • ✅ 完整示例

恭喜完成 ArgoCD 教程! 🎉