很多人在实际工作中都使用过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的Kubernetes一致性验证之后,为了大家更好地认知腾讯的容器服务产品,产品的名字从之前的CCS正式改名为TKE。
Kubernetes 组件

接下来我们看一下想要让Kubernetes集群运行起来我们要做哪些工作。如果对Kubernetes有了解的同学,可能知道使Kubernetes跑起来,无非是初始化一些Master组件和Node组件。首先给大家介绍Master组件,一个最简单的部署要包括Kube-apiserver、Kube-controller-manager 、kube-scheduler这些组件。Kube-apiserver可以理解为整个集群的大脑或者是集中存储,所有组件与Kubernetes的交互都是通过Kube-apiserver来完成的。其中存储着我们定义的一些工作负载以及我们对于存储的一些需求,这些数据都存储在Kube-apiserver中。
第二个组件Kube-controller-manager主要负责将声明的一些工作负载在实际的集群中运行起来,举个最简单的例子,当我们在Kubernetes上创建了一个Deployment之后,Kube-controller-manager就会去创建相应的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结点加入到一个集群中配置网络的过程,当我们将一个结点加到集群中的时候,Kubernetes的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插件进行分配。

容器存储

接下来给大家介绍我们的Kubernetes和腾讯云容器集成的实现。Kubernetes集群集成了腾讯云的CBS和CFS两个能力,一个是块存储,一个是基于NFS的文件系统存储。当我们在一个Pod中声明需要一个volume时,Kubernetes如何将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设置销毁或者是保留。

Kubernetes目前通过与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的方式去提供存储的能力。这部分代码我们将会开源,但目前这个工作还正在进行中。
容器日志与监控

接下来为大家介绍一下日志和监控的方案,首先介绍一下日志的方案。在Kubernetes中没有提供默认的日志方案,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存在资源浪费的情况。
文章来源:腾讯云容器团队。
Kubernetes企业级实战训练营

Kubernetes企业级实战训练营将于2019年8月30日在北京举办,3天时间带你系统掌握Kubernetes,学习效果不好可以继续学习。本次培训包括:Docker基础、容器技术、Docker镜像、数据共享与持久化、Docker三驾马车、Docker实践、Kubernetes基础、Pod基础与进阶、常用对象操作、服务发现、Helm、Kubernetes核心组件原理分析、Kubernetes服务质量保证、调度详解与应用场景、网络、基于Kubernetes的CI/CD、基于Kubernetes的配置管理等,点击下方图片或者阅读原文链接查看详情

