一、介绍
- 简要介绍
Jenkins是一个可扩展的持续集成/持续部署引擎。
持续集成/持续部署,就是通常所说的CI/CD,是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员至少集成一次,也意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误,在集成完成后,再通过手动触发的方式将交付内容部署到服务器上。这个过程可以大大减少集成的问题,让团队能够更快的进行软件开发。
- 应用场景
场景1 :持续集成/持续部署
集成 Git/SVN 等代码管理工具实现源码检出,集成 maven/ant/gradle 等构建工具实现源代码编译、打包的构建过程,集成 docker/kubernetes 等容器和编排管理工具实现基于容器的持续部署
场景2:自动化测试
利用 Jenkins + ant + jmeter 搭建持续集成的自动化测试平台
二、环境要求
硬件要求
支持硬件
软件要求
Jenkins 的 Web 应用程序 ARchive(WAR)文件版本可以安装在任何支持 Java 的操作系统或平台上。如果以容器方式运行,则不需要考虑 JDK 版本。
三、准备工作
如果在 Docker 或 Kubernetes 环境中安装,需要提前准备 Docker 或 Kubernetes 环境和可连接的 Jenkins 镜像仓库地址或提前下载好镜像
如果在物理机上安装,需要下载好 Jenkins 的 war 包并配置 JDK 环境和安装 Tomcat.
四、部署流程
在 Docker 环境安装
在 Docker 环境安装比较简单,只需要拉取镜像后,一条启动命令即可实现安装
拉取镜像
dockerhub上的 jenkins 项目现在提供长期支持版(LTS)镜像
docker pull jenkins/jenkins:lts
新建工作目录
注意:在安装jenkins时候,挂载文件夹 /home/jenkins/ 的归属用户id必须是1000,否则会抛出无操作权限异常。
mkdir /home/jenkins
chown -R 1000:1000 /home/jenkins/
启动容器
docker run -itd -p 9999:8080 -p 50000:50000 --name jenkins --privileged=true -v /home/jenkins:/var/jenkins_home jenkins/jenkins:lts
启动命令中使用到的参数说明如下:
-
--privileged=true
-
-p 9090:8080
-
-v /home/jenkins:/var/jenkins_home
在 Kubernetes 环境安装
创建工作空间(NameSpace)
在k8s集群内创建Jenkins工作的namespace,这里创建一个新的工作目录命名为 jenkins
kubectl create ns jenkins
准备存储挂载(NFS PV PVC)
为 Jenkins 创建 pv-pvc,挂载点使用 nfs 服务:
jenkins-pv-pvc.yaml 的内容如下
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins-home-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
server: 10.8.56.30
path: "/home/jenkins_home"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-home-pvc
namespace: jenkins
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 10Gi
在NFS 服务器上做如下设置:
# 编辑 /etc/exports 文件
$ vim /etc/exports
# 新增一行记录
/home/jenkins_home *(rw,sync,no_root_squash)
# 重启 nfs
$ service nfs-server restart
/etc/exports的参数说明:[共享的目录] [主机名或IP(参数,参数)]
ro 只读访问 rw 读写访问 sync 所有数据在请求时写入共享 async NFS在写入数据前可以相应请求 secure NFS通过1024以下的安全TCP/IP端口发送 insecure NFS通过1024以上的端口发送 wdelay 如果多个用户要写入NFS目录,则归组写入(默认) no_wdelay 如果多个用户要写入NFS目录,则立即写入,当使用async时,无需此设置。 hide 在NFS共享目录中不共享其子目录 no_hide 共享NFS目录的子目录 subtree_check 如果共享/usr/bin之类的子目录时,强制NFS检查父目录的权限(默认) no_subtree_check 和上面相对,不检查父目录权限 all_squash 共享文件的UID和GID映射匿名用户anonymous,适合公用目录。 no_all_squash 保留共享文件的UID和GID(默认) root_squash root用户的所有请求映射成如anonymous用户一样的权限(默认) no_root_squas root用户具有根目录的完全管理访问权限 anonuid=xxx 指定NFS服务器/etc/passwd文件中匿名用户的UID anongid=xxx 指定NFS服务器/etc/passwd文件中匿名用户的GID
创建服务账号(ServiceAccount)
为 Jenkins 创建 ServiceAccount,因为有时候需要从 Jenkins 的 Pod 中发起对 Kubernetes 资源的操作,为了赋予权限,这里的 ClusterRole 直接使用的 cluster-admin 超级管理员
jenkins-serveraccount.yaml 的内容如下
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: jenkins
name: jenkins-admin
namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jenkins-admin
labels:
app: jenkins
subjects:
- kind: ServiceAccount
name: jenkins-admin
namespace: jenkins
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
准备配置文件(Deployment)
编写 Deployment 文件,在这之前,先给要分配 Jenkins-master 服务的 node 打标签(利用亲和性将 jenkins-master 固定在 node1):
$ kubectl label node node1
apps.k8s.jenkins/devops=
$ kubectl label node node1 jenkins-test=
标签的键值按需修改,需要和下面 yaml 文件中亲和性中 matchExpressions 保持一致
jenkins-deployment.yaml 如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
namespace: jenkins
labels:
app: jenkins
spec:
selector:
matchLabels:
app: jenkins
replicas: 1
template:
metadata:
labels:
app: jenkins
spec:
serviceAccountName: jenkins-admin
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: jenkins-test
operator: Exists
containers:
- name: jenkins
image: jenkins/jenkins:lts #镜像按需修改
imagePullPolicy: IfNotPresent
securityContext:
runAsUser: 0 #设置以ROOT用户运行容器
privileged: true #拥有特权
volumeMounts:
- name: jenkins-home
mountPath: /var/jenkins_home
readOnly: false
- name: docker-sock
mountPath: /var/run/docker.sock
- name: docker-cli
mountPath: /usr/bin/docker
ports:
- containerPort: 8080
- containerPort: 50000
volumes:
- name: jenkins-home
persistentVolumeClaim:
claimName: jenkins-home-pvc
- name: docker-sock
hostPath:
path: /var/run/docker.sock
- name: docker-cli
hostPath:
path: /usr/bin/docker
准备服务文件(Service)
创建 service,使用 NodePort 或者 ingress:
jenkins-service.yaml 示例如下;
apiVersion: v1
kind: Service
metadata:
labels:
app: jenkins
name: jenkins
namespace: jenkins
annotations:
prometheus.io/scrape: 'true'
spec:
type: NodePort
ports:
- name: jenkins-web
port: 8080
targetPort: 8080
nodePort: 31442
- name: jenkins-agent
port: 50000
targetPort: 50000
nodePort: 30005
selector:
app: jenkins
jenkins-ingress.yaml 示例如下:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: jenkins
labels:
name: jenkins
namespace: jenkins
spec:
rules:
- host: jenkins.eastcom.cn
http:
paths:
- path: /
backend:
serviceName: jenkins
servicePort: 8080
在 Linux 环境安装
直接在 Linux 上安装需要配合 JDK 和 Tomcat,安装步骤较复杂,建议使用 Docker 或 K8S 安装
安装 JDK
Jenkins 的安装依赖 JDK 环境,版本对应关系如下:
# 1. 创建目录
mkdir /usr/local/jdk
cd /usr/local/jdk
# 2. 下载安装包至当前目录并解压
## 下载地址:https://www.oracle.com/java/technologies/downloads/#java17
tar zxvf jdk-17_linux-x64_bin.tar.gz
# 3. 配置环境变量,添加下面的内容
## export JAVA_HOME=/usr/local/java/jdk1.8.0_144
## export CLASSPATH=$:CLASSPATH:$JAVA_HOME/lib/
## export PATH=$PATH:$JAVA_HOME/bin
vim /etc/profile
source /etc/profile
# 4. 验证安装(检查版本)
java -version
安装 Tomcat
# 1. 创建目录
mkdir /usr/local/tomcat
cd /usr/local/tomcat
# 2. 下载安装包至当前目录并解压
## 下载地址:http://tomcat.apache.org/
tar -zxvf apache-tomcat-10.1.6.tar.gz
mv apache-tomcat-10.1.6/ tomcat10
启动 Jenkins
通过 Tomcat 来启动 Jenkins
# 1. 进入 tomcat webapps 目录
cd /usr/local/tomcat/tomcat10/webapps
# 2. 下载 Jenkins war 包到当前目录
## 下载地址:https://www.jenkins.io/download/
# 3. 启动 tomcat 带起 Jenkins
## 在tomcat的 bin 目录下
./startup.sh