Jenkins项目中配置Git分支

最近发现很多人在Jenkins上的项目构建配置中都是用*/xxx这种方式来指定branch的,分享一点相关的经验。

问题

当我们在Jenkins上新添加一个构建项目时,项目的默认配置中的Branches to build(也就是需要构建的目标分支)就是写着*/master,所以大部分不熟悉的使用者会选择像下图里一样直接把后面的master改成实际需要构建的branch name,而无视掉前面的*/。虽然在绝大多数情况下这样的配置是会正常工作不出问题,但是很明显配置中的*是起通配符作用的,这样做其实就是在给自己藏雷。

Jenkins branch

案例

曾经遇到过的一个真实情况,GitLab上同时存在这样的两个branch:常驻branch develop和临时branch xxx/develop,Jenkins设置了Branches to build*/develop,通过pollSCM的方式两分钟扫描一次,发现分支有变化就执行构建,因为每次都扫描到了这两个branch,所以每次识别为代码有变更,然后就会执行构建,最后一个晚上下来构建次数达到了几百次。当然,即使不构建几百次,在某些情况下单纯是触发了构建导致发布了非期望版本的代码这个事情其实就够糟糕的了。

解决方案

  • 第一种方案,建议直接写branch name,不要在前面加*/。这个问题坑过很多人,Jenkins的官方JIRA上能找到一堆跟这个问题相关的Issue。
  • 第二种方案,不使用pollSCM的触发方式。如今Jenkins拥有众多的插件,如果需要即时构建最新代码,除了pollSCM的触发方式外,其实更推荐使用对应Git托管服务(GitHub、GitLab等)的插件,通过WebHook的方式,由代码托管服务器来调起Jenkins的构建,这样便能完全避开因为Jenkins扫描代码分支导致的问题。

zookeeper安装指引

说明

  • apache-zookeeper提供了跨平台的应用包,本文档以Linux安装使用为例进行说明;
  • 版本:zookeeper-3.5.8
  • 安装目录:/opt/zookeeper

安装步骤

检查运行环境

  • zookeeper需要JAVA环境,需要先检查是否已经配置;

下载解压

  • 下载安装包:wget https://github.com/apache/zookeeper/archive/release-3.5.8.tar.gz
  • 解压:tar -zxvf apache-zookeeper-3.5.8-bin.tar.gz
  • 移动文件夹到/opt目录下:sudo mv zookeeper-3.4.8 /opt/zookeeper

修改配置

  • /opt/zookeeper目录下的conf目录为配置文件目录,把其中的zoo_sample.cfg复制一份作为zookeeper的启动配置:cp /opt/zookeeper/conf/zoo_sample.cfg /opt/zookeeper/conf/zoo.cfg

  • 可修改配置项:

    1
    2
    3
    4
    5
    # 修改数据保存文件
    dataDir=/opt/zookeeper/data/

    # 默认端口为2181,如有必要可更改以下配置项
    clientPort=2181

启停命令

  • zookeeper启动命令:/opt/zookeeper/bin/zkServer.sh start /opt/zookeeper/conf/zoo.cfg
  • zookeeper状态检查:/opt/zookeeper/bin/zkServer.sh status
  • zookeeper关闭命令:/opt/zookeeper/bin/zkServer.sh stop
  • zookeeper重启命令:/opt/zookeeper/bin/zkServer.sh restart

配置开机启动

修改文件:vim /etc/rc.local,追加以下行(请修改<USER>为启动时期望使用的Linux用户):

su - <USER> -c /opt/zookeeper/bin/zkServer.sh start /opt/zookeeper/conf/zoo.cfg &

Nexus上配置Docker仓库

本文主要介绍如何在Nexus上配置Docker的仓库,以及如何配置本地Docker使用搭建好的Docker仓库。

环境

  • 服务器的Nexus版本为3.x以上,可下载安装,也可以直接使用Docker镜像的版本;
  • 使用方的系统及Docker版本没有限制,但因为不同版本的系统能兼容的Docker版本区别较大,此处仅以Centos7搭配Docker17为例说明;

关于Docker仓库

Nexus中的Docker仓库分为三种类型:

Type Description
proxy 代理仓库,提供代理其他仓库,一旦下载过的镜像会被存储在该仓库,下次无需再从外部网络重新下载
hosted 私有仓库,提供本地私服功能,上传的镜像可与使用该Nexus的用户共享
group 组合仓库,实际为多个仓库的组合,但只能使用原来仓库存在的镜像,不能直接通过对组合仓库操作来添加镜像

