• k8s-[排查记录]解决节点无法查看pod日志


    解决k8s某节点无法查看pod日志问题

    问题描述

    生产环境:

    • k8s版本:v1.17.9
    • 集群:三台master,一台worker,使用kubeadm部署

    问题现象:

    master执行 kubectl logs 出现下面错误:

    error: You must be logged in to the server (the server has asked for the client to provide credentials (pods/log xxx))
    

    通过k8sClient请求apiserver /api/v1/namespaces/{namespace}/pods/{name}/log 时,同样不行。

    但是执行 kubectl get pods 或者 请求 GET /api/v1/namespaces/{namespace}/pods 能正常返回结果。

    换个节点,在master2上执行 kubectl logs ,能正常返回。

    排查过程

    首先盲猜大概率就是该节点证书的问题。

    但不久前集群证书已经通过 kubeadm alpha certs renew all 更新过了,再次通过 kubeadm alpha certs check-expiration 查看证书日志,是没问题的。

    难道是该节点的kubectl config没更新,于是在出错节点更新config cp -f /etc/kubernetes/admin.conf ${HOME}/.kube/config,网上还有些说使用 export KUBECONFIG=/etc/kubernetes/admin.conf 来更新。

    发现还是没用。

    仔细想想,这个跟kubectl确实是没关系的,因为绕过kubectl直接请求api时也出现了问题。

    所以问题应该就是在 kubelet与api-server 交互上。

    • 检查kubelet日志 systemctl status kubelet,虽然有一些错误日志,但没看到一些有用的关键信息。

    • 那可能就是 kube-apiserver 服务证书没更新,于是找到对应节点的 apiserver 的pod,执行:

      kubectl -n kube-system delete pod kube-apiserver-xxxx
      

    很奇怪,还是不行?而且重启后这个pod看似重启了,但数据好像没更新(我看到该pod的重启次数没刷新)。

    那就直接使用docker查看 docker ps |grep kube-apiserver,果然,该容器的UP时间都没刷新。

    最终杀手锏,暴力重启 docker restart containerID

    问题就解决了!

    原因分析

    排查了我老半天,而且是带着半信半疑排查解决的,总结一下这个问题:

    为什么获取pod列表就可以,获取pod日志就不行?

    • 首先无论是kubectl还是使用k8sClient,实质都是请求apiserver进行交互的,认证信息都在~/.kube/config里。

    • 为了缓解各模块对API Server的访问压力,kubelet会定期从从 API Server 获取指定的资源对象信息(LIST/WATCH方法)保存到etcd。

    • 获取pod列表实际是通过apiserver访问etcd里的数据;而查看pod日志需要通过 apiserver -> kubelet -> CRI(containerd)。中间apiserver与kubelet的交互需要证书验证。

    为什么直接删掉kube-apiserver pod达不到重启的效果,需要docker restart

    • 默认情况下kubelet是会定时扫描/etc/kubernetes/manifests(kubeadm默认目录,或通过 --pod-manifest-path 来指定目录),然后根据这个文件夹下的 YAML/JSON 文件来创建/删除静态 Pod。

    • 也就是说,执行 kubectl delete pod kube-apiserver 时,不是通过apiserver,而是通过Kubelet来删除。

    • kubelet监听到删除事件,只是将mirror pod(annotations里有kubernetes.io/config.mirror的key)标记删除,仅仅删除etcd里的信息,随后又会自动上传static pod信息并重新生成pod。

    所以直接删掉kube-apiserver pod是不会重启真正的容器的。

    为什么证书刚更新过,还需要删除kube-apiserver container证书才能正常?

    • 证书过期了,k8s调度没有问题,只是apiserver与kubelet之间通信的证书没有生效。
    • controller-manager和schduler都是利用的client-go去调用apiserver,是利用kubernetes 的配置文件/etc/kubernetes/路径下的controller-manager.conf和scheduler.conf来进行安全通信。
    • 而apiserver调用kubelet,是通过读取apiserver初始化的配置缓存信息,获取kubelet 的client证书,再进行https的安全通信。
    • 实际上这些k8s组件都没有自动加载证书的功能,但恰巧controller-manager和schduler都重启过。
    • 此时apiserver容器里的证书刚好过期,与 kubelet交互认证失败,所以获取 pod log 或者 exec 会失败。

    所以出现创建、查看和删除资源是没问题;获取pod日志时,apiserver调用kubelet接口时才有问题。

    总结

    更新证书后,除了重启控制节点的kubelet,还需要手动重启 kube-apiserver、kube-controller、kube-scheduler、etcd 这4个容器。

    docker ps | grep -v pause | grep -E "etcd|scheduler|controller|apiserver" | awk '{print $1}' | xargs docker restart
    

    参考资料

    kubelet之cri演变史

    Kubectl exec 背后到底发生了什么?

    关于Kubernetes证书的那点事

  • 相关阅读:
    团队项目个人工作总结(4.27)
    团队项目个人工作总结(4.26)
    团队项目个人工作总结(4.25)
    评测—输入法
    学习进度(2016.4.24)
    团队项目个人工作总结(4.24)
    团队项目个人工作总结(4.23)
    第一阶段冲刺(第四天)
    典型用户和用户场景描述
    第一阶段冲刺(第三天)
  • 原文地址:https://www.cnblogs.com/wzs5800/p/15085193.html
Copyright © 2020-2023  润新知