1. 前言
本文记录使用K8S过程中遇到的问题、解决办法和一些原理。
问题排查方法参考《kubectl命令——故障排查篇》。
2. kubelet不停重启
2.1. 问题描述
K8S的一个worker节点磁盘不足,关机进行磁盘扩容,物理扩容后开机,执行esize2fs /dev/vdb
,扩容完成。
docker ps
,发现没有容器被启动。kubectl status kubelet
,发现kubelet不停进行重启,每次都启动失败。kubectl status docker
,正常docker正常running。
重启机器,问题依旧。
2.2. 排查解决
1 | journalctl -xeu kubelet -r |
kubelet日志没有报错,docker日志中报错:
1 | level=error msg="xxx cleanup: failed to delete container from containerd: no such container |
FROM ChatGPT:
该错误日志表示 Docker 清理容器时失败,原因是没有找到相应的容器。
可能原因及解决方法:
- 容器不存在:检查容器是否已被删除或者已经退出,如果是则不需要处理该错误。
- 容器正在运行:如果容器正在运行,可能是由于正在执行某些任务而无法清理。此时可以尝试停止容器后再进行清理。
- Docker daemon 出现故障:在某些情况下,Docker daemon 可能会出现故障导致无法清理容器。尝试重启 Docker daemon 可能会解决问题。
- 操作系统出现故障:在某些情况下,操作系统可能会出现故障导致无法清理容器。尝试重启操作系统可能会解决问题。
解决办法:手动清理容器,然后重启机器。
1 | docker container prune |
3. 新增节点flannel启动失败
3.1. 问题描述
K8S集群新增了一个节点,flannel pod自动调度上去了,但是并没有启动成功。
查看kubelet日志,报错为:
[failed to find plugin “flannel” in path [/opt/cni/bin]]
W0523 20:49:19.343813 12586 cni.go:239] Unable to update cni config: no valid networks found in /etc/cni/net.d
3.2. 解决办法
从其他正常节点拷贝一个flannel文件到这个问题节点上的 /opt/cni/bin 目录。
4. 节点上的pod被驱逐
4.1. 问题描述
因为磁盘压力,节点上的pod被驱逐了。但是,实际上节点还有很多磁盘空间。
4.2. 解决办法
1、查找kubelet配置文件路径
1 | systemctl status kubelet -l |
找到Drop-In配置文件路径,一般为:
1 | /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf |
2、修改kubelet配置文件
配置文件中添加:
1 | KUBELET_EXTRA_ARGS="--eviction-hard=memory.available<100Mi,nodefs.available<5%,imagefs.available<15%,nodefs.inodesFree<5%" |
3、重启kubelet
1 | systemctl daemon-reload |
4.3. 扩展阅读
节点压力驱逐是 kubelet 主动终止 Pod 以回收节点上资源的过程。
kubelet 监控集群节点的内存、磁盘空间和文件系统的 inode 等资源。 当这些资源中的一个或者多个达到特定的消耗水平, kubelet 可以主动地使节点上一个或者多个 Pod 失效,以回收资源防止饥饿。
在节点压力驱逐期间,kubelet 将所选 Pod 的 PodPhase 设置为 Failed。这将终止 Pod。
我们可以为 kubelet 指定自定义驱逐条件,以便在作出驱逐决定时使用。驱逐条件分为软驱逐条件和硬驱逐条件。
软驱逐条件将驱逐条件与管理员所必须指定的宽限期配对。 在超过宽限期之前,kubelet 不会驱逐 Pod。如果没有指定的宽限期,kubelet 会在启动时返回错误。
硬驱逐条件没有宽限期。当达到硬驱逐条件时, kubelet 会立即杀死 pod,而不会正常终止以回收紧缺的资源。
kubelet 具有以下默认硬驱逐条件:
- memory.available<100Mi
- nodefs.available<10%
- imagefs.available<15%
- nodefs.inodesFree<5%(Linux 节点)
参考文档:节点压力驱逐
5. 节点上的镜像被清理
5.1. 问题描述
节点上的镜像,被清理掉了,但是并没有人进行过手动清理操作,也没有定时任务。
手动拉取镜像,过一段时间还是会被清理掉。
5.2. 问题原因
参考文档:
Kubernetes 对节点上的所有镜像提供生命周期管理服务,这里的所有镜像是真正意义上的所有镜像,不仅仅是通过 Kubelet 拉取的镜像。当磁盘使用率超过设定上限 HighThresholdPercent 时,Kubelet 就会按照 LRU 清除策略逐个清理掉那些没有被任何 Pod 容器(包括已经死亡的容器)所使用的镜像,直到磁盘使用率降到设定下限 LowThresholdPercent 或没有空闲镜像可以清理。此外,在进行镜像清理时,会考虑镜像的生存年龄,对于年龄没有达到最短生存年龄 MinAge 要求的镜像,暂不予以清理。
在磁盘使用率超出设定上限后:首先,通过 CRI 容器运行时接口读取节点上的所有镜像以及 Pod 容器;然后,根据现有容器列表过滤出那些已经不被任何容器所使用的镜像;接着,按照镜像最近被使用时间排序,越久被用到的镜像越会被排在前面,优先清理;最后,就按照排好的顺序逐个清理镜像,直到磁盘使用率降到设定下限(或者已经没有空闲镜像可以清理)。
需要注意的是,Kubelet 读取到的镜像列表是节点镜像列表,而读取到的容器列表却仅包括由其管理的容器(即 Pod 容器,包括 Pod 内的死亡容器)。因此,那些用户手动 docker run 起来的容器,对于 Kubelet 垃圾回收来说就是不可见的,也就不能阻止对相关镜像的垃圾回收。当然,Kubelet 的镜像回收不是 force 类型的回收,虽然会对用户手动下载的镜像进行回收动作,但如果确实有运行的(或者停止的任何)容器与该镜像关联的话,删除操作就会失败(被底层容器运行时阻止删除)。
影响镜像垃圾回收的关键参数有:
1 | --image-gc-high-threshold:磁盘使用率上限,有效范围 [0-100],默认 85 |
需要注意的是,1.21 版本之后 image-gc-high-threshold 替换为了 eviction-hard,image-gc-low-threshold 替换为了 eviction-mininum-reclaim。
6. 业务服务响应很慢
6.1. 问题描述
某个业务服务的Pod响应很慢,发现它的requests资源配置很低,limits资源配置很高。
调大requests后响应速度明显变快了,是什么原理?
6.2. 原理解析
requests是长期允许,保证资源;limits是临时允许,并不保证资源。
上面的问题中,因为requests配置的很低,所以只能保证requests中配置的资源,并不能保证用到用到limits中配置的资源。
6.3. 扩展阅读
“requests”和”limits”在Kubernetes中的原理是通过Linux的cgroups(control groups)来实现资源管理和隔离。cgroups是Linux内核提供的一种机制,它允许对进程组进行资源限制、优先级调整和统计。Kubernetes利用cgroups将资源限制和隔离应用到容器级别。
“requests”定义了容器所需的最小资源数量。Kubernetes调度器使用这个值来决定在哪个节点上运行容器,并确保节点上有足够的资源满足容器的请求。”requests”的目的是为了确保容器能够正常运行而不会遇到资源不足的问题。
而”limits”定义了容器允许使用的资源的上限。Kubernetes使用这个值来监控容器的资源使用情况,并保护节点的稳定性。如果容器试图使用超过其限制的资源量,Kubernetes会采取相应的措施,如终止容器或重新调度到其他节点。”limits”的目的是为了防止容器使用过多的资源,从而保护整个集群的稳定性。
尽管可以在容器中设置超过”requests”的资源使用量,但这并不是一个推荐的做法。当容器超过其”requests”的资源使用量时,它可能会影响其他容器的性能,导致资源竞争和不稳定的情况。超过”requests”的使用量只是暂时允许,Kubernetes会尽力满足容器的需求,但不保证持续提供额外的资源。
7. 节点资源充足但是无法调度
7.1. 问题描述
某个节点CPU、内存资源充足,也没有污点和亲和性配置,但是Pod无法调度到上面。
7.2. 排查解决
除了检查资源之外,再检查下节点上Pod数量的限制。
1 | kubectl describe node node01 |
Non-terminated Pods
要小于 Allocatable.pods
,如果Pod数量已经达到了节点上Pod数量限制,那么需要调大这个上限。
1 | vim /var/lib/kubelet/config.yaml # maxPods默认110,调大它 |
8. kubectl top命令执行报错
8.1. 问题描述
执行kubectl top pod
,报错:
error: Metrics API not available
在Kubernetes Dashboard上,也发现Pod的CPU使用率和内存使用都无法显示。
8.2. 问题分析
参考kubectl top node error: metrics not available yet可知,之所以出现上面的问题,是因为K8S集群没有安装 metrics-server 。
8.3. 解决办法
解决办法:安装 metrics-server 。
通用安装方法:
1 | wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml |
如果是sealos安装的K8S集群,那么可以使用 metrics-server 集群镜像安装。
1 | sealos run labring/metrics-server:v0.6.2 --cmd="\ |
其中 /root/metrics-server/values.yaml 内容为:
1 | defaultArgs: |
9. kubectl get响应慢
9.1. 问题描述
执行 kubectl get xxx
,响应很慢,十几秒,总会几条出现提示:
1 | I0819 11:17:11.769943 2075052 request.go:668] Waited for 1.159893511s due to client-side throttling, not priority and fairness, request: GET:https://192.168.56.101:6443/apis/enterprisesearch.k8s.elastic.co/v1beta1?timeout=32s |
而且每次request后面的内容都不同。
9.2. 解决办法
解决办法:kube-apiserver 的启动参数中添加 --feature-gates=APIPriorityAndFairness=false
具体操作方法:
1 | # master节点 |
添加启动参数:
1 | spec: |
但是,上面的办法只能解决部分问题。kubectl get pod
正常了,但是kubectl get all
还是有问题。
终极解决办法:升级kubectl到v1.22版本以上。从提示其实也能看出是 client-side 侧的限流,但是 kubectl 并没有修改限流配置的方法,只能升级版本。
参考文档:
- Kubectl Error - Waited for … due to client-side throttling, not priority and fairness, request
- API Priority and Fairness
- Crossplane 支持的自定义资源数量突破了 Kubernetes 的限制
- How to avoid “Waited for Xs due to client-side throttling, not priority and fairness”
- kubectl get all - command return - Throttling request
- k8smaster-请求受到了节流
- kube-apiserver
10. 某个节点无法访问coredns
10.1. 问题描述
新增了一个节点X,处于Ready状态,但是发现节点X和coredns不通。
具体表现为 telnet 10.96.0.10 53
不通,nslookup www.baidu.com 10.96.0.10
也无法得到解析结果。
与此同时,节点A是正常的,telnet 10.96.0.10 53
通,nslookup www.baidu.com 10.96.0.10
可以得到解析结果。
10.2. 问题排查解决
1、检查节点状态
所有节点都处于Ready状态。
2、检查pod网络组件
查看节点X的flannel和kube-proxy,都运行正常。
3、确认问题边界
- 节点X ping 节点A和节点B,通
- 节点X telnet 另外的 service,不通
- 节点X ping coredns pod ip,不通
- 节点X ping 本机 pod ip,通
- 节点X ping 节点A pod ip,通
- 节点X ping 节点B pod ip,不通
这就有意思了,节点X和主机A pod通,和主机B pod不通,大概率是CNI的问题。
4、检查所有主机的cni插件
1 | kubectl get nodes |
10个节点,发现只有5个节点有flannel,但是这些没有flannel的节点也处于Ready状态,也是个bug。
继续排查发现没有flannel的节点存在污点,因此给flannel添加容忍,使每个节点都部署上CNI插件。
至此,问题解决。
10.3. 根因分析
CNI插件的根本作用是调整节点上网络的转发规则。
虽然节点X上的CNI插件正常,但是有5个节点缺少CNI插件,那么当节点X上调整网络转发规则时,会漏掉这5个节点上的pod,也就是说节点X上没有网络转发规则可以访问到它们。
11. 某个节点上的pod全部pending
11.1. 问题描述
节点X处于Ready状态,pod也可以调度到上面,但是所有调度到上面的pod全部处于pending状态,也没有任何events输出。
11.2. 解决办法
解决办法:重启节点X的kubelet。
12. read eth0/speed: invalid argument
12.1. 问题描述
个别GPU节点上,运行 gpu-feature-discovery 报错:
1 | E0927 10:43:40.329641 1 network.go:146] failed to read net iface attribute speed: read /host-sys/class/net/eth0/speed: invalid argument |
登录GPU节点,执行:
1 | cat /host-sys/class/net/eth0/speed |
同样会报错 invalid argument
12.2. 解决办法
升级内核。
参考文档:
13. 无法删除pod情况一
13.1. 问题描述
一些Pod处于Terminating状态,但是一直无法被删除。
使用--force
和--grace-period
强制删除,会报出警告:
1 | warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely. |
13.2. 解决办法
1 | kubectl describe pod xxx -n yyy |
可以看到具体的pod无法被删除的原因,比如:
1 | Warning Unhealthy 12s (x3182 over 8h) kubelet Readiness probe errored: rpc error: code = Unknown desc = Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? |
根据提示检查docker状态,发现docker没有正常运行,启动它即可。
14. 无法删除pod情况二
14.1. 问题描述
一些Pod处于Terminating状态,但是一直无法被删除。
使用--force
和--grace-period
强制删除,依然会卡住,无法删除。
14.2. 解决办法
1 | kubectl describe pod xxx -n yyy |
依然看不到无法删除pod的原因,只能看到Status为Terminating,State为Terminated,Reason为Error。
解决办法:编辑pod,删除 metadata.finalizers 字段。
参考文档:Finalizers
15. 无法删除CRD
15.1. 问题描述
1 | kubectl delete crd ingresses.networking.internal.knative.dev |
卸载knative时,删除CRD ingresses.networking.internal.knative.dev ,无法删除。
15.2. 解决办法
1 | kubectl edit crd ingresses.networking.internal.knative.dev |
删除其中的 metadata.finalizers 字段。
参考文档:Finalizers
16. 日志不存在
16.1. 问题描述
systemctl status kubelet
,发现大量报错:
1 | 11月 28 15:48:31 node1 kubelet[1663]: E1122 15:48:31.502542 1663 cri_stats_provider.go:669] "Unable to fetch container log stats" err="failed to get fsstats for \"/var/log/pods/calico-system_csi-node-driver-jbf9l_969616b6-784a-4154-8161-24206f4501cc/calico-csi/21.log\": no such file or directory" containerName="calico-csi" |
16.2. 问题排查解决
查看报错中的日志路径:
1 | /var/log/pods/calico-system_csi-node-driver-jbf9l_969616b6-784a-4154-8161-24206f4501cc/calico-csi/21.log -> /var/lib/docker/containers/8b352f0c0582b0c048449fef8305fde15ce4017dbb37abfaedcd698e9e1d2ffb/8b352f0c0582b0c048449fef8305fde15ce4017dbb37abfaedcd698e9e1d2ffb-json.log |
日志路径是一个软链,而真实日志已经不存在了。
解决办法为删除所有失效软链:
1 | find /var/log/pods -type l ! -exec test -e {} \; -print |
然后重启kubelet
1 | systemctl restart kubelet |
17. 流量经过ingress偶发502问题
17.1. 问题描述
100个并发压测一个接口,直接压测service,全部200;通过域名压测时,无论是在内网压测还是外网压测,都会出现1%的502。
服务pod日志中,没有502。
ingress access.log 中,出现502。
ingress errer.log 中,出现104。
1 | 2023/12/09 02:35:50 [error] 7960#7960: *60866823 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 172.20.0.100, server: test.voidking.com, request: "POST /api/v1/user/login HTTP/1.1", upstream: "http://100.107.80.144:80/api/v1/user/login", host: "test.voidking.com" |
17.2. 问题排查解决
1、调整服务pod资源、ingress pod资源、coredns pod资源,都没有效果。
2、去掉tls证书,没有效果。
3、调整ingress内核参数,没有效果。
4、调整ingress upstream-keepalive-timeout
参数为 4 ,502数量降低到了 0.1% ,效果明显!调整 ingress upstream-keepalive-timeout
参数为 30,502数量降低到了 0.1% 。
注意:要在ingress controller的configMap中修改 upstream-keepalive-timeout
配置,而不是ingress的annotations(经验证无效)。
参考文档:
17.3. 扩展阅读
502错误是网关错误,504错误是网关超时。
有个比较好的比喻:502是电话打通没人接,504是电话打不通。
什么是keepalive?HTTP/1.1中的Keep-Alive是一种机制,它允许在单个TCP连接上发送多个HTTP请求和响应,而不需要为每个请求/响应对都建立一个新的连接。在HTTP/1.0中,每个HTTP请求都需要建立一个新的TCP连接,这会导致一些性能上的开销。HTTP/1.1引入了Keep-Alive以解决这个问题。
那么 keepalive_timout 和 502 错误之间有什么关系?因为网站的架构不是浏览器直接连接后端的应用服务器,而是中间有nginx服务器做反向代理,浏览器和nginx服务器之间建立keepalive连接,nginx再和后端的应用服务器建立keepalive连接,所以这是两种不同的keepalive连接。
我们把浏览器和nginx之间的keepalive连接叫做ka1,把nginx和应用服务器之间的keepalive连接叫做ka2。如果ka1的超时设置为100秒,也就是说如果100秒之内没有新内容要传输,就把nginx和浏览器之间的连接断掉。而同时,我们把ka2设置为50秒,也就是说如果nginx和应用服务器之间没有新内容要传输,那么就把应用服务器和nginx之间的连接断掉。那么这时候就会产生一个问题:前50秒没有传输内容,在第51秒的时候,浏览器向nginx发了一个请求,这时候ka1还没有断掉,因为没有到100秒的时间,所以这是没有问题的,但是当nginx试图向应用服务器发请求的时候就出问题了,ka2断了!因为ka2的超时设置是50秒,这时候已经超了,所以就断了,这时候nginx无法再从应用服务器获得正确响应,只好返回浏览器502错误!
因此,解决办法也就明确了:让ka1小于ka2。
18. udp包问题
18.1. 问题描述
1 | ffprobe rtsp://user:password@192.168.56.200:8080/api/to/stream |
在宿主机上执行上面这条命令,可以正常获取到视频流。
启动一个容器,执行上面这条命令,可以正常获取到视频流。
使用同一个镜像启动Pod,执行上面这条命令,获取到视频流时会卡住。
正常输出:
1 | ffprobe version 4.2.7-0ubuntu0.1 Copyright (c) 2007-2022 the FFmpeg developers |
卡住的输出:
1 | ffprobe version 4.2.7-0ubuntu0.1 Copyright (c) 2007-2022 the FFmpeg developers |
18.2. 解决办法
指定 tcp 可以正常获取到视频流。
1 | ffprobe rtsp://user:password@192.168.56.200:8080/api/to/stream -rtsp_transport tcp |
从问题表现,只能推测出calico网络插件对于udp包的处理存在问题,具体原因还需要探索。
19. 卸载istio后无法创建pod问题
19.1. 问题描述
卸载istio后,创建了一个deployment,但是k8s无法创建出这个deployment对应的pod,到不了调度阶段,看不到pod。
查看deployment的描述,发现报错:
1 | Warning FailedCreate 24m (x17 over 29m) deployment-controller Error creating: Internal error occurred: failed calling webhook "rev.object.sidecar-injector.istio.io": Post "https://istiod.istio-system.svc:443/inject?timeout=10s": no endpoints available for service "istiod" |
19.2. 原因分析
出现这个问题的原因是卸载 Istio 后,ValidatingWebhookConfiguration 还保留在 Kubernetes 系统中。当 Kubernetes API server 内部试图调用 webhook 但无法找到相应的 webhook 服务端点时,会出现此错误。
19.3. 解决办法
1、列出k8s集群中所有的 MutatingWebhookConfiguration 和 ValidatingWebhookConfiguration
1 | kubectl get mutatingwebhookconfigurations |
找到与 Istio 相关的 webhook 配置。
2、删除与 Istio 相关的 webhook 配置
1 | kubectl delete mutatingwebhookconfigurations <your-mutating-webhook-config-name> |
删除这些 webhook 配置之后,deployment 对应的 pods 就能够正常创建了。
20. pod网段、service网段与docker网段冲突问题
20.1. 问题描述
部署k8s时规划网段不合理,给pod或service规划的网段为 172.17.0.0/16 ,刚好和docker的默认网段 172.17.0.0/16 冲突了。
1 | ip addr show docker0 |
20.2. 解决办法
如果刚开始部署k8s集群就发现这个问题,那么给pod或service修改一个网段,重新部署即可。
如果已经使用了一段时间后才发现这个问题,那么修改起来就比较麻烦了。这里有两个解决办法:
方法一:修改docker默认网段(验证可行)
1、停止kubelet和docker
1 | systemctl stop kubelet |
2、编辑docker配置
1 | vim /etc/docker/daemon.json |
添加一行docker网关ip配置:
1 | "bip": "192.168.254.1/24", |
3、启动docker和kubelet
1 | systemctl daemon-reload |
4、查看修改后的docker0 IP
1 | ip addr show docker0 |
方法二:修改pod或service的网段(未验证)
参考文档:
- k8s更换svc和pod网段
- How to make the pod CIDR range larger in kubernetes cluster deployed with kubeadm?
- Migrate from one IP pool to another
21. 怎样扩展service网段?
21.1. 问题描述
发现knative controller报错:
1 | failed to create private K8s Service: Internal error occurred: failed to allocate a serviceIP: range is full |
21.2. 解决办法
1、确认serviceIP是否已经用完
1 | kubectl describe pod -n kube-system $(kubectl get pods -n kube-system | grep kube-apiserver | awk '{print $1}') | grep service-cluster-ip-range |
如果发现 --service-cluster-ip-range=10.96.0.0/22
,那么最多可以创建 1022 个 serviceIP。当实际svc数量大于1022时,那么证明serviceIP确实用完了。
2、修改apiserver配置,扩展service网段
在master节点执行:
1 | vim /etc/kubernetes/manifests/kube-apiserver.yaml |
修改 serviceIP 范围为 10.96.0.0/20
3、检查 kube-apiserver 是否重启(配置发生修改时会自动重启)
1 | kubectl get pods -n kube-system | grep kube-apiserver |
4、验证修改
1 | kubectl describe pod -n kube-system $(kubectl get pods -n kube-system | grep kube-apiserver | awk '{print $1}') | grep service-cluster-ip-range |
22. 怎样修改Service NodePort范围?
22.1. 问题描述
在Kubernetes中,默认情况下,NodePort类型的Service可以使用的端口范围是30000-32767。
在某些情况下,我们可能需要使用更大的端口范围,此时该怎样修改Service NodePort的端口范围?
22.2. 修改方法
1、登录master节点,修改 apiserver 配置
1 | vim /etc/kubernetes/manifests/kube-apiserver.yaml |
添加 --service-node-port-range
参数:
1 | - command: |
修改后,会自动重建 apiserver pod
注意:最小端口建议大于1024,这样可以避免占用系统保留端口。
2、查看新的 apiserver pod
1 | kubectl get pod -n kube-system |
23. pvc内容未更新问题
23.1. 问题描述
已知条件:
- 多个pod挂载了同一个pvc
- pvc后端基于cephfs,挂载路径为 /data -> cephfs:/path/to/data
- cephfs挂载到了一台主机A,挂载路径为 /path -> cephfs:/path
问题:在主机A上更新了 /path/to/data 中的内容后,从pod中看,/data 中的内容并没有更新;而新创建的pod,/data 中的内容是有更新的。
23.2. 问题排查解决
同步情况验证:
1、更新主机A /path/to/data 中的内容,发现老的pod /data 中的内容不会更新,新的pod /data 中的内容会更新。
2、更新新的pod /data 中的内容,发现老的pod /data 中的内容不会更新,主机A /path/to/data 中的内容会更新。
3、更新老的pod /data 中的内容,发现新的pod /data 中的内容不会更新,主机A /path/to/data 中的内容不会更新,但是其他老的pod /data 中的内容会更新。
以上问题表现,有两个怀疑:1)K8S某些节点有问题,没有处理好cephfs同步问题;2)cephfs存在问题,多副本间没有实现一致性。
但是,检查了K8S节点,没有发现问题;检查cephfs日志,也没有发现问题。
意外发现:老的 pod /data 中内容更新后会同步到主机A上的 /path/to/data.bak 目录!
由此问题就清晰了:有位同学在主机A上更新 /path/to/data 中的内容时,并不是直接修改该目录中的内容,而是直接把该目录重命名为了 /path/to/data.bak,然后重建了一个目录 /path/to/data ,最终导致内容同步出现问题。
这是因为cephfs挂载时读取文件名,会转换成一个统一标志符再进行挂载,哪怕重命名了,挂载的依然是原本的目录,所以老的pod挂载的目录,从 /path/to/data 变成了 /path/to/data.bak ,新的pod挂载的目录是 /path/to/data
24. pod中执行bash速度很慢
24.1. 问题描述
在pod中,执行 bash
会卡住,要10s左右才能执行成功,切到新的bash shell。
24.2. 问题排查解决
1、更换pod镜像,问题依然存在。证明不是镜像的问题。
2、更换Docker版本,升级内核版本,更换操作系统,问题依然存在。证明不是它们的问题。
3、执行bash时抓包,并没有网络流量。证明不是因为访问网络耗时导致的速度慢。
4、执行 bash 时速度慢,执行 sh 时速度很快。证明执行速度慢和命令有关。
5、删除 .profile、.bashrc 等文件,执行 bash 速度快了一些,大概需要 5s 左右。证明 bash 速度慢和 bash 初始化有关。
6、执行 env 发现 pod 中有上万条环境变量,unset 这些环境变量后执行 bash 不再卡住。证明执行 bash 卡住的根本原因是 pod 环境变量过多。
问题原因:k8s中,默认情况下,同一个 namespace 的 service 信息会作为环境变量注入到 pod 中。
解决办法:pod 中不要默认注入 service 信息。
1 | apiVersion: v1 |
此外,同一个namespace下的service过多,还可能引起pod无法启动,报错:
1 | standard_init_linux.go:211: exec user process caused "argument list too long" |
解决办法:pod 中不要默认注入 service 信息。参考文档:standard_init_linux.go:211: exec user process caused argument list too long
25. 服务不可用说明
25.1. 问题描述
当服务A不可用时,怎样给服务A添加一个不可用说明?
25.2. 解决办法
创建一个说明服务B,当服务A不可用时,调整服务A的ingress配置,流量打到服务B。
说明服务B定义参考:xxx-unavailable.yaml
26. 修改Ingress配置不生效问题
26.1. 问题描述
修改了一个 ingress 配置,但是测试发现没有生效。
查看ingress-nginx日志,发现报错:
1 | Failed to determine a suitable ClusterIP Endpoint for Service "default/demo": service "default/demo" does not exist |
26.2. 问题排查解决
问题原因:这个报错的原因是 ingress 中配置使用了 default namespace 中的 demo service,但是这个service已经不存在了。
解决办法:找到使用 demo service 的 ingress,修改或删除它
1 | kubectl get ingress -n default -oyaml | grep demo -A10 |