从美图容器优化实践谈Kubernetes网络方案设计

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本文通过介绍美图线上容器化的实践经验,包括线上遇到的实际问题,来探讨 Kubernetes 环境下的网络方案设计。值得正在转型 K8S 的架构师学习和借鉴。 李连荣,美图高级系统研发工程师,曾建立支持千万的长连接服务,从零开始在建立美图的容器化服务,并主导完成美图容器化的网络方案。

本文通过介绍美图线上容器化的实践经验,包括线上遇到的实际问题,来探讨 Kubernetes 环境下的网络方案设计。值得正在转型 K8S 的架构师学习和借鉴。

李连荣,美图高级系统研发工程师,曾建立支持千万的长连接服务,从零开始在建立美图的容器化服务,并主导完成美图容器化的网络方案。在网络、存储方面有非常深厚的造诣。

目前,我们的 Kubernetes 集群选择使用 Calico 作为基础网络方案。


选择 Calico 网络方案的挑战

Calico 是一套基于路由(BGP)的 SDN,它通过路由转发的方式实现容器的跨主机通信。Calico 将每个节点虚拟为一个“路由器”并为之分配独立的虚拟网段,该路由器为当前节点上的容器提供路由服务。

更多 Calico 项目介绍可参阅 https://www.projectcalico.org/ 下面以具体网络为例介绍其中的设计与难点。

以上图为例,如果节点 192.168.1.2 分配的虚拟网段是 10.233.1.0/24,其上运行了一个容器 10.233.1.2,其路由信息如下:

10.233.1.2 0.0.0.0 255.255.255.255 UH 0 0 0 cali814214d5913

当物理机收到目标地址为10.233.1.2 的IP 数据包时会转发到网口 cali814214d5913,而 cali814214d5913 是通过 veth-pair 创建的网卡,它与本机上 IP 地址为 10.233.1.2 的容器互通,因此,IP 地址为 10.233.1.2 容器就可以收到相应的 IP 数据包。

当位于节点 192.168.1.3 上的容器 10.233.2.2 给 10.233.1.2 发送 IP 数据包时,需要知道 10.233.1.2 所在的物理节点的 IP,并添加以下路由规则:

10.233.1.0/16 192.168.1.2 eth0

Calico 通过 BGP 实现节点间相互学习路由规则。节点 192.168.1.2与节点192.168.1.3 建立 BGP 邻居,节点 192.168.1.3 可以通过 BGP 学习到上面的路由规则。当容器 10.233.2.2 发送 IP 数据包给 10.233.1.2 时,会根据上面的路由规则转发到节点 192.168.1.2,并由节点 192.168.12 转发给 10.233.1.2,进而实现容器的跨主机通信。

但是当两个容器所在的节点处于不同的子网时,如10.233.3.2,其所在的节点192.168.2.2与节点192.168.1.2处于不同的子网,此时无法在192.168.2.2上添加以下路由:

10.233.1.0/16 192.168.1.2 eth0

这是因为物理机 192.168.2.2与物理机 192.168.1.2 链路层不通。为了解决这个问题,Calico 选择了 IPIP。IPIP 是将虚拟网络的 IP 数据包封装到物理网络的 IP 数据包里传输。启用 IPIP 后,节点上会出现相应的虚拟网卡,通常是 tunl0,节点1 92.168.2.2 可以添加以下路由规则:

10.233.1.0/16 192.168.1.2 tunl0

与之前的路由的区别在网口换成了 tunl0。当 10.233.3.2 发送 IP 数据包给10.233.1.2 时,其所在的节点会将 IP 数据包转发到网口 tunl0,转发到 tunl0 的 IP 数据包会被 IPIP 驱动接管。IPIP 驱动会将每个 IP 数据包封装到物理网络的 IP 数据包内(目标地址是下一跳地址,即 192.168.1.2,Payload 是虚拟机发出的原始 IP 数据包)发送出去。

由于该 IP 数据包的目标地址是节点 192.168.1.2,因此,可以经过物理网关进行转发。运行在节点 192.168.1.2 上 IPIP 服务接收到该物理网络 IP 数据包后将其 Payload 取出,再根据节点 192.168.1.2 上路由规则转发给相应的容器,进而实现了容器的跨子网通信。

