4

DevOps实战系列【第四章】:详解Jenkins搭建及使用

 1 year ago
source link: https://blog.51cto.com/u_15909716/5996627
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

个人亲自录制全套DevOps系列实战教程 :​ ​手把手教你玩转DevOps全栈技术​

DevOps实战系列【第四章】:详解Jenkins搭建及使用_ssh

Jenkins概述

根据jenkins官网对自己的描述,它是一个​ ​可集成有1800+插件​​​的自动化服务,
提供构建、部署和自动化的工程,可以说是opsdev的大总管,将开发的代码工程与环境紧密结合起来。以实现CI持续集成、CD持续发布的能力。

中文地址:
​​ ​https://www.jenkins.io/zh/doc/book/installing/​

Jenkins构建镜像/部署容器

拉取jenkins lts长期稳定版本[JDK8]

# 从dockerhub上能找到的支持jdk8的长期稳定版是2.346.3-2,所以这里就选的这个版本
# 可参看官网的jdk支持对照表:https://www.jenkins.io/doc/administration/requirements/java/
docker pull jenkins/jenkins:2.346.3-2-lts-centos7

构建自定义jenkins镜像Dockerfile

由于jenkins环境需要jdk、maven和git的支持,而jenkins现有镜像是没有全部集成这三个工具的,所以我们采用自己编写镜像文件,基于jenkins/jenkins:2.361.2-lts

​注意:​​Dockerfile中我们使用了些实现要准备的文件,如下:都需要拷贝到宿主机/docker/jenkins中(和Dockerfile和docker-compose.yml同目录)

1. jdk-8u181-linux-x64.tar.gz
2. apache-maven-3.8.6-bin.tar.gz
3. git-2.38.1.tar.gz
4. mvnrepo/settings.xml
因为jenkins作为使用maven的客户端,需要一个settings.xml,
这个文件就是用《DEVOPS系列[三]:详解Maven仓库环境及搭建》的即可(注意localRespository要修改)。
5. Dockerfile
6. docker-compose.yml
7. home:目录
8. mvnrepo/repo:目录
# 在vi /docker/jenkins中创建Dockerfile文件[避免下载jdk等,并和Dockerfile一起拷贝到宿主机的/docker/jenkins目录]

