前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >王蕴达:腾讯云 Kubernetes 一键部署实践

王蕴达:腾讯云 Kubernetes 一键部署实践

原创
作者头像
腾讯云开发者社区技术沙龙
修改2018-07-06 10:08:53
5.8K0
修改2018-07-06 10:08:53
举报

演讲嘉宾:王蕴达,腾讯高级工程师。现任腾讯云容器服务后台开发。主要负责容器服务运行时的研发工作,专注于在公有云上通过基于开源 kubernetes 提供产品化的 kubernetes 服务和周边服务。

很多人在实际工作中都使用过Kubernetes,我们的容器服务在2016年年底开始提供全托管的Kubernetes服务,主要提供了四个方面的功能。首先是提供了一键部署的Kubernetes,与其他容器服务的提供商不一样,我们的Kubernetes是完全隔离的,每个用户都会独享所有的计算节点和控制节点,集群网络也在用户自己的VPC中。我们在这个基础上提供了集群的全生命周期管理,包括集群的创建、销毁,还有计算节点的添加、删除,还有一些类似Kubernetes原有组件的初始化以及证书的初始化工作。为了大家更方便地使用Kubernetes,我们在控制台包装了一些界面,使大家可以通过可视化的方式创建一些负载来暴露自己的服务,避免了大家手工编码的烦琐。第三,我们提供了周边的监控能力,包括集群本身pod内存的使用率以及一些Kubernetes事件。这些能力都与腾讯云的云监控产品进行了打通,大家可以直接在云监控产品界面使用这些能力。为了方便大家将自己的一些比较传统的应用部署到云上,我们在Kubernetes集群之外还提供了Docker镜像仓库、TencentHub、CICD的功能,为大家提供了一站式应用的云解决方案。

我今天所讲的内容,一方面是介绍Kubernetes相关的知识,另一方面是如何将Kubernetes和腾讯云进行集成。首先带大家了解一下Kubernetes集群需要哪些组件,将Kubernetes部署好之后还要做什么工作使它正常运行。之后会介绍云上Kubernetes上的网络存储和日志与监控,这是将Kubernetes和腾讯云集成时进行的工作。最后介绍Kubernetes的两种部署方案,一种是容器服务产品发展早期所采用的一种基于CVM的方案,另一种是最近逐渐部署的使用Kubernetes集群来管理Kubernetes集群组件的方案。随着容器服务产品以及Kubernetes社区的发展,在我们提供托管的CCS服务通过了CNCF的K8s一致性验证之后,为了大家更好地认知腾讯的容器服务产品,产品的名字从之前的CCS正式改名为TKE。

Kubernetes 组件

接下来我们看一下想要让Kubernetes集群运行起来我们要做哪些工作。如果对Kubernetes有了解的同学,可能知道使Kubernetes跑起来,无非是初始化一些Master组件和Node组件。首先给大家介绍Master组件,一个最简单的部署要包括Kube-apiserver、Kube-contioller-mannager 、kube-scheduler这些组件。Kube-apiserver可以理解为整个集群的大脑或者是集中存储,所有组件与k8s的交互都是通过Kube-apiserver来完成的。其中存储着我们定义的一些工作负载以及我们对于存储的一些需求,这些数据都存储在Kube-apiserver中。

第二个组件Kube-contioller-mannager主要负责将声明的一些工作负载在实际的集群中运行起来,举个最简单的例子,当我们在Kubernetes上创建了一个deployment之后,Kube-contioller-mannager就会去创建相应的replicaset、pod这些。根据需求将pod创建出来,在创建pod后,Kube-scheduler负责对这些pod进行调度,比如这个pod实际应该被运行在哪台机器,比如GPU的结点做这样的调度工作。当一个集群的Master组件被完全部署好之后,我们会部署一些Node。在它的上面部署两个组件,一个是kubelet,负责在这些Node上创建出来我们需要的pod。另一个是kube-proxy,它在集群中负责的工作是:当一个deployment需要以服务的形式对外暴露的时候,Kude-proxy会负责配置这些iptables规则,让集群内不管是宿主机上的程序还是容器里的程序,都能够按照service的名字去做一个自动的发现和访问。

在Kubernetes这些标准化的组件之外,我们还提供了额外的组件,主要给大家介绍一下。包括三个,一个是hpa-metrics-server,它是我们为了使用Kubernetes提供本身的pod横向扩展控制器而去自研的一个组件,这个组件相比于Kubernetes社区方案的优点,是Kubernetes社区方案只提供了基于CPU和内存的扩展,而我们在这个基础上更加拓展了Pod的入带宽和出带宽的指标,方便大家去适应更多的扩缩容场景。第二个组件是cbs-provisioner,这个组件提供了去让Kubernetes里面的pod去消费我们腾讯云一个叫做Cbs块存储服务,我们后面会详细讲到。第三是Ccs-log-collector,这个组件主要是负责收集容器里pod运行的日志,后面也会讲到。

