CI/CD流水线自动化实战:GitLab CI/CD与ArgoCD GitOps部署配置详解

CI/CD流水线架构选型与GitOps理念

传统CI/CD流水线中,部署阶段通常通过脚本直接操作目标环境(kubectl apply、helm install等),部署状态散落在各次执行记录中,难以审计和回滚。GitOps将Git仓库作为系统状态的唯一真实来源,部署过程变为”让Git中的声明状态与集群实际状态一致”。ArgoCD作为Kubernetes原生的GitOps持续交付工具,持续监控Git仓库与集群状态的差异并自动同步。

完整的GitOps流水线分为两个阶段:CI阶段(代码提交到镜像构建推送)由GitLab CI/CD负责,CD阶段(镜像部署到集群)由ArgoCD负责。两者通过镜像仓库(Harbor/ACR)解耦,CI只负责产出制品,CD只负责消费制品。

GitLab CI/CD流水线配置

GitLab CI/CD通过项目根目录的.gitlab-ci.yml文件定义流水线。以下配置实现代码检查、单元测试、镜像构建和推送的完整CI流程:

# .gitlab-ci.yml
stages:
  - lint
  - test
  - build
  - deploy-trigger

variables:
  IMAGE_REGISTRY: "registry.cn-east-1.aliyuncs.com"
  IMAGE_NAME: "myapp/api-server"
  DOCKER_DRIVER: overlay2

# 代码检查
lint:
  stage: lint
  image: golangci/golangci-lint:v1.61
  script:
    - golangci-lint run --timeout 5m ./...
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

# 单元测试
test:
  stage: test
  image: golang:1.23-alpine
  services:
    - name: redis:7-alpine
      alias: redis-test
    - name: mysql:8.0
      alias: mysql-test
      command: ["--default-authentication-plugin=mysql_native_password"]
  variables:
    REDIS_HOST: redis-test
    MYSQL_HOST: mysql-test
    MYSQL_ROOT_PASSWORD: testpass
    MYSQL_DATABASE: app_test
  script:
    - go test -race -coverprofile=coverage.out -covermode=atomic ./...
    - go tool cover -func=coverage.out | tail -1
  coverage: '/coverage:\s+(\d+\.\d+)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.out

# 镜像构建与推送(仅main分支触发)
build-and-push:
  stage: build
  image: docker:24.0
  services:
    - docker:24.0-dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $IMAGE_REGISTRY
    - docker build -t $IMAGE_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA .
    - docker tag $IMAGE_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA $IMAGE_REGISTRY/$IMAGE_NAME:latest
    - docker push $IMAGE_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA
    - docker push $IMAGE_REGISTRY/$IMAGE_NAME:latest
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

# 触发ArgoCD同步(更新GitOps仓库中的镜像版本)
update-gitops:
  stage: deploy-trigger
  image: alpine:3.20
  before_script:
    - apk add --no-cache git curl jq
  script:
    - git clone https://gitlab-ci-token:$CI_JOB_TOKEN@gitlab.com/team/gitops-repo.git
    - cd gitops-repo
    - |
      sed -i "s|image:.*|image: $IMAGE_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA|" apps/api-server/deployment.yaml
    - git config user.name "GitLab CI"
    - git config user.email "ci@gitlab.com"
    - git add apps/api-server/deployment.yaml
    - git commit -m "Update api-server image to $CI_COMMIT_SHORT_SHA"
    - git push origin main
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

流水线的关键设计:rules字段控制Job执行条件,merge request阶段只运行lint和test,main分支推送时才触发build和deploy-trigger。update-gitops步骤将新镜像版本写入GitOps仓库,ArgoCD检测到变更后自动同步部署。

Dockerfile多阶段构建优化

镜像构建环节对最终镜像大小和构建速度有直接影响。多阶段构建将编译环境和运行环境分离,运行镜像只包含二进制文件和必要依赖:

# Dockerfile
# 阶段1:构建
FROM golang:1.23-alpine AS builder
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o api-server ./cmd/server

# 阶段2:运行
FROM alpine:3.20
RUN apk add --no-cache ca-certificates tzdata
COPY --from=builder /build/api-server /usr/local/bin/
COPY --from=builder /build/configs /app/configs
EXPOSE 8080
ENTRYPOINT ["api-server"]

-ldflags="-s -w"去除调试信息和符号表,二进制体积减少约30%。使用go mod download单独缓存依赖层,代码变更时不会重新下载依赖。

ArgoCD安装与Application配置

ArgoCD通过Helm安装在Kubernetes集群中:

helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd -n argocd --create-namespace

# 获取初始密码
kubectl -n argocd get secret argocd-initial-admin-secret   -o jsonpath="{.data.password}" | base64 -d

# 端口转发访问UI
kubectl port-forward svc/argocd-server -n argocd 8080:443

Application定义GitOps仓库与Kubernetes集群的同步关系。以下配置监控GitOps仓库的apps/api-server目录,自动同步到production命名空间:

# argocd-app-api-server.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: api-server
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://gitlab.com/team/gitops-repo.git
    targetRevision: main
    path: apps/api-server
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true         # 删除Git中已移除的资源
      selfHeal: true       # 自动修复手动修改导致的漂移
      allowEmpty: false
    syncOptions:
      - CreateNamespace=true
      - PruneLast=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

selfHeal: true是GitOps的核心约束:如果有人手动kubectl edit修改了集群中的资源,ArgoCD会自动将其恢复为Git仓库中声明的状态。这确保了集群状态始终与Git仓库一致。如果需要临时手动修改,需先将变更提交到Git仓库。

多环境部署与ApplicationSet

生产环境通常需要dev、staging、prod三个环境,手动为每个环境创建Application会导致配置重复。ApplicationSet通过模板化生成Application,一份配置管理多环境:

# applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: api-server-multi-env
  namespace: argocd
spec:
  generators:
    - list:
        elements:
          - env: dev
            branch: develop
            namespace: dev
          - env: staging
            branch: release
            namespace: staging
          - env: prod
            branch: main
            namespace: production
  template:
    metadata:
      name: 'api-server-{{env}}'
    spec:
      project: default
      source:
        repoURL: https://gitlab.com/team/gitops-repo.git
        targetRevision: '{{branch}}'
        path: 'apps/api-server/overlays/{{env}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{namespace}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

配合Kustomize的overlays目录结构,每个环境使用独立的配置覆盖(副本数、资源限制、环境变量等):

apps/api-server/
├── base/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
└── overlays/
    ├── dev/
    │   ├── kustomization.yaml
    │   └── patches.yaml
    ├── staging/
    │   ├── kustomization.yaml
    │   └── patches.yaml
    └── prod/
        ├── kustomization.yaml
        └── patches.yaml

GitOps仓库结构清晰后,开发人员只需提交代码,CI流水线自动构建镜像并更新对应环境的Kustomize配置,ArgoCD自动同步到集群。整个部署流程无需人工操作,且每次变更都有Git提交记录可审计。

同步状态监控与告警

ArgoCD的同步状态需要持续监控。通过ArgoCD Notifications插件实现同步失败时自动发送告警:

# argocd-notifications-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: $slack-token
  trigger.on-deploy-failed: |
    - when: app.status.operationState.phase in ['Failed', 'Error']
      send: [slack-failed]
  template.slack-failed: |
    message: |
      ArgoCD同步失败: {{.app.metadata.name}}
      状态: {{.app.status.operationState.phase}}
      错误: {{.app.status.operationState.message}}
      链接: https://argocd.example.com/applications/{{.app.metadata.name}}

使用argocd app sync命令可手动触发同步,argocd app diff查看Git仓库与集群状态的差异。生产环境建议关闭automated自动同步,改为手动审批后同步,dev和staging环境保持自动同步以提高迭代速度。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/cicd-liu-shui-xian-zi-dong-hua-shi-zhan-gitlabcicd-yu/

(0)
小编小编
上一篇 4小时前
下一篇 4小时前

相关推荐