大家好,今天给大家带来一篇 DevOps 核心技能的实战原创教程 —— 基于 Kubernetes 集群,从零搭建完整的 GitLab CI/CD 持续集成体系,最终实现代码提交→自动构建→镜像打包→仓库推送→K8s 自动部署的全自动化流水线。
在如今的云原生研发体系中,DevOps 已经成为企业提效的核心手段,而GitLab CI/CD凭借与代码仓库的深度原生集成、轻量化的配置方式、强大的 Kubernetes 生态适配能力,已经成为从创业团队到大型企业构建持续集成体系的首选方案。
这篇教程我会全程以第一实操视角,带大家走完从 GitLab 服务部署、Runner 执行器配置、K8s 集群集成,到最终流水线落地的全流程,每一行代码都附带详细注释,同时给大家讲清每个组件的核心作用、配置逻辑,以及我踩过的所有坑,新手也能跟着一步步落地。
一、先搞懂:GitLab CI/CD 核心概念与架构解析
很多刚接触 CI/CD 的朋友会搞不清各个组件的分工,这里我用最通俗的话给大家讲清楚核心概念和整体架构,先懂原理再动手,事半功倍。
核心术语解析
| 组件名称 | 核心定位 | 核心作用 |
|---|---|---|
| GitLab | 代码托管与 CI/CD 调度中枢 | 开源的分布式代码托管平台,自带完整的 CI/CD 能力,负责代码版本管理、流水线定义、任务调度、执行结果展示,是整个 DevOps 流程的核心载体。 |
| GitLab CI/CD | 持续集成 / 持续交付核心引擎 | GitLab 内置的自动化引擎,通过项目根目录的.gitlab-ci.yml文件定义流水线规则,代码提交后自动触发流水线,实现从构建、测试、打包到部署的全流程自动化。 |
| GitLab Runner | 流水线任务执行器 | CI/CD 流水线的 "干活的节点",负责接收 GitLab 下发的流水线任务,我们将其部署在 K8s 集群中,支持动态创建临时 Pod 执行构建、打包等任务,执行完成后自动销毁,资源利用率极高。 |
| GitLab Agent | GitLab 与 K8s 集群的安全桥梁 | 用于实现 GitLab 和 K8s 集群的安全集成,无需暴露 K8s APIServer 到公网,即可实现 GitOps 自动化部署、集群状态监控、流水线中直接操作 K8s 资源,是 GitLab 对接 K8s 的官方推荐方案。 |
整体流水线架构
我们最终实现的完整流程如下:
- 开发者提交代码到 GitLab 项目仓库
- GitLab 自动触发 CI/CD 流水线,将任务下发给 GitLab Runner
- Runner 在 K8s 集群中创建临时 Pod,按流水线阶段依次执行:
- 代码编译构建
- 容器镜像打包
- 镜像推送到私有镜像仓库
- 自动部署应用到 K8s 集群
- 全程自动化,无需人工干预,实现代码提交即发布
二、前置环境与准备工作
先给大家同步我的实操环境,所有操作均在 K8s 集群中执行,大家可以根据自己的环境对应调整:
| 环境项 | 详细配置 |
|---|---|
| Kubernetes 集群 | 1 个 master 节点 + 1 个 worker 节点,版本 1.20+ |
| 容器运行时 | containerd |
| 核心工具 | Helm 3 已在 master 节点安装完成 |
| master 节点 IP | 172.18.10.44 |
| worker 节点 IP | 172.18.10.45 |
| 资源包 | Gitlab-CI.tar.gz(包含所有镜像、安装包、2048 demo 项目代码) |
基础环境初始化
首先我们先完成资源包解压、镜像导入,因为 K8s 调度 Pod 会分布在不同节点,所以需要把镜像导入到集群所有节点的 containerd 中。
1.解压资源包
# 进入root目录,所有操作均在此目录下执行 cd /root # 解压GitLab CI资源包 tar -zvxf Gitlab-CI.tar.gz2.镜像分发与导入
# 将镜像压缩包拷贝到worker节点,确保worker节点也能加载到所需镜像 scp /root/gitlab-ci/images/images.tar k8s-worker-node1:/root3.master 节点导入镜像
# 导入镜像到k8s.io命名空间(containerd中K8s使用的默认命名空间) ctr -n k8s.io image import gitlab-ci/images/images.tar4.worker 节点导入镜像
# 登录worker节点,执行镜像导入 ssh k8s-worker-node1 ctr -n k8s.io image import images.tar至此,基础环境准备完成,所有节点都已加载好所需镜像,接下来正式开始服务部署。
三、第一步:K8s 集群中部署 GitLab 服务
首先我们要在 K8s 中部署 GitLab 服务,作为整个 CI/CD 体系的核心中枢。我们会创建专属命名空间,通过 Deployment 部署 GitLab,用 NodePort 方式对外暴露服务,同时预配置 root 用户密码,避免首次登录手动修改。
3.1 创建专属命名空间
我们为 GitLab CI/CD 体系创建独立的命名空间,实现资源隔离,便于后续权限管理和运维:
# 创建gitlab-ci命名空间 kubectl create ns gitlab-ci # 输出namespace/gitlab-ci created即创建成功3.2 编写 GitLab Deployment 部署文件
Deployment 是 K8s 中用于部署无状态应用的核心资源,我们通过它定义 GitLab 的镜像、环境变量、端口等配置。
首先生成 Deployment 的基础模板,再进行自定义修改:
# 生成Deployment基础yaml模板,输出到gitlab-deploy.yaml文件 kubectl create deployment gitlab --image=gitlab/gitlab-ce:latest --port=80 --namespace=gitlab-ci --dry-run=client -o yaml > gitlab-deploy.yaml修改后的完整gitlab-deploy.yaml文件,附带逐行详细注释:
apiVersion: apps/v1 # 资源类型为Deployment kind: Deployment metadata: creationTimestamp: null labels: app: gitlab # Deployment名称 name: gitlab # 所属命名空间 namespace: gitlab-ci spec: # 副本数,单节点部署设置1即可,生产环境可调整为多副本 replicas: 1 selector: # 标签选择器,匹配对应标签的Pod matchLabels: app: gitlab strategy: {} # Pod模板定义 template: metadata: creationTimestamp: null labels: app: gitlab spec: # 容器定义 containers: - name: gitlab # GitLab镜像,我们已提前导入到集群 image: gitlab/gitlab-ce:latest # 镜像拉取策略:IfNotPresent表示本地有镜像就不拉取,避免外网拉取失败 imagePullPolicy: IfNotPresent # 环境变量配置,预设置GitLab root用户的密码和邮箱 env: # 设置root用户初始密码,生产环境请更换为强密码 - name: GITLAB_ROOT_PASSWORD value: admin@123 # 设置root用户邮箱 - name: GITLAB_ROOT_EMAIL value: 123456@qq.com # 容器端口暴露 ports: - name: http containerPort: 80 # 资源限制,生产环境请根据服务器配置调整,GitLab最低建议2核4G resources: {} status: {}3.3 编写 GitLab Service 服务文件
Service 用于给 GitLab Pod 提供固定的访问入口,我们使用 NodePort 类型,将 GitLab 的 80 端口映射到宿主机的 30880 端口,实现集群外访问。
生成 Service 基础模板:
# 生成NodePort类型的Service模板,输出到gitlab-service.yaml文件 kubectl create service nodeport gitlab --namespace=gitlab-ci --tcp=80:80 --node-port=30880 --dry-run=client -o yaml > gitlab-service.yaml修改后的完整gitlab-service.yaml文件,附带详细注释:
apiVersion: v1 # 资源类型为Service kind: Service metadata: creationTimestamp: null labels: app: gitlab # Service名称 name: gitlab # 所属命名空间 namespace: gitlab-ci spec: # 端口映射配置 ports: - name: http # NodePort端口,集群外通过这个端口访问GitLab nodePort: 30880 # Service端口 port: 80 # 目标Pod端口,和Deployment中暴露的容器端口一致 targetPort: http # 标签选择器,匹配GitLab Pod的标签,实现流量转发 selector: app: gitlab # Service类型为NodePort,实现集群外访问 type: NodePort status: loadBalancer: {}3.4 部署 GitLab 服务并验证
1.执行部署命令
# 部署GitLab Deployment kubectl apply -f gitlab-deploy.yaml # 输出deployment.apps/gitlab created即部署成功 # 部署GitLab Service kubectl apply -f gitlab-service.yaml # 输出service/gitlab created即部署成功2.查看部署状态GitLab 启动较慢,需要等待 1-3 分钟,Pod 状态变为 Running 即为启动成功:
# 查看gitlab-ci命名空间下的Pod状态 kubectl get pod -n gitlab-ci # 正常输出示例 NAME READY STATUS RESTARTS AGE gitlab-5df67d6c7f-jgbpp 1/1 Running 0 86s # 查看Service状态 kubectl get svc -n gitlab-ci # 正常输出示例 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gitlab NodePort 10.96.193.92 <none> 80:30880/TCP 3m24s访问 GitLab 服务此时我们可以通过浏览器访问http://master节点IP:30880,比如我的环境就是http://172.18.10.44:30880,使用账号root、密码admin@123即可登录 GitLab。
四、第二步:GitLab 集群内 DNS 解析配置与项目初始化
4.1 配置 CoreDNS 实现 GitLab Pod 域名解析
GitLab 在流水线中会返回 Pod 内的仓库地址,为了让集群内的 Runner 能正常解析 GitLab 的地址,我们需要修改 K8s 的 CoreDNS 配置,添加 GitLab Pod 的 hosts 解析。
1.首先获取 GitLab Pod 的 IP 和名称
# 获取GitLab Pod的详细信息,记录NAME和IP kubectl get pod -n gitlab-ci -o wide2.编辑 CoreDNS 的 ConfigMap 配置
# 编辑kube-system命名空间下的coredns配置 kubectl edit configmap coredns -n kube-system在 Corefile 中添加 hosts 配置,注释掉默认的 forward 配置,修改后的核心配置如下:
hosts { # 这里替换为你的GitLab Pod IP和Pod名称 10.244.0.18 gitlab-f6874fdb8-zfx9v fallthrough } prometheus :9153 # forward . /etc/resolv.conf { # max_concurrent 1000 # } cache 303.重启 CoreDNS 使配置生效
# 滚动重启CoreDNS Deployment kubectl -n kube-system rollout restart deploy coredns # 输出deployment.apps/coredns restarted即重启成功4.2 创建 GitLab 项目并上传代码
接下来我们创建一个 demo 项目,用于后续的 CI/CD 流水线测试,这里使用 2048 游戏项目作为示例。
创建项目登录 GitLab 后,点击
New a project→Create blank project,项目名称填写demo-2048,可见等级选择Public,点击创建即可。
上传 demo 代码到 GitLab 仓库
# 进入demo项目代码目录 cd /root/gitlab-ci/demo-2048 # 配置git全局用户信息 git config --global user.name "administrator" git config --global user.email "admin@example.com" # 移除默认的远程仓库,添加我们刚创建的GitLab仓库地址 git remote remove origin # 这里替换为你的GitLab仓库地址,IP为master节点IP git remote add origin http://172.18.10.44:30880/root/demo-2048.git # 添加所有代码文件到暂存区 git add . # 提交代码到本地仓库 git commit -m "initial commit" # 推送代码到GitLab远程仓库的drone分支 git push -u origin drone执行完成后,刷新 GitLab 项目页面,就能看到我们上传的代码了。这里注意,我们的默认分支是drone,如果需要修改默认分支,可以在项目的设置→仓库→默认分支中调整。
五、第三步:部署 GitLab CI Runner 执行器
GitLab Runner 是 CI/CD 流水线的执行器,负责接收 GitLab 下发的任务并执行。我们将通过 Helm 在 K8s 集群中部署 Runner,实现流水线任务的动态 Pod 执行。
5.1 前置配置:获取 Runner 注册令牌
首先我们需要获取 GitLab 的 Runner 注册令牌,用于 Runner 和 GitLab 服务的注册绑定:
- 登录 GitLab 管理界面,访问
http://master节点IP:30880/admin - 点击左侧菜单栏
CI/CD→Runners - 记录下页面中的注册令牌,后续配置会用到
5.2 配置 RBAC 权限
Runner 需要在 K8s 集群中创建、删除 Pod,所以需要给它配置对应的 RBAC 权限,这里提供两种配置方式,效果一致。
方式一:命令行快速创建
# 创建ServiceAccount kubectl create serviceaccount gitlab-ci -n gitlab-ci # 创建Role,授予gitlab-ci命名空间下所有资源的所有权限 kubectl create role gitlab-ci --resource=* --verb=* -n gitlab-ci # 创建RoleBinding,将Role绑定到ServiceAccount kubectl create rolebinding gitlab-ci --role=gitlab-ci --serviceaccount=gitlab-ci:gitlab-ci -n gitlab-ci方式二:YAML 文件创建(推荐,便于版本管理)
创建runner-rbac.yaml文件,内容如下:
# ServiceAccount:给Runner提供身份凭证 apiVersion: v1 kind: ServiceAccount metadata: name: gitlab-ci namespace: gitlab-ci --- # Role:定义权限规则,授予命名空间下所有资源的所有操作权限 kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: gitlab-ci namespace: gitlab-ci rules: - apiGroups: [""] resources: ["*"] verbs: ["*"] --- # RoleBinding:将Role和ServiceAccount绑定,使权限生效 kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: gitlab-ci namespace: gitlab-ci subjects: - kind: ServiceAccount name: gitlab-ci namespace: gitlab-ci roleRef: kind: Role name: gitlab-ci apiGroup: rbac.authorization.k8s.io执行部署命令:
kubectl apply -f runner-rbac.yaml同时,我们需要给 default ServiceAccount 授予集群管理员权限,用于后续流水线中操作集群资源:
# 创建ClusterRoleBinding,给gitlab-ci命名空间下的default SA绑定cluster-admin集群管理员权限 kubectl create clusterrolebinding default --clusterrole=cluster-admin --serviceaccount=gitlab-ci:default5.3 Helm 部署 GitLab Runner
我们使用官方的 GitLab Runner Helm Chart 进行部署,实现高可用、可配置的 Runner 部署。
1.解压 Helm Chart 包
# 解压Runner Helm Chart包 tar -zxvf gitlab-runner-0.43.0.tgz # 进入Chart目录 cd gitlab-runner2.修改values.yaml核心配置
编辑values.yaml文件,修改以下四个核心参数,同时添加特权模式配置:
# 1. 指定我们创建的ServiceAccount名称 serviceAccountName: gitlab-ci # 2. GitLab服务地址,替换为你的master节点IP gitlabUrl: http://172.18.10.44:30880/ # 3. 之前记录的Runner注册令牌 runnerRegistrationToken: "3x2Q7nbinwq58eN2KbGj" # 4. Runner配置,开启特权模式,用于容器镜像构建 runners: config: | [[runners]] [runners.kubernetes] namespace = "{{.Release.Namespace}}" image = "ubuntu:16.04" # 开启特权模式,必须开启,否则Docker in Docker构建镜像会失败 privileged = true3.(可选)配置构建缓存 PVC为了避免每次构建都重新下载依赖,提升构建速度,我们配置 PVC 用于构建缓存持久化:
创建templates/pvc.yaml文件,定义 PV 和 PVC:
# 持久化卷PV,使用hostPath模式,单节点测试使用,生产环境建议使用分布式存储 apiVersion: v1 kind: PersistentVolume metadata: name: ci-build-cache-pv namespace: gitlab-ci labels: type: local spec: storageClassName: manual capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: "/opt/ci-build-cache" --- # 持久化卷声明PVC apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ci-build-cache-pvc namespace: gitlab-ci spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 5Gi在values.yaml文件末尾追加缓存配置:
## configure build cache cibuild: cache: pvcName: ci-build-cache-pvc mountPath: /home/gitlab-runner/ci-build-cache编辑templates/configmap.yaml文件,在 Runner 启动前添加 PVC 挂载配置:
# 在start the runner之前添加如下配置,实现PVC自动挂载 cat >>/home/gitlab-runner/.gitlab-runner/config.toml <<EOF [[runners.kubernetes.volumes.pvc]] name = "{{.Values.cibuild.cache.pvcName}}" mount_path = "{{.Values.cibuild.cache.mountPath}}" EOF # Start the runner exec /entrypoint run --user=gitlab-runner \ --working-directory=/home/gitlab-runner4.执行 Helm 安装
# 在gitlab-runner目录下执行安装命令,安装到gitlab-ci命名空间 helm -n gitlab-ci install gitlab-runner .安装成功后,会输出如下提示:
NAME: gitlab-runner LAST DEPLOYED: Mon Sep 11 15:56:17 2025 NAMESPACE: gitlab-ci STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: Your GitLab Runner should now be registered against the GitLab instance reachable at: "http://172.18.10.44:30880/"5.验证 Runner 部署与注册
# 查看gitlab-ci命名空间下的Pod,确认Runner Pod正常Running kubectl get pod -n gitlab-ci # 正常输出示例,Runner Pod状态为Running NAME READY STATUS RESTARTS AGE gitlab-f6874fdb8-8w9vx 1/1 Running 0 66m gitlab-runner-768f67cffb-kczpp 1/1 Running 0 112s此时回到 GitLab 的 Runner 页面,刷新后就能看到我们刚部署的 Runner 已经成功注册,状态为在线,至此 Runner 部署完成。
六、第四步:配置 GitLab Agent 实现 K8s 集群集成
GitLab Agent 是 GitLab 官方推荐的 K8s 集群集成方案,用于实现 GitOps 自动化部署、流水线中安全操作 K8s 资源,无需暴露 K8s APIServer 到公网,安全性更高。
6.1 创建 Agent 配置文件
在 GitLab 的 demo-2048 项目中,创建 Agent 配置文件,路径为.gitlab/agents/kubernetes-agent/config.yaml,内容如下:
# GitLab Agent配置,定义GitOps管理的项目和规则 gitops: manifest_projects: # 要管理的项目ID,格式为 用户名/项目名 - id: root/demo-2048 # 部署的默认命名空间 default_namespace: gitlab-ci # 要扫描的K8s资源清单路径,匹配所有yaml/yml/json文件 paths: - glob: '/**/*.{yaml,yml,json}'提交配置文件到 GitLab 仓库后,进入项目的运维→Kubernetes页面,点击添加Kubernetes集群,选择连接现有集群,记录下 Agent 的令牌和接入地址。
6.2 Helm 安装 GitLab Agent
回到 master 节点,执行以下 Helm 命令安装 Agent,替换为你的令牌和 GitLab 地址:
helm install kubernetes-agent gitlab-agent-1.1.0.tgz --namespace gitlab-ci \ --set image.tag=v16.2.0 \ --set config.token=qbn5FDiW4d1hytg-EA7WFKcidG-rwz-WyGY5hBBAwn8ZWt_jAw \ --set config.kasAddress=ws://172.18.10.44:30880/-/kubernetes-agent/安装完成后,验证 Agent 状态:
# 查看helm发布列表 helm -n gitlab-ci list # 查看Agent Pod状态,正常为Running kubectl get pod -n gitlab-ci | grep kubernetes-agent回到 GitLab 的 Kubernetes 页面,刷新后就能看到集群已成功连接,Agent 状态为在线。
七、第五步:构建完整 CICD 流水线,实现自动构建与部署
接下来就是最核心的环节,我们通过编写.gitlab-ci.yml文件,定义完整的 CI/CD 流水线,实现代码提交后自动完成代码构建→镜像打包→仓库推送→K8s 部署的全流程自动化。
7.1 前置配置:Harbor 镜像仓库准备
我们需要一个私有镜像仓库来存储构建好的应用镜像,这里使用 Harbor 作为私有仓库,提前完成以下配置:
- 在 Harbor 中创建一个公开项目
demo - 将基础镜像推送到 Harbor 仓库,确保流水线能正常拉取
- 配置 K8s 集群的 containerd,使其能正常访问 Harbor 仓库
1. 推送基础镜像到 Harbor
# 给tomcat基础镜像打标签,替换为你的Harbor仓库IP ctr -n k8s.io images tag docker.io/library/tomcat:8.5.64-jdk8 172.18.10.44/library/tomcat:8.5.64-jdk8 # 推送镜像到Harbor仓库,替换为你的Harbor账号密码 ctr -n k8s.io images push 172.18.10.44/library/tomcat:8.5.64-jdk8 --plain-http=true --user admin:Harbor123452. 配置 containerd 支持 Harbor HTTP 仓库
修改集群所有节点的 containerd 配置文件,添加 Harbor 仓库配置:
# 编辑containerd配置文件 vi /etc/containerd/config.toml # 在[plugins."io.containerd.grpc.v1.cri".registry.mirrors]下添加以下内容 [plugins."io.containerd.grpc.v1.cri".registry.mirrors."172.18.10.44"] endpoint = ["http://172.18.10.44"] # 重启containerd使配置生效 systemctl daemon-reload systemctl restart containerd⚠️ 注意:master 和 worker 节点都需要修改配置并重启 containerd。
7.2 编写.gitlab-ci.yml 流水线文件
在 demo-2048 项目的根目录创建.gitlab-ci.yml文件,定义流水线的三个核心阶段:build(代码构建)、release(镜像打包推送)、review(应用部署),完整代码附带逐行注释如下:
# 定义流水线的阶段,按顺序执行 stages: - build - release - review # 全局环境变量,所有阶段都能使用 variables: # Maven本地仓库路径,配合PVC缓存,避免每次重新下载依赖 MAVEN_OPTS: "-Dmaven.repo.local=/opt/cache/.m2/repository" # Harbor仓库账号 REGISTRY_USER: admin # Harbor仓库密码 REGISTRY_PASSWORD: Harbor12345 # Harbor仓库地址,替换为你的IP REGISTRY: 172.18.10.44 # 镜像名称 REGISTRY_IMAGE: demo # Harbor项目名称 REGISTRY_PROJECT: demo # 第一阶段:代码构建,使用Maven镜像编译打包Java项目 maven_build: # 使用的镜像,包含Maven和JDK8环境 image: maven:3.6-jdk-8 # 所属阶段 stage: build # 触发规则:仅drone分支提交代码时触发 only: - drone # 执行的脚本 script: # 拷贝预下载的依赖到缓存目录,加速构建 - cp -r /opt/repository /opt/cache/.m2/ # 执行Maven打包,跳过单元测试 - mvn clean install -DskipTests=true # 进入target目录,解压war包,用于后续镜像构建 - cd target && jar -xf 2048.war # 将解压后的文件拷贝到PVC缓存目录,供下一阶段使用 - cp -rfv 2048 /home/gitlab-runner/ci-build-cache # 第二阶段:镜像构建与推送,使用Docker-in-Docker实现容器镜像打包 image_build: image: docker:18.09.7 stage: release # Docker环境变量 variables: DOCKER_DRIVER: overlay2 DOCKER_HOST: tcp://localhost:2375 # 依赖的服务,Docker-in-Docker,用于镜像构建 services: - name: docker:18.09.7-dind entrypoint: ["dockerd-entrypoint.sh"] # 开启HTTP仓库支持,避免HTTPS证书问题 command: ["--insecure-registry", "0.0.0.0/0"] script: # 从缓存目录拷贝上一阶段构建好的项目文件 - cp -rfv /home/gitlab-runner/ci-build-cache/2048 . # 替换Dockerfile中的Harbor地址为当前环境变量 - sed -i "s/10.24.2.3/$REGISTRY/g" ./Dockerfiles/Dockerfile # 构建Docker镜像 - docker build -t "${REGISTRY_IMAGE}:latest" -f ./Dockerfiles/Dockerfile . # 给镜像打标签,符合Harbor仓库规范 - docker tag "${REGISTRY_IMAGE}:latest" "${REGISTRY}/${REGISTRY_PROJECT}/${REGISTRY_IMAGE}:latest" # 登录Harbor仓库 - docker login -u "${REGISTRY_USER}" -p "${REGISTRY_PASSWORD}" "${REGISTRY}" # 推送镜像到Harbor仓库 - docker push "${REGISTRY}/${REGISTRY_PROJECT}/${REGISTRY_IMAGE}:latest" # 第三阶段:自动部署到K8s集群 deploy_review: # 包含kubectl工具的镜像,用于操作K8s集群 image: bitnami/kubectl:1.22.1 stage: review only: - drone script: # 替换部署文件中的镜像仓库地址为当前环境变量 - sed -i "s/REGISTRY/$REGISTRY/g" template/demo-2048.yaml # 应用K8s部署文件,自动部署应用到集群 - kubectl apply -f template/7.3 触发流水线并验证
将.gitlab-ci.yml文件提交并推送到 GitLab 仓库后,GitLab 会自动触发流水线,我们可以在项目的CI/CD→流水线页面查看执行状态。
流水线执行成功后,我们可以验证应用是否部署成功:
# 查看gitlab-ci命名空间下的Pod,确认demo应用Pod正常Running kubectl get pod -n gitlab-ci # 正常输出示例 NAME READY STATUS RESTARTS AGE demo-2048-56847d667c-59dtp 1/1 Running 0 95s # 查看Service,确认应用端口映射正常 kubectl get svc -n gitlab-ci # 正常输出示例 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE demo-2048 NodePort 10.96.67.233 <none> 8080:8889/TCP 4h28m此时我们通过浏览器访问http://master节点IP:8889,就能看到我们部署的 2048 游戏应用,至此完整的 CI/CD 流水线全部落地完成!
八、踩坑指南与生产环境注意事项
8.1 我踩过的核心坑点,帮大家避坑
Runner 注册失败
- 大概率是 GitLab 地址无法解析,检查 CoreDNS 的 hosts 配置是否正确,确保 Runner Pod 能 ping 通 GitLab 的 Service 和 Pod 地址
- 检查注册令牌是否正确,GitLab 的项目级令牌和全局管理员令牌不能混用
流水线镜像构建失败
- 必须给 Runner 开启 privileged 特权模式,否则 Docker-in-Docker 无法正常运行
- 检查 Harbor 仓库的 HTTP 配置,containerd 和 dind 服务都需要配置 insecure-registry,否则会报 HTTPS 证书错误
K8s 部署权限不足
- 检查流水线使用的 ServiceAccount 是否有对应的命名空间权限,提前给 default SA 绑定 cluster-admin 权限,或者按需配置最小权限
GitLab 启动慢 / 无法访问
- GitLab 对资源要求较高,最低需要 2 核 4G 配置,资源不足会导致启动失败、页面无法访问
- 检查 NodePort 端口是否被防火墙拦截,开放 30880 端口的访问权限
8.2 生产环境注意事项
- 高可用部署
- GitLab 服务建议使用多副本部署,使用共享存储做数据持久化,避免单点故障
- Runner 部署多个副本,提升流水线并发执行能力
- 安全加固
- 所有默认密码必须更换为强密码,包括 GitLab root 账号、Harbor 账号、数据库密码
- GitLab 和 Harbor 都配置 HTTPS 证书,替换 HTTP 访问,避免数据传输泄露
- 给 Runner 配置最小权限原则,不要直接绑定 cluster-admin 集群管理员权限
- 持久化存储
- GitLab 的代码数据、Runner 的构建缓存、Harbor 的镜像数据都必须使用持久化存储,避免数据丢失
- 生产环境建议使用分布式存储(如 Ceph、NFS),不要使用 hostPath 模式
- 资源限制
- 给所有 Deployment 都配置 CPU 和内存的 requests 和 limits,避免单个服务占用过多资源,影响集群稳定
- 流水线优化
- 配置依赖缓存,减少重复下载,提升构建速度
- 增加单元测试、代码扫描、漏洞检测阶段,提升代码质量
- 配置多环境流水线,实现开发、测试、生产环境的分级部署
结尾总结
今天这篇教程,我带大家从零开始,在 K8s 集群中完成了 GitLab 服务部署、Runner 执行器配置、K8s 集群 Agent 集成,最终落地了一套完整的代码提交→自动构建→镜像打包→仓库推送→自动部署的全流程 CI/CD 流水线。
整个流程下来,大家不仅能掌握 GitLab CI/CD 的核心原理和实操技能,更能理解 DevOps 持续集成的核心思想 —— 通过自动化减少人工操作,提升研发效率,降低发布风险。后续大家还可以基于这套体系,扩展代码扫描、自动化测试、灰度发布、回滚机制等高级功能,打造更完善的企业级 DevOps 体系。
如果大家在部署过程中遇到任何问题,欢迎在评论区留言交流,我会一一回复。