# cicd **Repository Path**: qfns1860/cicd ## Basic Information - **Project Name**: cicd - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 8 - **Forks**: 0 - **Created**: 2026-05-13 - **Last Updated**: 2026-05-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Argo GitOps CI/CD Pipeline 基于 **Argo Events + Argo Workflows + ArgoCD** 的多集群 GitOps CI/CD 方案。 双仓分离架构:`charts` 仓库管理 Helm chart 源码,`configmaps` 仓库管理集群配置值。支持 DMZ / QA / PROD 环境隔离,通过 `default` + 集群差异分层配置减少重复。 --- ## 目录 - [Argo GitOps CI/CD Pipeline](#argo-gitops-cicd-pipeline) - [目录](#目录) - [架构总览](#架构总览) - [触发矩阵](#触发矩阵) - [目录结构](#目录结构) - [ci — Charts CI 流水线](#ci--charts-ci-流水线) - [流水线步骤](#流水线步骤) - [关键文件说明](#关键文件说明) - [cd — Configmaps CD 流水线](#cd--configmaps-cd-流水线) - [流水线步骤](#流水线步骤-1) - [环境隔离规则](#环境隔离规则) - [关键文件说明](#关键文件说明-1) - [common — 公共模板](#common--公共模板) - [模板清单](#模板清单) - [配置合并机制(read-config)](#配置合并机制read-config) - [tools — 工具与依赖](#tools--工具与依赖) - [RBAC](#rbac) - [存储](#存储) - [Secret 创建](#secret-创建) - [自定义镜像](#自定义镜像) - [参数传递机制](#参数传递机制) - [Sensor → Workflow(event\_config)](#sensor--workflowevent_config) - [Workflow 全局输出(globalName)](#workflow-全局输出globalname) - [Configmaps 仓库结构](#configmaps-仓库结构) - [配置合并顺序(helm template -f,右覆盖左)](#配置合并顺序helm-template--f右覆盖左) - [部署判断规则](#部署判断规则) - [k8s.yaml 格式](#k8syaml-格式) - [前置依赖](#前置依赖) - [Secrets 清单](#secrets-清单) - [部署顺序](#部署顺序) - [镜像清单](#镜像清单) - [配套](#配套) - [示例](#示例) --- ## 架构总览 ``` GitLab Webhook │ ▼ ┌─────────────────────────────────────────┐ │ EventSource │ │ eventsource-gitlab-charts (port 12000)│ 监听 charts 仓库 │ eventsource-gitlab-config (port 12001)│ 监听 configmaps 仓库 └────────┬────────────────────────────────┘ │ charts 事件 configmaps 事件 │ │ ▼ ▼ ┌──────────────┐ ┌─────────────────┐ │ charts-merge │ │ config-merge │ │ Sensor │ │ Sensor │ │ (MR 事件) │ │ (MR opened/ │ └──────┬───────┘ │ updated 事件) │ │ └────────┬────────┘ ▼ ▼ Charts CI Pipeline Configmaps CD Pipeline (lint/template/ (lint/template/ kubeconform/package) deploy/sync-wait) ``` --- ## 触发矩阵 | 事件 | Charts 流水线 | Configmaps 流水线 | |------|--------------|-----------------| | MR opened / updated | ✅ lint + helm template + kubeconform + helm package | ✅ yaml-lint + helm template 验证 + deploy(DMZ 自动 / QA·PROD 审批) | | Push to main | — | — | | Tag push | — | — | > **环境部署策略**:DMZ 集群 MR 合并后直接 deploy;QA / PROD 需要人工审批(`approve-suspend`,超时 30 分钟自动失败)。 --- ## 目录结构 ``` cicd/ ├── ci/ # Charts CI 流水线 │ ├── charts-eventsource.yaml # EventSource:监听 charts 仓库 GitLab Webhook │ ├── charts-merge-sensor.yaml # Sensor:charts MR 事件触发器 │ ├── charts-merge-template.yaml # 主编排:charts MR 流水线(DAG) │ ├── charts-tpl-template.yaml # Helm template 渲染测试(本地 chart,多 kube-version) │ ├── helm-package-template.yaml # Helm package 打包(按变更 chart 并行) │ └── kubeconform-template.yaml # K8s schema 校验(kubeconform,多 kube-version) │ ├── cd/ # Configmaps CD 流水线 │ ├── config-eventsource.yaml # EventSource:监听 configmaps 仓库 GitLab Webhook │ ├── config-merge-sensor.yaml # Sensor:configmaps MR 事件触发器(过滤 opened/updated) │ ├── config-merge-template.yaml # 主编排:configmaps MR 流水线(含人工审批) │ ├── clone-detect-template.yaml # 克隆双仓 + 环境隔离校验 + 变更检测生成 deploy_list │ ├── config-tpl-template.yaml # Helm template 渲染验证(从 ChartMuseum 拉取 chart) │ ├── config-deploy-template.yaml # ArgoCD 部署(patch version/branch → hard-refresh → sync-wait) │ └── yaml-lint-template.yaml # YAML 语法检查(仅校验 MR 变更文件) │ ├── common/ # 公共 WorkflowTemplate │ ├── clone-repos-template.yaml # 通用 git clone + Chart.yaml 版本校验 │ ├── commit-api-template.yaml # GitLab Commit Status API 回写(自动重试 3 次) │ ├── old-workflow-template.yaml # 终止同 trigger_ref 的旧 Workflow(kubectl / argo CLI) │ ├── pres-work-template.yaml # 前置:终止旧 Workflow + 重置 GitLab commit status │ ├── post-work-template.yaml # 后置:清理 PVC 工作目录 │ └── read-config-template.yaml # 读取 cicd.yaml 并与 ConfigMap 三层合并生成 external_config │ ├── tools/ # 基础设施 & 镜像 │ ├── argo-events-sa.yaml # Argo Events ServiceAccount + RBAC │ ├── argo-workflow-sa.yaml # Argo Workflows ServiceAccount + RBAC │ ├── gitlab-token.yaml # GitLab Secret 创建命令(charts + configmaps 两套) │ ├── pv-pvc.yaml # NFS PV / PVC(cicd-shared-pvc,10Gi,ReadWriteMany) │ ├── tools.dockerfile # tools 镜像:bash + curl + jq + yq(v4) + kubectl │ ├── python-git.dockerfile # python-git 镜像:python3.11 + git + jq + yq │ ├── argocd-python.dockerfile # argocd-python 镜像:argocd v3.3.4 + python3 │ └── kubeconform.dockerfile # kubeconform 镜像:alpine + kubeconform v0.7.0 │ └── README.md ``` --- ## ci — Charts CI 流水线 ### 流水线步骤 ``` MR opened / updated (charts 仓库) │ ▼ charts-merge-sensor │ 过滤:object_kind = merge_request │ 标签:event_type / trigger_ref(mr-{iid}) / project_id ▼ charts-merge-template (main-dag) │ ├── Step 0: pres-work ──────── 终止同 MR 的旧 Workflow + 重置 GitLab commit status ├── Step 1: read-config ─────── GitLab API 拉取 cicd.yaml,三层合并生成 external_config ├── Step 2: clone-repos ─────── 克隆 charts(source branch) + configmaps(main) │ └── post-clone: git diff → 提取变更 chart 列表(校验 Chart.yaml version 必须更新) │ ├── Step 3: helm-template ───── 对每个变更 chart 并行 helm template(多 kube-version) │ when: charts_names != '[]' │ ├── Step 4: kubeconform ─────── 对 helm-template 生成的 rendered-{ver}.yaml 进行 K8s schema 校验 │ depends: helm-template.Succeeded │ ├── Step 5: helm-package ─────── helm package 打包(与 kubeconform 并行) │ depends: helm-template.Succeeded │ └── Step 6: post-work ──────── 清理 PVC 工作目录 depends: (kubeconform.Succeeded || Omitted) && (helm-package.Succeeded || Omitted) ``` ### 关键文件说明 | 文件 | Kind | 说明 | |------|------|------| | `charts-eventsource.yaml` | EventSource | 监听 `root/charts` 仓库,端口 12000,接收 Push / TagPush / MR 事件 | | `charts-merge-sensor.yaml` | Sensor | 订阅 `eventsource-gitlab-charts`,使用 Go 模板提取 MR 字段,打包为 `event_config` JSON | | `charts-merge-template.yaml` | WorkflowTemplate | 主编排,DAG 6 步骤,parallelism=10,挂载 `cicd-shared-pvc` | | `charts-tpl-template.yaml` | WorkflowTemplate | `helm template` 按 chart 并行(withParam),循环多 kube-version;使用 `configmaps/default/{chart}/k8s.yaml` + `cfg.yaml` + `cluster.yaml` 渲染 | | `helm-package-template.yaml` | WorkflowTemplate | `helm package .` 按变更 chart 并行打包,镜像固定 `alpine/helm:3.16.4` | | `kubeconform-template.yaml` | WorkflowTemplate | 对 `rendered-{ver}.yaml` 逐 kube-version 校验,离线 schema 挂载在 `/work/schemas` | --- ## cd — Configmaps CD 流水线 ### 流水线步骤 ``` MR opened / updated (configmaps 仓库) │ ▼ config-merge-sensor │ 过滤:object_kind = merge_request, state = opened / updated │ 标签:event_type / trigger_ref(mr-{iid}) / project_id ▼ config-merge-template (main-dag) │ ├── Step 0: pres-work ──────────────── 终止旧 Workflow + 重置 GitLab commit status ├── Step 1: read-config ─────────────── 拉取 cicd.yaml + 三层合并(global → project → cicd) ├── Step 2: clone-detect ─────────────── 克隆 configmaps(source) + charts(main) │ ├── validate-isolation: 校验同一 MR 不能跨 dmz / qa / prod 类型 │ │ 输出: cluster_type(dmz / qa / prod) │ └── detect-changes: git diff → 构建 deploy_list(含 app_name / cluster / chart_version) │ 输出: deploy_list (JSON) + has_deploy (bool) │ ├── Step 3: yaml-lint ─────────────────── 对 .changed_yaml_files.txt 中的 YAML 文件 lint ┐ 并行 ├── Step 4: helm-temp ─────────────────── helm pull@ChartMuseum + helm template 渲染验证 ┘ │ when: deploy_list != '[]' │ ├── Step 5: approve-deploy ─────────────── 人工审批(Suspend) │ when: cluster_type != 'dmz' && has_deploy == 'true' │ 超时: 1800s(30 分钟) │ ├── Step 6: config-deploy ─────────────── 并行部署各 app │ depends: approve-deploy.Succeeded || approve-deploy.Skipped │ 子 DAG (deploy-app): │ patch-apply: argocd app set --revision chart_version / values_branch + hard-refresh │ sync-wait: argocd app sync --prune --async + argocd app wait --sync --health │ └── Step 7: post-work ──────────────────── 清理 PVC 工作目录 ``` ### 环境隔离规则 | 规则 | 说明 | |------|------| | 单 MR 单类型 | 同一 MR 变更的所有集群必须属于同一 `cluster_type`(dmz / qa / prod),否则 `validate-isolation` 失败 | | 仅改 cluster.yaml | 拒绝:变更中必须包含至少一个 app 级别文件 | | dmz 自动部署 | `cluster_type == 'dmz'` 时跳过人工审批,直接 deploy | | qa / prod 需审批 | `approve-suspend` 挂起等待,超时 30 分钟自动失败 | ### 关键文件说明 | 文件 | Kind | 说明 | |------|------|------| | `config-eventsource.yaml` | EventSource | 监听 `root/configmaps` 仓库,端口 12001 | | `config-merge-sensor.yaml` | Sensor | 过滤 `state = opened/updated`,打包 MR 事件为 `event_config` JSON | | `config-merge-template.yaml` | WorkflowTemplate | 主编排,含 `approve-suspend`(Suspend 节点)实现人工审批 | | `clone-detect-template.yaml` | WorkflowTemplate | Python 脚本:`validate-isolation`(类型隔离)+ `detect-changes`(生成 deploy_list) | | `config-tpl-template.yaml` | WorkflowTemplate | 按 deploy_list 并行 `helm pull + helm template`,values 合并顺序与 Application.yaml 一致 | | `config-deploy-template.yaml` | WorkflowTemplate | 每个 app 串行(patch-apply → sync-wait),多 app 并行;Python 实现 sync 状态监控 | | `yaml-lint-template.yaml` | WorkflowTemplate | 读取 `.changed_yaml_files.txt`,仅对变更文件执行 yamllint -d relaxed | --- ## common — 公共模板 所有流水线共享的 WorkflowTemplate,通过 `templateRef` 引用。 ### 模板清单 | 文件 | Template 名 | 说明 | |------|------------|------| | `pres-work-template.yaml` | `pres-work-dag` | 前置:并行执行 terminate-old + reset-commit-statuses,保证同 MR 只运行一个 Workflow | | `post-work-template.yaml` | `post-work-dag` | 后置:`rm -rf /work/{workflow.name}` 清理 PVC 中的工作目录 | | `read-config-template.yaml` | `read-config-dag` | 通过 GitLab API 拉取 `cicd.yaml`(可选),与 `global.yaml` + `project.yaml` 三层合并,输出 `external_config`(globalName) | | `clone-repos-template.yaml` | `clone-repos-dag` | 并行 clone source + others;post-clone 脚本校验 `Chart.yaml version` 必须更新,输出 `charts-names`(globalName) | | `commit-api-template.yaml` | `commit-status` | 调用 GitLab Commit Status API,状态映射:Succeeded→success / Failed→failed / Running→running / Skipped→canceled;自动重试 3 次指数退避 | | `old-workflow-template.yaml` | `terminate-old-kubectl` / `terminate-old-argo` | 通过 label `project_id + trigger_ref` 找到同组 Running/Pending Workflow,kubectl patch shutdown=Terminate | ### 配置合并机制(read-config) ``` global.yaml(ConfigMap default-config) ↓ 覆盖 project.yaml(ConfigMap default-config,按项目名匹配) ↓ 覆盖 cicd.yaml(GitLab API 从当前 MR source_branch 拉取,可选) ↓ external_config(JSON,globalName 跨 DAG 共享) ``` **external_config 示例**: ```json { "parameters": { "charts_name": "charts", "configmaps_name": "configmaps", "charts_repo": "http://gitlab.example.com/group/charts.git", "configmaps_repo": "http://gitlab.example.com/group/configmaps.git", "configmaps_default_branch": "main", "charts_default_branch": "main", "charts_registry": "http://chartmuseum:8080", "argocd_server": "argocd-server.argocd:80", "kube_versions": "1.28.0,1.32.0", "image_helm": "alpine/helm:3.16.4", "image_python_git": "python-git:1.0.0", "image_argocd": "argocd-python:v3.3.4" } } ``` --- ## tools — 工具与依赖 ### RBAC | 文件 | 说明 | |------|------| | `argo-events-sa.yaml` | `argo-events-sa`(namespace: argo-events)+ Role(namespace: argo),权限:create/get/list workflows & workflowtemplates | | `argo-workflow-sa.yaml` | `argo-workflow-sa`(namespace: argo)+ Role,权限:pods/log/exec/configmaps/secrets/workflowtaskresults + workflow CRUD | ### 存储 | 文件 | 说明 | |------|------| | `pv-pvc.yaml` | NFS PV(`192.168.16.138:/data/nfs/cicd`,10Gi,ReadWriteMany) + PVC `cicd-shared-pvc`(namespace: argo);Workflow 间通过 PVC 共享工作目录 | ### Secret 创建 ```bash # charts 仓库(argo-events namespace) kubectl create secret generic gitlab-access \ --from-literal=token= \ --namespace=argo-events kubectl create secret generic gitlab-secret \ --from-literal=token= \ --namespace=argo-events # charts 仓库(argo namespace) kubectl create secret generic gitlab-access \ --from-literal=token= \ --namespace=argo # configmaps 仓库(使用独立 token,argo-events namespace) kubectl create secret generic gitlab-access-config \ --from-literal=token= \ --namespace=argo-events kubectl create secret generic gitlab-secret-config \ --from-literal=token= \ --namespace=argo-events # ArgoCD 访问(argo namespace) kubectl create secret generic argocd-access \ --from-literal=token= \ --namespace=argo ``` ### 自定义镜像 | Dockerfile | 镜像标签 | 基础镜像 | 内置工具 | 用途 | |-----------|---------|---------|---------|------| | `tools.dockerfile` | `tools:1.0.0` | `alpine:3.18` | bash、curl、wget、jq、yq(v4.44.3)、kubectl | GitLab API 调用、commit status 回写、旧 Workflow 终止 | | `python-git.dockerfile` | `python-git:1.0.0` | `python:3.11-slim` | git、curl、jq、yq、openssh-client | 仓库克隆、变更检测、隔离校验 | | `argocd-python.dockerfile` | `argocd-python:v3.3.4` | `argocd:v3.3.4` | python3、pip3 | ArgoCD CLI sync-wait(Python 状态监控) | | `kubeconform.dockerfile` | `kubeconform:v0.7.0` | `alpine:3.18` | kubeconform v0.7.0 | K8s 资源 schema 合规校验 | --- ## 参数传递机制 ### Sensor → Workflow(event_config) Sensor 将 GitLab Webhook 字段通过 Go 模板提取,打包为单个 JSON 参数 `event_config`: ```json { "event": { "event_type": "merge_request", "project": "root/charts", "project_id": "123", "repo": "http://192.168.16.128/root/charts.git", "default_branch": "main", "mr_iid": 42, "mr_state": "opened", "source_branch": "feature/add-nginx", "target_branch": "main", "commit_id": "abc123...", "commit_author": "张三", "user_username": "zhangsan" } } ``` ### Workflow 全局输出(globalName) 跨 DAG step 通过 `workflow.outputs.parameters` 共享: ```yaml # 声明输出(在 WorkflowTemplate 中) outputs: parameters: - name: external_config valueFrom: path: /tmp/external_config.json globalName: external_config # ← 注册为全局 # 下游引用 value: "{{workflow.outputs.parameters.external_config}}" # jsonpath 取具体字段 value: "{{=jsonpath(workflow.outputs.parameters['external_config'], '$.parameters.kube_versions')}}" ``` | globalName | 产出步骤 | 说明 | |-----------|---------|------| | `external_config` | `read-config` | 合并后的完整配置 JSON | | `charts-names` | `clone-repos / post-clone` | 变更的 chart 名称数组(JSON) | --- ## Configmaps 仓库结构 ``` configmaps/ ├── default/ ← 基线配置(所有集群共享) │ ├── cluster.yaml ← 集群公共 values(type: dmz,role: base) │ ├── {app}/ │ │ ├── k8s.yaml ← argo 字段(chart/version/server/namespace)+ helm values 基线 │ │ └── cfg.yaml ← 额外 helm values(可选) ├── hf01/ ← DMZ 集群差异配置 │ ├── cluster.yaml ← type: dmz │ └── {app}/ │ └── k8s.yaml ← 仅写差异字段,自动 merge 覆盖 default ├── hf02/ ← QA 集群 │ └── cluster.yaml ← type: qa └── hf03/ ← PROD 集群 └── cluster.yaml ← type: prod ``` ### 配置合并顺序(helm template -f,右覆盖左) ``` default/cluster.yaml → default/{app}/k8s.yaml → default/{app}/cfg.yaml → {cluster}/cluster.yaml → {cluster}/{app}/k8s.yaml → {cluster}/{app}/cfg.yaml (可选) ``` ### 部署判断规则 `{cluster}/{app}/k8s.yaml` 文件存在 → 该 app 在该集群部署。每个集群独立判断,互不影响。 --- ## k8s.yaml 格式 ```yaml argo: # ArgoCD Application 控制字段 app: telegraf # 应用名(ArgoCD Application 名 = {cluster}-{app}) cluster: hf01 # 目标集群名 chart: telegraf # Helm chart 名 chartVersion: 1.8.55 # chart 版本(deploy_list 中的 chart_version) server: https://kubernetes.default.svc namespace: monitoring valuesBranch: main # values 来源分支 k8s: # Helm values(直接传给 helm template -f) replicaCount: 3 resources: limits: cpu: 500m memory: 256Mi ``` --- ## 前置依赖 | 组件 | 版本 / 说明 | |------|-----------| | Argo Events | EventSource + Sensor + EventBus(default,NATS) | | Argo Workflows | WorkflowTemplate + DAG | | ArgoCD | Application CRD,multi-source 支持 | | GitLab | Webhook + API(Commit Status / File API) | | ChartMuseum | Helm chart 仓库(`helm pull --repo`),configmaps 流水线使用 | | NFS | `cicd-shared-pvc`(ReadWriteMany,10Gi),Workflow 间共享工作目录 | | ConfigMap | `default-config`(含 `global.yaml` + `{project}.yaml`) | ### Secrets 清单 | Secret 名 | Namespace | 用途 | |----------|-----------|------| | `gitlab-access` | argo-events | charts 仓库 GitLab API token(EventSource) | | `gitlab-secret` | argo-events | charts Webhook 验证 token | | `gitlab-access-config` | argo-events | configmaps 仓库 GitLab API token(EventSource) | | `gitlab-secret-config` | argo-events | configmaps Webhook 验证 token | | `gitlab-access` | argo | GitLab API token(Workflow 内调用) | | `gitlab-secret` | argo | git clone 认证(`gitlab-ci-token:{token}`) | | `argocd-access` | argo | ArgoCD auth token(`ARGOCD_AUTH_TOKEN`) | --- ## 部署顺序 ```bash # 1. 创建命名空间(如不存在) kubectl create namespace argo kubectl create namespace argo-events # 2. 创建 RBAC kubectl apply -f tools/argo-events-sa.yaml kubectl apply -f tools/argo-workflow-sa.yaml # 3. 创建存储 kubectl apply -f tools/pv-pvc.yaml # 4. 创建 Secrets(参考 tools/gitlab-token.yaml,替换真实 token) kubectl create secret generic gitlab-access --from-literal=token= -n argo-events kubectl create secret generic gitlab-secret --from-literal=token= -n argo-events kubectl create secret generic gitlab-access-config --from-literal=token= -n argo-events kubectl create secret generic gitlab-secret-config --from-literal=token= -n argo-events kubectl create secret generic gitlab-access --from-literal=token= -n argo kubectl create secret generic gitlab-secret --from-literal=token= -n argo kubectl create secret generic argocd-access --from-literal=token= -n argo # 5. 构建并推送自定义镜像(参考 tools/*.dockerfile) docker build -f tools/tools.dockerfile tools/ -t tools:1.0.0 docker build -f tools/python-git.dockerfile tools/ -t python-git:1.0.0 docker build -f tools/argocd-python.dockerfile tools/ -t argocd-python:v3.3.4 docker build -f tools/kubeconform.dockerfile tools/ -t kubeconform:v0.7.0 # 6. 创建 ConfigMap default-config(包含 global.yaml + project.yaml) kubectl create configmap default-config \ --from-file=global.yaml \ --from-file=charts.yaml \ --from-file=configmaps.yaml \ -n argo # 7. 部署公共模板(common) kubectl apply -f common/ # 8. 部署 CI 流水线(charts) kubectl apply -f ci/ # 9. 部署 CD 流水线(configmaps) kubectl apply -f cd/ ``` --- ## 镜像清单 | 镜像 | 来源 | 用途 | |------|------|------| | `tools:1.0.0` | 自建(tools.dockerfile) | commit status 回写、旧 Workflow 终止、read-config | | `python-git:1.0.0` | 自建(python-git.dockerfile) | git clone、变更检测、类型隔离校验 | | `argocd-python:v3.3.4` | 自建(argocd-python.dockerfile) | ArgoCD sync + Python 状态监控 | | `kubeconform:v0.7.0` | 自建(kubeconform.dockerfile) | K8s schema 校验 | | `alpine/helm:3.16.4` | 官方 | helm template / helm package | | `cytopia/yamllint:latest` | 官方 | YAML 语法检查 | | `alpine:3.18` | 官方 | post-work 清理目录 | | `argoproj/argocli:v4.0.4` | 官方 | terminate-old-argo(备用方式) | ## 配套 https://github.com/qfns1861/configmaps.git https://github.com/qfns1861/charts.git ## 示例 ![charts-pipeline](charts-pipeline.png) ![config-pipeline](config-pipeline.png) ![config-merge](charts-merge.png) ![config-merge](config-merge.png)