Skip to content

Instantly share code, notes, and snippets.

@hisui
Created February 10, 2022 09:37
Show Gist options
  • Save hisui/f019da9b798cd7f7a3f8fa5660df02b1 to your computer and use it in GitHub Desktop.
Save hisui/f019da9b798cd7f7a3f8fa5660df02b1 to your computer and use it in GitHub Desktop.
Execute perf-record in a pod-in-cluster and pref-script in local and then generate a flame graph.
#!/usr/bin/env ruby
require "json"
# https://github.com/brendangregg/FlameGraph
FG_SCRIPTS = raise "`FG_SCRIPTS` must be set by hand."
if ARGV.empty?
$stderr.puts("Usage: ruby kperf.rb $POD [ $CONTAINER ] > out.svg")
exit(-1)
end
pod = ARGV[0]
pod_spec = JSON.parse(`kubectl get pod "#{pod}" -o jsonpath='{.spec}'`)
cont = ARGV[1]
cont_spec =
cont ? pod_spec["containers"].find { |e| e["name"] == cont } || raise("No container named '#{cont}'.")
: pod_spec["containers"][0]
pid = nil
trap(:INT) {
Process.kill("INT", pid)
}
$stderr.puts("kperf: Start profiling (Ctrl+C to stop)")
pid = spawn("kubectl exec -c '#{cont_spec['name']}' -it '#{pod}' -- perf record --call-graph dwarf -p 1 -o perf.data")
Process.waitpid(pid)
$stderr.puts("kperf: Start downloading 'perf.data'..")
pid = spawn("kubectl cp -c '#{cont_spec['name']}' '#{pod}':perf.data perf.data")
Process.waitpid(pid)
$stderr.puts("kperf: Start generating a flamegraph..")
exec("docker run -i -v $(pwd):/host --rm --entrypoint perf '#{cont_spec['image']}' script -i /host/perf.data | #{FG_SCRIPTS}/stackcollapse-perf.pl | #{FG_SCRIPTS}/flamegraph.pl")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment