📌K8s生产环境排错之:那些暗黑操作

278 阅读7分钟

🔥 开篇血泪史:当集群突然"失忆"时

凌晨2点收到告警,某个生产环境Pod疯狂重启但毫无日志输出。官方文档的kubectl describe三板斧毫无作用,直到偶然发现...

image.png


🕵️♀️ 场景一:Pod卡在Pending状态(你以为只是资源不够?)

暗黑手法1️⃣:撕开调度器的伪装面具

# 官方解法:看Events事件(但可能被误导!)
kubectl describe pod my-pod | grep Events -A10

# 暗黑指令:直击调度器内心OS(真实过滤逻辑)
kubectl get events --field-selector involvedObject.kind=Pod | jq '.items[] | select(.reason=="FailedScheduling")'

📌 真相清单

表象原因真实黑幕必杀指令
节点资源不足QoS策略暗藏优先级杀招kubectl get priorityclass
亲和性冲突污点容忍的隐藏继承规则kubectl get pod -o custom-columns=TOLERATIONS:.spec.tolerations
PVC绑定失败StorageClass幽灵回收锁kubectl get pv -l failure-domain.beta.kubernetes.io/zone

🌪️ 场景二:服务突然"鬼打墙"(间歇性503错误)

暗黑手法2️⃣:抓包不用进容器

# 绕过sidecar直接嗅探(需要hostNetwork权限)
kubectl debug node/<node-name> -it --image=nicolaka/netshoot
tcpdump -i eth0 port 80 -vvv

💡 避坑指南

  1. kubectl logs显示正常时👉立即检查conntrack表溢出
# 节点上执行(这才是真实罪魁祸首!)
sysctl net.netfilter.nf_conntrack_count
  1. 使用IPVS模式时👉必查/proc/net/ip_vs_conn黑洞

推荐我的私藏诊断镜像(非官方!):

FROM alpine:3.14
RUN apk add --no-cache bind-tools tcpdump curl jq
CMD ["sleep", "infinity"]

快速调试命令:kubectl debug -it <pod-name> --image=my-diag-tools -- sh


🌐 场景三:DNS解析离奇失踪案(比nslookup更狠的破案工具)

暗黑手法3️⃣:直击CoreDNS的"记忆错乱"

# 官方解法:检查DNS配置(但可能被缓存欺骗!)
kubectl exec -it busybox -- nslookup kubernetes.default

# 暗黑指令:解剖CoreDNS的"大脑皮层"
kubectl logs -l k8s-app=kube-dns -n kube-system --tail=100 | grep -E 'ERROR|WARN'

🔍 真相流程图

graph TD
    A[服务无法解析] --> B{检查Pod DNS配置}
    B -->|正确| C[抓包验证DNS请求]
    B -->|错误| D[修正dnsConfig]
    C --> E{CoreDNS收到请求?}
    E -->|是| F[检查上游DNS日志]
    E -->|否| G[排查NetworkPolicy封锁]

📌 幽灵DNS三宗罪

  1. ndots陷阱
# 查看Pod的resolv.conf暗藏杀机(ndots默认5!)
kubectl exec <pod-name> -- cat /etc/resolv.conf
现象破解方案
内部域名解析超时添加ndots:2到dnsConfig
外部域名解析失败检查CoreDNS的forward插件配置
  1. 幽灵缓存污染
# 暴力清除所有CoreDNS缓存(非官方操作!)
kubectl exec -n kube-system <coredns-pod> -- redis-cli flushall
  1. Hosts文件覆盖攻击
# 检测被篡改的hosts文件(警惕某些Sidecar!)
kubectl exec <pod-name> -- grep '10.96.0.1' /etc/hosts

🔒 场景四:ETCD的隐藏日记本——偷看调度器的小秘密

暗黑手法4️⃣:绕过API Server直连ETCD

# 需要SSH到ETCD节点(高风险操作!)
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get / --prefix --keys-only | grep pending

📌 ETCD暗黑档案解密

Key路径模式隐藏信息破译工具
/registry/pods/查看被调度器"遗忘"的Podetcdctl get /registry/pods/<namespace>/<pod-name>
/registry/events/挖掘被GC清理的远古事件etcdctl get --prefix /registry/events
/registry/daemonsets/检查幽灵DaemonSet残留配置jq解析JSON数据

⚠️ 禁忌操作红名单

diff
- 直接修改ETCD数据(会导致集群精神分裂)
- 非快照情况下执行defrag(可能触发OOM)
+ 推荐安全操作:定期备份快照
  etcdctl snapshot save /var/lib/etcd/snapshot.db

🛠️ 诊断工具进阶包

