服务器维护,服务器代维,安全设置,漏洞扫描,入侵检测服务

运维之家

 找回密码
 注册
搜索
查看: 6575|回复: 2

使用GitLab、Jenkins、Docker建立快速持续化集成交付部署方案

[复制链接]
dirtysea 发表于 2017-11-29 10:52:31 | 显示全部楼层 |阅读模式

使用GitLab、Jenkins、Docker建立快速持续化集成交付部署方案(一)


摘要

本系列文章将要完成的:

  • 安装GitLab、Jenkins、Docker等一系列基础环境
  • 建立自己的 Docker Registry,私有的Docker镜像服务,用于存储我们自己的Docker镜像仓库(Repository)
  • 使用GitLab进行代码管理,并联动Jenkins进行自动化打包,生成Docker Image,推送到自己的Repository
  • 使用Docker Compose在目的机上进行集成环境部署


本系列文章不会包含:Linux、GitLab、Jenkins、Docker等基础概念和知识,不包含Docker swarm、集群、单元测试和自动化测试。

文章索引

  1. GitLab、Jenkins、Docker 初始环境安装(本文)
  2. 制作 Docker镜像 及 Docker Compose 的使用
  3. 使用 Webhook 自动触发 Jenkins 进行 Docker镜像制作并保存到私有镜像仓库,以及目的机部署

环境版本

  • Ubuntu 14.04 LTS
  • GitLab Community Edition 8.13.1
  • Docker 1.11, Docker Compose V1,Docker Registry V2
  • Jenkins 2.19 LTS

GitLab安装

简介

关于Git的基本知识我就不在这里讲了,有兴趣的可以了解下我之前写的文章:我也讲讲Git

GitLab与GitHub十分相似,区别并不是很大。对于想要了解GitHub的可以参见:我再讲讲GitHub

比较不同的一点,GitHub中的Pull Request,在GitLab中叫做Merge Request。其实并没有区别,Pull就是要Merge嘛。

GitLab同样需要生成证书等一系列操作,与GitHub相同,其实都是Git工作流中的必需项。这些内容在刚才提到的链接中都有讲,不在针对GitLab进行描述。

安装

安装的方法很多,根据天朝的网络情况,这里选择从清华大学的TUNA镜像站下载Gitlab Community Edition:

https://mirror.tuna.tsinghua.edu.cn/help/gitlab-ce/

目的机为Ubuntu 14.04,所以这里建议:

如果要在公司内部安装的话,可能会下载一天的速度都不如拿个U盘拷的情况,所以直接去TUNA的HTTPS服务器上,抠对应的安装包,在家里下载完,之后拿个U盘拷贝更靠谱更靠谱:(https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu/pool/trusty/main/g/gitlab-ce/)

使用 dpkg -i 对deb包进行安装。

注意,GitLab对系统的其他包依赖特别严重,对nginx、postgresql、redis、git等都有严重的依赖。所以建议安装GitLab的服务器即作为代码仓库专用服务器,上面不要随意安装任何其他工具或软件,不要在宿主机上跑其他的服务。Docker除外。

配置

  • 域名

打开/etc/gitlab/gitlab.rb文件.

修改服务器地址:

  • 邮箱

新增如下代码以配置邮箱。

建议配置邮箱系统。GitLab使用用户名和用户邮箱区分用户,均不可重复。管理员新建邮箱时不能指定用户密码,GitLab会向注册邮箱中发送第一次修改密码邮件。之后用户找回密码凭据也是使用邮箱。

如果你对Postfix比较熟悉的话,也可以使用GitLab自带的Postfix做邮箱系统。对于初学者,建议使用其他邮箱的SMTP服务。

之后执行 gitlab-ctl reconfigure 生效配置

  • 注册登录

对于非对公众开放的GitLab系统来说,关闭注册系统是必要的。

在Admin Area,点击右侧的 齿轮,点击 Setting,取消勾选 Sign-up Restrictions。注意页面很长,修改完之后到最下方点击保存。

安装Docker

一些概念

Docker的定义和一些基本概念就不在这里讲了。这里只讲一下为什么要使用Docker,以及为什么会可以与GitLab无冲突的安装到同一台机器上。

Docker容器即是实质的虚拟环境,容器内包含整个服务所需的所有依赖环境,且运行在其自己的虚拟环境中的,相当于最小化的虚拟机,他的状态不会影响宿主机,反过来宿主机的状态也不会影响到容器。只有容器被设置的端口和存储才能与外部环境通信,剩下的完全是个黑盒,外界看不到,也不关心。

Docker部署简单,容器从镜像创建,而镜像内包含所需的所有依赖,做到了一个镜像直接部署,就像游戏机一样,插卡即玩,不再需要修改服务器的系统配置。在一定程度上避免了部署人员胡乱搞最后还得开发人员动手的问题。

注意Docker镜像是无状态的,而容器是 有状态 但应是 状态不重要 的,容器在运行时生成的数据是被保存在容器内的,这就是说容器内的进程生成的临时文件仍然被存放在容器内,并且当整个容器被删除时也会跟着删除。如果生成的文件包含重要资料,则需要把对应生成的目录指向宿主机目录或者数据卷容器。

数据卷容器与普通容器没有区别,只不过里面不包含应用进程,只为了保存数据而存在的容器。数据卷容器也是唯一一种状态重要 的,不要手贱把数据卷删除了。

对于手残党还是把数据挂载到硬盘上吧。

安装Docker环境

Docker的安装十分简单。

官方文档:https://docs.docker.com/engine/installation/linux/ubuntulinux/

要把鲸鱼放冰柜,总共分三步:确认自身操作系统内核版本、更新源、安装包。

