【图解】Kubernetes Deployment 故障排查指南
DevOps技术栈
共 7428字,需浏览 15分钟
·
2021-04-19 14:58
来源:K8sMeetup社区
太长不看版:下面这张图可以帮助你调试 Kubernetes 中的 Deployment。
Deployment:创建 Pod 副本的方法; Service:内部负载均衡器,将流量路由到 Pod; Ingress:描述流量如何从外部集群流向 Service;
Kubernetes 中应用程序通过内部和外部两层负载均衡器暴露
内部负载均衡器叫 Service,外部负载均衡器叫 Ingress
假设你希望部署一个简单的 Hello World 应用程序,这个应用程序的 YAML 应该类似于如下内容:
何时应使用端口 80,何时应使用端口 8080? 是否应该为每个服务创建一个新端口,以免冲突? 标签(label)名称重要吗?应该保持标签名称一致吗?
令人惊讶的是,Deployment 和 Service 之间根本没有连接。相反,Service 直接指向 Pod,完全跳过了 Deployment。因此,你应该关注的是 Pod 和 Service 之间是如何相互关联的。
请记住以下三件事:
Service selector 应至少匹配 Pod 的一个标签;
Service 的
targetPort
应该与 Pod 的containerPort
匹配;Service 端口可以是任何数字。多个 Service 可以使用同一个端口,因为每个 Service 分配到的 IP 地址不同;
下图总结了如何连接端口:
port
/targetPort
应该是匹配的。track:canary
标签呢?也要匹配上吗?matchLables
selector 呢?它必须始终与 Pod 的标签匹配,Deployment 用它来跟踪 Pod。any-name=my-app
是any-name:my-app
标签。port-forward
命令来连接到 Service 并测试该连接。service
/<service name>
是 service 的名称(在当前的 YAML 文件中是 "my service")。3000 是你想在计算机上开启的端口。 80 是由 Service 在 port
字段中暴露的端口。
Ingress 的 service.port
必须匹配 Service 的port
。Ingress 的 service.name
必须匹配 Service 的name
。
kubectl port-forward
,但是要注意是连接到 Ingress controller 而不是 Service。Service selector 应该和 Pod 的标签匹配; Service 的 targetPort
应该和 Pod 里面容器的containerPort
匹配;Service 端口可以是任意数字。多个 Service 可以使用同一个端口,因为不同的 Service 分配的 IP 地址不同; Ingress 的 service.port
应该和 Service 的port
匹配;Service 的名称应该和 Ingress 中 service.name
字段匹配;
确保 Pod 正在运行; 着重关注让 Service 将流量路由到 Pod; 检查 Ingress 的配置是否正确。
排查 Pod 故障
kubectl logs <pod name>
有助于检索 Pod 中容器的日志;kubectl describe pod <pod name>
对检索与 Pod 相关的事件列表很有用;kubectl get pod <pod name>
可提取 Kubernetes 中存储的 Pod 的 YAML 定义;kubectl exec -ti <pod name> bash
可在 Pod 中的一个容器运行一个交互式命令。
常见的 Pod 报错
ImagePullBackoff ImageInspectError ErrImagePull ErrImageNeverPull RegistryUnavailable InvalidImageName
CrashLoopBackOff RunContainerError KillContainerError VerifyNonRootError RunInitContainerError CreatePodSandboxError ConfigPodSandboxError KillPodSandboxError SetupNetworkError TeardownNetworkError
ImagePullBackOff
镜像名称无效——比如,你拼错了镜像名称,或者镜像不存在。 为镜像指定了一个不存在的标签。 正在检索的镜像属于私有 registry,Kubernetes 没有访问的凭证。
CrashLoopBackOff
应用程序中存在错误,阻止了容器的启动; 容器配置有误:StackOverFlow 上这个问题就是如此 https://stackoverflow.com/questions/41604499/my-kubernetes-pods-keep-crashing-with-crashloopbackoff-but-i-cant-find-any-lo Liveness 探针失败多次。
RunContainerError
挂载不存在的卷,如 ConfigMap 或 Secret; 将只读卷挂载为读写卷。
kubectl describe pod <pod-name>
命令检查和分析这个错误。Pod 处于 Pending 的状态
集群没有足够的资源(例如 CPU 和内存)来运行 Pod。 当前的命名空间具有 ResourceQuota 对象,创建 Pod 将使命名空间超过配额。 该 Pod 绑定了一个处于 Pending 状态的 PersistentVolumeClaim。
kubectl describe
命令中检查事件。Pod 处于未就绪状态
kubectl describe
中的“事件”以验证错误。排查 Service 故障
<ip address:port>
,当 Service 定位到一个 Pod 后,至少应该有一个 Endpoint。正在运行的 Pod 没有正确的标签(应该检查一下是否在正确的命名空间中); Service 的 selector
标签拼写有误。
targetPort
可能出问题了。如何测试 Service 呢?无论什么类型的 Service,都可以用 kubectl port-forward
来连接:<service-name>
是 Service 的名称;3000
是你想在计算机上打开的端口;80
是 Service 暴露的端口。
Pod 在运行中且是就绪状态; Service 可以分发流量分配到 Pod。
service.name
和 service.port
连接到 Service。应该检查一下这些配置是否正确。将 Ingress 暴露到公网的方式; 将集群暴露到公网的方式;
最后,连接到 Pod:
如果解决了,那么就是基础设施问题。你要看一下流量是如何路由到集群的。 如果没有解决,那么是 Ingress controller 的问题,你应该调试 controller。
调试 Ingress Nginx
kubectl ingress-nginx
来进行如下操作:检查日志、Backend、证书等; 连接到 Ingress; 检查当前配置。
kubectl ingress-nginx lint
:用于检查nginx.conf
;kubectl ingress-nginx backend
:用于检查 Backend(类似kubectl describe ingress <ingress-name>
);kubectl ingress-nginx logs
:用于检查日志。
请注意,你可能需要使用 --namespace
为 Ingress controller 指定正确的命名空间。
出现故障的 Job 和 CronJob; StatefulSet 和 DaemonSet。
- END -
公众号后台回复「加群」加入一线高级工程师技术交流群,一起交流进步。
推荐阅读 让运维简单高效,轻松搞定运维管理平台 备份和迁移 Kubernetes 利器:Velero 搭建一套完整的企业级 K8s 集群(v1.20,二进制方式) 记一次 Kubernetes 机器内核问题排查 Shell 脚本进阶,经典用法及其案例 Kubernetes 集群网络从懵圈到熟悉 记一次 Linux服务器被入侵后的排查思路 5个面试的关键技巧,助你拿到想要的offer!
点亮,服务器三年不宕机
评论