作者 | 溪恒 阿里云技术专家
直播完整视频回顾: https://www.bilibili.com/video/BV1nC4y1x7mt/
关注 "阿里巴巴云原生" 公众号, 后台回复 "416" 即可下载 PPT.
4 月 16 日, 我们发起了第 2 期 SIG Cloud-Provider-Alibaba 网研会直播. 本次直播主要介绍了阿里云在云原生环境中如何设计和构建高性能云原生容器网络. 本文汇集了此次直播完整视频回顾及资料下载, 并整理了直播过程中收集的问题和解答, 希望能够对大家有所帮助~
本文汇集了此次直播完整视频回顾及资料下载, 并整理了直播过程中收集的问题和解答, 希望能够对大家有所帮助~
前言
首先, 给大家介绍一下 Cloud Provider SIG, Cloud Provider SIG 是 Kubernetes 的云厂商兴趣小组, 致力于让 Kubernetes 的生态系统往厂商中立的方向演进, 他会负责协调不同厂商尽可能以统一的标准来满足开发者的需求. 阿里云作为国内首个加入 Cloud Provider SIG 的云厂商也在推动 Kubernetes 的进一步标准化, 并进一步和横向云厂商如 AWS,Google,Azure 进行技术协同, 优化云和 Kubernetes 连接, 并统一不同组件的模块化和标准化协议. 非常期待你与我们一同共建.
第 1 期网研会回顾: Kubernetes SIG-Cloud-Provider-Alibaba 首次网研会(含 PPT 下载)
随着云原生计算的普及, 越来越多的应用负载都部署在 Kubernetes 之上, Kubernetes 已成为云原生计算的基石, 成为用户和云计算新的交互界面. 而网络作为应用的最基础的依赖之一, 在应用云原生化中是必不可少的基础组件, 也是很多开发者在云原生化时最担心的地方, 面临很多问题, 例如容器网络跟原有机器网络不在一个平面, 容器的 Overlay 容器网络带来了封包的性能损失, Kubernetes 的负载均衡和服务发现的可扩展性不足等等. 那么怎样才能构建集群容器网络呢?
本次分享将会介绍阿里云在云原生环境中如何设计和构建高性能云原生容器网络.
今天的分享将从 3 个方面进行:
Kubernetes 容器网络概述
构建高性能云原生 CNI 网络
增强网络的扩展性和性能
Kubernetes 容器网络概述
首先我们会介绍下 Kubernetes 容器网络的基础概念, 包括:
Pod 网络连通性(CNI)
Kubernetes 负载均衡(Service)
Kubernetes 服务发现(Coredns)
Pod 网络连通性(CNI)
如下所示是 Kubernetes Pod 网络示意图:
首先我们会介绍 Pod 网络的连通性, 这里就是我们常说的 CNI 网络, 主要包含了以下内容:
Pod 有自己独立的网络空间和 IP 地址. 不同 Pod 的应用可以监听同样的端口而不冲突;
Pod 可以通过各自的 IP 地址互相访问. 集群中 Pod 可以通过它独立的 IP 地址访问其它网络: Pod 和 Pod 的联通; Pod 与 Node 的联通; Pod 与外部网络连通.
而实现这些网络的能力, 需要地址分配和网络打通, 通常是由网络插件 (CNI) 来负责实现的.
什么是 CNI
CNI 插件即 Container Network Interface, 是 K8s 配置容器网络的 API 接口. CNI 插件就是实现了这个 API 的一系列网络插件, 例如我们常见的有 Terway,Flannel, Calico 等等.
在我们创建 Pod 时:
Kubelet 会首先从 ApiServer 监听到 Pod 的创建, 会创建 Pod 的沙箱;
然后通过 CNI 接口调用 CNI 的插件去配置容器的网络;
CNI 会配置 Pod 的网络空间, 以及打通不同 Pod 之间的网络访问.
如何打通的网络?
通常 Pod 跟宿主机网络不在一个平面, 要如何打通 Pod 之间通信呢? 一般实现 Pod 之间联通的方案有两种:
封包方式: 容器之间的通信报文封装成宿主机之间通信的报文;
路由方式: 容器之间的通信报文由路由表转发到对应的节点上.
Kubernetes 网络负载均衡(Service)
为什么需要 Kubernetes Service? 原因如下:
Pod 生命周期短暂, IP 地址随时变化, 需要固定的访问方式;
Deployment 等的一组 Pod 组需要统一访问入口和做负载均衡.
Kubernetes Service
Kubernetes Service 对象创建会分配一个相对固定的 Service IP 地址;
通过 labelSelector 选择到一组 Pod, 将这个 Service IP 地址和端口负载均衡到这一组 Pod IP 和端口上;
从而实现一组 Pod 固定的访问入口, 并对这一组 Pod 做负载均衡.
Kubernetes LoadBalancer Service
Kubernetes 服务发现(DNS)
虽然 Service 固定了 IP 访问方式, 但 Service 的 IP 在不同的 namespace 或者集群中是不同的, 如何统一?
集群的 Coredns 会将 Service 名自动转换成对应的 Service 的 IP 地址, 来实现不同部署环境中同样的访问入口.
构建高性能云原生的 CNI 网络
什么是云原生容器网络?
云上 IaaS 层网络虚拟化, 在容器中再做一层网络虚拟化带来的性能损失比较大.
云原生容器网络是直接使用云上原生云资源配置容器网络:
容器和节点同等网络平面, 同等网络地位;
Pod 网络可以和云产品无缝整合;
不需要封包和路由, 网络性能和虚机几乎一致.
在 CNI 调用中调用云网络 OpenAPI 完成网络资源分配:
网络资源一般是弹性网卡, 弹性网卡辅助 IP 等, 绑定到 Pod 所在的节点上;
网络资源分配出来之后 CNI 插件在宿主机中将资源配置到 Pod 的沙箱中.
由于容器的网络直接成为了 VPC 中的一等公民, 所以使用云原生容器网络会有这些优势:
Pod 和虚拟机同一层网络, 便于业务云原生化迁移;
不依赖封包或者路由表, 分配给 Pod 的网络设备本身可以用来通信;
集群节点规模不受路由表或者封包的 FDB 转发表等 Quota 限制;
不需要额外为 Pod 规划 Overlay 的网段, 多个集群 Pod 之间只要安全组放开就可以互相通信;
可以直接把 Pod 挂到 LoadBalancer 后端, 无需节点上端口再做一层转发;
NAT 网关可以对 Pod 做 SNAT, 无需节点上对容器网段做 SNAT:Pod 访问 VPC 内资源, 所带的源 IP 都是 PodIP, 便于审计; Pod 访问外部网络不依赖 conntrack SNAT, 失败率降低.
如何利用云原生资源构建容器网络?
IaaS 层网络资源(以阿里云为例):
弹性网卡(ENI). IaaS 层虚拟化出来的虚拟网卡, 可动态分配和绑定到虚拟机上; 一般能绑定数量有限, 受限于 PCI-E 的限制;
弹性网卡辅助 IP. 弹性网卡上通常可以绑定多个 VPC 的 IP 地址, 为辅助 IP; 一个弹性网卡可以绑定数十个辅助 IP 地址, 限制较小.
利用弹性网卡或者弹性网卡辅助 IP 分配给 Pod 来实现云原生容器网络:
容器网络资源管理
如何解决云资源跟容器快速扩缩容的差距:
容器的启动速度是秒级的, 而 IaaS 层操作和调用一般在 10s 的级别;
容器扩缩容操作频繁, 云产品 OpenAPI 通常有严格的调用限流.
Terway 通过内置资源池来缓冲资源加速启动:
资源池中记录分配的正在使用和空闲的资源;
Pod 释放后资源会保留在资源池中供下次快速启动;
资源池有最低水位和最高水位. 空闲资源低于最低水位调用 API 补充资源, 预热资源减缓峰值 Pod 创建对 API 的调用; 空闲资源高于最高水位调用 API 释放资源.
对并行的 Pod 网络配置调用批量申请资源:
除此之外还有很多资源管理策略, 例如: 如何选择 Pod 要用的虚拟交换机, 保证 IP 充裕? 如何平衡每个节点上的网卡的队列和中断数, 保证争抢最少?
可参考 Terway 文档或代码: https://github.com/AliyunContainerService/terway .
网络如何打通
Pod 独占弹性网卡模式:
它的在 CNI 的实现方式是:
通过 Terway 资源管理将弹性网卡绑定 Pod 所在 Node;
Terway CNI 将网卡直接移入到 Pod 网络空间;
Terway CNI 为其网卡配置 IP 和路由等网络配置.
这种方式的特点和优势是:
Pod 网络完全不经过宿主机网络栈
性能和 ECS 机器一致, 无损耗
Pod 中为弹性网卡, 可以使用 DPDK 等加速应用
Pod 共享弹性网卡模式:
它的在 CNI 的实现方式是:
Terway 资源管理器根据申请的 IP 数量和现有 ENI 上 IP 来判断申请 ENI 还是辅助 IP 地址
Terway CNI 在 ENI 上创建 IPVLAN 子接口
将 IPVLAN 子接口放入到 Pod 网络空间
配置 Pod 网络空间的 IP 和路由信息
这种方式的特点和优势是:
IPVLAN 网络仅部分经过网络栈, 不走 iptables, 路由表, 损耗极低
一个弹性网卡一般支持 10~20 个辅助 IP, 不担心部署密度
性能对比
TCP_RR,UDP,PPS, 带宽和延时都优于通用的 Flannel Vxlan 的 Overlay 网络;
独占 ENI 模式可以跑满机器的网络资源 PPS 和带宽无损失, 适合于高性能计算和游戏场景.
增强 Kubernetes 网络扩展性和性能
Kubernetes Service 性能和扩展性问题
默认的 Kubernetes 的 Service 实现 kube-proxy, 它是使用了 iptables 去配置 Service IP 和负载均衡:
如上图所示:
负载均衡过程的 iptables 链路长, 导致网络延时显著增加, 就算是 ipvs 模式也是绕不开 iptables 的调用;
扩展性差. iptables 规则同步是全量刷的, Service 和 Pod 数量多了, 一次规则同步都得接近 1s;Service 和 Pod 数量多了之后, 数据链路性能大幅降低.
NetworkPolicy 性能和扩展性问题
NetworkPolicy 是 Kubernetes 控制 Pod 和 Pod 间是否允许通信的规则. 目前主流的 NetworkPolicy 实现基于 iptables 实现, 同样有 iptables 的扩展性问题:
iptables 线性匹配, 性能不高, Scale 能力差
iptables 线性更新, 更新速度慢
使用 eBPF 加速 Service 和 NetworkPolicy 扩展性
关于 eBPF 的介绍如下:
Linux 在最近版本提供的可编程接口
通过 tc-ebpf 将 ebpf 程序注入到网卡中
用于大幅降低网络链路的长度和复杂度
如上图所示, 使用 tc 工具注入 eBPF 程序到 Pod 的网卡上, 可以直接将 Service 和 NetworkPolicy 在网卡中解决, 然后直接转发到弹性网卡, 大幅降低网络复杂度:
每个节点上运行 eBPF Agent, 监听 Service 和 NetworkPolicy, 配置容器网卡的 Ingress 和 Egress 规则;
在 Egress 的 eBPF 程序中, 判断访问 k8s Service IP 的请求直接负载均衡到后端 Endpoint;
在 Ingress 的 eBPF 程序中, 根据 NetworkPolicy 规则计算源 IP 决定是否放行.
PS: 我们使用 Cilium 作为节点上的 BPF-agent 去配置容器网卡的 BPF 规则, 已贡献 Terway 相关适配: https://github.com/cilium/cilium/pull/10251
性能对比
通过 eBPF 对链路的简化, 性能有明显提升, 相对 iptables 提升 32%, 相对 ipvs 提升 62%;
通过编程的 eBPF 的形式, 让 Service 数量增加到 5000 时也几乎没有性能损耗, 而 iptables 在 Service 增加到 5000 时性能损失了 61%.
Kubernetes Coredns 性能和扩展性问题
Kubernetes Pod 解析 DNS 域名会 search 很多次, 例如上图 Pod 中 DNS 配置, 当它请求 aliyun.com, 会依次解析:
- aliyun.com.kube-system.svc.cluster.local -> NXDOMAIN
- aliyun.com.svc.cluster.local -> NXDOMAIN
- aliyun.com.cluster.local -> NXDOMAIN
- aliyun.com -> 1.1.1.1
Coredns 是中心化部署在某一个节点上的, Pod 访问 Coredns 解析经过链路过长, 又是 UDP 协议, 导致失败率高.
使用 AutoPath 大幅降低 Pod DNS 的查询量
由客户端 Search 变成服务端 Search:
当 Pod 请求 Coredns 时解析域名:
Coredns 会通过源 IP 地址查询到 Pod 的信息
然后根据 Pod 的 Namespace 信息, 匹配到它真正想访问的是哪个服务直接返回
客户端请求从 4 个直接减少到 1 个, 降低了 75% 的 Coredns 请求, 从而让失败率降低
在每个节点上使用 node-local-dns
拦截 Pod 的 DNS 查询的请求
将外部域名分流, 外部域名请求不再请求中心 Coredns
中间链路使用更稳定的 TCP 解析
节点级别缓存 DNS 解析结果, 较少请求中信 Coredns
ExternalDNS 直接使用阿里云的域名解析服务
云原生的 DNS 解析, Pod 直接请求云服务 PrivateZone 中的自定义 DNS 能力
由 ExternalDNS 监听到服务和 Pod 创建后配置 PrivateZone 中的域名解析
和原生的 ECS 解析同样的 DNS 解析性能
总结
以上就是阿里云的高性能云原生的容器网络设计和构建过程, 随着云原生的不断发展, 会有越来越多类型的应用负载运行在 K8s 上, 同时也会有更多的云服务会融入到容器场景之中. 我们相信以后在高性能的云原生容器网络中会孵化出更多的功能和应用场景.
欢迎有兴趣的同学一起参与共建!
项目地址: https://github.com/AliyunContainerService/terway
来源: http://www.tuicool.com/articles/2MR7Fz6