Kubernetes 运维手册-Pod - Service - Ingress 常见问题排查_第1页
Kubernetes 运维手册-Pod - Service - Ingress 常见问题排查_第2页
Kubernetes 运维手册-Pod - Service - Ingress 常见问题排查_第3页
Kubernetes 运维手册-Pod - Service - Ingress 常见问题排查_第4页
Kubernetes 运维手册-Pod - Service - Ingress 常见问题排查_第5页
已阅读5页,还剩60页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Kubernetes运维手册

Pod·Service·Ingress常见问题排查

从现象到根因的系统化排障路径

10大章节·60+排障命令·40个真实场景

云原生运维实战系列

目录

第一章Kubernetes排障方法论与工具链

第二章Pod生命周期与状态诊断

第三章Pod常见异常排查(上)

第四章Pod常见异常排查(下)

第五章Service工作原理与访问链路

第六章Service常见问题排查

第七章Ingress配置与问题排查

第八章DNS解析与网络连通性排查

第九章资源、调度与存储问题排查

第十章综合排障实战与速查表

Kubernetes运维手册·Pod/Service/Ingress常见问题排查

第一章Kubernetes排障方法论与工具链

1.1排障的核心思路

Kubernetes的排障与传统的单机运维有本质区别。传统的运维模式中,服务是长期驻留在某台机器上的,出问

题可以直接登录主机查看进程、日志、配置。而在Kubernetes中,Pod会被调度到不同节点、随时被重建、IP每次

都在变化,如果还沿用"登上去看看"的思路,会非常低效。

正确的排障思路是围绕声明式对象展开的。每一个Pod、Service、Ingress都是一个期望状态的声明,控制器

持续对比实际状态与期望状态,驱动系统向期望状态收敛。因此,当出现问题时,第一件事是查看对象的"状态"字

段和"事件",而不是去节点上找进程。

可以把排障分为四个阶段。第一阶段,确认现象:用户看到的是什么,是访问不通,还是访问慢,还是部分用

户受影响。第二阶段,定位层次:问题出在Pod、Service、Ingress、DNS、节点、还是底层网络。第三阶段,收集

证据:用kubectldescribe、kubectllogs、kubectlexec、kubectlgetevents等命令获取对象状态。第

四阶段,验证假设:做出修改后重新测试,确认问题是否解决。

1.2必备命令工具链

熟练掌握以下命令,能覆盖90%以上的排障场景。

命令用途关键选项

kubectlget列出资源-owide、-oyaml、-w实时监视

kubectldescribe查看对象详情与事件排障第一命令,重点看Events段

kubectllogs查看Pod日志-f、--previous、-c指定容器

kubectlexec在容器内执行命令-it--sh进入交互式shell

kubectlport-forward端口转发到本地用于本地调试远端服务

kubectlgetevents查看集群事件--sort-by='.lastTimestamp'按时间排序

kubectltop查看资源使用pod/node,需要metrics-server

kubectlcp复制文件在本地与容器之间传输文件

kubectlauthcan-i检查权限--as模拟其他用户

kubectldebug调试容器注入临时容器,用于无shell镜像

#查看所有命名空间的Pod

kubectlgetpods-A

#查看Pod详细信息(含事件)

kubectldescribepodmyapp-7d4f8b6c9-x2k4m-nproduction

#实时查看日志

kubectllogs-fmyapp-7d4f8b6c9-x2k4m-nproduction

#查看上次崩溃的日志(容器重启后,前一次日志)

kubectllogsmyapp-7d4f8b6c9-x2k4m-nproduction--previous

#多容器Pod指定容器

kubectllogsmyapp-7d4f8b6c9-x2k4m-csidecar-nproduction

#进入容器

kubectlexec-itmyapp-7d4f8b6c9-x2k4m-nproduction--sh

#本地端口转发到Pod(用于本地测试)

kubectlport-forwardpod/myapp-7d4f8b6c9-x2k4m8080:8080-nproduction

#查看最近5分钟的事件,按时间排序

kubectlgetevents-nproduction--sort-by='.lastTimestamp'

#查看Pod资源使用(需要metrics-server)

kubectltoppod-nproduction

#用临时容器调试无shell镜像

