第六章: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']
启用通知¶
完整示例¶
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 教程! 🎉