zhangguanzhang's Blog

利用travis同步gcr.io镜像到dockerhub

字数统计: 2.4k阅读时长: 11 min
2018/07/08

项目地址https://github.com/zhangguanzhang/gcr.io/tree/master

利用gcloud sdk去查看谷歌镜像站的镜像,获取每一个镜像的tag后改名推送到自己的dockerhub
上面全部是shell思路,脚本一旦写完就需要不断的执行去同步了,所以借用travis去构建
两个分支,一个master分支和一个构建分支
travis触发构建后拉取仓库后,切换到构建分支,pull构建分支,然后同步镜像

脚本我写了两种https://github.com/zhangguanzhang/bash/tree/master/google_containers_sync
v1是利用 dockerhub registry 的v2 api去查询当前遍历的tag是否存在
因为 docker 镜像迭代不会去修复老镜像的 bug,也就是说 v1 每次执行都会去查询一个固定值,参照 kuops 的思路是本地生成文件,去判断有文件就说明dockerhub上同步过了,也就是脚本v2的思路

思路借鉴https://kuops.com
先说下本地思路过程,需要梯子

配置gcloud

获取授权文件

打开 gcloud 控制台,点击 iam 管理,创建一个授权查看镜像列表的账号,json 格式

点击创建密钥下载json文件

下载json文件后上传到主机,此处我上传到家目录改名为gcloud.config.json

安装gcloud

下面发代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 添加yum源
sudo tee -a /etc/yum.repos.d/google-cloud-sdk.repo << EOM
[google-cloud-sdk]
name=Google Cloud SDK
baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOM

# 安装 gcloud sdk
yum install google-cloud-sdk -y

# 登陆
gcloud auth activate-service-account --key-file gcloud.config.json

#获取镜像列表
gcloud container images list --repository=gcr.io/google_containers --format="value(NAME)"

gcloud的container命令的相关文档

https://cloud.google.com/sdk/gcloud/reference/container/images/list
https://cloud.google.com/sdk/gcloud/reference/container/images/list-tags

登陆dockerhub

1
2
3
4
[root@k8s-n1 ~]# docker login
# 授权文件保存在
[root@k8s-n1 ~]# ls -l ~/.docker/config.json
-rw------- 1 root root 172 Jun 30 12:18 /root/.docker/config.json

利用脚本并发同步镜像

https://github.com/zhangguanzhang/bash/blob/master/google_containers_sync/v2.sh

脚本过程解释

因为 gcloud 只能查看下面的仓库,后期可能同步多个仓库,所以每个镜像名包含了仓库名
假设镜像是gcr.io/google_containers/busybox:test, /转换为.去推送,即zhangguanzhang/gcr.io.google_containers.busybox:test

  • gcr.io
  • us.gcr.io
  • eu.gcr.io
  • asia.gcr.io
  • staging-k8s.gcr.io
  • l.gcr.io
  • launcher.gcr.io
  • marketplace.gcr.io
  • us-mirror.gcr.io
  • eu-mirror.gcr.io
  • asia-mirror.gcr.io
  • mirror.gcr.io
  • k8s.gcr.io

刚开始写的时候就是利用多进程来写,生产者和消费者的模式,多进程拉取,多进程推送.结果经常网络问题,拉取和推送冲突了

然后直接多进程拉取,每个进程拉取前判断根分区的容量到了70%以上没,到了就wait等待所有后台完成,然后推送
推送完一个镜像就本地gcr.io.google_containers/busybox/目录生成一个标签的文件
下一次执行因为[ -f "$repository_dir/$image_name/$tag" ] && continue跳过,latest标签处理思路在我上面脚本链接下的readme.md写了

如何融入到travis里

travis官网

travis同步流程

上面本地来同步来说,全部弄好了,后期就是不断执行就行了,无论执行中是否中断,毕竟推送完就生成文件,下次就能继续同步了
travis的工作流程是(得先提前在travis官网上把你要构建的仓库勾上,并且根目录有.travis.yml编排文件)你提交了github仓库,travis会拉取你仓库代码到构建服务器里(就是一台云主机)后按照.travis.yml里的编排去执行操作

.travis.yml里一般都会解密后最终执行一个命令,所以最终命令是我们的脚本
因为是文件判断镜像拉取了没,所以每次推送镜像完都把本地的所有文件git add -A;git commit -m 'xxx';git push

流程就是(下面流程都是构建服务器执行的)

  • 拉取你的仓库代码
  • 解密文件,然后解压压缩包,gcloud的json密钥文件,docker的login文件,github的私钥(用于在构建服务器里推送到github免密)
  • 授权gcloud,安装docker-ce
  • 执行同步脚本

项目过程

安装travis

建议使用docker镜像挂载进去使用travis命令行,因为rvm有安装完ssh无法ctrl+c的bug
本机安装的话得先安装rvm,然后安装ruby,然后用gem install travis

准备加密文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 登陆travis

[root@k8s-n1 ~]# travis login
Shell completion not installed. Would you like to install it now? |y| y
We need your GitHub login to identify you.
This information will not be sent to Travis CI, only to api.github.com.
The password will not be displayed.

Try running with --github-token or --auto if you don't want to enter your password anyway.

Username: zhangguanzhang
Password for zhangguanzhang: ********
Successfully logged in as zhangguanzhang!

# 生成ssh免密用于推送github

[root@k8s-n1 ~]# ssh-keygen -t -b 4096 rsa -f ~/.ssh/id_rsa -P '' -C 'zhangguanzhang@qq.com'
Generating public/private rsa key pair.
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:8PbPnOc5R******************f7UAz1dTEJI zhangguanzhang@qq.com
The key's randomart image is:
+---[RSA 2048]----+
| ..++*|
| **..B=|
| . . *.@.=|
| o * *.*.|
| S . B.= o|
| . . . *...|
| . o.o o|
| = .o+ |
| *++. |
+----[SHA256]-----+

生成密钥后把~/.ssh/id_ras.pub的内容添加到github的SSH and GPG keys

先把所有文件打包,我在家目录打包

1
2
3
4
5
6
7
8
[root@k8s-n1 ~]# tar zcf conf.tar.gz  .docker/config.json  gcloud.config.json  .ssh/id_rsa

# 进到脚本项目目录并git init

[root@k8s-n1 ~]# cd gcr.io
[root@k8s-n1 gcr.io]# git init
Reinitialized existing Git repository in /root/gcr.io/.git/
[root@k8s-n1 gcr.io]# git remote add origin git@github.com:zhangguanzhang/gcr.io.git

在github上创建仓库后

登陆travis让travis知道仓库(点击左上角的sync account),不然travis无法加密文件

使用 travis cli 对多个文件进行加密,必须先创建.travis.yml文件

1
2
3
4
5
6
7
8
9
[root@k8s-n1 gcr.io]# touch .travis.yml
[root@k8s-n1 gcr.io]# travis encrypt-file $HOME/conf.tar.gz --add
encrypting /root/conf.tar.gz for zhangguanzhang/gcr.io
storing result as conf.tar.gz.enc
storing secure env variables for decryption

Make sure to add conf.tar.gz.enc to the git repository.
Make sure not to add /root/conf.tar.gz to the git repository.
Commit all changes to your .travis.yml.

解密的关键信息每个人都不一样,不能用别人的,内容会生成在文件里,去掉~\/conf.tar.gz里的转义斜线,此处是个bug

1
2
3
4
5
6
7
8
9
10
11
[root@k8s-n1 gcr.io]# cat .travis.yml 
before_install:
- openssl aes-256-cbc -K $encrypted_79f048dff636_key -iv $encrypted_79f048dff636_iv
-in conf.tar.gz.enc -out ~\/conf.tar.gz -d

# 确保下面后再写编排脚本,可以去官网学习下简单的操作

[root@k8s-n1 gcr.io]# cat .travis.yml
before_install:
- openssl aes-256-cbc -K $encrypted_79f048dff636_key -iv $encrypted_79f048dff636_iv
-in conf.tar.gz.enc -out ~/conf.tar.gz -d

