1.k8s pod版本更新流程及命令行实现升级与回滚

Day9-结合Jenkins与gitlab实现代码部署与回滚、k8s结合ELK实现日志收集_回滚

 

1.1 k8s中pod版本更新策略

deployment控制器支持两种更新策略:默认为滚动更新

1.滚动更新(rolling update)
滚动更新是默认的更新策略,滚动更新是基于新版本镜像创建新版本pod,然后删除一部分旧版本pod,然后再创建新版本Pod,再删除一部分旧版本pod,直到旧版本pod删除完成,滚动更新优势是在升级过程中不会导致服务不可用,缺点是升级过程中会导致两个版本在短时间内会并存。
具体升级过程是在执行更新操作后k8s会再创建一个新版本的ReplicaSet控制器,在删除旧版本的ReplicaSet控制器下的Pod的同时会在新版本的ReplicaSet控制器下创建新的pod,直到旧版本的pod全部被删除完后再把旧版本的ReplicaSet控制器也回收掉。

在执行滚动更新的同时,为了保证服务的可用性,当前控制器内不可用的pod(pod需要拉取镜像执行创建和执行探针探测期间是不可用的)不能超出一定范围,国为需要至少保留一定数量的pod以保证服务可以被客户端正常访问,可以通过以下参数指定:#kubectl explain deployment.spec.strategy
deployment.spec.strategy.rollingUpdate.maxSurge #指定在升级期间Pod总数可以超出定义好的期望的pod数的个数或者百分比,默认为25%;如果设置为10%,假如当前是100个pod,那么升级时最多将创建110个pod,即额外有10%的pod临时会超出当前(replicas)指定的副本数限制。
deployment.spec.strategy.rollingUpdate.maxUnavailable #指定在升级期间最大不可用的pod数,可以是整数或者当前pod的百分比,默认是25%,假如当前是100个pod,那么升级时最多可用25个(25%)pod不可用,即还要75个(75%)pod是可用的。

2.重建更新(recreate)
先删除现有的pod,然后基于新版本的镜像重建,优势是同时只有一个版本在线,不会产生多版本同时在线问题,缺点是Pod删除后到Pod重建成功中间的时间会导致服务无法访问,因此较少使用。

1.2 灰度更新流程

暂停更新与恢复更新 #https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/#canary-deployment

灰度升级(即在更新过程中暂停一下)

  • 更新set image,暂停rollout pause,灰度节点验证,继续更新rollout resume,更新完成;

  • 更新set image,暂停rollout pause,遇到问题,回滚rollout undo;

1.3 命令行更新与回滚

升级到镜像的指定版本

# kubectl apply -f nginx.yaml --record=true #v1版本,--record=true为记录执行的kubectl

#镜像更新命令格式为
#kubectl set image deployment/{deployment-name} {containers-name}={image} -n {namespace}

#V2
# kubectl set image deployment/magedu-nginx-deployment magedu-nginx-container=harbor.magedu.net/magedu/nginx:1.16.1:v2 -n magedu --record

#V3
# kubectl set image deployment/magedu-nginx-deployment magedu-nginx-container=harbor.magedu.net/magedu/nginx:1.16.1:v3 -n magedu --record

  查看历史版本信息

查看历史版本信息
# kubectl rollout history deployment/magedu-nginx-deployment -n magedu deployment.extensions/magedu-nginx-deployment

  回滚到上一个版本

kubectl rollout undo deployment magedu-nginx-deployment -n magedu

  回滚到指定版本

查看当前版本号
# kubectl rollout history deployment/magedu-nginx-deployment -n magedu deployment.extensions/magedu-nginx-deployment

# kubectl rollout undo deployment magedu-nginx-deployment -n magedu --to-revision=3
deployment.apps/magedu-nginx-deployment rolled back

查看回滚后版本号展示
# kubectl rollout history deployment/magedu-nginx-deployment -n magedu deployment.extensions/magedu-nginx-deployment

  金丝雀/灰度

1.指定新镜像版本
# kubectl set image deployment magedu-tomcat-app1-deployment magedu-tomcat-app1-container=tomcat:8.5.56 -n magedu 

2.暂停更新(即灰度一部分pod)
# kubectl rollout pause deployment magedu-tomcat-app1-deployment -n magedu