配置步骤

  • 首先,打开Nexus的系统页面,按图中步骤开始创建仓库:

    点击创建仓库

  • 选择不同Docker仓库类型后进入各自的创建页面:

    选择仓库类型

    • proxy

      proxy仓库配置

      关键步骤:

      • 输入唯一的仓库名称;
      • 选择协议及对应端口,该端口会在后面配置Docker镜像时会用到,注意所选端口不要被占用;
      • 填写本仓库所代理的远程仓库,可使用国内的镜像进行加速;
    • hosted

      hosted仓库配置

      关键步骤:

      • 输入唯一的仓库名称;
      • 选择协议及对应端口,会在配置Docker登录、上传下载私服仓库镜像时会用到,注意所选端口不要被占用;
    • group

      group仓库配置

      关键步骤:

      • 输入唯一的仓库名称;
      • 选择协议及对应端口,该端口会在后面配置Docker镜像时会用到,注意所选端口不要被占用;
      • 选择该组合仓库需要包括的仓库,镜像会从所选的仓库里获取;

配置使用Nexus的Docker仓库

  • 新建或修改配置文件/etc/docker/daemon.json,添加

    1
    2
    3
    4
    {
    "registry-mirrors": ["http://xxx.xxx.xxx.xxx:8099"],
    "insecure-registries":["http://xxx.xxx.xxx.xxx:8098"]
    }

    其中:

    • http://xxx.xxx.xxx.xxx:8099为Nexus上的proxy仓库或group仓库,配置生效后会默认通过该仓库获取镜像;
    • http://xxx.xxx.xxx.xxx:8098为私服仓库,即镜像push的目标仓库,使用前需要先通过docker login登陆;
    • 注意registry-mirrors的地址必须要加上协议类型[http/https];
  • 使配置生效

    1
    2
    systemctl daemon-reload
    systemctl restart docker
  • 登录Nexus私服帐号

    1
    2
    docker login xxx.xxx.xxx.xxx:8098
    # 使用Nexus帐号登录,Nexus默认帐号密码: admin/admin123

使用Nexus仓库

  • 使用Nexus的proxy仓库

    当配置好环境后默认即使用Nexus的proxy仓库,每次本地pull新的镜像时,proxy仓库就会下载并缓存该镜像,下次再pull的时候就会直接从proxy仓库取而不必再通过外部网络获取。

  • 使用Nexus的hosted仓库

    对于自构建的镜像,需要通过Nexus的hosted仓库上传下载,以下为具体步骤:

    • 使用docker tag命令对构建完的镜像进行命名,命名规则为在镜像名前添加hosted仓库地址(即xxx.xxx.xxx.xxx:8098),如java:1.8应该命名为xxx.xxx.xxx.xxx:8098/java:1.8,因为如果不重命名则会默认提交到Docker Hub上;
    • 确认已登录后把重命名的镜像上传,如 docker push xxx.xxx.xxx.xxx:8098/java:1.8
    • push成功后可在Nexus上查看到上传的镜像;
    • 需要使用时通过docker pull xxx.xxx.xxx.xxx:8098/java:1.8命令可从hosted仓库下载该镜像;

使用RVM安装管理Ruby

RVM(Ruby Version Manager)是一个负责安装、管理不同版本的Ruby环境的命令行工具。

安装RVM

  • 确认是否已安装curl,没有则执行命令yum install curl进行安装;

  • 打开RVM官网,使用上面提供的命令安装RVM:

    1
    2
    $ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
    $ \curl -sSL https://get.rvm.io | bash -s stable
  • 使配置文件生效:

    • 查找配置文件位置: find / -name rvm.sh
    • 配置文件生效: source /etc/profile.d/rvm.sh
  • 下载RVM依赖: rvm requirements

安装Ruby

  • 查看RVM库所有Ruby版本: rvm list known
  • 指定安装其中某个版本的Ruby :rvm install ruby-2.5.1

常用命令

  • 查看所有已安装的Ruby版本信息:rvm list
  • 设置Ruby的当前需要版本: rvm use 2.5.1
  • 设置为默认版本:rvm use 2.5.1 default
  • 删除其中某个版本:rvm remove 2.5.1

理解SSH服务的原理