kubectldebug-itmyapp-7d4f8b6c9-x2k4m\

--image=busybox--target=myapp-nproduction

1.3排障的黄金三问

面对任何Kubernetes问题,先问三个问题,能快速缩小范围。

问题一:Pod是什么状态?用kubectlgetpods查看STATUS列,常见的有Running、Pending、

CrashLoopBackOff、ImagePullBackOff、Error、ContainerCreating等。每种状态对应不同的故障类别。

问题二:Pod的Events里说了什么?用kubectldescribepod查看最下方的Events段。绝大多数问题(镜

像拉取失败、调度失败、探针失败、资源不足)都能从这里直接找到答案。Events保留时间有限,通常1小时,所

以发现问题要第一时间查看。

问题三:Pod的日志里有什么?用kubectllogs查看应用日志。应用层面的错误(配置解析失败、数据库

连接失败、端口被占用)会在日志中体现。如果容器已经崩溃重启,加--previous参数查看上一次运行的日志。

1.4常见状态速查

状态含义常见原因

PendingPod已创建但未调度到节点资源不足、节点选择器不匹配、污点与容忍不匹配、PVC未绑定

ContainerCreatingPod已调度,正在创建容器镜像拉取慢、卷挂载慢、CNI网络配置中

Running容器正在运行正常状态;但可能未通过健康检查

CrashLoopBackOff容器反复崩溃重启应用启动失败、依赖服务不可用、配置错误

ImagePullBackOff镜像拉取失败镜像不存在、仓库认证失败、网络不通

ErrImagePull镜像拉取的瞬间错误同上,通常是ImagePullBackOff的前一个状态

TerminatingPod正在被删除正常删除过程;如果长时间停留,可能有finalizer阻塞

Completed容器正常退出Job类Pod的正常状态

Error容器以非零状态退出应用崩溃、启动脚本失败

Unknown无法获取Pod状态节点失联、kubelet异常

快速定位技巧:kubectlgetpods-A-owide可以一眼看到所有命名空间的Pod状态和所在节点。

kubectlgetpods--field-selector=status.phase!=Running可以过滤出非Running状态的Pod,快速

找出异常实例。

1.5命名空间与上下文管理

生产环境通常有多个命名空间(开发、测试、预发、生产),频繁切换容易出错。建议使用kubectlconfig

set-context预配置上下文,或者使用kubens、kubectx等工具快速切换。

#查看当前上下文

kubectlconfigcurrent-context

#列出所有上下文

kubectlconfigget-contexts

#切换上下文

kubectlconfiguse-contextproduction-cluster

#设置默认命名空间

kubectlconfigset-context--current--namespace=production

#使用kubectx/kubens(需单独安装)

kubectxproduction-cluster

kubensproduction

#临时用其他命名空间执行命令

kubectlgetpods-nstaging

#查看当前用户权限

kubectlauthcan-i--list

#模拟其他用户检查权限

kubectlauthcan-icreatepods--as=developer@-nproduction

生产环境操作的安全习惯:使用kubectldelete前先kubectlget确认目标;批量操作时加--dry-

run=client预演;kubectlapply前先kubectldiff看差异;kubectledit要谨慎,因为它直接修改线

上对象,且不留下审计记录。凡是破坏性操作,先想清楚回滚路径。

第二章Pod生命周期与状态诊断

2.1Pod的生命周期阶段

理解Pod的生命周期是排障的基础。Pod从创建到销毁,会经历几个明确的阶段,每个阶段都有对应的状态和

可能的故障点。

阶段说明失败可能

PendingPod已提交给APIServer,等待调度资源不足、亲和性冲突、PVC未就绪

ContainerCreating调度完成,kubelet正在创建容器镜像拉取失败、卷挂载失败、网络配置失败

Running至少一个容器在运行应用内部错误、探针失败

Succeeded所有容器正常退出且不会再重启Job的期望状态

Failed所有容器已终止,至少一个失败需要检查退出码和日志

Unknown无法获取Pod状态节点失联、kubelet异常

2.2容器状态与重启策略

每个容器有自己的状态:Waiting(等待启动)、Running(运行中)、Terminated(已终止)。容器终止

时的退出码是排查问题的关键线索。

