查看原文
其他

K8s 最强 CNI Cilium 网络故障排查指南

自在的LEE 云原生实验室 2023-08-15

本文转自掘金,原文:https://juejin.cn/post/7176184210284085285,版权归原作者所有。欢迎投稿,投稿请添加微信好友:cloud-native-yang

我是 LEE,老李,一个在 IT 行业摸爬滚打 16 年的技术老兵。

事件背景

最近不少 k8s 底层网络模块都从 kubenet 升级到了 cilium,cilium  还是相对比较易用的,就是运维、监控和报警方案需要花点时间来适应。但是最近我们有一组 k8s 结构比较特殊,导致它在从 kubenet 升级到  cilium 的时候出现了一个小插曲:在 kubenet 网络的节点上的 pod 无法访问 cilium 网络的节点上且部署了 networkpolicy 的 pod,导致了这个 k8s 上部分商户在新发应用 pod 时,pod 被调度到 cilium 网络的节点上,此时无法与运行在 kubenet 网络的节点上 pod 互访问题。

现象获取

当我们接到监控系统的报警,以及客户的反馈,所以部分商户出现了服务异常,而且只是少量商户的出现了问题。针对这些商户的服务我第一时间看了下共性,发现这些商户的服务性质,受众群体,以及触发报警时间都不一样,难道是巧合?我随机找一个商户做了简单的排查:

直接测试商户的接口

接口异常

发现商户接口直接返回:upstream connect error or disconnect/reset before headers. reset reason: connection failure ,单看这个信息,就知道这个应该不是服务返回的内容,应该是后端服务前某一层转发层的问题。

查看但是商户服务的异常日志

日志 503 报错

查看应用 sidecar 的日志, 把有问题的部分过滤出来,发现是错误代码是 503。

通过上面的故障,我顿时觉得整个问题很奇怪。Http 503 的意思是说后端的服务资源不存在了,但是后端的 IP 还是通的,要不然就会是 502。

所以这里踩了一个小坑,觉得是商户应用的问题,还跟商户确认了很多内容,以及最近发布的情况。但是实际是因为网络层请求被截断,导致数据包无法正常转发,才导致这次故障,具体我们看下一个环节。

原理分析

故障测试

通过大量的排查和分析,而且确定商户的服务启动正常,没有运行报错日志。只是服务无法对外正常提供,我就快速将排障范围缩小到了网络层面。

这里我提供一份网络流量结构图:

网络架构简图
  • Ingress pod:是 istio Ingress gateway
  • App pod: 是商户应用服务的 pod,拥有 istio 的 sidecar

为了确认丢包的位置,我们分在如下几个点抓包测试:

抓包点

抓包信息汇总表:

测试点抓包结果
A 点有 request,没有 respond
B 点有 request,没有 respond
C 点什么都没有

测试完,我大吃一惊,感觉丢包了啊,而且是 cilium 节点把数据包丢了。带着怀疑,有仔细检查了两个 cilium 节点上的 ct 表,以及 networkpolicy 挂载点信息。

ENDPOINT 信息

ENDPOINT   POLICY (ingress)   POLICY (egress)   IDENTITY   LABELS (source:key[=value])                                          IPv6   IPv4           STATUS
           ENFORCEMENT        ENFORCEMENT
2636       Enabled            Disabled          59271      k8s:app=wetown-java                                                         10.242.2.149   ready
                                                           k8s:app_id=468205436992_wetown-java
                                                           k8s:app_name=wetown-java
                                                           k8s:appnew=468205436992_wetown-java
                                                           k8s:group=standard
                                                           k8s:io.cilium.k8s.namespace.labels.istio-injection=enabled
                                                           k8s:io.cilium.k8s.namespace.labels.project_id=468205436992_default
                                                           k8s:io.cilium.k8s.namespace.labels.project_name=default
                                                           k8s:io.cilium.k8s.namespace.labels.tenant_id=468205436992
                                                           k8s:io.cilium.k8s.policy.cluster=default
                                                           k8s:io.cilium.k8s.policy.serviceaccount=default
                                                           k8s:io.kubernetes.pod.namespace=468205436992-default
                                                           k8s:metric_source=customize
                                                           k8s:security.istio.io/tlsMode=istio
                                                           k8s:service.istio.io/canonical-name=wetown-java
                                                           k8s:service.istio.io/canonical-revision=latest

