123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- #!/bin/bash
- # Copyright 2015 The Kubernetes Authors.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- set -o errexit
- set -o nounset
- set -o pipefail
- function grab_profiles_from_component {
- local requested_profiles=$1
- local mem_pprof_flags=$2
- local binary=$3
- local tunnel_port=$4
- local path=$5
- local output_prefix=$6
- local timestamp=$7
- echo "binary: $binary"
- for profile in ${requested_profiles}; do
- case ${profile} in
- cpu)
- go tool pprof "-pdf" "${binary}" "http://localhost:${tunnel_port}${path}/debug/pprof/profile" > "${output_prefix}-${profile}-profile-${timestamp}.pdf"
- ;;
- mem)
- # There are different kinds of memory profiles that are available that
- # had to be grabbed separately: --inuse-space, --inuse-objects,
- # --alloc-space, --alloc-objects. We need to iterate over all requested
- # kinds.
- for flag in ${mem_pprof_flags}; do
- go tool pprof "-${flag}" "-pdf" "${binary}" "http://localhost:${tunnel_port}${path}/debug/pprof/heap" > "${output_prefix}-${profile}-${flag}-profile-${timestamp}.pdf"
- done
- ;;
- esac
- done
- }
- KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
- source "${KUBE_ROOT}/hack/lib/init.sh"
- server_addr=""
- kubelet_addreses=""
- kubelet_binary=""
- master_binary=""
- scheduler_binary=""
- scheduler_port="10251"
- controller_manager_port="10252"
- controller_manager_binary=""
- requested_profiles=""
- mem_pprof_flags=""
- profile_components=""
- output_dir="."
- tunnel_port="${tunnel_port:-1234}"
- 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: -- "$@")
- if [[ $? -ne 0 ]]; then
- >&2 echo "Error in getopt"
- exit 1
- fi
- HEAPSTER_VERSION="v0.18.2"
- MASTER_PPROF_PATH=""
- HEAPSTER_PPROF_PATH="/api/v1/proxy/namespaces/kube-system/services/monitoring-heapster"
- KUBELET_PPROF_PATH_PREFIX="/api/v1/proxy/nodes"
- SCHEDULER_PPROF_PATH_PREFIX="/api/v1/proxy/namespaces/kube-system/pods/kube-scheduler"
- CONTROLLER_MANAGER_PPROF_PATH_PREFIX="/api/v1/proxy/namespaces/kube-system/pods/kube-controller-manager"
- eval set -- "${args}"
- while true; do
- case $1 in
- -s|--server)
- shift
- if [ -z "$1" ]; then
- >&2 echo "empty argument to --server flag"
- exit 1
- fi
- server_addr=$1
- shift
- ;;
- -m|--master)
- shift
- profile_components="master ${profile_components}"
- ;;
- --master-binary)
- shift
- if [ -z "$1" ]; then
- >&2 echo "empty argumet to --master-binary flag"
- exit 1
- fi
- master_binary=$1
- shift
- ;;
- -h|--heapster)
- shift
- profile_components="heapster ${profile_components}"
- ;;
- -k|--kubelet)
- shift
- profile_components="kubelet ${profile_components}"
- if [ -z "$1" ]; then
- >&2 echo "empty argumet to --kubelet flag"
- exit 1
- fi
- kubelet_addreses="$1 $kubelet_addreses"
- shift
- ;;
- --kubelet-binary)
- shift
- if [ -z "$1" ]; then
- >&2 echo "empty argumet to --kubelet-binary flag"
- exit 1
- fi
- kubelet_binary=$1
- shift
- ;;
- --scheduler)
- shift
- profile_components="scheduler ${profile_components}"
- ;;
- --scheduler-binary)
- shift
- if [ -z "$1" ]; then
- >&2 echo "empty argumet to --scheduler-binary flag"
- exit 1
- fi
- scheduler_binary=$1
- shift
- ;;
- --scheduler-port)
- shift
- if [ -z "$1" ]; then
- >&2 echo "empty argumet to --scheduler-port flag"
- exit 1
- fi
- scheduler_port=$1
- shift
- ;;
- -c|--controller-manager)
- shift
- profile_components="controller-manager ${profile_components}"
- ;;
- --controller-manager-binary)
- shift
- if [ -z "$1" ]; then
- >&2 echo "empty argumet to --controller-manager-binary flag"
- exit 1
- fi
- controller_manager_binary=$1
- shift
- ;;
- --controller-manager-port)
- shift
- if [ -z "$1" ]; then
- >&2 echo "empty argumet to --controller-manager-port flag"
- exit 1
- fi
- controller-managerr_port=$1
- shift
- ;;
- -o|--output)
- shift
- if [ -z "$1" ]; then
- >&2 echo "empty argument to --output flag"
- exit 1
- fi
- output_dir=$1
- shift
- ;;
- --inuse-space)
- shift
- requested_profiles="mem ${requested_profiles}"
- mem_pprof_flags="inuse_space ${mem_pprof_flags}"
- ;;
- --inuse-objects)
- shift
- requested_profiles="mem ${requested_profiles}"
- mem_pprof_flags="inuse_objects ${mem_pprof_flags}"
- ;;
- --alloc-space)
- shift
- requested_profiles="mem ${requested_profiles}"
- mem_pprof_flags="alloc_space ${mem_pprof_flags}"
- ;;
- --alloc-objects)
- shift
- requested_profiles="mem ${requested_profiles}"
- mem_pprof_flags="alloc_objects ${mem_pprof_flags}"
- ;;
- --cpu)
- shift
- requested_profiles="cpu ${requested_profiles}"
- ;;
- --help)
- shift
- echo "Recognized options:
- -o/--output,
- -s/--server,
- -m/--master,
- -h/--heapster,
- --inuse-space,
- --inuse-objects,
- --alloc-space,
- --alloc-objects,
- --cpu,
- --help"
- exit 0
- ;;
- --)
- shift
- break;
- ;;
- esac
- done
- if [[ -z "${server_addr}" ]]; then
- >&2 echo "Server flag is required"
- exit 1
- fi
- if [[ -z "${profile_components}" ]]; then
- >&2 echo "Choose at least one component to profile"
- exit 1
- fi
- if [[ -z "${requested_profiles}" ]]; then
- >&2 echo "Choose at least one profiling option"
- exit 1
- fi
- gcloud compute ssh "${server_addr}" --ssh-flag=-nN --ssh-flag=-L${tunnel_port}:localhost:8080 &
- echo "Waiting for tunnel to be created..."
- kube::util::wait_for_url http://localhost:${tunnel_port}/healthz
- SSH_PID=$(pgrep -f "/usr/bin/ssh.*${tunnel_port}:localhost:8080")
- kube::util::trap_add 'kill $SSH_PID' EXIT
- kube::util::trap_add 'kill $SSH_PID' SIGTERM
- requested_profiles=$(echo ${requested_profiles} | xargs -n1 | sort -u | xargs)
- profile_components=$(echo ${profile_components} | xargs -n1 | sort -u | xargs)
- kubelet_addreses=$(echo ${kubelet_addreses} | xargs -n1 | sort -u | xargs)
- echo "requested profiles: ${requested_profiles}"
- echo "flags for heap profile: ${mem_pprof_flags}"
- timestamp=$(date +%Y%m%d%H%M%S)
- binary=""
- for component in ${profile_components}; do
- case ${component} in
- master)
- path=${MASTER_PPROF_PATH}
- binary=${master_binary}
- ;;
- controller-manager)
- path="${CONTROLLER_MANAGER_PPROF_PATH_PREFIX}-${server_addr}:${controller_manager_port}"
- binary=${controller_manager_binary}
- ;;
- scheduler)
- path="${SCHEDULER_PPROF_PATH_PREFIX}-${server_addr}:${scheduler_port}"
- binary=${scheduler_binary}
- ;;
- heapster)
- rm heapster
- wget https://github.com/kubernetes/heapster/releases/download/${HEAPSTER_VERSION}/heapster
- kube::util::trap_add 'rm -f heapster' EXIT
- kube::util::trap_add 'rm -f heapster' SIGTERM
- binary=heapster
- path=${HEAPSTER_PPROF_PATH}
- ;;
- kubelet)
- path="${KUBELET_PPROF_PATH_PREFIX}"
- if [[ -z "${kubelet_binary}" ]]; then
- binary="${KUBE_ROOT}/_output/local/bin/linux/amd64/kubelet"
- else
- binary=${kubelet_binary}
- fi
- ;;
- esac
- if [[ "${component}" == "kubelet" ]]; then
- for node in $(echo ${kubelet_addreses} | sed 's/[,;]/\n/g'); do
- grab_profiles_from_component "${requested_profiles}" "${mem_pprof_flags}" "${binary}" "${tunnel_port}" "${path}/${node}" "${output_dir}/${component}" "${timestamp}"
- done
- else
- grab_profiles_from_component "${requested_profiles}" "${mem_pprof_flags}" "${binary}" "${tunnel_port}" "${path}" "${output_dir}/${component}" "${timestamp}"
- fi
- done
|