k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/hack/grab-profiles.sh (about) 1 #!/usr/bin/env bash 2 3 # Copyright 2015 The Kubernetes Authors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 # This script grabs profiles from running components. 18 # Usage: `hack/grab-profiles.sh`. 19 20 set -o errexit 21 set -o nounset 22 set -o pipefail 23 24 function grab_profiles_from_component { 25 local requested_profiles=$1 26 local mem_pprof_flags=$2 27 local binary=$3 28 local tunnel_port=$4 29 local path=$5 30 local output_prefix=$6 31 local timestamp=$7 32 33 echo "binary: $binary" 34 35 for profile in ${requested_profiles}; do 36 case ${profile} in 37 cpu) 38 go tool pprof "-pdf" "${binary}" "http://localhost:${tunnel_port}${path}/debug/pprof/profile" > "${output_prefix}-${profile}-profile-${timestamp}.pdf" 39 ;; 40 mem) 41 # There are different kinds of memory profiles that are available that 42 # had to be grabbed separately: --inuse-space, --inuse-objects, 43 # --alloc-space, --alloc-objects. We need to iterate over all requested 44 # kinds. 45 for flag in ${mem_pprof_flags}; do 46 go tool pprof "-${flag}" "-pdf" "${binary}" "http://localhost:${tunnel_port}${path}/debug/pprof/heap" > "${output_prefix}-${profile}-${flag}-profile-${timestamp}.pdf" 47 done 48 ;; 49 esac 50 done 51 } 52 53 KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 54 source "${KUBE_ROOT}/hack/lib/init.sh" 55 56 server_addr="" 57 kubelet_addresses="" 58 kubelet_binary="" 59 master_binary="" 60 scheduler_binary="" 61 scheduler_port="10251" 62 controller_manager_port="10252" 63 controller_manager_binary="" 64 requested_profiles="" 65 mem_pprof_flags="" 66 profile_components="" 67 output_dir="." 68 tunnel_port="${tunnel_port:-1234}" 69 70 if ! args=$(getopt -o s:mho:k:c -l server:,master,heapster,output:,kubelet:,scheduler,controller-manager,help,inuse-space,inuse-objects,alloc-space,alloc-objects,cpu,kubelet-binary:,master-binary:,scheduler-binary:,controller-manager-binary:,scheduler-port:,controller-manager-port: -- "$@"); then 71 >&2 echo "Error in getopt" 72 exit 1 73 fi 74 75 HEAPSTER_VERSION="v0.18.2" 76 MASTER_PPROF_PATH="" 77 HEAPSTER_PPROF_PATH="/api/v1/namespaces/kube-system/services/monitoring-heapster/proxy" 78 KUBELET_PPROF_PATH_PREFIX="/api/v1/proxy/nodes" 79 SCHEDULER_PPROF_PATH_PREFIX="/api/v1/namespaces/kube-system/pods/kube-scheduler/proxy" 80 CONTROLLER_MANAGER_PPROF_PATH_PREFIX="/api/v1/namespaces/kube-system/pods/kube-controller-manager/proxy" 81 82 eval set -- "${args}" 83 84 while true; do 85 case $1 in 86 -s|--server) 87 shift 88 if [ -z "$1" ]; then 89 >&2 echo "empty argument to --server flag" 90 exit 1 91 fi 92 server_addr=$1 93 shift 94 ;; 95 -m|--master) 96 shift 97 profile_components="master ${profile_components}" 98 ;; 99 --master-binary) 100 shift 101 if [ -z "$1" ]; then 102 >&2 echo "empty argument to --master-binary flag" 103 exit 1 104 fi 105 master_binary=$1 106 shift 107 ;; 108 -h|--heapster) 109 shift 110 profile_components="heapster ${profile_components}" 111 ;; 112 -k|--kubelet) 113 shift 114 profile_components="kubelet ${profile_components}" 115 if [ -z "$1" ]; then 116 >&2 echo "empty argument to --kubelet flag" 117 exit 1 118 fi 119 kubelet_addresses="$1 $kubelet_addresses" 120 shift 121 ;; 122 --kubelet-binary) 123 shift 124 if [ -z "$1" ]; then 125 >&2 echo "empty argument to --kubelet-binary flag" 126 exit 1 127 fi 128 kubelet_binary=$1 129 shift 130 ;; 131 --scheduler) 132 shift 133 profile_components="scheduler ${profile_components}" 134 ;; 135 --scheduler-binary) 136 shift 137 if [ -z "$1" ]; then 138 >&2 echo "empty argument to --scheduler-binary flag" 139 exit 1 140 fi 141 scheduler_binary=$1 142 shift 143 ;; 144 --scheduler-port) 145 shift 146 if [ -z "$1" ]; then 147 >&2 echo "empty argument to --scheduler-port flag" 148 exit 1 149 fi 150 scheduler_port=$1 151 shift 152 ;; 153 -c|--controller-manager) 154 shift 155 profile_components="controller-manager ${profile_components}" 156 ;; 157 --controller-manager-binary) 158 shift 159 if [ -z "$1" ]; then 160 >&2 echo "empty argument to --controller-manager-binary flag" 161 exit 1 162 fi 163 controller_manager_binary=$1 164 shift 165 ;; 166 --controller-manager-port) 167 shift 168 if [ -z "$1" ]; then 169 >&2 echo "empty argument to --controller-manager-port flag" 170 exit 1 171 fi 172 controller_manager_port=$1 173 shift 174 ;; 175 -o|--output) 176 shift 177 if [ -z "$1" ]; then 178 >&2 echo "empty argument to --output flag" 179 exit 1 180 fi 181 output_dir=$1 182 shift 183 ;; 184 --inuse-space) 185 shift 186 requested_profiles="mem ${requested_profiles}" 187 mem_pprof_flags="inuse_space ${mem_pprof_flags}" 188 ;; 189 --inuse-objects) 190 shift 191 requested_profiles="mem ${requested_profiles}" 192 mem_pprof_flags="inuse_objects ${mem_pprof_flags}" 193 ;; 194 --alloc-space) 195 shift 196 requested_profiles="mem ${requested_profiles}" 197 mem_pprof_flags="alloc_space ${mem_pprof_flags}" 198 ;; 199 --alloc-objects) 200 shift 201 requested_profiles="mem ${requested_profiles}" 202 mem_pprof_flags="alloc_objects ${mem_pprof_flags}" 203 ;; 204 --cpu) 205 shift 206 requested_profiles="cpu ${requested_profiles}" 207 ;; 208 --help) 209 shift 210 echo "Recognized options: 211 -o/--output, 212 -s/--server, 213 -m/--master, 214 -h/--heapster, 215 --inuse-space, 216 --inuse-objects, 217 --alloc-space, 218 --alloc-objects, 219 --cpu, 220 --help" 221 exit 0 222 ;; 223 --) 224 shift 225 break; 226 ;; 227 esac 228 done 229 230 if [[ -z "${server_addr}" ]]; then 231 >&2 echo "Server flag is required" 232 exit 1 233 fi 234 235 if [[ -z "${profile_components}" ]]; then 236 >&2 echo "Choose at least one component to profile" 237 exit 1 238 fi 239 240 if [[ -z "${requested_profiles}" ]]; then 241 >&2 echo "Choose at least one profiling option" 242 exit 1 243 fi 244 245 gcloud compute ssh "${server_addr}" --ssh-flag=-nN --ssh-flag=-L"${tunnel_port}":localhost:8080 & 246 247 echo "Waiting for tunnel to be created..." 248 kube::util::wait_for_url http://localhost:"${tunnel_port}"/healthz 249 250 SSH_PID=$(pgrep -f "/usr/bin/ssh.*${tunnel_port}:localhost:8080") 251 kube::util::trap_add "kill $SSH_PID" EXIT 252 kube::util::trap_add "kill $SSH_PID" SIGTERM 253 254 requested_profiles=$(echo "${requested_profiles}" | xargs -n1 | LC_ALL=C sort -u | xargs) 255 profile_components=$(echo "${profile_components}" | xargs -n1 | LC_ALL=C sort -u | xargs) 256 kubelet_addresses=$(echo "${kubelet_addresses}" | xargs -n1 | LC_ALL=C sort -u | xargs) 257 echo "requested profiles: ${requested_profiles}" 258 echo "flags for heap profile: ${mem_pprof_flags}" 259 260 timestamp=$(date +%Y%m%d%H%M%S) 261 binary="" 262 263 for component in ${profile_components}; do 264 case ${component} in 265 master) 266 path=${MASTER_PPROF_PATH} 267 binary=${master_binary} 268 ;; 269 controller-manager) 270 path="${CONTROLLER_MANAGER_PPROF_PATH_PREFIX}-${server_addr}:${controller_manager_port}" 271 binary=${controller_manager_binary} 272 ;; 273 scheduler) 274 path="${SCHEDULER_PPROF_PATH_PREFIX}-${server_addr}:${scheduler_port}" 275 binary=${scheduler_binary} 276 ;; 277 heapster) 278 rm heapster 279 wget https://github.com/kubernetes/heapster/releases/download/${HEAPSTER_VERSION}/heapster 280 kube::util::trap_add 'rm -f heapster' EXIT 281 kube::util::trap_add 'rm -f heapster' SIGTERM 282 binary=heapster 283 path=${HEAPSTER_PPROF_PATH} 284 ;; 285 kubelet) 286 path="${KUBELET_PPROF_PATH_PREFIX}" 287 if [[ -z "${kubelet_binary}" ]]; then 288 binary="${KUBE_ROOT}/_output/local/bin/linux/amd64/kubelet" 289 else 290 binary=${kubelet_binary} 291 fi 292 ;; 293 esac 294 295 if [[ "${component}" == "kubelet" ]]; then 296 for node in ${kubelet_addresses//[,;]/' '}; do 297 grab_profiles_from_component "${requested_profiles}" "${mem_pprof_flags}" "${binary}" "${tunnel_port}" "${path}/${node}/proxy" "${output_dir}/${component}" "${timestamp}" 298 done 299 else 300 grab_profiles_from_component "${requested_profiles}" "${mem_pprof_flags}" "${binary}" "${tunnel_port}" "${path}" "${output_dir}/${component}" "${timestamp}" 301 fi 302 done