diff --git a/check_full_pvs.sh b/check_full_pvs.sh new file mode 100755 index 0000000..41d5107 --- /dev/null +++ b/check_full_pvs.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +showHelp () { + echo "Script to check for full PVs in Kubernetes." + echo "Requires kubectl with a configuration file in ~/.kube/config and df-pv krew plugin." + echo "Usage: " + echo " ./check_full_pvs.sh [-t threshold] [-f]" + echo "Parameters:" + echo " -t (optional) : Threshold to use for near full PV evaluation (in %). Defaults to 85%." + echo " -f (optional) : Fix near full PVs (resize them). Defaults to false." + echo " -i (optional) : Percentage of PV increase when resizing. Defaults to 30%." +} + +checkReqs () { + if [ ! -x "$(command -v "kubectl")" ]; then + echo "ERROR: Kubectl is required for this script to run." + exit + fi + kubectl df-pv -h > /dev/null + if [ $? -ne 0 ]; then + echo "ERROR: df-pv kubectl plugin is required for this script to run. First install krew, then install df-pv plugin." + exit + fi + +} + +appstop () { + $NAMESPACE = $1 + #Stop deployments + DEPLOYS=$(kubectl get deployments --namespace ${NAMESPACE} | grep -v NAME | awk '{print $1}' ) + if [ $? -ne 0 ]; then + echo " |-- Error trying to get deployments for namespace $NAMESPACE." + else + for DEPLOY in $DEPLOYS; do + echo -n " |-- Stopping in ${NAMESPACE}... " && \ + kubectl scale --replicas=0 deployment ${DEPLOY} --namespace ${NAMESPACE} + if [ $? -ne 0 ]; then + echo "Error stopping $DEPLOY in namespace $NAMESPACE." + fi + done + fi + + #Stop statefulsets + SSETS=$(kubectl get statefulsets --namespace ${NAMESPACE} | grep -v NAME | awk '{print $1}' ) + if [ $? -ne 0 ]; then + echo " |-- Error trying to get statefulsets for namespace $NAMESPACE." + else + for SSET in $SSETS; do + echo -n "Stopping in ${NAMESPACE}... " && \ + kubectl scale --replicas=0 statefulset ${SSET} --namespace ${NAMESPACE} + if [ $? -ne 0 ]; then + echo "Error stopping $SSET in namespace $NAMESPACE." + fi + done + fi + +} + +FULLTHRESHOLD=85 +FIX=0 +INCREASEPERC=30 + +while getopts ":t:i:f" opt; do + case ${opt} in + t ) + FULLTHRESHOLD=$OPTARG + ;; + f ) + FIX=1 + ;; + i ) + INCREASEPERC=$OPTARG + ;; + \? ) + echo "ERROR: Invalid option: $OPTARG" 1>&2 + showHelp + exit 1 + ;; + : ) + echo "ERROR: Invalid option: $OPTARG requires an argument" 1>&2 + showHelp + exit 1 + ;; + esac +done +shift $((OPTIND -1)) + +checkReqs + +ALLNS=$(kubectl get ns -o=jsonpath='{.items[*].metadata.name}') + +IFS=$' ' +for ns in $ALLNS; do + usedstr=$(kubectl df-pv -n ${ns} -d | grep -v "PV NAME" | sed -r '/^\s*$/d') + IFS=$'\n' + for pv in $usedstr; do + usedperc=$(echo "$pv" | awk '{print $10}') + pvcname=$(echo "$pv" | awk '{print $2}') + size=$(echo "$pv" | awk '{print $7}' | numfmt --from=iec-i --to=iec-i --to-unit=Gi --round=up) + if (( $(bc <<< "($usedperc > $FULLTHRESHOLD)") )); then + echo "Volume $pvcname is almost full: ${usedperc}%!" + if [ $FIX -ne 0 ]; then + pvcstatus=$(kubectl get pvc $pvcname -n $ns -o=jsonpath='{.status.conditions[0].type}') + if [[ "$pvcstatus" == 'Resizing' ]]; then + echo " |-- Volume $pvcname already has a Resizing operation going on." + else + newsize=$(echo ${size}*1.5| bc | grep -v "$\.0") + echo " |-- Resizing $pvcname: ${size}Gi --> ${newsize}Gi..." + fi + fi + fi + done +done