Jenkins 安装

Jenkins 支持主流的 Linux 发行版系统,同时还支持 macOS、Windows、和 Docker 运行。 具体系统的 Jenkins 安装包可以去官网下载 https://www.jenkins.io/download

作为运行在生产环境,推荐在 CentOS 中安装,目前容器技术也非常流行,在 Docker 中运行 Jenkins 也是不错的选择。接下来将会演示在 CentOS 和 Docker 中运行 Jenkins 服务。

Jenkins 的版本迭代非常快,插件也是每天都有更新。目前 Jenkins 界面也有非常大的改版,我测试对比了一下,只有 2.222.4 及以下的版本界面还是熟悉的样子,2.222.4 之后的版本在 UI 界面上变化非常大,特别是配置管理的功能菜单要花点时间熟悉下。所以我后面的演示操作全是基于 Jenkins 2.222.4 版本,如果各位有兴趣可以尝试用一用最新版的 Jenkins。

Linux 下安装 Jenkins

直接在 Linux 中安装 Jenkins 需要做以下的几件事,参见详细步骤:

1、Jenkins 运行时需要安装 Git 和 JDK

# 安装最新版的 git 和 JDK 1.8
$ sudo yum install git java-1.8.0-openjdk

2、设置 Jenkins 源并安装 Jenkins

# 安装指定版本的 Jenkins
$ wget https://pkg.jenkins.io/redhat-stable/jenkins-2.222.4-1.1.noarch.rpm
$ sudo rpm -ivh jenkins-2.222.4-1.1.noarch.rpm # 安装最新版本的 Jenkins
$ sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
$ sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
$ sudo yum install jenkins -y # 将 Jenkins 加入开机启动项
$ sudo systemctl start jenkins
$ sudo systemctl enable jenkins
$ sudo systemctl daemon-reload

3、允许 Jenkins 通过 Linux 防火墙

# Jenkins 默认运行在 8080 端口,允许8080端口通过防火墙
$ sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
$ sudo firewall-cmd --zone=public --add-service=http --permanent
$ sudo firewall-cmd --reload # 或者直接关闭防火墙
$ sudo firewall-cmd --state # 查看防火墙状态
$ sudo systemctl stop firewalld.service # 停止防火墙
$ sudo systemctl disable firewalld.service # 禁用防火墙开机启动 $ sudo systemctl enable firewalld.service # 起用防火墙开机启动
$ sudo systemctl start firewalld.service # 禁用防火墙开机启动

Docker 容器部署 Jenkins

采用容器来跑服务有个很大的好处,那就是搞坏了可以快速重新开始,这是我喜欢 Docker 的原因之一。采用 Docker 容器来跑 Jenkins 服务有两种方式:其一是直接使用 docker run 命令;其二就是使用 docker-compose 命令。推荐使用 docker-compose ,因为后期如果要升级 Jenkins 比较方便,更换下 Jenkins 镜像就可以了。下面还是将两种方式都做个记录,各自选择自己喜欢的方式进行实操。

为了让运行在 Docker 容器中的 Jenkins 也能执行 docker 相关命令,我们这里要把宿主机的 dockerdocker.sock 挂载到容器中。当然你也可以在 Jenkins 容器中再安装 Docker 服务,这就是 docker-in-docker 的模式了,docker-in-docker 的坑比较多,留给各位自己去探索吧,我这里就把宿主机的 docker 客户端和 docker daemon 挂载到 Jenkins 容器中。

注意点:

  1. 要想能执行 docker 命令,就需要将系统用户加到 docker 组,安装完 docker 服务这个组就会自动创建。
  2. docker 容器中运行 jenkins,容器里面是默认使用的 uid=1000 的 jenkins 用户启动的 jenkins 服务。
  3. 确保宿主机中存在一个系统账号,可以执行 docker 命令,并且和容器中的 jenkins 用户的 uid、gid和组的属性相同。

所以这里会涉及到调整系统用户的 id 和组的 id,相关操作和说明,参见后续的操作过程,当然你可以简单粗暴地将 docker 和 docker.sock 的权限设置为任何账号都可执行,但是不推荐这样,可能存在安全风险。

采用 docker run 的方式运行 Jenkins 容器

