自从2012年正式成立,经过10的建设与发展,天翼云数据中心已经覆盖了全国所有主要城市,满足政府、教育、医疗和大中企业关键业务上云的需求。随着越来越多的多可用区资源池的上线,天翼云的基础设施建设也在计算资源利用,运维,开发效率等方面遇到了挑战。随着云原生转型概念的流行,天翼云也积极拥抱变化,积极加入到向云原生的队伍中。
天翼云基础设施向云原生主要为了以下几个目的:
- 控制成本:通过将基础设施控制面的应用容器化部署,同时引入统一的部署与调度平台,更加合理的分配部署应用的资源。配合容器集群的弹性伸缩机制,提高资源利用率,进一步降低了计算资源使用与运维的成本
- 提升效率:在业务应用的开发与发布方面,引入了标准化的发布工具与持续集成平台,实现应用在云平台上的快速部署,发布与升级。通过小步快跑的方式提高开发和发布效率
- 保证质量:通过提高底座平台的可观测性并建设全方位的监控告警体系,提前发现问题隐患,提高平台上业务运行稳定性,从而保证服务质量
背景与云原生网络的需求
天翼云底座在向云原生转型道路上的第一步是将所有线上线下业务进行容器化改造,并满足天翼云规模和业务上的特殊需求。为此天翼云云原生团队对 Kubernetes 集群的各个组件进行了深度定制,形成了包含容器集群,可视化运维与监控,应用发布与部署的一体化集群底座。集群底座目前已经支撑了天翼云在全国60多个资源池中基础设施的控制面和各种离在线业务的运行。天翼云基础设施从2019年开始全面的容器化改造,到目前为止已经完成了90%业务的容器化,并运行在容器底座上。
天翼云容器底座网络也在业务容器化改造过程中向更加云原生的方向发展。 天翼云基础设施的业务规模以及网络架构,对容器底座集群的网络提出了更多要求。首先是天翼云遍布全国的多地域多可用区中集群的组网需求。天翼云有遍布全国的数据中心,并且有 IDC 的 VLAN 网络与 SDN 提供的 VPC 两种节点网络。 容器底座要求容器集群能够跨可用区部署,并且无论是处于数据中心或是处于边缘机房的集群中的业务都能够用容器 IP 直接进行通信。
那么容器底座集群的云原生网络还面临哪些挑战呢?
首先是天翼云数据中心中异构网络环境的适应性问题。集群底座的节点可以是物理服务器,用于承载像是虚拟化等对计算资源有较高要求的业务。这些节点所处的网络一般是由VLAN进行隔离的物理网络。另外一部分集群节点使用了虚拟机实例,用于运行一些相对来说不太重要,但有弹缩需求的离线业务。这类节点处在 SDN 虚拟化的 VPC 网络中。底座要求集群网络方案能够连通处于两种网络架构节点中的容器,并且能够对集群用户向上屏蔽掉这两种网络的差异。
其次是跨集群的容器之间,以及容器与虚拟机之间的网络连通性问题。社区普遍的容器集群网络方案中,容器的 IP 地址一般来自集群的一个内网网段,这个网段中的地址只在集群内部有意义,不能从集群外直接访问。但在天翼云的集群底座网络中,要求某些在集群外以非容器化部署的应用,能够直接用容器的 IP 访问集群内的业务。同时不同集群中的业务,也要能够用对方集群的容器IP直接访问其他集群中的业务,这就对容器 IP 地址的固定与唯一性,以及跨集群的容器网络打通提出了更高的要求。
再就是容器网络的性能问题。首先是避免容器网络在跨节点通信时使用的隧道封包。在 IDC 的 VLAN 网络中,我们可以通过使用 Underlay 容器网络,将容器的网卡直接接入宿主机网卡所在的交换机,获得宿主机所在网段的 IP 地址来解决这个问题。在虚拟机节点网络中,由于出于安全考虑,VPC 网络一般不会放开伪传输和端口欺诈这样的选项,所以只能将容器的网卡挂载到分配给宿主机的额外的弹性网卡上。使用这两种方法可以使物理机和虚拟机节点中的容器,获得接近于宿主机网卡的网络性能,并且能够分配与宿主机同一子网中的 IP 地址,达到从集群外直接用容器 IP 访问容器内业务的效果。但这两种方案也有一定的缺点,就是对IP地址,弹性网卡这样的网络资源的消耗。由于天翼云的容器集群节点数量通常比较大,如果无论容器对网络的吞吐或者访问的需求一律接入宿主机所在的网络,无疑是对 IP 地址和弹性网卡的巨大浪费。所以容器底座还要求集群网络能够同时兼容 Overlay 网络,提高容器集群的兼容性和可扩展性。另外还需要支持容器挂载智能网卡,优化内核参数,利用 dpdk,eBPF 等高级内核功能,来加速容器网络。
最后是对集群网络的可观测性,可运维性以及易用性的要求。同时还要支持指定节点作为集群出网流量的网关。充分利用天翼云其他成熟的网络产品,例如负载均衡,云路由器,来扩展容器集群的功能,同时避免重复造轮子。
天翼云底座容器网络的云原生建设
然后我们带着上面的挑战与需求投入到了容器集群底座的建设当中。下图是在天翼云容器底座的架构中,我们投入建设工作的部分组件:
首先容器底座集群构建在天翼云各种基础设施之上,在单个底座集群当中,我们从下到上的利用内核的高级选项,将容器网络的 QoS, Underlay/Overlay 网络,网卡直通等需求,最终实现在了自研 CNI 插件中。同时通过天翼云在集群外提供的其他能力,例如负载均衡,网关,以及自研的跨集群的服务发现的 DNS 方案,提供集群到集群,外部到集群的访问打通方案。
为此天翼云云原生团队自主研发了集群底座专用的网络插件:CTCNI。相较于常见的开源 CNI 项目,CTCNI 实现了以下的特色功能:
- 同时兼容 VLAN 与 VPC 两种节点网络,并能够根据节点所在网络类型,决定容器网卡的挂载方式
- 在 VLAN 网络中支持 Underlay 容器网络,在 VPC 网络中支持容器挂载节点的弹性网卡。达到容器与宿主机处于同一网络的目的。
- 同时支持 Overlay 网络,这也是容器的默认挂载选项。在满足大多数容器的网络需求时,尽量降低对IP地址,弹性网卡等网络资源的消耗
- 支持智能网卡,使用了 dpdk,eBPF 等内核技术加速了容器网络栈
- 自动配置天翼云的负载均衡,云路由器等产品,扩展集群网络功能
CTCNI 的一个重要应用场景是打通服务器中非容器化部署的应用对集群内容器化应用的访问。虽然 Kubernetes 集群原生提供了诸如 Ingress,NodePort 等方案将集群内服务暴露到集群外,但在天翼云底座的云原生改造过程中,用户还是希望能够保留之前使用习惯,用固定的 IP 地址和端口访问容器化的应用服务。为此 CTCNI 通过将容器挂载弹性网卡,或者使用 Underlay 网络分配给容器宿主机所在网络的 IP,让集群外应用能用直接用这个 IP 地址访问到容器提供的服务:
另外为了还支持了在同一个集群内,Underlay,Overlay 和 弹性网卡三种网络并存。容器根据自己所在节点的网络类型,以及自己对网络功能需求,选择其中之一。下图中节点1和节点2中的容器处于集群中的 Overlay 网络,使用了集群内网段的 IP 地址,没有使用弹性网卡或者宿主机网络 IP。而节点3的容器则通过 Underlay 网络与宿主机处于同一子网,它的 IP 地址可以直接从集群外部访问到:
除了 CTCNI 内部实现的丰富功能以外,天翼云还提供了丰富的网络功能,例如负载均衡,弹性公网地址以及云路由器。利用这些外部产品,可以方便的扩展底座容器网络的功能。例如在前面提到的,容器底座集群有跨地域集群的互访需求,这可以在两个集群之间配置云路由器的路由规则来实现,达到两个集群间使用对方的容器 IP 来进行互访:
另外利用将弹性公网 IP 与固定的容器 IP 进行绑定,可以将容器内服务暴露给集群外的用户。利用弹性公网 IP 加负载均衡器的方式,可以在其后端绑定多个容器,配合健康检查可以达到流量分流与高可用的效果:
虽然使用 Underlay 网络或者弹性网卡避免跨节点隧道的封解包,已经让容器获得了近似与宿主机网卡的网络延迟与吞吐带宽。但是依然额外的使用了 veth 虚拟网卡对,Linux 网桥,iptables 这样的内核子系统来实现容器网卡,流量转发等功能,最终还是加长了容器网络栈的处理链路。为了进一步优化容器网络的性能, CTCNI 利用了 eBPF 这样的内核技术,对访问集群内容器服务的场景做出了优化。通过在容器网卡发送数据的链路中注入 eBPF 程序,直接将 Service IP 转换成后端容器的 IP 地址,从而绕过了 iptables 或者 ipvs 的规则匹配。另外对于容器直接访问集群外服务,或者集群外服务直接访问容器的场景,CTCNI 也通过将内核中的网络栈的处理工作,卸载到宿主机的智能网卡上,或者直接由应用程序包含进 dpdk,绕过内核的网络栈处理链路,进一步优化容器网络性能。
容器底座网络云原生化的落地实践
在底座集群网络的云原生化实践过程中,我们也遇到了一些在需求整理和建设初期未曾考虑到的问题。下面将从易用性,扩展性,可观测性三方面进行介绍。
易用性问题
首先遇到的是易用性问题。基于 CTCNI 的容器网络功能丰富,并且涉及了与众多类型的网络资源的交互。从功能方面讲,CTCNI 就支持了容器固定 IP,同时支持 Overlay 和 Underlay 网络,以及容器挂载智能网卡或者宿主机的弹性网卡等多种选择;而从涉及的网络资源方面看,又包含了 VPC,子网,弹性网卡,弹性 IP,路由规则等资源。要正确的配置这些资源来实现 CTCNI 丰富的功能,对云原生团队的开发者来说已经并非易事,对真正用户来说更是心智负担。例如要将一组容器通过负载均衡向集群外暴露,最初就需要手动的创建和配置负载均衡,监听器,监控检查,目标组等资源来达到目的。为了对用户屏蔽掉繁琐重复的配置流程将用户从中解放出来,但又同时对用户保持配置状态的透明,云原生团队决定使用声明式的方案配置和管理这些网络资源。我们各种网络资源类型扩展成为 Kubernetes 集群的资源,并为每种资源开发相应的 Operator,将资源的配置工作根据期望的状态由 Operator 调用天翼云平台的 OpenAPI 自动完成。用户只需要在容器工作负载中声明希望如何暴露服务,一切资源就会被自动创建和配置,用户也可以查询这些资源的状态。
跨集群的服务发现
其次是跨集群的服务发现问题,因为天翼云容器底座要求集群容器可以跨集群用容器 IP 直接通信。而从服务名到容器 IP 的转换有两种方法:
- 用 Nacos 这样的服务注册和发现方案,中心化的提供服务名到 IP 地址的查询服务。但这要求使用方编写查询逻辑的代码,有一定侵入性
- 实现一个全局的 DNS 服务,作为所有集群的 DNS 上游服务器,负责服务名到 IP 地址的解析工作。但这也有服务不稳定,延迟大,因为缓存原因解析结果不准确等问题
而且两种方案都需要服务提供方以某种方式将域名和 IP 注册,虽然容器 IP 地址可以固定,但仍然是一种心智负担。所以天翼云云原生团队实现了自己的解决方案:CTDNS。为了解决自动服务注册的问题,CTDNS 的方法是:
- 运行一个中心化的 Nacos 集群,用于服务注册和发现
- 在集群中运行一个 Mutation Webhook,监听并判断一个容器是否需要将其 IP 和域名注册到 Nacos。如果是,则向 Pod 注入一个初始化容器。
- 初始化容器在运行时获取域名与容器的 IP 地址,并向 Nacos 注册。
而为了解决服务发现的问题,CTDNS 在集群中运行了另一个 DNS 服务,设置成为了集群 CoreDNS 的上游服务器。该DNS服务器监听 Nacos 集群所有记录的更新,并将解析记录缓存在本地。当集群中容器有解析需求时,会立即返回给 CoreDNS 最新的解析结果。
上面介绍的CTDNS 注册和解析服务的工作流程大致如下图所示:
集中式出集群网关
在一般的集群容器网络的实现中,容器访问集群外的服务的出网节点是当前的宿主机节点。在 Underlay 和弹性网卡作为容器网卡的方案中,由于容器 IP 来自于宿主机网络网段且是唯一的,可以使用安全组来对其进行限制。在 Overlay 网络中,服务端看到的请求源 IP 就是当前节点的 IP。容器底座出于安全,流量审计以及对请求来源IP设置白名单的需求,要求集群所有的出网流量通过指定的节点流出集群,并支持出网节点的高可用。CTCNI 根据对出网网关这样的扩展资源的配置,通过配置每个节点上的流表,实现了这个功能。
可观测性
虽然网络资源声明式的管理方式可以向用户和运维人员展示资源的当前状态。但是对于集群中每个节点和容器的网络状态和各种实时指标,需要进行额外的采集和展示,来提高底座容器网络的可观测性。通过在每个节点运行专门的网络指标的 exptor,将网络控制平台信息以及数据平面质量信息以 Prometheus 所支持的格式对外暴露,并由 Dashboard 进行可视化的展示。同时天翼云的统一监控平台也会监控相关指标,并对异常进行告警。
总结
天翼云容器底座目前已经支撑了天翼云60个线上资源池业务的运行。从功能上将,它兼容了各地异构的主机网络,支持跨集群的容器之间访问。通过自研的跨集群服务发现机制与天翼云的其他网络产品,扩展了云原生网络功能。在性能上,通过 eBPF,dpdk,智能网卡卸载等方案,进一步提升了容器网络的性能。在易用性和可观测性上,更以声明式和指标可视化的方式,使天翼云容器底座网络以更加云原生的方式工作。