容器网络

当我们把Kubernetes和腾讯云进行集成的时候,网络方案是怎么做的呢?在你将一些控制组件搭建起来之后,Kubernetes对于网络提出了三点的要求。第一是在不使用NAT的情况下,集群内所有容器都可以和其他的容器进行通讯。第二是所有的节点都可以和所有的容器进行通信,反向也可以通信,同样要求不能使用NAT。第三是容器看到的自己的IP与其他人看到的IP是一样的。总的来说,它实现了Node和container之间的扁平化网络。同时为了应对服务发现的需求,降低网络复杂度,还要求不能使用NAT。Kubernetes并没有内置的网络解决方案,所以在社区其实有很多不同的解决方案,例如flannel,它是通过Tun/tap设备,再通过内核用户态的转化程序,实现一个类似于overlay的网络能力。Callco不需要进行overlay封装,直接通过路由的方案可以完成Kubernetes的网络需求。

接下来为大家介绍一下腾讯云Kubernetes使用的方案,我们的网络方案主要是直接使用了VPC提供的路由能力,叫做global route。简单介绍一下Kubernetes结点加入到一个集群中配置网络的过程,当我们将一个结点加到集群中的时候,K8s的Kube-controller-manager会为这个结点分配一个网端。例如,集群网络是172.16.1.0/16掩码,这时加进去一个结点。按照我们的逻辑,我们会给它赋172.16.1.0/24位掩码的CIDR。也就是所有在这个主机上创建的pod,它的ID都在这个CIDR的范围内。然后我们会去VPC那里做一个动作,将172.16.1.0/24掩码到目的地址的流量去注册一条路由规则,使所有的包都发往被赋予这个pod CIDR的主机。这样我们就可以完成之前提到的pod和Node之间的扁平化网络。

具体过程如下:假设现在有一个位于172.16.1.0/24网端机上的pod,向另一个机器的pod发送了这样一个包,这个包首先从容器出来,到cbr0 bridge然后出了主机。这时就会进入VPC的路由表进行匹配,当它发现这个pod的目的IP在172.16.2.0/24时,这个包就会被VPC转发到10.1.1.3,这样我们就可以完成一个pod的跨主机通信。pod在本地的通信比较简单,这里就不多讲了。通过这种方式,我们实现了一个pod和Node之间的扁平化网络,这里Docker的网络模式是用的bridge模式,pod IP直接由cni插件进行分配。

容器存储

接下来给大家介绍我们的K8s和腾讯云容器集成的实现。K8s集群集成了腾讯云的CBS和CFS两个能力,一个是块存储,一个是基于NFS的文件系统存储。当我们在一个pod中声明需要一个volume时,K8s如何将volume最终挂载到pod里面?其实是这样一个过程:首先,Kube-controller-manager会去provisnon这样一个volume。也就是说,实际去创建一个云盘,当云盘创建好之后会做一个Attach的动作,相当于把刚刚创建好的云盘插到对应主机上,这时,主机上的Kubelet会做一个mount动作,也就是将插进来的这个设备去mount到一个Kubernetes指定的目录,Kubelet在创建这个pod的时候,通过mount的形式把mount到的目录实际挂载到容器的namespace里面。然后当我们这个pod销毁,这个volume不再被需要的时候,它就反向去执行,先从主机上把对应的块设备先mount掉,再将它detach掉,相当于把这块磁盘从主机上拔下来,然后会由Kube-controller-manager根据对应的plugin设置销毁或者是保留。

K8s目前通过与cloud provider进行volume集成的方面主要是三种。一种是比较早期,所有要和kubernetes进行集成的Volume代码都需要写在kubernetes自己的代码仓库中。这样的缺点在于,假设我是一个存储提供商,我写的代码有些bug,这样不仅影响存储功能的正常使用,可能也会影响整个集群的稳定性。所以后来为了更好的扩展性和稳定性,Kubernetes提供了一种叫做Flex volume的形式。具体是将mount和umount这两个形式由Flex volume实现,Flex volume是一个实现了特定接口的二进制文件,实际上在需要mount、amount的时候,Kubelet会执行这个二进制文件,做一个mount、umount的动作。

