GitLab CI 是默认包含在 GitLab 中的,我们的代码使用 GitLab 进行托管,这样可以很容易的进行集成
GitLab CI 的前端界面比较美观,容易被人接受
包含实时构建日志,容易追踪
采用 C/S 的架构,可方面的进行横向扩展,性能上不会有影响
使用 YAML 进行配置,任何人都可以很方便的使用
所有 Stages 按顺序执行,即当一个 Stage 完成后,下一个 Stage 才会开始
任一 Stage 失败,后面的 Stages 将永不会执行,Pipeline 失败
只有当所有 Stages 完成后,Pipeline 才会成功
相同 Stage 中的 Jobs 会并行执行
任一 Job 失败,那么 Stage 失败,Pipeline 失败
相同 Stage 中的 Jobs 都执行成功时,该 Stage 成功
docker run --rm -t -i -v /path/to/config:/etc/gitlab-runner --name gitlab-runner gitlab/gitlab-runner register \
--executor "docker" \
--docker-image alpine:3 \
--url "https://gitlab.com/" \
--registration-token "PROJECT_REGISTRATION_TOKEN" \
--description "docker-runner" \
--tag-list "dev" \
--run-untagged \
--locked="true"
sudo gitlab-runner register \
--non-interactive \
--url "https://gitlab.com/" \
--registration-token "PROJECT_REGISTRATION_TOKEN" \
--executor "docker" \
--docker-image alpine:3 \
--description "docker-runner" \
--tag-list "docker,aws" \
--run-untagged \
--locked="false" \
(这段代码来自官方文档)
Shared:Runner runs jobs from all unassigned projects
Group:Runner runs jobs from all unassigned projects in its group
Specific:Runner runs jobs from assigned projects
Locked:Runner cannot be assigned to other projects
Paused:Runner will not receive any new jobs
concurrent = 1
check_interval = 0
这两个。 比较需要关注的是下面几个:
concurrent:并发数,0 为无限制。
sentry_dsn:与 Sentry 联动,可以将异常等收集至 Sentry 中。
listen_address:暴露出 metrics 供 Prometheus 监控。
Shell
Docker(本次的分享内容)
Docker Machine and Docker Machine SSH(autoscaling)
Parallels
VirtualBox
SSH
Kubernetes(推荐)
sudo docker run --rm -ti -v /var/run/docker.sock:/var/run/docker.sock taobeier/docker /bin/sh
在容器内可进行正常的 Docker images 等操作, 同时需要注意,在容器内的动作,将影响到 宿主机上的 Docker daemon。
如何实现
创建组和用户,并将用户加入该组。 使用 groupadd 和 useradd 命令。
更新 subuid 和 subgid 文件, 将新用户和组配置到 /etc/subgid 和 /etc/subuid 文件中。 subuid 和 subgid 规定了允许用户使用的从属 ID。
接下来需要挂载 /sys/kernel/security 为 securityfs 类型可以使用 mountpoint 命令进行测试 mountpoint /sys/kernel/security 如果不是一个挂载点, 那么使用 mount -t securityfs none /sys/kernel/security 进行挂载。如果没有挂载成功的话, 可以检查是否是 SELinux 或者 AppArmor 阻止了这个行为。这里详细的安全问题,可以参考 Linux Security Modules (LSM)。
接下来允许 dockerd 命令启动 daemon 即可, dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2375 即可将docker daemon 监听至 2375 端口。
[[runners]]
name = "docker"
url = "https://gitlab.example.com/"
token = "TOKEN"
limit = 0
executor = "docker"
builds_dir = ""
shell = ""
environment = ["ENV=value", "LC_ALL=en_US.UTF-8"]
clone_url = "http://172.17.0.4"
由于网络原因, clone_url 可以配置为可访问的地址,这样代码 clone 的时候,将会使用配置的这个地址。实际请求为 http://gitlab-ci-token:[email protected]/namespace/project.git。
[runners.docker]
host = ""
hostname = ""
tls_cert_path = "/home/tao/certs"
image = "docker"
dns = ["8.8.8.8"]
privileged = false
userns_mode = "host"
devices = ["/dev/net/tun"]
disable_cache = false
wait_for_services_timeout = 30
cache_dir = ""
volumes = ["/data", "/home/project/cache"]
extra_hosts = ["other-host:127.0.0.1"]
services = ["mongo", "redis:3"]
allowed_images = ["go:*", "python:*", "java:*"]
DNS,Privileged,extra_hosts,Services 比较关键, 尤其是在生产中网络情况多种多样, 需要格外关注。 至于 Devices 配置 ,在今儿分享的一开始已经讲过了, allowed_images 的话, 是做了个限制。
image: registry.docker-cn.com/taobeier/docker
variables:
DOCKER_DRIVER: overlay2 # overlay2 is best bug need kernel >= 4.2
services:
- name: registry.docker-cn.com/taobeier/docker:stable-dind
alias: docker
stages:
- build
- deploy
build_and_test:
stage: build
tags:
- build
script:
# change repo
#- sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
# 使用默认官方源 apk 耗时 7min 30s. 修改后 耗时 18s
- ping -c 1 docker
- ping -c 1 registry.docker-cn.com__taobeier__docker
- ipaddr
- apk add --no-cache py-pip
# 使用默认耗时 1 min 15s. 修改后耗时 43s
- pip install -i https://mirrors.ustc.edu.cn/pypi/web/simple docker-compose
- docker-compose up -d
- docker-compose run --rm web pytest -s -v tests/test_session.py
deploy:
image: "registry.docker-cn.com/library/centos"
stage: deploy
tags:
- deploy
script:
# install ssh client
- 'ssh-agent || (yum install -y openssh-clients)'
# run ssh-agent
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
# create ssh dir
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
# use ssh-keyscan to get key
- ssh-keyscan -p $SSH_PORT $DEPLOY_HOST >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
# - ssh -p $SSH_PORT $DEPLOY_USER@$DEPLOY_HOST ls
- rm -rf .git
- scp -r -P $SSH_PORT . $DEPLOY_USER@$DEPLOY_HOST:~/we/
Services 的本质其实是使用了 Docker 的 --link ,我们来看下它如何工作:
创建 service 容器(已经配置在 service 中的镜像)
创建 cache 容器(存储已经配置在 config.toml 的卷和构建镜像的 Dockerfile)
创建 build 容器 并且 link 所有的 service 容器
启动 build 容器 并且发送 job 脚本到该容器中
执行 job 的脚本
检出代码:/builds/group-name/project-name/
执行 .gitlab-ci.yml 中定义的步骤
检查脚本执行后的状态码,如果非 0 则构建失败
移除 build 和 service 容器
{
"auths": {
"registry.example.com": {
"auth": "5oiR5piv5byg5pmL5rab"
}
}
}
简单的做法就是,我们在本地/服务器上执行 docker login 私有镜像源 登录成功后,将 ~/.docker/config.json 的文件内容直接复制,作为我们的变量的值。
services:
- name: registry.docker-cn.com/taobeier/docker:stable-dind
那这个 service 的host 是什么呢?
variables:
DOCKER_HOST: "tcp://registry.docker-cn.com__taobeier__docker:2375"
但是这种方式很麻烦,没有人能完全记住遇到 / 会转换为 _ 难免会有问题。 那么就有了第二种办法:
services:
- name: registry.docker-cn.com/taobeier/docker:stable-dind
alias: docker
加一个 alias 。 这个方法目前很少人在用, 毕竟网络上查到的都是第一种 ,但是这个方式却是最简单的。