Calico 网络方案存在的问题

通过 Calico 的工作原理可以看出,Calico 存在以下问题:

  • 使用 IPIP 时,需要嵌套 IP 协议,多余的打包和拆包动作会带来的性能开销。
  • 使用 IPIP 时,嵌套的 IP 协议头导致实际有效的 MTU 长度变小,也会影响实际的带宽利用率。
  • 由于集群外的节点无法学习集群内的路由信息,故无法直接访问集群内的容器。

根据 Calico 的工作原理可知,Calico 为了解决容器的跨子网通信选择了 IPIP,也正是因为引入了 IPIP 才引发了一系列的性能问题,那么,为什么 Calico 会选择 IPIP 协议呢?

为了理解这个问题,我们先看一下传统的物理网络是如何解决跨子网通信的。仍以上图为例,物理机 192.168.2.3 访问物理机 192.168.1.2 的步骤如下:

  • 物理机 192.168.2.3 检测到目标 IP 与自己处于不同的子网,因此,通过默认路由规则发送给其所在网关 192.168.2.1。
  • 物理网关 192.168.2.1 通过路由协议可以知道网关 192.168.2.1 可以转发 IP 包给物理 192.168.1.2,因此,将相应的 IP 包转发给网关 192.168.1.1。
  • 物理网关 192.168.1.1 再将 IP 包转发给物理机 192.168.1.2。

我们再来看一下 Calico 网络。如果没有 IPIP,容器 10.233.4.2 访问容器 10.233.1.2 的步骤如下:

  • 宿主机 192.168.2.3 检测到目标 IP 与自己处于不同的子网,因此,会将目标地址为 10.233.1.2 的 IP 包转发给其所在网关 192.168.2.1。
  • 网关 192.168.2.1 没有匹配的路由规则,因此 drop 该 IP 包并会返回目标不可达。

如果引入 IPIP,容器 10.233.4.2 访问容器 10.233.1.2 的步骤如下:

  • 宿主机 192.168.2.3 匹配到路由规则 “10.233.1.0/16 192.168.1.2 tunl0”。
  • 宿主机 192.168.2.3 将该容器发出的 IP 包通过 tunl0 端口转发到物理机192.168.1.2。
  • IPIP 驱动将容器发出的 IP 包(目标地址 10.233.1.2)作为物理网络 IP 包(目标地址 192.168.1.2)的 Payload 发出。
  • 宿主机 192.168.2.3 按照物理网络的传输方式将物理网络 IP 包发送到宿主机 192.168.1.2。
  • 宿主机 192.168.1.2 上 IPIP 驱动接收到该 IP 包之后解包并将该 Payload 作为 IP 包转发给容器 10.233.1.2。

因此,在物理网关不能为虚拟网络提供路由服务的前提下,Calico 选择使用 IPIP 的方式来解决容器的跨子网通信。

如果通过某种方法,让物理网关能够学习到 Calico 虚拟网络的路由规则,那么物理网关就可以为虚拟网络提供路由服务,Calico 就可以在不引入 IPIP 的前提下实现容器的跨子网通信,但是,Calico 为什么没有选择这种方式呢?

这是因为 Calico 的主要应用场景是公有云,公有云具备以下特性:

  • 多数公有云厂商可以提供一个稳定的大二层环境,其内的主机可以工作在同一个子网段,也就不存在跨子网通信的问题
  • 不是所有的公有云厂商都可以提供 BGP 路由学习的接口,如果云厂商不提供 BGP 接口,Calico就无法同步虚拟网络路由规则给公有云

因此,在这个前提下,Calico 选择 IPIP 方式是非常合理的。

对于私有云场景:

  • 不是所有的私有云环境都支持大二层,对 Calico 跨子网通信的需求是非常强烈的。
  • 所有硬件(包括网关)都在可控范围内,只要物理网关支持 BGP 协议,Calico 就可以同步路由规则给物理网关。