3.恢复更新(即继续更新)
# kubectl rollout resume deployment magedu-tomcat-app1-deployment -n magedu

  

  2.k8s结合Jenkins与gitlab实现代码升级与回滚(持续集成与部署)

Day9-结合Jenkins与gitlab实现代码部署与回滚、k8s结合ELK实现日志收集_tomcat_02 

Day9-结合Jenkins与gitlab实现代码部署与回滚、k8s结合ELK实现日志收集_回滚_03

测试环境准备

一台Gitlab-server-172.31.5.101,4C4G;

一台Jenkins-server-172.31.5.102,4C4G;

2.1 部署Jenkins

安装包下载https://www.jenkins.io/download/

清华源下载https://mirrors.tuna.tsinghua.edu.cn/jenkins/debian-stable/jenkins_2.303.2_all.deb

root@jenkins-server:~# apt update
root@jenkins-server:~# apt install openjdk-11-jdk
root@jenkins-server:~# java -version
root@jenkins-server:~# dpkg -c jenkins_2.303.2_all.deb  #查看安装包使用的路径;
root@jenkins-server:~# dpkg -i jenkins_2.303.2_all.deb  #可能会提示需要安装依赖包daemon;
root@jenkins-server:~# apt install daemon   #会自动安装jenkins和启动jenkins;
root@jenkins-server:~# systemctl  stop jenkins  #停止jenkins,修改配置文件设置启动用户,这里使用root身份;
JAVA_ARGS="-Djava.awt.headless=true -Dhudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true"    #勾子,通过gitlab远程触发jenkins开始构建,根据需要开启CSRF;
JENKINS_USER=root
JENKINS_GROUP=root
root@jenkins-server:~# systemctl  restart  jenkins

查看登录jenkins web页面使用的secrets;

root@jenkins-server:~# cat /var/lib/jenkins/secrets/initialAdminPassword

浏览器登录http://172.31.5.102:8080安装插件,需要这台虚机可以联网,或者从其它已经安装插件机器中将插件目录下的文件拷贝过来;

Day9-结合Jenkins与gitlab实现代码部署与回滚、k8s结合ELK实现日志收集_git_04

安装插件完成后,设置jenkins管理员账号和密码,比如jenkinsadmin账户;

安装插件后,很多插件还没有加载,需要重启jenkins服务加载插件;

root@jenkins-server:~# systemctl  restart  jenkins

使用浏览器登录jenkins web页面创建简单的任务验证jenkins是否可以正常运行;

1> web页面右侧,新建任务,输入任务名称;
2> 选择构建一个自由风格的软件项目;(SCM,Source Code Management代码管理仓库,比如gitlab或svn)
3> “源码管理”,先选择“无”;
4> “构建”选择“执行shell”;
测试shell命令:echo "$USER"
保存,应用
5> 选择这个任务,选择“立即构建”,查看执行结果;
6> 在build history中查看执行结果,选择“控制台输出”

2.2 部署gitlab

根据系统版本下载相应的gitlab安装包,这里使用的ubuntu focal系统,使用gitlab-ce_14.2.5安装包;

https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu/pool/focal/main/g/gitlab-ce/gitlab-ce_14.2.5-ce.0_amd64.deb

