本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
网络断开后的应用程序网络流量
本页上的主题与 Kubernetes 集群网络以及节点与 Kubernetes 控制平面之间断开网络连接期间的应用程序流量有关。
Cilium
Cilium 有多种模式可用于 IP 地址管理 (IPAM)、封装、负载平衡和集群路由。本指南中验证的模式使用了集群范围 IPAM、VXLAN 覆盖、BGP 负载平衡和 kube-proxy。Cilium 也是在没有 BGP 负载平衡的情况下使用的,取而代之的是 MetalB L2 负载均衡。
Cilium 安装的基础由 Cilium 操作员和 Cilium 代理组成。Cilium 操作员以部署方式运行,注册 Cilium 自定义资源定义 (CRD),管理 IPAM,将集群对象与 Kubernetes API 服务器同步等功能。https://docs.cilium.io/en/stable/internals/cilium_operator/
通常,Cilium 配置的集群内路由在网络断开期间仍然可用且处于原位,这可以通过观察集群内流量和 pod 网络的 IP 表 (iptables) 规则来确认。
ip route show table all | grep cilium
10.86.2.0/26 via 10.86.3.16 dev cilium_host proto kernel src 10.86.3.16 mtu 1450 10.86.2.64/26 via 10.86.3.16 dev cilium_host proto kernel src 10.86.3.16 mtu 1450 10.86.2.128/26 via 10.86.3.16 dev cilium_host proto kernel src 10.86.3.16 mtu 1450 10.86.2.192/26 via 10.86.3.16 dev cilium_host proto kernel src 10.86.3.16 mtu 1450 10.86.3.0/26 via 10.86.3.16 dev cilium_host proto kernel src 10.86.3.16 10.86.3.16 dev cilium_host proto kernel scope link ...
但是,在网络中断期间,由于运行状况检查与与Kubernetes API服务器连接的运行状况相结合,Cilium运营商和Cilium代理会重新启动。在网络断开期间,预计将在Cilium运营商和Cilium代理的日志中看到以下内容。在网络断开期间,您可以使用诸如 crictl CLI 之类的工具来观察这些组件的重启情况,包括它们的日志。
msg="Started gops server" address="127.0.0.1:9890" subsys=gops msg="Establishing connection to apiserver" host="https://<k8s-cluster-ip>:443" subsys=k8s-client msg="Establishing connection to apiserver" host="https://<k8s-cluster-ip>:443" subsys=k8s-client msg="Unable to contact k8s api-server" error="Get \"https://<k8s-cluster-ip>:443/api/v1/namespaces/kube-system\": dial tcp <k8s-cluster-ip>:443: i/o timeout" ipAddr="https://<k8s-cluster-ip>:443" subsys=k8s-client msg="Start hook failed" function="client.(*compositeClientset).onStart (agent.infra.k8s-client)" error="Get \"https://<k8s-cluster-ip>:443/api/v1/namespaces/kube-system\": dial tcp <k8s-cluster-ip>:443: i/o timeout" msg="Start failed" error="Get \"https://<k8s-cluster-ip>:443/api/v1/namespaces/kube-system\": dial tcp <k8s-cluster-ip>:443: i/o timeout" duration=1m5.003834026s msg=Stopping msg="Stopped gops server" address="127.0.0.1:9890" subsys=gops msg="failed to start: Get \"https://<k8s-cluster-ip>:443/api/v1/namespaces/kube-system\": dial tcp <k8s-cluster-ip>:443: i/o timeout" subsys=daemon
如果您使用 Cilium 的 BGP 控制平面功能来平衡应用程序负载,则在网络断开连接期间,您的 Pod 和服务的 BGP 会话可能会关闭,因为 BGP 扬声器功能已集成到 Cilium 代理中,并且与 Kubernetes 控制平面断开连接时 Cilium 代理将持续重启。有关更多信息,请参阅 Cilium 文档中的 Cilium BGP 控制平面操作指南。此外,如果您在断开网络(例如重新启动电源或计算机重启)期间同时遇到故障,则不会通过这些操作保留 Cilium 路由,尽管当节点重新连接到 Kubernetes 控制平面并且 Cilium 再次启动时,会重新创建路由。
Calico
即将推出
MetalB
MetalB 有两种负载平衡模式:L2 模式
kube-proxy
在 EKS 集群中,kube-proxy 作为 DaemonSet 在每个节点上运行,负责管理网络规则,通过将服务 IP 地址转换为底层 pod 的 IP 地址来实现服务与 pod 之间的通信。由 kube-proxy 配置的 IP 表(iptables)规则将在网络断开期间保持不变,集群内路由继续运行,kube-proxy pod 继续运行。
你可以使用以下 iptables 命令来观察 kube-proxy 规则。第一条命令显示通过该PREROUTING链的数据包被定向到KUBE-SERVICES链。
iptables -t nat -L PREROUTING
Chain PREROUTING (policy ACCEPT) target prot opt source destination KUBE-SERVICES all -- anywhere anywhere /* kubernetes service portals */
通过检查KUBE-SERVICES链,我们可以看到各种集群服务的规则。
Chain KUBE-SERVICES (2 references) target prot opt source destination KUBE-SVL-NZTS37XDTDNXGCKJ tcp -- anywhere 172.16.189.136 /* kube-system/hubble-peer:peer-service cluster IP / KUBE-SVC-2BINP2AXJOTI3HJ5 tcp -- anywhere 172.16.62.72 / default/metallb-webhook-service cluster IP / KUBE-SVC-LRNEBRA3Z5YGJ4QC tcp -- anywhere 172.16.145.111 / default/redis-leader cluster IP / KUBE-SVC-I7SKRZYQ7PWYV5X7 tcp -- anywhere 172.16.142.147 / kube-system/eks-extension-metrics-api:metrics-api cluster IP / KUBE-SVC-JD5MR3NA4I4DYORP tcp -- anywhere 172.16.0.10 / kube-system/kube-dns:metrics cluster IP / KUBE-SVC-TCOU7JCQXEZGVUNU udp -- anywhere 172.16.0.10 / kube-system/kube-dns:dns cluster IP / KUBE-SVC-ERIFXISQEP7F7OF4 tcp -- anywhere 172.16.0.10 / kube-system/kube-dns:dns-tcp cluster IP / KUBE-SVC-ENODL3HWJ5BZY56Q tcp -- anywhere 172.16.7.26 / default/frontend cluster IP / KUBE-EXT-ENODL3HWJ5BZY56Q tcp -- anywhere <LB-IP> / default/frontend loadbalancer IP / KUBE-SVC-NPX46M4PTMTKRN6Y tcp -- anywhere 172.16.0.1 / default/kubernetes:https cluster IP / KUBE-SVC-YU5RV2YQWHLZ5XPR tcp -- anywhere 172.16.228.76 / default/redis-follower cluster IP / KUBE-NODEPORTS all -- anywhere anywhere / kubernetes service nodeports; NOTE: this must be the last rule in this chain */
检查应用程序的前端服务链,我们可以看到支持该服务的 pod IP 地址。
iptables -t nat -L KUBE-SVC-ENODL3HWJ5BZY56Q
Chain KUBE-SVC-ENODL3HWJ5BZY56Q (2 references) target prot opt source destination KUBE-SEP-EKXE7ASH7Y74BGBO all -- anywhere anywhere /* default/frontend -> 10.86.2.103:80 / statistic mode random probability 0.33333333349 KUBE-SEP-GCY3OUXWSVMSEAR6 all -- anywhere anywhere / default/frontend -> 10.86.2.179:80 / statistic mode random probability 0.50000000000 KUBE-SEP-6GJJR3EF5AUP2WBU all -- anywhere anywhere / default/frontend -> 10.86.3.47:80 */
在网络断开连接期间,预计会出现以下 kube-proxy 日志消息,因为它尝试监视 Kubernetes API 服务器是否有节点和端点资源的更新。
"Unhandled Error" err="k8s.io/client-go/informers/factory.go:160: Failed to watch *v1.Node: failed to list *v1.Node: Get \"https://<k8s-endpoint>/api/v1/nodes?fieldSelector=metadata.name%3D<node-name>&resourceVersion=2241908\": dial tcp <k8s-ip>:443: i/o timeout" logger="UnhandledError" "Unhandled Error" err="k8s.io/client-go/informers/factory.go:160: Failed to watch *v1.EndpointSlice: failed to list *v1.EndpointSlice: Get \"https://<k8s-endpoint>/apis/discovery.k8s.io/v1/endpointslices?labelSelector=%21service.kubernetes.io%2Fheadless%2C%21service.kubernetes.io%2Fservice-proxy-name&resourceVersion=2242090\": dial tcp <k8s-ip>:443: i/o timeout" logger="UnhandledError"
CoreDNS
默认情况下,EKS 集群中的 Pod 使用 CoreDNS 集群 IP 地址作为集群内 DNS 查询的名称服务器。在 EKS 集群中,CoreDNS 作为部署在节点上运行。使用混合节点,当 CoreDNS 副本在混合节点上本地运行时,Pod 能够在网络断开期间继续与 CoreDNS 通信。如果您的 EKS 集群在云端有节点,在本地环境中有混合节点,则建议在每个环境中至少有一个 CoreDNS 副本。CoreDNS 继续为网络断开之前创建的记录提供 DNS 查询,并继续运行网络重新连接以实现静态稳定性。
在网络断开连接期间,当它尝试列出来自 Kubernetes API 服务器的对象时,预计会出现以下 CoreDNS 日志消息。
Failed to watch *v1.Namespace: failed to list *v1.Namespace: Get "https://<k8s-cluster-ip>:443/api/v1/namespaces?resourceVersion=2263964": dial tcp <k8s-cluster-ip>:443: i/o timeout Failed to watch *v1.Service: failed to list *v1.Service: Get "https://<k8s-cluster-ip>:443/api/v1/services?resourceVersion=2263966": dial tcp <k8s-cluster-ip>:443: i/o timeout Failed to watch *v1.EndpointSlice: failed to list *v1.EndpointSlice: Get "https://<k8s-cluster-ip>:443/apis/discovery.k8s.io/v1/endpointslices?resourceVersion=2263896": dial tcp <k8s-cluster-ip>: i/o timeout