退出码含义排查方向

0正常退出对于长驻服务,可能意味着容器启动后立即退出

1应用级错误应用报错,需查看日志

2shell命令误用启动脚本有语法错误

126命令不可执行文件权限问题或格式错误

127命令未找到入口命令写错,或依赖未安装

137被SIGKILL杀死通常是OOMKiller,内存超限

139段错误底层程序崩溃

143被SIGTERM正常终止收到优雅停止信号,正常行为

#查看容器退出码

kubectldescribepodmyapp-xxx|grep-A5"LastState"

#或用JSON输出查看

kubectlgetpodmyapp-xxx-o

jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}'

#查看重启次数

kubectlgetpods-ocustom-

columns=NAME:.,RESTARTS:.status.containerStatuses[0].restartCount

#按重启次数排序

kubectlgetpods--sort-by='.status.containerStatuses[0].restartCount'

2.3健康检查三种探针

Kubernetes提供三种探针检测容器健康状态。livenessProbe判断容器是否需要重启;readinessProbe判断

容器是否准备好接收流量;startupProbe判断应用是否启动完成(用于启动慢的应用)。

apiVersion:v1

kind:Pod

metadata:

name:myapp

spec:

containers:

-name:app

image:myapp:v1.0

ports:

-containerPort:8080

#启动探针:应用启动阶段使用,成功后开始执行存活/就绪探针

startupProbe:

httpGet:

path:/health

port:8080

failureThreshold:30

periodSeconds:10

#存活探针:失败达到阈值则重启容器

livenessProbe:

httpGet:

path:/health

port:8080

initialDelaySeconds:10

periodSeconds:10

timeoutSeconds:3

failureThreshold:3

#就绪探针:失败则从Service端点摘除

readinessProbe:

httpGet:

path:/ready

port:8080

initialDelaySeconds:5

periodSeconds:5

timeoutSeconds:3

failureThreshold:3

探针配置不当的典型问题:initialDelaySeconds过小,应用还没启动完成探针就失败,导致容器反复重

启;failureThreshold过小,网络抖动就触发重启或摘除;存活探针检查依赖(如数据库连接),一旦依赖

抖动就会导致应用重启雪崩。存活探针应该只检查"自身是否卡死",就绪探针才检查"依赖是否可用"。

2.4探针排查命令

#查看探针最近失败记录

kubectldescribepodmyapp-xxx|grep-A10"Events"

#从节点端查看探针日志(需要登录节点)

#journalctl-ukubelet|grepmyapp

#手动测试探针端点

kubectlexecmyapp-xxx--curl-vhttp://localhost:8080/health

#查看容器是否处于Ready状态

kubectlgetpods-owide

#READY列显示1/1或0/1,0/1表示未通过就绪探针

#从Service端点确认

kubectlgetendpointsmyapp-svc-oyaml

#如果endpoints为空,说明所有Pod都未就绪

2.5常见Pod状态诊断流程

面对一个异常Pod,按以下流程逐层诊断,能快速定位问题。

第一步:kubectlgetpod<name>-owide查看基本状态、所在节点、PodIP。

第二步:kubectldescribepod<name>查看详细信息,重点看Status、Conditions、Events三个部分。

Conditions会告诉你Pod是否Ready、是否调度完成、容器是否初始化。

第三步:kubectllogs<name>--previous查看应用日志,特别是崩溃前的最后几行。

第四步:如果容器还在运行,kubectlexec-it<name>--sh进入容器,手动检查配置、环境变量、网络。

第五步:如果涉及节点问题,kubectldescribenode<node>查看节点状态、资源、污点。

高效排障的秘诀:养成"先看Events"的习惯。Kubernetes的事件系统记录了资源生命周期的所有关键节点,

从调度、拉镜像、启动容器、探针失败到OOM,几乎所有信息都在事件里。90%的问题通过一次kubectl

describe就能定位到方向。

第三章Pod常见异常排查(上)

案例1:Pod一直处于Pending状态

现象:创建Deployment后,Pod一直是Pending,不会进入Running。

排查命令:

#查看Pod状态

kubectlgetpods-owide

#关键:查看describe的Events段

kubectldescribepodmyapp-7d4f8b6c9-x2k4m

#事件中常见的关键信息:

#0/3nodesareavailable:3Insufficientcpu.

#0/3nodesareavailable:3node(s)hadtaint{key:value},

#thatthepoddidn'ttolerate.

#0/3nodesareavailable:3node(s)didn'tmatchPod'snodeaffinity.

#persistentvolumeclaim"myapp-pvc"notfound

#0/3nodesareavailable:3Toomanypods.

常见原因与解决方案:

事件信息根本原因解决方案

Insufficientcpu/memory节点资源不足降低requests、扩容节点、驱逐其他Pod

node(s)hadtaint节点有污点,Pod没有容忍添加tolerations,或移除节点污点

didn'tmatchnodeaffinity节点亲和性不匹配检查nodeSelector、affinity配置

Toomanypods节点Pod数量达到上限调整kubelet的maxPods,或扩容节点

persistentvolumeclaimnotfoundPVC不存在或未绑定检查PVC状态、StorageClass配置

nonodesavailable集群没有可用节点检查节点是否Ready

#检查节点资源使用

kubectldescribenodenode-1|grep-A10"Allocatedresources"

#检查节点污点

kubectldescribenodenode-1|grepTaints

#检查PVC状态

kubectlgetpvc-nproduction

kubectldescribepvcmyapp-pvc-nproduction

#检查Pod的资源请求

kubectlgetpodmyapp-xxx-ojsonpath='{.spec.containers[*].resources}'

案例2:ImagePullBackOff镜像拉取失败

现象:Pod状态显示ImagePullBackOff或ErrImagePull,容器一直无法启动。

#查看详细事件

kubectldescribepodmyapp-xxx|grep-A10"Events"

#典型事件信息:

#Failedtopullimage"/myapp:v1.0":

#rpcerror:code=Unknowndesc=failedtopullandunpackimage:

#failedtoresolvereference:unexpectedstatuscode401Unauthorized

#Failedtopullimage"/myapp:v1.0":

#manifestunknown

#Failedtopullimage"nginx:wrong-tag":notfound

常见原因与解决方案:

错误信息原因解决方案

401Unauthorized私有仓库认证失败创建imagePullSecrets并挂载到Pod

manifestunknown镜像标签不存在确认标签拼写、推送是否成功

notfound镜像名错误检查完整镜像地址

nosuchhostDNS解析失败检查集群DNS、节点resolv.conf

i/otimeout网络不通检查节点到镜像仓库的网络、代理配置

x509:certificatesignedbyunknownauthorityHTTPS证书不受信将CA证书添加到节点信任链

#创建DockerRegistrySecret

kubectlcreatesecretdocker-registrymyregistry-secret\

--docker-server=\

--docker-username=myuser\

--docker-password=mypassword\

--docker-email=myemail@\

-nproduction

#在Pod中引用

apiVersion:v1

kind:Pod

metadata:

name:myapp

spec:

imagePullSecrets:

-name:myregistry-secret

containers:

-name:app

image:/myapp:v1.0

#或者在ServiceAccount上附加(推荐,所有Pod自动使用)

kubectlpatchserviceaccountdefault\

-p'{"imagePullSecrets":[{"name":"myregistry-secret"}]}'\

-nproduction

#手动在节点上测试拉取

#登录到节点执行

#crictlpull/myapp:v1.0

镜像拉取的优化:频繁拉取的镜像可以配置imagePullPolicy:IfNotPresent,避免每次都去远程仓库检

查。固定tag的镜像适合这种策略,而使用:latest标签时,Kubernetes默认使用Always策略,这会带来额

外的网络开销。

案例3:CrashLoopBackOff容器反复重启

现象:Pod状态显示CrashLoopBackOff,RESTARTS列的数字不断增长。

#查看上次崩溃的日志

kubectllogsmyapp-xxx--previous

#查看退出码

kubectldescribepodmyapp-xxx|grep-A5"LastState"

#典型日志信息:

#Error:Cannotfindmodule'/app/server.js'->入口路径错误

#Error:connectECONNREFUSED:5432->依赖服务不可用

#FATAL:passwordauthenticationfailed->配置错误

#panic:runtimeerror:invalidmemoryaddress->程序崩溃

