背 景

很多用户在使用Jenkins做项目发布的时候都没有结合监控系统一块去做,如果同时还没有消息通知系统的话发布是否成功无法知晓。出现发布事故的概率大大的增加。

痛 点

运维人员一般会被上级要求每次发布要确认是否发布成功。服务器数量多的话会要求分批发布,如何验证发布成功成为很多运维人员的挑战,手动验证方式又不够及时。

收 益

其实Jenkins除了发布也能做接口的健康检查,这样每次发布完循环多次去调用接口做对应到各个应用的健康检查并细化到每个主机的应用端口。哪个主机哪个端口出问题就及时报警。用户可以迅速的知道哪个应用对应的哪个主机出了问题。如果要做出现故障后重启或回滚也会方便很多。保证了业务上线的稳定性。

jenkins上的job配置

选择构建自由风格的项目

配 置

  • Description

    • 所有服务健康检测

  • 设置每两小时运行一次H */2 * * *原因是防止进程僵死和jenkins内存泄漏

  • 构建 build

    • shell执行

OLD_BUILD_ID=$BUILD_ID
#因为脚本monitor-all-services.sh是会调用另外一个脚本monitor-service-status.sh跑的,如果monitor-all-services.sh循环跑完了,那么monitor-service-status.sh也就不跑了,只有把build_id改成一个不存在的值让服务kill不了,这样就可以继续后台跑
BUILD_ID=dontKillMe
${JENKINS_SHELL_PATH}/ops/monitor-all-services.sh
#改回原来的BUILD_ID值
BUILD_ID=$OLD_BUILD_ID

  • 构建后操作 Post-build Actions

    • jenkins URL 默认自动输入

    • 钉钉access token 使用钉钉机器人的token

    • 在构建失败时通知 勾选

    • 钉钉通知器配置

用到的脚本

$ cat monitor-all-services.sh
#! /bin/bash
#定义jenkins_shell路径
if [[ -z ${JENKINS_SHELL_PATH} ]];thenJENKINS_SHELL_PATH="/opt/app/jenkins/scripts/"
fi#杀掉旧的还在执行的监控脚本
kill $(ps aux|grep monitor-se|awk '{print $2}')
sleep 1#映射文件路径
mapping_path=${JENKINS_SHELL_PATH}/mapping/
#定义当前脚本执行的路径
basepath=$(cd `dirname $0`; pwd)
cd ${basepath}
cd ${mapping_path}
#用ls命令来显示当前目录下的文件并进行for循环遍历
mapping_files=$(ls)
for mapping_file in ${mapping_files}
do#定义应用名称app_name=${mapping_file}#使用文件内写的应用名称app_real_name=$(cat ${mapping_file} | awk '{print $1}')#定义部署类型app_deploy_type=$(cat ${mapping_file} | awk '{print $2}')#定义要检查的uricheck_uri=$(cat ${mapping_file} | awk '{print $3}')ps aux | grep "monitor-service-status.sh ${app_name} " | grep -v 'grep'#如果ps返回不等于0说明没有这个监控,那么执行如下操作if [[ $? -ne 0 ]];then#如果检查的uri不为空if [[ ! -z ${check_uri} ]];thenecho ${app_name} 开启检测date=`date +%Y%m%d-%H`#nohup ${basepath}/monitor-service-status.sh ${app_name} ${app_real_name} ${app_deploy_type} ${check_uri} >> "/tmp/monitor-"${app_name}-${date} 2>&1 &#后台执行监控程序,日期参数${date}已经不用nohup ${basepath}/monitor-service-status.sh ${app_name} ${app_real_name} ${app_deploy_type} ${check_uri} >> /dev/null 2>&1 &fifi
done
$ cat monitor-service-status.sh
#! /bin/bash
function getConsul() {#取余数mod=$(($j % 10))#如果余数等于1if [[ ${mod} == 1 ]];thenk=1#循环9次for (( i=1;i<10;i++))dosleep 1#获取consul所有的节点信息,因为服务器的ip和端口信息是存在consul上的,python -m json.tool显示json格式,jq -r '.[] | .Key'选取Key这列的值,grep -v '\/d-\|\/t-\|\/b-' 去掉dev/test/beta环境,公司当前d-开头的代表开发环境,t-开头的代表测试环境,b-开头的代表预发环境app_info=$(curl --connect-timeout ${timeout} -m ${timeout} -s -X GET "${consul_url}?recurse" | python -m json.tool  | jq -r '.[] | .Key' | grep ${app_name}/ | grep upstream  |grep -v '\/d-\|\/t-\|\/b-')# 如果拿到信息keys信息从app_info变量里拿if [[ $? -eq 0 ]];thenkeys=$(echo "${app_info}")#grep -P是把匹配到的标红,o是把匹配到的取出来app_hosts=$(echo ${keys} | grep -Po [0-9.]+:[0-9]+)echo $app_hosts > ${temp_consul_path}${app_name}i=10else#k值+1k=$(($k+1))i=1fi# 如果k=10,就到文件里去取,consul有时会挂掉,挂掉就拿不到了if [[ ${k} -eq 10 ]];thenapp_hosts=$(cat ${temp_consul_path}${app_name})i=10fidoneelse#如果余数不等于1也是到文件里去取app_hosts=$(cat ${temp_consul_path}${app_name})fi
}#查看url状态
function checkUrlStatus() {http_code=$(curl --connect-timeout ${timeout} -m ${timeout} -o /dev/null -s -w %{http_code} ${check_url})if [[ ${http_code} != 200 ]];thensleep 2echo 'second check'http_code=$(curl --connect-timeout ${timeout} -m ${timeout} -o /dev/null -s -w %{http_code} ${check_url})fi
}#查看uri状态
function checkUriStatus() {for app_host in ${app_hosts}do#获取ip和ssh端口app_host_ip=$(echo ${app_host} | awk -F ':' '{print $1}')ssh_port=8888if [[ ${app_host_ip} =~ "192.168." ]];thenssh_port=22fi#定义check_urlcheck_url="http://${app_host}${check_uri}"checkUrlStatus#如果检查url不为200if [[ ${http_code} != "200" ]];thenif [[ ${app_deploy_type} == "jetty" || ${app_deploy_type} == "springboot" || ${app_deploy_type} == "go" || ${app_deploy_type} == "tomcat" ]];thendesc=${check_url}" http_code is "${http_code}# 获取主机名,这是自己做的api接口通过ip可以获取主机名,此处不做详细介绍hostname=$(curl -s http://jenkins.xxx.com:7000/getInstanceName/${app_host_ip})# 如果主机名不是华为云的服务器那么直接登录服务器拿主机名,公司主机名定义规则为云厂商-地域-部门-应用组-使用语言-编号,例如huawei-sh-crm-sp-java-001if [[ ${hostname} != "huawei-" ]];thenhostname=$(ssh -p ${ssh_port} -n ${remote_user}@${app_host_ip} "hostname")fi# 拿部门信息dpt=$(echo ${hostname} | awk -F '-' '{print $3}')# 拿环境信息,环境信息是放在用户家目录下.bashrc的app_env变量里的app_env=$(ssh -p ${ssh_port} -n ${remote_user}@${app_host_ip} "cat ~/.bashrc | grep app_env | grep -v \#" | awk -F '=' '{print $2}' | grep -Po [a-z-]+)# 获取最终的环境信息,get-env.sh脚本在下面env=$(bash ${basepath}/get-env.sh ${app_env})# prometheus中自定义value设置1是错误,0是正常value=1#把监控信息push到prometheus上,注意此处的PUSHGATEWAY_BASE大写变量是配置在jenkins的全局变量中的,例如值为192.168.0.200echo 'ops_auto_restart_application{dpt="'${dpt}'",application="'${app_real_name}'",deploy_type="'${app_deploy_type}'",hostname="'${hostname}'",env="'${env}'",desc="'${desc}'"} '"${value}"'' | curl --data-binary @- http://${PUSHGATEWAY_BASE}:9091/metrics/job/"monitor-"${app_name}"-"${app_host_ip}# 如果出问题就重启服务source ~/.bash_profile &&  ssh -p ${ssh_port} -n ${remote_user}@${app_host_ip} "/opt/bin/${app_deploy_type} restart ${app_real_name}"# 重启好服务后继续检查url状态checkUrlStatusfifi#定义一个秒数变量second=$(date "+%S")# 如果状态3小于404,那么值为0if [[ ${http_code} -lt "404" ]];thenvalue=0echo `date`#把正常信息推送到prometheussleep 15 && echo 'ops_auto_restart_application '"${value}"'' | curl --data-binary @- http://${PUSHGATEWAY_BASE}:9091/metrics/job/"monitor-"${app_name}"-"${app_host_ip}fidone
}#定义consul临时目录
temp_consul_path="/tmp/consul/"
if [[ ! -d ${temp_consul_path} ]];thenmkdir ${temp_consul_path}
fi
# 超时时间
timeout=5#app_name用变量传进去,没传就退出
app_name=$1
if [[ -z ${app_name} ]];thenecho no app_nameexit 1
fiapp_real_name=$2
app_group=$(echo ${app_real_name} | awk -F '/' '{print $1}')
app_deploy_type=$3
check_uri=$4
remote_user="dev"#jenkins_shell路径定义
if [[ -z ${JENKINS_SHELL_PATH} ]];thenJENKINS_SHELL_PATH="/opt/app/jenkins/scripts/"
fi
#consul地址
consul_url="http://consul.xxx.com:8500/v1/kv/upstreams/"
#映射的文件路径
mapping_path=${JENKINS_SHELL_PATH}/mapping/
#监控检查的日志路径
health_log_path="/tmp/health/"
health_log_file=${health_log_path}${app_name}
mkdir -p ${health_log_path}
basepath=$(cd `dirname $0`; pwd)
# 设定备份代码的路径
if [[ -z ${LOCAL_BACKUP_PATH} ]];thenLOCAL_BACKUP_PATH="/opt/code-backup"
fi
# 设置锁定目录
lock_dir=${LOCAL_BACKUP_PATH}/lock
mkdir -p ${lock_dir}
cd ${basepath}
j=0
while true
do
{#如果存在锁定目录则说明在发布不检测if_exist=$(ls ${lock_dir} | grep ${app_name}"-" | grep "beta\|online")if [[ ${if_exist} ]];thenecho `date` "发布代码中,不检测!"sleep 10else#否则把j+1j=$(($j+1))#获取consul信息getConsul#查看uricheckUriStatussleep 1fi
}
done
#用于打印环境信息
$ cat get-env.sh
#!/bin/bash
app_env=$1
if [[ ${app_env} = "d-" ]];thenecho "dev"
elif [[ ${app_env} = "t-" ]];thenecho "test"
elif [[ ${app_env} = "b-" ]];thenecho "beta"
elif [[ ${app_env} = "" ]];thenecho "online"
elif [[ ${app_env} = "hd-" ]];thenecho "online"
elif [[ ${app_env} = "hb-" ]];thenecho "online"
elseecho ${app_env}
fi

