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

事情背景

最近不少 k8s 底层网络模块都从 kubenet 晋级到了 cilium,cilium 仍是相对比较易用的,便是运维、监控和报警方案需求花点时刻来适应。可是最近咱们有一组 k8s 结构比较特别,导致它在从 kubenet 晋级到 cilium 的时分出现了一个小插曲:在 kubenet 网络的节点上的 pod 无法拜访 cilium 网络的节点上且布置了 networkpolicy 的 pod,导致了这个 k8s 上部分商户在新发使用 pod 时,pod 被调度到 cilium 网络的节点上,此刻无法与运行在 kubenet 网络的节点上 pod 互拜访题。

现象获取

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

直接测验商户的接口

cilium 网络故障一例,导致 k8s 不同类型节点之间的 Pod 互访异常

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

查看可是商户服务的反常日志

cilium 网络故障一例,导致 k8s 不同类型节点之间的 Pod 互访异常

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

经过上面的毛病,我登时觉得整个问题很古怪。 Http 503 的意思是说后端的服务资源不存在了,可是后端的 IP 仍是通的,要不然就会是 502。

所以这儿踩了一个小坑,觉得是商户使用的问题,还跟商户承认了许多内容,以及最近发布的情况。可是实践是因为网络层恳求被截断,导致数据包无法正常转发,才导致这次毛病,具体咱们看下一个环节。

原理剖析

毛病测验

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

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

cilium 网络故障一例,导致 k8s 不同类型节点之间的 Pod 互访异常

  • Ingress pod:是 istio Ingress gateway
  • App pod: 是商户使用服务的 pod,拥有 istio 的 sidecar

为了承认丢包的位置,咱们分在如下几个点抓包测验:

cilium 网络故障一例,导致 k8s 不同类型节点之间的 Pod 互访异常

抓包信息汇总表:

测验点 抓包成果
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 网络的节点。 为什么会出现不通呢?为了验证这个问题,咱们又做了如下一个试验,仍是上图:

cilium 网络故障一例,导致 k8s 不同类型节点之间的 Pod 互访异常

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

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

测验内容 状态介绍 测验点 测验成果
kubenet 节点上 pod 拜访 cilium 节点上事务 pod 1. 建议恳求的测验 pod 运行在 kubenet 节点上
2. 被测验事务 pod 运行在 cilium 节点上
3. 被测验事务 pod 装备有 networkpolicy
C 点 失利
cilium 节点上 pod 拜访 kubenet 节点上事务 pod 1. 建议恳求的测验 pod 运行在 kubenet 节点上
2. 被测验事务 pod 运行在 cilium 节点上
3. 被测验事务 pod 装备有 networkpolicy
B 点 成功
kubenet 节点上 pod 拜访 cilium 节点上事务 pod
去除 cilium 节点上 pod 上的 networkpolicy
1. 建议恳求的测验 pod 运行在 kubenet 节点上
2. 被测验 pod 运行在 cilium 节点上
3. 删去被测验 pod 的 networkpolicy
4. 被测验 pod 监听 8080 端口
5. 测验 pod 建议 tcp 恳求到被测验 pod
C 点 成功
cilium 节点上 pod 拜访 kubenet 节点上事务 pod
去除 cilium 节点上 pod 上的 networkpolicy
1. 建议恳求的测验 pod 运行在 kubenet 节点上
2. 被测验 pod 运行在 cilium 节点上
3. 删去被测验 pod 的 networkpolicy
4. 测验 pod 监听 8080 端口
5. 被测验 pod 建议 tcp 恳求到测验 pod
B 点 成功

总结下: 从 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 的迁移,尽量削减这样的不合理的共存环境。