自定义脚本实现K8S微服务更新
2020-11-26 本文已影响0人
阿乐_822e
项目背景:公司生产环境,两组De-Exsi服务器,各搭配一台磁盘阵列,所有的微服务要各居其一,以实现高可用。先配置2台k8s-master与k8s-node服务器,每组服务各一master一node。然后,因为资源有限,无法配置私有仓库与jekenis服务器。这样,但要更新微服务器时,就要手工拷贝镜像再load、update了,比较繁琐,还容易出错,因此,写了一个更新脚本来实现自动化。
服务器:Manager00:192.168.0.100(k8s-master)
DC-App00/01:192.168.0.104~105 (2台k8s-node)
部署文件准备:
- 在Manager00机器上新建/root/k8s-deploy/myapp目录,再新建与应用所在namespace同名的子目录,将所有微服务部署的yml文件放置在这里;
- yml文件名要与文件中定义的应用的名称(metadata.name)相同,另外,spec.template.spec.containers.image字段,即镜像名称采用metadata.name:版本号形式(通常使用日期时间字段)
$ cd /root/k8s-deploy/myapp/dc-stg-ns
$ cat mytest-dc-service-biz-event.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: mytest-dc-service-biz-event
name: mytest-dc-service-biz-event
namespace: dc-stg-ns
spec:
template:
spec:
containers:
image: 'mytest-dc-service-biz-event:202011131847'
imagePullPolicy: Always
name: mytest-dc-service-biz-event
ports:
- containerPort: 8080
protocol: TCP
......
配置ssh免密登录
在Manager00机器的/root/k8s-deploy/myapp目录下,放置了更新脚本update.sh
要实现自动更新,首先要配置Manager00机器到两个工作负载服务器DC-App00/01的免密登录
# 登录到Manager00
$ ssh-keygen # 生成登录秘钥,一路狂按回车
$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.0.104 # copy公钥到DC-App00
$ ssh 'root@192.168.0.104' # 测试一下免密登录,成功
$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.0.105 # copy公钥到DC-App01
$ ssh 'root@192.168.0.105' # 测试一下免密登录,成功
编写更新脚本
$ cd /root/k8s-deploy/myapp
$ vi updateapp.sh
#!/bin/bash
# 参数说明: namespace app.version(镜像压缩文件名称)
## 检查参数完整性
clear
if [ x"$1" = x ] || [ "$1" = "-h" ]; then
# echo -e "未传入命名空间参数!\n程序退出,未作任何改变!"
echo "----------XX系统kubernetes镜像更新程序----------------"
echo "用法:./updateapp.sh namespace app.version"
echo "namespace:命名空间名称"
echo "app.version:新的镜像压缩文件名称(同时,app也是微服务名,version是最新的版本号)"
echo "此文件'app.version'请提前放置于/root/k8s-deploy/myapp/目录下 "
exit 1
fi
if [ x"$2" = x ]; then
echo -e "未传入镜像文件参数!\n输入./updateapp.sh -h查看命令格式.\n程序退出,未作任何改变!"
exit 1
fi
#判断镜像压缩文件是否存在
imagefile="/root/k8s-deploy/myapp/"$2
if [ ! -f $imagefile ]; then
echo -e "指定的镜像压缩文件'$imagefile'不存在!\n程序退出,未作任何改变!"
exit
fi
echo "OK!已发现镜像压缩包文件: "$imagefile
#判断部署文件是否存在
apppath="/root/k8s-deploy/myapp/"$1"/"
imagename=${2%%.*} # 取点号左边部分
version=${2##*.} # 取点号右边部分
ymlfile=$apppath$imagename".yml"
if [ ! -f $ymlfile ]; then
echo -e "指定的部署文件'$ymlfile'不存在!\n程序退出,未作任何改变!"
exit
fi
echo "OK!已发现部署文件: "$ymlfile
# 判断目标机器是否可到达
for a in {104..105}
do
if ping -c1 -w1 192.168.0.$a &>/dev/null;then
echo "OK!目标机器 192.168.0.$a 可到达."
else
echo -e "请注意!目标机器 192.168.0.$a 不可到达!\n程序退出,未作任何改变!"
exit
fi
done
#传送压缩包文件到目标节点
for a in {104..105}
do
if scp $imagefile 192.168.0.$a:/root;then
echo "OK!镜像文件已传送至目标机器:192.168.0.$a"
else
echo -e "请注意!镜像文件传送至目标机器 192.168.0.$a 失败!\n程序退出,未作任何改变!"
exit
fi
done
# 在目标机器上装载镜像
echo "现在开始在目标机器上装载镜像,请稍候......"
for a in {104..105}
do
if ssh 192.168.0.$a docker load -i /root/$2;then
echo "OK!目标机器192.168.0.$a装载镜像成功!"
else
echo -e "请注意!目标机器192.168.0.$a装载镜像失败!\n程序将在删除镜像文件后退出,未作任何改变!"
# 删除镜像文件
ssh 192.168.0.$a rm -rf /root/$2
exit
fi
done
# 修改deployment文件
image=`grep image: $ymlfile`
useVersion=${image##*:}
# 更改之前先备份
/bin/cp -rf $ymlfile $ymlfile-bak
if sed -i "s/$useVersion/$version/" $ymlfile;then
echo "OK!成功更改镜像部署文件版本号!"
else
echo -e "请注意!更改镜像部署文件版本号失败!\n程序退出,未作任何改变!"
exit
fi
# 更新目标机器镜像
if kubectl apply -f $ymlfile;then
echo "OK!目标机器镜像已更新!"
else
echo -e "请注意!目标机器镜像更新失败!\n程序将在恢复部署文件后退出,未作任何改变!"
# 恢复yml文件......
mv -rf $ymlfile-bak $ymlfile
exit
fi
# 清理中间文件
rm -rf $imagefile
#echo "现在清理目标机器中间文件......"
for a in {104..105}
do
if ssh 192.168.0.$a rm -rf /root/$2 $ymlfile-bak;then
echo "OK!目标机器192.168.0.$a删除镜像文件成功!"
else
echo -e "请注意!目标机器192.168.0.$a删除镜像文件失败!\n请自行前往检查!"
fi
done
echo "OK!更新工作完成.......byebye"
更新过程
- 程序员先在开发环境中测试代码正常通过,生成新版本的镜像,并使用docker save命令生成压缩包文件,注意文件的命名格式为:app-name.version,如:mytest-dc-service-biz-event.202011261847 ;
- 将压缩文件上传到DC-Manager00机器的/root/k8s-deploy/myapp/目录下;
- 登录到DC-Manager00并切换至/root/k8s-deploy/myapp/目录下;
$ ./updateapp.sh namespace app-name.version
# 如: ./updateapp.sh dc-stg-ns mytest-dc-service-biz-event.202011261847
- 脚本会自动把这个包文件传送到DC-App00/01两台机,并load为docker的镜像,再更改部署脚本中的镜像包标签,并应用更新过的部署文件,实现滚动更新,当更新成功后,会自动清除过程中的中间文件.
PS:在打包镜像的压缩文件之前,要注意有可能开发与实际生产环境中的镜像名称有所不同,如果有差异一定要先打好生产环境的标签,再打包压缩镜像文件。