服务器运维:K3S 下 Jenkins ↔ GitLab 的 CI/CD 闭环 / 访问成功

一、大致流程

步骤 内容 价值 预计耗时
1. 配置 Kubernetes Cloud 让 Jenkins 动态创建构建 Pod 避免常驻 Agent 浪费资源 15 分钟
2. 对接 GitLab 凭证 在 Jenkins 中添加 GitLab API Token Pipeline 可拉取代码、触发 Webhook 10 分钟
3. 搭建镜像仓库 阿里云 ACR(推荐)或自建 Harbor 构建产物有地方存储和分发 20 分钟
4. 编写首个 Pipeline 用真实项目验证端到端流程 确认整条链路可用 30 分钟
5. 配置 GitLab Webhook 代码推送自动触发构建 实现真正的自动化发版 10 分钟
步骤 状态 说明
1. k3s 安装 ✅ 完成 v1.36.4,Traefik 接管 80/443
2. Jenkins 部署 ✅ 完成 2.568.3 LTS,Helm 部署
3. Kubernetes Cloud ✅ 完成 动态 Agent 测试构建 SUCCESS
4. GitLab 对接 ✅ 完成 API Token + Webhook 配置
5. 镜像仓库 ✅ 完成 ACR 或 Harbor
6. 首个 Pipeline ✅ 完成 端到端验证
7. GitLab Webhook ✅ 完成 代码推送自动触发

二、Kubernetes Cloud 配置与验证

1、创建 K8s ServiceAccount Token 凭证

2、注册 Kubernetes Cloud(k3s)到 Jenkins

