KubeSphere 帮助本来生活网在 K8s 物理环境暴露集群服务

互联网
2020
04/07
15:28
分享
评论

本来生活网架构负责人陈杰

关于本来生活网

本来生活网创办于 2012 年,是一个专注于食品、水果、蔬菜的电商网站,从优质食品供应基地、供应商中精挑细选,剔除中间环节,提供冷链配送、食材食品直送到家服务。致力于通过保障食品安全、提供冷链宅配、基地直送来改善中国食品安全现状,成为中国优质食品提供者。

技术现状

基础设施

部署在 IDC 机房

拥有 100 多台物理机

虚拟化部署

存在的问题

物理机 95% 以上的占用率

相当多的资源闲置

应用扩容比较慢

互联网、电商公司的核心业务集中在线上进行,IT 支持决定公司的命脉。本来生活网原本的 IT 基础设施以传统虚拟化的方式部署在 IDC 机房,物理机日常占用率达到了 95% 以上,资源紧缺,应用弹性扩容缓慢,无法满足线上业务的需求。

同时,本来生活网虽然是一家互联网电商公司,但很早就停止了烧钱模式,开始追求盈利,对IT 建设也提出了尽量平衡成本、开源节流的要求。所以,本来生活网迫切需要重构基础设施,建设一套更为灵活、更为敏捷的 IT架构,帮助自己优化开发运维流程,最大程度提高应用开发效率并降低 IT生产环境运维成本。

迁移到 Kubernetes

最终,我们决定将生产环境容器化,把生产环境从虚拟化迁移到 Kubernetes 上,这样做的好处有以下几点:

提高资源的利用率

使应用能快速扩容

降低运维人员工作复杂度

此外,本来生活的应用发布由测试团队完成,但测试人员缺乏一定的开发运维经验,无法快速上手 Kubernetes 实现版本快速迭代。想要打通开发、测试与运维的 DevOps 一体化流程,需要有一个统一的平台配合应用开发和上线发布整套流程。我们通过大量调,选择可视化覆盖率高、运维友好、简单易用 KubeSphere 作为底层容器平台,我们在上进行二次开发,这样可以帮助我们节省很多开发时间。

如何暴露集群

由于本来生活网是基于物理机也就是裸机(Bare Metal)部署,所以无论基于什么平台还是要考虑如何暴露 K8s 集群,目前,常用的暴露K8s 集群的方式有以下几种:

LoadBalancer

LoadBalancer 是 Kubernetes 官方推荐的暴露方式,很可惜使用 LoadBalancer需要部署在云上。本来生活网是全部是裸机环境部署,因此这个方式在一开始就被我们放弃了。

NodePort

NodePort 的端口范围一般是 30000 以上,每个端口只能对应一种服务,随着应用越来越多,端口可能不够用。除此之外,它最大的问题是如果你暴露某一个节点给外部访问,那么这个节点会成为单点。如果你要做高可用,这几个节点都暴露出去,前面一样需要要部属一个负载均衡,这样事情就变得复杂了。

Ingress

Ingress 可以解决 NodePort 端口复用的问题,它工作在7 层上,可以复用 80 和 443 端口。使用 Ingress 的前提是必须要有 Ingress Controller 配合,而 Ingress Controller 同样会出现暴露端口并公开的问题。这时候如果你用 HostNetwork 或 HostPort 把端口暴露在当前的节点上,就存在单点问题;如果你是暴露多个节点的话,同样需要在前面再加一个 LoadBalancer。

HostNetwork/HostPort

这是一种更暴力的方式,直接把 Pod 的端口绑定到宿主机的端口上。这时候端口冲突会是一个很大的问题,同时单点问题依旧存在。

发现 Porter

我们当时没有想出如何更优雅的解决这个问题,甚至都决定是不是还要像以前一样,在前面加一套 HAProxy with keepalived 做高可用。

后来我在浏览 KubeSphere 的文档时,在安装负载均衡器插件页面底部看到了一行不起眼的文字:

"Porter 是一款适用于物理机部署 Kubernetes 的负载均衡器,该负载均衡器使用物理交换机实现,利用 BGP 和 ECMP 从而达到性能最优和高可用性,Porter 是一个提供用户在物理环境暴露服务和在云上暴露服务一致性体验的插件。"

看到了物理机部署的字样后,我们发现这正是我们需要的东西。

Porter 是开源项目 KubeSphere 下的子项目,的所有代码和文档已在 GitHub 开源 ,欢迎大家关注和使用。

使用 Porter 的前置条件

我们对 Porter 研究了很久,中间也踩了较多的坑,总结下来要用这个东西必须满足以下条件:

首先你的路由器,也可以是三层交换机需要支持 BGP 协议。现在大多数路由设备都会支持这个协议,所以这个条件一般都能满足;

其次集群节点上不能有和路由器建立 BGP 通信的服务。举例来说,当使用 Calico 时,开启了 BGP 模式。它的 BGP 模式有一种方式是让所有代理同时连到一个路由器,如果 Calico 和 Porter 要连的路由器是同一个的话,需要注意这个方案是有问题的。而 KubeSphere 默认安装的 Calico 是 IPIP 模式的,所以我们没有遇到冲突问题;

最后一定要有网络运维人员支持,配合你完成路由器配置以及了解整个网络拓扑结构。了解网络拓扑结构是非常重要的,否则会遇到很多问题。

物理部署架构图

Porter 官方介绍比较简单,有三张图片。这是第一张。这个网络结构应该是云环境的网络拓扑结构。在公司测试环境或者普通小机房不一定有这么复杂的网络结构。

我们来看下它是如何工作的,首先当你访问云上的 1.1.1.1 地址,请求转到 Border 路由器,Border 路由器再转到 Spine 交换机,Spine 交换机再转到 leaf 交换机,最后落到 K8s 的集群节点上。

Porter 的主要作用就是动态告诉这些路由器,整个路由应该怎么走。

我们再来看一个简单的例子。

假设你要做测试,你的办公室网络或测试网络可以组成这样一个简单的结构。如上图所示,一个三层核心交换机,所有网络都会连到它。同时整个网络还包括 K8s 集群的服务器。

以一个网段 10.0.0.0/16 为例,我们把这个网段可以定义为 K8s 集群的出口 IP,即ExternalIP(EIP),这些 IP 是不存在的。我们给每一个服务分配一个 EIP,所有到这些 IP 的请求最终会落到集群里的节点上。

要实现这个效果,一般比较笨的做法就是手动配置一个个的静态路由。这样的方式不太灵活,你要网工一直协助你操作路由器,维护成本是相当高的,肯定不适合生产环境。Porter 的做法是只要你告诉它你要配置这样一个网段,由它的 Porter-Manager 与交换机建立 BGP 连接,并对所有 Load Balancer 类型的 Service 自动分配 EIP。它会把对应的路由规则直接写到交换机上,无需人工干预,这就是动态路由。

什么是 BGP

BGP 是边界网关协议(Border Gateway Protocol),是一种动态路由协议,使用 TCP 协议进行通信。BGP 在不同的自治系统(AS)之间交换路由信息。

什么是 AS

这里有一个新名词——自治系统(AS)

自治系统是什么?是一个(或多个)实体管辖下的所有 IP 网络和路由器的全体,每个自治系统都被分配一个唯一的自治系统编码(ASN)。你可以简单的理解为 AS 是一个公司,而 ASN 就是这个公司的唯一标识,像中国电信、中国联通、中国移动都有一个 ASN,如果他们之间要进行某些 IP 的路由交换,就是通过 BGP 来实现。

这里又提到一个新的名词 ASN,那这个 ASN 和我们的 Porter 又有什么关系呢?我们先来看下 ASN 的取值范围。

ASN 表

ASN,它最早的版本是 16 位的,现在可以支持 32 位,如果你的路由器比较老,可能 32 位不支持,所以我们一般还是使用 16 位的 ASN。红色部分的范围是 64512-65534,表示 ASN 的私有号段。大家可以理解为 IP 地址有公网和私网,ASN 也有公有和私有的概念。内部使用 ASN 只要用私有号段就可以了。

