1. K3S 里跑 Jenkins 到底卡在哪从 Pod 起不来聊到 Ingress 404如果你正在用 K3S 搭一套轻量 CI/CDJenkins 大概率是绕不开的一环。K3S 本身把 Kubernetes 的组件裁剪得很干净单节点就能跑资源占用低特别适合个人服务器、边缘节点或者小团队的自建流水线。而 Jenkins 作为老牌持续集成工具插件生态成熟Pipeline 语法稳定两者组合起来就是一套「低成本、可自控」的自动化方案。这篇笔记要解决的核心问题很具体在 K3S 集群里用 Helm 部署 Jenkins通过 Ingress 暴露服务并用 values.yaml 定制持久化和资源限制最后跑通从部署到访问验证的完整闭环。我先把常见的坑摆出来你对照一下是不是也遇到过。第一个坑是镜像拉取失败Pod 一直卡在ImagePullBackOff原因多半是 tag 写错了。Jenkins 官方镜像的 tag 命名有讲究lts-jdk17这种是滚动标签而2.568.3-jdk17这种带具体版本号加 JDK 后缀的写法在部分镜像仓库里根本不存在Helm 渲染出来的镜像地址拉不到就直接失败。第二个坑是ContainerCreating卡住不动这通常是镜像源 DNS 解析或者网络策略的问题K3S 的registries.yaml配置不对就会这样。第三个坑是 Ingress 配好了外网访问却返回 404要么是安全组没放行 80 端口要么是请求没带正确的 Host 头。第四个坑是 values.yaml 格式错误导致helm install直接报错尤其是 Ingress 的 paths 字段多嵌套一层就解析不了。这些问题的共同点是它们都不难但每一个都能让你在部署阶段耗掉半小时。所以这篇笔记不会只给你一堆命令而是把每一步的「为什么」和「出错了怎么查」都写清楚。你跟着操作遇到报错能自己定位这才是运维笔记该有的样子。另外这篇还会多走一步Jenkins 流水线里经常需要调用 AI 能力做代码审查、日志分析或者自动生成变更说明这些步骤需要一个统一的鉴权入口。我会在部署完成后把 TaoToken 的统一 Key 和 API 通道接进 Jenkins 的凭据体系让流水线里的 AI 步骤有一个稳定的调用入口。这部分不是必须的但如果你有类似需求可以照着配。整篇的操作环境是一台装了 K3S 的 Linux 服务器Helm v3.18.4Jenkins Chart 版本 5.9.56Traefik 作为默认 Ingress Controller。下面从 Helm 安装开始一步步来。2. 前置准备Helm 安装、Chart 仓库与 K3S 镜像源配置在 K3S 里部署 JenkinsHelm 是首选工具因为它能把一堆 YAML 模板化values.yaml 一改就能适配不同环境。但 Helm 本身的安装在国内网络环境下容易卡在下载环节所以第一步先把 Helm 装好并且用国内镜像源加速。Helm 的安装命令如下我用的是华为云镜像下载速度比较稳curl -fsSL https://mirrors.huaweicloud.com/helm/v3.18.4/helm-v3.18.4-linux-amd64.tar.gz -o helm.tar.gz tar -xzf helm.tar.gz mv linux-amd64/helm /usr/local/bin/ helm version执行完helm version应该输出v3.18.4如果提示命令找不到检查/usr/local/bin是否在 PATH 里。这一步没什么难度但要注意别从 GitHub 直接拉超时概率很高。Helm 装好后添加 Jenkins 的 Chart 仓库helm repo add jenkins https://charts.jenkins.io helm repo updatehelm repo update会拉取仓库索引如果卡住可以换用--repository-config指定配置或者检查 DNS。仓库添加成功后可以用helm search repo jenkins看看有哪些版本我们后面会指定--version 5.9.56来避免 Chart 版本漂移带来的兼容问题。接下来是 K3S 的镜像源配置这一步很关键因为 Jenkins 镜像默认从 Docker Hub 拉国内环境大概率超时。K3S 的镜像代理配置在/etc/rancher/k3s/registries.yaml你需要确认这个文件里的 endpoint 是否可达。一个典型的配置长这样mirrors: docker.io: endpoint: - https://your-mirror-endpoint注意这里不要写具体的镜像仓库品牌你用自己的内网镜像服务或者云厂商提供的加速地址即可。配置改完后需要重启 K3S 服务systemctl restart k3s。重启后可以用crictl pull jenkins/jenkins:lts-jdk17测试一下能不能拉取如果这个命令能成功后面 Helm 部署就不会卡在镜像拉取上。还有一个容易忽略的点Jenkins Chart 的镜像配置逻辑是repository:tag拼接不要单独去设registry字段。也就是说你在 values.yaml 里写repository: jenkins/jenkins和tag: lts-jdk17Helm 会拼成jenkins/jenkins:lts-jdk17镜像拉取走的是 K3S 全局的 registries.yaml 代理。如果你额外加了 registry 字段反而可能拼出错误的地址。前置准备做到这里就够了Helm 能用、Chart 仓库能访问、镜像能拉取。接下来写 values.yaml这是整个部署的核心。3. 可复制配置values.yaml 定制持久化、资源限制与 Ingress 路由values.yaml 是 Helm 部署的灵魂写对了后面一路顺畅写错了就是各种报错。我把关键配置拆成几块来讲你可以直接复制但建议每一行都看懂再改。先看 controller 部分的镜像和管理员账号配置controller: image: repository: jenkins/jenkins tag: lts-jdk17 admin: username: admin password: admin123 resources: requests: cpu: 500m memory: 512Mi limits: cpu: 1000m memory: 1Gi这里tag: lts-jdk17是重点。我试过写2.568.3-jdk17结果 Pod 直接ImagePullBackOff因为那个 tag 在镜像仓库里不存在。lts-jdk17是官方维护的滚动标签指向最新的 LTS 版本配 JDK17稳定且可用。管理员账号密码先设成admin/admin123部署完立刻改这个不用多说。资源限制这块requests是调度时预留的资源limits是上限。Jenkins 启动时内存占用不低512Mi 的 request 能保证调度成功1Gi 的 limit 防止它吃爆节点。如果你的服务器内存紧张可以把 limit 降到 768Mi但低于 512Mi 容易 OOM。持久化配置在persistence字段persistence: enabled: true size: 10Gi storageClass: local-pathK3S 默认自带local-path这个 StorageClass它会自动创建 PVC 并绑定到本地路径。10Gi 对 Jenkins 来说够用如果你要存大量构建产物可以调大。enabled: true必须写否则 Pod 重启后所有配置和构建记录都会丢。Ingress 配置是外网访问的关键ingress: enabled: true hostName: jenkins.local path: / annotations: {}hostName设成jenkins.local后面访问时要么改本地 hosts要么用 curl 带 Host 头。path: /表示根路径全部路由到 Jenkins 服务。annotations留空即可Traefik 作为 K3S 默认的 Ingress Controller不需要额外注解就能工作。把上面几段拼起来完整的 values.yaml 就是controller: image: repository: jenkins/jenkins tag: lts-jdk17 admin: username: admin password: admin123 resources: requests: cpu: 500m memory: 512Mi limits: cpu: 1000m memory: 1Gi persistence: enabled: true size: 10Gi storageClass: local-path ingress: enabled: true hostName: jenkins.local path: / annotations: {}保存成values.yaml然后创建命名空间并部署kubectl create namespace jenkins helm install jenkins jenkins/jenkins -n jenkins -f values.yaml --version 5.9.56--version 5.9.56指定 Chart 版本避免自动拉到不兼容的新版本。部署命令执行后用kubectl get pods -n jenkins -w观察 Pod 状态正常会经历ContainerCreating到Running最终显示2/2因为 Jenkins Chart 默认会起一个 Jenkins 容器加一个配置容器。等 Pod 变成2/2 Running后检查 Ingresskubectl get ingress -n jenkins输出里应该能看到jenkins.local对应的 ADDRESS 和 HOSTS。如果 ADDRESS 为空等几十秒再查Traefik 分配地址需要一点时间。到这里部署部分就完成了。接下来验证访问。4. 验证请求curl 带 Host 头测试与浏览器访问闭环部署完成后最直接的验证方式是用 curl 带 Host 头请求不需要改本地 hosts 就能确认服务是否正常。先拿到节点的 IP假设是39.107.52.178执行curl -H Host: jenkins.local http://39.107.52.178/如果返回 200 或 302说明 Ingress 路由正常Jenkins 已经能响应请求。302 通常是跳转到登录页属于正常行为。如果返回 404往下看排障部分。确认 curl 通了之后可以在本地 hosts 文件里加一条映射方便浏览器访问。Windows 下用管理员权限编辑C:\Windows\System32\drivers\etc\hostsmacOS 或 Linux 用sudo sh -c echo 39.107.52.178 jenkins.local /etc/hosts加完后浏览器访问http://jenkins.local应该能看到 Jenkins 的登录页标题是 Sign in - Jenkins。用admin/admin123登录首次登录后立刻修改密码。登录进去后可以确认几个关键状态Jenkins 版本是 2.568.3 LTS JDK17预装插件包括 kubernetes、git、gitlab-plugin、blueocean 等持久化存储挂载的是 10Gi 的 PVC。这些信息在「系统管理」里都能看到。如果你不想改 hosts也可以直接用 IP 访问但需要把 Ingress 的 hostName 改成 IP 地址然后重新helm upgrade。不过用域名的方式更灵活后面换 IP 只需要改 hosts 映射。验证通过后建议做一件事在 Jenkins 的凭据管理里加一个 Secret text把 TaoToken 的 API Key 存进去。这样流水线里调用 AI 步骤时可以直接引用这个凭据不用把 Key 硬编码在 Jenkinsfile 里。TaoToken 的 API 地址是https://taotoken.net/api你可以在流水线的 shell 步骤里这样用withCredentials([string(credentialsId: taotoken-key, variable: TAOTOKEN_KEY)]) { sh curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_KEY \ -H Content-Type: application/json \ -d {model:gpt-4o-mini,messages:[{role:user,content:总结本次构建日志}]} }这样 AI 步骤的鉴权就统一走 TaoToken 的 Key换模型或者换通道只需要改凭据不用动流水线代码。如果你还没有 Key可以在 TaoToken 的 API Keys 页面创建一个模型对话入口可以先用起来测试调用是否通。访问验证这一步做完整个部署闭环就完成了。下面把常见的报错整理一下方便你对照排查。5. 常见报错排查ImagePullBackOff、ContainerCreating 与 Ingress 404部署过程中最容易遇到的几个报错我按现象、原因、解决方式列出来你对照着查。Pod 状态 ImagePullBackOff。原因基本是镜像 tag 不存在。Jenkins 官方镜像的 tag 命名规则是lts-jdk17这种滚动标签或者2.568.3-jdk17这种具体版本。但具体版本号加 JDK 后缀的写法在部分镜像仓库里没有同步拉取就会失败。解决方式是把 tag 改成lts-jdk17然后helm upgrade重新部署。如果你用的是私有镜像仓库确认仓库里确实有这个 tag。Pod 状态 ContainerCreating 长时间不结束。这通常是镜像源 DNS 解析失败或者网络不通。检查/etc/rancher/k3s/registries.yaml里的 endpoint 是否可达可以用curl测试那个地址。另外确认 K3S 节点能解析外网域名nslookup docker.io看看有没有返回。如果用了内网镜像服务确认防火墙放行了对应端口。helm install 报错 values.yaml 格式错误。最常见的是 Ingress 的 paths 字段多嵌套了一层。Jenkins Chart 的 Ingress 配置里path是直接写在ingress下面的不要写成paths: - path: /这种列表结构。另外 YAML 的缩进必须用空格不能用 Tab缩进错了也会报解析失败。建议用helm template先渲染一遍看看输出的 YAML 有没有问题helm template jenkins jenkins/jenkins -n jenkins -f values.yaml --version 5.9.56外网访问返回 404。两个常见原因一是安全组没放行 80 端口去云控制台加入方向 TCP/80 规则二是请求没带正确的 Host 头。用 curl 测试时加-H Host: jenkins.local浏览器访问时确认 hosts 文件里加了映射。如果 hosts 加了还是 404检查 Ingress 的 hostName 是否和请求的 Host 一致。Pod 一直 Pending。检查节点资源是否足够kubectl describe pod -n jenkins看 Events 里有没有Insufficient cpu或Insufficient memory。如果有调低 values.yaml 里的 requests 值或者给节点加资源。登录后提示 403 或 CSRF 错误。这通常是 Ingress 的路径重写问题确认path: /没有配错。如果用了子路径需要额外配置jenkinsUriPrefix但本文用的是根路径不涉及这个问题。排查的时候kubectl describe pod和kubectl logs是最有用的两个命令。Pod 起不来先 describe 看 Events容器起来了但服务异常就看 logs。Ingress 的问题用kubectl describe ingress -n jenkins看后端服务是否正确绑定。把这些报错都过一遍基本能覆盖 90% 的部署问题。剩下的就是环境差异导致的个别情况按同样的思路定位即可。6. 把 TaoToken 统一 Key 接进 Jenkins 流水线鉴权入口与调用示例Jenkins 部署好之后真正的价值在于跑流水线。现在很多团队会在 CI 流程里加 AI 步骤比如自动审查代码变更、分析构建失败日志、生成发布说明。这些步骤需要一个稳定的 API 鉴权入口TaoToken 的统一 Key 就是干这个的。配置方式很简单在 Jenkins 的「凭据」页面新建一个 Secret textID 填taotoken-key值填你在 TaoToken 控制台创建的 API Key。然后在 Jenkinsfile 里用withCredentials引用pipeline { agent any stages { stage(AI Review) { steps { withCredentials([string(credentialsId: taotoken-key, variable: TAOTOKEN_KEY)]) { sh curl -s -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_KEY \ -H Content-Type: application/json \ -d { model: claude-3-5-sonnet, messages: [ {role: user, content: 审查以下代码变更指出潜在问题$(git diff HEAD~1)} ] } | jq -r .choices[0].message.content } } } } }这段 Pipeline 做了三件事从凭据里取 Key、调用 TaoToken 的 API 通道、用 jq 提取返回内容。模型 ID 可以按需换TaoToken 支持多种模型你可以在模型对话页面测试不同模型的效果再决定流水线里用哪个。如果你用的是 Coding Plan 或者需要长期跑 Agent 任务建议把 Key 的权限和配额单独管理避免流水线里的调用影响到其他业务。TaoToken 的控制台可以创建多个 Key按用途区分这样排查问题时也清晰。还有一个实用技巧把 AI 步骤的调用封装成一个共享库这样多个 Jenkinsfile 都能复用不用每个项目都写一遍 curl。共享库的写法这里不展开核心就是把withCredentials和 curl 调用包在一个vars/aiReview.groovy里流水线里直接aiReview()调用。接入完成后你的 Jenkins 流水线就有了一个统一的 AI 鉴权入口。后续换模型、换通道、调配额都只需要在 TaoToken 侧操作Jenkins 这边不用改。这对于需要长期维护的 CI/CD 系统来说能省不少事。最后提醒一句API Key 不要硬编码在 Jenkinsfile 或者脚本里一定走凭据管理。另外流水线里的 AI 调用建议加超时和重试避免网络波动导致构建卡住。这些细节配好了整套系统才算真正可用。