暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

kubernetes Pod无法启动问题排查总结

海涛技术漫谈 2019-10-13
2004

一:问题描述

本周,通过 kubernetes
搭建企业级 jupyterhub
服务的时候,遇到个问题: 通过 helm
部署 jupyterhub
的时候, hook-image-puller-b8p5p
这个 pod
一直无法启动,反复于 ErrImagePull
ImagePullBackOff
两个状态,如下

  1. [zhanhaitao@master ~]$ kubectl -n jhub get pods

  2. NAME READY STATUS RESTARTS AGE

  3. hook-image-awaiter-qpsw6 1/1 Running 0 68s

  4. hook-image-puller-b8p5p 0/1 ErrImagePull 0 68s

 

二:系统环境

  1. centos7.1版本

  2. k8s 版本:1.13.2

  3. helm 版本:v2.13.1



  4. k8s集群是参考官网的用户手册通过kubeadm完成搭建的,一个master,一个node



  5. jupyterhub的配置文件:

  6. [zhanhaitao@master ~]$ cat config.yaml

  7. proxy:

  8. secretToken: ebcf616d2ae617e67bf8d5c93c4b131abb25adf5849d68a5be51bc922ef072c7

  9. https:

  10. enabled: false



  11. 部署命令:

  12. [zhanhaitao@master ~]$ helm upgrade --install jhub jupyterhub/jupyterhub \

  13. > --namespace jhub \

  14. > --version=0.8.2 \

  15. > --values config.yaml

 

三:问题分析

status=ErrImagePull
ImageBackOff
,通过字面分析,应该是 k8s
启动 pod
时候,拉取镜像失败导致。ImageBackOff
k8s
中一个镜像相关的常见问题,一般导致的原因主要有如下几个:1.镜像是本公司的私服镜像 2.镜像写法不对或者版本不对 3.镜像所在仓库无法访问,或者访问超时

3.1 确定具体的问题镜像

下面来分析是上面哪个原先导致,在 k8s
中,大部分的问题,都能通过 logs
describe
两个命令进行分析和定位

# 1. 通过logs验证了猜测,问题是pull image导致

  1. [zhanhaitao@master ~]$ kubectl -n jhub logs hook-image-puller-b8p5p

  2. Error from server (BadRequest): container "pause" in pod "hook-image-puller-b8p5p" is waiting to start:

  3. trying and failing to pull image




  4. # 2. 然后通过describe查明问题所在

  5. # 考虑篇幅,仅仅贴出了关键的信息

  6. [zhanhaitao@master ~]$ kubectl -n jhub describe pod hook-image-puller-b8p5p

  7. Containers:

  8. pause:

  9. Container ID:

  10. Image: gcr.io/google_containers/pause:3.0

  11. Image ID:

  12. Port: <none>

  13. Host Port: <none>

  14. State: Waiting

  15. Reason: ImagePullBackOff

  16. Events:

  17. Type Reason Age From Message

  18. ---- ------ ---- ---- -------

  19. Warning Failed 7m24s (x2 over 7m56s) kubelet, tx-phxmlp-demo-k8s-staging01.mt Failed to

  20. pull image "gcr.io/google_containers/pause:3.0": rpc error: code = Unknown desc = Error response from daemon:

  21. Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while

  22. awaiting headers)




  23. # 通过上面的信息,明确了是 gcr.io/google_containers/pause:3.0 镜像拉去失败导致

3.2 确定镜像失败原因

镜像明确后,接下来就是分析为什么这个镜像会拉取失败,

如果对 docker
有一定的了解的话,看到 gcr.io
这个镜像前缀,就知道原因了,中国大概率是无法访问 gcr.io
相关镜像网站的

但是,这里我认为可能并不是每个人都知道这个先验知识,可能部分同学就是简单的操作官网的手册,参照着部署的,不一定具备相关的理论知识

下面,我们分析,镜像失败的原因,首先,看前缀,可以确定不是私服导致的,其实 pause
镜像是 k8s
的底层基础镜像,第三节会简单介绍下

其次,我们的部署配置 config.yaml
并没有这个镜像,所以这个镜像也不是我们拼写或者版本写错导致,所以,只能是网络问题

  1. # 通过本地pull下,发现确实是网络问题导致

  2. [zhanhaitao@master ~]$ sudo docker pull gcr.io/google_containers/pause:3.0

  3. Error response from daemon: Get https://gcr.io/v2/: net/http: request canceled while waiting for connection

  4. (Client.Timeout exceeded while awaiting headers)

 

四:问题解决

4.1 pause 镜像简介

