环境要求:你需要一个正常可以使用的Kubernetes集群,集群中可以使用的内存大于等于4G。
Kubernetes版本1.18
Jenkins插件可以在Kubernetes集群中运行动态jenkins-slave代理。
基于Kubernetes的docker,自动化在Kubernetes中运行的Jenkins-slave代理的缩放。
该插件为每个jenkins-slave代理创建Kubernetes Pod,并在每个构建后停止它。
在Kubernetes中jenkins-slave代理启动,会自动连接到Jenkins主控制器。 对于某些环境变量,会自动注入:
不需要在Kubernetes内运行Jenkins Controller。
官网:https://jenkins.io/download
docker:hub.docker.com/r/jenkins/jenkins/tags
建议下载长期支持的版本
To use the latest LTS: docker pull jenkins/jenkins:lts-jdk11
拉取镜像
docker pull jenkins/jenkins:2.289.2-lts-jdk11
重新打tag,上传私服
docker tag jenkins/jenkins:2.289.2-lts-jdk11 harbor.example.com/public/jenkins:2.289.2
docker push harbor.example.com/public/jenkins:2.289.2
制作镜像
mkdir /opt/dockerfile/jenkins -p
cd /opt/dockerfile/jenkins
制作密钥
ssh-keygen -t rsa -b 2048 -C "[email protected]" -N "" -f /root/.ssh/id_rsa
cp /root/.ssh/id_rsa .
#公钥要上传到git
拷贝config.json
cp /root/.docker/config.json .
Dockerfile
vi Dockerfile
FROM harbor.example.com/public/jenkins:2.289.2
USER root
ADD id_rsa /root/.ssh/id_rsa
ADD config.json /root/.docker/config.json
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
echo 'Asia/Shanghai' >/etc/timezone
build 镜像打tag
docker build . -t harbor.example.com/infra/jenkins:2.289.2
上传镜像到harbor
docker push harbor.example.com/infra/jenkins:2.289.2
在k8s上创建名称空间
kubectl create ns infra
创建可以访问harbor的secret
kubectl create secret docker-registry harbor --docker-server=harbor.example.com --docker-username=admin --docker-password=Harbor12345 -n infra
jenkins 拉取代码有两种方式(ssh;http)
用ssh的方式要配置密钥对,把公钥放到git里,打私钥放到jenkins镜像中
把公钥配置到[email protected]
测试jenkins镜像是否可以通过密钥来连接git
docker run --rm harbor.example.com/infra/jenkins:2.289.2 ssh -i /root/.ssh/id_rsa -T git@gitee.com
可以选择使用nfs+pvc
准备一台机器,搭建NFS服务,这台机器要是k8s集群可以访问到的
yum install nfs-utils -y
vim /etc/exports
/wyyt/data/nfs-volume *(rw,no_root_squash)
systemctl start nfs
systemctl enable nfs
mkdir /opt/data/nfs-volume/jenkins_home
在node节点里测试
yum install nfs-utils
showmount -e 10.4.7.1
mkdir /opt/k8s-yaml/jenkins -p
cd /opt/k8s-yaml/jenkins
vi pv-nfs-jk.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-jk #pv名称
spec:
capacity: #存储能力,一个pv对象都要指定一个存储能力,
storage: 100Gi #存储空间
accessModes:
- ReadWriteOnce #访问模式
persistentVolumeReclaimPolicy: Recycle #回收策略
nfs: #服务模式 (nfs、ceph、hostpath等)
path: /opt/data/nfs-volume/jenkins_home #共享数据目录挂载点
server: 10.4.7.200 #nfs服务器地址
kubectl apply -f pv-nfs-jk.yaml
persistentvolume/pv1 created
[root@master storage]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv1 1Gi RWO Recycle Available 5s
persistentVolumeReclaimPolicy回收策略
不过需要注意的是,目前只有NFS和HostPath两类支持回收策略,一般设置Retain比较保险
状态有以下几种
vim pvc-nfs-jk.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-nfs-jk
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
cd /opt/k8s-yaml/jenkins
vi dp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: jenkins
name: jenkins
namespace: infra
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: jenkins
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: jenkins
spec:
containers:
- env:
- name: JAVA_OPTS
value: '-Xmx512m -Xms512m'
image: 'harbor.example.com/infra/jenkins:2.289.2'
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 15
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 1
name: jenkins
ports:
- containerPort: 50000
protocol: TCP
- containerPort: 8080
protocol: TCP
readinessProbe:
failureThreshold: 3
initialDelaySeconds: 15
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 1
resources:
requests:
cpu: 250m
memory: 512Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /run/docker.sock
name: volume-image-0
- mountPath: /var/jenkins_home
name: volume-jenkins
- mountPath: /etc/localtime
name: volume-localtime
volumes:
- hostPath:
path: /run/docker.sock
type: ''
name: volume-image-0
- name: volume-jenkins
persistentVolumeClaim:
claimName: pvc-nfs-jk
- hostPath:
path: /etc/localtime
type: ''
name: volume-localtime
vi svc.yaml
kind: Service
apiVersion: v1
metadata:
name: jenkins-svc
namespace: infra
spec:
ports:
- name: jenkins-svc-8080-8080
port: 8080
protocol: TCP
targetPort: 8080
- name: jenkins-svc-50000-50000
port: 50000
protocol: TCP
targetPort: 50000
selector:
app: jenkins
vim ingress.yaml
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: jenkins-ingress
namespace: infra
spec:
rules:
- host: jenkins.example.com#ingress定义对外域名
http:
paths:
- path: /
backend: #绑定server资源配置清单内容
serviceName: jenkins-svc
servicePort: 80
在运维主机上应用资源配置清单
kubectl apply -f http://k8s-yaml.example.com/jenkins/dp.yaml
kubectl apply -f http://k8s-yaml.example.com/jenkins/svc.yaml
kubectl apply -f http://k8s-yaml.example.com/jenkins/ingress.yaml
查看jenkins密码
cd /opt/data/nfs-volume/jenkins_home/
Secret填写你k8s集群的访问token
创建token
创建jenkins用户
kubectl create serviceaccount jenkins -n infra
绑定admin角色到jenkins用户
$ clusterrolebinding NAME --clusterrole=NAME [–user=username] [–group=groupname] [–serviceaccount=namespace:serviceaccountname] [–dry-run]
kubectl create clusterrolebinding -n infra jenkins-cluster-admin --clusterrole='cluster-admin' --serviceaccount=infra:jenkins
查询token
kubectl get secrets -n infra-o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='jenkins')].data.token}" | base64 -d
结果填入secret
描述:访问k8stoken
系统管理在节点列表中选择configure clouds
名称:kubernetes
Kubernetes 地址:https://kubernetes.default.svc.cluster.local:443
Kubernetes 命名空间:infra
凭据:访问k8stoken
连接测试
Jenkins 地址:http://jenkins-svc:8080
Jenkins 通道:jenkins-svc:50000
保存应用
临时创建一个demo项目测试是否能正常动态启动jenkins-slave后销毁
创建一个叫demo 的Pipeline
pipeline脚本
def label = "mypod-${UUID.randomUUID().toString()}"
podTemplate(label: label, cloud: 'kubernetes') {
node(label) {
stage('Run shell') {
sh 'sleep 130s'
sh 'echo hello world.'
}
}
}
https://plugins.jenkins.io/kubernetes/