You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kubernetes环境Jenkins流水线/var/jenkins_home写入权限问题求助

问题描述

Jenkins或容器进程尝试写入/var/jenkins_home时缺少必要的文件系统权限。在Kubernetes上运行的Jenkins流水线通过共享podTemplate动态定义容器和卷,其中一个阶段使用Jenkins的withCredentials步骤绑定GCP服务账号密钥文件(类型为Secret file),执行gcloud auth activate-service-account --key-file=$GCLOUD_KEY完成谷歌云认证。

尽管已将/var/jenkins_home挂载为emptyDirVolume,但流水线在尝试访问$GCLOUD_KEY时仍失败,报错:

hudson.remoting.ProxyException: java.nio.file.AccessDeniedException: /var/jenkins_home

日志显示credentials-binding插件尝试将密钥文件写入$JENKINS_HOME(默认路径为/var/jenkins_home),但因写入权限不足导致文件创建失败。尝试将流水线限定在dir("${WORKSPACE}")范围内指定可写路径,但Jenkins内部仍指向$JENKINS_HOME,未能解决问题。容器以root用户运行,但卷挂载的所有权问题依然存在。不想通过securityContext将runAsUser、runAsGroup和fsGroup都设置为0(不希望所有进程以root运行,不符合最佳实践),且配置为jenkins用户时容器无法启动——因为容器需要以root启动dockerd。

流水线withCredentials代码片段:

withCredentials([file(credentialsId: 'key-sa-prd', variable: 'GCLOUD_KEY')]) {
    key_json = readFile("${GCLOUD_KEY}")
}
writeFile file: 'key.json', text: key_json
sh "cat key.json"
sh "gcloud auth activate-service-account --key-file=key.json"
sh "gcloud auth configure-docker ${registry}"

当前使用的Pod模板YAML:

apiVersion: v1
kind: Pod
metadata:
    labels:
        ecosystem: ${ecosystem}
        job_name: ${job_name}
spec:
  containers:
    - name: ${containerName}
      image: ${dImage}
      command:
        - dockerd
      tty: true
      securityContext:
        privileged: true
      volumeMounts:
        - name: jenkins-home
          mountPath: /var/jenkins_home
          readOnly: false
  securityContext:
    fsGroup: 1000
  initContainers:
    - name: init-jenkins-home
      image: alpine
      command:
        - sh
        - -c
        - "addgroup -g 1000 jenkins && adduser -D -u 1000 -G jenkins jenkins && chown -R 1000:1000 /var/jenkins_home && chmod -R 777 /var/jenkins_home"
      volumeMounts:
        - name: jenkins-home
          mountPath: /var/jenkins_home
  enableServiceLinks: "false"
  volumes: ${volumes}
  tolerations: ${tolerations}
  nodeSelector:
    ${nodeSelector}
解决方案

1. 自定义Credentials绑定的临时目录

credentials-binding插件默认使用$JENKINS_HOME存储临时密钥文件,可通过指定自定义路径规避权限问题:

// 提前在工作目录创建可写的临时凭证目录
def credsTempDir = "${WORKSPACE}/.jenkins-creds"
sh "mkdir -p ${credsTempDir} && chmod 700 ${credsTempDir}"

// 在withCredentials中指定密钥写入的目标目录
withCredentials([file(
    credentialsId: 'key-sa-prd', 
    variable: 'GCLOUD_KEY',
    targetDirectory: credsTempDir
)]) {
    key_json = readFile("${GCLOUD_KEY}")
}

2. 调整Pod模板的卷权限配置

修改init容器的权限设置,确保root用户(容器运行用户)能写入/var/jenkins_home,同时保留fsGroup的安全配置:

initContainers:
    - name: init-jenkins-home
      image: alpine
      command:
        - sh
        - -c
        - "addgroup -g 1000 jenkins && adduser -D -u 1000 -G jenkins jenkins && chown -R root:jenkins /var/jenkins_home && chmod -R 775 /var/jenkins_home"
      volumeMounts:
        - name: jenkins-home
          mountPath: /var/jenkins_home

此配置将目录所有者设为root用户、jenkins组,权限775允许root用户和jenkins组写入,结合fsGroup:1000确保容器进程对卷文件拥有组权限。

3. 改用Secret text类型凭证,避免写入Jenkins_home

将GCP服务账号密钥保存为Secret text类型(直接粘贴JSON内容),跳过credentials-binding插件写入文件的步骤:

withCredentials([string(credentialsId: 'key-sa-prd', variable: 'GCLOUD_KEY_JSON')]) {
    writeFile file: 'key.json', text: GCLOUD_KEY_JSON
}
sh "gcloud auth activate-service-account --key-file=key.json"
sh "gcloud auth configure-docker ${registry}"

这种方式直接在工作目录生成密钥文件,彻底规避/var/jenkins_home的权限问题。

4. 容器启动权限分离

如果必须用root启动dockerd,但希望Jenkins agent以非root用户运行,可修改容器启动命令实现权限切换:

containers:
    - name: ${containerName}
      image: ${dImage}
      command:
        - sh
        - -c
        - "dockerd & sleep 5 && su jenkins -c '/usr/local/bin/jenkins-agent'"
      tty: true
      securityContext:
        privileged: true

此配置让dockerd以root运行,Jenkins agent切换为jenkins用户运行,兼顾服务启动需求和权限安全。

内容的提问来源于stack exchange,提问作者Manish Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 18:05:55