在容器化大行其道的今天,经常有需求要检查容器内部状态,debug容器内的应用。

今天总结介绍一下几个场景与解决方案。

docker debug

有时候我们的容器应用A会有些网络问题,或是cpu memory io占用过高,我们想看看容器内到底什么在作怪。

然而一般的应用镜像的基础镜像是精简镜像,它几乎没什么调试查看工具。

这时候就需要利用namespace(控制资源隔离)的相关知识,启动一个tools-B容器来检查目标容器A。

# 以下命令本质上是启动一个新的容器,但是新容器的namespace使用的是A容器的,所以可以对A容器下的pid、网络等进行读写
# 开启后,即可使用ping、telnet等各种命令进行环境检查啦
docker run --rm -it --network=container:container_A --pid=container:container_A busybox

当然,你也可以将这条命令写入bashrc,以便未来更方便的使用它。因为我用的是zsh,我将如下代码写在.zshrc配置中

# docker debug
function dockerdebug() {
    docker run --rm -it --network=container:$1 --pid=container:$1 busybox;
}

source后或者打开新的终端后,就可以使用命令dockerdebug 容器名进入容器了。

kubectl debug

以上介绍了docker进入容器debug的问题,k8s中,怎么做呢?

  1. 安装kubectl

  2. 命令行进入debug

# 如果k8s集群不在本机,可以先拉取k8s集群的kubeconfig(一个包含了certificate、authority、地址等信息的文件)到本地,再设置环境变量
export KUBECONFIG=/xxx/xxx/admin.conf
# 进入选取pod进入调试
kubectl debug pod_name

此时,可以看见启动了一个debug-agent-pod-xxx,如果失败,一般是需要集群机器上需要docker pull docker.io/nicolaka/netshoot:latest,类似上文docker debug的busybox镜像。

还有更多功能可以参见官方文档

当我们需要调试本地应用,访问集群上的其它服务

# NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
# nginx-service   NodePort    11.11.198.200   <none>        88:32267/TCP   7d19h


# 如果非本地集群,需要设置kubeconfig环境变量即可
export KUBECONFIG=/xxx/xxx/admin.conf
# 方式一:将流量通过本地8888转发到service的88端口上,此时访问本地8888端口即相当于访问了service的88端口
kubectl port-forward service/nginx-service 8888:88

# 方式二:将流量通过本地9999端口转发到对应deployment中的pod的80端口上
kubectl port-forward deployment/nginx-deployment 9999:80

Telepresence

上面描述了访问集群中的服务,本地调试的方法。下面介绍下被调试的应用需要被集群中服务调用,应当如何做。

即将集群中的流量转发到本地应用。

Telepresence安装

  • OS X
brew install --cask osxfuse
brew install datawire/blackbird/telepresence
  • Ubuntu 16.04 or later
curl -s https://packagecloud.io/install/repositories/datawireio/telepresence/script.deb.sh | sudo bash
sudo apt install --no-install-recommends telepresence

Telepresence使用

假设我们集群有a、b、c三个服务,他们分别由deployement管理,service-a、service-b、service-c。

服务a依赖服务b的某个接口,b依赖c。

忽然,服务b的这个接口出了点问题,我们想定位下原因或调试下,难道要重新打包制作个镜像、上传到服务器再调试吗?

大可不必,我们用下面的步骤实现本地调试。

  1. 在本地改好服务b程序

  2. 运行命令,admin.conf是目标k8s集群的kubeconfig

export KUBECONFIG=/xxx/xxx/admin.conf
  1. 使用本地程序接收集群中的流量
# service-b 是deployment名称
# 8081是本地监听端口(注意本地的服务b也需要监听8081端口)
# 80是线上服务b的pod的监听端口
# binary-b是本地的二进制可执行文件
telepresence --swap-deployment service-b --expose 8081:80 --run ./binary-b
  1. 使用本地debug
telepresence --swap-deployment service-b --expose 8081:80
# 再使用编辑器debug启动web服务,这样就可以本地debug集群中的请求了
  1. 如果需要集群中的环境变量

    • 5.1 安装EnvFile插件并重启Goland

    • 5.2 使用telepresence –swap-deployment service-b –expose 8081:80后;将环境变量写入文件env > k8s.env

    • 5.3 编辑debug启动项 图示