mapping文件

在/opt/app/jenkins/scripts/mapping下示例:

$ cat crm-lmsweb
crm-lmsweb tomcat /health/HealthCheck/health

依次是组名/项目名 部署类型 健康检查接口

自动添加mapping文件流程

  • 在function-common.sh中写映射函数

# 如果环境是线上的,并且部署类型是如下的,输出仓库名称,不属类型,要检查的uri到映射对象文件,${mapping_file}在common.sh,${CHECK_URI}参数通过jenkins页面设置文本参数配置获得,APP_DEPLOY_TYPE变量也是jenkins 发布项目job上配置的部署方式参数
function mappingInfo() {if [[ ${app_env} == "online" ]];thenif [[ ${APP_DEPLOY_TYPE} == "python" || ${APP_DEPLOY_TYPE} == "springboot" || ${APP_DEPLOY_TYPE} == "jetty" || ${APP_DEPLOY_TYPE} == "go" || ${APP_DEPLOY_TYPE} == "tomcat" ]];thenecho ${job_name} ${APP_DEPLOY_TYPE} ${CHECK_URI} > ${mapping_file} # 映射关系表,监控使用fifi
}
  • common.sh中调用,任何文件调用了common.sh就会调用执行它

#使用jenkins自带的环境变量${JOB_NAME获取信息}
job_name=$(echo ${JOB_NAME} | awk -F '/' '{print $1"/"$2}')
# lms-dev/S_cwsp/master => lms-dev/S_cwsp
remote_hosts=${job_name//\//-} # ansible hosts中的组名
mapping_file=${JENKINS_SHELL_PATH}/mapping/${remote_hosts}
source ${JENKINS_SHELL_PATH}/function-common.sh
mappingInfo # mapping信息

利用jenkins做应用健康检查相关推荐

  1. Java利用jenkins做项目的自动化部署

    本地的jekins密码 2722e8ea873b4cf08884c22dff732bab 这篇文章主要介绍了Java利用jenkins做项目的自动化部署,小编觉得挺不错的,现在分享给大家,也给大家做个 ...

  2. 【Consul】Consul实践指导-健康检查(Checks)

    Consul的一个基本功能是提供系统级和应用级健康检查.如果健康检查与某个服务关联,则称为是应用级的:如果不予服务关联,则监控整个节点的健康. check定义在配置文件中,或运行时通过HTTP接口添加 ...

  3. consul 服务健康检查

    文章目录 简介 check方法 Script check(Script+ Interval) 基于HTTP请求 基于tcp请求 基于grpc请求 Docker 简介 服务注册 - 服务进程在注册中心注 ...

  4. k8s探针检测php,k8s探针实现grpc健康检查

    这篇文章教大家如何利用k8s实现grpc健康检查 一. 配置Liveness和Readiness探针 kubelet 使用 liveness probe(存活探针)来确定何时重启容器.例如,当应用程序 ...

  5. 负载均衡中的服务器健康检查

    为了确保应用的高可用性,在做服务器负载均衡时,负载均衡器对服务器做健康检查是必须的.健康检查可以应用到服务器.服务器端口.服务组(Service-group)3个层面,之间是否有关联?应当如何应用?下 ...

  6. 20210720-springboot项目使用k8s部署,服务启动成功,但是健康检查失败

    问题一:提示/health 404错误 问题描述 Jenkins上配置了流水线脚本,其中配置了健康检查的路径(直接抄别人项目的配置) 此时虽然项目启动成功,但是由于健康检查提示404,导致项目一直重启 ...

  7. Kubernetes健康检查如何做?官方推荐教程

    编者语:这是 Google 开发者布道师 Sandeep Dinesh[1]的视频[2]和博客系列 "如何充分利用 Kubernetes 环境" 的第三部分. 分布式系统管理比较困 ...

  8. 运维企业专题(8)LVS高可用与负载均衡后篇——LVS健康检查与高可用详解

    实验准备 1.下面的实验使用的是rhel6系列(rhel6.5)的虚拟机,因此你需要有对应的镜像和yum源 2.准备三台虚拟机,为了区分主机名与IP分别为 server1 172.25.6.1 ser ...

  9. nginx限流健康检查

    Nginx原生限流模块: ngx_http_limit_conn_module模块 根据前端请求域名或ip生成一个key,对于每个key对应的网络连接数进行限制. 配置如下: http模块 serve ...

最新文章

  1. FusionCharts下载地址汇总及更新介绍
  2. HDU2035人见人爱A^B(快速幂求余)
  3. 和ur的区别_UR机械臂simscape正逆解仿真
  4. java 学习笔记2022.1.26
  5. Python基础语法-三种函数特殊形参定义以及使用方式
  6. 关于Istio 1.1,你所不知道的细节
  7. python学习——基础(八)
  8. 基于JAVA+SpringMVC+MYSQL的在线英语精品课程视频教学平台
  9. 关于xendesktop外部SQL数据库连接设置的问题
  10. 店宝宝:电商直播被“敲响警钟”了
  11. FFMPEG录屏(12)---- DXGI 捕获桌面
  12. u盘为什么要安全弹出?丢失的数据怎么恢复?
  13. 深度学习论文: An Improved One millisecond Mobile Backbone及其PyTorch实现
  14. CPT203 软件工程开发 笔记
  15. P处理的中有大量判断条件是的sql写法
  16. 卫星影像领域的深度学习数据和模型项目
  17. 每一次人生的最低点便是最好的修炼阶段,只有坚持过好最低点,才能挑战更高点---致自己
  18. 行业分析报告怎么做?
  19. linux安装和配置 MariaDB (ubuntu20.04)
  20. 曾为面试官的我也有今天,面试百度Android被按地上血虐

热门文章

  1. 人员行为识别系统 TensorFlow
  2. redhat linux光盘4,技巧:把3张Redhat Linux 9的安装光盘刻录到一张DVD光盘中
  3. node安装node-pre-gyp报错的解决方案
  4. C# .NET实现手机接收短信
  5. FASTQ文件详解【转】
  6. 爬虫笔记之——selenium安装与使用(1)
  7. yolo系列之yolo v3【深度解析】——讲的挺好,原作者厉害的
  8. App地推活动的效果差?可能是地推业绩统计效率低惹的祸
  9. 6 生僻字_蔬菜中的生僻字你知道哪些?
  10. 银河麒麟系统安装失败