如何在 pod 中的 container 里面生成 coredump 文件并拷贝出来使用 GDB debug

Posted by Luffyao on Monday, December 2, 2019

前言

为什么会记录这篇文章呢,是因为在工作中,遇到了这个问题,由于我们这个是 C++写的代码,crash tracing 并没有 golang 好,所以代码 crash 在 pod 中的 container 里面,很难调查。最多的也就是多加 log,但是你懂的,添加 log debug 效率还是蛮低的。所以就要用 coredump 去快速找到问题所在。但是就遇到文章的问题。你怎么去 pod 中的 container 生成 coredump 呢,然后拷到本地 gdb 呢?

在 helm chart 里面加上一个 initContainer

  • 在 deployment.yaml 里面添加一个 initContainer 和 volume

    ```yaml
      volumes:
      - name: dumps
        emptyDir: {}
      initContainers:
      - name: {{ .Values.initContainers.coredumps.service.name }}
        image: "{{ .Values.global.registry.url }}/{{ .Values.imageCredentials.repoPath }}/{{.Values.initContainers.coredumps.images.name }}:{{ .Values.initContainers.coredumps.images.tag}}"
        command: ['sh', '-c', 'ulimit -c unlimited; echo "{{ .Values.initContainers.coredumps.service.dst }}/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern;']
        securityContext:
          privileged: true
    ```
    
  • 为需要生成 coredump 的 container 加上个 volumeMounts.

    ``` yaml
      volumeMounts:
      - name: dumps
        mountPath: {{ .Values.initContainers.coredumps.service.dst }}
    ```
    
  • 添加下面 code 在你的 value.yaml 里面 (如何你在第一步里面是 hardcode 的话,这里可以省略)

    ``` yaml
    # here image i used suse, you can use "docker pull registry.suse.com/suse/sles12sp4" pull ito your local
    # and then use "docker tag xxx bbb" command to retag it(this command can omit if you usorigin tag directly)
    initContainers:
      coredumps:
        images:
          name: xxx
          tag: 1.xxx
        service:
          name: coredumps
          dst: /root/dumps
    ```
    

用 debug 模式编译代码,然后 docker build 一个 image

  • 可参考下面命令生成 image

    ``` shell
    // "." means current directory
    docker build XXXX .
    ```
    

更新你的 image 到 deployment 里面

这里有两个方案:

  • 用下面命令直接在线修改你的 deployment, k8s 通过重启 pod 动态生效。

    ``` shell
    kubectl edit deploy your_deployment_name
    ```
    
  • 修改本地 deployment.yaml 文件,然后在 kubectl upgrade 更新(基于 helm install 的方式).

找到你挂载的 coredump 文件映射到本地的具体目录

  • 可参考下面命令

    docker ps | grep ApplicationName  #to found container id .
    docker inspect container id | grep dump #to found dir that docker volume mapped local dir.
    

将生成的 coredump 文件拷贝到你本地目录

Note: 其实好像还有个 docker cp 命令可以拷贝文件,但是我没有在这个情况亲自尝试过,这是用过将本地文件 copy 到 container 里面 . 具体怎么使用,可以参考官网指导 docker cp command guidance.

copy file from/to minikube

    1. minikube ssh -p master
    2. sudo passwd docker // to create a new password.
    3. exit from ssh 
    4. scp /local/path/file docker@minikubeip:/destionation/folder

抓取coredump in minikube

    1. minikube ssh -p master
    2. sudo -i
    3. ps -axu |grep processinfo
    4. ctr -n k8s.io task list |grep processId
    5. ctr -n k8s.io c info $(ctr -n k8s.io taks list | grep processID | awk -F " " '{print $1}') | grep core
    6. copy file to local from minikube

gdb 调试你的程序

总结

本文讲的方式是在主 container 运行之前,启动一个定制的 initContainer,目的是将 coredump 默认生成文件目录修改到自己设定的目录下。然后就可以将 coredump 文件弄出到本地,进行 debug 分析。

参考文章