目的


1、将业务打包容器化,实现快速部署多台机器;

2、代码发生变化时自动更新镜像;

3、自动拉取新的镜像;

4、自动重启容器使之生效的;

实现流程

参考:https://www.jianshu.com/p/358bfb64e3a6

1、服务器安装与部署 git、gitlab、jenkins、docker、docker registry

2、本地安装git,并将本地代码通过 git 上传到 gitlab 仓库(作为一个服务,比如 get_video_info)

3、gitlab 捕获 push 操作,触发webhook,推送到 jenkins

4、jenkins 获取推送源码,并编译、打包,构建新的镜像

5、jenkins push 新构建的镜像 到 docker registry

6、jenkins 在 需要部署应用的服务器执行远程脚本,执行 docker pull 操作拉取新的镜像,并删除旧容器、启动新的容器

7、测试人员通过 jenkins 获取部署结果

机器分配


假设总共 N台机器

A(1台):安装 Docker、Docker Registry、Git、GitLab、Jenkins

B(N-1台):安装 Docker

测试服务介绍:GetVideoInfo


Docker 篇


安装与配置 Docker

使用 Docker 安装 Docker Registry

Git 篇


安装与配置 Git

yum remove git

vim /etc/yum.repos.d/wandisco-git.repo

[wandisco-git]

name=Wandisco GIT Repository

baseurl=http://opensource.wandisco.com/centos/7/git/$basearch/

enabled=1

gpgcheck=1

gpgkey=http://opensource.wandisco.com/RPM-GPG-KEY-WANdisco

# 保存

rpm --import http://opensource.wandisco.com/RPM-GPG-KEY-WANdisco

yum -y install git

git --version
# git version 2.22.0

Gitlab 篇


安装与配置 GitLab

1、安装依赖包

sudo yum install -y curl policycoreutils-python openssh-server openssh-clients postfix

systemctl enable postfix && systemctl start postfix

2、配置安装源

cat <<EOF > /etc/yum.repos.d/gitlab_tsinghua.repo
[gitlab-ce]
name=gitlab-ce
baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/
Repo_gpgcheck=0
Enabled=1
Gpgcheck=0
EOF

3、安装 gitlab

yum makecache

yum install -y gitlab-ce

4、配置 gitlab

因为 gitlab 所在的机器要单独安装 prometheus 和 grafana,为了避免端口冲突,先关闭 gitlab中 两个服务

vim /etc/gitlab/gitlab.rb

external_url 'http://120.xxx.xx.xxx:10818'
unicorn['worker_processes'] = 2
gitlab_rails['time_zone'] = 'Asia/Shanghai'

# 1755行
prometheus['enable'] = false 
# 1945行
grafana['enable'] = false
# 保存

sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart

升级 Gitlab

Gitlab 不能跨大版本升级,所以最好定期进行升级更新;

查看是否可以升级,可以在 Gitlab 界面 右上角的管理中心-概览-仪表盘-组件,查看是否有橙色的提示:update available;

从13.10升级到14.03

# 查看当前版本号
cat /opt/gitlab/embedded/service/gitlab-rails/VERSION  # 13.10.0
yum list | grep gitlab-ce

# 停止 gitlab 的几个相关服务
gitlab-ctl stop unicorn

gitlab-ctl stop sidekiq

gitlab-ctl stop nginx

# unicorn 配置在14版本已被弃用,所以要注释掉 unicorn['worker_processes'] = 2
vim /etc/gitlab/gitlab.rb
# unicorn['worker_processes'] = 2
# 保存

# 备份 gitlab数据,默认存储在 /var/opt/gitlab/backups
# 备份文件名格式为:1565056437_gitlab_backup.tar,其中1565056437即为此次备份都版本号
# 可以修改备份存放位置 vim /etc/gitlab/gitlab.rb
# gitlab_rails['backup_path'] = "/var/opt/gitlab/backups"

gitlab-rake gitlab:backup:create
# 最好再手动备份一下 /etc/gitlab 这个文件夹

# 如果升级失败,可以恢复备份
gitlab-rake gitlab:backup:restore BACKUP=备份版本号

# 开始升级
cat <<EOF > /etc/yum.repos.d/gitlab_tsinghua.repo
[gitlab-ce]
name=gitlab-ce
baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/
Repo_gpgcheck=0
Enabled=1
Gpgcheck=0
EOF

yum makecache
yum install -y gitlab-ce-13.12.7
yum install -y gitlab-ce-14.0.3

gitlab-ctl reconfigure

gitlab-ctl restart

使用 Gitlab 并创建服务


