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