(注意以下操作均在root用户下执行,非root用户请自行sudo或su -。 # 表示提示符,这么做的原因是防止有小白一股脑把大片代码复制粘贴到shell中)

  1. 确认自身操作系统版本:注意Docker官方并不支持 Ubuntu 14.10 和 15.04,所以建议发行版尽量选择LTS版。

    官方也不支持kernal低于3.10的版本。对于内核低于3.10版本的系统,或是升级内核,或是升级操作系统。

  2. 更新源

    更新操作系统证书库和apt对https支持。

    添加对应源到本地。

    比如Trusty 14.04 (LTS)的源是:deb https://apt.dockerproject.org/repo ubuntu-trusty main,那么执行

    在这一步你也可以选择其他源,比如阿里的Docker源,不过版本会变得不确定,官方会提供最新的稳定版,现在是1.12,而阿里对Ubutnu提供的是1.11,对CentOS提供的是1.10。虽然我们暂时不会使用新版的一些新特性,但还请注意版本差异会导致一些特性或语义有重大差异,比如swarm。

  3. 安装

    注意,阿里云ECS上被定制的源和发行版可能不叫 docker-engine 而是直接叫 docker,要注意。

针对大陆用户的的一些调整。

我们毕竟是在墙内,去docker hub上拉镜像是十分不现实的,几M的文件拖几个小时之后报个错是很无奈的事情,所以就像我们经常修改apt和yum的source mirror一样,我们要修改docker的registry-mirror

对于使用阿里云ECS容器服务的用户,可以使用其自带的加速器配置,内网加速器不仅不消耗出口流量,而且也没有带宽限制。

地址:加速器

这个页面藏得很深,很难找到。

其他用户可以考虑daocloud

Ubuntu 14.04 对于registry-mirror很容易修改,我们只要在/etc/default/docker这个文件中添加上参数即可,比如:

而对于支持systemctl的新版Ubuntu和CentOS,我们要修改对应的docker.service中的ExecStart。

相关文档:https://docs.docker.com/engine/admin/systemd/

官方还有另一种修改方式,依靠Daemon configuration file。

看起来应该是更方便的方法,但是没有尝试过。有试过的朋友可以留言介绍下,

相关文档:https://docs.docker.com/engine/reference/commandline/dockerd/

至此Docker就安装完成了。

安装Jenkins

(关于Docker镜像的制作,参见第二章)

Jenkins简介

Jenkins是一个用Java编写的开源的持续集成工具,可以于GitLab等代码管理工具联动,触发一定条件之后,实现自动进行测试、编译、部署等一系列动作。

使用Docker获得Jenkins镜像

我们接下来就要依靠Docker来继续在这台GitLab服务器上安装Jenkins服务了。

jenkins官网:https://jenkins.io/

我们这里选择Docker平台的LTS版本,他会把我们引导到 hub.docker.com 的 jenkinsci/jenkins 页面,并告诉我们Docker Pull Command

注意他的介绍写错了,hub.docker.com写着是weekly releases,但其实github和真实下下来的都是LTS版,但github上的weekly releases又会指回这个页面。

What were they thinking! Never mind.

注意我们可不能pull下来直接用!因为jenkins默认要使用两个端口:8080和50000,而8080这个端口已经被GitLab占上了。

我们也不必把Jenkins的Dockerfile下下来自己改。别忘了Docker的镜像是分层存储的,我们只要在Jenkins上继续搭建一个Dockerfile就可以了。

自己生成一个Dockerfile,内容:

其中,本地目录etc/下方的是两个时区文件。

默认的JENKINS_OPTS –httpPort是8080,我们修改成8081,之后将8081端口映射出来。

之后执行

系统就会制作一个属于我们自己的,端口为8081的jenkins。

使用docker images查看

准备Jenkins的环境

新建目录/var/jenkins,你也可以自己选择存储路径,或者自己制作一个数据卷容器。

给予这个目录权限。Jenkins在Dockerfile中描述的用户权限如下:

当然手懒可以直接来个777。安全问题自己解决。

启动jenkins

启动容器

使用docker ps来查看容器运行情况。

打开浏览器,访问你的8081端口来查看。能打开页面,配置个账号密码就行了。本章节只是为了熟练我们对Docker的一些基础操作。我们会在后面的文章中继续讲Jenkins

你需要保存的数据完全保存在 /var/jenkins_home 中。你可以随时删除这个容器(注意是容器,不是镜像或Dockerfile),并重建新的容器,你的数据不会丢失。

基于nsenter的Docker容器内管理工具

容器是一个绝对的黑盒环境,这意味着当我们遇到容器内配置有问题时,会遭遇一墙之隔:明知道是容器内的配置有问题,我们却不知道配置文件在哪、怎么写的、怎么写错了。不像传统虚拟机,有个界面入口能让我们登入。

所以我们需要一个工具进入容器内,nsenter能满足我们的需求。

安装util-linux

nsenter是包含在util-linux 2.23及之后版本中的工具,如果你的发行版默认自带版本低于2.23,你需要手动安装新版。已知Ubuntu 14.04 仍然使用 util-linux 2.20。

在这里选择个版本https://www.kernel.org/pub/linux/utils/util-linux/,之后下载util-linux-version.tar.xz,解压,configure、make nsenter && cp nsenter /usr/local/bin。

基本用法

nsenter 启动一个新的shell进程, 同时会把这个新进程切换到和目标进程相同的命名空间,这样就相当于进入了容器内部。为此我们需要获取容器的第一个进程的 PID

之后根据获取的PID进入容器

使用shell简化步骤

新建一个文件getInDocker.sh并给予执行权限:

使用方式:

现在你已经进入容器了,这是一个几乎完全脱离宿主机的环境(除已挂在的数据卷),其中自带的命令非常有限,你可以在里面再安装一些调试工具。

附赠一段可以在阿里云ECS上直接复制粘贴的代码(非阿里云用户可以把aliyuncs改成aliyun,或者把整段改为其他源。注意发行版版本号):

这段代码会在你的容器内配置阿里云ECS源,并安装一些工具。你现在可以在容器内执行ifconfig、netstat、tcpdump、vi、rz、sz了。

只要不删除这个容器,下次你进入这个容器还可以继续使用这些工具。

你应该只在容器中安装不会影响原本服务的工具,这些工具应该只作为调试查看用,不能影响正常服务,并且可以被随时删除。

不要在容器内保存重要数据(除已挂在的数据卷位置)。容器应该是状态不重要的,可以随时删除随时新建。你不应该容器内部保存配置文件,你应该将调试确认的配置文件移出容器并妥善保存。

小结

至此,我们的基本环境已经准备好了。

 楼主| dirtysea 发表于 2017-11-29 10:53:04 | 显示全部楼层

使用GitLab、Jenkins、Docker建立快速持续化集成交付部署方案(二)

本文将要学习 Docker Image 的自定义,及 使用Docker Compose进行环境部署的方法。

文章索引

  1. GitLab、Jenkins、Docker 初始环境安装
  2. 制作 Docker镜像 及 Docker Compose 的使用(本文)
  3. 使用 Webhook 自动触发 Jenkins 进行 Docker镜像制作并保存到私有镜像仓库,以及目的机部署

 

Docker一些概念

国内各个厂家对Docker概念都翻译不一样,我这里先写一下我自己的概念理解

  • 镜像(image)镜像
  • 容器(container):由单一服务构成的针对最基本功能实现的 服务(service)(比如Nginx)
  • 项目(project):多个服务构成的 应用(application)(比如由 Nginx + PHP + Mysql + WordPress组成的博客)

单个容器只能提供非常基本的服务,比如单纯的Mysql数据库服务,单纯的Redis缓存服务。

需要由多个容器协同工作,才能组成一个复杂且强大的项目,实现产品功能。

这里鄙视以下各个厂家为圈地,拉拢用户,使用了非常多的混淆概念,比如引入微服务(microservice)。

什么是他妈的微服务,微博微信朋友圈玩多了吧。不论按照Windows还是按照Linux来讲,服务(service)指的都是由单一应用程序完成的最基本的功能实现。还他妈的微,是不是还要把HTTP服务拆成 HyperText Transfer Protocol 之后分三段去实现啊。

维基百科上有针对微服务的定义:微服务 (Microservices) 是一种软件架构风格 (Software Architecture Style),它是以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模组化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关 (Language-Independent/Language agnostic) 的 API 集相互通讯。微服务是由以单一应用程序构成的小服务,自己拥有自己的行程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 HTTP API 通讯。同时服务会使用最小的规模的集中管理 (例如 Docker) 能力,服务可以用不同的编程语言与数据库等元件实作。

很明显这里的微服务指的与我们所说的服务是相同的,只不过更强调其单一性,即甚至要把Apache+PHP这种组合也剥离开(传统模式下,PHP是以模块形式与Apache共同工作的,而Nginx与PHP是靠PHP-FPM共同工作,后者更颗粒化)

然而国内不少网站把微服务当做微信、微博一个级别的概念对待,以为微服务就是产品功能级的服务,订单微服务,通知微服务,狗屎微服务。

使用Docker实现一个项目

我们在这里,要基于nginx、php-fpm,实现一个PHP应用。这个项目将作为一个基础学习项目,对接下来的Jenkins和最终部署都有很大关系。

将要做的事

首先先给大家看一下我的目录结构,如果你对我写的整个结构都很一目了然的话,证明你对这一部分都很熟悉,你可以跳过这一章节了。

我们需要准备nginx和php-fpm的Dockerfile,从Docker Hub上获取。编写一个静态文件和一个php文件,并为自己的代码制作一个Dockerfile用于生成数据卷容器。

没人说过容器里不能放纯代码的。纯代码,满足最基本颗粒化要求(存储),无状态或状态不重要(随用随建,不用即删,临时文件不重要)。

至于为什么要专门为php等代码建立数据卷容器,而不是直接使用git或其他代码管理工具同步到硬盘上的原因,将在后面介绍。

nginx

Let’s make a nginx_modified

确认配置方法

首先我们要知道nginx的镜像内部到底是怎样的。有两种方法:

第一种,生成一个默认容器,并进入容器内部观察结构。这是一种不推荐的做法,因为除非你对整个服务有及其充分的了解,否则你永远摸不清它里面到底是怎样的。这就相当于你作为一个人类活了一辈子,除非你是专业的医生,否则你是没办法拿手术刀给别人做手术的。

第二种,根据Docker Hub上的描述来修改相应的配置。这是推荐的办法,多数项目都会对自己的docker项目有比较详细的描述。而且多数项目可能会针对Docker做一些调整,他们的配置与传统的编译安装配置也是不同的。使用推荐的办法修改配置是最安全的办法。

除非他们自身的描述写的相当渣,或者完全就没有描述,否则不要使用第一种方法。

Dockerfile

Dockerfile是用于构建镜像的文件,其内包含了多指令,每一条指令构建一层。

这是为自定义nginx服务而编写的dockerfile

逐条解释下:

FROM:基于哪个版本的镜像生成新的镜像,我们这里选择stable版的1.10.2。如果这里不指定版本号,docker会默认使用latest版本(2016年11月24日为1.11.5)

MAINTAINER:这个镜像的作者名

ENV:指定环境变量,这里声明了nginx的版本

COPY:将本地conf/中的文件复制到镜像的/etc/nginx目录下。使用这个办法我们替换了nginx的配置文件。包括默认网站、对php文件的处理等。

EXPOSE:可映射的端口

CMD:容器启动时要执行的命令

VOLUME:定义匿名卷

nginx的default.conf

生成镜像:

测试启动:

因为我们的设备上还跑着GitLab和Jenkins呢,所以要避开许多端口,这里选择使用10080。

使用浏览器打开本机的10080端口,这个时候/var/www/html并没有映射到任何数据卷,所以看到的应该是nginx的默认欢迎界面。

底层执行docker ps查看这个容器,使用docker down {container_id}停止这个容器,使用docker rm {container_id}删除这个容器。你也可以在容器未停止时,直接使用docker rm -f {container_id}强制删除这个容器。

提示:你可以使用docker rm $(docker ps -a -q)删除所有已停止的容器

底层执行docker image查看生成的镜像信息,使用docker rmi {image_id}删除这个镜像。

提示:你可以使用docker rmi $(docker images -q -f "dangling=true")删除所有无tag的镜像。

PHP-FPM

接下来我们制作PHP-FPM的镜像。

其实完全没有必要,PHP-FPM不仅是真正的无状态的,而且几乎没有修改配置的必要。

Dockerfile,我们只指定以下版本就好了

默认情况下,会继承原镜像的端口映射9000。

代码镜像

这里再次强调一下,Docker的镜像是分层文件系统,我们的自定义nginx镜像并不会占用一个整个nginx镜像所需的硬盘空间,只占用我们添加的配置文件的空间大小,而所需的nginx则继续使用FROM中的镜像。

那么对于没有基础依赖的代码镜像,应该FROM什么镜像呢?

网上有不少办法是基于一个最小化的Linux操作系统来做,比如Busybox。Bullshit!

注意一下现在所有的Docker镜像,生成他们的Dockerfile都是有FROM的,而且一般都是 debian:jessie。这意味着多数镜像都是依赖debian:jessie的,debian:jessie已经存在于我们的本地镜像库中。我们也可以继续基于debian:jessie制作镜像。

Dockerfile

web/a.txt

web/index.php

Docker Compose

Docker的每个容器只完成最基本的服务,而想要实现一个产品功能,往往需要多个基本服务共同完成。对于每个服务来讲他们是无依赖的,但对于项目来讲,他们就是需要紧密结合的。

Docker Compose就提供了这样一个功能,允许定义一组容器,组成一个项目。

安装

执行命令如:

官方也提供pip安装方式,但依赖和局限性比较多,在不同的系统上有不同的问题,不建议用这种方式安装

相关文档:https://docs.docker.com/compose/

配置

Docker Compose使用YAML格式的配置文件:docker-compose.yml

主要使用方法:直接在docker-compose.yml的路径下,执行以下命令:

  • docker-compose build 新建(或重建)项目中所有需要build的镜像。此步非必须。
  • docker-compose up 新建(或重建)项目中所有需要build的镜像,并启动对应项目。这是一个前台操作,在所有容器内所有进程退出之前不会退出,使用Ctrl-C会停止容器,但不会删除容器。使用 -d 参数使项目在后台启动。
  • docker-compose start 启动一个已经存在的项目。
  • docker-compose stop 停止一个已经运行的项目。
  • docker-compose down 停止一个已经运行的项目,并删除所有相关联容器。

启动项目

在docker-compose.yml的路径下执行docker-compose up -d。

现在访问你的服务器http://your-server:9080/a.txt应该可以打开这个静态文件 a.txt,http://your-server:9080/index.php可以打开执行后的php结果了。

一些问题

代码位置问题

有很多开发者会把要运行的代码与服务打包到同一个镜像中。

这些开发者一般多为JAVA开发者。对于JAVA开发者来讲,他们的项目结构可能是这样的:TOMCAT + JAVA包 + 数据存储。对于 TOMCAT + JAVA包 这种情况便是强依赖环境,同样符合无状态和最小颗粒的特性,或许并没有问题。

然而对于其他语言的开发者,项目结构一般为 HTTP服务 + 语言解析器 + 代码 + 数据存储。

以PHP开发者举例,可以理解为 NGINX + PHP-FPM + 代码 + Mysql。而代码中不仅包含php代码,也会包含html、js、css等代码。

将代码单独的放入 NGINX 镜像或者 PHP-FPM 镜像,都会导致运行过程中,容器之间无法获取代码,解析时出现404错误。

另外在日常开发时,经常变动的也只有代码部分,其他镜像一般多为万年不变的。将代码独立到单独容器中也会减小部署压力。

(目前还没见到过PHP开发者使用Docker和做持续化部署的)

配置文件问题

我们对标准的nginx镜像进行了修改,添加和修改了配置文件。对于应可以随时替换的标准服务来讲这并不完美。于是有一种思路,就是把配置文件像代码一样也做成数据卷容器。这样做未尝不可,但难度会很大。因为挂在数据卷的话,会导致配置文件下整个目录覆盖,可能会影响到我们并不想更改的默认参数。

 楼主| dirtysea 发表于 2017-11-29 10:53:57 | 显示全部楼层
使用GitLab、Jenkins、Docker建立快速持续化集成交付部署方案(三)



文中我们将完成 GitLab → Jenkins → Docker 的环境,并完成基于GitLab、Jenkins、Docker的面向Web开发的快速部署方案。

 

我们最终得到的结果,将是部署人员只在部署环境下只敲一句命令,就完成整个部署工作。

最终的目的就是接近一键部署,烧锅炉的大叔都会给服务器部署服务了,开除工程师。

文章索引

  1. GitLab、Jenkins、Docker 初始环境安装
  2. 制作 Docker镜像 及 Docker Compose 的使用
  3. 使用 Webhook 自动触发 Jenkins 进行 Docker镜像制作并保存到私有镜像仓库,以及目的机部署(本文)

 

私有Docker仓库

为什么要使用私有仓库

我们最终要得到的交付成果,应是一个 Docker Image。

在某种程度上,不少公司在开发测试阶段可能会考虑直接在开发服务器上生成本地镜像,或是使用 docker save 方式导出tar镜像包文件,在不同机器上进行部署。这种方式对于公司网络环境比较好的情况下确实可以实行,而且对于线上生产环境,某种意义 上人工验收后部署要比全自动部署更放心。

然而更多的企业,外部网络带宽有限,内部网络优化更是渣的可怜。一个镜像包一般都在百M左右,用网络复制可能需要几十分钟甚至半个小时,部署一次环境,等待网络复制的时间,要比 拿一个优盘抱着笔记本乘上几十层电梯钻进机房忍着低温和轰鸣 蛋疼的多。

(已见过不止 3 家公司内部网络是这种情况。而且一般公司的IT部也都是所谓的网管,出问题后 重启、重装、换机 三步走的风格与一般小农村网吧网管也没什么区别。这种职位多数都是公司内部解决职工亲属就业问题内推产生的。神州泰岳全公司都在用12.12.0.0/16这种公网地址当私网地址用,为服务器申请一个静态DHCP地址都会搞得吵架。神州数码这种大公司的网管也在给新员工配置新电脑的时候,装个盗版操作系统都要看手册,还总出错)

所以我们要在这里,充分利用Docker镜像的分层文件系统:没有更新的部分不会生成新的镜像,不会浪费硬盘空间,拉取新镜像时旧镜像也不会消耗流量和带宽。

建立私有仓库

你可以直接执行:

来启动一个仓库容器,默认端口5000,数据将会保存于/var/docker_registry。

注意这是Version 2,对于其他版本请参考其它文档。

注意这是一个HTTP服务,没有加密传输,对于安全性需求,建议自行解决。

相关文档:https://github.com/docker-library/docs/tree/master/registry

本地镜像打tag

这不是一个移动操作,而是一个复制软链接诶操作,在docker images中会新增一个ID相同但tag不同的镜像,不占用硬盘空间。

推送本地镜像到仓库

会将这个镜像推送到your_registry_domain/private-docker-registry/

拉取仓库镜像到本地,或直接执行

pull 和 run,不解释

 

配置GitLab

访问权限

注意,因为GitLab是我们自建的仓库,拥有完全的使用权,所以对于仓库的可视权限将要比GitHub多出两种选项。

https://blog.catscarlet.com/wp-c ... w/loading.gif") 50% 50% no-repeat;">

  • Private 私有,只有所有者、组内成员或已分配的用户有查看权限(同GitHub收费版的私有仓库)
  • Internal 内部,拥有GitLab账号的成员可以查看,无账号用户无法访问(适合于服务器放在公网但不想公开代码的情景,GitHub没有这个功能)
  • Public 公共,任何人都可以访问(同GitHub免费版的公共仓库)

建议公司内部的代码仓库都设置为 Internal。

使用GitLat Webhook与Jenkins实现持续交付

GitLab等代码仓库其实也支持CI/CD操作,然而我们将要执行的操作对于GitLab来讲过于复杂了,所以这些操作要交给Jenkins这种专门的持续集成工具。为了能在需要时自动触发Jenkins自动操作,我们要使用GitLab的Webhook进行操作。

Deploy Keys

你可以为Jenkins专门制作Deploy Keys,或者干脆在GitLab上增加一个Jenkins账户,用户Jenkins拉取代码。两种方法都可以。

https://blog.catscarlet.com/wp-c ... w/loading.gif") 50% 50% no-repeat;">

配置Webhook

根据我们之前的安装部署,Jenkins的端口是8081。假设我们的主机域名(地址)为your-what-server,项目为catscarlet/test1.git,则url为

触发条件建议选择 Merge Request event,或干脆手动触发。

这里就有GitLab安装在宿主机的好处了,端口很标准,不然改个ssh端口还要使用git的话,会变得很麻烦。至于https,相信搞得定Let’s encrypt的人很多,但搞不到公司域名的人更多。

 

配置Jenkins

安装必要插件

安装这些插件:

  • Credentials Plugin
  • Git plugin
  • Gitlab Hook Plugin
  • SSH plugin
  • Locale plugin

修改默认语言

Jenkins默认根据用户系统来显示语言,然而其自身的中文翻译挺糟糕的,所以换成纯英文更好一些。

在安装 Locale plugin 插件之后,点击 Manage Jenkins – Configure System,在Default Language处填写en,保存。

修改并发数

因为接下来我们会把项目代码复制到一个统一的临时目录下进行处理,如果这时候有其他项目也在处理,则这个临时文件夹内可能就会有文件混乱的问题。所以我们要把Jenkins的并发数改为1,参数为 # of executors 。对于需要并发处理的正式环境,您需要手动修改临时目录的位置。

新建Jenkins 项目

登录到Jenkins主页,New Item 新建一个 Freestyle project ,命名为test1。

在 Source Code Management 这里,选择Git,并在Repositories填写你的Git项目地址catscarlet/test1.git,Credentials选择你的证书,Branch Specifier选择对应Branch。在 Additional Behaviours 中增加 Clean before checkout。

Build Triggers选择Poll SCM,激活Webhook功能。内容留空,不定时Build,完全由Webhook触发。

在 Build 这里,Add build stemp 增加两个项目:Execute shell 和 Execute shell script on remote host using ssh。

不能选择直接在本地 Execute shell ,因为Jenkins目前是运行在Docker容器内的,与宿主机完全隔离,除了基本的Linux Shell和JAVA的SDK环境之外,容器内没有任何其他东西了,不能使用Docker命令,没有node和npm,不能编译,几乎什么都做不了。

所以我们在这里要分开做两件事:

  • 准备代码,并复制到宿主机环境
  • 登录到宿主机,在宿主机上进行打包。你也可以选择登录到其他主机上,比如一台专用打包服务器。

代码

更改Jenkins的启动方式,额外绑定一个数据卷目录。

我们已经在Source Code Management选择了Git,所以在执行Execute shell之前,Jenkins会先用Git把代码拉取到本地,不需要自己手动执行git pull。

Execute shell:

Execute shell script on remote host using ssh:

需要先在 Jenkins – configuration – SSH remote hosts 中添加对应的服务器登录方式。

这里建议调用从git仓库上拉下来的脚本,而不是把要执行的命令写在Jenkins这里。

project-build.sh

这里建议对每个镜像都手动打包,而不是使用compose打包。一方面compose无法针对镜像打tag(compose更关注于容器而非镜像,容器是NAME而镜像是TAG),另一方面最终部署所需的 docker-compose.yml 中需要编写的是 带仓库路径的 image 而非 build。

我们的理想情况是,部署人员从GitLab获取 docker-compose.yml 之后,执行 docker-compose up,便完成容器部署操作。(面向傻瓜的程序设计,一键部署吔)

测试

GitLab端

在GitLab的Webhooks页面有一个Test按钮,点一下就会触发Webhooks,如果提示 Hook executed successfully: HTTP 200 那么GitLab这端就工作正常。

Jenkins端

Jenkins接到Webhooks后就会开始打包。

https://blog.catscarlet.com/wp-c ... w/loading.gif") 50% 50% no-repeat;">

  • 灰色表示正在准备
  • 蓝色表示打包中或打包完成
  • 红色表示打包出错

点击进入后可通过左侧的 Console Output 查看控制台的情况,比如 Shell 执行出错在哪里。

注意Jenkins会在Git检查代码变更情况,如果GitLab那段没有新提交的话,Jenkins会认为代码相同,没有必要,会忽略这次打包。所以如果要进行测试的话,可能需要删除上一次的打包结果。你可以在 Polling Log 中查看相关信息。

部署

部署人员从GitLab获取 docker-compose.yml 并复制到目的机,执行 docker-compose up

https://blog.catscarlet.com/wp-c ... w/loading.gif") 50% 50% no-repeat;">

这回烧锅炉的大叔都会给服务器部署服务了,终于可以把工程师都开除了。

 

总结

本系列文章简单讲述了基于GitLab、Jenkins、Docker的面向Web开发的快速部署方案。文章中没有涉及Docker 1.12以及swarn等相关概念。

Docker 1.11中,基于compose的DAB方案,是以在同一服务器上部署所有服务镜像的方式实现的,这是一种容易简单理解的实现方式。在集群中,每个节点都运行相同的容器组合。多个节点运行相同的容器群,容器群之间隔离没有交互,而容器间紧密结合。

但这是一种可能浪费资源的模式。负责某些服务的容器可能负载非常大,但上下游容器则比较空闲。这种情况下,更希望多个节点都能分担压力大的服务,而对比较闲的服务则减少数量。

另外同一节点上可能会有多个项目,而项目间可能会有相同的无擦别服务,比如php-fpm。更希望复用这一个容器,而不是启用多个相同容器只占内存不干活。

Docker 1.12中实现了这种需求,将分布式的概念从项目分解到容器应用。但目前仍是试验中,所以没有仔细研究,也不建议使用。阿里云在Docker还在1.11版本期间,自己也开发了一个阿里版Docker,实现了1.12中的这个功能,但是限制太多,脚本不兼容,不建议使用。




来源 https://blog.catscarlet.com/201612082623.html

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|小黑屋|手机版|Archiver|运维之家

GMT+8, 2024-4-24 20:45 , Processed in 0.527775 second(s), 14 queries .

Powered by Dirtysea

© 2008-2020 Dirtysea.com.

快速回复 返回顶部 返回列表