# 自制ETCD健康检查脚本(非官方!)
#!/bin/bash
etcdctl endpoint status --write-out=table \
--endpoints=$(grep -h initial-cluster /etc/kubernetes/manifests/etcd.yaml | awk -F= '{print $2}') 
diff
+ 推荐组合技:
  kubectl get pods -o wide + 抓包 + CoreDNS日志三连击

🏴‍☠️ 场景五:镜像拉取的黑暗森林法则

暗黑手法5️⃣:突破DockerHub的限速结界

# 伪装成CI/CD工具获取加速特权(慎用!)
kubectl create secret docker-registry stealth-registry \
--docker-server=docker.io \
--docker-username=gitlab-ci-token \
--docker-password=${CI_JOB_TOKEN}

🔍 镜像拉取四重幻境解密

表象错误真实博弈场破解阵法
ImagePullBackOff镜像仓库鉴权套娃机制kubectl get secret -o yaml
ErrImagePull镜像分片哈希校验暗战crictl inspecti <image-id>
ImageInspectError节点磁盘inode隐形杀手df -i /var/lib/docker

💡 江湖生存指南

  1. 镜像预加载邪术
# 在所有节点预埋镜像(绕过kubelet管制)
for node in $(kubectl get nodes -o name); do 
  docker -H ${node#node/} pull my-image:latest
done
  1. 私有仓库的替身攻击
# 在Pod中植入镜像重定向咒语(非官方!)
spec:
  imagePullSecrets:
  - name: stealth-registry
  containers:
  - image: my-registry-proxy/docker.io/library/nginx:alpine

🌀 场景六:APIServer的量子纠缠——让Watch永不掉线

暗黑手法6️⃣:突破Watch连接的心跳诅咒

# 监听APIServer的脑电波(需要审计权限)
kubectl get --raw="/apis/apiregistration.k8s.io/v1/apiservices" \
--watch --v=8 2>&1 | grep -E 'Timeout|Too large'

🌌 量子态故障矩阵

graph LR
    A[Watch连接断开] --> B{资源版本号漂移?}
    B -->|是| C[启用书签机制]
    B -->|否| D[检查APIServer内存泄漏]
    C --> E[添加allowWatchBookmarks=true]
    D --> F[监控apiserver_go_goroutines指标]

📌 时空穿越秘籍

  1. 压缩历史事件黑洞
# 调整APIServer的时光机参数(影响深远!)
--watch-cache-sizes=leases.coordination.k8s.io#100
  1. 打破List请求的次元壁
// 客户端代码注入分页咒文(Golang示例)
listOptions := metav1.ListOptions{
    Limit: 500,
    Continue: continueToken, 
    AllowWatchBookmarks: true}

☠️ 终极禁忌仪式

# 集群复活术(当所有节点同时宕机时)
etcdctl snapshot restore snapshot.db \
--data-dir /var/lib/etcd-new \
--initial-cluster etcd1=http://ip1:2380 \
--initial-advertise-peer-urls http://ip1:2380

⚠️ 死亡红皮书

diff
- 直接修改kubelet证书过期时间(引发集群身份认知障碍)
- 在滚动更新时强制删除etcd成员(导致时空撕裂)
+ 推荐时空锚点:
  kubectl annotate node <node-name> rescue-timestamp=$(date +%s)

🧰 暗黑军火库

# 镜像拉取时空穿梭器(按时间戳拉取历史镜像)
docker pull nginx@sha256:xxxxxx
# Watch连接量子态检测器
kubectl get --raw=/metrics | grep apiserver_watch_events_total

🌉 场景七:Ingress流量神秘消失(穿越七层协议栈的幽灵)

暗黑手法7️⃣:撕开Ingress控制器的假面舞会

# 官方解法:检查Ingress状态(可能被虚假Ready欺骗!)
kubectl get ingress my-app -o wide

# 暗黑指令:直击控制器内核日志(需SSH到Pod所在节点)
kubectl logs -n ingress-nginx <pod-name> | grep -E 'http2|rewrite' --color=always

🔍 Ingress幻境解密矩阵

表象症状隐藏维度破壁指令
返回404但后端存在Annotation优先级战争kubectl get ingress -o jsonpath='{.items[*].metadata.annotations}'
HTTPS证书突然失效证书热重载时间裂缝`openssl s_client -connect :443 -prexit 2>/dev/nullgrep "Verify return code"`
长连接秒断Keepalive_buffer_size黑洞`kubectl exec -n ingress-nginx -- nginx -T 2>&1grep keepalive`

💡 时空穿越法则

graph LR
    A[客户端超时] --> B{TCP握手成功?}
    B -->|是| C[抓取Ingress Pod tcpdump]
    B -->|否| D[检查NodePort防火墙规则]
    C --> E{发现RST包?}
    E -->|是| F[调整nginx.ingress.kubernetes.io/proxy-next-upstream]
    E -->|否| G[检查后端Pod的http.Server超时设置]

💾 场景八:Persistent Volume的时空悖论(数据在时空中震荡)

暗黑手法8️⃣:突破StorageClass的因果律封锁

# 查看PV的隐藏元数据(官方命令会过滤关键信息!)
kubectl get pv -o json | jq '.items[] | {name: .metadata.name, phase: .status.phase, reclaimPolicy: .spec.persistentVolumeReclaimPolicy, finalizers: .metadata.finalizers}'

📌 存储卷三体问题解密

  1. 删除黑洞
# 强制移除PV的finalizer(可能引发跨维度数据丢失!)
kubectl patch pv pv-name -p '{"metadata":{"finalizers":null}}'
风险等级症状逃生方案
★★★☆☆PV卡在Released状态检查StorageClass回收策略
★★★★★云盘被意外释放立即创建同名PV绑定残留数据
  1. 容量膨胀幻术
# 绕过k8s直接扩展云盘(需云平台API密钥)
aliyun ecs ResizeDisk --DiskId=xxx --NewSize=100
kubectl edit pv pv-name  # 静默修改capacity字段

☄️ 终极生存工具包

# Ingress时间回溯器(按时间戳查看历史配置)
git -C /etc/nginx/ diff HEAD@{10.minutes.ago}
# 存储卷量子态检测脚本
while true; do kubectl get pv -w; done & \
watch -n 1 "df -h /mnt/data | grep -v Filesystem"

🛑 禁忌终章:当kubelet开始说谎

突破节点维度的真相封锁

# 绕过kubelet直接查询容器运行时(需要root权限!)
crictl ps | grep -v Running
# 检查cgroup的平行宇宙
cgget -g memory:kubepods | grep memory.limit_in_bytes

⚠️ 跨维度操作红皮书

diff
+ 安全操作:通过Node Problem Detector收集线索
- 危险操作:直接修改/var/lib/kubelet/pods目录
+ 进阶操作:对比kubelet日志与containerd日志时间线

🚨 终极暗黑警示录

以下操作可能引发次元裂缝,仅供绝境参考!

☠️ 禁忌操作1:强制解除Pod的"死亡拥抱"

# 直接操作CRI接口驱逐容器(绕过kubelet)
crictl stopp $(crictl pods --name my-pod -q) 

风险矩阵

操作目的常规方案暗黑代价
释放被卡死的Podkubectl delete --force可能残留幽灵cgroup
清理僵尸容器重启docker/containerd触发节点身份认证紊乱

🌌 禁忌操作2:篡改APIServer记忆宫殿

# 暴力清除Watch缓存(可能引发集群癫痫)
echo 3 > /proc/sys/vm/drop_caches

量子态副作用

  1. 已建立的Watch连接可能产生平行宇宙
  2. List请求可能返回来自其他时间线的资源
  3. 控制器陷入观测者悖论循环

🛡️ 重生秘术:集群复活指南

当遭遇降维打击时(如ETCD全盘崩溃)

步骤1:从高维空间提取备份

# 利用Velero进行跨维度快照(需提前布置)
velero restore create --from-backup=pre-disaster-backup

步骤2:重建因果律锚点

# 在Kubelet植入时空坐标(非官方操作!)
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
resolvConf: /etc/resolv.conf.backup

步骤3:启动因果律引擎

# 强制同步所有控制器状态(慎用!)
kubectl get deployments -o json | jq '.items[] | selstatus.replicas != .spec.replicas)' | xargs -I{} kubectl rollout restart

📜 暗黑排错法典(精华摘要)

graph TD
    A[故障现象] --> B{是否可观测?}
    B -->|是| C[启用常规武器库]
    B -->|否| D[启动混沌工程]
    C --> E[检查APIServer审计日志]
    D --> F[注入故障探针]
    F --> G{出现新症状?}
    G -->|是| H[建立症状关联矩阵]
    G -->|否| I[怀疑量子隧穿效应]

🌌 终局宣言

真正的K8s暗黑艺术,是学会:
在官方文档的字里行间读取空白处的真相
从APIServer的沉默中听出故障的弦外之音
让每个排错操作都成为对抗熵增的逆熵行为


🌟 让技术经验流动起来

▌▍▎▏ 你的每个互动都在为技术社区蓄能 ▏▎▍▌
点赞 → 让优质经验被更多人看见
📥 收藏 → 构建你的专属知识库
🔄 转发 → 与技术伙伴共享避坑指南

点赞 ➕ 收藏 ➕ 转发,助力更多小伙伴一起成长!💪

💌 深度连接
点击 「头像」→「+关注」
每周解锁:
🔥 一线架构实录 | 💡 故障排查手册 | 🚀 效能提升秘籍

R-C.gif