Kubernetes 一键部署实践相关推荐

  1. Kubernetes一键部署利器:kubeadm

    要真正发挥容器技术的实力,你就不能仅仅局限于对 Linux 容器本身的钻研和使用. 这些知识更适合作为你的技术储备,以便在需要的时候可以帮你更快的定位问题,并解决问题. 而更深入的学习容器技术的关键在 ...

  2. docker学习总结第六篇:Kubernetes一键部署利器-kubeadm

    通过前面几篇文章的内容,我其实阐述了这样一个思想:要真正发挥容器技术的实力,你就不能仅仅局限于对 Linux 容器本身的钻研和使用. 这些知识更适合作为你的技术储备,以便在需要的时候可以帮你更快的定位 ...

  3. Kubernetes 一键部署利器:kubeadm

    文章目录 集群部署痛点 kubeadm 的工作原理 kubeadm init 的工作流程 kubeadm join 的工作流程 kubeadm 的部署配置参数 集群部署痛点 Kubernetes 的部 ...

  4. k8s主从自动切换mysql_Kubernetes一键部署Mycat+Mysql主从集群

    Kubernetes一键部署一主一从,读写分离,自动切换的mycat+mysql架构,其中mycat配置文件.mysqsl数据文件的volume挂载未涉及,可根据实际情况进行修改.所有代码参照gith ...

  5. Kubernetes实战(二)- 一键部署神器kubeadm

    容器的核心在于"容器化"应用 比如,应用既可能是 Java Web和MySQL Cassandra这样的分布式系统 而要使用容器把后者运行起来,单通过Docker把一个Cassan ...

  6. Jenkins使用FTP进行一键部署及回滚2(Windows)(项目实践)

    前提: 这一篇是继上一篇http://www.cnblogs.com/EasonJim/p/6092938.html的真实项目实践. 思路和大致实现步骤请参照上一篇文章. 注意:这篇文章涉及到两台服务 ...

  7. 应用中心最佳实践之——使用应用组完成多集群一键部署

    简介:在现实中的应用交付实践中,常常需要将同一应用同时部署到多个集群中.应用中心支持将同一个数据源定义的应用,通过应用组的形式一键部署到多个集群中,实现统一管理. 作者:指北 背景 在现实中的应用交付 ...

  8. 【docker】kubernetes集群一键部署包

    背景说明: 随着docker使用的逐步深入,docker的管理变得越来越麻烦,单纯的通过docker命令行的方式进行管理已经不能满足需求,同时也存在效率低下的问题.所以急需一个docker集群管理工具 ...

  9. Kubernetes单机部署-一键安装

    Kubernetes单机部署-一键安装 环境说明 安装步骤 Kubernetes的应用已经越来越广了,我们总是为他强大而神秘的功能所折服.总想自己也搭一套环境,奈何网上很多教程都存在或多或少的问题.遂 ...

  10. 下载达 10 万次的 IDEA 插件,K8s 一键部署了解一下?

    作者 | 铃儿响叮当 导读:涉及开发的技术人员,永远绕不开的就是将应用部署到相应服务器上,本文将给大家讲解:对于容器服务 ACK,怎么实现真正"一键部署",提高开发部署效率,在 K ...

最新文章

  1. 冒号课堂 编程范式与OOP思想
  2. EF框架 对字段属性为NULL的空值处理 类型前面加上?保证EF列表读取显示数据不会报异常...
  3. JAVA课程设计——“小羊吃蓝莓”小游戏
  4. PowerDesigner的Table视图同时显示Code和Name的方法[转发]
  5. 【Python】数组索引到底怎么整?
  6. 上证50ETF申赎清单
  7. 高仿真的类-单例工厂的顶层设计
  8. hadoop(05)、使用Eclipse连接远程Hadoop集群
  9. 有的时候入门只是一瞬间
  10. LeetCode(404)——左叶子之和(JavaScript)
  11. UTI iPhone支持依文件后缀名打开应用
  12. ora-28500 ora-02063 mysql_ORA-01017/ORA-02063 DbLink建立错误问题分析及解决
  13. spring 注入 list和map及enum映射
  14. 车载安卓屏刷鸿蒙,车载安卓大屏相比于原车导航种种优势
  15. 统计分析软件_强大的多元统计分析软件-Mplus
  16. 高效人士的116个IT秘诀
  17. 网络游戏中玩家在线数据的存取
  18. python批量下载模库网图片
  19. IOS-Svn-Cornerstone 终端 命令行
  20. 医保基金稽查案件管理系统丨陀螺研究院×FISCO BCOS案例专辑

热门文章

  1. VMware Cloud Director Availability 4.0 百度网盘 下载
  2. 对诺基亚N8有兴趣的可以进来看看
  3. 条件语句与循环语句:将数字一二三四五六七八九十转化成汉字大写的壹, 贰,叁,肆,伍,陆,柒,捌,玖,拾
  4. 一盒两用!——破解电信IPTV机顶盒为普通安卓机顶盒
  5. 计算机无法安装新字体,怎么给电脑安装新字体
  6. 在Windows服务器上启用远程桌面连接
  7. 老男孩linux高端运维课程—linux系统目录结构知识讲解
  8. 我的世界服务器物品图标闪,我的世界用资源包修改闪烁标的方法分享
  9. meta分析-stata软件使用
  10. AE快速动画脚本MotionMonkey