龙空技术网

360容器云之独享集群介绍

360智汇云 83

前言:

如今你们对“云主机集群”大体比较注意,大家都想要分析一些“云主机集群”的相关知识。那么小编在网摘上搜集了一些有关“云主机集群””的相关文章,希望各位老铁们能喜欢,小伙伴们快快来了解一下吧!

一、托管集群介绍

所谓托管集群,即会有一个控制面帮助用户管理k8s master组件的生命周期,用户只需要将自己的虚拟机/物理机等注册给某个k8s子集群的api server,即可将当前虚拟机/物理机纳管成为某个k8s子集群的node节点,然后就可以通过k8s的api,在当前节点上运行各种workload。

一直以来,360都是通过rancher管理k8s集群的,rancher是一个容器管理平台,用于在多个主机上部署和管理容器化应用程序。有web ui。rancher架构图如下:

更多rancher相关信息请参考

但它依然存在很多问题,比如:

1. 集群搭建纯cmd的实现方式,操作繁琐;

2. 集群自定义组件实现不够灵活,需要声明完整的yaml,不够友好 ;

3. 无法控制集群升级进度 ;

4. 集群node组件无法特异化配置,即每个node组件的启动参数/配置可以不同;

二、托管k8s集群

相比传统的集群搭建方式,需要创建k8s所有组件,及其依赖组件的方式,目前更为推广的是托管k8s集群的模式。下图为云厂商托管k8s集群大致的架构图:

相比于传统的集群管理方式,我们会发现目前的架构存在很多优势:

1. 可扩展性,架构分离

2. 减少集群管理工作

3. 减轻开发同学的压力,专注

4. 便于资源预测,降低总拥有成本

5. 提升安全性

托管集群其实更多的是一种k8s集群管理概念,而其实现方式则多样,容器云对这一类的集群叫做独享集群,接下来看看我们是怎么做的吧。

三、项目实现过程

我们会发现,所谓集群托管,其实就是需要一个控制面去帮我们管理k8s控制面各个组件的生命周期,而k8s天然就是一个比较好的控制面,我们最终决定借助k8s去实现k8s托管集群的控制面,即 "k8s on k8s”。那么现在集群架构大致会是这样:

这个项目的优势在于:

1. 架构分离,用户不必再维护集群控制面;

2. 生命周期管理,降低集群维护复杂度;

3. 可扩展性,自定义组件安装的api ;

4. 安全,支持多种方式存在的etcd;

5. 声明式集群定义方式,完全兼容k8s 原生api;

接下来,我们来介绍下这种方案在实践的过程中遇到的问题。

四、项目经验

1.跨集群交互相关

这种方案必然是和我们所处的网络环境极相关的,想必这应该就是为什么各运厂商都在基于k8s做集群托管,但却很少开源的原因吧。

网络相关的问题很多,我们这里举一个和k8s自身组件交互相关的例子。

问题是这样的,我们通过konk的方式创建了一个新的k8s子集群,但是发现子集群中的很多基于webhook实现的系统组件均无法工作。

然后发现了一个非常奇妙的问题,子集群中webhook server对应的服务并没有收到来自apiserver的请求,然后去排查子集群apiserver的日志,确实是有发送请求到webhook的,请求莫名其妙消失了?然后开始翻k8s的源码,发现apiserver对于webhook请求的转发的地址来自声明的mutatingwebhookconfigurations/validatingwebhookconfigurations 资源的ClientConfig 的,详细声明如下:

// WebhookClientConfig contains the information to make a TLS// connection with the webhooktype WebhookClientConfig struct {   URL *string   Service *ServiceReference   CABundle []byte}

可以看到,支持配置webhook server地址的方式有两种,直接配置url地址,或者配置service信息。

大多时候,我们会直接通过service的方式去实现。

apiserver从这个配置找到自己应该把请求转给谁,然后去拼http请求,但是遗憾的是,这个请求永远无法到达子集群的webhook服务的。具体原因是,子集群的apiserver基于service拼完http请求进行转发,首先请求从base集群中子集群apiserver的pod中发出,经base集群的kubedns/coredns 将service转成service ip,然后节点侧基于kube-proxy下发的iptables/ipvs规则将请求转发到具体的pod ip。问题就在于这条流程中, base集群中的pod去访问service,那这个请求自然会被转发到base集群的某个pod中,肯定是不可能到子集群中啊,天,恍然大悟,我们一直将子集群中的apiserver的所有流程和自己集群相关联,但是却忽略了它也只是base集群中的一个普通pod而已。