#OOMKilled->内存超限

常见原因与解决方案:

原因排查方向解决方案

启动命令错误检查Dockerfile的ENTRYPOINT/CMD修正启动命令或工作目录

配置缺失检查ConfigMap、Secret是否挂载确保配置对象已创建且正确挂载

依赖服务未就绪应用启动时立即连接数据库添加initContainer等待依赖,或应用内实现重试

内存超限OOM退出码137增加内存limits,或修复应用内存泄漏

健康检查误杀存活探针配置过严调整initialDelaySeconds、failureThreshold

权限问题以非root运行但需要写文件检查securityContext、文件系统权限

端口冲突容器内多个进程监听同一端口修改应用端口配置

#排查OOM:查看Pod的内存限制和实际使用

kubectldescribepodmyapp-xxx|grep-A3"Limits"

kubectldescribepodmyapp-xxx|grep-A3"Requests"

#查看节点上的OOM事件

kubectlgetevents--field-selectorreason=OOMKilling

#分析内存使用曲线

kubectltoppodmyapp-xxx--containers

#使用initContainer等待依赖就绪

apiVersion:v1

kind:Pod

metadata:

name:myapp

spec:

initContainers:

-name:wait-for-db

image:busybox:1.36

command:

-sh

--c

-|

untilnc-zpostgres-service5432;do

echo"waitingforpostgres..."

sleep2

done

containers:

-name:app

image:myapp:v1.0

CrashLoopBackOff的指数退避:Kubernetes在容器反复崩溃时会采用指数退避策略重启,间隔从10秒、20

秒、40秒一直增长到5分钟。这意味着问题发现越晚,重启间隔越长,恢复也越慢。发现问题后不要等待,应

该主动干预。

案例4:容器OOMKilled内存超限

现象:容器被Kubernetes杀死,退出码为137,Pod状态显示OOMKilled。

#确认OOMKilled

kubectldescribepodmyapp-xxx|grep-A5"LastState"

#LastState:Terminated

#Reason:OOMKilled

#ExitCode:137

#查看当前内存使用

kubectltoppodmyapp-xxx--containers

#查看内存requests和limits

kubectlgetpodmyapp-xxx-ojsonpath='{.spec.containers[*].resources}'

解决方案:

第一,短期修复:提高limits.memory。但要留有余地,不要设置得过大(会影响调度和节点稳定性)。第

二,中期修复:用kubectltop、Prometheus、Grafana观察应用的内存使用曲线,找出增长模式。第三,长期修

复:如果是内存泄漏,需要修复应用代码;如果只是峰值内存需求大,可以调整JVM堆大小、Node.js的--max-

old-space-size、Python的GC参数等运行时配置。

#Java应用调整堆大小(容器内存1GB,堆设为768MB)

env:

-name:JAVA_OPTS

value:"-Xms512m-Xmx768m-XX:MaxMetaspaceSize=128m"

#Node.js应用调整堆大小

env:

-name:NODE_OPTIONS

value:"--max-old-space-size=768"

#设置内存requests和limits

resources:

requests:

memory:"512Mi"

cpu:"200m"

limits:

memory:"1Gi"

cpu:"1000m"

requests与limits的差异:requests是调度依据,决定Pod被分配到哪个节点;limits是运行时上限,超

过会触发OOM或CPU限流。二者设置相同时QoS等级为Guaranteed,最稳定;只设置requests时为

Burstable,灵活性好;都不设置时为BestEffort,最容易被驱逐。生产环境的核心服务建议使用Guaranteed或

接近Guaranteed的配置。

第四章Pod常见异常排查(下)

案例5:PodRunning但服务不可用

现象:Pod状态是Running,READY列显示0/1,通过Service访问不到。

#查看PodREADY状态

kubectlgetpods-owide

#NAMEREADYSTATUSRESTARTS

#myapp-xxx0/1Running0<-未通过就绪探针

#查看Pod详情中的Conditions

kubectldescribepodmyapp-xxx|grep-A10"Conditions"

#TypeStatus

#InitializedTrue

#ReadyFalse<-关键

#ContainersReadyFalse

#PodScheduledTrue

#查看探针失败的事件

kubectldescribepodmyapp-xxx|grep-i"readiness\|probe"

常见原因:

第一,就绪探针配置错误,指向的路径或端口不存在;第二,应用启动后初始化时间长,就绪探针在初始化完

成前就开始探测;第三,应用依赖的服务未就绪,导致应用虽然进程存在但无法提供服务;第四,就绪探针检查的

逻辑过于严格,把部分可用的状态也判为不可用。

#手动测试探针端点

kubectlexecmyapp-xxx--wget-qO-http://localhost:8080/ready

#如果容器没有wget/curl,用port-forward

kubectlport-forwardpod/myapp-xxx8080:8080

#另开终端

curlhttp://localhost:8080/ready

#查看应用的启动日志

kubectllogsmyapp-xxx|head-50

就绪探针的最佳实践:就绪探针应该检查应用"是否能正常处理请求",而不是"依赖是否健康"。如果就绪探

针包含数据库连接检查,那么数据库抖动时,Kubernetes会把所有Pod从Service端点摘除,导致整个服务不

可用,形成级联故障。更合理的设计是只检查应用自身状态,让应用层面处理依赖故障(重试、熔断、降

级)。

案例6:Pod无法访问外部网络

现象:Pod内的应用能启动,但无法访问外部的API或数据库。

#在Pod内测试外网连通性

kubectlexec-itmyapp-xxx--sh

#测试DNS解析

nslookup

#如果返回"servercan'tfind",说明DNS有问题

#测试网络连通性

nc-zv443

curl-v

#查看路由

iproute

#默认路由应该指向CNI网桥

#查看DNS配置

cat/etc/resolv.conf

#nameserver应该是kube-dns服务的ClusterIP

#search包含当前命名空间和集群域

常见原因与解决方案:

现象原因解决方案

DNS解析失败CoreDNS异常或Pod的dnsPolicy配置错误检查CoreDNSPod、dnsConfig配置

能解析但连不上网络策略阻止、出站流量被拦截检查NetworkPolicy、云防火墙

部分域名解析失败CoreDNS上游DNS配置问题检查CoreDNSConfigMap中的forward配置

间歇性超时连接数过多、conntrack表满调整sysctl参数、检查conntrack统计

无法访问公网节点没有公网IP或NAT规则检查节点网络、云厂商NAT网关

#查看Pod的DNS配置

kubectlgetpodmyapp-xxx-ojsonpath='{.spec.dnsPolicy}'

#可选值:ClusterFirst(默认)、Default、ClusterFirstWithHostNet、None

#自定义DNS配置

apiVersion:v1

kind:Pod

metadata:

name:myapp

spec:

dnsPolicy:ClusterFirst

dnsConfig:

nameservers:

-

-

searches:

-ernal

options:

-name:ndots

value:"2"

containers:

-name:app

image:myapp:v1.0

#检查CoreDNS

kubectlgetpods-nkube-system-lk8s-app=kube-dns

kubectllogs-nkube-system-lk8s-app=kube-dns--tail=100

#检查CoreDNS配置

kubectlgetconfigmapcoredns-nkube-system-oyaml

ndots参数的坑:默认情况下,Pod的/etc/resolv.conf中ndots:5,意味着任何包含少于5个点的域名,

都会被先当作集群内部域名尝试解析。例如访问,会依次尝试.

<namespace>.svc.cluster.local、.svc.cluster.local、

.cluster.local,最后才按原样查询。这会产生额外的DNS查询,影响性能。访问外部域

名频繁的场景可以将ndots调为2。

案例7:Pod内DNS解析慢

现象:应用响应时间较长,日志中大量DNS查询耗时超过1秒。

#测试DNS查询耗时

kubectlexec-itmyapp-xxx--sh

#单次查询

timenslookupkubernetes.default.svc.cluster.local

#大量查询测试

foriin$(seq110);do

timenslookup

done

#查看resolv.conf

cat/etc/resolv.conf

#查看conntrack表状态

#需要在节点上执行

conntrack-L|wc-l

sysctlfilter.nf_conntrack_count

sysctlfilter.nf_conntrack_max

常见原因:

第一,CoreDNS副本数不足,查询压力大;第二,ndots:5导致多次冗余查询;第三,UDP协议下DNS查询

偶发丢包,触发TCP重试;第四,节点conntrack表满,新连接建立失败。

#扩容CoreDNS(推荐至少2个副本,大规模集群更多)

kubectlscaledeploymentcoredns-nkube-system--replicas=3

#启用CoreDNS缓存(在ConfigMap中)

#检查cache插件是否启用

kubectlgetconfigmapcoredns-nkube-system-oyaml|grep-A5cache

#调整节点的conntrack参数

#/etc/sysctl.d/k8s.conf

filter.nf_conntrack_max=1048576

filter.nf_conntrack_tcp_timeout_established=86400

#应用配置

sysctl--system

案例8:Pod间通信异常

现象:同一命名空间内的两个Pod无法互相访问,但各自访问外部正常。

#从PodA访问PodB

kubectlexec-itpod-a--sh

nc-zvpod-b-ip8080

nc-zvpod-b-service8080

#查看PodB的IP

kubectlgetpodpod-b-owide

#查看PodB是否监听端口

kubectlexecpod-b--netstat-tlnp

#检查NetworkPolicy

kubectlgetnetworkpolicy-nproduction

kubectldescribenetworkpolicymyapp-policy-nproduction

原因表现解决

NetworkPolicy拦截特定方向的流量完全不通添加或修改策略规则

CNI插件异常所有跨节点Pod通信失败重启CNI组件、检查路由

Service未匹配到PodServiceIP不通,但PodIP通检查selector是否匹配Podlabel

Pod不在同一网络跨命名空间访问失败使用完全限定域名space.svc.cluster.local

MTU不匹配小包通、大包超时调整CNI或网卡的MTU

#查看NetworkPolicy

apiVersion:networking.k8s.io/v1

kind:NetworkPolicy

metadata:

name:api-policy

namespace:production

spec:

podSelector:

matchLabels:

app:api

policyTypes:

-Ingress

-Egress

ingress:

-from:

-podSelector:

matchLabels:

app:frontend

ports:

-protocol:TCP

port:8080

egress:

-to:

-podSelector:

matchLabels:

app:postgres

ports:

-protocol:TCP

port:5432

#测试网络策略的连通性

#从frontendPod访问api

kubectlexec-itfrontend-pod--nc-zvapi-service8080

#从其他Pod访问api(应该被拒绝)

kubectlexec-itother-pod--nc-zvapi-service8080

MTU问题的识别:MTU不匹配的典型特征是"小请求成功、大请求超时",比如ping通、curl小文件通、

curl大文件卡住。原因是小包不需要分片,大包需要分片时被丢弃。用ping-Mdo-s<size>可以测试路

径MTU。常见的MTU值是1500(物理网络)、1450(VXLAN封装)、1400(IPsec或某些云网络)。CNI插

件的MTU配置应与底层网络匹配。

案例9:Pod被驱逐Evicted

现象:Pod状态显示Evicted,被节点驱逐。

#查看被驱逐的Pod

kubectlgetpods-A--field-selector=status.phase=Failed

#查看驱逐原因

kubectldescribepodevicted-pod

#典型事件:

#Thenodewaslowonresource:ephemeral-storage.

#Thenodewaslowonresource:memory.

#Thenodewaslowonresource:pid.

#Thenodehadcondition:[DiskPressure].

#Thenodehadcondition:[MemoryPressure].

解决方案:

Pod驱逐通常由节点资源压力触发。Kubelet会监控节点的内存、磁盘、PID等资源,当达到驱逐阈值时,按

QoS等级从低到高驱逐Pod。BestEffort最先被驱逐,Burstable其次,Guaranteed最后。因此,为关键服务设置合理

的requests/limits,可以让它在资源紧张时更不容易被驱逐。

#查看节点的资源状况

kubectldescribenodenode-1|grep-A5"Conditions"

#查看节点的磁盘使用

kubectldescribenodenode-1|grep-A10"Allocatedresources"

#设置Pod的驱逐容忍时间(PodDisruptionBudget)

apiVersion:policy/v1

kind:PodDisruptionBudget

metadata:

name:myapp-pdb

namespace:production

spec:

minAvailable:2

selector:

matchLabels:

app:myapp

#清理被驱逐的Pod

