文档章节

基于Gitlab的CD流程实践

孤岛旭日
 孤岛旭日
发布于 2017/05/11 10:02
字数 1958
阅读 546
收藏 1

基于Gitlab的CD流程实践

DevOps(英文Development和Operations的组合)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。它的出现是由于软件行业日益清晰地认识到:为了按时交付软件产品和服务,开发和运营工作必须紧密合作。

— 百度百科

DevOps提出也已经有些年头了,本文不涉及相关概念,仅以基于Gitlab的CD(持续交付)流程为例子说明实践中工具的构成、配置及使用。

一提到CI(持续集成)就不得不提Jenkins这一神器,但本流程没有使用它,原因如下:

  • Gitlab本身带了CI功能,集成度更好,更简单
  • Jenkins过于复杂了,不适合DevOps,或是说对开发人员不友好,一个工程的测试部署往往需要运维人员介入,而Gitlab CI的CI流程开发人员可以自行操控
  • Jenkins没有天然的pipeline功能,需要通过blueocean插件实现

Note

以一个Spring Boot工程(Java项目)为例,说明如何做源码管控、代码质量检查、编译与部署。

本文环境IP为127.0.0.1,请自行修改。

  1. 使用Gitlab做版本控制
  2. 代码Push后:
    1. 调用SonarQube做质量检查
    2. 调用Gitlab CI做编译及单元测试(CI)
    3. 调用Gitlab CI做部署(CD)

环境准备

安装Docker.

curl -sSL https://get.docker.com/ | sh

安装Gitlab By Docker.

docker run -d  \
   -p 1443:443 -p 180:80 -p 122:22 \  #开放的端口,注意这里开放的是180的Web端口
   --name gitlab \
   --env GITLAB_OMNIBUS_CONFIG="external_url 'http://127.0.0.1:180'; nginx['listen_port'] = 80;" \  # Web URL,请将`127.0.0.1`替换成真实的宿主机IP,此URL对应于GIT的地址,如`http://root@127.0.0.1:180/root/test.git`,特别注意的是需要指明Nginx端口为`80`(容器真实端口),否则Nginx也会改成`180`端口导致无法访问。
   --restart always \
   -v /data/gitlab/config:/etc/gitlab \  # 映射的配置文件目录
   -v /data/gitlab/logs:/var/log/gitlab \
   -v /data/gitlab/data:/var/opt/gitlab \  # 映射的数据文件目录
   gitlab/gitlab-ce:latest

安装Gitlab-runner.

参考 https://docs.gitlab.com/runner/install/linux-repository.html

Tip

Gitlab CE自带了CI功能,但只相当于一只有调度与监控功能,实际的执行能力需要由Gitlab-runner提供,这带来的好处是Gitlab不会因为CI执行而影响性能,同时使用独立的Gitlab-runner可以使用执行器更为自由地在不同主机上部署。

Tip

由于本文使用到docker类型的Executor所以直接安装到宿主机上更为方便。

修改权限.

默认gitlab-runner会创建gitlab-runner用户,请将此用户加到sudo组(免密码)中:gitlab-runner ALL=(ALL) NOPASSWD: ALL

注册Runner.

本文件需要两个runner:

[root[@host1](https://my.oschina.net/host1) target]# gitlab-ci-multi-runner register # 注册`runner`
Running in system-mode.

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/): 
http://127.0.0.1:180/ # gitlab的地址
Please enter the gitlab-ci token for this runner:
yDNMAooQTxsrLrHgFf6C # token,见`http://<gitlab host>:180/admin/runners`
Please enter the gitlab-ci description for this runner:
[host1]:
Please enter the gitlab-ci tags for this runner (comma separated):
maven # 标签名,这里叫`maven`
Whether to run untagged builds [true/false]:
[false]:  # 是否使用标签驱动,即满足这个标签时才使用此`runner`
Whether to lock Runner to current project [true/false]:
[false]:  # 是否当前项目独占,上面的token是全局的,还一种token是关联项目的,如果使用关联某个项目的token且此处是true的时表示这个`runner`仅为这个项目使用
Registering runner... succeeded                     runner=yDNMAooQ
Please enter the executor: kubernetes, docker, parallels, shell, ssh, docker-ssh+machine, docker-ssh, virtualbox, docker+machine:
docker # 执行器类型,这里使用`docker`
Please enter the default Docker image (e.g. ruby:2.1):
maven:alpine  # `docker`容器,这里使用maven容器
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

[root[@host1](https://my.oschina.net/host1) target]# gitlab-ci-multi-runner register
Running in system-mode.

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://127.0.0.1:180/
Please enter the gitlab-ci token for this runner:
yDNMAooQTxsrLrHgFf6C
Please enter the gitlab-ci description for this runner:
[host1]:
Please enter the gitlab-ci tags for this runner (comma separated):
shell # 标签名,这里叫`shell`
Whether to run untagged builds [true/false]:
[false]:
Whether to lock Runner to current project [true/false]:
[false]:
Registering runner... succeeded                     runner=yDNMAooA
Please enter the executor: kubernetes, docker, parallels, shell, ssh, docker-ssh+machine, docker-ssh, virtualbox, docker+machine:
shell # 执行器类型,这里使用`shell`
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

此时在gitlab中可以看到runner已经生效了:

完成后生成的配置如下:

[root[@host1](https://my.oschina.net/host1) target]# cat /etc/gitlab-runner/config.toml
concurrent = 1
check_interval = 0

[[runners]]
  name = "host1"
  url = "http://127.0.0.1:180/"
  token = "dfc2643e12d0be2168950490c46999"
  executor = "docker"
  [runners.docker]
    tls_verify = false
    image = "maven:alpine"
    privileged = false
    disable_cache = false
    volumes = ["/cache", "/root/m2:/root/.m2"]  # 修改这个,将maven `.m2` 目录映射到本地
    pull_policy = "if-not-present" # 添加这行,默认每次执行都要pull镜像,修改成仅不存在时pull
    shm_size = 0
  [runners.cache]

[[runners]]
  name = "host1"
  url = "http://127.0.0.1:180/"
  token = "f069825bc10401c71e064218ba3987"
  executor = "shell"
  [runners.cache]

Tip

https://docs.gitlab.com/runner/executors/README.html

安装SonarQube.

# 运行Sonarqube依赖的数据库
docker run --name sonar-db -d \
  -e POSTGRES_USER=sonar \
  -e POSTGRES_PASSWORD=sonar \
  -e POSTGRES_DB=sonar \
  -v /data/sonar-db:/var/lib/postgresql/data \
  postgres:alpine
  
# 运行Sonarquble
docker run --name sonarqube -d \
  -p 9000:9000 -p 9092:9092 \
  -e SONARQUBE_JDBC_USERNAME=sonar \
  -e SONARQUBE_JDBC_PASSWORD=sonar \
  -e SONARQUBE_JDBC_URL=jdbc:postgresql://sonar-db/sonar?characterEncoding=utf8 \
  -v /data/sonarqube/data:/opt/sonarqube/data \
  -v /data/sonarqube/conf:/opt/sonarqube/conf \
  -v /data/sonarqube/extensions:/opt/sonarqube/extensions \  # 映射插件目录
  --link sonar-db:sonar-db \
  sonarqube:alpine

/data/sonarqube/extensions下创建plugins目录,将https://github.com/gabrie-allaigre/sonar-gitlab-plugin/releases/download/2.0.1/sonar-gitlab-plugin-2.0.1.jar下载到此目录

打开http://<host>:9000/updatecenter/available用户名/密码:`admin/admin`,下载SonarJava或其它插件并重启

https://gitlab.talanlabs.com/gabriel-allaigre/sonar-gitlab-plugin#configuration配置几个参数

示例工程

输入图片说明

/src/main/java/com/ecfront/test/devops/DevOpsApplication.java.

package com.ecfront.test.devops;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;

@SpringBootApplication
public class DevOpsApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(DevOpsApplication.class).web(true).run(args); 
    }

}
  • Spring Boot示例,开始默认为8080端口的web服务

/src/main/resources/application.yml.

spring:
  application:
    name: DevOps 
  • 指定组件名称,可忽略

/.gitlab-ci.yml.

stages:  # 定义三个阶段(pipeline)
  - verify
  - build
  - deploy

maven-build:  # job名称,可随意命名
  image: maven:alpine # 使用maven容器运行,可以忽略
  stage: build  # 绑定这个job为`build`阶段
  only: 
   - master # 仅在master分支变更时才触发执行
  tags: 
   - maven # 使用标签名为`maven`的`runner`执行
  script: "mvn package -B"  # 执行脚本,此处为打包操作
  artifacts: 
    paths:
      - target/*.jar # 本阶段输出文件,此处输出打包后的fatjar

docker-deploy:
  stage: deploy 
  tags: 
   - shell # 这个阶段使用标签名为`shell`的`runner`执行
  script:  # 这里的脚本逻辑是先把包含这个jar的文件编译成镜像,然后run it
  - sudo docker build -t ecfront/test:1.0 .
  - app="test"
  - if sudo docker ps | awk -v app="app" 'NR>1{  ($(NF) == app )  }'; then
  -  sudo docker stop "$app" && sudo docker rm -f "$app"
  - fi
  - sudo docker run --name test -d -p 8080:8080 ecfront/test:1.0

sonarqube:  # sonarqube的配置
  stage: verify
  only:
    - master
  tags:
    - maven
  script: # 使用mvn运行sonarqube处理,$SONAR\_URL为sonarqube的url
    - mvn verify sonar:sonar -Dsonar.host.url=$SONAR_URL 

Tip

在变量中添加SONAR_URL=<sonarqube url>

详见:https://docs.gitlab.com/ce/ci/variables/

Tip

https://docs.gitlab.com/ce/ci/yaml/README.html

/Dockerfile

FROM java:8-jdk-alpine 
VOLUME /tmp
ADD /target/devops.jar devops.jar 
ENTRYPOINT ["java","-jar","/devops.jar"] 
  • 使用java容器运行

  • 把上面打出的包加到镜像中

  • 容器运行后运行对应的jar文件

/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
    </parent>

    <groupId>com.ecfront.test</groupId>
    <artifactId>devops</artifactId>
    <packaging>jar</packaging>
    <version>1.0.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.sonarsource.scanner.maven</groupId>
            <artifactId>sonar-maven-plugin</artifactId>
            <version>3.3.0.603</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <finalName>${project.artifactId}</finalName>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

提交测试

我们push这个工程到gitlab后就可以看执行pipelines了:

输入图片说明

也可以查看job详细:

输入图片说明

在Sonarqube中可以看到工程已经建立了:

输入图片说明

查看test容器可以发现我们的工程已经运行起来了:

输入图片说明

© 著作权归作者所有

孤岛旭日
粉丝 45
博文 58
码字总数 30599
作品 3
杭州
架构师
私信 提问
3 天烧脑式基于Docker的CI/CD实战训练营 | 北京站

持续集成(Continuous integration)是一种软件开发实践。 它倡导团队开发成员必须经常集成他们的工作,甚至每天都可能发生多次集成。 与持续集成相关的,还有两个概念,分别是持续交付(Con...

DockOne
2017/07/25
1
0
3 天烧脑式基于Docker的CI/CD实战训练营 | 北京站

持续集成(Continuous integration)是一种软件开发实践。 它倡导团队开发成员必须经常集成他们的工作,甚至每天都可能发生多次集成。 与持续集成相关的,还有两个概念,分别是持续交付(Con...

DockOne
2017/07/25
0
0
DevOps 流水线工具 gitlab-ci 实践

GitLab-CI GitLab-CI 是一套配合 GitLab 使用的持续集成系统。当然,还有其它的持续集成系统,同样可以配合 GitLab 使用,比如 Jenkins。上一遍文章利用自定义 DSL 简化 jenkins 流水线,就是...

scottlin
03/24
0
0
Gitlab-CI 初级篇 - Gitlab Runner

Gitlab Runner 在项目根目录下添加 .gitlab-ci.yml 文件,整个持续集成系统是 Gitlab 自带的,要做的就是添加一个 Runner 到系统里来解析文件中的 script 部分。 安装 Gitlab Runner 官方提供...

内河
2018/12/27
0
0
I-team 博客的 gitlab-runner 持续集成实践

做为一个略微看过nodejs语法,但又不懂nodejs的攻城狮,搭建hexo环境很是麻烦,要考虑到FQ、版本兼容等问题。于是乎,博主每换一个电脑,为了能继续发博客,都需要在新电脑上花一天时间重新搞...

haifeiWu
2018/07/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Oracle SQL语法实例合集

如需转载请注明出处https://my.oschina.net/feistel/blog/3052024 目的:迅速激活Oracle SQL 参考:《Oracle从入门到精通》 ------------------------------------------------------------......

LoSingSang
今天
2
0
增加 PostgreSQL 服务进程的最大打开文件数

https://serverfault.com/questions/628610/increasing-nproc-for-processes-launched-by-systemd-on-centos-7 要在systemd的配置里加才行...

helloclia
今天
2
0
组合模式在商品分类列表中的应用

在所有的树形结构中最适合的设计模式就是组合模式,我们看看常用商品分类中如何使用。 先定义一个树形结构的商品接口 public interface TreeProduct { List<TreeProduct> allProducts(...

算法之名
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部