因此,对于私有云场景,通过让 Calico 同步虚拟网络路由规则给物理网关的方式来解决跨子网通信会是更好的选择。

性能提升方案

其实 Calico 的文档中提到了一种同步路由规则给物理网关的方式,具体可以参考如下链接:

https://docs.projectcalico.org/v2.6/usage/external-connectivity

本文参考这种设计,将虚拟网络路由规则同步给物理网关,虚拟网络与物理网络建立 BGP 邻居的方式有两种:

  • 方案一:各节点分别物理网关建立 BGP 邻居
  • 方案二:中心化组件与物理网关建立 BGP 邻居

下面针对两种方案进行分析。

方案一

如下图所示,方案一需要每个 SDN 节点分别与其所在的物理网关建立 BGP 邻居。由于每个 SDN 节点作为本机容器的网关,如果运行在该物理机上 Calico 服务能够与物理网关建立 BGP,并将自己的路由规则同步给物理网关,那么,物理网关就可以学习虚拟网络的路由规则。

运行在节点上的 SDN 服务可以通过编码或者脚本实现自动建立 BGP 邻居的逻辑,但是,这也需要物理网关的支持。如果物理网关不支持自动建立 BGP 邻居,仅仅是在 SDN 端实现是没有意义的。

传统的 BGP 路由器需要逐个配置 BGP 邻居,这对容器化集群来说是不可接受到。因为容器化集群的规模一般都比较大,在集群使用过程中也会经常的调整节点,如扩容、缩容、机器故障等。如果每次调整节点都需要运维手动完成 BGP 邻居的配置,运维成本是巨大的,而且容易因误操作而影响集群稳定性,因此,需要网关支持自动建立 BGP 邻居。

要实现自动建立 BGP 邻居需要使用支持 Dynamic Neighbors 功能的路由器。传统的路由器在配置 BGP 邻居时需要指定明确的 IP 地址,而支持 Dynamic Neighbors 的路由器可以指定一个 IP 网段,该路由器可以自动接受指定网段内BGP设备发起的建立邻居的请求。

集群部署前先配置好路由器的 Dynamic Neighbors,调整集群节点时运行在节点上的 SDN 服务主动与之建立 BGP 邻居,并将其所在节点的路由信息同步给物理网关。例如,运行在物理机 192.168.1.2 上的 SDN 服务自动与物理网关 192.168.1.1 建立 BGP 邻居(eBGP)并将以下路由规则同步给物理网关:

10.233.1.0/24 192.168.1.2 eth0

物理网关 192.168.1.1 学习到以上规则之后会通过 BGP 或者其它路由同步协议同步给物理网关 192.168.2.1,通过这种方式,整个物理网络都可以学习上以上规则。集群的容器要发送数据到 10.233.1.0/24 网段时,直接通过其宿主机将数据包发送给物理网关,物理网关即可根据其学到的虚拟网络路由信息转发到目标主机,最后,再由目标主机转发给相应的容器。

方案二

方案二需要引入中心化组件,本文称之为 BGP Speaker,其网络结构如下:

BGP Speaker 运行在 SDN 集群内,它负责收集 SDN 集群内的路由信息并通过BGP 同步给物理网关。由于该模块可以收集 SDN 集群内的全部路由信息,故不再需要每个 SDN 节点单独与物理网关建立 BGP 邻居,也就不再依赖物理网关的的 Dynamic Neighbors 功能。

如下图所示,BGP Speaker 主要分为两部分:observer 和 publisher。

  • observer:负责收集 SDN 集群的路由信息。
  • publisher:将 observer 收集到的路由信息同步给物理网关。

Calico 将 SDN 集群相关的信息(包括配置信息、每个节点的虚拟网段等)保存在 etcd 里,而 etcd 的支持 watch,因此,observer 可以通过watch方式实时获取 Calico 集群的节点信息。observer 主要关注每个 SDN 节点划分的虚拟网段信息,并根据获取到的虚拟网段信息生成对应的路由规则,如节点 192.168.1.2 划分的虚拟网段是 10.233.1.0/24,observer 会生成以下路由规则:

