美文网首页k8s&docker
自定义脚本实现K8S微服务更新

自定义脚本实现K8S微服务更新

作者: 阿乐_822e | 来源:发表于2020-11-26 11:29 被阅读0次

    项目背景:公司生产环境,两组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:在打包镜像的压缩文件之前,要注意有可能开发与实际生产环境中的镜像名称有所不同,如果有差异一定要先打好生产环境的标签,再打包压缩镜像文件。

    相关文章

      网友评论

        本文标题:自定义脚本实现K8S微服务更新

        本文链接:https://www.haomeiwen.com/subject/rejaiktx.html