第1集,环境搭建
第2集,LNMP项目准备
第3集,WebHook触发mvn打包
第4集,SonarQube实现CodeReview
第5集,build image
第7集,模拟版本更新,在测试环境验证
第8集,部署到生产环境
第9集,流水线部署到测试环境
一、准备一键式部署包
目录结构如下
1.部署脚本autoinstall.sh
#!/bin/bash
#AUTHOR:anqixiang
#DATE:2020-03-23
#MODIFY:
#FUNCTION:docker-compose部署LNMP
#VERSION:V1.0
#SYSTEM:Ubuntu 16 RedHat7.2/7.4 CentOS7.2/7.4 SUSE12 SP3(启动docker-compose系统会重启)
export LC_ALL=en_US.UTF-8
[ `whoami` != "root" ] && echo "######## Please Use root Install......" && exit 71
current_dir=$(cd `dirname $0` && pwd) #当前工作目录/home/secneo/install_yyjg
data_dir=/data #数据目录/data
source ${current_dir}/function #加载工具库
######################工具函数######################
#DISCRIPTION:设置debug值且范围为1-9开启调试;step=1为出现错误被挂起;step=2为每次调用函数后都会被挂起
Alert(){
local ret_code=$?
debug=0
step=0
if [ -z "${debug}" ] || [ "${debug}" -eq 0 ];then
return
fi
if [ "${ret_code}" -ne 0 ];then
cecho 31 "Warn:$* failed return ${ret_code}" >&2
[ "${debug}" -gt 9 ] && exit "${ret_code}"
[ "${step}" -eq 1 ] && {
echo "Press [Enter] to continue" >&2;read x
}
else
cecho 96 "############ $* excute is success..."
fi
[ "${step}" -eq 2 ] && {
echo "Press [Enter] to continue" >&2;read x
}
}
######################功能函数######################
#检测系统
Detect_Os(){
Check_Os
system_flag=0 #用作系统标识,表示为ubuntu系统
if echo ${os_version} |egrep -i 'red|centos' &>/dev/null;then
system_flag=1 #表示redhat或者CentOS
elif echo ${os_version} |grep -i 'suse' &>/dev/null;then
system_flag=2 #表示SUSE系统
fi
}
#初始化系统环境
Init_System(){
echo "############ Init_System..."
umask 0022
sed -i "s/%sudo\tALL=(ALL:ALL) ALL/%sudo\tALL=(ALL:ALL) NOPASSWD:ALL/" /etc/sudoers
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
hwclock -w
if [ ${system_flag} -eq 0 ];then
ufw disable &>/dev/null #关闭防火墙
elif [ ${system_flag} -eq 1 ];then
Security_Conf_Redhat #关闭防火墙,禁用selinux
else
systemctl disable SuSEfirewall2.service
systemctl stop SuSEfirewall2.service
fi
Alert Init_System
}
#安装docker
Install_Docker(){
echo "############ Install_Docker..."
if ! which docker &>/dev/null;then
[ ! -f ${current_dir}/install_docker.sh ] && cecho 31 "install_docker.sh不存在" && exit 71
sed -i "/ExecStart/c ExecStart=/usr/bin/dockerd --graph ${data_dir}/docker_dir -H unix://var/run/docker.sock" ${current_dir}/install_docker.sh #设置doker存储路径为${data_dir}/docker
/bin/bash ${current_dir}/install_docker.sh
else
cecho 96 "docker已安装"
fi
Alert Install_Docker
}
#安装docker-compose
Install_Docker_compose(){
echo "############ Install_Docker_compose..."
[ ! -f ${current_dir}/docker-compose ] && cecho 31 "docker-compose不存在" && exit 71
chmod +x ${current_dir}/docker-compose
\cp ${current_dir}/docker-compose /usr/bin/
if ! /usr/bin/docker-compose -v;then
cecho 31 "docker-compose安装失败" && exit 71
fi
Alert Install_Docker-compose
}
#安装工具(mysql-client,lrzsz,unzip,dos2unix)
Install_Kits(){
echo "############ Install_Kits..."
if [ ${system_flag} -eq 0 ];then
dpkg -i ${current_dir}/debs/*.deb
elif [ ${system_flag} -eq 1 ];then
rpm -ivh ${current_dir}/rpms/*.rpm --nodeps --force
else
rpm -ivh ${current_dir}/rpms/*.rpm --nodeps --force
fi
Alert Install_Kits
}
#初始化数据卷
Deploy_Init_Data(){
echo "############ Deploy_Init_Data..."
[ ! -d ${data_dir}/docker ] && mkdir -pv ${data_dir}/docker
echo "tar xf ${current_dir}/init_data.tgz -C ${data_dir}/docker/......"
tar xf ${current_dir}/init_data.tgz -C ${data_dir}/docker/
Alert Deploy_Init_Date
}
#导入镜像
#如果在公司,去私有仓库pull镜像
Import_Images(){
echo "############ Import_Images..."
repository_ip=172.16.38.202
repository_port=8010
if curl http://${repository_ip}:${repository_port}/v2/_catalog &>/dev/null;then
Docker_Insecure
else
cd $(dirname ${current_dir})
[ ! -f docker_images.tgz ] && cecho 31 "docker_images.tgz不存在" && exit 71
echo "tar xvf docker_images.tgz......"
tar xvf docker_images.tgz
for i in $(ls docker_images/)
do
docker load < docker_images/${i}
done
rm -rf docker_images/
fi
Alert Import_Images
}
#启动服务
Start_Service(){
echo "############ Start_Service..."
cd ${current_dir}
sed -i "/\/data\// s#/data/#${data_dir}/#" docker-compose.yml
/usr/bin/docker-compose up -d
Alert Start_Service
}
#设置静态IP(ubuntu系统)
Config_Ip(){
echo "############ Config_Ip..."
if [ ${system_flag} -eq 0 ];then
CONFIG_IP_UBUNTU
elif [ ${system_flag} -eq 1 ];then
CONFIG_IP_REDHAT
else
CONFIG_IP_SUSE
fi
Alert Config_Ip
}
Excute_All(){
Init_System
Install_Docker
Install_Docker_compose
Install_Kits
Deploy_Init_Data
Import_Images
Start_Service
Config_Ip
cecho 96 "部署完成,访问地址:http://${IP}/wordpress"
}
#传入镜像名,修改docker-compose.yml文件,实现镜像版本的控制
Modify_Yml(){
compose_conf="${current_dir}/docker-compose.yml"
[ ! -f ${compose_conf}.bak ] && cp ${compose_conf}{,.bak}
for i in $@
do
if [ "x${i}" == "x-v" ];then
continue
fi
image_name=$(echo ${i%:*}) #提取镜像的名字
tag_name=$(echo ${i##*:}) #提取镜像的tag
case ${image_name} in
#sed -ri "/aptsource_bg_aptsource/ s#^(.{11})(.*)#\1${i}#" ${compose_conf};;
nginx-php-fpm)
sed -ri "/nginx-php-fpm/ s#^(.*)(:)(.*)#\1\2${tag_name}#" ${compose_conf};;
*)
cecho 31 "Invalid option:bash `basename $0` [-h]"
esac
done
dos2unix ${compose_conf}
}
#帮助信息
help(){
cat << EOF
optional arguments
-h: 查看帮助
-c:
system 初始化系统
docker 安装docker
compose 安装docker-compose
kit 安装基础工具
data 部署数据卷
image 导入镜像
start 启动服务
ip 配置静态IP
reset 回滚操作(删除所有数据,慎用)
-v:
172.16.38.202:8010/lnmp/nginx-php-fpm:ver1.0_20200323 #镜像名
EXAMPLE:
sudo ./autoinstall.sh -v 172.16.38.202:8010/lnmp/nginx-php-fpm:ver1.0_20200323
sudo ./autoinstall.sh #全部安装
sudo ./autoinstall.sh -c system
EOF
}
######################主函数######################
Detect_Os
if [ $# -eq 0 ];then
Excute_All
elif [ "x$1" == "x-c" -a "$#" -eq 2 ];then
case $2 in
system)
Init_System;;
docker)
Install_Docker;;
compose)
Install_Docker_compose;;
kit)
Install_Kits;;
data)
Deploy_Init_Data;;
image)
Import_Images;;
start)
Start_Service;;
ip)
Config_Ip;;
reset)
Delete_Docker && exit 0;;
*)
cecho 31 "Invalid option:sudo ./`basename $0` [-h]"
esac
elif [ "x$1" == "x-h" ];then
help
elif [ "x$1" == "x-v" -a "$#" -gt 1 ];then
Modify_Yml $@
else
help && exit 71
fi
2.function功能函数
#!/bin/bash
#AUTHOR:anqixiang
#VERSION:1.1.0
#DATE:2020-02-06
#MODIFY:
#FUNCTION:
cecho(){
echo -e "\033[$1m$2\033[0m"
}
#检测操作系统
Check_Os() {
local os_flag=false
if [ -e /etc/redhat-release ]; then
os_flag=true
os_version=$(cat /etc/redhat-release)
cecho 92 "操作系统为: ${os_version}"
fi
if [ "${os_flag}" == "false" ] && [ -e /etc/issue ]; then
if [ `grep -i 'Ubuntu' /etc/issue|wc -l` == '1' ]; then
os_flag=true
os_name=$(cat /etc/os-release |grep "^NAME" |awk -F'"' '{print $2}')
os_version="${os_name} $(cat /etc/os-release |grep "^VERSION=" |awk -F'"' '{print $2}')"
cecho 92 "操作系统为: ${os_version}"
fi
fi
if [ "${os_flag}" == "false" ] && [ -e /etc/issue ]; then
suse_flag=`cat /etc/issue | grep 'SUSE Linux Enterprise Server 12 SP3'|wc -l`
if [ "${suse_flag}" == "1" ]; then
os_flag=true
os_version="SUSE12 SP3"
cecho 92 "操作系统为: ${os_version}"
fi
fi
}
#关闭防火墙,禁用selinux(RedHat系列)
Security_Conf_Redhat(){
systemctl disable firewalld &>/dev/null
systemctl stop firewalld &>/dev/null
local selinux_mode=$(grep '^SELINUX=' /etc/selinux/config |awk -F'=' '{print $2}')
if [ ${selinux_mode} != "disabled" ];then
setenforce 0
sed -i '/^SELINUX=/c SELINUX=disabled' /etc/selinux/config
cecho 92 "selinux需重启系统才能生效"
fi
}
#配置docker信任私有仓库
Docker_Insecure(){
local user=admin
local pwd=admin
[ ! -f /etc/docker/daemon.json.bak ] && cp /etc/docker/daemon.json{,.bak}
tee /etc/docker/daemon.json << EOF
{
"insecure-registries": ["${repository_ip}:${repository_port}"]
}
EOF
systemctl restart docker
docker login http://${repository_ip}:${repository_port} -u ${user} -p ${pwd} &>/dev/null
[ "$?" -ne 0 ] && cecho 31 "docker登陆失败" && exit 71
return 0
}
#设置静态IP
CONFIG_IP_UBUNTU(){
IP=`ip addr |awk '/inet /' |sed -n '2p' |awk -F' ' '{print $2}' |awk -F'/' '{print $1}'`
MASK=`ifconfig | sed -n 2p | awk -F ':' '{print $4}'`
GATEWAY=`route | grep 'default' | awk '{print $2}'`
INNETO=` ip addr | awk -F '^2:' '{print $2}' |awk -F ':' '{print $1}' | awk NF|awk '{sub("^ *","");sub(" *$","");print}' |sed -n 1p`
INNETW=`ip addr | awk -F '^3:' '{print $2}' |awk -F ':' '{print $1}' | awk NF|awk '{sub("^ *","");sub(" *$","");print}' |sed -n 1p`
local net_name1=$(echo ${INNETO%%[0-9]*}) #截取网卡非数字部分,如eth
local net_name2=$(echo ${INNETW%%[0-9]*})
if ! egrep '\bstatic\b' /etc/network/interfaces &>/dev/null;then
cp -r /etc/network/interfaces /etc/network/interfaces-backup
cat >/etc/network/interfaces<<EOF
auto lo
iface lo inet loopback
auto $INNETO
iface $INNETO inet static
address $IP
netmask 255.255.255.0
gateway $GATEWAY
dns-nameservers 223.5.5.5
EOF
if [ ! -z $INNETW -a "${net_name2}" == "${net_name1}" ];then
cat >> /etc/network/interfaces <<EOF
auto $INNETW
iface $INNETW inet static
address 192.168.253.1
netmask 255.255.255.0
EOF
fi
/etc/init.d/networking restart
else
if [ ! -z $INNETW -a "${net_name2}" == "${net_name1}" ];then
if ! grep "$INNETW" /etc/network/interfaces &>/dev/null;then
cat >> /etc/network/interfaces <<EOF
auto $INNETW
iface $INNETW inet static
address 192.168.253.1
netmask 255.255.255.0
EOF
fi
/etc/init.d/networking restart
fi
echo "already config static IP"
fi
}
CONFIG_IP_REDHAT(){
#提取IP地址和网关
IP=`ip addr |awk '/inet /' |sed -n '2p' |awk -F' ' '{print $2}' |awk -F'/' '{print $1}'`
MASK=`ifconfig |grep 'inet '|grep -v '127.0.0.1'|awk '{print $4}'`
GATEWAY=`route -n |sed -n '3p'|awk '{print $2}'`
INNETO=`ip addr | awk -F '^2:' '{print $2}' |awk -F ':' '{print $1}' | awk NF|awk '{sub("^ *","");sub(" *$","");print}' |sed -n 1p`
INNETW=`ip addr | awk -F '^3:' '{print $2}' |awk -F ':' '{print $1}' | awk NF|awk '{sub("^ *","");sub(" *$","");print}' |sed -n 1p`
local eth_conf=/etc/sysconfig/network-scripts/ifcfg-${INNETO}
if grep "dhcp" ${eth_conf} &>/dev/null;then
[ ! -f ${eth_conf}.bak ] && cp ${eth_conf}{,.bak}
sed -i '/BOOTPROTO/ s/dhcp/static/' ${eth_conf}
sed -i "/BOOTPROTO/a GATEWAY=${GATEWAY}" ${eth_conf}
sed -i "/BOOTPROTO/a NETMASK=255.255.255.0" ${eth_conf}
sed -i "/BOOTPROTO/a IPADDR=${IP}" ${eth_conf}
boot_value=$(grep '^ONBOOT' ${eth_conf} |awk -F'"' '{print $2}')
if [ ${boot_value} != "yes" ];then
sed -i '/ONBOOT/s /no/yes/' ${eth_conf}
fi
service network restart
[ ! -f /etc/resolv.conf.bak ] && cp /etc/resolv.conf{,.bak}
echo "nameserver 223.5.5.5" > /etc/resolv.conf
else
echo "already config static IP"
fi
}
CONFIG_IP_SUSE(){
#提取IP地址和网关
IP=`ip addr |awk '/inet /' |sed -n '2p' |awk -F' ' '{print $2}' |awk -F'/' '{print $1}'`
#MASK=`ifconfig |grep 'inet '|grep -v '127.0.0.1'|awk '{print $4}'`
GATEWAY=`route -n |sed -n '3p'|awk '{print $2}'`
INNETO=`ip addr | awk -F '^2:' '{print $2}' |awk -F ':' '{print $1}' | awk NF|awk '{sub("^ *","");sub(" *$","");print}' |sed -n 1p`
INNETW=`ip addr | awk -F '^3:' '{print $2}' |awk -F ':' '{print $1}' | awk NF|awk '{sub("^ *","");sub(" *$","");print}' |sed -n 1p`
local eth_conf=/etc/sysconfig/network/ifcfg-${INNETO}
if grep "dhcp" ${eth_conf} &>/dev/null;then
[ ! -f ${eth_conf}.bak ] && cp ${eth_conf}{,.bak}
cat > ${eth_conf} << EOF
BOOTPROTO='static'
IPADDR=${IP}
NETMASK=255.255.255.0
STARTMODE='auto'
EOF
[ ! -f /etc/sysconfig/network/routes.bak ] && cp /etc/sysconfig/network/routes{,.bak}
echo "default ${GATEWAY}" > /etc/sysconfig/network/routes
service network restart
else
echo "already config static IP"
fi
}
Delete_Docker(){
cd ${current_dir}
/usr/bin/docker-compose down
docker system prune -a -f
systemctl stop docker
rm -rf ${data_dir}
[ ! -d /usr/bin.bak ] && cp -rp /usr/bin{,.bak}
rm -rf /usr/bin/docker*
rm -rf /etc/systemd/system/docker.service
}
3.安装Docker
docker-18.06.3-ce.tgz百度网盘地址:
链接:https://pan.baidu.com/s/1IYKIpqlrsjrxRlqXkpcGTQ
提取码:kmkm
install_docker.sh脚本【默认路径为/data/docker_dir】
#!/bin/bash
#setup
echo "######install docker......"
tar zxf docker-18.06.3-ce.tgz && mv docker/* /usr/bin/ && rm -rf docker/
#systemd config
cat >/etc/systemd/system/docker.service <<-EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd --graph /data/docker_dir -H unix://var/run/docker.sock
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
#start
chmod +x /etc/systemd/system/docker.service
systemctl daemon-reload && systemctl start docker && systemctl enable docker.service
#testing
docker -v && echo "######docker install success!!!"
4.debs和rpms下是一些常用包,如lrzsz、dos2unix
5.docker-compose二进制包
curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
6.README.txt
#注意事项
1.如果/分区不是最大,需要修改脚本data_dir变量的值,或者做软链接
2../autoinstall.sh -h 查看帮助
#执行脚本
./autoinstall.sh
7.docker-compose.yml和init_data.tgz从gitlab上拿
yum -y install git
git clone http://172.16.38.31/root/dev_lnmp.git
二、在Jenkins机器上准备habor_taglist.sh
脚本,获取habor仓库的镜像tag,自定义镜像版本
1.脚本内容
#!/bin/bash
Username="admin"
Passwd="admin"
HaborUrl="http://172.16.38.202:8010"
RepoName=$1
Ttoken=`curl -iksL -X GET -u ${Username}:${Passwd} ${HaborUrl}/service/token?account=${Username}\&service=harbor-registry\&scope=repository:${RepoName}:pull --insecure|grep "token" |awk -F '"' '{print $4}'`
Llist=`curl -ksL -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $Ttoken" ${HaborUrl}/v2/${RepoName}/tags/list|awk -F '[' '{print $2}'|awk -F ']' '{print $1}'|sed 's/"//g'`
echo $Llist|sed 's/,/\n/g' |sort -rn
2.拷贝到Jenkins容器里面
docker cp habor_taglist.sh jenkins:.
3.执行效果
docker exec -it jenkins bash
./habor_taglist.sh lnmp/nginx-php-fpm
三、在172.16.38.210部署Selenium
Docker+Selenium+Jenkins 实现web自动化测试
sele.py脚本内容:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
from selenium import webdriver
selenium_url = "http://172.16.38.210:4444/wd/hub" #selenium的访问地址
access_url = "http://172.16.38.165/wordpress" #测试地址
chrome_capabilities ={
"browserName": "chrome",
"version": "",
"platform": "ANY",
"javascriptEnabled": True,
}
browser = webdriver.Remote(selenium_url, desired_capabilities=chrome_capabilities)
browser.get(access_url)
result = str(browser.get_screenshot_as_base64())
#print(result)
if result[-1] != "C": #如果访问成功最后一位的值是"="号
print("访问失败")
browser.quit()
exit(1)
print("访问成功")
browser.quit()
exit(0)
四、Jenkins配置
1.添加测试机器的SSH remote hosts
2.添加Selenium机器的SSH remote hosts
添加凭据
3.安装Active Choices插件,用于参数化构建
4.创建item
Groovy Script脚本内容:"/bin/bash /habor_taglist.sh lnmp/nginx-php-fpm".execute().text.readLines()
部署命令:
cd /root/install_lnmp && ./autoinstall.sh -c reset
cd /root/dev_lnmp && git pull
\cp /root/dev_lnmp/docker-compose.yml /root/install_lnmp/
\cp /root/dev_lnmp/init_data.tgz /root/install_lnmp/
cd /root/install_lnmp/
./autoinstall.sh -v "nginx-php-fpm:${nginx}"
./autoinstall.sh
5.执行构建
6.WEB访问