然后这个问题最终的解法是通过配置apiserver的一个flag

// Turns on aggregator routing requests to endpoints IP rather than cluster IP--enable-aggregator-routing=true

这样从base集群转出去的请求就可以到pod,所以这里其实还要求base集群中pod能够访问子集群中pod ip, 所以目前集群托管集群的webhook的pod必须用host network。

2.关于证书签发

起初,我们的设计思路是这样的,kubecluster crd会管理子集群维度的相关配置、证书管理、底层数据存储等,然后k8s master的各个组件也会有对应的controller管理其生命周期,能够单独声明不同组件的副本数,相关配置等等。

但是在项目落地的过程中在证书签发部分遇到一系列问题,具体如下:

新建集群时,无法提前预知apiserver的pod ip, 无法生成集群证书 ;apiserver的pod重建时,会导致证书失效 ;证书过期新签;

核心问题在于现在这种实现方式下,集群组件是pod创建的,而pod作为k8s集群中随时可以被创建删除替换的资源,随着pod重新,pod ip也会发生变化,就会导致证书的白名单没法确定。

所以其实种种说明这种设计模式下用pod ip去签发证书是绝对不可以的。

最终我们通过将k8s master组件部署在同一个pod中解决,原因在于同一个pod中的多个container之间共享net namespace,这样各个组件就可以通过127.0.0.1/0.0.0.0这种固定的方式去访问,巧妙解决因为pod ip变化无法签发证书的问题。

但是对于集群外我们一般通过kubeconfig 提供用户访问k8s的证书信息,在这里我们一般会将apiserver的pod ip注册给一个lvs ip, 由于lvs ip在集群外是可以访问的,通过lvs ip将流量下发到具体 apiserver pod ip,而这个lvs ip也会同时作为证书的白名单。这样就解决了集群内外https访问的所有问题。

3.对接不同容器运行时

k8s的容器运行时有多种多样,目前独享集群集群支持的容器运行时支持docker与containerd,也在serverless团队的独享集群当中替换了kata作为容器的运行时

在设计之初,独享集群的node节点的kubelet与kube-proxy是通过docker容器启动的,相比于systemed,通过docker容器启动的kubelet与kube-proxy的容器在更新配置,更改命令行参数的时候更具有灵活性

但是在不同容器运行时的情况下,就会出现kubelet与kube-proxy是docker启动的容器,k8s启动的容器则为kubelet指定的容器运行时,这对于运维、开发来说去维护其实是一种很大难度的事,经常会出现containerd修改了参数,docker容器消失,宿主机出现僵尸进程的情况

为此独享集群对于不同的容器运行时,定制了不同的容器运行时的kubelet与kube-proxy

但是在对接containerd的时候,启动kubelet和kube-proxy容器出现了以下的问题:

创建出来的kubelet与kube-proxy不能正常使用;

k8s集群里的configmap与serviceaccout莫名其妙的失效;

问题的解决,第一个还很好说,很快解决了,第二个问题只需要给容器开特权模式与使用host网络等一系列功能,就可以解决。

正常来说,configmap与serviceaccount是由kubelet通过api-server读取etcd中记录的信息,写到宿主机kubelet定义的rootdir的pod某个目录当中,再mount到具体的k8s容器当中的,异常现象是,kubelet容器内可以看到具体目录下的cofigmap和serviceaccount信息,但是pod内看不到,导致一些控制面组件,连接apiserver的时候找不到配置文件而产生重启的现象

仔细一想容器挂载configmap和serviceaccount的原理,kubelet通过将configmap和serviceaccount中的内容通过etcd中读取出来,通过tempfs挂载到容器当中,这就需要提到一个关于namespace的小知识:

大家都知道,容器的隔离是通过不同的namesapce实现的,这里包括经常使用的net、mount、pid的namesapce。

这里简单提一下三个小知识:

1.mount namesapce:每个容器都可以拥有自己独立挂载的文件系统