NETWORKPOLICY 信息

Defaulted container "cilium-agent" out of: cilium-agent, mount-cgroup (init), apply-sysctl-overwrites (init), clean-cilium-state (init)
POLICY   DIRECTION   LABELS (source:key[=value])                                                    PORT/PROTO   PROXY PORT   BYTES      PACKETS
Allow    Ingress     reserved:unknown                                                               9999/TCP     NONE         0          0
Allow    Ingress     reserved:host                                                                  ANY          NONE         408725     5154
Allow    Ingress     k8s:app=istiod                                                                 ANY          NONE         11824851   910
                     k8s:install.operator.istio.io/owning-resource=unknown
                     k8s:io.cilium.k8s.namespace.labels.istio-injection=disabled
                     k8s:io.cilium.k8s.namespace.labels.system=true
                     k8s:io.cilium.k8s.policy.cluster=default
                     k8s:io.cilium.k8s.policy.serviceaccount=istiod-1-11-8
                     k8s:io.kubernetes.pod.namespace=istio-system
                     k8s:istio.io/rev=1-11-8
                     k8s:istio=istiod
                     k8s:operator.istio.io/component=Pilot
                     k8s:sidecar.istio.io/inject=false
Allow    Ingress     k8s:app=istio-ingressgateway                                                   ANY          NONE         8007       14
                     k8s:chart=gateways
                     k8s:heritage=Tiller
                     k8s:install.operator.istio.io/owning-resource=unknown
                     k8s:io.cilium.k8s.namespace.labels.istio-injection=disabled
                     k8s:io.cilium.k8s.namespace.labels.system=true
                     k8s:io.cilium.k8s.policy.cluster=default
                     k8s:io.cilium.k8s.policy.serviceaccount=istio-ingressgateway-service-account
                     k8s:io.kubernetes.pod.namespace=istio-system
                     k8s:istio.io/rev=1-11-8
                     k8s:istio=ingressgateway
                     k8s:operator.istio.io/component=IngressGateways
                     k8s:release=istio
                     k8s:service.istio.io/canonical-name=istio-ingressgateway
                     k8s:service.istio.io/canonical-revision=1-11-8
                     k8s:sidecar.istio.io/inject=false
Allow    Ingress     k8s:app=network-debug                                                          ANY          NONE         0          0
                     k8s:io.cilium.k8s.namespace.labels.system=true
                     k8s:io.cilium.k8s.policy.cluster=default
                     k8s:io.cilium.k8s.policy.serviceaccount=default
                     k8s:io.kubernetes.pod.namespace=default
Allow    Ingress     k8s:app=wetown-java                                                            ANY          NONE         0          0
                     k8s:app_id=468205436992_wetown-java
                     k8s:app_name=wetown-java
                     k8s:appnew=468205436992_wetown-java
                     k8s:group=standard
                     k8s:io.cilium.k8s.namespace.labels.istio-injection=enabled
                     k8s:io.cilium.k8s.namespace.labels.project_id=468205436992_default
                     k8s:io.cilium.k8s.namespace.labels.project_name=default
                     k8s:io.cilium.k8s.namespace.labels.tenant_id=468205436992
                     k8s:io.cilium.k8s.policy.cluster=default
                     k8s:io.cilium.k8s.policy.serviceaccount=default
                     k8s:io.kubernetes.pod.namespace=468205436992-default
                     k8s:metric_source=customize
                     k8s:security.istio.io/tlsMode=istio
                     k8s:service.istio.io/canonical-name=wetown-java
                     k8s:service.istio.io/canonical-revision=latest
                     k8s:tenant_id=468205436992