10.233.1.0/24 192.168.1.2 eth0

publisher 实现了 BGP 协议,它与物理网关建立 BGP 邻居(eBGP),主要工作是将 observer 收集到的路由信息同步给物理网关。由于 publisher 需要将不同节点的路由信息同步给物理网关,因此,publisher 对物理网关来讲,实际上是个 BGP Route Reflector。

gobgp 提供了开源的 BGP 协议库,支持完整的 BGP 协议,可以作为 publisher的基础库。另外,BGP 是双向的,publisher 不仅可以将自己持有的路由信息同步给物理路由器,物理路由器也会同步路由信息给 publisher,由于 SDN 不需要了解物理网络的路由信息,因此,publisher 可以过滤掉这些路由信息。

由于 BGP Speaker 是中心化部署的,因此 BGP Spaker 的高可用程度会直接影响 SDN 集群的稳定性。BGP Speaker 直接从 SDN 集群的 etcd 存储中获取集群信息,其自身不需要保存任何数据(包括生成的路由信息),故 BGP Speaker是无状态的,因此,只需要在 SDN 集群内部署多套 BGP Speaker 即可实现高可用。

多套 BGP Speaker 之间相互不感知,各自独立运行。部署 BGP Speaker时,还可以根据物理网络的拓扑结构将 BGP Speaker 部署在不同的机架或者机房,保证某个机架或机房出现故障时 SDN 集群仍可正常工作。

安全隐患

以上两种方案都可以实现物理网络与虚拟网络的互通,但两种方案都是虚拟网络通过 BGP 协议自动的同步路由规则给物理网关,如果虚拟网络产生了错误的路由规则或者产生的路由规则与物理网络冲突,就会影响集群所处物理网络的运行状态;如果同一物理网络内部署了多套 SDN 集群且这多套 SDN 的网段有冲突时,也会造成虚拟网络的路由规则紊乱,影响 SDN 的稳定性。

因此,还需要采取一些措施来保证 SDN 之间以及 SDN 与物理网络之间不冲突。

确保 SDN 与物理网络不冲突

现在的物理网关大多都支持路由过滤,也就是说当网关通过 BGP 学习到新的路由规则时,可以根据一定的规则进行过滤,只有满足要求的路由规则,才会同步到自己的路由表。部署容器化集群时,应先规划好 SDN 的网络地址,要保证 SDN 的网络地址与物理网络不冲突。

配置物理网关时,可以通过设置过滤规则来保证 SDN 不能修改其所属网段以外的任何任何路由规则(例如,限制 SDN 只能更新目标地址处于 10.233.0.0/16 网段内的路由规则),通过这种方式,可以确保 SDN 不会影响物理网络稳定性。

确保 SDN 之间不冲突

物理网络与虚拟网络互通后,部署在同一个物理网络内的多个 SDN 集群的路由信息都会同步到物理网关,如果不同 SDN 的网络地址有重叠,就会引发冲突,导致 SDN 网络无法稳定工作,因此,在部署 SDN 集群时,还需要为不同的 SDN 集群分配不同的网络地址(这些地址都与物理网络不冲突)。配置网关时,限制每个 SDN 只能同步处于自己网络地址内的路由规则。

总结

Calico 存在性能问题的根本原因是物理网络与虚拟网络不互通,本文设计了两种方案实现物理网络与虚拟网络的互通,解决了 Calico 引入 IPIP 和 NAT 带来的性能问题,也带来了一定的安全隐患,但是,可以通过额外的保障措施排除安全隐患,保证物理网络与 SDN 网络的稳定运行。

