经过太多搜索后,我仍然不确定如何在声明性 Jenkins 管道中使用 K8S 密钥作为环境变量。我们尝试了几种不同的方法,包括以下方法。构建涉及设置一个 Python 容器,将 Python 轮子推送到我们的私有 ECR 注册表。
build_pod_config = '''
apiVersion: "v1"
kind: "Pod"
metadata:
namespace: "jenkins"
spec:
containers:
# ...
- name: 'python'
image: '870326185936.dkr.ecr.us-east-2.amazonaws.com/605data/build-tools-python:3.12'
command:
- 'sleep'
args:
- 'infinity'
env:
- name: PYPI_PWD
valueFrom:
secretKeyRef:
name: 'secret-credentials'
key: 'pypi-admin-pwd'
# ...
nodeSelector:
kubernetes.io/os: "linux"
restartPolicy: "Never"
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsUser: 1000
serviceAccountName: "dev-jenkins"
volumes:
# ...
'''
pipeline {
agent {
kubernetes {
yaml build_pod_config
defaultContainer 'python'
}
} // agent
stages {
stage("Setup") {
steps {
script {
// we don't clone here, the job definition handles everything
this_branch = "${GIT_BRANCH}".trim()
echo "Building branch ${this_branch}..."
currentBuild.displayName = "${this_branch}"
push_branches = [
"origin/master"
]
}
}
}
// ...
stage("Publish") {
when {
expression { push_branches.contains(this_branch) }
}
steps {
echo "Pushing wheel and Docker image"
container("python") {
echo "Pushing wheel, src distributions to PyPi"
// From the Kubernetes plugin, but currently not working
secretEnvVar(key: 'PYPI_PWD', secretName: 'secret-credentials', secretKey: 'pypi-pwd', optional: false) {
// sh("""python -m pip install '.[publish]'""")
sh("""python -m twine upload --repository-url https://pypi.shared-services.605.nu dist/* --user admin --password ${PYPI_PWD}""")
}
}
}
}
}
post {
// ...
}
}
问题是,虽然上面的 K8S 秘密值在 Python 容器中显示为环境变量,但在将轮子推向注册表的管道步骤中无法使用它。我们希望在我们的管道中使用此类 K8S 秘密值作为环境变量。
我们已经尝试了所有能想到的或在网上找到的方法,但没有成功。 Jenkins Kubernetes 插件确实定义了“secretEnvVar”,但它似乎仅在脚本化管道中可用,而不是声明性管道。关于如何在我们的构建步骤中设置基于 K8S 秘密的环境变量有什么想法吗?
我们希望继续使用带有 YAML 构建 Pod 配置的声明式方法,因为我们有一些工具可以帮助用户创建此类管道。如果可能的话,我们也不希望涉及 Jenkins 凭证。
有什么想法吗?
我有一种感觉,它确实有效,但不是以你期望的方式。根据管道类型,如果环境变量定义了两次,Jenkins 可以更改环境变量的名称。即使是声明式管道和声明式多分支管道在这方面的工作方式也不同。
为了确保这一点,您可以通过在容器中运行
printenv
来检查它。这些值可能会被屏蔽,但您很可能会看到类似这样的内容:
...
PYPI_PWD=*****
pypi_pwd=*****
...
无论如何,我不确定您是否需要使用
secretEnvVar
提取该环境变量 - 此外,如果我没记错(并阅读 docs),它甚至不会像那样工作,而是旨在当您没有 YAML 文件时构建 pod 模板。这种定义 pod 模板的方式已被弃用,取而代之的是 YAML、AFAIR。
twine upload
能够利用环境变量本身的事实,我会尝试
只需在 pod 模板中定义 TWINE_PASSWORD
环境变量,而不是自定义 PYPI_PWD
。这也更安全,因为您不使用 Groovy 字符串插值,这使得 CLI 上使用的秘密以纯文本形式提供:
build_pod_config = '''
apiVersion: "v1"
kind: "Pod"
metadata:
namespace: "jenkins"
spec:
containers:
# ...
- name: 'python'
image: '870326185936.dkr.ecr.us-east-2.amazonaws.com/605data/build-tools-python:3.12'
command:
- 'sleep'
args:
- 'infinity'
env:
- name: TWINE_PASSWORD
valueFrom:
secretKeyRef:
name: 'secret-credentials'
key: 'pypi-admin-pwd'
# ...
'''
pipeline {
agent {
kubernetes {
yaml build_pod_config
defaultContainer 'python'
}
} // agent
stages {
// I omitted the unrelated parts for brevity
// ...
stage("Publish") {
when {
expression { push_branches.contains(this_branch) }
}
steps {
echo "Pushing wheel and Docker image"
container("python") {
echo "Pushing wheel, src distributions to PyPi"
sh 'python -m twine upload --repository-url https://pypi.shared-services.605.nu dist/* --user admin'
}
}
}
}
post {
// ...
}
}
您可以以相同的方式设置其他选项,这样您的 Pod 模板就可以与任何管道共享并随时可用,并且管道更简单。
旁注:您可以使用 label
步骤的
sh
参数来避免混乱的 echo
步骤。 Jenkins 将自动在构建日志中的命令日志前面添加以下文本:
sh script: 'python -m twine upload dist/*',
label: 'Pushing wheel, src distributions to PyPi'