Allow    Egress      reserved:unknown                                                               ANY          NONE         990293     6509

CT 信息

TCP IN 10.242.2.153:60064 -> 10.242.2.149:15021 expires=17276052 RxPackets=6 RxBytes=464 RxFlagsSeen=0x1b LastRxReport=17276043 TxPackets=4 TxBytes=371 TxFlagsSeen=0x1b LastTxReport=17276043 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:2464 -> 10.242.2.149:15020 expires=17276618 RxPackets=5 RxBytes=418 RxFlagsSeen=0x1b LastRxReport=17276609 TxPackets=5 TxBytes=376 TxFlagsSeen=0x1b LastTxReport=17276609 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:19582 -> 10.242.2.149:15021 expires=17275992 RxPackets=6 RxBytes=464 RxFlagsSeen=0x1b LastRxReport=17275983 TxPackets=4 TxBytes=371 TxFlagsSeen=0x1b LastTxReport=17275983 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:17164 -> 10.242.2.149:15021 expires=17276443 RxPackets=6 RxBytes=464 RxFlagsSeen=0x1b LastRxReport=17276434 TxPackets=4 TxBytes=371 TxFlagsSeen=0x1b LastTxReport=17276434 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:15068 -> 10.242.2.149:15020 expires=17276115 RxPackets=5 RxBytes=418 RxFlagsSeen=0x1b LastRxReport=17276106 TxPackets=5 TxBytes=376 TxFlagsSeen=0x1b LastTxReport=17276106 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:3468 -> 10.242.2.149:15021 expires=17276081 RxPackets=6 RxBytes=464 RxFlagsSeen=0x1b LastRxReport=17276072 TxPackets=4 TxBytes=371 TxFlagsSeen=0x1b LastTxReport=17276072 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:60072 -> 10.242.2.149:15021 expires=17276413 RxPackets=6 RxBytes=464 RxFlagsSeen=0x1b LastRxReport=17276404 TxPackets=4 TxBytes=371 TxFlagsSeen=0x1b LastTxReport=17276404 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:13152 -> 10.242.2.149:15021 expires=17276083 RxPackets=6 RxBytes=464 RxFlagsSeen=0x1b LastRxReport=17276074 TxPackets=4 TxBytes=371 TxFlagsSeen=0x1b LastTxReport=17276074 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:60054 -> 10.242.2.149:15021 expires=17276509 RxPackets=18 RxBytes=1392 RxFlagsSeen=0x1b LastRxReport=17276500 TxPackets=12 TxBytes=1113 TxFlagsSeen=0x1b LastTxReport=17276500 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:14902 -> 10.242.2.149:15020 expires=17276263 RxPackets=5 RxBytes=417 RxFlagsSeen=0x1b LastRxReport=17276254 TxPackets=5 TxBytes=376 TxFlagsSeen=0x1b LastTxReport=17276254 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:7100 -> 10.242.2.149:15021 expires=17276003 RxPackets=6 RxBytes=464 RxFlagsSeen=0x1b LastRxReport=17275994 TxPackets=4 TxBytes=371 TxFlagsSeen=0x1b LastTxReport=17275994 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:1396 -> 10.242.2.149:15020 expires=17276207 RxPackets=5 RxBytes=418 RxFlagsSeen=0x1b LastRxReport=17276198 TxPackets=5 TxBytes=376 TxFlagsSeen=0x1b LastTxReport=17276198 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:11408 -> 10.242.2.149:15020 expires=17275973 RxPackets=5 RxBytes=418 RxFlagsSeen=0x1b LastRxReport=17275964 TxPackets=5 TxBytes=376 TxFlagsSeen=0x1b LastTxReport=17275964 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:60010 -> 10.242.2.149:15020 expires=17276575 RxPackets=63 RxBytes=5171 RxFlagsSeen=0x1b LastRxReport=17276566 TxPackets=60 TxBytes=4512 TxFlagsSeen=0x1b LastTxReport=17276566 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:18134 -> 10.242.2.149:15020 expires=17276315 RxPackets=5 RxBytes=418 RxFlagsSeen=0x1b LastRxReport=17276306 TxPackets=5 TxBytes=376 TxFlagsSeen=0x1b LastTxReport=17276306 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:3438 -> 10.242.2.149:15021 expires=17276076 RxPackets=6 RxBytes=464 RxFlagsSeen=0x1b LastRxReport=17276067 TxPackets=4 TxBytes=371 TxFlagsSeen=0x1b LastTxReport=17276067 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:17962 -> 10.242.2.149:15020 expires=17276032 RxPackets=5 RxBytes=418 RxFlagsSeen=0x1b LastRxReport=17276023 TxPackets=5 TxBytes=376 TxFlagsSeen=0x1b LastTxReport=17276023 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:10100 -> 10.242.2.149:15020 expires=17276500 RxPackets=5 RxBytes=418 RxFlagsSeen=0x1b LastRxReport=17276491 TxPackets=5 TxBytes=376 TxFlagsSeen=0x1b LastTxReport=17276491 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:8154 -> 10.242.2.149:15021 expires=17276329 RxPackets=12 RxBytes=928 RxFlagsSeen=0x1b LastRxReport=17276320 TxPackets=8 TxBytes=742 TxFlagsSeen=0x1b LastTxReport=17276320 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0
TCP IN 10.242.2.153:19556 -> 10.242.2.149:15021 expires=17275986 RxPackets=6 RxBytes=464 RxFlagsSeen=0x1b LastRxReport=17275977 TxPackets=4 TxBytes=371 TxFlagsSeen=0x1b LastTxReport=17275977 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=1 IfIndex=0