配置路由器和 Porter

到这里我们的基础知识基本补全了,可以开始配置路由器和 Porter 了。

我们设置这个 Porter 只需要用到两个 ASN,一个是设在路由器上(65001),另一个设在 Porter 上(65002)。他们互相之间要知道对方的 IP、端口和对方的 ASN。当路由器和 Porter 配置好并启动后,他们两个设备就建立了 BGP 连接。

Porter 插件逻辑

我们再来看下 Porter 架构的第二张图,现在来看就比较清晰了。

我们给路由器配了 ASN 65001,给 Porter-Manager 分配了ASN 65002。

Porter 内部会过滤所有 Load-Balancer 类型的 Service,当符合以下规则时,如果你指定了 IP 的话,它会分配给你指定的 IP;如果没有指定,就在指定网段范围里随机分配一个 IP。

插件列表

Porter-Manager

Porter-Agent

前面主要解释 Porter-Manager 的工作原理。Porter-Manager 是使用 Deployment 部署到 Master 节点上的,但默认只部署 1 个副本,它负责同步 BGP 路由到物理交换机。还有一个组件,Porter-Agent,它以 DaemonSet 的形式在所有节点都部署一个副本,功能是维护引流规则。

插件部署架构图

这是 Porter 第三张图。这里的 Agent 即 Porter-Agent,它是维护引流规则的,那具体是什么意思呢?

Porter-Agent 会根据 Service Endpoints 的变化动态调整路由,确保 EIP下一跳的 Node 节点一定有目标 Pod 存在。当你为 Service 开启 External Traffic Policy=Local 时,流量可直接转到节点本地 Pod,不会再增加一次跳转。

如果熟悉 External Traffic Policy=Local 这个设置的意义,你会知道这个东西有利有弊。好处是减少网络跳转,还可以拿到 SourceIP;缺点是它可能会导致负载不均衡。实际的情况还是需要进行调试和验证。

如何在 KubeSphere 上使用 Porter

虽然 KubeSphere 没有内置支持 Porter,但是我们在 KubeSphere UI 上进行简单的设置就可以使用 Porter 了。

支持 Ingress 访问

首先要在 KS 的项目(也就是 K8s 命名空间)的高级设置中启用网关。

我们在 Test 命名空间中开启了网关,并且设置了两个关键的 Annotation。

当网关的 ExternalIP 显示了我们设置的 10.0.0.1 IP 地址后,就表示当前命名空间的 Ingress 出口已经建立,接下来我们只要在 KS 的路由设置中添加 Ingress 。

加好路由后,只要把 www.benlai.com 域名指向到 10.0.0.1 后就可以访问了。

支持 TCP 访问

我们可能还有一些应用不是基于 HTTP/HTTPS 访问的,比如想暴露一个 MySQL 的 3306 端口给外部,这时候你就需要直接对 Service 进行设置。

我们选择了 10.0.0.2 这个 EIP 作为暴露 IP,以下是这个 Service 的 yaml :

当在 Service 列表里看到外网访问这列出现了 10.0.0.2 这个 IP 后,就表示该 Service 的 EIP 已经暴露给外部,这时候你就可以使用 MySQL 客户端对 10.0.0.2 进行连接了。

高可用架构

说到这里,你可能会有许多疑问,比如:

单个路由器挂了怎么办?

单个 Porter-Manager 挂了怎么办?

Porter-Manager 和路由器网络断了怎么办?

EIP 下一跳地址所在的节点挂了怎么办?

某个 EIP 流量突然飙升,一个节点扛不住怎么办?

一般路由器或交换机都会准备两台做 VSU (Virtual Switching Unit) 实现高可用,这个是网络运维擅长的,这里不细讲了,可以参考 Porter 的第一张架构图里网络拓扑结构。我们重点讲下后面四点要怎么解决。

检查 BGP 路由表

