您的位置:首页 > 其它

基于Gitlab的CD流程实践

2017-05-11 10:02 465 查看

基于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
,请自行修改。



使用Gitlab做版本控制

代码Push后:

调用SonarQube做质量检查

调用Gitlab CI做编译及单元测试(CI)

调用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
容器可以发现我们的工程已经运行起来了:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: