个人亲自录制全套DevOps系列实战教程 :手把手教你玩转DevOps全栈技术
Jenkins概述
根据jenkins官网对自己的描述,它是一个可集成有1800+插件的自动化服务,
提供构建、部署和自动化的工程,可以说是opsdev的大总管,将开发的代码工程与环境紧密结合起来。以实现CI持续集成、CD持续发布的能力。
Jenkins构建镜像/部署容器
拉取jenkins lts长期稳定版本[JDK8]
构建自定义jenkins镜像Dockerfile
由于jenkins环境需要jdk、maven和git的支持,而jenkins现有镜像是没有全部集成这三个工具的,所以我们采用自己编写镜像文件,基于jenkins/jenkins:2.361.2-lts
注意:
Dockerfile中我们使用了些实现要准备的文件,如下:都需要拷贝到宿主机/docker/jenkins中(和Dockerfile和docker-compose.yml同目录)
运行Jenkins容器
为了方便维护,后续统一使用docker-compose.yml
Jenkins初始化
查看web页面入口密码:/var/jenkins_home/secrets/initialAdminPassword
入口:10.10.1.199:9078选择推荐安装即可:避免手动安装麻烦,如果这里安装失败也没关系,进入jenkins后可以更改为国内源后重新安装。
更新国内镜像源:ManageJenkins -> ManagePlugins -> Advance -> 升级站点
输入:http://mirror.esuni.jp/jenkins/updates/update-center.json重启:http://10.10.1.199:9078/restart
我这里安装后有一个警告:这个是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后的包发布到目标服务器(如微服务服务器等)
-> 安装完后重启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时会报错。
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 root@10.10.1.199
期间会要求输入宿主机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连接宿主机测试是否成功,如果不需要密码直接登录则表示成功,如下图:
问题:
此处我们使用的是宿主机的root账号登录,权限最大;如果是自建的普通账号,那么账号的home目录(保存authorized_keys的目录)需要设置成不允许其他用户和组操作,即755权限,而文件authorized_keys需要指定为700权限。而客户端jenkins生成的公私钥的目录也要做同样的权限修改。
Jenkins配置
"系统管理"->"系统配置"->"Publish over SSH"
配置完成后,点击测试提示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设置的目录都是基于宿主机的共享目录之上进行设置的。
Gitlab SSHKEY配置
其实和ssh免密登录几乎一样,只不过生成密钥对时需要指定使用哪个gitlab账号
生成密钥对后,只需要2步:
- 将公钥内容配置到gitlab对应账号的sshkey
- 将私钥配置到jenkins的凭证中
注意:这样配置将会是失败的,因为我们已经生成了2套公私钥,并且默认使用的是/etc/.ssh/ssh_config中指定的~/.ssh/id_rsa,而gitlab使用的是gitlab的账号,所以需要单独配置一下gitlab的认证使用哪个私钥,否则都去用默认的了,肯定会验证失败。
如果是如下结果,说明配置成功:
更正一个网上错误概念:
如上操作,其实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的仓库页面可以看到不会提示报错了
详细命令可参考OpenSSH官网:
https://www.openssh.com/manual.html