FROM jenkins/jenkins:2.346.3-2-lts-centos7
LABEL maintainer="[email protected]"
USER root
COPY * /docker/
WORKDIR /usr/local
RUN set -e \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo 'Asia/Shanghai' > /etc/timezone \
&& chmod 755 /docker/* \
&& mv -f /docker/jdk-8u181-linux-x64.tar.gz ./ \
&& tar -zxf jdk-8u181-linux-x64.tar.gz \
&& rm -f jdk-8u181-linux-x64.tar.gz \
&& echo "jdk install is complete!" \
&& echo "try to install maven ..." \
&& mv -f /docker/apache-maven-3.8.6-bin.tar.gz ./ \
&& tar -zxf apache-maven-3.8.6-bin.tar.gz \
&& rm -f apache-maven-3.8.6-bin.tar.gz \
&& echo "maven install is complete!" \
&& echo "try to install git ..." \
&& mv -f /docker/git-2.38.1.tar.gz ./ \
&& tar -zxf git-2.38.1.tar.gz \
&& rm -f git-2.38.1.tar.gz \
&& yum remove -y git \
&& yum install -y curl-devel expat-devel gettext-devel openssl-devel zlib-devel \
&& yum install -y gcc-c++ make \
&& cd git-2.38.1 && ./configure && make && make install \
&& echo "git install is complete!" \
&& yum clean all

ENV JAVA_HOME /usr/local/jdk1.8.0_181
ENV CLASSPATH .:$JAVA_HOME/lib
ENV MAVAN_HOME /usr/local/apache-maven-3.8.6
ENV GIT_HOME /usr/local/git-2.38.1
ENV PATH $JAVA_HOME/bin:$MAVAN_HOME/bin:$GIT_HOME:$PATH
ENV JAVA_OPTS "-Dfile.encoding=UTF8 -Dsun.jnu.encoding=UTF8 -Djava.security.egd=file:/dev/./urandom"

EXPOSE 8080
EXPOSE 50000
USER jenkins

运行Jenkins容器

为了方便维护,后续统一使用docker-compose.yml

# 1.首先在宿主机创建jenkins的容器目录/docker/jenkins
mkdir /docker/jenkins

# 2.因为jenkins容器启动后会自动使用jenkins用户(所属组为1000)来进行操作,所以需要给宿主机的/docker/jenkins目录授权,此处为简单我们直接使用777授权
chmod -R 777 /docker/jenkins

# 3.编写docker-compose.yml文件:vi docker-compose.yml

version: '3'
services:
jenkins:
build:
context: .
dockerfile: Dockerfile
image: 'lij/jenkins:2.346.3-2-lts-centos7'
restart: always
container_name: 'jenkins'
hostname: 'jenkins'
environment:
# 该参数为避免插件安装失败,不校验
- JAVA_OPTS="-Dhudson.model.DownloadService.noSignatureCheck=true"
ports:
- '9078:8080'
# 50000 端口是jenkins内部通过JNLP(java提供的一个通过浏览器可以访问java应用的机制)
- '50000:50000'
networks:
- 'exist-net-bloom'
volumes:
- '/docker/jenkins/home:/var/jenkins_home'
# maven仓库的映射,容器中的目录会自动创建
- '/docker/jenkins/mvnrepo:/mvnrepo'
- '/etc/timezone:/etc/timezone:ro'
- '/etc/localtime:/etc/localtime:ro'
networks:
exist-net-bloom:
external:
name: devops

Jenkins初始化

查看web页面入口密码:/var/jenkins_home/secrets/initialAdminPassword
入口:10.10.1.199:9078

选择推荐安装即可:避免手动安装麻烦,如果这里安装失败也没关系,进入jenkins后可以更改为国内源后重新安装。

DevOps实战系列【第四章】:详解Jenkins搭建及使用_docker_02

更新国内镜像源:ManageJenkins -> ManagePlugins -> Advance -> 升级站点
输入:​ ​http://mirror.esuni.jp/jenkins/updates/update-center.json​​​

DevOps实战系列【第四章】:详解Jenkins搭建及使用_git_03

重启:​ ​http://10.10.1.199:9078/restart​​​ DevOps实战系列【第四章】:详解Jenkins搭建及使用_ssh_04

我这里安装后有一个警告:这个是jenkins内置的jetty存在一个漏洞,具体大家可以点过去看一下,因为jenkins一般都在内网使用,忽略这个问题就行。

全局工具配置

maven的settings.xml我们已经通过宿主机的目录将其映射到容器内部,直接选择即可。

其他参照容器的环境变量设置好即可。

路径:系统管理->全局工具配置[如果路径不对,页面会直接报错,放心配置即可]

Jenkins插件安装

  • 集成maven插件:Maven Integration、Pipeline Maven Integration
  • 集成gitlab插件:GitLab、Generic Webhook Trigger、Git Parameter(允许选择分支、tag构建)
  • 集成ssh插件:Publish Over SSH,让jenkins具备通过ssh远程发布的能力,通俗讲就是通过ssh将build后的包发布到目标服务器(如微服务服务器等)
    DevOps实战系列【第四章】:详解Jenkins搭建及使用_docker_05

​-> 安装完后重启Jenkins服务​

【Publish Over SSH】配置

  • 基于用户名密码方法
  • 基于RSA公/私钥免密方式

路径:系统配置->Publish over SSH
主要功能就是可以让jenkins容器能够通过ssh命令远程到其他目标机器。

jenkins构建后的工程会在自身的/var/jenkins_home/workspace目录,而我们的前、后端服务一般都是单独,比如都是用docker,那么jendins构建的包就需要发送给可以构建docker镜像的服务器(如宿主机、kubernetes等),交由他们去将构建包打入镜像,然后部署镜像运行容器。【我们这里目标机器就是宿主机】

用户名密码方式

通过输入用户名和密码来完成ssh的鉴权,会存在中间人攻击的风险。

  • 原理:首次客户端要连接ssh服务时,如果客户端未携带公钥参数访问ssh服务,则ssh服务将本地的公钥下发给客户端,客户端使用收到的公钥将密码加密后发送,ssh服务收到密文后使用私钥解密,得到密码然后进行鉴权。
  • 风险:中间人攻击,如果客户端连接的是中间人的ssh服务,那么中间人很容易就得到了客户端的密码。
  • 配置方法:用户名密码方式比较简单,重点是RemoteDirectory,就是目标机器的目录,该目录在目标机器需要事先创建好,否则在配置页面test时会报错。
    DevOps实战系列【第四章】:详解Jenkins搭建及使用_docker_06
RSA公/私钥免密方式

客户端不需要输入密码直接连接ssh进行操作。

  • 原理:客户端需要自己生成一套公私钥,并提前将公钥发送给ssh服务,由ssh服务存储在自己的密钥配置文件(~/.ssh/authorized_keys)中.这样当客户端与ssh建立连接时,将会把自己的公钥传递给ssh服务,而ssh收到请求后发现客户端传递了公钥,所以将使用RSA认证,同时他也不会给客户端发送自己的公钥,而是将收到的公钥与自己保存的公钥列表比对,如果成功比对则通过在ssh服务创建一个随机数,并用收到的公钥加密发给客户端,客户端收到密文使用自己的私钥解密再讲解密后的随机数发回ssh服务,ssh服务收到后与创建时的随机数比对,成功则完成连接握手。
  • 优点:不存在中间人攻击,安全性高,但效率不如前者。
  • 配置方法:①服务端开启RSA验证 ②客户端生成RSA密钥对 ③客户端公钥提交至服务端 ④客户端配置使用RSA进行ssh连接 ⑤修改jenkins的配置
1.修改服务端ssh服务,开启RSA验证:

vi /etc/ssh/sshd_config

RSAAuthentication yes #开启rsa验证 PubkeyAuthentication yes #通过公钥进行验证 AuthorizedKeysFile .ssh/authorized_keys #保存公钥的的服务端文件,该目录为>~/.ssh/authorized_keys

2.客户端生成RSA密钥:

进入jenkins容器,执行如下命令生成密钥对

# 生成密钥对,因为我们jenkins容器使用的是jenkins用户,而jenkins容器的默认用户是我们指定的/var/jenkins_home # 所以此处我们直接回车,使用默认的保存密钥对目录:/var/jenkins_home/.ssh/ # 继续回车会让输入私钥的加密密码,我们此处不输入直接回车,即不设置私钥密码(如果设置的话,打开私钥文件都需要输入密码) ssh-keygen -t rsa

此时进入/var/jenkins_home/.ssh/目录会发现已经生成了id_rsa(私钥)和id_rsa.pub(公钥)文件,其内容都是经过Base64编码后的内容。

3.客户端公钥拷贝到ssh服务器端:

此处我们使用远程公钥发送命令(在jenkins容器中执行如下命令)

ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

DevOps实战系列【第四章】:详解Jenkins搭建及使用_gitlab_07

期间会要求输入宿主机root账号密码(此处多以演示为主,线上我们一般会专号专用,根据需求设置账号权限,不会使用root账号操作)完成后,会在宿主机root账号的home目录的.ssh/authorized_keys中增加公钥内容,如果没有该文件会新建,如果有则会追加。

4.客户端配置开启RSA登录ssh:

vi /etc/ssh/ssh_config 【注意作为客户端是ssh_config起作用,作为服务端是sshd_config起作用,注意区分】

# 注意该文件为root权限修改,需要以root用户登录jenkins容器进行操作 docker exec -it -u root jenkins bash vi /etc/ssh/ssh_config

# 将以下注释释放即可 IdentityFile ~/.ssh/id_rsa

至此:配置完毕,可以直接在jenkins容器内部,通过ssh连接宿主机测试是否成功,如果不需要密码直接登录则表示成功,如下图:

DevOps实战系列【第四章】:详解Jenkins搭建及使用_ssh_08

​​​问题:​​ 此处我们使用的是宿主机的root账号登录,权限最大;如果是自建的普通账号,那么账号的home目录(保存authorized_keys的目录)需要设置成不允许其他用户和组操作,即755权限,而文件authorized_keys需要指定为700权限。而客户端jenkins生成的公私钥的目录也要做同样的权限修改。

Jenkins配置

"系统管理"->"系统配置"->"Publish over SSH"

DevOps实战系列【第四章】:详解Jenkins搭建及使用_ssh_09

配置完成后,点击测试提示Success即可。

​问题:​​​有些同学点击测试后可能会提示​​privatekey(Failed to add SSH key)​​错误。

​解答:​​​这是因为生成的私钥文件内容的格式有些问题,打开内容应该会发现开头是​​BEGIN OPENSSH...​​,而这不是标准的RSA私钥格式,

我们需要使用工具将内容转换成RSA格式,比如使用puttygen工具,有可视化界面,将私钥文件导入生成新的私钥再替换到jenkins容器的id_rsa即可。

当然也有命令行工具可以转换,这个交给大家自己去拓展吧,在此就不多说了。

标准RSA私钥文件内容开头应该是​​BEGIN RSA...​​。

​原因:​​之所以通过ssh-keygen -t rsa会生成"BEGIN OPENSSH..."样的私钥,是因为openssh生成密钥格式有两种,而老版本是"BEGIN RSA..."开头,新版本是"BEGIN OPENSSH..."开头,生成的是哪个版本看openssh的版本,当然也可以强制生成老版本格式,比如通过指定参数:

ssh-keygen -m PEM -t rsa,其中-m PEM就是生成RSA格式的密钥,这个大家知道下就行了,具体可以查看ssh-keygen的使用。

​关于sftp的简单了解​​​:其实ssh服务除了包括sshd服务还包含sftp服务,即我们设置了以上的免密登录,那么sftp也自动变成了免密登录,而sftp授权的根目录是一般是登录用户的home目录,如果需要调整则要到sshd_config中进行配置,而我用的是root免密,所以共享目录是/root,如果通过jenkins需要拷贝文件(Transfer Set)到远程目录,需要留意一下这个目录,jenkins设置的目录都是基于宿主机的共享目录之上进行设置的。 DevOps实战系列【第四章】:详解Jenkins搭建及使用_devops_10

Gitlab SSHKEY配置

其实和ssh免密登录几乎一样,只不过生成密钥对时需要指定使用哪个gitlab账号

# 在jenkins容器中生成密钥对,并指定gitlag账号
ssh-keygen -t rsa -C “登录gitlab的邮箱”
DevOps实战系列【第四章】:详解Jenkins搭建及使用_docker_11

生成密钥对后,只需要2步:

  • 将公钥内容配置到gitlab对应账号的sshkey
    DevOps实战系列【第四章】:详解Jenkins搭建及使用_gitlab_12
  • 将私钥配置到jenkins的凭证中
    DevOps实战系列【第四章】:详解Jenkins搭建及使用_ssh_13

注意:这样配置将会是失败的,因为我们已经生成了2套公私钥,并且默认使用的是/etc/.ssh/ssh_config中指定的~/.ssh/id_rsa,而gitlab使用的是gitlab的账号,所以需要单独配置一下gitlab的认证使用哪个私钥,否则都去用默认的了,肯定会验证失败。

DevOps实战系列【第四章】:详解Jenkins搭建及使用_docker_14
# 修改jenkins容器ssh_config配置文件:vi /etc/ssh/ssh_config
# ssh命令读取配置文件顺序:命令行参数 -> ~/.ssh/config -> /etc/ssh/ssh_config
Host 10.10.1.199 # 随意定义的一个名字【但因为我这里gitlab是将22端口映射到宿主机2224上,所以Host要指定为10.10.1.199,否则匹配补上】
HostName 10.10.1.199 # gitlab的ip地址【指定宿主机ip】
Port 2224 # 端口号,我们的gitlab映射ssh端口时指定的为2224
PreferredAuthentications publickey # 指定认证方式
User [email protected] # 指定登录gitlab的账号
IdentityFile ~/.ssh/gitlab_id_rsa # 指定为gitlab生成的证书的私钥绝对路径

# 操作完后可以在jenkins容器中先做测试,直接拉取gitlab代码看是否正常,注意要使用ssh方式拉取
git clone ssh://[email protected]:2224/devops/demo.git

如果是如下结果,说明配置成功: 

DevOps实战系列【第四章】:详解Jenkins搭建及使用_git_15

​更正一个网上错误概念:​​​如上操作,其实openssh的配置文件都是以一个Host节点为单位,可以配置多个Host,而默认的一般是"Host *",表示所有的都生效

但是网上有多数资料,在解决ssh客户端存在多个证书密钥时都需要配置一个ssh-add ~/.ssh/gitlab_id_rsa的命令,

其实这是不对的,一个很大的误导,ssh-add是向ssh-agent代理认证服务中添加私钥证书,如果添加了即便~/.ssh/config配置的不对也是生效的,

其实这是两种方式,前者是ssh自身读配置去建立连接,而ssh-agent是ssh将认证功能交给代理完成,而代理不会使用默认的配置,而是优先使用提交给代理高速缓存的证书进行验证,而ssh-add就是向高速缓存中存入证书信息,所以指定了ssh-add后,即便不配置~/.ssh/config也是可行的,但ssh-agent是一个临时存储,重启后缓存会清空。

​​​如果要用这种方式,则按如下操作即可:​

# 加入代理,如果执行报错【Could not open a connection to your authentication agent】 # 可以先执行命令:[ssh-agent bash],然后执行如下命令 ssh-add ~/.ssh/gitlab_id_rsa # 查看是否成功 ssh-add -l

最后我们在jenkins的仓库页面可以看到不会提示报错了

DevOps实战系列【第四章】:详解Jenkins搭建及使用_git_16

详细命令可参考OpenSSH官网:
​​ ​https://www.openssh.com/manual.html​


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK