Kubernetes是Google开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。伴随着云原生技术的迅速崛起,如今Kubernetes 事实上已经成为应用容器化平台的标准,越来越受到企业的青睐,在生产中也应用的也越来越广泛。
我们的容器平台建设从2016年开始,大致经历了探索预研、体系建设和平台落地这样三个阶段。
下面就从Kubernetes的网络、存储、集群管理和监控与运维几个方面来分享下我们容器云平台建设走过的历程,希望给大家一些思考和启发。
一、 kubernetes网络
容器网络发展到现在,已经是双雄会的格局。双雄会其实指的就是Docker的CNM和Google、CoreOS、Kuberenetes主导的CNI。首先明确一点,CNM和CNI并不是网络实现,他们是网络规范和网络体系,从研发的角度他们就是一堆接口,你底层是用Flannel也好、用Calico也好,他们并不关心,CNM和CNI关心的是网络管理的问题。
网络需求调研发现,业务部门主要关注以下几点:1、容器网络与物理网络打通2、速度越快越好3、改动越少越好4、尽可能少的风险点。
容器的网络方案大体可分为协议栈层级、穿越形态、隔离方式这三种形式
协议栈层级:二层比较好理解,在以前传统的机房或虚拟化场景中比较常见,就是基于桥接的 ARP+MAC 学习,它最大的缺陷是广播。因为二层的广播,会限制节点的量级;三层(纯路由转发),协议栈三层一般基于 BGP,自主学习整个机房的路由状态。它最大的优点是它的 IP 穿透性,也就是说只要是基于这个 IP 的网络,那此网络就可以去穿越。显而易见,它的规模是非常有优势,且具有良好的量级扩展性。但在实际部署过程中,因为企业的网络大多受控。比如,有的企业网络的 BGP 是基于安全考虑不给开发者用或者说企业网络本身不是 BGP,那这种情况下你就受限了;协议栈二层加三层,它的优点是能够解决纯二层的规模性扩展问题,又能解决纯三层的各种限制问题,特别是在云化 VPC 场景下,可以利用 VPC 的跨节点三层转发能力。
穿越形态:
这个与实际部署环境十分相关。穿越形态分为两种:Underlay、Overlay。
Underlay:在一个较好的可控的网络场景下,我们一般利用 Underlay。可以这样通俗的理解,无论下面是裸机还是虚拟机,只要整个网络可控,容器的网络便可直接穿过去 ,这就是 Underlay。
Overlay:Overlay 在云化场景比较常见。Overlay 下面是受控的 VPC 网络,当出现不属于 VPC 管辖范围中的 IP 或者 MAC,VPC 将不允许此 IP/MAC 穿越。出现这种情况时,我们可利用 Overlay 方式来做。
Overlay网络使物理网络虚拟化、资源池化,是实现云网融合的关键。把Overlay网络和SDN技术结合使用,把SDN控制器作为Overlay网络控制平面的控制器,这种方式更容易使网络与计算组件整合,是网络向云平台服务转变的理想选择。
隔离方式:
隔离方式通常分为VLAN和VXLAN 两种:
VLAN:VLAN 机房中使用偏多,但实际上存在一个问题。就是它总的租户数量受限。众所周知,VLAN 具有数量限制。
VXLAN:VXLAN 是现今较为主流的一种隔离方式。因为它的规模性较好较大,且它基于 IP 穿越方式较好。
我们从协议层级、穿越形态和隔离方式对kubernetes几个常见的网络组件(calico、contiv、flannel、Openshift SDN、自定义路由)在传统机房网络以及云化VPC网络应用场景下做一个分析,用连线图来表述它们之前的关系。
首先无论是传统机房网络还是云化 VPC 网络,我们可以看到 Overlay 方案是通用的,它在云化场景里可能用的更多一些,因为它有很好的穿越性。
在上图中,红线实线指向传统机房网络,这里重点说明下。Underlay + 三层的方案,是传统机房网络非常流行的方案,同时它的性能非常可观,场景应用比较偏多。
绿色虚线指向云化VPC网络, Underlay+三层网络在云化 VPC 场景下,也是可以受限使用。受限使用顾名思义,可以使用但不是每个供应商都让你用,因为每一个云厂商对他自己网络保护的定义不一样。比如像 Calico 方案,它的 BGP 在 AWS 中就容易做,但在 Azure 中就不允许,因为 Azure 的 VPC 本身是不允许不受它管控范围的 IP 通过。
黄颜色的实线指向云化VPC网络,Overlay+二层或三层在云化场景中比较常见。Overlay 下面是受控的 VPC 网络,管控会比较方便。
当然云化VPC场景下也存在一些问题,如下图所示。
接下来说一下多租户之间的网络隔离问题
K8s从1.3版引入网络策略机制,通过网络策略可实现POD之间的入站和出站访问策略。
网络策略可应用于通过常用标签标识的pod组,然后使用标签来模拟传统的分段网络,可以通过特定的“段”标签来标识前端和后端pod。策略控制这些段之间的流量,甚至控制来自外部源的流量。但并非所有的网络后端都支持策略,比如 flannel。现在很多厂商在这方面加强了研究,也有很多新的解决方案,就不一一列举了。
还有就是集群边界Ingress的管理
Ingress 是在kubernetes 1.2版本才出现的,容器应用默认以Service的形式提供服务,但Service仅作用于集群内部,通过Ingress将Service暴露出去才能为集群外的客户端提供服务。
下面对常见的Ingress Controller做一个对比,见下表
我们看到Nginx在性能和功能适用面上,还有社区活跃度上都较好,实用中也较多。
二、 kubernetes的存储
k8s最初用于管理无状态的服务,但随着越来越多的应用迁移到k8s平台,管理存储资源成为一个非常重要的功能。
Kubernetes中对于存储的使用主要集中在以下几个方面:
服务的基本配置文件读取、密码密钥管理等;服务的存储状态、数据存取等;不同服务或应用程序间共享数据。大致有以下几个场景,如图:
Kubernete存储在设计的时候遵循着Kubernetes的一贯哲学,即声明式(Declarative)架构。同时为了尽可能多地兼容各种存储平台,Kubernetes以in-tree plugin的形式来对接不同的存储系统,满足用户可以根据自己业务的需要使用这些插件给容器提供存储服务。同时兼容用户使用FlexVolume和CSI定制化插件。相比较于Docker Volume,支持的存储功能更加丰富和多样。
Kubernete存储插件解析:
1、in-tree plugin:存储代码与K8S紧密集成,耦合性太强
2、FlexVolume:存储插件安装在宿主机上,需要宿主机的root权限
3、CSI规范:将存储代码与K8S完全解耦(1.10版本及以上,使用CSI attacher使用0.2.0版本)
csi规范极大地方便了插件的开发、维护和集成,具有很好的发展前景。
Kubernetes使用两种资源管理存储:
PersistentVolume(简称PV):由管理员添加的的一个存储的描述,是一个全局资源,包含存储的类型,存储的大小和访问模式等。它的生命周期独立于Pod,例如当使用它的Pod销毁时对PV没有影响。
PersistentVolumeClaim(简称PVC):是Namespace里的资源,描述对PV的一个请求。请求信息包含存储大小,访问模式等。
PV可以看作可用的存储资源,PVC则是对存储资源的需求,PVC会根据Pod的要求去自动绑定合适的PV给Pod使用。PV和PVC的相互关系遵循下图所示的生命周期。
PV模式有静态和动态,静态PV模式管理NFS、FC、ISCSI,动态PV模式管理glusterfs、Cinder、Ceph RBD、Vsphere、ScaleIO、AWS、Azure等。静态的需要管理员创建和管理PV,而动态的则由系统自动生成PV并绑定PVC.
下面再简单补充下kubernetes中的镜像管理,生产中都会有很多不同版本不同应用的镜像,对镜像的管理也是比较重要的环节。
镜像的多租户权限管理:
1、不同租户的镜像应相互隔离
2、不同的租户对镜像拥有不同的权限,例如读写、只读、上传、下载权限
3、镜像库提供镜像的查询、更新和删除等功能
对于跨地域多数据中心的镜像管理,镜像库的远程复制管理需要注意:
1、在多数据中心或跨地域多站点的环境下,为了提高多地区镜像的下载效率,至少需要两级镜像库的设置:总镜像库和子镜像库
2、镜像库之间的准实时增量同步
三、 Kubernetes集群管理
在生产系统中,kubernetes多集群的管理主要涉及:
1、服务运维
2、集中配置
3、扩容升级
4、资源配额
首先说说多集群的调度管理
1、Kubernetes中的调度策略可以大致分为两种,一种是全局的调度策略,另一种是运行时调度策略
2、NODE的隔离与恢复;NODE的扩容;Pod动态扩容和缩放
3、亲和性可以实现就近部署,增强网络能力实现通信上的就近路由,减少网络的损耗。反亲和性主要是出于高可靠性考虑,尽量分散实例。
4、 微服务依赖,定义启动顺序
5、跨部门应用不混部
6、api网关以及GPU节点应用独占
多集群管理中的应用弹性伸缩管理:
1、手工扩缩容:预先知道业务量的变化情况
2、基于CPU使用率的自动扩缩容:v1.1版引入控制器HPA,POD必须设置CPU资源使用率请求
3、基于自定义业务指标的自动扩缩容:v1.7版对HPA重新设计,增加了组件,被称为HPA v2
在实际应用中,HPA还有很多不完善的地方,很多厂商都用自己的监控体系来实现对业务指标的监控并实现自动扩容
Kubernetes多集群的调优:
主要有三个难点:
第一是如何分配资源,当用户选择多集群部署后,系统根据每个集群的资源用量,决定每个集群分配的容器数量,并且保证每个集群至少有一个容器。集群自动伸缩时,也会按照此比例创建和回收容器。
第二是故障迁移,集群控制器主要是为了解决多集群的自动伸缩和集群故障时的容器迁移,控制器定时检测集群的多个节点,如果多次失败后将触发集群容器迁移的操作,保障服务可靠运行。
第三是网络和存储的互连,由于跨机房的网络需要互连,我们采用vxlan的网络方案实现,存储也是通过专线互连。容器的镜像仓库采用Harbor,多集群之间设置同步策略,并且在每个集群都设置各自的域名解析,分别解析到不同的镜像仓库。
接下来说说K8S集群的Master节点高可用实现,我们知道Kubernetes集群的核心是其master node,但目前默认情况下master node只有一个,一旦master node出现问题,Kubernetes集群将陷入“瘫痪”,对集群的管理、Pod的调度等均将无法实施。所以后面出现了一主多从的架构,包括master node、etcd等都可设计高可用的架构。
还有了解下Federation 集群联邦架构
在云计算环境中,服务的作用距离范围从近到远一般可以有:同主机(Host,Node)、跨主机同可用区(Available Zone)、跨可用区同地区(Region)、跨地区同服务商(Cloud Service Provider)、跨云平台。K8s的设计定位是单一集群在同一个地域内,因为同一个地区的网络性能才能满足K8s的调度和计算存储连接要求。而集群联邦(Federation)就是为提供跨Region跨服务商K8s集群服务而设计的,实现业务高可用。
Federation 在1.3版引入,集群联邦federation/v1beta1 API扩展基于DNS服务发现的功能。利用DNS,让POD可以跨集群、透明的解析服务。
1.6版支持级联删除联邦资源,1.8版宣称支持5000节点集群,集群联邦V2
目前存在的问题:
1、网络带宽和成本的增加
2、削弱了多集群之间的隔离性
3、成熟度不足,在生产中还没有正式的应用
四、kubernetes的监控与运维
对于一个监控系统而言,常见的监控维度包括:资源监控和应用监控。资源监控是指节点、应用的资源使用情况,在容器场景中就延伸为节点的资源利用率、集群的资源利用率、Pod的资源利用率等。应用监控指的是应用内部指标的监控,例如我们会将应用在线人数进行实时统计,并通过端口进行暴露来实现应用业务级别的监控与告警。那么在Kubernetes中,监控对象会细化为哪些实体呢?
系统组件
kubernetes集群中内置的组件,包括apiserver、controller-manager、etcd等等。
静态资源实体
主要指节点的资源状态、内核事件等等
动态资源实体
主要指Kubernetes中抽象工作负载的实体,例如Deployment、DaemonSet、Pod等等。
自定义应用
主要指需要应用内部需要定制化的监控数据以及监控指标。
不同容器云监控方案的对比:
关于Prometheus监控:
主要注意两点:
查询api的封装
配置文件的下发
有了prometheus这个强大的监控开源系统之后,我们所需要投入的工作就是查询api的封装和配置文件的下发。查询api的封装没什么好说的,无非就是前端调用我们自己的server,我们的server呢通过http协议去调用prometheus的api接口查询到原始数据,然后进行组装,最后返回给前端。 配置文件的话包含三部分吧,警报的定义,alertmanager的配置,以及prometheus的配置,这里也不好展开讲,有兴趣的可以去官网看看。当然也可以使用Prometheus+Grafana来搭建监控系统,这样可视化会更丰富些,展现也比较快。
运维的思考---开发与运维的一体化
运维的思考---高可用问题
• Ocp平台:
1、负载均衡Router高可用集群: 2个节点
2、EFK高可用集群: 3个ES节点+n个F节点
3、镜像仓库高可用集群: 2个镜像仓库
• 微服务架构:
1、注册中心高可用集群(Eureka): 3个
2、配置中心高可用集群: 3个
3、网关高可用集群: 2个
4、关键微服务均是高可用集群
运维的思考---高并发问题
• Ocp平台:
1、对后端微服务(Pod)配置弹性扩容, K8的弹性伸缩扩容以及Docker容器的秒级启动可以支撑用户量的持续增长;
2、提前预留20%的资源, 当高并发情况发生时, 可以紧急扩充资源。
• 微服务架构:
- 调大关键链路微服务的熔断线程数: 提升主要业务的并发响应能力。
- 对非关键链路微服务通过熔断限流进行降级处理甚至关闭非关键链路的微服务。
- 熔断机制:提升容器云高并发场景下的容错能力,防止故障级联以及微服务的雪崩效应,提升系统的可用性。
• 中间件:
1、除了正在使用的集群外, 提前增加冷备的集群。
2、当高并发场景即将发生时, 可以紧急水平扩展。
还有就是性能压测与优化问题,限于时间关系,这里就不展开讲了。
最后,容器云之路总结
1.业务层面:因大型企业对业务的稳定性和连续性有比较高的要求,故容器化的演进路径必然是从边缘业务到核心业务,从简单应用到复杂应用,具体到业务,首先可以考虑在Web前端进行容器化迁移,最后动后端业务。
2.技术层面:目前原生Docker在服务发现、负载均衡、容器生命周期管理、容器间网络、存储等方面还存在诸多的不足,许多第三方厂家提供的开源解决方案和商业化版本,各具特色,难分高下。用户无论选择何种产品,可靠性、灵活性是需要慎重考虑的2个重要因素。
3.兼顾成本效益:综合考虑容器化付出的成本代价与未来收益之间的平衡。
4.考虑现有硬件的负载能力,容器化并非包治百病的良药,某些对并发吞吐量要求更高的业务,直接运行在裸机上,通过系统调优提高性能,容器化未必是最好的选择。
5、持续更新,时刻提醒自己持续学习,拥抱变化,这样才能看到平台的不足,不断迭代出更好的产品。
在生产实践中,只有夯实基础不断去完善基于容器云平台的产品和建设生态体系,才能掌控未来决胜千里!