# 拉取指定版本 Jenkins 容器
$ docker pull jenkins/jenkins:2.222.4-lts-centos7 # 创建一个属于 Jenkins 容器的 docker 网络(可选,如果没创建,后面就不要指定网络)
$ docker network create jenkins_network # 运行 jenkins 容器
$ docker run --name jenkins-in-docker \
--network jenkins_network \
--publish 8080:8080 --publish 50000:50000 \
--volume jenkins_home:/var/jenkins_home \
--volume /usr/bin/docker:/usr/bin/docker \
--volume /var/run/docker.sock:/var/run/docker.sock \
jenkins/jenkins:2.222.4-lts-centos7

docker run 中的命令参数设置不做过多解释,不明白的可以自己去先熟悉下 docker 常用命令。这里单独说明下 --volume 数据卷的设置,该参数可以挂载宿主机的文件到容器,也可以创建新的数据卷,新的数据卷由 docker 容器管理,如果你是将 jenkins_home 目录挂载到宿主机,可能还会遇到 Jenkins 容器启动失败的问题。

# 看看容器日志 docker logs -f <container_id_or_name>
$ docker logs -f jenkins-in-docker --tail=50 touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions? # 如果看到是上面的内容,那就是目前权限的问题,需要把映射到宿主机的 jenkins_home 目录的所有权调整下
$ sudo chown -R 1000:1000 volume_dir

容器里面一般都是笔记精简的,能不要的东西就不要,这样可以保证容器镜像尽量安全且体积小,但有时我们确实需要在容器中安装些工具,但是又发现进入容器后默认的用户又没有管理权限,这是就需要用如下命令以管理员身份进入容器,然后在容器中安装工具,进行特殊操作都是可以的。

# 以root身份进入容器,有的容器没有 bash,将 bash 换成 sh 即可

$ docker exec -u 0 -it <container_id_or_name> bash

采用 docker-compose 方式运行 Jenkins 容器

采用 docker-compose 方式运行 Jenkins 容器,首先请确保自己系统可以执行 docker-compose 命令,如果还没安装 docker-compose 可翻看前面安装 docker 的章节。

新建一个目录,在下面创建 infrastructure-docker-compose.yml、startup-infrastructure-docker-compose.sh 两个文件。

docker-compose 配置文件如下 infrastructure-docker-compose.yml :

version: '3.7'

services:
jenkins-in-docker:
image: jenkins/jenkins:2.222.4-lts-centos7
container_name: jenkins-in-docker
privileged: true
restart: unless-stopped
ports:
- 8080:8080
- 50000:50000
environment:
JAVA_OPTS: "-Xmx2048m -Xms1024m -Djava.security.egd=file:/dev/./urandom -Duser.timezone=Asia/Shanghai -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
volumes:
- /usr/bin/docker:/usr/bin/docker
- /var/run/docker.sock:/var/run/docker.sock
- ./docker_data/jenkins/2.222.4/jenkins_home:/var/jenkins_home
- ./docker_data/jenkins/2.222.4/jenkins_home_bak:/var/jenkins_home_bak
networks:
- infrastructure_network
deploy:
resources:
limits:
memory: 4096M
cpus: '2' networks:
infrastructure_network:
external: true

下面就是启动 docker-compose 运行 jenkisn 服务,我这里专门写了个 shell 脚本,在演示的过程中有时需要重复的敲命令,写在 shell 脚本中直接运行就行,省去重复敲命令的繁琐。

shell 脚本 startup-infrastructure-docker-compose.sh :

#!/usr/bin/env bash

# 设置docker网络名称和docker-compose文件
docker_network=infrastructure_network
docker_compose_file=infrastructure-docker-compose.yml # 输出下docker-compose文件内容
echo "The compose file as below: "
docker-compose -f ${docker_compose_file} config nw=$(docker network ls | grep ${docker_network} | awk '{print $1}')
if [[ ${nw} ]]; then
docker-compose -f ${docker_compose_file} --compatibility up --remove-orphans -d
else
docker network create ${docker_network} && docker-compose -f ${docker_compose_file} --compatibility up --remove-orphans -d
fi

运行 shell 脚本,启动 Jenkins 服务:

# 设置shell脚本可执行
$ chmod +x startup-infrastructure-docker-compose.sh # 运行shell脚本
$ ./startup-infrastructure-docker-compose.sh

同样你可能还是会遇到 jenkins_home 目录权限问题,解决方式还是如下,调整目前所有权:

$ chown -R 1000:1000 docker_data/jenkins
$ ./startup-infrastructure-docker-compose.sh

没什么意外的话等个1分钟,就可以访问 Jenkins 服务了,或者看到 jenkins 日志 Jenkins is fully up and running 也说明 jenkins 已经启动好了。浏览器访问 http://host_ip:8080,如果访问不了,确保自己防火墙开放了 8080 端口。

Jenkins 日志和默认密码



输入 jenkins 默认密码,【继续】到下一步。



安装 Jenkins 插件,暂时不知道安装哪些插件的话可以选择默认【安装推进的插件】。



当然你也可以【选择插件来安装】,在里面选择自己想要的插件,每个插件的功能都有介绍。



选好后就点击【安装】,进入插件安装界面,这个界面要等几分钟,如果网络不好的话,有些插件还可能会安装失败,不过失败了也没关系,可以点击界面下的【重试】按钮,重新安装失败的插件。



插件安装好后就开始设置第一个管理员账号。



Jenkins URL 的设置,这里先默认即可,如果后面我们要为 Jenkins 服务设置域名可以重新在 Jenkins 的配置里面重新设置。



这就是 Jenkins 默认的界面了,目前还没有任何任务 Job。



这是管理 Jenkins 的界面,还是熟悉的界面。



如果你安装的 Jenkins 版本是 2.222.4 以上版本,就需要先熟悉下 Jenkins 的管理面板了。

这个版本是 2.263.1,我当时的最新版 Jenkins,下图是进入 Jenkins 的默认界面。



这是 Jenkins 的管理配置界面,对管理配置进行了分类,已经大变样了。



到这里你以为完了,并没有!还有个问题要解决,Jenkins 运行在容器中,并且希望可以正常执行 docker 命令。前面我们将宿主机的 docker 客户端和 docker.sock 挂载到了容器里面,现在在 Jenkins 容器里面执行 docker 命令你可能会遇到如下提示:

$ docker ps
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json: dial unix /var/run/docker.sock: connect: permission denied

这就很纳闷儿了,我宿主机上有个 jenkins 用户,并且 uid 也是 1000,为什么在 jenkins 容器中还是不能执行 docker 相关命令呢?我的排查过程如下:

先看看我在宿主机上的用户信息:

$ id jenkins
uid=1000(jenkins) gid=1000(jenkins) 组=1000(jenkins),10(wheel),994(docker) 环境=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

可以看到 jenkins 这个用户的 uid、gid和所属组的信息,我们再看看容器中 jenkins 的 uid、gid 信息:

$ docker exec -it jenkins-in-docker bash
bash-4.2$ id jenkins
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)

发现 Jenkins 容器默认的 jenkins 用户没有在 docker 组中,处理方式如下:

# 以 root 身份进入容器
$ docker exec -it -u root jenkins-in-docker bash # 看看用户和组信息
[root@e77ed7439afd ~]$ cat /etc/group

jenkins:x:1000:
docker:x:997:
⋮ # 发现docker组存在,但是宿主机docker组的id=994,容器中docker组的id=997
# 我们先将jenkins用户加入到docker组中试试
[root@e77ed7439afd ~]$ usermod -aG docker jenkins
[root@e77ed7439afd ~]$ id jenkins
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins),997(docker) # 退出容器,将jenkins容器重启下
$ docker restart jenkins-in-docker # 以默认身份进入容器
$ docker exec -it jenkins-in-docker bash
bash-4.2$ docker ps
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json: dial unix /var/run/docker.sock: connect: permission denied # 发现还是不能执行docker命令,我们把docker组的id也调整成和宿主机一样试试
$ docker exec -it -u root jenkins-in-docker bash
[root@e77ed7439afd ~]$ groupmod -g 994 docker
[root@e77ed7439afd ~]$ id jenkins
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins),994(docker) # 再重启下jenkins容器,以默认用户进入容器看能否执行docker命令
$ docker exec -it jenkins-in-docker bash
bash-4.2$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e77ed7439afd jenkins/jenkins:2.222.4-lts-centos7 "/sbin/tini -- /usr/…" 2 weeks ago Up 4 seconds 0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp jenkins-in-docker
5f89b1a44f39 mysql:8.0.17 "docker-entrypoint.s…" 4 weeks ago Up 2 weeks 0.0.0.0:3306->3306/tcp, 33060/tcp mysql-in-docker
87c2dcc88c71 nginx:1.18.0 "/docker-entrypoint.…" 4 weeks ago Up 2 weeks 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx-in-docker
bash-4.2$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker 20.10.1-dind 8d54f09a2b77 5 weeks ago 256MB
nginx 1.18.0 05f64a802c26 6 weeks ago 133MB
jenkins/jenkins 2.222.4-lts-centos7 32078832282a 7 months ago 637MB
mysql 8.0.17 b8fd9553f1f0 16 months ago 445MB # 如果容器中没有docker用户组,直接创建一个docker并设置docker组ID与宿主机docker组ID相同,然后将jenkins用户加入docker组
$ groupadd -g 994 docker && usermod -aG docker jenkins

现在发现在容器中可以正常执行 docker 命令了,其实总结起来就两点:

  • 容器中默认的 jenkins 用户要在 docker 组中。
  • 容器中 docker 组的 id 要保持和宿主机的 docker 组的 id 相同。

OK,到此才算是真正地做完了 jenkins 服务的准备工作,我们将宿主机的 docker 挂载到容器中,并且在尽量不调整宿主机的设置,做到了在容器中可以完美执行 docker 命令。

插件下载加速

Jenkins 插件的官方源在国外,下载速度非常慢,国内也有一些镜像源,但是却做得不彻底,实际上还是会从国外下载。经过我自己测试验证,以及在网上寻找到的资料,有以下的几种方式来加速 Jenkins 插件的下载,但是具体哪种方式有效,各位也可以自己试试看。

  1. 修改默认的配置文件,使其从国内镜像源下载

在 Jenkins 的安装目录下有个updates目录,该目录下有个default.json文件,该文件就是插件镜像源的JSON内容。修改这个文件,将里面的 mirrors.jenkins-ci.org 批量替换成 mirrors.tuna.tsinghua.edu.cn/jenkins 或者你自己知道并且想使用的镜像源,将 www.google.com 替换成 www.baidu.com 即可。

  1. 设置反向代理,将下载源从官方源代理到国内镜像源

主要是将 Jenkins 插件下载地址代理到清华等国内的 Jenkins 插件下载地址。在 Jenkins 机器上安装 Nginx 服务,然后添加一条hosts记录:127.0.0.1 updates.jenkins-ci.org 然后修改 Nginx 的配置文件:

rewrite ^/download/plugins/(.*)$ https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/$1? last;

# 或者添加一条 location 配置
location /download/plugins {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_set_header Host mirrors.tuna.tsinghua.edu.cn;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
rewrite /download/plugins(.*) /jenkins/plugins/$1 break;
proxy_pass https://mirrors.tuna.tsinghua.edu.cn;
}
  1. 设置 Jenkins 插件的升级站点

Jenkins 系统管理 → 插件管理 → 高级 → 升级站点,设置国内的镜像源。

  1. 使用 Localization: Chinese (Simplified) 插件

安装 Localization: Chinese (Simplified) 插件后,在 Jenkins 界面的右下角会多出一个【Jenkins 中文社区】按钮。点击进去你会看到 Jenkins 中文社区的介绍和二维码,下边还有个【更新中心镜像设置】,点击下【使用】按钮,然后将 Jenkins 的默认的升级站点 https://updates.jenkins.io/update-center.json 修改为 https://updates.jenkins-zh.cn/update-center.json ,【提交】修改后【立即获取】试试看,没什么问题就可以去【可选插件】里面找几个插件安装看看速度是不是快多了。

经过我自己的测试和验证,目前第4种方式是最有效且没有什么问题的。其他方式都是治标不治本,并且还可能会遇到如下签名校验不过的问题。



关于 Jenkins 镜像源加速站点在使用过程中如果有什么问题,可以参考 Jenkins 中文社区的一些解答 https://community.jenkins-zh.cn/t/jenkins/26

Jenkins 基础篇 - 安装部署的更多相关文章

  1. Jenkins 基础篇 - 插件安装

    这一小节主要介绍 Jenkins 插件的安装,登录到 Jenkins 后,依次进入到[系统管理]→ [插件管理]→ [可选插件],在这里可以看到所有的 Jenkins 插件,如下图: 我们在最开始安装 ...

  2. Jenkins: 基础篇(环境配置)

    自动化领域比较有影响力的开源框架jenkins,确实比较强大,易用.很多公司将其用来做持续即成CI(continuous integration).为了拓展和强化自己的软件设计生态系统,也将很久前使用 ...

  3. JENKINS系统的安装部署

    JENKINS 安装使用文档 简介 Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台.这是一个免费的源代码,可以处理任何类型的构建或持续集成,集成Jenkins可 ...

  4. Jenkins 基础篇 - 环境准备

    前期准备 为了开发这套课程,我专门购买了一台二手戴尔服务器 Dell R720,同时把废弃多年的笔记本电脑也利用了起来.当然如果自己没有多余的电脑,也可以在自己电脑上安装 Vmware Worksta ...

  5. 开源EDR(OSSEC)基础篇- 02 -部署环境与安装方式

    https://yq.aliyun.com/articles/683077?spm=a2c4e.11163080.searchblog.9.753c2ec1lRj02l

  6. Jenkins 基础篇 - 小试牛刀

    现在我们来创建一个简单的 Jenkins 任务,这个任务输出 Java 版本信息和系统信息,通过这个任务我们先了解创建 Jenkins 任务的流程,以及了解一些对任务的基础设置,接下来就是演示任务的整 ...

  7. Jenkins 基础篇 - 任务创建

    前面了解了 Jenkins 上各种任务的区别后,我们就来实践应用下,先创建一个[文件夹]类型的任务,将我们目前的一些基础的演示任务[移动]到文件夹里面去,这样可以先做个简单的分类. 新建一个[文件夹] ...

  8. Sharepoint 2013 系列篇(安装部署)--上篇

    前言 sharepoint的部署是按照物理拓扑图的架构来部署,按照物理拓扑图架构分为一层拓扑图架构,二层拓扑图架构,三层拓扑图架构,多层拓扑图架构. 按照分层的拓扑图部署是按照需求来划分的,一层拓扑图 ...

  9. jmeter学习(1)基础支持+安装部署

    1. Apache jmeter 是100%的java桌面应用程序 支持的协议有:WEB-HTTP/HTTPS   , SOAP,   FTP,  JDBC,  LDAP, MAIL, MongoDB ...

随机推荐

  1. 2019 GDUT Rating Contest III : Problem C. Team Tic Tac Toe

    题面: C. Team Tic Tac Toe Input file: standard input Output file: standard output Time limit: 1 second M ...

  2. JVM笔记--如果你写JVM,最需要考虑的重要结构是什么?

    开局一张图,前面已经从每一部分解析过JVM的内存结构了,现在按照顺序来分析: 整体上来看:类文件从类加载子系统,加载完成之后,主要存放在方法区(JRockit和H9没有方法区,这里指的是HotSpot ...

  3. concurrentHashMap的put方法详解

    本文主要介绍ConcurrentHashMap的put操作如果有错误的地方欢迎大家指出. 1.ConcurrentHashMap的put操作 ConcurrentHashMap的put操作主要有3种方 ...

  4. Announcing cnblogs-hardening 1.0 Preview 1

    Release Notes Write about coding Note About coding Share about coding Talk about coding Comment abou ...

  5. 【linux】系统编程-8-Socket

    目录 前言 11. 套接字 11.1 Socket简介 11.2 socket() 11.3 bind() 11.4 connect() 11.5 listen() 11.6 accept() 11. ...

  6. 文字变图片——GitHub 热点速览 v.21.14

    作者:HelloGitHub-小鱼干 程序的力量,在 deep-daze 体现得淋漓尽致,你用一句话描述下你的图片需求,它就能帮你生成对应图片.同样的,appsmith 的力量在于你只要拖拽即可得到一 ...

  7. 【长文】Spring学习笔记(七):Mybatis映射器+动态SQL

    1 概述 本文主要讲述了如何使用MyBatis中的映射器以及动态SQL的配置. 2 MyBatis配置文件概览 MyBatis配置文件主要属性如下: <settings>:相关设置,键值对 ...

  8. Django 视图(View)

    1. 视图简介 2. URLconf 1)关联各应用下的 URLconf 2)URLconf 的编写 3)namespace 反向解析 3. 视图函数&错误视图 4. HttpRequest ...

  9. k8s deployment 金丝雀发布 更新的 暂停 恢复 回滚

    假设现在有业务需求,计划将所有的nginx 从镜像版本1.14更新到1.15,这一次发布不紧需要平滑发布,还需要 金丝雀发布,及确认其中一个Pod没有问题后在进行剩余的更新. 暂停与恢复也可以使用ym ...

  10. AdaBoostClassifier参数

    [AdaBoostClassifier] Adaboost-参数: base_estimator:基分类器,默认是决策树,在该分类器基础上进行boosting,理论上可以是任意一个分类器,但是如果是其 ...