From d5c13ae6fb951ab0c7d823821b4a6f959c82cadd Mon Sep 17 00:00:00 2001 From: jiema Date: Fri, 18 Sep 2020 11:41:30 +0800 Subject: [PATCH] Created _Footer (markdown) --- _Footer.md | 441 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 441 insertions(+) create mode 100644 _Footer.md diff --git a/_Footer.md b/_Footer.md new file mode 100644 index 0000000..5caee65 --- /dev/null +++ b/_Footer.md @@ -0,0 +1,441 @@ +#!/bin/bash +#author: chuxiaowei@360.cn +#date: 2020.08.04 + +: ${HELM_MINIMUM_ACCEPTABLE_VERSION:='3.2.4'} +: ${ACTION_INFO_PATH:='./resources/info'} +: ${PACKAGE_VALUES_PATH:='./resources/values'} +: ${DOCKER_IMAGES_PATH:='./resources/dockerImages'} +: ${HELM_LOCAL_INSTALL_SHELL:='./resources/helm/install_helm.sh'} + +# 版本比较辅助函数 +VER_SPLIT_SED='s/\./ /g;s/\([[:digit:]]\)\([^[:digit:] ]\)/\1 \2/g;s/\([^[:digit:] ]\)\([[:digit:]]\)/\1 \2/g' +# Compare with one element of version components +_ver_cmp_1() { + [[ "$1" = "$2" ]] && return 0 + if [[ -z "${1//[[:digit:]]/}" ]] && [[ -z "${2//[[:digit:]]/}" ]]; then + # Both $1 and $2 are numbers + # Using arithmetic comparison + (( $1 > $2 )) && return 1 + (( $1 < $2 )) && return 2 + else + # Either or both are not numbers, containing non-digit characters + # Using string comparison + [[ "$1" > "$2" ]] && return 1 + [[ "$1" < "$2" ]] && return 2 + fi + # This should not be happening + exit 1 +} + +ver_cmp() { + local A B i result + A=($(sed "$VER_SPLIT_SED" <<< "$1")) + B=($(sed "$VER_SPLIT_SED" <<< "$2")) + i=0 + while (( i < ${#A[@]} )) && (( i < ${#B[@]})); do + _ver_cmp_1 "${A[i]}" "${B[i]}" + result=$? + [[ $result =~ [12] ]] && return $result + let i++ + done + # Which has more, then it is the newer version + _ver_cmp_1 "${#A[i]}" "${#B[i]}" + return $? +} + +# 解析json +parse_json(){ + # {"target_version":"1.1.0","current_version":"1.0.0"} + local keystr="$2\":\"" + echo `cat "$1" | sed "s/{\"//g" | sed "s/\"}//g" | sed "s/\",\"/+++/g" | tr "+++" "\n" | grep "$keystr" | sed "s/$keystr//g"` +} + +# log +log() { + local msg='' + for m in $@; + do + msg="$msg $m" + done + echo -e "[---info-->>>] $msg" +} + +logerr() { + local msg='' + for m in $@; + do + msg="$msg $m" + done + echo -e "[--error-->>>] $msg" +} + +get_absolute_path() { + local path="$(dirname $0)/$(echo $1 | sed "s/\.\///g")" + echo $path +} + +# helm 安装 +helm_install() { + read -p "helm离线安装使用资源包自带的version 3.2.4 版本,在线安装将联网拉取线上最新版本。是否离线安装?(y/n [y]): " offline + echo $offline + if [[ "$offline" == "y" || "$offline" == "Y" || "$offline" == `echo -e "\n"` ]];then + log "执行helm安装脚本..." + local shellPath=$(get_absolute_path $HELM_LOCAL_INSTALL_SHELL) + chmod 700 $shellPath + eval $shellPath + else + local helmInstallShellUrl='https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3' + log "准备拉取helm安装脚本: $helmInstallShellUrl" + curl -fsSL -o get_helm.sh $helmInstallShellUrl + log "为helm安装脚本赋权..." + chmod 700 get_helm.sh + log "执行helm安装脚本..." + ./get_helm.sh + fi + + local version=$(get_helm_version) + if [ "$version" != "" ];then + log "helm install success. current Version : $version" + fi +} + +# 获取helm 版本 +get_helm_version() { + local helmVersionInfo=$(helm version | grep version.BuildInfo) + local info=$(echo $helmVersionInfo) + if [ "$info" == "" ];then + echo "" + fi + # helmVersion=$(echo $info | grep -o '".*"' | sed 's/"//g') + # helmVersion=${helmVersion%%,*} + local helmVersion=$(helm version --template="{{ .Version }}") + helmVersion=$(echo $helmVersion | sed 's/v//g') + echo "$helmVersion" +} + + +# 环境检查,检查helm是否安装,版本检查 +check_helm_env() { + # 1.检查kubectl + local kubeVersion=$(kubectl version) + if [ "$(echo $kubeVersion | grep 'command not found')" != "" ];then + logerr "未检测到 kubectl命令,请安装 kubectl 命令行工具后重试。" + exit 3 + fi + local kubeContextInfo=$(kubectl config current-context) + if [ "$(echo $kubeContextInfo | grep 'current-context is not set')" != "" ];then + logerr "未检测到 kubectl config 配置,请在配置kubectl config后重试." + exit 3 + fi + + # 2.检查helm + local version=$(get_helm_version) + if [ $version == "" ];then + log "can not find helm command... try install." + local infoPath=$(get_absolute_path $ACTION_INFO_PATH) + local actionType=$(parse_json $infoPath "action_type") + if [[ $actionType == "install" ]];then + helm_install + version=$(get_helm_version) + else + exit 4 + fi + fi + + log "current helm version: $version" + set +e + ver_cmp "$version" "$HELM_MINIMUM_ACCEPTABLE_VERSION" + cmp_res=$? + set -e + if [ $cmp_res == 2 ] # < + then + log "当前版本太低,请升级helm版本,helm version 不低于 v$HELM_MINIMUM_ACCEPTABLE_VERSION ." + read -p "是否立即升级?(y/n [y]): " flag + if [[ "$flag" == "y" || "$flag" == "Y" || "$flag" == `echo -e "\n"` ]];then + helm_install + else + log "程序已退出,请升级 helm 版本后重试。" + exit 4 + fi + fi +} + +package_action_confirmation() { + local infoPath=$(get_absolute_path $ACTION_INFO_PATH) + local releaseName=$(parse_json $infoPath "release_name") + local actionType=$(parse_json $infoPath "action_type") + local targetVersion=$(parse_json $infoPath "target_version") + local changeLog=$(parse_json $infoPath "change_log") + log "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + log "\t Release Name: $releaseName" + log "\t Target Version: $targetVersion" + log "\t Action Type: $actionType" + log "\t Change Log: $changeLog" + log "\t Another K8S Nodes: $K8S_IPs" + log "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + local flag="" + read -p "请确认上述关于安装包任务的相关信息,是否立即执行?(y/n [y]): " flag + if [[ "$flag" == "y" || "$flag" == "Y" || "$flag" == `echo -e "\n"` ]];then + return + else + log "已取消【立即执行】操作,程序已退出。" + exit 0 + fi +} + +make_docker_image_dir(){ + + mkdir -p /root/local_images/images/ + + # 确保存镜像的文件夹存在 + if [ $# -lt 1 ];then + continue + fi + + # 同步到其他节点 + for i in $@; + do + ssh -p 22 -nq $i 'mkdir -p /root/local_images/images/' + done +} + +# 拉镜像 +pull_docker_images() { + + read -p "是否需要为安装拉取镜像, 并同步到其他节点?(y/n [n]): " flag + if [[ "$flag" == "y" || "$flag" == "Y" ]];then + log "即将拉取镜像..." + else + log "跳过【镜像拉取】" + return + fi + + local tmp_dockerImage='dockerImage.tmp' + if [ -f $tmp_dockerImage ];then + rm -rf $tmp_dockerImage + fi + local dockerImagesPath=$(get_absolute_path $DOCKER_IMAGES_PATH) + local content=$(sort -n $dockerImagesPath | uniq >> $tmp_dockerImage) + imagesCount=0 + log "+++++++++++++++++++++++ 将要拉取同步下列镜像 +++++++++++++++++++++++++" + for LINE in `cat "./$tmp_dockerImage"` + do + log "\t$LINE" + let imagesCount+=1 + done + log "++++++++++++++++++++++++ 共 $imagesCount 个镜像++++++++++++++++++++++++++++" + + make_docker_image_dir $@ + + imagesCount=0 + + # 并发执,控制最大并发数为10 + start_time=`date +%s` + tmp_fifofile="/tmp/$$.fifo" # 已进程号命令创建临时文件 + mkfifo $tmp_fifofile + exec 6<>$tmp_fifofile # 将FD6指向FIFO类型 + rm $tmp_fifofile + thread_num=10 #最大进程数 + for ((i=0;i<${thread_num};i++));do + echo >&6 + done + + for LINE in `cat "./$tmp_dockerImage"` + do + read -u6 + { + local imageAddr=`echo $LINE | sed "s/'//g"` + local imageName=`basename $imageAddr` + docker pull $imageAddr + docker save $imageAddr -o /root/local_images/images/$imageName.tar + log "当前节点 : $imageName 拉取成功" + + # 检查入参是否有传入其他节点 + if [ $# -lt 1 ];then + continue + fi + + # 同步到其他节点 + for i in $@; + do + if ssh -p 22 -nq $i test -e "/root/local_images/images/$imageName.tar" ;then + log "$i : $imageName 已存在" + else + log "准备同步 $i : $imageName" + rsync -avz --progress /root/local_images/images/$imageName.tar $i:/root/local_images/images/$imageName.tar + fi + log "$i : docker will load $imageName" + ssh -p 22 -nq $i "docker load -i /root/local_images/images/$imageName.tar" + log "$i : $imageName 同步、加载完成" + done + let imagesCount+=1 + echo >&6 + } & + done + wait + stop_time=`date +%s` + log "拉取同步镜像共耗时:`expr $stop_time - $start_time`" + + exec 6<&- #关闭文件描述符的读 + exec 6>&- #关闭文件描述符的写 + rm "./$tmp_dockerImage" +} + +package_install() { + local infoPath=$(get_absolute_path $ACTION_INFO_PATH) + local releaseName=$(parse_json $infoPath "release_name") + local packagePath=$(parse_json $infoPath "package_path") + local actionType=$(parse_json $infoPath "action_type") + + local actionCMD='' + case "$actionType" in + 'install') actionCMD='upgrade --install' ;; + 'upgrade') actionCMD='upgrade --install' ;; + 'rollback') actionCMD='upgrade' ;; + esac + + packagePath=$(get_absolute_path $packagePath) + + local valuesDir=$(get_absolute_path $PACKAGE_VALUES_PATH) + local valuesCmd='' + for j in `ls $valuesDir`; + do + valuesCmd="$valuesCmd -f $valuesDir/$j" + done + + local HELM_CMD="helm $actionCMD $releaseName $packagePath $valuesCmd" + log "执行命令: $HELM_CMD" + eval $HELM_CMD +} + +jobs_install_cmd() { + local infoPath=$(get_absolute_path $ACTION_INFO_PATH) + local packagePath=$(parse_json $infoPath "job_package_path") + local actionType=$(parse_json $infoPath "action_type") + + if [[ "$actionType" == "rollback" ]];then + log "当前执行的是回滚操作,job暂不执行" + echo "" + else if [[ "$packagePath" == "" ]];then + log "未发现有需要执行的jobs" + echo " + else + local pwdPath=`pwd` + local releaseName=`basename $pwdPath` + releaseName="$releaseName-jobs" + packagePath=$(get_absolute_path $packagePath) + + local valuesDir=$(get_absolute_path $PACKAGE_VALUES_PATH) + local valuesCmd='' + for j in `ls $valuesDir`; + do + valuesCmd="$valuesCmd -f $valuesDir/$j" + done + + local HELM_CMD="helm install $releaseName $packagePath $valuesCmd" + echo $HELM_CMD + fi +} + +jobs_install() { + + local HELM_CMD=$(jobs_install_cmd) + + if [[ "$HELM_CMD" == "" ]];then + log "离线包版本job检查完毕" + else + read -p "检测到离线包中有 jobs 可以执行,是否需要执行离线包中的 jobs? (m:手动模式)(y/m/n [n]): " flag + if [[ "$flag" == "y" || "$flag" == "Y" || "$flag" == "m" || "$flag" == "M" ]];then + log "开始执行版本任务..." + HELM_CMD="$HELM_CMD --set tags.all=true" + if [[ "$flag" == "m" || "$flag" == "M" ]];then + HELM_CMD="$HELM_CMD --set migration.manual=true" + fi + log "执行命令: $HELM_CMD" + eval $HELM_CMD + else + log "跳过【jobs 执行】" + fi + fi +} + + +fail_trap() { + result=$? + if [ "$result" != "0" ]; then + case "$result" in + "3") echo "请确保安装 kubectl 命令行工具,以及正确配置集群环境." ;; + "4") echo "请确保安装 helm 命令行工具,以及版本不低于 $HELM_MINIMUM_ACCEPTABLE_VERSION ." ;; + esac + if [[ -n "$INPUT_ARGUMENTS" ]]; then + logerr "Failed to install package with the arguments provided: $INPUT_ARGUMENTS" + help + else + logerr "Failed to install package." + fi + echo -e "\tFor support, read the file Readme.md" + fi + exit $result +} + +help () { + echo "Accepted cli arguments are:" + echo -e "\t[--help | -h ] ->> prints this help" + echo -e "\t[--install | -i ] . When it not defined, the dcoker images cannot be synchronized to other nodes." + echo -e "\te.g. --install k8s2 k8s3 k8s4 k8s5 or -i k8s2 k8s3 k8s4 k8s5" +} + +main() { + + # 1.检查执行环境 + log "检查相关执行环境..." + check_helm_env + + # 2.离线任务信息确认 + log "离线任务信息确认..." + package_action_confirmation + + # 3.拉取docker镜像 + log "为服务安装拉取相关镜像..." + pull_docker_images $@ + log "拉取相关镜像操作已完成" + + # 4.执行版本任务 + log "检查版本job..." + jobs_install + + # 5.执行版本操作 + log "开始安装离线包..." + package_install + + log "安装包执行完毕." +} + +trap "fail_trap" EXIT +set -e + +# 解析参数 +export INPUT_ARGUMENTS="${@}" +set -u +while [[ $# -gt 0 ]]; do + case $1 in + '--install'|-i) + shift + if [[ $# -ne 0 ]]; then + export K8S_IPs=$@ + fi + ;; + '--help'|-h) + help + exit 0 + ;; + *) exit 1 + ;; + esac + break +done +set +u + + +main $K8S_IPs \ No newline at end of file