1. Jenkins部署
1.1 基于k8s部署
1.1.1 创建命名空间
kubectl create namespace devops
kubectl create namespace devops
1.1.2 创建RABC
1.jenkins-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins-sa
namespace: devops
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: jenkins-cr
rules:
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- apiGroups: [""]
resources: ["services"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- 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"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jenkins-crd
roleRef:
kind: ClusterRole
name: jenkins-cr
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: jenkins-sa
namespace: devops
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins-sa
namespace: devops
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: jenkins-cr
rules:
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- apiGroups: [""]
resources: ["services"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- 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"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jenkins-crd
roleRef:
kind: ClusterRole
name: jenkins-cr
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: jenkins-sa
namespace: devops
- 执行
kubectl apply -f 1.jenkins-rbac.yaml
kubectl apply -f 1.jenkins-rbac.yaml
1.1.3 创建存储
2.jenkins-pvc-nfs.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-pvc
namespace: devops
spec:
accessModes:
- ReadWriteMany
storageClassName: "nfs-provisioner-storage"
resources:
requests:
storage: 5Gi #根据线上环境修改
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-pvc
namespace: devops
spec:
accessModes:
- ReadWriteMany
storageClassName: "nfs-provisioner-storage"
resources:
requests:
storage: 5Gi #根据线上环境修改
- 执行
kubectl apply -f 2.jenkins-pvc-nfs.yaml
kubectl apply -f 2.jenkins-pvc-nfs.yaml
1.1.4 创建svc
3.jenkins-deploy-svc.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
namespace: devops
spec:
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
terminationGracePeriodSeconds: 10
serviceAccount: jenkins-sa
containers:
- name: jenkins
image: registry.cn-zhangjiakou.aliyuncs.com/hsuing/jenkins:2.452.3-lts
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: web
protocol: TCP
- containerPort: 50000
name: agent
protocol: TCP
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 1Gi
livenessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
readinessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
volumeMounts:
- name: jenkinshome
mountPath: /var/jenkins_home
env:
- name: JAVA_OPTS
value: -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Duser.timezone=Asia/Shanghai -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
securityContext:
#ifsGroup: 1000
runAsUser: 0
volumes:
- name: jenkinshome
persistentVolumeClaim:
claimName: jenkins-pvc
---
apiVersion: v1
kind: Service
metadata:
name: jenkins
namespace: devops
labels:
app: jenkins
spec:
selector:
app: jenkins
type: ClusterIP
ports:
- name: web
port: 8080
targetPort: web
- name: agent
port: 50000
targetPort: agent
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
namespace: devops
spec:
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
terminationGracePeriodSeconds: 10
serviceAccount: jenkins-sa
containers:
- name: jenkins
image: registry.cn-zhangjiakou.aliyuncs.com/hsuing/jenkins:2.452.3-lts
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: web
protocol: TCP
- containerPort: 50000
name: agent
protocol: TCP
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 1Gi
livenessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
readinessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
volumeMounts:
- name: jenkinshome
mountPath: /var/jenkins_home
env:
- name: JAVA_OPTS
value: -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Duser.timezone=Asia/Shanghai -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
securityContext:
#ifsGroup: 1000
runAsUser: 0
volumes:
- name: jenkinshome
persistentVolumeClaim:
claimName: jenkins-pvc
---
apiVersion: v1
kind: Service
metadata:
name: jenkins
namespace: devops
labels:
app: jenkins
spec:
selector:
app: jenkins
type: ClusterIP
ports:
- name: web
port: 8080
targetPort: web
- name: agent
port: 50000
targetPort: agent
- 执行
kubectl apply -f 3.jenkins-deploy-svc.yaml
kubectl apply -f 3.jenkins-deploy-svc.yaml
参数介绍:
默认情况下,Jenkins生成代理是保守的。
例如,如果队列中有两个构建,它不会立即生成两个执行器。它将生成一个执行器,并等待某个时间释放第一个执行器,然后再决定生成第二个执行器。Jenkins确保它生成的每个执行器都得到了最大限度的利用。
如果你想覆盖这个行为,并生成一个为每个构建队列不等待的执行器,所以在Jenkins启动时候添加这些参数:
-Dhudson.slaves.NodeProvisioner.initialDelay=0
-Dhudson.slaves.NodeProvisioner.MARGIN=50
-Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
1.1.5 创建ingress
4.jenkins-ing.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jenkins-ingress
namespace: devops
spec:
ingressClassName: nginx
rules:
- host: jenkins.ikubernetes.net
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: jenkins
port:
number: 8080
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jenkins-ingress
namespace: devops
spec:
ingressClassName: nginx
rules:
- host: jenkins.ikubernetes.net
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: jenkins
port:
number: 8080
- 执行
kubectl apply -f 4.jenkins-ing.yaml
kubectl apply -f 4.jenkins-ing.yaml
1.1.6 访问
- 查看密码
kubectl logs jenkins-6b59fcc49-4dwnc -n devops
kubectl logs jenkins-6b59fcc49-4dwnc -n devops
2. Jenkins Slave部署
2.0 Jenkins Master/Slave架构
基于k8s拉起的服务,实际上都是以Pod形式存在的,而Pod是个容器组, 最终服务实际是以Pod内的Container来支撑运行的。那么针对Slave的应用场景, Container应该如何设计?
- Jenkins-Master在构建Job的时候,Kubernetes会创建Jenkins-Slave的Pod来完成 Job的构建
- 我们选择运行Jenkins-Slave的镜像为官方推荐镜像:jenkins/inbound-agent:latest,但是这个镜像里面并没有Maven 环境,为了方便使用,我们需要自定义一个新的镜像
这里我们使用docker进行slave的构建,Dockerfile
#FROM jenkins/jnlp-slave:latest
#FROM jenkins/jnlp-slave:4.13.3-1-jdk11
#
FROM registry.cn-zhangjiakou.aliyuncs.com/hsuing/inbound-agent:latest-jdk11
MAINTAINER han
# 切换到 root 账户进行操作
USER root
# 安装 maven
COPY apache-maven-3.3.9-bin.tar.gz .
RUN tar -zxf apache-maven-3.3.9-bin.tar.gz && \
mv apache-maven-3.3.9 /usr/local && \
rm -f apache-maven-3.3.9-bin.tar.gz && \
ln -s /usr/local/apache-maven-3.3.9/bin/mvn /usr/bin/mvn && \
ln -s /usr/local/apache-maven-3.3.9 /usr/local/apache-maven && \
mkdir -p /usr/local/apache-maven/repo
COPY settings.xml /usr/local/apache-maven/conf/settings.xml
USER jenkins
#FROM jenkins/jnlp-slave:latest
#FROM jenkins/jnlp-slave:4.13.3-1-jdk11
#
FROM registry.cn-zhangjiakou.aliyuncs.com/hsuing/inbound-agent:latest-jdk11
MAINTAINER han
# 切换到 root 账户进行操作
USER root
# 安装 maven
COPY apache-maven-3.3.9-bin.tar.gz .
RUN tar -zxf apache-maven-3.3.9-bin.tar.gz && \
mv apache-maven-3.3.9 /usr/local && \
rm -f apache-maven-3.3.9-bin.tar.gz && \
ln -s /usr/local/apache-maven-3.3.9/bin/mvn /usr/bin/mvn && \
ln -s /usr/local/apache-maven-3.3.9 /usr/local/apache-maven && \
mkdir -p /usr/local/apache-maven/repo
COPY settings.xml /usr/local/apache-maven/conf/settings.xml
USER jenkins
❌ 注意
这里的jdk一定的和jenkins中的jdk保持一致,否则会出现通信问题
- 构建镜像
docker build -t registry.cn-zhangjiakou.aliyuncs.com/hsuing/jenkins-slave-maven:v1 .
docker build -t registry.cn-zhangjiakou.aliyuncs.com/hsuing/jenkins-slave-maven:v1 .
- 上传镜像
git push registry.cn-zhangjiakou.aliyuncs.com/hsuing/jenkins-slave-maven:v1
git push registry.cn-zhangjiakou.aliyuncs.com/hsuing/jenkins-slave-maven:v1
为了不侵入宿主机Node上的docker服务,那么目前最佳的思路是要引入Docker in Docker技术来完成:
docker tag docker:stable registry.cn-zhangjiakou.aliyuncs.com/hsuing/docker:stable
docker tag docker:stable registry.cn-zhangjiakou.aliyuncs.com/hsuing/docker:stable
2.1 原理
当 Jenkins Master 接受到 Build 请求时,会根据配置的 Label 动态创建一个运行在 Pod 中的 Jenkins Slave 并注册到 Master 上,当运行完 Job 后,这个 Slave 会被注销并且这个 Pod 也会自动删除,恢复到最初状态。
2.2 优势
- 负载均衡:Master-Slave模式让Jenkins可以在多台机器中分布任务,从而提高Jenkins处理任务的能力。
- 故障容错:Master-Slave模式在Jenkins系统出现故障时能够提供更好的支持。
- 扩展性:使用Master-Slave模式可以帮助Jenkins系统轻松扩展。
- 分布式构建:在Master-Slave模式下,Jenkins可以在多个Slave节点运行不同的任务,从而实现分布式构建。
- 安全性:Master-Slave模式可以提高Jenkins系统的安全性。
2.3 测试验证
def git_address = "http://house.freehan.ink/root/springdemo.git"
def git_auth = "731f32c4-0a6d-4dca-989f-50b7cdc0c85c"
//创建一个Pod的模板,label为jenkins-slave
podTemplate(label: 'jenkins-slave', cloud: 'kubernetes', containers: [
containerTemplate(
name: 'jnlp',
image: "registry.cn-zhangjiakou.aliyuncs.com/hsuing/jenkins-slave-maven:v1"
)
]
)
{
//引用jenkins-slave的pod模块来构建Jenkins-Slave的pod
node("jenkins-slave"){
stage('拉取代码'){
checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
}
}
}
def git_address = "http://house.freehan.ink/root/springdemo.git"
def git_auth = "731f32c4-0a6d-4dca-989f-50b7cdc0c85c"
//创建一个Pod的模板,label为jenkins-slave
podTemplate(label: 'jenkins-slave', cloud: 'kubernetes', containers: [
containerTemplate(
name: 'jnlp',
image: "registry.cn-zhangjiakou.aliyuncs.com/hsuing/jenkins-slave-maven:v1"
)
]
)
{
//引用jenkins-slave的pod模块来构建Jenkins-Slave的pod
node("jenkins-slave"){
stage('拉取代码'){
checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
}
}
}
731f32c4-0a6d-4dca-989f-50b7cdc0c85c 这个是当时创建凭证时创建出来的
- 效果
#会产生一个slave的pod进行编译,编译完自动销毁这个pod
[root@kube-master jenkins]# kubectl get pod |grep jenkins
jenkins-slave-wwd15-qkbv3 1/1 Running 0 9s
#会产生一个slave的pod进行编译,编译完自动销毁这个pod
[root@kube-master jenkins]# kubectl get pod |grep jenkins
jenkins-slave-wwd15-qkbv3 1/1 Running 0 9s
3. jenkins加速
cd /data/nfs/pv01/devops/jenkins-pvc/updates
sed -i 's#http://updates.jenkins-ci.org/download#https://mirrors.tuna.tsinghua.edu.cn/jenkins#g;s#http://www.google.com#https://www.baidu.com#g' default.json
cd /data/nfs/pv01/devops/jenkins-pvc/updates
sed -i 's#http://updates.jenkins-ci.org/download#https://mirrors.tuna.tsinghua.edu.cn/jenkins#g;s#http://www.google.com#https://www.baidu.com#g' default.json
4. jenkins界面重启
- 安全重启:
http://[jenkins-server]/safeRestart
- 立即重启:
http://[jenkins-server]/restart
5. jenkins关闭更新
忽略Jenkins系统警告 转到Manage Jenkins => Configure System => Administrative monitors configuration,不勾选 Jenkins Update Notification
忽略插件升级或安全警告,转到 Manage Jenkins => Configure Global Security => Hidden security warnings,不勾选插件警告
忽略Jenkins系统警告 转到Manage Jenkins => Configure System => Administrative monitors configuration,不勾选 Jenkins Update Notification
忽略插件升级或安全警告,转到 Manage Jenkins => Configure Global Security => Hidden security warnings,不勾选插件警告
6. helm部署Jenkins
https://github.com/civo/kubernetes-marketplace/blob/master/jenkins/install.sh