基于k8s 平台 jenkins 部署及动态slave节点制作和配置
前期准备1. 一个已经部署好的k8s 平台2. 一个已经搭建好的harbor 私有仓库jenkins 部署这里 使用主流的rbac 模式部署jenkins 也就是说们们需要创建:1. 一个jenkins 命名空间2. 一个nodeportservice 用来外部web访问3.一个 serviceaccount 用来 保障jenkins 服务器能 访问Jenkins 命名空间下的资源3. 一个 cl
前期准备
1. 一个已经部署好的k8s 平台
2. 一个已经搭建好的harbor 私有仓库
jenkins 部署
这里 使用主流的rbac 模式部署jenkins 也就是说们们需要创建:
1. 一个jenkins 命名空间
2. 一个nodeport service 用来外部web访问
3.一个 serviceaccount 用来 保障jenkins 服务器能 访问Jenkins 命名空间下的资源
3. 一个 clusterRole 用来设置 jenkins 能访问 k8s 哪些资源以及具体权限
4. 一个 clusterBinding 将 clusterRole 跟 serviceaccount绑定起来 决定这个sa 能访问的范围
5. 一个 deployment 用来 真正启动jenkins 服务器
具体jenkins.yaml 如下:
---
# 命名空间
apiVersion: v1
kind: Namespace
metadata:
name: jenkins
---
#动态存储 pvc 因为我这里用nfs 来存放jenkins 数据,如果你不需要进行数据持久化可以不创建,
#需要的话可以参考我之前文章搭建一个nfs 环境。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5G
---
# jenkins deployment 启动 jenkins 服务器
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins-master
namespace: jenkins
spec:
selector:
matchLabels:
app: jenkins-master
template:
metadata:
labels:
app: jenkins-master
namespace: jenkins
spec:
securityContext:
fsGroup: 1000
containers:
- name: jenkins-master
image: kanq.k8s.com:7443/devops/jenkins:latest #这里用的是我自己搭建的私有仓库。
imagePullPolicy: Always
ports:
- containerPort: 8080
name: http
- containerPort: 50000
name: agent
volumeMounts:
- name: jenkins-master-vol
mountPath: /var/jenkins_home
volumes:
- name: jenkins-master-vol
persistentVolumeClaim:
claimName: jenkins-pvc
serviceAccount: "jenkins-master"
---
# svc 用来支持外部访问,这里我将jenkins 的 8080 和 50000 都设成了nodeport 型因为我需要 在jenkisn
# 上外挂 非k8s 集群的节点,还有 k8s 默认的nodeport 节点范围是3000-32767 所以如果想用32768及以上的端口
# 的话一定到将 api-server service-node-port-range 这个启动参数设为你需要的。然后重启api-server 服务
apiVersion: v1
kind: Service
metadata:
name: jenkins-master
namespace: jenkins
spec:
type: NodePort
ports:
- port: 8080
name: http
targetPort: 8080
nodePort: 38080
- port: 50000
name: agent
nodePort: 50000
targetPort: 50000
selector:
app: jenkins-master
---
# 使用默认的secert 创建的serviceaccout 给 jenkins pod 提供访问k8s 集群的ssl 认证
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins-master
namespace: jenkins
---
# 创建一个角色 设置 访问k8s资源类型和权限范围
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: jenkins-master
namespace: jenkins
rules:
- apiGroups: [""]
resources: ["pods"]
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"]
---
# 将serviceaccount 和 role 绑定 这样配置了这个serviceaccount的pod 就能根据这个role 来规范访问
# 这个命名空间下的资源数据
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jenkins-master
namespace: jenkins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins-master
subjects:
- kind: ServiceAccount
name: jenkins-master
namespace: jenkins
kubectl apply -f jenkins.yaml
正常执行完后
[root@kanq template]# kubectl get pod -n jenkins
NAME READY STATUS RESTARTS AGE
jenkins-master-5c65d6b7f-hx4f2 1/1 Running 0 5d17h
kubectl logs -f jenkins-master-5c65d6b7f-hx4f2 -n jenkins
....
*************************************************************
*************************************************************
*************************************************************
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password ddto proceed to installation:
4aa4c650ddddee9d46f1b020e2142e2df369 #这个就是你网页登录 http://k8s节点ip:38080 后输入的token
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
*************************************************************
*************************************************************
*************************************************************
动态slave 节点制作
一般直接用 jenkins 自带的就行但是如果不能满足我们的需求 我们可以自己定制。比如我这里需要满足 centos8 版本而且需要里面 可以使用podman kubectl 等。
这里顺便介绍了podman, 后面 docker 已经商业收费了,而且 k8s 也会跟docker 解耦。 再加上 docker 实现dind(容器中可以执行docker 命令比如说docker build docker push )这个在 以容器为jenkins 节点的场景下 非常有必要.。
比较麻烦的是因为docker 有一个守护进程的原因,需要我们将宿主机的docker.sock 挂载到容器中,限制太大,如果k8s 使用二进制部署,使用containerd 作为容器运行时而不用docker 就会发现宿主机根本就没有docker.sock 咋挂, 额外再安装一个docker?
如果用 podman 就没有这个顾虑了。因为podman 没有后台运行的 docker.sock 这个守护进程。我们只用对容器内部的podman 做些配置即可。
回归正题 下面是制作 slave 的dockerfile 文件:
#使用centos8 的基础镜像 可以根据 需求修改
# 如果只制作jenkins slave 的话 可以不安装podman 两个sed 命令可以不执行。kubectl 也可以不拷
# slave.jar 下载地址:
#获取agent.jar
#也叫slave.jar,实际jenkins中的remoting
#官网地址
#https://www.jenkins.io/zh/projects/remoting/
#jar包下载地址
#https://repo.jenkins-ci.org/public/org/jenkins-ci/main/remoting/
#获取jenkins-slave
#git地址
#https://github.com/jenkinsci/docker-inbound-agent/blob/master/jenkins-agent
FROM centos:centos8
RUN mkdir -p /usr/share/jekins && \
yum install -y java-1.8.0-openjdk podman && \
sed -i 's/#mount_program/mount_program/g' /etc/containers/storage.conf && \
sed -i 's/mountopt/#mountopt/g' /etc/containers/storage.conf && \
chmod +777 /usr/local/bin/jenkins-slave
COPY slave.jar /usr/share/jenkins/slave.jar
COPY jenkins-slave /usr/local/bin/jenkins-slave
COPY kubectl /usr/bin/kubectl
USER root
WORKDIR /home/jenkins
ENTRYPOINT ["jenkins-slave"]
将 slave.tar 跟 jenkins-slave 放在跟Dockerfile 文件同级目录就可以了。
docker build -t centos:jenkins-slave .
jenkins 配置动态节点
-
打开 jenkins 配置找到cloud(一般在 配置页面的最下面)
-
添加云环境选 kubernetes
-
配置 kubernetes
a. 设置云平台 信息 名称随便填, 地址 不知道的看下自己的master 节点/root/.kube/config 中的
server 地址
配置完后 点击连接测试
b. 配置 jenkins 相关配置 ,这里使用 svc 内部ip 和 端口
[root@kanq jenkins-slave]# kubectl get svc -n jenkins
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins-master NodePort 10.68.185.27 <none> 8080:30180/TCP,50000:50000/TCP 5d19h
这里 10.68.185.27 就是内部clusterip
端口 是下面的 portip (port 是集群内部端口 ,nodePort 是宿主机暴露端口, tragetPort 是 容器里面端口 )
所以我们这儿用 集群内部端口 8080 和50000
kubectl get svc jenkins-master -n jenkins -o yaml
'''
spec:
clusterIP: 10.68.185.27
clusterIPs:
- 10.68.185.27
externalTrafficPolicy: Cluster
ports:
- name: http
nodePort: 30180
port: 8080
protocol: TCP
targetPort: 8080
- name: agent
nodePort: 50000
port: 50000
protocol: TCP
targetPort: 50000
selector:
app: jenkins-master
sessionAffinity: None
type: NodePort
b. 配置pod
名字随便取,但是命名空间要跟jenkins 服务器统一,标签 就是你后面 流水线中配置的节点名称。
如果使用默认的slave节点 到上一步就直接保存退出就可以了。因为jenkins 这个框架下自带一个jnlp 容器 使用 jenkins/inbound-agent 镜像
如果你想替换默认 pod 的镜像 需要如下配置,名字一定要填jnlp ,工作目录随便, 运行命令和参数不用填
如果你想再添加一个pod内容器(这种情况在pipline 流水下常见) 点击添加容器 注意这里的工作目录所有的容器要保持一致,这是 pod 内容器共享目录
注: 运行命令,和命令参数填写一定要保证 执行后容器一直运行,不会直接退出(pod 特性,里面启动的容器执行完配置的命令后会自动退出,这里如果不填它会执行镜像本身配置的命令)。不然会出现pod notready 情况
这也是曾困扰了一天的问题。所以这里最简单的我直接用sleep 99999 保障 容器一直运行,
主要的配置就上面那些 还有其他 挂载卷,环境变量等。 这里就不一一介绍了。
注:
1. 这里挂的卷,配的环境变量会挂在所有容器中。不能自定义哪几个容器用哪几个变量和卷
2. 还有 对于多容器的jenkins slave 配置 只用保证 名为jnlp 这个 容器中安装了jenkins slave 相关工具就可以了,其他容器不用安装,而且即使安装了你的容器名如果不是jnlp 相关参数也不会传给你这个pod ,从而导致 容器运行失败(如果你的容器启动命令也是java-slave)。
下面介绍一种 在pipline中 配置 pod 模板的方法。 比上面页面配置就自主多了,可以自定义容器挂载的卷和 环境变量。做到每个容器 对应自己的配置
下面是我编写的一个声明式的pipline,当代码提交通过webhook 触发后 执行这个pipline. 主要做的就是:
- 配置 云kubernetes 的pod 模板
- 默认的jnlp 容器(镜像自己制作的添加了git)中 下载代码,
- build 容器中编译代码(使用的docker.hub 上下的golang:v1.17)
- podman 容器(安装了podman)中build镜像,并push 到私有仓库,然后执行kubectl create 命令用这个镜像启动一个deployment ,不成功异常退出,成功后删除启动的deployment
- 根据运行情况,发送邮件给代码提交人
def webHookData = readJSON text: "${head_commit}"
String commitID= webHookData["id"][0..7]
String url=webHookData.url
//String head_commit_author_email =
realJenkinsUrl=BUILD_URL.replaceAll("172.16.3.154:30180","113.57.110.41:15401")
pipeline{
agent {
kubernetes{
yaml '''
apiVersion: "v1"
kind: "Pod"
metadata:
name: "devops"
spec:
containers:
# 如果 默认的jenkins/inbound-agent满足你的需求可以跟 上面页面那样不配置
- name: "jnlp"
image: "kanq.k8s.com:7443/devops/centos-slave-jnlp-git:latest"
imagePullPolicy: "IfNotPresent"
volumeMounts:
- mountPath: "/home/jenkins/agent"
name: "workspace-volume"
readOnly: false
workingDir: "/home/jenkins/agent"
# 编译用镜像,记住一定要保证容器一直运行
- name: "build"
args:
- "999999"
command:
- "sleep"
image: "kanq.k8s.com:7443/devops/golang:1.17"
imagePullPolicy: "IfNotPresent"
name: "build"
volumeMounts:
- mountPath: "/home/jenkins/agent"
name: "workspace-volume"
readOnly: false
workingDir: "/home/jenkins/agent"
# 用于镜像制作,推库 ,部署 验证。
- name: "podman"
args:
- "999999"
command:
- "sleep"
env:
- name: HarborU
valueFrom:
secretKeyRef:
name: harbor
key: username
- name: HarborP
valueFrom:
secretKeyRef:
name: harbor
key: password
image: "kanq.k8s.com:7443/devops/centos-slave-podman-kubectl:latest"
imagePullPolicy: "IfNotPresent"
securityContext:
privileged: true
volumeMounts:
- mountPath: "/etc/containers/certs.d/kanq.k8s.com/"
name: podman
- mountPath: "/home/"
name: k8sconfigmap
- mountPath: "/home/jenkins/agent"
name: "workspace-volume"
readOnly: false
workingDir: "/home/jenkins/agent"
activeDeadlineSeconds: 60000
volumes:
- emptyDir:
medium: ""
name: "workspace-volume"
- secret:
secretName: dockersecret
name: podman
- secret:
secretName: harbor
name: harbor
- configMap:
name: k8sconfig
name: k8sconfigmap
'''
}
}
stages {
stage('git') {
steps {
container("jnlp"){
sh """
git clone git@e.coding.net:kanqtest/kanq/kanqtest.git
env
"""
}
}
}
stage("compile"){
steps {
container("build"){
dir("$WORKSPACE/kanqtest"){
sh """
go build -a -o devops-go-sample cmd/main.go
"""
}
}
}
}
stage("build"){
steps {
container("podman"){
dir("$WORKSPACE/kanqtest"){
sh '''
cp -r /etc/containers/certs.d/kanq.k8s.com /etc/containers/certs.d/kanq.k8s.com:7443
echo "172.16.3.154 kanq.k8s.com" >>/etc/hosts
echo $HarborP |podman login -u $HarborU --password-stdin kanq.k8s.com:7443
podman build -t kanq.k8s.com:7443/devops/busybox:go .
podman push kanq.k8s.com:7443/devops/busybox:go
kubectl create deployment devopstest --image="kanq.k8s.com:7443/devops/busybox:go" -n jenkins
sleep 6s
heal=$(kubectl get pod -n jenkins|grep devopstest|grep Running)
if [[ "$heal" == "" ]];then
exit -1
fi
kubectl delete deployment devopstest -n jenkins
'''
}
}
}
}
}
post{
always{
sh "echo $commitID"
sh "echo $url"
addShortText background: 'white', borderColor: 'white', color: 'DodgerBlue', link: "$url", text: "$commitID"
mail bcc: '', body: """
代码coding 地址:'${head_commit_url}'
jenkins 地址: '${realJenkinsUrl}'
""", cc: '', from: '2833732855@qq.com', replyTo: '', subject: "kanq devops success!!!!", to: "$head_commit_author_email"
}
}
}
更多推荐
所有评论(0)