1、访问 gitlab,浏览器地址栏输入刚才配置的 external_url

2、创建新用户,并需要进入命令行激活,也可以在这里冻结用户,修改密码等;

# 修改 密码
gitlab-rails console -e production
user = User.where(id: 1).first    # 修改 root 密码
user=User.where(email:'jenkins@domian.com').first    # 根据邮箱修改密码
user.password = 'secret_pass'
user.password_confirmation = 'secret_pass'
user.state = "active"
user.save!
exit

3、为新用户授权管理员

1、通过第二步的方式修改root的密码 

2、gitlab 页面中登录 root账户

3、用户管理中心 -> 概览 -> 用户 ->
编辑要设置的用户 -> 访问类型(access level) 修改为 管理员

4、在 头像的 preferences 中 设置语言为中文

5、创建群组,群组名为项目名(CasiaCopyrightTeam);

6、在本地 windows 机器,创建一个新的项目,比如叫 CopyrightModule,里面放着各个未来要封装为镜像的文件夹,并把每个镜像对应的文件夹 初始化为 git 仓库,以 GetVideoInfo 为例,把 GetVideoInfo 放到 CopyrightModule 目录下,并在 GetVideoInfo 下创建.gitignore 文件:

*.log
*.pyc
Temp/
.idea/
.idea
venv/
__pycache__/

GetVideoInfo 文件夹下还应该有 dockerfile、requirements.txt、构建与上传镜像的脚本、拉取镜像与删除旧容器启动新容器的脚本。

7、查看本地 Windows 的SSH密钥,并复制到 用户设置 -> SSH 密钥中,路径在

C:\Users\Ezrealer\.ssh\id_rsa.pub

8、在 CopyrightModule\GetVideoInfo 路径下执行如下命令:

git init
git remote add origin git@external_url:casia_copyright/GetVideoInfo.git
git add .
git commit -m "Initial commit"
git push -u origin master

执行后,群组 CasiaCopyrightTeam 下会多出一个名为 GetVideoInfo 的代码仓库;

9、接下来,基于这个代码仓库,我们介绍当这个仓库中的代码发生变更时,如何自动更新镜像仓库的镜像,并重启容器使之生效。

10、插个广告:优化 gitlab 配置,减少占用内存和CPU

参考:

11、gitlab 常用命令

gitlab-ctl reconfigure                           
gitlab-ctl start                                  
gitlab-ctl stop                                
gitlab-ctl restart                               
gitlab-ctl status                                 
vim /etc/gitlab/gitlab.rb                         
gitlab-rake gitlab:check SANITIZE=true --trace    # 检查gitlab
gitlab-ctl tail                                   # 查看日志
gitlab-ctl tail nginx/gitlab_access.log

12、gitlab 自带一些服务,比如 Prometheus 、Nginx 等,如果要安装这些服务,可能会产生端口冲突,因此需要在安装前配置 /etc/gitlab/gitlab.rb ,把对应服务的 enable 设置为 false。

Jenkins 篇


安装与配置 jenkins

1、安装 jenkins (jenkins-2.277.1-1.1.noarch )

参考:https://pkg.jenkins.io/redhat-stable/

sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
yum install jenkins

rpm -ql jenkins # 查看 jenkins 的安装路径

/etc/init.d/jenkins
/etc/logrotate.d/jenkins
/etc/sysconfig/jenkins
/usr/lib/jenkins
/usr/lib/jenkins/jenkins.war
/usr/sbin/rcjenkins
/var/cache/jenkins
/var/lib/jenkins
/var/log/jenkins

2、安装 JAVA

cd /usr/software
# wget https://repo.huaweicloud.com/java/jdk/13+33/jdk-13_linux-x64_bin.tar.gz
wget https://repo.huaweicloud.com/java/jdk/8u151-b12/jdk-8u151-linux-x64.tar.gz
tar -zxvf jdk-8u151-linux-x64.tar.gz -C /usr/local/
cd /usr/local
mv jdk1.8.0_151 jdk1.8
vim /etc/profile

export JAVA_HOME=/usr/local/jdk1.8
CLASSPATH=$JAVA_HOME/lib/
PATH=$PATH:$JAVA_HOME/bin
export PATH JAVA_HOME CLASSPATH
# 保存
source /etc/profile
java -version

配置 jenkins

1、修改 jenkins 的配置

vim /etc/sysconfig/jenkins

# 修改配置
JENKINS_PORT="11818"

# 保存

2、配置 java 路径

vim /etc/init.d/jenkins

# 修改配置,candidates 下新增一行,java 的安装路径,可以通过 which java 查看 

candidates=“
/usr/local/jdk1.8/bin/java
”
# 保存

初始化 jenkins

1、启动 jenkins

chkconfig jenkins on 
systemctl start jenkins
systemctl daemon-reload
systemctl status jenkins

2、根据 IP + port 访问,并选择安装推荐插件,然后 创建一个账户 Ezrealer

3、修改初始密码

cd /var/lib/jenkins/users/Ezrealer_xxx
vim config.xml

# <passwordHash> 内改为如下值,对应的密码是123456 

#jbcrypt:$2a$10$MiIVR0rr/UhQBqT.bBq0QehTiQVqgNpUGyWW2nJObaVAM/2xSQdSq

# 保存退出

4、安装常用插件

安装方法:jenkins 主页 -> 系统管理 -> 插件管理 -> 搜索 插件名称 -> 点击左下角 Install without restart

1、Publish over SSH # 构建时通过ssh在本机或远程执行shell命令

2、Credentials Binding # 添加用户名密码、证书、密钥等用于登录服务器的凭证

3、GitLab Plugin  # gitlab 的插件

4、Generic Webhook Trigger Plugin # 配置 webhook 用的插件

5、在 Jenkins 中配置 Git 路径

系统管理 -> 全局工具配置 -> Git 

输入 git 的名称 以及 git 的路径 (通过 which git 查看)

6、为 Publish over SSH 添加 服务器登录信息

可以添加多台服务器,在构建是做部署的时候就可以选择这些服务器进行文件传输或shell命令执行

系统管理 -> 系统配置 -> 下拉到最下面 -> Publish over SSH -> SSH Servers ->

Name 是自己起的服务器名称,一般用IP,

Hostname 是服务器IP,

Username是服务器用户名,

Remote Directory 是要部署的路径,以后在构建时或构建后选择文件部署路径都是基于这里设置的路径的

勾选 Use password authentication, or use a different key ,并填写服务器密码

Port是 ssh 登录的端口

Timeout (ms) 是连接超时时间

填写后,点击 test,出现 success 后保存

新建任务

参考:

1、新建任务 -> 构建一个自由风格的软件项目 -> 输入任务名称(GetVideoInfo) -> 确定

2、输入描述:视频条目的信息补充,包括 标题、作者、发布时间、时长、view、like 等

3、勾选 丢弃旧的构建

4、源码管理选择 git,输入 Repository URL(从 gitlab 的 HTTP 克隆中复制),并添加 Credentials,选择 全局凭据、Username with password,填写 仓库所在的 gitlab 的用户名,密码,再写个描述,然后点击添加,再在Credentials 中选择刚添加的凭据

5、构建触发器中 选择 Generic Webhook Trigge

6、构建环境选择 Add timestamps to the Console Output

7、构建中选择增加构建步骤 , 选择 执行shell ,并写入命令 bash build_and_push_image.sh

8、构建后操作选择增加构建后操作步骤 ,选择 Send build artifacts over SSH:

Source files 填写 pull_image_and_start_docker.sh(这里的路径是基于 jenkins_home/workspace/该任务名称/ 路径下的)

Remote directory 填写 /get_video_info (这里的路径是基于 Publish over SSH 中配置的 Remote Directory)

Exec command 填写 bash /usr/jenkins_workspace/get_video_info/pull_image_and_start_docker.sh (这里的路径是基于当前登录用户的目录,因此路径要写绝对路径)

9、保存

10、如果要部署到多台机器,可以在第8步多次点击 增加构建后操作步骤,也可以使用 docker swarm,然后写脚本做部署

10、附录1:构建镜像并推送到镜像仓库的脚本

11、附录2:远程服务器执行拉取镜像、删除容器并启动新容器的脚本

配置 webhook

1、配置用户的 API Token 和 Security

jenkins 主页 -> 用户列表 -> 点击当前用户ID -> 设置 -> API Token -> 添加新 Token ->

输入 Token 名称 -> 点击生成 -> 拷贝并保存好生成的 Token -> 保存

2、配置 Gitlab 的 WebHooks

Gitlab 主页 -> 群组 -> 进入 GetVideoInfo 代码仓库 -> 设置 -> webhooks ->

输入网址:http://<User ID>:<API Token>@<Jenkins IP地址>:端口/generic-webhook-trigger/invoke ->
add webhook -> 报错: Urlis blocked: Requests to localhost are not allowed ->

# 解决 Urlis blocked: Requests to localhost are not allowed
管理中心 -> 网络 -> 外发请求 -> 勾选 允许Webhook和服务对本地网络的请求 -> save changes

然后再重试 add webhook 即可成功!