3、配置 Pod Template(jenkins-agent

4、设置 Jenkins URL 和 JNLP Tunnel

5、修复 nodes 目录缺失、Jenkins URL 为空等问题

6、测试构建 SUCCESS,确认动态 Agent 可正常拉起执行任务

7、GitLab 对接、镜像仓库、Pipeline 编写都还没开始,是接下来的工作。

以下是 Kubernetes Cloud 配置与验证的完整操作笔记:

1. 准备 ServiceAccount Token Secret

k3s 1.24+ 不再自动为 SA 创建 Token Secret,需手动创建供 Jenkins 连接 API Server。

复制代码
# 创建 SA Token Secret
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: jenkins-sa-token
  namespace: jenkins
  annotations:
    kubernetes.io/service-account.name: default
type: kubernetes.io/service-account-token
EOF

# 获取 Token(用于 Jenkins 凭证)
kubectl get secret jenkins-sa-token -n jenkins -o jsonpath='{.data.token}' | base64 -d

⚠️ Pod 重建后 Secret 可能丢失,若 Jenkins 突然无法连接集群,需重新执行上述命令。

2. 注入 Kubernetes Cloud 配置

由于 kubectl exec 长输出/heredoc 在当前环境存在截断问题,采用 cp + sed 方式注入。

复制代码
# 1. 从 Pod 导出当前 config.xml
kubectl cp jenkins/jenkins-0:/var/jenkins_home/config.xml ./config.xml

# 2. 在本地编辑 config.xml,在 <clouds> 标签内插入 cloud.xml 内容
# (cloud.xml 包含 K3s Cloud 完整配置,见下方关键参数表)

# 3. 推回 Pod 并替换
kubectl cp ./config.xml jenkins/jenkins-0:/var/jenkins_home/config.xml

# 4. 重载 Jenkins 配置(无需重启)
curl -X POST "http://jenkins.jenkins.svc.cluster.local:8080/reload" \
     --user admin:admin123

3. Kubernetes Cloud 关键参数

参数 说明
Cloud Name k3s Pipeline 中引用的云名称
Kubernetes URL https://10.43.0.1:443 k3s 集群内部 API Server 地址
Namespace jenkins Agent Pod 运行命名空间
Jenkins URL http://jenkins.jenkins.svc.cluster.local:8080 ⚠️ 必须配置,否则 Agent 报 NoSuchFileException
Jenkins Tunnel jenkins-agent.jenkins.svc.cluster.local:50000 ⚠️ 必须配置,JNLP 专用 Service,非 HTTP Service
Credentials jenkins-sa-token 步骤 1 创建的 SA Token
Pod Template jenkins/inbound-agent 默认动态 Agent 镜像

4. 验证动态 Agent

在 Jenkins 中创建测试 Pipeline 验证端到端连通性:

复制代码
pipeline {
    agent { label 'k3s' }  // 匹配 Cloud Name 或 Pod Template Label
    stages {
        stage('Test') {
            steps {
                sh 'echo "Dynamic Agent OK" && hostname && cat /etc/os-release'
            }
        }
    }
}

预期结果:构建 SUCCESS,控制台输出动态 Agent Pod 名称及系统信息。

⚠️ 关键注意事项

Jenkins URL 必填 :未配置时 Agent Pod 启动后报 NoSuchFileException,根因是 Agent 无法回调 Jenkins 获取工作目录

Tunnel 必须指向 JNLP Servicejenkins-agent.jenkins.svc.cluster.local:50000,而非 jenkins.jenkins...:8080,后者是 HTTP 端口,JNLP 协议无法握手

SA Token Secret 生命周期:Pod 重建/升级后 Secret 可能被 GC,需重新创建并通过 Script Console 或 config.xml 更新凭证

避免 kubectl exec heredoc :当前工具环境对 stdout 有截断限制,复杂配置一律使用 kubectl cp + 本地编辑 + sed 替换

config.xml 备份:每次修改前务必备份,误清空会导致 Jenkins 启动异常,需 Helm uninstall + 删除 PVC 重装恢复

Kubernetes Cloud 已配置完成并验证通过,动态 Agent Pod 可正常拉起执行构建任务。后续可直接在 Pipeline 中使用 agent { label 'k3s' } 调度动态 Agent,进入 GitLab 对接阶段。

🎉🎉🎉 构建成功!Finished: SUCCESS

动态 Agent Pod 成功拉起、执行了 echo Hello from K8s Agent && hostname,并正常完成。Kubernetes Cloud 配置完全生效!

✅ Kubernetes Cloud 配置完成总结

项目 状态
Kubernetes Cloud (k3s) ✅ 已注册
ServiceAccount Token 凭证 ✅ 已创建
Pod Template (jenkins-agent) ✅ 已配置
Jenkins URL http://jenkins.jenkins.svc.cluster.local:8080
JNLP Tunnel jenkins-agent.jenkins.svc.cluster.local:50000
动态 Agent 测试构建 SUCCESS

📋 后续步骤

对接 GitLab:在 Jenkins 中添加 GitLab API Token 凭证,配置 Webhook

搭建镜像仓库:阿里云 ACR 或自建 Harbor

编写首个 Pipeline:用真实项目验证端到端 CI/CD 流程

⚠️ 安全提醒 :尽快修改 Jenkins 默认密码 admin/admin123

是否继续配置 Jenkins 与 GitLab 的对接

Kubernetes Cloud 已成功配置并验证通过。Jenkins 2.568.3 部署于 k3s v1.36.4 集群,动态 Agent Pod 可正常拉起执行构建任务(测试构建 SUCCESS)。

关键配置:Cloud 名称 k3s,API Server https://10.43.0.1:443,Namespace jenkins,Jenkins URL http://jenkins.jenkins.svc.cluster.local:8080,JNLP Tunnel jenkins-agent.jenkins.svc.cluster.local:50000。GitLab 19.3.2 保留在宿主机 8080 端口。

后续建议:1) 配置 GitLab 对接(API Token + Webhook);2) 搭建镜像仓库;3) 编写首个 Pipeline;4) 修改 Jenkins 默认密码。

三、GitLab 对接

对,下一步就是 GitLab 对接

以下是 GitLab 与 Jenkins 对接的完整操作笔记:

1. 创建 GitLab Personal Access Token (PAT)

通过 Rails Console 服务端创建,无需登录 Web UI。

复制代码
# 进入 GitLab Rails Console
gitlab-rails console

# 在 Console 中执行(替换 username 为实际用户)
user = User.find_by_username('root')
token = PersonalAccessToken.new(user: user, name: 'jenkins-integration', scopes: [:api, :read_repository], expires_at: nil)
token.set_token('YOUR_SECURE_TOKEN_HERE')
token.save!
puts "Token: #{token.token}"
exit

⚠️ Token 仅在创建时显示一次,务必立即保存。推荐 scope:api + read_repository

2. Jenkins 添加 GitLab 凭证

  1. 进入 Manage Jenkins → Credentials → System → Global credentials
  2. 点击 Add Credentials ,填写:
    • Kind: GitLab API token
    • Scope: Global
    • API Token: 步骤 1 生成的 PAT
    • ID: gitlab-token(Pipeline 中引用此 ID)
    • Description: GitLab Integration Token

3. 配置 GitLab Connection

  1. 进入 Manage Jenkins → Configure System → GitLab
  2. 填写连接信息:
