找回密码
立即注册
搜索
发回帖 发新帖

6402

积分

1

好友

802

主题
发表于 昨天 23:27 | 查看: 5| 回复: 0

代码推上去,然后呢?手动构建镜像、手动 push 到 Registry、手动 kubectl apply?GitLab CI/CD 用一个 .gitlab-ci.yml 把全流程串起来,push 即部署。

周五晚上改了个 bug。提交代码、本地构建镜像、push 到 Registry、SSH 到 K3s、kubectl set image……一气呵成,结果发现镜像 tag 写错了,又得重来。如果这些步骤能自动跑该多好?

CI/CD 的本质:把“代码到部署”之间所有手动步骤变成自动流水线。

CI vs CD

代码提交 → [CI] → 可部署的产物 → [CD] → 生产环境
            │                      │
            ├ 构建镜像              ├ 部署到 K8s
            ├ 运行测试              ├ 健康检查
            └ 安全扫描              └ 流量切换
概念 全称 干什么
CI Continuous Integration 代码提交后自动构建+测试
CD Continuous Delivery 构建产物自动部署到环境
CD Continuous Deployment 部署也全自动,无需人工批准

架构

GitLab CI/CD 由两部分组成:

  • GitLab Server:托管代码仓库,定义 Pipeline
  • GitLab Runner:执行具体任务(构建、测试、部署)

HomeLab 场景下,Server 可以用你现有的 Git 服务,Runner 装在 K3s 集群里。

安装 GitLab Runner

# Ubuntu/Debian
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt install gitlab-runner

# 注册 Runner
sudo gitlab-runner register
# 输入 GitLab URL:    https://gitlab.example.com/
# 输入 Token:         从 GitLab → Settings → CI/CD → Runners 获取
# 输入描述:           homelab-runner
# 输入 tag:           k3s,deploy
# 选择 executor:      shell(简单) 或 docker(隔离)

# 验证
sudo gitlab-runner verify
sudo gitlab-runner status

.gitlab-ci.yml:流水线定义

在项目根目录创建 .gitlab-ci.yml。这是一个完整示例:

# 定义阶段
stages:
- build
- test
- scan
- deploy

# 定义变量
variables:
  IMAGE_NAME: registry.local:5000/myapp
  IMAGE_TAG: $CI_COMMIT_SHORT_SHA

# 构建阶段
build:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  script:
    - docker build -t $IMAGE_NAME:$IMAGE_TAG .
    - docker push $IMAGE_NAME:$IMAGE_TAG
    - docker tag $IMAGE_NAME:$IMAGE_TAG $IMAGE_NAME:latest
    - docker push $IMAGE_NAME:latest
  only:
    - main
  tags:
    - docker

# 测试阶段
test:
  stage: test
  image: python:3.12-slim
  script:
    - pip install -r requirements.txt
    - pytest --junitxml=report.xml
  artifacts:
    reports:
      junit: report.xml
  only:
    - main

# 安全扫描
scan:
  stage: scan
  image: aquasec/trivy:latest
  script:
    - trivy image --exit-code 1 --severity HIGH,CRITICAL $IMAGE_NAME:$IMAGE_TAG
  allow_failure: true
  only:
    - main

# 部署阶段
deploy:
  stage: deploy
  script:
    - kubectl set image deployment/myapp myapp=$IMAGE_NAME:$IMAGE_TAG -n myapp
    - kubectl rollout status deployment/myapp -n myapp
  only:
    - main
  tags:
    - k3s

这个 Pipeline 做了 4 件事:

  1. Build:构建 Docker 镜像,推送到私有 Registry
  2. Test:运行单元测试,生成测试报告
  3. Scan:用 Trivy 扫描镜像漏洞
  4. Deploy:更新 K8s 集群中的镜像版本

git push 到 main 分支后自动触发,全程无人工干预。

关键语法详解

阶段和作业

stages:
- build    # 先执行
- test     # build 通过后执行
- deploy   # test 通过后执行

build-app:
  stage: build
  script:
    - echo "构建中..."

build-docs:
  stage: build   # 同一阶段的作业并行执行
  script:
    - echo "构建文档..."

同 stage 内的作业并行执行,不同 stage 串行执行。