......

通过检查,就是没有发现从 kubenet 网络的节点转发过来的流量。然后回想到应用上有挂载  networkpolicy,我这边果断删除这个业务 pod 上挂载的 networkpolicy,然后在所有测试点抓包。 全部都通了,现在破案了,应该是 networkpolicy 的问题。

这里又来一个隐含的问题,既然在同一个 k8s 内,有 cilium 网络的节点,也有传统的 kubenet 网络的节点。为什么会出现不通呢?为了验证这个问题,我们又做了如下一个实验,还是上图:

抓包点

在做这个实验前,有一点可以确认:丢包点是在两种不同的网络模型,并不是外部进入 k8s 集群,所以只要关注 C 点流量。

测试方法跟之间一样,然后我们在不同的点抓包,这次结果也让我惊掉了下巴。

测试内容状态介绍测试点测试结果
kubenet 节点上 pod 访问 cilium 节点上业务 pod1. 发起请求的测试 pod 运行在 kubenet 节点上 2. 被测试业务 pod 运行在 cilium 节点上 3. 被测试业务 pod 配置有 networkpolicyC 点失败
cilium 节点上 pod 访问 kubenet 节点上业务 pod1. 发起请求的测试 pod 运行在 kubenet 节点上 2. 被测试业务 pod 运行在 cilium 节点上 3. 被测试业务 pod 配置有 networkpolicyB 点成功
kubenet 节点上 pod 访问 cilium 节点上业务 pod (去除 cilium 节点上 pod 上的 networkpolicy1. 发起请求的测试 pod 运行在 kubenet 节点上 2. 被测试 pod 运行在 cilium 节点上 3. 删除被测试 pod 的 networkpolicy 4. 被测试 pod 监听 8080 端口 5. 测试 pod 发起 tcp 请求到被测试 podC 点成功
cilium 节点上 pod 访问 kubenet 节点上业务 pod (去除 cilium 节点上 pod 上的 networkpolicy1. 发起请求的测试 pod 运行在 kubenet 节点上 2. 被测试 pod 运行在 cilium 节点上 3. 删除被测试 pod 的 networkpolicy 4. 测试 pod 监听 8080 端口 5. 被测试 pod 发起 tcp 请求到测试 podB 点成功

总结下: 从 kubenet 网络的节点上 pod 访问带有 networkpolicy 的 cilium 网络的节点上 pod,是不通,其他的场景都是 OK 的。

技术解析

那么是不是有这样一种猜想,cilium 不识别其他的网络模型的节点呢?让我们看看 cilium cluster 信息:

Cluster health:             15/15 reachable   (2022-12-12T08:19:02Z)
  Name                      IP                Node        Endpoints
  10.118.201.53 (localhost)   10.118.201.53       reachable   reachable
  10.118.201.48               10.118.201.48       reachable   reachable
  10.118.201.49               10.118.201.49       reachable   reachable
  10.118.201.50               10.118.201.50       reachable   reachable
  10.118.201.51               10.118.201.51       reachable   reachable
  10.118.201.52               10.118.201.52       reachable   reachable
  10.118.201.54               10.118.201.54       reachable   reachable
  10.118.201.55               10.118.201.55       reachable   reachable
  10.118.201.56               10.118.201.56       reachable   reachable
  10.118.201.57               10.118.201.57       reachable   reachable
  10.118.201.58               10.118.201.58       reachable   reachable
  10.118.201.59               10.118.201.59       reachable   reachable
  10.118.201.60               10.118.201.60       reachable   reachable
  10.118.201.61               10.118.201.61       reachable   reachable
  10.118.201.62               10.118.201.62       reachable   reachable

通过节点信息,我们可以清楚看出,cilium 只管理部署了 cilium agent 的节点。其他的 kubenet  网络节点他是不管的,也就是这些节点对他来说的跟外部服务器一样,从这些节点传入的网络流量都当成外部流量,即便在同一个 k8s 内,cilium  也不看你流量信息,以及来源哪里。

说到这里,不得不提到之前写一篇文章《ebpf 开发入门之核心概念篇》,那里面提到了一个 HOOK 的概念,networkpolicy  就是通过 HOOK 挂载到容器的网卡的 Ingress 上。既然 kubenet 网络的节点 和 cilium 网络的节点都在同一个 k8s  内,但是 cilium 的只管理自己的节点,其他的节点都认为是外部的,如果不匹配 Ingress 的规则,都会被拒绝。

通过抓包测试,以及分析 cilium 的相关信息,我们找到问题所在:cilium 如果没有管理全部的 k8s 所有节点,剩余的节点就按照外部服务器的方式来处理

处理方法

知道了原因,有了实验验证,那么办法也当然就有了,当然也很简单。

  1. 移动所有的 pod 到 cilium 网络的节点
  2. 移动 Ingress pod 到 cilium 网络的节点
  3. 删除 cilium 受影响 pod 的 networkpolicy

从解决办法上看,最合理也最有可操作性的是:2 号

最终效果

通过调整后,最终结果当然也复合预期,所有的业务互联互通都没有了问题。同时也在加速 pod 的迁移,尽量减少这样的不合理的共存环境。




你可能还喜欢

点击下方图片即可阅读

初探 Cloudflare 零信任 - 通过 Docker 部署 Bitwarden 密码管理器

2022-12-13

我将 9 个 ChatGPT 账号接入微信,我现在整个人都麻了...

2022-12-10

AI 对话模型被网友玩坏了!这次还可以运行 Docker 容器...

2022-12-04

JVM 内存与 K8s 容器内存不一致引发的 OOMKilled 总结

2022-12-01


云原生是一种信仰 🤘

关注公众号

后台回复◉k8s◉获取史上最方便快捷的 Kubernetes 高可用部署工具,只需一条命令,连 ssh 都不需要!



点击 "阅读原文" 获取更好的阅读体验!


发现朋友圈变“安静”了吗?

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存