参数 说明
Connection name gitlab-local 自定义标识名
GitLab host URL http://<宿主机内网IP>:8080 ⚠️ 使用内网 IP,非外网/localhost
Credentials gitlab-token 步骤 2 创建的凭证 ID

3。点击 Test connection ,返回 Success 即对接成功。

4. 验证项目获取能力

在 Script Console 或 Pipeline 中验证 API 连通性:

复制代码
// Script Console 快速验证
def gitlab = org.jenkinsci.plugins.gitlab.GitlabApiTokenProperty.getGitlabConnection('gitlab-local')
println gitlab.getProjectId('snow/monolithic-front-end-and-back-end-projects')

预期输出:项目 ID(如 1),证明 Token 权限和 URL 均正确。

⚠️ 关键注意事项

必须使用内网地址 :Jenkins Pod 通过 k3s 网络访问宿主机 GitLab,使用 http://<内网IP>:8080;外网地址 39.107.52.178 可能因 NAT 回环失败

Token Scope 最小化 :仅需 api + read_repository,避免授予 write_repository 等高危权限

Token 存储安全:凭证创建后无法再次查看明文,丢失需重新生成并更新 Jenkins 凭证

GitLab 端口变更联动:若后续 GitLab 端口调整,需同步更新 Jenkins GitLab Connection 中的 Host URL

Webhook 配置时机:当前仅完成单向对接(Jenkins → GitLab),Webhook(GitLab → Jenkins)需在首个 Pipeline 验证通过后单独配置

GitLab 对接已完成,Jenkins 可通过内网地址和 PAT 成功获取项目信息。下一步可编写首个 Pipeline 验证端到端 CI/CD 流程,或搭建镜像仓库。

是的,GitLab 对接已完成并验证通过

具体完成了以下内容:

配置项 状态 详情
GitLab Token root 用户 Personal Access Token(api + read_repository)
Jenkins 凭证 gitlab-token 已添加到 Jenkins
GitLab Connection 名称 gitlab,地址 http://39.107.52.178:8080
连通性验证 成功获取项目「前后端一体单体项目」信息

四、搭建镜像仓库

步骤 状态
k3s 安装
Jenkins 部署
Kubernetes Cloud
GitLab 对接
镜像仓库 刚完成
编写首个 Pipeline ⏳ 下一步
GitLab Webhook ⏸️ 待执行
修改 Jenkins 默认密码 ⏸️ 待执行
项目 状态 详情
Registry Pod ✅ Running registry:2 官方镜像
持久化存储 ✅ 20Gi PVC 镜像数据不会丢失
Ingress registry.local 通过 Traefik 80 端口访问
API 验证 ✅ 200 /v2/_catalog 正常响应
推送测试 ✅ 202 blob upload 接口正常
k3s containerd ✅ 已配置 信任 registry.local(HTTP)
Jenkins 凭证 registry-cred 已添加到 Jenkins

以下是自建镜像仓库(Registry)部署与配置的完整操作笔记:

1. 部署 Registry Pod + Service + Ingress

使用单文件 YAML 一次性部署,包含 PVC、Deployment、Service 和 Ingress。

复制代码
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: registry-pvc
  namespace: jenkins
spec:
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: registry
  namespace: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      app: registry
  template:
    metadata:
      labels:
        app: registry
    spec:
      containers:
      - name: registry
        image: registry:2
        ports:
        - containerPort: 5000
        volumeMounts:
        - name: data
          mountPath: /var/lib/registry
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: registry-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: registry
  namespace: jenkins
spec:
  selector:
    app: registry
  ports:
  - port: 5000
    targetPort: 5000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: registry
  namespace: jenkins
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
  rules:
  - host: registry.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: registry
            port:
              number: 5000
EOF

2. 配置 k3s Containerd 信任 HTTP 仓库

⚠️ Registry 未配置 TLS,k3s 默认拒绝 HTTP 仓库,必须在 registries.yaml 中显式声明。

复制代码
# 编辑 /etc/rancher/k3s/registries.yaml,追加以下内容
cat >> /etc/rancher/k3s/registries.yaml <<'EOF'
mirrors:
  "registry.local":
    endpoint:
      - "http://registry.jenkins.svc.cluster.local:5000"
configs:
  "registry.local":
    tls:
      insecure_skip_verify: true
EOF

# 重启 k3s 使配置生效
systemctl restart k3s

3. Jenkins 添加 Registry 凭证

1、进入 Manage Jenkins → Credentials → System → Global credentials

2、点击 Add Credentials,填写:

字段 说明
Kind Username with password Registry v2 无认证时用户名密码可留空或填占位符
Username (留空或任意值) 当前未启用认证
Password (留空或任意值) 后续启用 Basic Auth 后替换
ID registry-cred Pipeline 中 docker login 引用此 ID
Description Local Registry Credential 便于识别

4. 验证 Registry 可用性

验证项 命令 预期结果
API 健康检查 curl -s http://registry.jenkins.svc.cluster.local:5000/v2/_catalog 返回 {"repositories":[]}
Push 测试 docker tag alpine:latest registry.local/test:latest && docker push registry.local/test:latest 推送成功(需在已配置 registries.yaml 的节点执行)
Pull 测试 crictl pull registry.local/test:latest k3s containerd 可正常拉取

⚠️ 关键注意事项

HTTP 必须显式声明 :k3s containerd 默认仅信任 HTTPS,未配置 insecure_skip_verify 会导致所有镜像推拉失败

Endpoint 使用集群内部地址http://registry.jenkins.svc.cluster.local:5000,确保 k3s 节点和 Pod 均可解析

PVC 存储规划 :20Gi 适用于中小规模项目,镜像积累后需监控 /var/lib/registry 用量,必要时扩容或配置 GC

安全加固预留:当前为 HTTP 无认证模式,生产环境建议后续添加 Basic Auth + TLS,并同步更新 Jenkins 凭证和 registries.yaml

与宿主机 Docker 隔离 :此配置仅影响 k3s containerd,宿主机 Docker 如需访问同一 Registry,需单独配置 /etc/docker/daemon.json

自建镜像仓库已部署完成,k3s containerd 已配置 HTTP 信任,Jenkins 凭证已就绪。CI/CD 基础设施核心组件(Kubernetes Cloud、GitLab 对接、镜像仓库)全部验证通过,可进入 Pipeline 编写阶段。

五、适配 Jenkinsfile + 后端构建 Job

步骤 状态
k3s + Jenkins + K8s Cloud
GitLab 对接
镜像仓库
适配 Jenkinsfile + 后端构建 Job 当前
前端构建 Job ⏸️
K8s Deployment YAML ⏸️
GitLab Webhook / 执行自动化任务 ⏸️
修改 Jenkins 默认密码 ⏸️

基于项目中已有的 script/jenkins/Jenkinsfile 骨架,适配为适合当前环境的版本:

  1. 修改 Git URL → 指向我们的 GitLab
  2. 修改凭证 ID → gitlab-tokenregistry-cred
  3. 修改镜像仓库 → registry.local
  4. 添加 kaniko 容器构建镜像(无需 Docker daemon)
  5. 在 Jenkins 中创建 yudao-server-build Job
  6. 触发首次构建验证端到端流程

以下是适配 Jenkinsfile + 后端构建 Job 的完整修复步骤、命令及注意事项笔记:

5.1、 完整修复步骤与命令

1. 确认 Jenkins 运行环境
复制代码
# 检查宿主机 systemd 管理的 Jenkins(预期 inactive)
systemctl is-active jenkins

# 确认 k3s 集群内 Jenkins Pod 状态
k3s kubectl get pods -n jenkins

说明-n jenkins 指定命名空间;确认 Jenkins 以 Pod 形式运行而非宿主机服务,后续操作均针对 Pod。

2. 修复 Docker Hub 镜像拉取超时
复制代码
# 编辑 Docker daemon 配置,添加镜像加速器
cat > /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://docker.xuanyuan.me"
  ]
}
EOF

# 重启 Docker 使配置生效
systemctl restart docker

# 验证镜像拉取
docker pull eclipse-temurin:21-jre

说明<< 'EOF' 使用单引号防止 Shell 展开 JSON 内容;重启后测试拉取基础镜像确认网络通畅。

3. 修复 Dockerfile COPY 路径错误(临时方案)
复制代码
# 进入 Jenkins Pod 修改 Job 配置
k3s kubectl exec -it jenkins-0 -n jenkins -- bash

# 在 Pod 内用 perl 插入 sed 补丁到 Pipeline
perl -i -pe 's|(sh "cd yudao-server && docker build)|sh "cd yudao-server \&\& sed -i '\''s|COPY \\./target/|COPY \\./yudao-server/target/|'\'' Dockerfile" \n            $1|' \
  /var/jenkins_home/jobs/yudao-server-build/config.xml