这种方式其实也有一个问题,在kubernetes的部署环境中,如果要往主机上放一个二进制的动作,看起来不是那么的容器化。另外二进制文件执行的环境也有一定的要求,所以后来Kubernetes提供了第三种方式,也就是利用社区的CSI接口实现了基于CSI的插件。之前由Flex volume这个二进制文件完成的工作全部放到了容器里面,然后通过unix socket的形式,使Kubelet和实现对应功能的插件做一个通信,最后一个mount、umount的动作。我们现在也与腾讯云的CBS块存储做了集成,使用第一种方式,这是因为我们在早期使用的就是这种方式。后期我们也会将这部分独立出来,计划通过CSI的方式去提供存储的能力。这部分代码我们将会开源,但目前这个工作还正在进行中。

容器日志与监控

接下来为大家介绍一下日志和监控的方案,首先介绍一下日志的方案。在K8s中没有提供默认的日志方案,Kubernetes社区提供的这种方式可以运行一个sidecar容器,在你自己的容器中运行一个这样的进程并将它输出到标准输出,然后再用你的sidecar容器做一个收集。这样的问题在于,每跑一个pod,就要跑一个类似的sidecar容器,对于资源的消耗不太可以接受。腾讯容器服务基于Fluentd+Kubernetes custom resource definition,实现了日志收集的控制器。这个控制器可以支持收集容器的标准输出,也可以支持收集我的pod所在的Node上主机上文件路径的文件内容。

主要的实现原理是:我们会在kube-apiserver上注册一个LogCollector的custom resource definition,里面声明了我要收集namespaces下面某一个deployment对应的pod资源。还有另外一个进程就是LogCollector,去监听Kubernetes apiserver资源,然后去生成对应的Fluentd的配置文件,再通过sighup信号的形式去触发Fluentd的重载,然后去收集我们想要的日志文件。因为Kubernetes pod对应的日志文件是存储在主机的/var/log/containers的路径规则下来,直接配置Fluentd去收集这个规则,再根据我们的实际需要做一个日志的路由。这样就可以把不同的日志发往用户指定的不同后端,比如Kafka或腾讯云的CIS的日志服务。这是我们目前对于日志收集的方案实现。

在监控方面,我们将Kubernetes中pod的性能信息和云监控做了对接,主要的实现方法是在用户的每台kubernete结点上运行一个agent,这个agent在kubelet中内置的cadvisor收集pod运行的性能信息,然后再到apiserver获取这些pod对应的元数据。我们将这些性能信息和元数据进行打包,再将它上传到腾讯云的监控服务上。另外,基于腾讯云存储的监控指标,我们实现了hpa-metrics-server。Kubernetes提供的HPA能力,是它在kube-controller-manager里面实现了horizontal pod autoscaler,它会定期请求hpa metrics server去获取这个pod目前的CPU Usage或者是入带宽、出带宽这些指标的数量,根据我们的定义,比如当CPU使用率超过80%的时候,我们要去进行扩容。它也会定期拉取数据,比对当前的pod负载,直接去修改deployment中的replica字段,实现自动扩缩容。目前日志和监控的方案,是将Kubernetes和腾讯云的基础设施进行对接时候所需要做的一部分工作,也是我们的主要工作。

在 CVM 上部署 Kubernetes

下面介绍一下我们早期在腾讯云上的部署方案。当时为了产品能够快速上线,也为了满足一个完全的隔离的全托管的Kubernetes服务,我们直接把Kubernetes的Master组件部署在了一台CVM上面。同时,为了实现隔离的方式,我们将Master放到用户的VPC中。在Master组件上运行了一些标准化的Kubernetes组件,用户的Node结点以用户的身份直接在CVM那边购买机器,我们在这个基础上做一些kubelet或者kube proxy参数数值化的工作。此外,我们会做一些集群的证书配置、默认拉取镜像的凭证初始化工作。在这个方案中,我们所有的节点都处于用户的VPC里面,通过Agent初始化的方式将整个集群部署起来。缺点在于难以管理,因为我们早期是通过SSH直接登录到客户的Master结点上进行一些运维操作,对于客户的Node结点是没有办法访问的。当然,现在也没有办法访问。对于Master的一些运维工作比较困难,因为它没有办法去编程化。

将 Kubernetes 组件部署在 Kubernetes 集群中

虽然我们自己提供的是Kubernetes的服务,但对于整个容器的运维好像和Kubernetes完全没有关系。在Master上一些组件的监控并不是用我们之前提到的方式来实现的,是通过内部的监控组件来收集。这与我们之前提到的用户Node组件信息收集方式不太一样,相当于两种方式并行在跑,人力消耗也比较大。之前我们的ETCD是共享的,也就是每个集群都在ETCD中有一个自己的目录,相当于一个软隔离,没有一个硬隔离的措施。大家知道ETCD其实并不是为了海量数据存储而服务的,而我们在线上运行了数万个集群,导致遇到了很多和ETCD有关的问题。在这样的大背景下,我们推出了第二种方案,也就是将Kubernetes部署在Kubernetes里面,通过Kubernetes API去管理Master组件,包括我们刚才提到的apiserver、kube-controller-manager和一些自研的组件。这样的好处在于,我们不需要再通过SSH的方式,比如当我们需要做一个apiserver的升级或kube-controller-manager的bug修复的情况,我们不需要再通过SSH的方式去每台机器上进行操作,可以直接通过API Kubernetes提供的deployment的滚动升级的能力来完成这一点。

我们也可以充分利用Kubernetes运维的能力,包括健康检查和就绪检查的机制实现故障自愈。基于之前提到的hpa-metrics-server,可以实现apiserver的动态扩容,应对用户的集群结点有一个大规模的上升或者突然下降的情况,更好地满足Kubernetes集群里面的结点对于apiserver性能的需求。在这个基础上,我们还需要解决一个问题:之前基于CVM的部署方案是将所有的组件部署在用户的VPC里面,如果我们将所有组件部署在kubernetes Master中又要怎么做呢?我们并不能给每个用户部署一个Kubernetes集群,然后再跑它的Master,这样听起来好像和第一种方案没有什么区别。所以我们提供了一个专门的Kubernetes集群,在这个集群里面运行着现在线网所有集群的Master,这个集群运行在我们自己的VPC里面,它又要怎么和用户的VPC结点进行通信呢?我们利用了VPC提供的弹性网卡能力,这个弹性网卡会被直接绑定到运行apiserver的pod中。大家可以理解为这个pod既加入了我们用来运行Master组件集群的VPC,又加入了用户的VPC,也就是一个pod同时在两个网络中,这样就可以很好的去实现和用户Node相关的互通。另外在这个基础上,我们也可以复用之前提到的一些监控和日志设施,更好地去做信息的收集和运维。

值得提到的一点是,这个方案中,我们可以利用一个叫做Etcd operator的组件,也就是coreos其中的一个组件来为每个集群提供独立的Etcd的部署,这样就可以解决在集群数量不断上升的情况下Etcd性能吃紧的问题。通过在Kubernetes集群里面部署Kubernetes Master组件,降低了运维的成本。同时也统一了我们做运维工作的方式,我们都是通过Kubernetes的方式进行运维的。有效降低了Master组件的资源消耗,因为之前Master组件是免费提供给客户的,但有些客户的集群规模非常大,Master配置也非常高,这时集群的Master存在资源浪费的情况。

Q/A

Q:我想问一下您最后讲的运营K8s,Master假如让你们来管理,作为开发来说,是否就没有时间控制这个东西?

A:目前产品形态是这样的,这取决于我们对于产品的定义。我们希望提供一个运维透明的Kubernetes服务,不希望用户操心apiserver的扩容和Etcd的维护工作,但这就相当于将运维工作落到了用户那边。

Q:这样做是为了将权利归到你们,我们作为开发来说只是使用这个?例如我是一个Node,我要换点资源,就要通过你们的页面去加一个Node?

A:目前来说是这样的,你也可以在同样的VPC里去购买CVM,然后把所有组件都初始化,然后再通过Kubernetes的API去注册,这样也是没有问题的。

Q:刚才您提到日志监控方面,现在这种方式我只需要统一部署一个基于主机去收集这个日志就好,还是需要针对每个pod单独收集它的日志?

A:因为时间关系,没有很详细来讲。现在我们的界面上可以一键给一个集群开通一个日志收集服务,背后所做的工作,我们会去集群中创建一个daemonset,这个daemonset里面的pod运行的是我们日志收集控制器。你可以通过我们的界面,或直接通过Kubernetes crd的方式配置日志的收集规则,例如我想收集default namespace下面所有容器的日志,或者我想收集default namespace下面一个服务名字叫做nginx的日志,这些都是可以通过我们界面去配置,并不需要单独为每个pod去配置。

Q:所以从开发的角度来说,需要稍微配置一下想要收集哪些信息?

A:是的,并不需要额外再做pod发现的逻辑开发。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Kubernetes 组件
  • 容器网络
  • 容器存储
  • 容器日志与监控
  • 在 CVM 上部署 Kubernetes
  • 将 Kubernetes 组件部署在 Kubernetes 集群中
  • Q/A
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档