k8s
中,服务是运行在一个个的 Pod
中,一个 Pod
包含一个或多个 container
container
中则根据指定的 docker images
运行着具体的服务( runtime container
可以不是 docker
,可以是其他容器技术,这里通过 docker
举例), pod
k8s
的最小调度单位,如下图示意

k8s
通过 kubelet
这个组件管理着 Pod
的生命周期, pause
正是每个 Pod
启动时,最开始加载的镜像,用于管理这个 Pod
的网络和命名空间,官方介绍如下:The image whose network/ipc namespaces containers in each pod will use. This docker-specific flag only works when container-runtime is set to docker. (default "k8s.gcr.io/pause:3.1")

正是这个镜像的拉取失败,导致整个 Pod
无法启动

4.2 解决办法

问题明确,背景知识也了解后,现在就是怎么解决问题了

1. 通用的解决办法

  1. # 对于docker由于网络问题无法拉取的问题,较为通用的解决方法主要是:

  2. # 本地取其他镜像源下载,然后替换名字,如下所示

  3. # 这样拉取镜像的时候,发现本地有需要的镜像,就直接使用本地镜像了,避免去网上再次拉取

  4. sudo docker pull docker.io/mirrorgooglecontainers/pause:3.0

  5. sudo docker tag mirrorgooglecontainers/pause:3.0 gcr.io/google_containers/pause:3.0



  6. # 看下image是否改成需要的名字,已经成功本地创建了一个同名的镜像了

  7. [zhanhaitao@master ~]$ sudo docker images|grep pause

  8. mirrorgooglecontainers/pause 3.0 99e59f495ffa 3 years ago 747kB

  9. gcr.io/google_containers/pause 3.0 99e59f495ffa 3 years ago 747kB

2. 更为优雅的办法

第一个方法很方便,但是是类似补丁式的修复,治标不治本。一般适合小规模的镜像问题,或者日常使用,或者是团队没有维护镜像的私服

更为优雅的方式是通过配置私服的方式,通过配置 imagePullSecrets
这个参数,因为我这次不是通过这种方式,就不展开了

具体可以自行Google或者参考:kubernetes troubleshooting

3. 针对pause这个特殊镜像的解决办法

通过前面的 pause
镜像介绍知道,它是Pod的基础架构镜像,所以还可以通过其他特定的方式进行解决,

我们知道, k8s
是通过 kubelet
进行 Pod
管理的, kubelet
启动参数有一个参数 --pod-infra-container-image
就是用来知道 pause
镜像名的,将其换成能够获取到的镜像名即可

  1. # 1. 我们通过 ps -ef 先看下 kubelet的启动命令,发现其默认使用的是 k8s.gcr.io/pause:3.1

  2. [zhanhaitao@master ~]$ ps -ef | grep pause

  3. root 8924 1 0 Oct12 ? 00:12:27 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf

  4. --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --cgroup-driver=systemd

  5. --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.1



  6. # 2. kubelet是配置成了系统服务,我们看下它的状态信息,发现其配置文件是/etc/systemd/system/kubelet.service.d下的10-kubeadm.conf

  7. [zhanhaitao@master ~]$ systemctl status kubelet

  8. kubelet.service - kubelet: The Kubernetes Node Agent

  9. Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: disabled)

  10. Drop-In: /etc/systemd/system/kubelet.service.d

  11. └─10-kubeadm.conf

  12. Active: active (running) since Sat 2019-10-12 11:48:52 CST; 1 day 2h ago

  13. Docs: https://kubernetes.io/docs/

  14. Main PID: 8924 (kubelet)

  15. Memory: 82.3M

  16. CGroup: /system.slice/kubelet.service

  17. └─8924 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/k...



  18. # 3. 查看启动配置文件,已经查看里面配置的环境目录,可以找到pause的版本指定在:/var/lib/kubelet/kubeadm-flags.env 中

  19. [zhanhaitao@master kubelet.service.d]$ cat 10-kubeadm.conf

  20. # Note: This dropin only works with kubeadm and kubelet v1.11+

  21. [Service]

  22. Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"

  23. Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"

  24. # This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically

  25. EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env

  26. # This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use

  27. # the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.

  28. EnvironmentFile=-/etc/sysconfig/kubelet

  29. ExecStart=

  30. ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS



  31. # 4. 将pause镜像改为指定的版本

  32. [zhanhaitao@master kubelet.service.d]$ sudo cat /var/lib/kubelet/kubeadm-flags.env

  33. KUBELET_KUBEADM_ARGS=--cgroup-driver=systemd --network-plugin=cni --pod-infra-container-image=docker.io/mirrorgooglecontainers/pause:3.1



  34. # 5. kubelet服务重启

  35. [zhanhaitao@master kubelet.service.d]$ sudo systemctl restart kubelet.service


文章转载自海涛技术漫谈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论