kubectlgetpods-A--field-selector=status.phase=Failed\

-ojson|kubectldelete-f-

#或者单独删除

kubectldeletepodevicted-pod

第五章Service工作原理与访问链路

5.1Service的本质

Pod的IP是动态的,每次重建都会变化。如果客户端直接使用PodIP,那么在Pod重建后连接就会失效。

Service解决了这个问题:它提供一个稳定的虚拟IP(ClusterIP)和DNS名称,后端的Pod可以随意变化,客户端只

需访问Service。

Service的实现依赖两个关键组件。kube-proxy负责在每个节点上维护iptables或IPVS规则,把访问ClusterIP的

流量转发到后端的PodIP。Endpoints(或EndpointSlice)对象记录当前匹配Serviceselector的Pod列表,kube-

proxy根据这个列表生成转发规则。

5.2Service的四种类型

类型作用典型场景

ClusterIP集群内部虚拟IP,仅集群内可访问内部微服务通信

NodePort在每个节点上开放一个端口外部通过节点IP:端口访问

LoadBalancer云厂商提供负载均衡器云环境暴露服务

ExternalName映射到外部DNS名称访问集群外服务

apiVersion:v1

kind:Service

metadata:

name:myapp-service

namespace:production

spec:

type:ClusterIP

selector:

app:myapp#匹配Pod的label

ports:

-name:http

protocol:TCP

port:80#Service暴露的端口

targetPort:8080#容器监听的端口

sessionAffinity:None

---

#NodePort示例

apiVersion:v1

kind:Service

metadata:

name:myapp-nodeport

spec:

type:NodePort

selector:

app:myapp

ports:

-port:80

targetPort:8080

nodePort:30080#30000-32767之间

protocol:TCP

5.3Service的访问链路

从客户端到Pod,一个请求会经过以下环节:

第一步:DNS解析。客户端用space.svc.cluster.local域名查询,CoreDNS返回Service

的ClusterIP。

第二步:路由到ClusterIP。客户端把请求发往ClusterIP,报文在节点内核中由iptables或IPVS规则拦截。

第三步:DNAT转换。kube-proxy配置的规则把目标地址从ClusterIP改写为某个后端Pod的IP和端口。

第四步:到达Pod。报文最终到达Pod网络命名空间,被应用进程处理。

任何一个环节出错,都会导致访问失败。理解这个链路,就能在排障时快速定位到具体环节。

5.4Endpoints与EndpointSlice

Endpoints是Service与Pod之间的桥梁。它由Kubernetes自动维护,记录所有匹配Serviceselector且通过就绪

探针的PodIP。如果Endpoints为空,说明没有可用的后端。

#查看Endpoints

kubectlgetendpointsmyapp-service-nproduction

#NAMEENDPOINTSAGE

#myapp-service:8080,:80805m

#如果ENDPOINTS列显示,说明没有匹配的Pod

kubectlgetendpointsmyapp-service-oyaml

#查看EndpointSlice(推荐,Kubernetes1.21+默认启用)

kubectlgetendpointslices-nproduction

kubectlgetendpointslicemyapp-service-xxxx-oyaml

Endpoints为空的常见原因:Service的selector与Pod的label不匹配;Pod存在但未通过就绪探针;Pod处

于Pending或CrashLoopBackOff状态;Pod与Service不在同一命名空间。排查时先kubectlgetpods--

show-labels查看Pod的label,再kubectlgetsvcmyapp-service-oyaml查看Service的selector,两

者应该匹配。

5.5kube-proxy的两种模式

模式原理特点

iptables用iptables规则做DNAT稳定,但规则多时性能下降

IPVS用内核IPVS模块做负载均衡支持更多调度算法,大规模集群性能更好

userspace用户态代理已淘汰

#查看kube-proxy模式

kubectlgetconfigmapkube-proxy-nkube-system-oyaml|grepmode

#查看IPVS规则(IPVS模式)

ipvsadm-Ln

#输出示例:

#TCP0:80rr

#->:8080Masq100

#->:8080Masq100

#查看iptables规则(iptables模式)

iptables-tnat-LKUBE-SERVICES-n|grepmyapp

#查看Service对应的规则链

iptables-tn

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论