条件控制

deploy_prod:
  stage: deploy
  script:
    - kubectl apply -f k8s/prod/
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: on_success
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: manual   # MR 触发时需要手动点击
    - when: never    # 其他情况不执行

缓存和制品

build:
  script:
    - npm ci
    - npm run build
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/   # 缓存依赖,下次构建更快
  artifacts:
    paths:
      - dist/           # 构建产物,下载保留 7 天
    expire_in: 7 days

环境变量管理

不要把密码写在 .gitlab-ci.yml 里。用 GitLab 的 CI/CD 变量:

GitLab → Settings → CI/CD → Variables

Key: REGISTRY_PASSWORD
Value: *****
Type: Variable
Protected: true    # 只有受保护分支可用
Masked: true       # 日志中不显示

在 Pipeline 中直接用:

script:
  - docker login registry.local:5000 -u $REGISTRY_USER -p $REGISTRY_PASSWORD

实战:完整部署流水线

以下是一个 HomeLab 应用的完整 CI/CD 配置:

stages:
  - lint
  - build
  - deploy

variables:
  APP_NAME: vaultwarden
  IMAGE: registry.local:5000/$APP_NAME
  TAG: ${CI_COMMIT_SHORT_SHA}

# 代码检查
lint:
  stage: lint
  image: hadolint/hadolint:latest-debian
  script:
    - hadolint Dockerfile
  allow_failure: true

# 构建镜像
build:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  before_script:
    - docker login -u $REGISTRY_USER -p $REGISTRY_PASSWORD registry.local:5000
  script:
    - docker build -t $IMAGE:$TAG -t $IMAGE:latest .
    - docker push $IMAGE:$TAG
    - docker push $IMAGE:latest
  after_script:
    - docker logout registry.local:5000

# 部署到 K3s
deploy_staging:
  stage: deploy
  environment:
    name: staging
    url: https://staging.homelab.local
  script:
    - kubectl set image deployment/$APP_NAME $APP_NAME=$IMAGE:$TAG -n vaultwarden
    - kubectl rollout status deployment/$APP_NAME -n vaultwarden
  rules:
    - if: $CI_COMMIT_BRANCH == "develop"

deploy_prod:
  stage: deploy
  environment:
    name: production
    url: https://vault.homelab.local
  script:
    - kubectl set image deployment/$APP_NAME $APP_NAME=$IMAGE:$TAG -n vaultwarden
    - kubectl rollout status deployment/$APP_NAME -n vaultwarden
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual   # 生产环境需要手动确认

这个配置实现了:

  • push 到 develop → 自动部署到 staging
  • push 到 main → 构建镜像,但部署需要手动点“Play”按钮确认
  • 生产部署有审批环节,防止误操作

配合 ArgoCD:GitOps 模式

如果用 ArgoCD,CI 只需要构建镜像和更新 Git 仓库中的版本号:

deploy:
  stage: deploy
  script:
    # 更新 Git 仓库中的镜像版本
    - git clone https://token:$GIT_TOKEN@gitlab.example.com/homelab/k8s-manifests.git
    - cd k8s-manifests
    - sed -i "s|image:.*|image: $IMAGE:$TAG|" apps/vaultwarden/deployment.yaml
    - git add .
    - git commit -m "update vaultwarden to $TAG"
    - git push
    # ArgoCD 会自动检测 Git 变更并部署

这样 CI 不需要 kubectl 权限,ArgoCD 负责部署。职责分离更清晰。

小结

维度 Shell 脚本 GitLab CI/CD
触发 手动执行 git push 自动触发
记录 靠日志文件 Pipeline 可视化历史
失败处理 脚本中断 某阶段失败,下游不执行
并行 不支持 同阶段自动并行
环境 单机 多 Runner 分布式

CI/CD 不是要不要做的问题,是什么时候开始做的问题。2 个应用以上就该上了。下一篇,聊 K8s CronJob——把定时任务也跑进集群里。




上一篇:K8s CronJob 定时任务实战:从 crontab 迁移到集群自动调度
下一篇:Helm 入门:K8s 包管理器像装 App 一样部署 Redis,还能自建 Chart
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-8 01:47 , Processed in 0.077654 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表