2.挂载传播:简而言之就是同一个挂载点可以让不同容器使用

3.rootfsPropagation:和挂载传播的作用类似,但是这个是解决嵌套容器的挂载传播,正好符合我们的场景需求

我们的kubelet和正常的k8s容器在都是拥有自己mount的namespace的,也在宿主机上以容器启动,而kubelet是调用containerd的unix socket进行pod的镜像拉取,容器创建等功能

正好和rootfsPropagation所描述的关系一样,通过加入以下代码,调整kubelet的容器rootfsPropagation等于shared之后,pod内configmap,serviceaccount和secret都可以正常访问,我们的问题也成功解决了。

opts = append(opts, oci.WithRootfsPropagation("shared"))func WithRootfsPropagation(options string) SpecOpts {return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {    setLinux(s)    s.Linux.RootfsPropagation = optionsreturn nil  }}

4.独享集群的功能多样化

五、独享集群支持的功能介绍

独享集群目前支持的功能丰富多样,下面我来通过在网络、存储、监控等方面说一下现在独享集群支持的哪些功能:

1.网络方面

独享集群目前集成了经典网络和hulk-vpc-cni网络;

经典网络是指使用了cilium以及vxlan特性,通过自定义隔离网段实现了稳定,高效的k8s的南北向cnihulk-vpc-cni是指通过与hulk-vpc打通,通过cni controller的ipam管理以及agent的在宿主机上挂载openstack(弹性网卡)等一系列操作,给独享集群提供了一个低延迟、稳定、高效的网络环境,目前hulk-vpc-cni已经更新到池化版本,并且在应用平台部已经大量的使用,对于pod创建,网络延迟有更一步的优化,获得一致好评。

2.存储方面

存储方面目前集成了本地盘以及远端存储,各自功能优势如下:

本地盘:本地盘使用了lvm的技术,结合了k8s不同的存储(pvc,emptydir等)本地的优势就是速度快,扩容方便,创建pvc的链路短,创建速度快,保证本地盘磁盘性能的一系列优势目前集成的业务有系统部云州,it办公网盘已经大幅度使用本地盘,通过本地盘pvc去存储他们的数据库,中间件等持久化数据,获得一致好评共享存储:共享存储使用了polefs,通过csi以及与奇麟大数据polefs结合,形成了标准的C/S架构的csi,目前已有应用平台部大幅度使用共享存储

3.日志方面

目前独享集群支持的日志组件为arkit,通过与系统部的结合,给独享集群提供了简单,方便使用的日志组件。

4.监控告警方面

监控方面独享集群适配了监控组件firehawk-vmagent,k8s原生metrics server以及node exporter以及结合了推推告警,真正保障了提前预知问题风险,第一时间解决的独享集群稳定性。

5.流量方面

流量方面独享集群支持4层与7层的流量控制:

7层:通过与hulk域名解析与ingress-controller的配合,实现了独享集群内的7层流量控制,目前重度使用的用户有360云盘、数据平台部以及金融等。

4层:4层方面目前支持vpc网络类型的独享集群,通过自研load-balancer与hulk四层负载均衡的结合,实现了独享集群内的四层负载均衡。

6.资源隔离以及在离线混部方面

资源隔离:资源隔离目前独享集群使用了lxcfs对pod进行资源试图的隔离,在pod内使用top与free命令是看到的是自己本身的资源使用率而不是宿主机的。

在离线混合部署:在离线混合部署是指将低优先级的服务与高优先级的服务共同部署在同一个节点上,通过调度以及驱逐,保障了节点的健康状态的同时增加了机器的资源使用率,目前在离线混部的独享集群共有9个,所纳管的裸金属共有390台,所有机器上都已经部署了系统部的离线pod,未来这一数量会持续增加。

六、总结

上述主要描述了独享集群的底层实现原理,当前独享集群在容器云上已经有一定的集群规模,用户可以按需创建和变更k8s集群,有很大的自主可控权,比较适合对k8s有定制化需求的用户。未来在研发层面还会在集群自动升级流程、声明式node管理等方面继续迭代,也欢迎大家按需试用。

了解更多技术知识,欢迎关注“360智汇云”。

标签: #云主机集群