业务镜像版本升级及回滚

部署

1
kubectl apply -f nginx.yaml --record=true # --record=true为记录执行的kubectl

滚动更新

滚动更新策略 spec.strategy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: Enter deployment name
spec:
strategy:
rollingUpdate:
maxSurge: 1 # 一次性最多添加多少pod
maxUnavailable: 1 # 不可用Pod的数量最多是多少
type: RollingUpdate # 指定更新策略:滚动更新
replicas: Enter the number of replicas
template:
metadata:
labels:
editor: vscode
spec:
containers:
- name: name
image: Enter containers image

更新策略有两种:

  • RollingUpdate :默认的更新策略,表示滚动更新
  • Recreate:重建,会终止所有正在运行的实例,然后用较新的版本来重新创建它们,即在创建新 Pods 之前,所有现有的 Pods 会被杀死,测试环境可以使用

Pod 有多个副本,滚动更新的过程就是轮流更新 pod,直至所有 pod 都更新成功,至于如何轮流更新,取决于 maxSurge 和 maxUnavailable 这两个参数,示例:

1
2
3
# 如果Pod有5个
maxSurge: 1 # 每次添加1个新版本Pod,启动成功后删除一个旧版本Pod
maxUnavailable: 0 # 不允许有不可用的Pod,即更新过程中始终保持5个Pod正常运行

升级命令 kubectl set

1
2
3
4
5
6
7
kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N [options]

# 示例
kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
kubectl set image deployments,rc nginx=nginx:1.9.1 --all
kubectl set image daemonset abc *=nginx:1.9.1
kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml

除了使用 kubectl get 命令升级,还可以直接 kubectl apply -f 升级,但是需要先手动修改 yaml 文件,所以不推荐使用

回滚

回滚到上一个版本

1
kubectl rollout undo deployment/nginx-deployment -n linux36

回滚到指定版本

1
2
3
4
5
6
7
8
9
10
# 查看当前版本号
kubectl rollout history deployment/nginx-deployment -n linux36
deployment.extensions/nginx-deployment
REVISION CHANGE-CAUSE
1 kubectl apply --filename=nginx.yaml --record=true
3 kubectl apply --filename=nginx.yaml --record=true
4 kubectl apply --filename=nginx.yaml --record=true

# 回滚到指定的1版本
kubectl rollout undo deployment/nginx-deployment --to-revision=1 -n linux36

Jenkins 持续继承与部署

参考以下脚本:

1
2
3
4
5
6
$cat build-command.sh

#!/bin/bash
docker build -t harbor.magedu.local/pub-images/nginx-base-wordpress:v1.14.2 .
sleep 1
docker push harbor.magedu.local/pub-images/nginx-base-wordpress:v1.14.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
$cat linux36-ningx-deploy.sh

#!/bin/bash
#Author: ZhangShiJie
#Date: 2019-08-03
#Version: v1
#记录脚本开始执行时间
starttime=$(date +'%Y-%m-%d %H:%M:%S')
#变量
SHELL_DIR="/root/scripts"
SHELL_NAME="$0"
K8S_CONTROLLER1="192.168.7.101"
K8S_CONTROLLER2="192.168.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.20.100.1:linux36/app1.git"
DIR_NAME=$(echo ${Git_URL} | awk -F "/" '{print $2}' | awk -F "." '{print $1}')
DATA_DIR="/data/gitdata/linux36"
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/linux36/nginx/
echo "压缩文件拷贝完成,服务器${K8S_CONTROLLER1}即将开始制作Docker 镜像!" && sleep 1
}

#到控制端执行脚本制作并上传镜像
function Make_Image() {
echo "开始制作Docker镜像并上传到Harbor服务器" && sleep 1
ssh root@${K8S_CONTROLLER1} "cd /opt/k8s-data/dockerfile/linux36/nginx && 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/linux36/nginx && sed -i 's/image:
harbor.magedu.*/image: harbor.magedu.net\/linux36\/nginx-web1:${DATE}/g' nginx.yaml"
echo "k8s yaml文件镜像版本更新完成,即将开始更新容器中镜像版本" && sleep 1
}

#到控制端更新k8s中容器的版本号,有两种更新办法,一是指定镜像版本更新,二是apply执行修改过的yaml文件
function Update_k8s_container() {
#第一种方法
ssh root@${K8S_CONTROLLER1} "kubectl set image deployment/linux36-nginx-deployment linux36-nginx-container=harbor.magedu.net/linux36/nginx-web1:${DATE} -n linux36"
#第二种方法,推荐使用第一种
#ssh root@${K8S_CONTROLLER1} "cd /opt/k8s-data/yaml/web-test/tomcat-app1 && kubectl apply -f web-test.yam --record"
echo "k8s 镜像更新完成" && sleep 1
echo "当前业务镜像版本: harbor.magedu.net/linux36/nginx-web1:${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/linux36-nginx-deployment -n linux36"
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 $3

代码升级和回滚

代码升级:Jenkins 负责 pull 最新代码,编译成 war 包(如果需要),然后将编译后的包发送到 k8s 或者专门负责制作镜像的服务器,使用 dockerfile 制作完新镜像后,就上传到 harbor,最后再由 kubectl 执行更新镜像的操作

代码回滚:直接回滚镜像即可