环境准备
k8s环境:node1 和 node2
创建命名空间
╰─# kubectl create ns devopsnamespace/devops created
创建jenkins-master
deployment文件:
kindDeployment apiVersionapps/v1 metadata labels k8s-appjenkins namejenkins namespacedevops spec replicas1 revisionHistoryLimit10 selector matchLabels k8s-appjenkins template metadata labels k8s-appjenkins namespacedevops namejenkins spec containersnamejenkins imagejenkins/jenkins2.381 imagePullPolicyIfNotPresent portscontainerPort30080 nameweb protocolTCP containerPort30081 nameagent protocolTCP resources limits cpu1000m memory2Gi requests cpu500m memory512Mi livenessProbe httpGet path/login port30080 initialDelaySeconds60 timeoutSeconds5 failureThreshold12 readinessProbe httpGet path/login port30080 initialDelaySeconds60 timeoutSeconds5 failureThreshold12 volumeMountsnamejenkins-home mountPath/var/lib/jenkins envnameJENKINS_HOME value/var/lib/jenkins nameJENKINS_OPTS value--httpPort=30080 nameJENKINS_SLAVE_AGENT_PORT value"30081" volumesnamejenkins-home hostPath path/data/devops/jenkins typeDirectory serviceAccountNamejenkins ---apiVersionv1 kindServiceAccount metadata labels k8s-appjenkins namejenkins namespacedevops ---kindService apiVersionv1 metadata labels k8s-appjenkins namejenkins namespacedevops spec typeNodePort portsnameweb port30080 targetPort30080 nodePort30080nameslave port30081 targetPort30081 nodePort30081 selector k8s-appjenkins ---kindRole apiVersionrbac.authorization.k8s.io/v1 metadata namejenkins namespacedevops rulesapiGroups"" resources"pods""configmaps""namespaces" verbs"create""delete""get""list""patch""update""watch"apiGroups"" resources"pods/exec" verbs"create""delete""get""list""patch""update""watch"apiGroups"" resources"pods/log" verbs"get""list""watch"apiGroups"" resources"secrets" verbs"get"---apiVersionrbac.authorization.k8s.io/v1 kindRoleBinding metadata namejenkins namespacedevops roleRef apiGrouprbac.authorization.k8s.io kindRole namejenkins subjectskindServiceAccount namejenkins namespacedevops
通过一下命令启动jenkins-master
kubectl create -f deployment.yml
在启动jenkins过程中,容器状态为 CrashLoopBackOff ,查看日志出现 java.nio.file.AccessDeniedException: /var/lib/jenkins/war
错误信息时,容器挂载的宿主机目录,无权限访问,需要 执行 chmod 777 /data/devops/jenkins , 然后在重启一下pod
╰─# kubectl get pods -n devops 1 ↵ NAME READY STATUS RESTARTS AGE jenkins-65dbc65fbd-kkxbc 0/1 CrashLoopBackOff 5 5m26s ╭─root@k201 ~/jenkins-k8s ╰─# kubectl logs pods/jenkins-65dbc65fbd-kkxbc -n devops Running from/usr/share/jenkins/jenkins.war webroot/var/lib/jenkins/war 2022-12-12 09:47:16.120+0000 id=1 INFO winstone.Logger#logInternalBeginning extraction from war file 2022-12-12 09:47:16.139+0000 id=1 WARNING winstone.Logger#logInternalFailed to recreate dirs /var/lib/jenkins/war java.nio.file.AccessDeniedException/var/lib/jenkins/war at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116) at java.base/sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:389) at java.base/java.nio.file.Files.createDirectory(Files.java:690) at java.base/java.nio.file.Files.createAndCheckIsDirectory(Files.java:797) at java.base/java.nio.file.Files.createDirectories(Files.java:783) at winstone.HostConfiguration.getWebRoot(HostConfiguration.java:265) at winstone.HostConfiguration.<init>(HostConfiguration.java:87) at winstone.HostGroup.initHost(HostGroup.java:65) at winstone.HostGroup.<init>(HostGroup.java:44) at winstone.Launcher.<init>(Launcher.java:150) at winstone.Launcher.main(Launcher.java:389) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at executable.Main.main(Main.java:356) 2022-12-12 09:47:16.143+0000 id=1 WARNING winstone.Logger#logInternalFailed to create dirs /var/lib/jenkins/war/META-INF 2022-12-12 09:47:16.229+0000 id=1 INFO winstone.Logger#logInternalJetty shutdown successfully java.io.FileNotFoundException/var/lib/jenkins/war/META-INF/MANIFEST.MF (No such file or directory) at java.base/java.io.FileOutputStream.open0(Native Method) at java.base/java.io.FileOutputStream.open(FileOutputStream.java:298) at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:237) at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:187) at winstone.HostConfiguration.getWebRoot(HostConfiguration.java:309) at winstone.HostConfiguration.<init>(HostConfiguration.java:87) at winstone.HostGroup.initHost(HostGroup.java:65) at winstone.HostGroup.<init>(HostGroup.java:44) at winstone.Launcher.<init>(Launcher.java:150) at winstone.Launcher.main(Launcher.java:389) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at executable.Main.main(Main.java:356) 2022-12-12 09:47:16.232+0000 id=1 SEVERE winstone.Logger#logInternalContainer startup failed java.io.FileNotFoundException/var/lib/jenkins/war/META-INF/MANIFEST.MF (No such file or directory) at java.base/java.io.FileOutputStream.open0(Native Method) at java.base/java.io.FileOutputStream.open(FileOutputStream.java:298) at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:237) at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:187) at winstone.HostConfiguration.getWebRoot(HostConfiguration.java:309) at winstone.HostConfiguration.<init>(HostConfiguration.java:87) at winstone.HostGroup.initHost(HostGroup.java:65) at winstone.HostGroup.<init>(HostGroup.java:44) at winstone.Launcher.<init>(Launcher.java:150) at winstone.Launcher.main(Launcher.java:389) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at executable.Main.main(Main.java:356) ╭─root@k201 ~/jenkins-k8s ╰─#
动态配置jenkins Slave节点
安装kubernetes插件(安装完成后最好重启一下)。配置插件信息 系统设置 -> 节点管理 -> Configure Clouds ->增加一个云。
制作Kubernetes证书
- 进入集群服务器 .kube/config
- 复制config文件中的certificate-authority-data内容,生成base64文件 ca.crt
- 复制config文件中的client-certificate-data内容,生成base64文件 client.crt
- 复制config文件中的client-key-data内容,生成base64文件 client.key
- echo zzzzzzzzz | base64 –d > client.key
- 生成证书(会输入密码需要记住后面jenkins需要配置)
- openssl pkcs12 -export -out cert.pfx -inkey client.key -in client.crt -certfile ca.crt
- 下载证书 cert.pfx
Jenkins新建凭据
注意:这里上传证书文件,通过 openssl 文件生成的 cert.pfx 的文件
配置Salve集群节点
将ca.crt 内容复制到 服务证书key 选择证书凭据 测试连接
注意:
获取kubenetes地址方式:
╰─# kubectl config view | grep server serverhttps//192.168.10.2016443╭─root@k201 ~/jenkins-k8s ╰─#
kubernetes 服务证书key为 ca.crt 文件中的内容
创建pipeline
流水线示例
以PodTemplate模板创建脚本
def label = "slave-${UUID.randomUUID().toString()}"podTemplate(cloud'kubernetes', namespace'devops',labellabel, serviceAccount'jenkins',containers containerTemplate(name'golang' image'golang:1.14.2-alpine3.11' command'cat' ttyEnabledtrue) containerTemplate(name'docker' image'docker:latest' command'cat' ttyEnabledtrue) containerTemplate(name'kubectl' image'cnych/kubectl' command'cat' ttyEnabledtrue) ,volumes hostPathVolume(mountPath'/home/jenkins/.kube' hostPath'/root/.kube') hostPathVolume(mountPath'/var/run/docker.sock' hostPath'/var/run/docker.sock') ) node(label) stage('单元测试') echo "测试阶段" stage('代码编译打包') container('golang') echo "代码编译打包阶段" stage('构建 Docker 镜像') container('docker') echo "构建 Docker 镜像阶段" stage('运行 Kubectl') container('kubectl') echo "查看 K8S 集群 Pod 列表" sh "kubectl get pods"