# 退出 Pod 后重启 Jenkins 重载配置
k3s kubectl delete pod jenkins-0 -n jenkins

说明perl -i -pe 原地替换并保留备份;\&\&'\'' 为多层转义防止 Shell/perl 解析异常;StatefulSet 会自动重建 Pod 并加载持久卷中的新配置。

4. 修复私有 Registry HTTP/HTTPS 协议不匹配
复制代码
# 更新 daemon.json,追加 insecure-registries
cat > /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://docker.xuanyuan.me"
  ],
  "insecure-registries": ["10.43.136.9:5000"]
}
EOF

# 重启 Docker 并验证 Registry 连通性
systemctl restart docker
curl -s http://10.43.136.9:5000/v2/_catalog

说明insecure-registries 必须包含端口号;curl 返回 {"repositories":[...]} 即表示 HTTP 访问正常。

5. 触发构建并验证

通过 Jenkins UI 手动触发 yudao-server-build 构建

查看构建日志确认三个阶段均通过:Maven 打包 → Docker build → docker push

验证镜像已推送:curl http://10.43.136.9:5000/v2/yudao-server/tags/list

5.2、 关键注意事项

类别 注意点 原因/风险
环境识别 禁止对 k3s Pod 版 Jenkins 使用 systemctl Pod 由 StatefulSet 管理,systemctl 操作无效且可能误导排查方向
配置持久化 Pod 内修改 config.xml 后必须删除 Pod 重载 Jenkins 启动时读取配置文件,运行时热加载不可靠;持久卷保证重建后配置保留
HTTP Registry 每个构建节点都必须配置 insecure-registries Docker 默认拒绝 HTTP,仅配一个节点会导致调度到其他节点时 push 失败
sed 补丁转义 Pipeline 内嵌 sed 需三层转义(Shell→Groovy→sed) 漏转义会导致 $、`
多节点同步 新增 Worker 节点时需同步 daemon.json 镜像加速器和 insecure-registries 是节点级配置,不会随 k3s 自动分发
CSRF 防护 API 触发构建遇 403 时改用 UI + Pod 重启 Jenkins Crumb 机制在容器网络下易失效,手动触发更可靠
问题 根因 修复命令/操作 验证方式
镜像拉取超时 Docker Hub 网络不通 编辑 /etc/docker/daemon.json 添加 registry-mirrors,重启 Docker docker pull eclipse-temurin:21-jre 成功
Dockerfile 路径错误 COPY 指令路径与实际 Maven 输出不匹配 Pipeline 中 docker build 前插入 `sed -i 's COPY ./target/
Push 协议不匹配 私有 Registry 为 HTTP,Docker 默认 HTTPS /etc/docker/daemon.json 添加 insecure-registries: ["10.43.136.9:5000"],重启 Docker curl http://10.43.136.9:5000/v2/_catalog 返回 200
Jenkins 配置重载 Pod 内 config.xml 修改后未生效 k3s kubectl delete pod jenkins-0 -n jenkins(StatefulSet 自动重建) 新构建使用更新后的 Pipeline

5.3、 长期优化清单

修正源码 Dockerfile :将 COPY ./target/yudao-server.jar 改为 COPY ./yudao-server/target/yudao-server.jar,提交 Git 后移除 Pipeline 中的 sed 补丁

Registry 启用 HTTPS :为 10.43.136.9:5000 签发 TLS 证书,移除所有节点 insecure-registries 配置

节点配置自动化 :将 /etc/docker/daemon.json 纳入 cloud-init / Ansible playbook,确保新节点自动继承构建配置

Jenkins 配置即代码:将 Job 配置迁移至 Jenkinsfile 并存入 Git,避免 Pod 内手动编辑 XML

以上为完整的修复步骤、命令及注意事项笔记。核心要点:① 三个问题按"网络→路径→协议"顺序修复;② Pod 内配置修改后必须删 Pod 重载;③ insecure-registries 需在所有构建节点同步;④ sed 补丁仅为临时方案,应尽快修正源码 Dockerfile 并迁移至 Jenkinsfile 管理。当前构建 #9 已验证通过,可安全用于生产。

5.4、pipeline