测试代码管理、镜像自动更新与推送、远端服务器镜像自动拉取与容器自动更新

在本地PC git push 代码到 gitlab,然后在 jenkins 查看是否有更新

17、同步代码后可以执行构建与推送镜像 也可以执行18

在 jenkins 任务的配置中,既可以 通过 选择构建环境中的 Send files or execute commands over SSH after the build runs ,也可以配置 构建后操作,这里建议配置 构建后操作,因为 前者在构建失败后也会触发,不合理

1、编写构建镜像的 shell 脚本
build_image.sh

#! /bin/bash

echo "开始构建GetVideoInfo镜像..."
cd /var/lib/jenkins/workspace/GetVideoInfo
docker build -t get_video_info .
echo "构建GetVideoInfo镜像成功!"

2、在 构建中勾选 执行 shell,并写入 sudo bash build_image.sh

3、本地 PC 执行 git push ,jenkins 在执行shell脚本时报错(sudo: no tty present and no askpass program specified)

# 查看 jenkins 执行用户
cat /etc/sysconfig/jenkins

# 修改
JENKINS_USER="root"
JENKINS_GROUP="root"
sudo systemctl restart jenkins

4、继续本地 PC 执行 git push

5、执行后构建-> 点击 增加构建后操作步骤 -> send build artifacts over SSH -> 

Name选择一个已添加好的机器 
source files 就是准备上传的文件,该文件是相对于这个项目的workspace目录,也就是$JENKINS_HOME/workspace/xxxx/ 每个项目都会在build时候自动创建worksapce

 比如我要上传

$JENKINS_HOME/workspace/xxxx/target/class/helloworld1.java

$JENKINS_HOME/workspace/xxxx/target/class/helloworld2.java 

那么我们就可以设置如下参数

source files=target/class/*.java

remove prefix = target (remove prefix必须是source files中指定的目录,如果不写,那就是把这个目录层级都上传,如果写target,就传class目录层级,如果写target/class 就传*.java文件)

remote diretory = rd (remote diretory就是相对于系统配置中对服务器配置中的remote diretory来说的,比如在服务器配置中的remote diretory如果是空,那应该就是家目录,如果不是空,假如是/usr/local)

那这样上传过去,文件存在服务器的目录是   /usr/local/rd/class/*.java

也就是   服务器配置里的remote diretory[/usr/local]+这里配置的remote diretory[rd]+source files去掉remove prefix的目录剩下的部分[class/*.java]
# 定义变量
API_NAME="demo"
API_VERSION="0.0.1"
API_PORT=58080
IMAGE_NAME="127.0.0.1:5000/billjiang/$API_NAME:$BUILD_NUMBER"
CONTAINER_NAME=$API_NAME-$API_VERSION
 
# 进入target 目录复制Dockerfile 文件
cd $WORKSPACE/target
cp classes/Dockerfile .
 
#构建docker 镜像
docker build -t $IMAGE_NAME .
 
#推送docker镜像
docker push $IMAGE_NAME
 
#删除同名docker容器
cid=$(docker ps | grep "$CONTAINER_NAME" | awk '{print $1}')
if [ "$cid" != "" ]; then
   docker rm -f $cid
fi
 
#启动docker 容器
docker run -d -p $API_PORT:8080 --name $CONTAINER_NAME $IMAGE_NAME
 
#删除 Dockerfile 文件
rm -f Dockerfile

18、也可以直接把新的代码部署到指定服务器

https://www.bilibili.com/video/BV17y4y1v7Qy?p=9&spm_id_from=pageDriver

19、jenkins 常用命令

# 重启 jenkins
ip:port/restart

基于 k8s + habor + gitlab + jenkins

持续集成:Jenkins VS gitlab-ci

https://www.jianshu.com/p/acec7866891d

DevOps 相关

Docker环境部署Prometheus+Grafana监控系统:https://mp.weixin.qq.com/s/DWnKNkoVgcf1pZeo4o5u8g
k8s部署 redis 高可用集群:https://mp.weixin.qq.com/s/xklgkK8ZkUYzFLR_CGrhSA
年薪50W运维岗位核心技能解析:https://mp.weixin.qq.com/s/LOnZQejCy0O9wKKwyFByLQ
k8s集群网络:https://mp.weixin.qq.com/s/JKBcU6cHFUhTXjaLbBVpAA
k8s 部署应用的流程:https://mp.weixin.qq.com/s/DNZ6w2vO-UhTtSK5UF2IAw

基于Jenkins,docker实现自动化部署(持续交互):https://www.jianshu.com/p/358bfb64e3a6

参考