SSH全称Secure Shell,是一种加密的网络传输协议,其目的是在不安全的网络中为网络服务提供安全的传输环境。

相关文件

SSH服务会在系统的用户目录下生成一个.ssh的文件夹,文件夹下一般会有以下几个文件:

  • config : 配置文件,可以为远程主机配置host、登录端口、默认登录用户等,方便用户使用;
  • known_hosts : 记录本机访问过的服务端所提供的host key,下次访问相同主机时会核对host key,如不匹配会发出警告;
  • id_rsa : 保存本机的私钥;
  • id_rsa.pub : 保存本机的公钥;
  • authorized_keys : 本机作为服务端所保存的已授权客户端的公钥;

关于非对称加密

SSH有密码登录和证书登录两种认证方式,都是以非对称加密实现身份验证。不同于对称加密的加密解密使用同一套密钥的方式,非对称加密拥有公钥和私钥两套密钥,其中 公钥负责加密,私钥负责解密 ,公钥加密后的密文只能通过对应的私钥进行解密,而通过公钥几乎不可能推算出私钥。另外提一下,数字签名一类是使用私钥编码、公钥解码的,但是这种方式只能称为编解码而不能称作加密解密,因为公钥是公开的,拥有公钥者都可以通过密文解码出明文,加密的意义就不存在。

密码登录的验证过程

  1. 客户端向远程服务端发出登录请求,服务端把自己的公钥发给客户端;
  2. 客户端本机使用服务端提供的公钥对密码进行加密,并把密文发送至服务端;
  3. 服务端接收密文并使用私钥把密文解密出密码;
  4. 服务端通过密码验证用户身份并返回登录结果;

证书登录的验证过程

  1. 客户端事先生成本机的公钥和私钥,并把公钥追加到服务端主机的authorized_keys文件中;
  2. 客户端发出登录请求,服务端在authorized_keys中匹配该客户端对应的公钥;
  3. 服务端生成随机数,并使用客户端的公钥进行加密,然后把密文发送给客户端;
  4. 客户端通过本机私钥解密密文获得随机数;
  5. 客户端利用随机数和会话密钥session key通过MD5生成摘要Digest,并发送给服务端;
  6. 服务端使用同样的算法生成另一份Digest;
  7. 服务端对比生成的Digest和客户端发送过来的Digest,返回登录结果;

以上两种方式的验证过程是主要的流程而非全部的过程,其他还包括会话密钥session key的生成以及使用会话密钥对会话过程进行加密等等此处略过不提。另外,为了保证访问的远程主机是真正的目标主机,防止IP劫持等中间人攻击(Man-in-the-middle attack)的出现(具体手段为拦截登录请求,向客户端提供伪造的服务端公钥,并在获取密文密码后通过假公钥对应的私钥解密为明文,然后使用明文密码对真正的服务端主机进行攻击。),客户端在初次访问远程主机时会获取远程主机的公钥指纹host key(会提示无法确认主机真实性,询问是否连接)并把其添加到本机.ssh目录下的known_hosts文件中,以后访问远程主机时会先通过对比host key确保是同一主机;

证书登录的配置过程

上面提及到证书登录的前提是把公钥放到目标主机中,下面是详细的过程:

  • 客户端执行ssh-keygen命令生成私钥和公钥,会在用户目录下的.ssh文件夹下生成id_rsaid_rsa.pub两个文件,其中id_rsa为私钥文件,id_rsa.pub为公钥文件;
  • 把公钥文件的内容追加到服务端主机的~/.ssh目录下的authorized_keys中,注意是追加,没有该文件要新建,已存在则不要覆盖原有内容,完成后如果发现不能免密登录应尝试重启服务端的SSH服务(本步骤也可以直接通过在客户端执行ssh-copy-id命令完成);
  • 当然,对于安全性的更多考虑,可以增加禁止root用户登录、禁用密码登录等设置。
  • 此外,当第一次访问某台服务器的时候会因为检查到HostKey不存在而提示添加,这是因为配置项StrictHostKeyChecking的默认值为ask,即会进行对话提示确认,但某些情况下(比如执行脚本)我们并不希望该交互的出现,因此可以添加参数-o StrictHostKeyChecking=no或者在~/.ssh/config配置文件中添加配置StrictHostKeyChecking no来跳过该对话,不过该方法相当于降低了安全性,需要自行斟酌使用。