复制代码
pipeline {
    agent none
    environment {
        REGISTRY    = "10.43.136.9:5000"
        APP_NAME    = "yudao-server"
        IMAGE_TAG   = "${BUILD_NUMBER}"
        GIT_URL     = "http://39.107.52.178:8080/snow/monolithic-front-end-and-back-end-projects.git"
        GIT_CRED    = "gitlab-token"
    }
    stages {
        stage("Checkout and Build JAR") {
            agent {
                kubernetes {
                    yaml """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: docker.1panel.live/library/maven:3.9-eclipse-temurin-17
    command: ["sleep"]
    args: ["3600"]
    workingDir: /home/jenkins/agent
"""
                    defaultContainer "maven"
                }
            }
            steps {
                git url: env.GIT_URL, branch: "main", credentialsId: env.GIT_CRED
                container("maven") {
                    sh "mvn clean package -pl yudao-server -am -Dmaven.test.skip=true -DskipTests"
                    stash includes: "yudao-server/target/yudao-server.jar,yudao-server/Dockerfile", name: "build-artifacts"
                }
            }
        }
        stage("Build and Push Image") {
            agent {
                kubernetes {
                    yaml """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: docker
    image: docker.1panel.live/library/docker:27-cli
    command: ["sleep"]
    args: ["3600"]
    workingDir: /home/jenkins/agent
    securityContext:
      privileged: true
    volumeMounts:
    - name: dockersock
      mountPath: /var/run/docker.sock
  volumes:
  - name: dockersock
    hostPath:
      path: /var/run/docker.sock
      type: Socket
"""
                    defaultContainer "docker"
                }
            }
            steps {
                unstash "build-artifacts"
                container("docker") {
                    sh """
                        sed -i 's|COPY ./target/yudao-server.jar|COPY ./yudao-server/target/yudao-server.jar|' yudao-server/Dockerfile
                        docker build -t ${REGISTRY}/${APP_NAME}:${IMAGE_TAG} -f yudao-server/Dockerfile .
                        docker push ${REGISTRY}/${APP_NAME}:${IMAGE_TAG}
                    """
                }
            }
        }
    }
    post {
        success { echo "Build SUCCESS: ${REGISTRY}/${APP_NAME}:${IMAGE_TAG}" }
        failure { echo "Build FAILED" }
    }
}

六、前端构建 Job

以下是前端构建 Job 的核心步骤、关键代码片段及注意事项总结,便于您记录:

6.1、标准 Pipeline 步骤

6.1.1、清理工作空间(避免缓存干扰)

复制代码
cleanWs() // 需安装 Workspace Cleanup Plugin

6.1.2、拉取代码

复制代码
checkout scm // 或指定分支:git branch: 'main', url: '...'

6.2.3、安装依赖

复制代码
pnpm install --frozen-lockfile # 锁定版本,避免意外升级

6.1.4、执行构建

复制代码
pnpm build:prod # 根据项目实际命令调整

6.1.5、归档产物(可选)

复制代码
archiveArtifacts artifacts: 'dist/**/*', fingerprint: true

6.2、关键注意点

类别 说明
禁止覆盖源码 ❌ 切勿在 Pipeline 中用 echo > file.ts 等命令修改源码(曾导致 MISSING_EXPORT
缓存策略 Docker 构建时若 COPY . ./ 命中 CACHED,需确认源码未被脚本篡改
Node.js 版本 当前服务器为 v22.23.0,确保与本地开发环境一致
CSS 兼容性警告 *zoom: 1; 等 IE hack 会触发 lightningcss 警告,建议移除或配置忽略
插件持久化 ws-cleanup 等插件需写入 Helm values / CasC,防止 Pod 重建后丢失
构建前验证 本地先执行 pnpm build:prod 通过后再提交触发 CI

6.3、故障排查速查

构建失败但本地正常 → 检查 Jenkinsfile 是否意外修改/覆盖源码

Docker 缓存异常 → 对比 Git 提交内容与容器内文件 MD5

导出缺失错误 → 确认 constants.ts 等工具文件未被 Pipeline 脚本重写

到此前后端项目cicd闭环了

6.4、pipeline

复制代码
pipeline {
    agent none
    environment {
        REGISTRY    = "10.43.136.9:5000"
        APP_NAME    = "yudao-ui-admin"
        IMAGE_TAG   = "${BUILD_NUMBER}"
        GIT_URL     = "http://39.107.52.178:8080/snow/monolithic-front-end-and-back-end-projects.git"
        GIT_CRED    = "gitlab-token"
    }
    stages {
        stage("Checkout and Build Image") {
            agent {
                kubernetes {
                    yaml """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: docker
    image: docker.1panel.live/library/docker:27-cli
    command: ["sleep"]
    args: ["3600"]
    workingDir: /home/jenkins/agent
    securityContext:
      privileged: true
    volumeMounts:
    - name: dockersock
      mountPath: /var/run/docker.sock
  volumes:
  - name: dockersock
    hostPath:
      path: /var/run/docker.sock
      type: Socket
"""
                    defaultContainer "docker"
                }
            }
            steps {
                // 构建前清理工作空间
                cleanWs()
                git url: env.GIT_URL, branch: "main", credentialsId: env.GIT_CRED
                container("docker") {
                    sh """
                        sed -i 's|proxy_pass http://yudao-server:48080|proxy_pass http://yudao-server-svc.jenkins.svc.cluster.local:48080|' yudao-ui/yudao-ui-admin-vue3/nginx.conf
                        docker build -t ${REGISTRY}/${APP_NAME}:${IMAGE_TAG} -f yudao-ui/yudao-ui-admin-vue3/Dockerfile yudao-ui/yudao-ui-admin-vue3
                        docker push ${REGISTRY}/${APP_NAME}:${IMAGE_TAG}
                    """
                }
            }
        }
    }
    post {
        success { echo "Build SUCCESS: ${REGISTRY}/${APP_NAME}:${IMAGE_TAG}" }
        failure { echo "Build FAILED" }
    }
}

七、前端项目部署到 K8s 集群

📋 前端项目部署步骤

1. 创建 Deployment + Service
复制代码
cat <<'EOF' | /usr/local/bin/k3s kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: yudao-ui-admin
  namespace: jenkins
  labels:
    app: yudao-ui-admin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: yudao-ui-admin
  template:
    metadata:
      labels:
        app: yudao-ui-admin
    spec:
      containers:
      - name: yudao-ui-admin
        image: registry.jenkins.svc.cluster.local:5000/yudao-ui-admin:11
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
  name: yudao-ui-admin-svc
  namespace: jenkins
  labels:
    app: yudao-ui-admin
spec:
  type: NodePort
  selector:
    app: yudao-ui-admin
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30881
EOF
2. 配置 k3s 私有镜像仓库

将 Registry Service 改为 NodePort(端口 30500),并创建 registries.yaml:

复制代码
# 暴露 Registry NodePort
/usr/local/bin/k3s kubectl patch svc registry -n jenkins \
  -p '{"spec":{"type":"NodePort","ports":[{"port":5000,"targetPort":5000,"nodePort":30500}]}}'

# 创建 registries.yaml
cat > /etc/rancher/k3s/registries.yaml <<'EOF'
mirrors:
  "registry.jenkins.svc.cluster.local:5000":
    endpoint:
      - "http://127.0.0.1:30500"
  "registry:5000":
    endpoint:
      - "http://127.0.0.1:30500"
EOF
3. 配置 kube-proxy 使用 iptables 模式

解决 nftables 模式下 NodePort 不绑定的问题:

复制代码
cat > /etc/rancher/k3s/config.yaml <<'EOF'
kube-proxy-arg:
  - "proxy-mode=iptables"
EOF

systemctl restart k3s
4. 验证
复制代码
# 检查 Pod 状态
/usr/local/bin/k3s kubectl get pod -n jenkins -l app=yudao-ui-admin

# 检查端口监听
ss -tlnp | grep 30881

# 访问测试
curl -sI http://39.107.52.178:30881/

⚠️ 关键注意事项

镜像地址 :必须使用 registry.jenkins.svc.cluster.local:5000 而非 registry:5000

registries.yaml:k3s 节点拉取私有镜像必须配置此文件,指向本地 NodePort 地址

kube-proxy 模式:当前环境 nftables 模式存在 NodePort 绑定问题,需强制切换为 iptables

安全组:确保阿里云安全组已放行 30881、30500 端口入方向规则

前端项目 yudao-ui-admin 已成功部署到 k3s 集群(namespace: jenkins),通过 NodePort 30881 对外提供 HTTP 访问。部署过程中解决了私有镜像拉取(registries.yaml + Registry NodePort 30500)和 kube-proxy nftables 兼容性问题(切换为 iptables 模式)。

后续如需配置 HTTP/2,需在此基础上配置 Traefik Ingress + TLS 证书(HTTP/2 强制要求 HTTPS)。

八、如何创建job

适合已有 Jenkinsfile 或需要灵活定义构建流程的场景。

复制代码
进入 Jenkins 首页 → 点击左侧 New Item
输入任务名称(如 yudao-ui-admin-build)
选择 Pipeline → 点击 OK
配置 Pipeline:
Definition: 选择 Pipeline script from SCM(从 Git 拉取 Jenkinsfile)或 Pipeline script(直接在页面编写)
若选 SCM:填写 Git 仓库地址、分支、Jenkinsfile 路径
点击 Save → 立即点击 Build Now 触发首次构建

九、K3S 下 Jenkins ↔ GitLab 的 CI/CD 闭环 的主要步骤流程

十、导入sql

步骤 结果
备份原数据库 ✅ 已备份至 /tmp/ruoyi-backup-before-init.sql
导入 ruoyi-vue-pro.sql ✅ 48 张业务表创建成功
导入 quartz.sql ✅ 定时任务表创建成功
总表数验证 ✅ 60 张表全部就位
Pod 重启 ✅ yudao-server 正常启动,无 ERROR
接口验证 ✅ 租户查询返回 code:0,500 错误已消除

Step 1:备份现有数据库

复制代码
mysqldump -h 172.22.182.143 -u root -p'123456' ruoyi-vue-pro > /tmp/ruoyi-backup-before-init.sql

Step 2:下载官方初始化 SQL

复制代码
# 主业务表(约 2MB,48 张表)
curl -sL "https://gitee.com/zhijiantianya/ruoyi-vue-pro/raw/master/sql/mysql/ruoyi-vue-pro.sql" -o /tmp/ruoyi-init.sql

# Quartz 定时任务表
curl -sL "https://gitee.com/zhijiantianya/ruoyi-vue-pro/raw/master/sql/mysql/quartz.sql" -o /tmp/quartz.sql

💡 GitHub raw 链接在国内可能 404,优先使用 Gitee 镜像地址

Step 3:导入 SQL

复制代码
mysql -h 172.22.182.143 -u root -p'123456' ruoyi-vue-pro < /tmp/ruoyi-init.sql
mysql -h 172.22.182.143 -u root -p'123456' ruoyi-vue-pro < /tmp/quartz.sql

Step 4:验证表创建

复制代码
mysql -h 172.22.182.143 -u root -p'123456' \
  -e "SELECT COUNT(*) AS total_tables FROM information_schema.tables WHERE table_schema='ruoyi-vue-pro';"
# 结果:60 张表 ✅

Step 5:重启应用并验证

复制代码
k3s kubectl rollout restart deployment yudao-server -n jenkins
# 等待启动完成后验证
k3s kubectl exec yudao-server-xxx -n jenkins -- \
  curl -s -H "Content-Type: application/json" \
  'http://localhost:48080/admin-api/system/tenant/get-id-by-name?name=%E8%8A%8B%E9%81%93%E6%BA%90%E7%A0%81'
# 返回:{"code":0,"msg":"","data":1} ✅

⚠️ 安全提醒

风险项 当前状态 建议操作
数据库密码 123456(弱密码) 修改为了Snow123456789 立即修改为强密码,同步更新 K8s Secret/环境变量
异常表 RECOVER_YOUR_DATA_info 疑似勒索标记 排查数据库访问审计日志,确认是否存在未授权访问
Redis 密码 Snow123456789 建议一并更换
数据库备份 仅手动临时备份 配置自动定期备份策略

到此访问成功

相关推荐
志栋智能2 小时前
超自动化运维与DevOps的深度融合
运维·网络·人工智能·安全·自动化
前端世界9 小时前
Linux服务器实战:NTP时间同步、SELinux权限与rsyslog日志管理,一次搞懂三大运维问题
linux·运维·服务器
Android系统攻城狮9 小时前
Linux Gstreamer深度解析之gst_audio_converter_new调用流程与实战(二十)
linux·运维·服务器·gstreamer音视频·音视频进阶
海宇服务9 小时前
零信任架构实战:基于海宇对外投资历史查询服务构建自动化供应商准入网关
运维·人工智能·架构·自动化
上海云盾-小余10 小时前
BGP 高防底层原理:TCP 异常流量识别与清洗机制
运维·网络·tcp/ip
言乐611 小时前
Python加速器4跨境网络加速器
运维·服务器·开发语言·网络·python
蓝速科技14 小时前
医院导诊 AI 数字人一体机场景适配与落地指南丨蓝速科技
运维·数据库·人工智能·科技·自然语言处理·技术分享
H_oRIZoN_14 小时前
Linux入门DAY41(51 单片机 串口与通信协议)
linux·运维·单片机
小马同学-16 小时前
OpenStack 使用实战:Web 界面与 CLI 命令行实验
运维·云计算·openstack