4 min read

如何正确收缩已部署的Kubernetes应用

【封面图片:广州市天河国际乒乓培训中心】如何正确收缩已部署的Kubernetes应用
如何正确收缩已部署的Kubernetes应用

需求

有时候我们需要对已经部署在Kubernetes的应用进行清理(比如:节省资源或是资源不足的情况下),同时又可能在某个心血来潮的时间来恢复它,在这种不确定的场景下,我们就不能使用deleteuninstall

此时我们可以将已部署的应用副本收缩为0,恢复时将副本收缩前的数量还原即可。

操作步骤

记录副本数量

获取控制器的副本数量,同时将信息追加至annotate


# kubectl -n <命名空间> get deploy -o jsonpath='{range .items[*]}{"kubectl -n <命名空间> annotate --overwrite deploy "}{@.metadata.name}{" previous-size="}{@.spec.replicas}{" \n"}{end}' | sh

# kubectl -n <命名空间> get sts -o jsonpath='{range .items[*]}{"kubectl -n <命名空间> annotate --overwrite sts "}{@.metadata.name}{" previous-size="}{@.spec.replicas}{" \n"}{end}' | sh

副本收缩

正式将控制器的副本数量设置为0

  • deployment
# export namespace=demo-dev
kubectl -n $namespace scale --replicas=0 $(kubectl -n $namespace get deploy -o name)
  • statefulset
# export namespace=demo-dev
kubectl -n $namespace scale --replicas=0 $(kubectl -n $namespace get sts -o name)

也可以将以上2条命令合并如下:

# export namespace=demo-dev
kubectl -n $namespace scale --replicas=0 $(kubectl -n $namespace get deploy,sts -o name)

应用恢复

此时我们有副本数量的信息,就可以随时将应用恢复到副本收缩前的状态。

  • deployment
kubectl -n <命名空间> get deploy -o jsonpath='{range .items[*]}{"kubectl -n <命名空间> scale deploy "}{@.metadata.name}{" --replicas="}{.metadata.annotations.previous-size}{"\n"}{end}' | sh
  • statefulset
kubectl -n <命名空间> get sts  -o jsonpath='{range .items[*]}{"kubectl -n <命名空间> scale sts "}{@.metadata.name}{" --replicas="}{.metadata.annotations.previous-size}{"\n"}{end}' | sh

脚本整合

SHELL脚本内容

#!/usr/bin/env bash
# 文件名: pod-scale.sh
# 功  能: 快速将指定命名空间的pod资源进行收缩/还原脚本
# 作  者: Qiu<shuhui@vqiu.cn>

# 定义终端颜色
txtbld=$(tput bold)             # 加粗
bldred=${txtbld}$(tput setaf 1) # 红
bldgre=${txtbld}$(tput setaf 2) # 绿
bldylw=${txtbld}$(tput setaf 3) # 黄
txtrst=$(tput sgr0)             # 复位
err=${bldred}ERROR${txtrst}
info=${bldgre}INFO${txtrst}
warn=${bldylw}WARNING${txtrst}

# 获取当前命名空间
namespace=$(kubectl config get-contexts | grep -e "^\*" | awk '{print $5}')

function print_info() {

    # 输出操作信息
    cat<< EOF
`printf " ============= ${bldred}操作确认${txtrst} ===============\n"`
`printf " - 命令空间: ${bldgre}${namespace}${txtrst}"`
`printf " - 操作行为: ${bldgre}$1${txtrst}"`
`printf " - 当前时间: ${bldgre}$(date +%F' '%T)${txtrst}"`
`printf " ======================================"`
`printf ""`
EOF
    read -p "确认无误,请按Enter键继续..."

}

case $1 in
    shrink|s )
        print_info 副本收缩
        for name in $(kubectl -n $namespace get deploy,sts -o name);
        do
            # 获取当前控制器副本数量
            current_replicas=$(kubectl get $name -o=jsonpath='{.spec.replicas}')
            if [[ "${current_replicas}" != "0" ]]
            then
                kubectl -n $namespace annotate $name --overwrite previous-size=${current_replicas} >/dev/null
                kubectl -n $namespace scale --replicas=0 $name >/dev/null && printf "$info: [ ${txtbld}$name${txtrst} ] 已收缩.\n"
            else
                printf "$warn: [ ${txtbld}$name${txtrst} ] 已收缩,无须处理.\n"
            fi

        done
        ;;
    recovery|r )
        print_info 副本还原
        for name in $(kubectl -n $namespace get deploy,sts -o name);
        do
            replicas=$(kubectl get $name -o=jsonpath='{.metadata.annotations.previous-size}' 2>/dev/null)
            if [[ "$replicas" != "" ]]
            then
                kubectl -n $namespace scale --replicas=$replicas $name >/dev/null && printf "$info: [ ${txtbld}$name${txtrst} ] 副本数量已恢复为 ${bldgre}$replicas${txtrst}.\n"
            else
                printf "$err:[ ${txtbld}$name${txtrst} ] 恢复失败.\n"
            fi
        done
        ;;
    *)
        echo """
用法: $(basename $0) [选项]
选项:
  shrink       资源副本收缩
  recovery     资源副本还原

${txtbld}使用案例${txtrst}
 示例1. 将当前命名空间 deploy,sts 资源副本收缩
 # ${bldgre}$(basename $0) shrink${txtrst}

 示例2. 将当前命名空间 deploy,sts 资源副本还原
 # ${bldgre}$(basename $0) recovery${txtrst}

 示例3. 将middleware命名空间 deploy,sts 资源副本收缩
 # ${bldgre}kubectl config set-context --current --namespace=middleware && $(basename $0) shrink${txtrst}

 示例4. 将middleware命名空间 deploy,sts 资源副本还原
 # ${bldgre}kubectl config set-context --current --namespace=middleware && $(basename $0) recovery${txtrst}
"""
esac

参考引用