背景
为了使用Kubernetes管理并自动化部署应用程序,领导"纠结"了几个同事搭了一个Kubernetes集群环境。
不过,为了减少复杂度,采用了非官方推荐的方式:
- API Server使用http方式
- 不使用Admission Controllers,即API Server启动参数admission-control设为空
关于Admission Controllers的解释,可以参照官方文档
搭好k8s环境后,参考文档 初试 Jenkins 使用 Kubernetes Plugin 完成持续构建与发布 部署了Jenkins Server。
尝试运行pipeline脚本:
def label = "mypod-${UUID.randomUUID().toString()}"
podTemplate(label: label, cloud: 'kubernetes', containers: [
containerTemplate(name: 'maven', image: 'maven:3.3.9-jdk-8-alpine', ttyEnabled: true, command: 'cat'),
]) {
node(label) {
stage('Get a Maven Project') {
git 'https://github.com/jenkins-docs/simple-java-maven-app.git'
container('maven') {
stage('Build a Maven project') {
sh 'mvn -B clean install'
}
}
}
}
}
发生了java.nio.file.NoSuchFileException: /var/run/secrets/kubernetes.io/serviceaccount/namespace的错误。错误信息:
...
> git checkout -f 0d85b7e1fd39bc6978511f92381aa10534ca4c1b
> git branch -a -v --no-abbrev # timeout=10
> git checkout -b master 0d85b7e1fd39bc6978511f92381aa10534ca4c1b
Commit message: "Amend README.md"
First time build. Skipping changelog.
[Pipeline] container
[Pipeline] // container
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] }
[Pipeline] // podTemplate
[Pipeline] End of Pipeline
java.nio.file.NoSuchFileException: /var/run/secrets/kubernetes.io/serviceaccount/namespace
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
...
接下来就是2,3天的调查,关于这个错误的能查到的资料几乎没有,也尝试了很多方法,无果... 非常煎熬。
原因
关于这个错误,有几个疑问
- 文件/var/run/secrets/kubernetes.io/serviceaccount/namespace有什么用
- 为什么Jenkins(Kubernetes Plugin)要去找这个文件
- 为什么这个文件不存在
带着这些问题找到了官方文档 Accessing Clusters,文档中出现了这个文件的身姿。
Accessing the API from a Pod
When accessing the API from a pod, locating and authenticating to the apiserver are somewhat different.The recommended way to locate the apiserver within the pod is with the kubernetes.default.svc DNS name, which resolves to a Service IP which in turn will be routed to an apiserver.
The recommended way to authenticate to the apiserver is with a service account credential. By kube-system, a pod is associated with a service account, and a credential (token) for that service account is placed into the filesystem tree of each container in that pod, at
/var/run/secrets/kubernetes.io/serviceaccount/token
.If available, a certificate bundle is placed into the filesystem tree of each container at
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
, and should be used to verify the serving certificate of the apiserver.Finally, the default namespace to be used for namespaced API operations is placed in a file at
/var/run/secrets/kubernetes.io/serviceaccount/namespace
in each container.
那为什么我们搭建环境的container里没有这个文件呢?就连目录 /var/run/secrets 都没有...
调查过程中,渐渐地把疑点定位到API Server的启动参数 admission-control
(1.10版本后被替换成 enable-admission-plugins
)。官方推荐的设值有 ServiceAccount
但是搭环境的时候没有设置,即设置为空。
于是,把API Server的启动admission-control参数改成了 --admission-control=ServiceAccount。
然后,重启API Server,修改Jenkins的Deployment(为了让k8s重新部署Jenkins Pod)。
接着,进入新部署的Jenkins Pod(container)确认,上帝保佑,生成了目录/var/run/secrets以及相关文件!
由于重新部署了Jenkins,需要重新设置Jenkins(安装Plugin、设置k8s云、创建上述脚本的pipeline job)
运行job(item),脚本运行成功。问题解决了!
所有评论(0)