- 持续集成
- 自动化测试
- 虚拟化
Introduce to GitLab CI
GitLab CI(Continuous Integration )从GitLab8.0开始就集成于GitLab中,后端的Runner使用.gitlab-ci.yml file 文件来描述对项目进行配置,.gitlab-ci.yml文件告诉GitLab运行器该做什么。 默认情况下,它运行一个包含三个stage的pipeline:构建,测试和部署。 你不需要使用所有三个stage; 没有job的stage会被忽略。
here's a growing trend to use continuous delivery and continuous deployment to automatically deploy tested code to staging and production environments.
运行一个CI需要有两步操作:
- 将.gitlab-ci.yml添加到存储库的根目录
- 配置一个Runner
Write a .gitlab-ci.yml
.gitlab-ci.yml文件是您配置CI对项目执行的操作的位置。 它位于存储库的根目录中。在任何推送到您的存储库时,GitLab将查找.gitlab-ci.yml文件,并根据该文件的内容在Runners上启动该提交的Job。
注意:.gitlab-ci.yml是一个YAML文件,所以你必须特别注意缩进。 始终使用空格,而不是制表符。
jobs
YAML文件定义了一组具有约束的job,说明应该何时运行它们。 您可以将job的顶级元素定义为任意名称,它们至少需要包含script子句。
job1:
script: "execute-script-for-job1"
job2:
script: "execute-script-for-job2"
job内的关键字
关键字 | 功能 |
---|---|
script | 由shell执行的脚本 |
stage | job的stage,默认为test |
variables | job可见的环境变量 |
allow_failure | 是否运行job失败 |
when | 什么情况下执行job,可选on_success/on_failure/always/manual |
only/except/tags | 只在某些分支下执行job,指定执行job |
artifacts | job完成后把文件存在这个目录里 |
dependencies | 依赖的job,可以用artifacts进行共享文件 |
coverage | ? |
before_script | 覆盖在job之前执行的一组命令 |
stages
stages:
- build
- test
- deploy
stages指定了各个stage的执行顺序
- 同一stage的job是并行运行的。
- 下一stage的job在上一stage的job成功完成后运行。
artifacts
artifacts指的是成功后应附加到job的文件和目录列表。job成功完成后,artifact将被发送到GitLab,并可在GitLab UI中下载
** artifacts:paths**:路径
**artifacts:expire_in ** 有效时间,默认为30天
dependencies
此功能应与artifact结合使用,并允许您定义要在不同job之间传递的artifact。请注意,默认情况下会传递所有先前阶段的artifact。
在CI中使用docker
Docker与GitLab CI一起使用时,使用.gitlab-ci.yml中设置的预定义镜像在单独且隔离的容器中运行每个job。
register a docker runner
使用sudo权限输入
sudo gitlab-runner register
接下来会提示输入gitlab仓库位置,tocken,以及使用的执行器,使用docker的话执行器就选择docker,然后选择镜像,这个配置以后可以通过修改配置文件进行修改,如果是通过root权限注册的,那么配置文件在/etc/gitlab-runner/config.toml文件中。
使用docker镜像的时候,默认是会从docker-hub下载镜像,如果镜像在本地,可以在config文件设置pull的policy:pull_policy = "if-not-present"或者pull_policy = "never"
[[runners]]
name = ""
url = ""
token = ""
executor = "docker"
[runners.docker]
tls_verify = false
image = "nb-node"
privileged = false
disable_cache = false
volumes = ["/cache"]
+ pull_policy = "if-not-present"
[runners.cache]
安装docker 和 nvidia-docker
ubuntu安装docker
Nvidia-Docker安装使用 -- 可使用GPU的Docker容器
具体安装方法参考官方github文档
值得注意的是上面的教程都是针对 nvidia-docker 1.0版本的,而最近我测试安装时不成功的,所以我安装了最新的nvidia-docker 2.0, nvidia-docker 2.0要求docker 版本为 18.06.0-ce,而这个版本的docker 使用apt-get 是无法安装的,所以我们从官网手动下载deb文件,进行安装。
卸载老版本的docker
apt-get remove docker-ce
下载安装新版本的docker
wget https://download.docker.com/linux/ubuntu/dists/trusty/pool/stable/amd64/docker-ce_18.06.0~ce~3-0~ubuntu_amd64.deb
dpkg -i docker-ce_18.06.0~ce~3-0~ubuntu_amd64.deb
rm docker-ce_18.06.0~ce~3-0~ubuntu_amd64.deb
然后安装nvidia-docker的github的方式安装nvidia-docker-2.
docker自定义远端仓库位置
docker切换默认镜像源
默认安装的 docker 镜像源是在国外,pull 镜像的时候奇慢无比,需要自己手动切换成国内的镜像源。
docker 默认的配置文件是 /etc/default/docker
,如果此目录下不存在 docker 文件,可以自己手动创建一个,将文件中添加内容:
DOCKER_OPTS=" --registry-mirror=https://【xxxxx】.mirror.aliyuncs.com"
上述代码中的地址替换成自己想要更换的镜像源的地址即可,然后使用 service docker restart命令重启服务。
自定义的仓库可能需要通过 docker login 进行登录。
可以参考define-an-image-from-a-private-container-registry
如果要将私有docker仓库用作构建的镜像源,可以在DOCKER_AUTH_CONFIG秘密变量中设置授权配置。 它可以在项目的GitLab变量部分(网页端)和config.toml文件中设置。
在CI中定义镜像和服务
before_script:
- bundle install
test:2.1:
image: ruby:2.1
services:
- postgres:9.3
script:
- bundle exec rake spec
test:2.2:
image: ruby:2.2
services:
- postgres:9.4
script:
- bundle exec rake spec
CI 手动调docker回传artifact 的一个例子
#image: cicuda8
build_arti:
stage: build
tags:
- manual_docker
script:
- hostname
- mkdir build && cd build
- touch tmp
- echo "cd hostbuild && echo hello-world > tmp2" > tmp
artifacts:
expire_in: 1 day
paths:
- build/
test_arti:
stage: test
tags:
- manual_docker
script:
- sudo docker run --name test_manual_docker -i \
-v $(pwd)/build:/hostbuild cicuda8 sh /hostbuild/tmp
- sudo docker rm test_manual_docker
dependencies:
- build_arti
artifacts:
expire_in: 1 day
paths:
- build/
deploy_arti:
stage: deploy
tags:
- manual_docker
script:
- cd build
- cat tmp2
- echo "end4"
dependencies:
- test_arti
CI通过SSH连接来调docker的例子
#image: cicuda8
build_arti:
stage: build
tags:
- manual_docker
script:
- hostname
- mkdir build && cd build
- touch tmp
- echo "cd hostbuild && echo hello-world > tmp2" > tmp
artifacts:
expire_in: 1 day
paths:
- build/
test_arti:
stage: test
tags:
- manual_docker
script:
- cp /usr/share/expect_login.sh expect_login.sh
- echo "send \"sudo docker run --name test_manual_docker -i -v $(pwd)/build:/hostbuild cicuda8 sh /hostbuild/tmp\r\"" >> expect_login.sh
- echo "expect $*" >> expect_login.sh
- echo "send \"sudo docker rm test_manual_docker\r\"" >> expect_login.sh
- echo "expect $*" >> expect_login.sh
- cat expect_login.sh
- expect expect_login.sh 10.10.36.34
#- sudo docker run --name test_manual_docker -i -v $(pwd)/build:/hostbuild cicuda8 sh /hostbuild/tmp
#- sudo docker rm test_manual_docker
dependencies:
- build_arti
artifacts:
expire_in: 1 day
paths:
- build/
deploy_arti:
stage: deploy
tags:
- manual_docker
script:
- cd build
- cat tmp2
- echo "end6"
dependencies:
- test_arti
这里使用了expect脚本:expect_login.sh
#!/usr/bin/expect
set timeout 30
set ip [lindex $argv 0]
spawn ssh -l maxiaolong 10.0.8.241
expect "password:"
send "mxl@lt.776688\r"
expect "Ip:*"
send "$ip\r"
expect "$*"
send "hostname\r"
expect $*
send ifconfig\r
expect "$*"
#interact
第二个例子 本地执行docker
stages:
- build-default2
- lint
- test-default
- build-more
- test-more
- build-python-full
- test-python-full
build-default2:
stage: build-default2
variables:
CC: "/usr/bin/gcc-4.8"
CXX: "/usr/bin/g++-4.8"
GTEST_ROOT: "/usr/local/gtest/gtest-4.8"
tags:
- manual_docker
script:
- mkdir temp && cd temp && touch scripts.sh mylog.log
- git clone $CI_REPOSITORY_URL
- echo "cd /temp && export CC=/usr/bin/gcc-4.8 && export CXX=/usr/bin/g++-4.8 && export GTEST_ROOT=/usr/local/gtest/gtest-4.8 " >> scripts.sh
- echo "cd $CI_PROJECT_NAME " >> scripts.sh
- echo "git checkout $CI_COMMIT_REF_NAME" >> scripts.sh
- echo "mkdir build && cd build/ && cmake .. && make -j8 " >> scripts.sh
- echo "cd ../python && make -j8 " >> scripts.sh
- cat scripts.sh
- cd -
- sudo nvidia-docker run -i --rm -v $(pwd)/temp:/temp cicuda8:parrots2 sh /temp/scripts.sh
- cat temp/mylog.log
第三个例子 上海集群执行docker
stages:
- build-default
- lint
- test-default
- build-more
- test-more
- build-python-full
- test-python-full
build-default:
stage: build-default
variables:
CC: "/usr/bin/gcc-4.8"
CXX: "/usr/bin/g++-4.8"
GTEST_ROOT: "/usr/local/gtest/gtest-4.8"
tags:
- ssh_docker
script:
- hostname
- who -m
- mkdir temp && cd temp && touch scripts.sh
- echo "cd /$CI_PROJECT_NAME && export CC=/usr/bin/gcc-4.8 && export CXX=/usr/bin/g++-4.8 && export GTEST_ROOT=/usr/local/gtest/gtest-4.8 " >> scripts.sh
- echo "cd $CI_PROJECT_NAME && hostname && pwd " >> scripts.sh
- echo "mkdir build && cd build/ && cmake .. && make -j8 " >> scripts.sh
- echo "cd ../python && make -j8 " >> scripts.sh
- cat scripts.sh
- cd -
- nvidia-docker run -i --rm -v $(pwd):/$CI_PROJECT_NAME registry.sensetime.com/platform/cicuda8:parrots2 sh /$CI_PROJECT_NAME/temp/scripts.sh
Configure a Runner
在GitLab中,Runners运行您在.gitlab-ci.yml中定义的作业。 Runner可以是虚拟机,VPS,裸机,docker容器甚至是容器集群。
get more information at GitLab Runner.
reference
"error while loading shared libraries: xxx.so.x" 错误的原因和解决办法
the docker excutor
Using Docker images
Getting started with GitLab CI/CD
Configuration of your jobs with .gitlab-ci.yml