本文转自kubernetes中文社区-从美图容器优化实践谈Kubernetes网络方案设计

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
11天前
|
运维 Kubernetes Cloud Native
探索Kubernetes的大二层网络:原理、优势与挑战🚀
在云原生领域,Kubernetes (K8s) 已经成为容器编排的事实标准☁️📦。为了支撑其灵活的服务发现和负载均衡🔍🔄,K8s采用了大二层网络的设计理念🕸️。本文将深入探讨大二层网络的工作原理、带来的好处✨,以及面临的挑战和解决方案❗🛠️。
探索Kubernetes的大二层网络:原理、优势与挑战🚀
|
17天前
|
Kubernetes 容器
k8s容器时间与服务器时间不一致问题
k8s容器时间与服务器时间不一致问题
17 0
|
2天前
|
网络协议 Java API
深度剖析:Java网络编程中的TCP/IP与HTTP协议实践
【4月更文挑战第17天】Java网络编程重在TCP/IP和HTTP协议的应用。TCP提供可靠数据传输,通过Socket和ServerSocket实现;HTTP用于Web服务,常借助HttpURLConnection或Apache HttpClient。两者结合,构成网络服务基础。Java有多种高级API和框架(如Netty、Spring Boot)简化开发,助力高效、高并发的网络通信。
|
3天前
|
监控 安全 网络安全
云端防御:云计算环境中的网络安全策略与实践
【4月更文挑战第15天】 在数字化转型的时代,云计算已成为企业运营不可或缺的技术支撑。然而,随着云服务模式的广泛采纳,网络安全挑战亦随之而来。本文深入探讨了云计算环境下的安全威胁,分析了云服务模型对安全策略的影响,并提出了一系列创新的网络安全防护措施。通过研究最新的加密技术、访问控制机制和持续监控方法,文章旨在为企业提供一个综合性的网络安全框架,以确保其云基础设施和数据的安全性和完整性。
20 8
|
6天前
|
JSON Kubernetes Go
无缝集成:在IntelliJ IDEA中利用Kubernetes插件轻松管理容器化应用
无缝集成:在IntelliJ IDEA中利用Kubernetes插件轻松管理容器化应用
15 0
无缝集成:在IntelliJ IDEA中利用Kubernetes插件轻松管理容器化应用
|
10天前
|
安全 网络安全 网络虚拟化
虚拟网络设备与网络安全:深入分析与实践应用
在数字化时代📲,网络安全🔒成为了企业和个人防御体系中不可或缺的一部分。随着网络攻击的日益复杂和频繁🔥,传统的物理网络安全措施已经无法满足快速发展的需求。虚拟网络设备🖧,作为网络架构中的重要组成部分,通过提供灵活的配置和强大的隔离能力🛡️,为网络安全提供了新的保障。本文将从多个维度深入分析虚拟网络设备是如何保障网络安全的,以及它们的实际意义和应用场景。
|
18天前
|
安全 算法 网络安全
网络安全与信息安全:防范之道与实践策略
在数字化时代,网络安全与信息安全已成为全球关注的焦点。本文将深入探讨网络安全漏洞的成因、加密技术的最新发展以及提升安全意识的重要性。通过对这些关键领域的分析,我们旨在为读者提供一套综合性的策略,以增强个人和组织在网络空间的防护能力。
|
20天前
|
Kubernetes Shell Docker
K8S核心插件-Flannel网络插件
K8S核心插件-Flannel网络插件
35 0
|
25天前
|
监控 安全 网络安全
云计算环境下的网络安全新策略与实践
在数字化时代,云计算为企业提供了弹性、可扩展的资源管理平台,但同时也带来了复杂的安全挑战。本文聚焦于云服务中的网络安全和信息保护问题,首先分析了云计算环境中存在的安全威胁和风险因素,然后详细探讨了当前最新的安全技术和策略,包括身份认证、数据加密、入侵检测系统以及安全运营中心(SOC)等。最后,文章提出了一套综合的安全框架,旨在帮助组织在享受云计算便利的同时,确保其数据和资源的安全性和完整性。
|
27天前
|
运维 安全 网络安全
Python灰帽子网络安全实践
旨在降低网络防范黑客的入门门槛,适合所有中小企业和传统企业。罗列常见的攻击手段和防范方法,让网站管理人员都具备基本的保护能力。Python 编程的简单实现,让网络运维变得更简单。各种黑客工具的理论和原理解剖,让人知其然更知道防范于未来。涉及互联网和局域网,让企业级网管工作更轻松。涵盖Linux&Windows 的知识点。
14 1

相关产品

  • 容器服务Kubernetes版