首先我们要查下路由器上的 BGP 的路由表。如果 Porter 装好后一切正常,你在路由器上会看到这样一个 BGP 列表。其中星号代表这条 BGP 路由可用,大于号代表路由器现在正在使用这条路由规则。注意这是 BGP 路由,不是路由器的当前路由,这是有区别的。这个列表表示你把路由写到了 BGP 路由表里,每一个 EIP 只写了一条路由规则。

若要做到高可用,这里每个 EIP 对应的路由必须有两条以上。这样设置后,当 192.168.0.201 挂了以后,路由器会再从 BGP 路由表里选一条路由规则进行跳转。否则只有一条的话,这时候网络就断掉了,我们做过这样的测试。因此一定要确保 BGP 路由表是一个 EIP 对多个节点。

如果它不是这样的,你要找一下原因,是不是你的路由器没有配置好,或者你的 Porter 配置不对,或者有其他什么问题存在。

检查 BGP 邻居状态

接下来我们查看 BGP 的邻居状态。所谓的邻居状态意思是 Porter-Manager 在路由器上的连接状态。

默认安装 Porter,它只是在一个 Master 上部署 Porter-Manager。在邻居列表里能看到该 Porter-Manager,状态是 Established。注意检查其状态一定得是 Established。当状态为断开后,路由器会删除所有 Porter 提交的路由规则,也就是说当你的 Porter-Manager 挂了,你整个集群对外的网络也就挂了,是全部挂了。

我们应该怎么办?

我们要确保我们的路由器和 Porter-Manager 是多对多部署的。当你在路由表上看到你的 BGP 是上面图片这样的。无论是两个还是三个以上,它们的状态应该全部是 Established,并且列表中的收发数据量是会增长的,你就可以放心。但是你还是要时刻监控这张列表,预防全部断开连接的情况。

检查路由表

最后你要查看路由器真正的路由表,路由表大致是上图这样的。B 是 BGP 的缩写,代表当前这个路由是从 BGP 那边学习过来的。其中包含我们设置的 EIP 以及节点对应的 IP 地址。当你的路由表是这样的话,你需要担心流量突然增大时,你的节点撑不住怎么办?

我们还要做什么?

你要确保把路由器的等价路由(ECMP)开启,什么是等价路由?你告诉路由器这个 IP 有多条通路,让它自己做负载均衡,这才是路由器真正的负载均衡。

在路由器上要设置 MultIPath 或者 Additional Paths 才能开启等价路由,具体请参考路由器的操作手册。当你开启了等价路由后,你应该就能在路由表里能看到图中红色的部分。这个时候,你就可以不用担心某一天 10.0.0.1 突然流量很高的时候会压垮 192.168.0.201 这台机器了。

小结

我们归纳下实现高可用部署需要做的事情,还有要做好故障演练和压力测试。

确保一个 EIP 有多条 BGP 路由;

确保路由器和 Porter-Manager 是多对多部署;

确保路由器开启等价路由(ECMP)。

Porter 实践心得体会

尚处于早期版本,稳定性需要经受考验;

不支持 Service 的 spec.loadBalancerIP 字段,只能通过 annotations 中的eIP.Porter.kubesphere.io/v1alpha1 指定 IP 地址;

文档较少。

一个比较新的东西肯定有不足的地方,我们使用 Porter 早期版本一直到现在,当中经历过踩坑的阶段。现在 Porter 处于 v0.1.1 的版本,稳定性是我们需要考虑的因素,这个需要在你的环境里测试和验证。其次这个项目需要更多的人使用和反馈,这样它才有进步,成为一个更稳定的版本。

未来的展望

支持其他简单路由协议;

更加方便的 VIP 管理;

BGP 的 Policy 支持;

在 KubeSphere 集成,提供 UI。

这些是KubeSphere 官方的计划,我们本来生活网更期待最后一项的支持,这样我们的工作量又会小很多。

THE END
广告、内容合作请点击这里 寻求合作
免责声明:本文系转载,版权归原作者所有;旨在传递信息,不代表砍柴网的观点和立场。

相关热点

相关推荐

1
3