此处我单独把加密的压缩包放在了目录下,所以openssl的解密的-in后面目录改了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@k8s-n1 gcr.io]# mkdir .travis;  mv conf.tar.gz.enc .travis/
[root@k8s-n1 gcr.io]# cat .travis.yml
sudo: required
language: python
python:
- '2.7'
addons:
apt:
packages:
- docker-ce
branches:
only:
- master
install:
- git remote -v
script:
- "bash ./sync.sh 5"
before_install:
- mkdir -p ~/.docker
- mkdir -p ~/.ssh
- openssl aes-256-cbc -K $encrypted_79f048dff636_key -iv $encrypted_79f048dff636_iv
-in .travis/conf.tar.gz.enc -out ~/conf.tar.gz -d
- tar zxf ~/conf.tar.gz -C ~
- chmod 600 ~/.ssh/id_rsa
- chmod 600 ~/.docker/config.json
- eval $(ssh-agent)
- ssh-add ~/.ssh/id_rsa

准备github仓库文件,master存放源码,develop存放构建过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[root@k8s-n1 gcr.io]# ll -a
total 36
drwxr-xr-x 4 root root 117 Jul 15 18:40 .
dr-xr-x---. 16 root root 4096 Jul 15 14:30 ..
drwxr-xr-x 8 root root 254 Jul 15 16:10 .git
-rw-r--r-- 1 root root 205 Jul 14 14:39 .gitignore
-rw-r--r-- 1 root root 11357 Jul 14 14:39 LICENSE
-rw-r--r-- 1 root root 576 Jul 14 14:39 README.md
-rw-r--r-- 1 root root 5184 Jul 15 14:25 sync.sh
drwxr-xr-x 2 root root 29 Jul 15 16:10 .travis
-rw-r--r-- 1 root root 1006 Jul 15 16:10 .travis.yml
[root@k8s-n1 gcr.io]# git config --global user.name "zhangguanzhang"
[root@k8s-n1 gcr.io]# git config --global user.email zhangguanzhang@qq.com
[root@k8s-n1 gcr.io]# git add -A
[root@k8s-n1 gcr.io]# git commit -m 'XXX'

[root@k8s-n1 gcr.io]# git push -u origin master

[root@k8s-n1 gcr.io]# git checkout -b develop
Switched to a new branch 'develop'
[root@k8s-n1 gcr.io]# git status
# On branch develop
nothing to commit, working directory clean
[root@k8s-n1 gcr.io]# git add -A
[root@k8s-n1 gcr.io]# git commit -m 'develop first'
# On branch develop
nothing to commit, working directory clean
[root@k8s-n1 gcr.io]# git remote add origin git@github.com:zhangguanzhang/gcr.io.git
[root@k8s-n1 gcr.io]# git push origin develop -f
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:zhangguanzhang/gcr.io.git
+ ad2758b...3554dde develop -> develop (forced update)

travis设置

登陆并关联仓库

随便改下仓库的东西触发构建

可以看见构建过程中git push了已经同步的镜像判断文件

travis调度到的机器可能gce可能aws,磁盘空间可以看到一般30G左右,我脚本里的百分比设置为70,线程设置为20

当然,第一次同步肯定会超时,每次免费构建50分钟,所以不断的构建就行了

友情提醒: gcr.io/google_containers/cos-nvidia-driver-install每个tag都2G,进程数量太多的话会造成构建服务器的空间占满

最后给个东西给懂的人

抓包为下面内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
POST /build/404478037/restart HTTP/1.1
Host: api.travis-ci.org
Connection: keep-alive
Content-Length: 0
Travis-API-Version: 3
Origin: https://travis-ci.org
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
Content-Type: application/json
Accept: application/json
Authorization: token feJJF1****wY1U1kfJAw
Referer: https://travis-ci.org/zhangguanzhang/gcr.io
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9


curl -s -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Travis-API-Version: 3" \
-H 'Origin: https://travis-ci.org' \
-H "Authorization: token feJJF1******1U1kfJAw" \
-H "User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36" \
https://api.travis-ci.org/build/404478037/restart

再高级点

1
travis restart -r zhangguanzhang/gcr.io
CATALOG
  1. 1. 配置gcloud
    1. 1.1. 获取授权文件
    2. 1.2. 安装gcloud
  2. 2. 登陆dockerhub
  3. 3. 利用脚本并发同步镜像
  4. 4. 脚本过程解释
  5. 5. 如何融入到travis里
    1. 5.1. travis同步流程
  6. 6. 项目过程
    1. 6.1. 安装travis
    2. 6.2. 准备加密文件
    3. 6.3. 准备github仓库文件,master存放源码,develop存放构建过程
    4. 6.4. travis设置