root@gitlab-server:~# dpkg -i gitlab-ce_14.2.5-ce.0_amd64.deb 
       *.                  *.
      ***                 ***
     *****               *****
    .******             *******
    ********            ********
   ,,,,,,,,,***********,,,,,,,,,
  ,,,,,,,,,,,*********,,,,,,,,,,,
  .,,,,,,,,,,,*******,,,,,,,,,,,,
      ,,,,,,,,,*****,,,,,,,,,.
         ,,,,,,,****,,,,,,
            .,,,***,,,,
                ,*,.
  


     _______ __  __          __
    / ____(_) /_/ /   ____ _/ /_
   / / __/ / __/ /   / __ `/ __ \
  / /_/ / / /_/ /___/ /_/ / /_/ /
  \____/_/\__/_____/\__,_/_.___/
  

Thank you for installing GitLab!
GitLab was unable to detect a valid hostname for your instance.
Please configure a URL for your GitLab instance by setting `external_url`
configuration in /etc/gitlab/gitlab.rb file.
Then, you can start your GitLab instance by running the following command:
  sudo gitlab-ctl reconfigure

For a comprehensive list of configuration options please see the Omnibus GitLab readme
https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md

Help us improve the installation experience, let us know how we did with a 1 minute survey:
https://gitlab.fra1.qualtrics.com/jfe/form/SV_6kVqZANThUQ1bZb?installation=omnibus&release=14-2

root@gitlab-server:~# vi /etc/gitlab/gitlab.rb external_url 'http://172.31.5.101' root@gitlab-server:~# gitlab-ctl reconfigure root@gitlab-server:~# cat /etc/gitlab/initial_root_password

通过网页登录gitlab设置自己使用的密码;

设置web网页语言,可以设置为中文;

在左上角“菜单”--“管理员”,新建群组magedu;

新建用户usr1,创建用户后设置用户密码;

创建项目app1,添加index.html测试文件;

在client端安装git,拉取自建gitlab项目和更新代码验证;

# apt install git
# cd /opt
# git clone http://172.31.5.101/magedu/app1.git
# cd /opt/app1
# echo "666" >> index.html
# git add .
# git commit -m "v2"
# git push

2.3 实现代码部署与回滚

2.3.1 准备脚本

#!/bin/bash
#Author: ZhangShiJie
#Date: 2018-10-24
#Version: v1

#记录脚本开始执行时间
starttime=`date +'%Y-%m-%d %H:%M:%S'`

#变量
SHELL_DIR="/root/scripts"
SHELL_NAME="$0"
K8S_CONTROLLER1="172.31.7.101"
K8S_CONTROLLER2="172.31.7.102"
DATE=`date +%Y-%m-%d_%H_%M_%S`
METHOD=$1
Branch=$2


if test -z $Branch;then
  Branch=develop
fi


function Code_Clone(){
  Git_URL="git@172.31.5.101:magedu/app1.git"
  DIR_NAME=`echo ${Git_URL} |awk -F "/" '{print $2}' | awk -F "." '{print $1}'`
  DATA_DIR="/data/gitdata/magedu"
  Git_Dir="${DATA_DIR}/${DIR_NAME}"
  cd ${DATA_DIR} &&  echo "即将清空上一版本代码并获取当前分支最新代码" && sleep 1 && rm -rf ${DIR_NAME}
  echo "即将开始从分支${Branch} 获取代码" && sleep 1
  git clone -b ${Branch} ${Git_URL} 
  echo "分支${Branch} 克隆完成,即将进行代码编译!" && sleep 1
  #cd ${Git_Dir} && mvn clean package
  #echo "代码编译完成,即将开始将IP地址等信息替换为测试环境"
  #####################################################
  sleep 1
  cd ${Git_Dir}
  tar czf ${DIR_NAME}.tar.gz  ./*
}

#将打包好的压缩文件拷贝到k8s 控制端服务器
function Copy_File(){
  echo "压缩文件打包完成,即将拷贝到k8s 控制端服务器${K8S_CONTROLLER1}" && sleep 1
  scp ${Git_Dir}/${DIR_NAME}.tar.gz root@${K8S_CONTROLLER1}:/opt/k8s-data/dockerfile/web/magedu/tomcat-app1
  echo "压缩文件拷贝完成,服务器${K8S_CONTROLLER1}即将开始制作Docker 镜像!" && sleep 1
}

#到控制端执行脚本制作并上传镜像
function Make_Image(){
  echo "开始制作Docker镜像并上传到Harbor服务器" && sleep 1
  ssh root@${K8S_CONTROLLER1} "cd /opt/k8s-data/dockerfile/web/magedu/tomcat-app1 && bash build-command.sh ${DATE}"
  echo "Docker镜像制作完成并已经上传到harbor服务器" && sleep 1
}

#到控制端更新k8s yaml文件中的镜像版本号,从而保持yaml文件中的镜像版本号和k8s中版本号一致
function Update_k8s_yaml(){
  echo "即将更新k8s yaml文件中镜像版本" && sleep 1
  ssh root@${K8S_CONTROLLER1} "cd /opt/k8s-data/yaml/magedu/tomcat-app1 && sed -i 's/image: harbor.magedu.*/image: harbor.magedu.net\/magedu\/tomcat-app1:${DATE}/g' tomcat-app1.yaml"
  echo "k8s yaml文件镜像版本更新完成,即将开始更新容器中镜像版本" && sleep 1
}

#到控制端更新k8s中容器的版本号,有两种更新办法,一是指定镜像版本更新,二是apply执行修改过的yaml文件
function Update_k8s_container(){
  #第一种方法
  ssh root@${K8S_CONTROLLER1} "kubectl set image deployment/magedu-tomcat-app1-deployment  magedu-tomcat-app1-container=harbor.magedu.net/magedu/tomcat-app1:${DATE} -n magedu" 
  #第二种方法,推荐使用第一种
  #ssh root@${K8S_CONTROLLER1} "cd  /opt/k8s-data/yaml/magedu/tomcat-app1  && kubectl  apply -f tomcat-app1.yaml --record" 
  echo "k8s 镜像更新完成" && sleep 1
  echo "当前业务镜像版本: harbor.magedu.net/magedu/tomcat-app1:${DATE}"
  #计算脚本累计执行时间,如果不需要的话可以去掉下面四行
  endtime=`date +'%Y-%m-%d %H:%M:%S'`
  start_seconds=$(date --date="$starttime" +%s);
  end_seconds=$(date --date="$endtime" +%s);
  echo "本次业务镜像更新总计耗时:"$((end_seconds-start_seconds))"s"
}

#基于k8s 内置版本管理回滚到上一个版本
function rollback_last_version(){
  echo "即将回滚之上一个版本"
  ssh root@${K8S_CONTROLLER1}  "kubectl rollout undo deployment/magedu-tomcat-app1-deployment  -n magedu"
  sleep 1
  echo "已执行回滚至上一个版本"
}

#使用帮助
usage(){
  echo "部署使用方法为 ${SHELL_DIR}/${SHELL_NAME} deploy "
  echo "回滚到上一版本使用方法为 ${SHELL_DIR}/${SHELL_NAME} rollback_last_version"
}

#主函数
main(){
  case ${METHOD}  in
  deploy)
    Code_Clone;
    Copy_File;
    Make_Image; 
    Update_k8s_yaml;
    Update_k8s_container;
  ;;
  rollback_last_version)
    rollback_last_version;
  ;;
  *)
    usage;
  esac;
}

main $1 $2

2.3.2 配置jenkins通过ssh密钥登录gitlab

在jenkins生成ssh密钥;

root@jenkins-server:~# ssh-keygen
root@jenkins-server:~# cat /root/.ssh/id_rsa.pub
ssh pub公钥文本1

将pub公钥文本配置在gitlab的“用户设置”--“SSH密钥”中;

在client中验证git clone不需要输入密码;

2.3.3 在jenkins web页面配置脚本路径和选项参数

Day9-结合Jenkins与gitlab实现代码部署与回滚、k8s结合ELK实现日志收集_git_05

 2.3.4 验证脚本

注释脚本中配置行,逐项测试;

2.3.5 更新应用代码和发布

从客户端更新index.html代码,并git push上传;
在gitlab查查看代码更新是否成功;
使用jenkins发布更新到k8s pod;
使用jenkins测试回滚;

3.k8s结合ELK实现日志收集

Day9-结合Jenkins与gitlab实现代码部署与回滚、k8s结合ELK实现日志收集_nginx_06

Day9-结合Jenkins与gitlab实现代码部署与回滚、k8s结合ELK实现日志收集_nginx_07

测试环境:

ELK:
Elasticsearch+kafka+kibana,es1.s209.local,172.31.2.101
Elasticsearch+kafka,es2.s209.local,172.31.2.102
Elasticsearch+kafka,es3.s209.local,172.31.2.103
logstash,logstash1.s209.local,172.31.2.104

MQ:
zookeeper+kafka,mq1.s209.local,172.31.4.101
zookeeper+kafka,mq2.s209.local,172.31.4.102
zookeeper+kafka,mq3.s209.local,172.31.4.103

 

                                      Zookeeper(服务注册与发现)

Pod日志(filebeat)--> Kafka(Topic话题) --> Logstash(收集、解析和转换日志) --> Es索引存储--> Kibana展示

Day9-结合Jenkins与gitlab实现代码部署与回滚、k8s结合ELK实现日志收集_nginx_08

 

 

 

 

3.1.部署zookeeper集群

 

3.2.部署kafka

ff

3.3.部署ES集群及浏览器安装elasticsearch head插件

ff

3.4.pod中启动filebeat实现日志收集并输出到kafka

ff

3.5.部署logstash将kakfa数据输出至elasticsearch集群

fff

3.6.部署kibana并验证数据