本文摘自云+社区技术沙龙–《容器服务最佳部署与应用实践》嘉宾的分享,主要介绍了腾讯云 CIS 服务和 Clear Container,希望你们有所收获。
以下内容为嘉宾分享:
今天我讲的主要是关于腾讯云最近新上的一款产品 CIS。我自加入腾讯云以来就一直在负责 CIS 的开发工作。不多说,我们直接进入主题。
讲述主要从五方面开始。
第一,为什么会有 CIS 这个产品,CIS 是 Container Instance Service 的简称,它的由来是什么?
第二,CIS 产品简介,它到底能为我们带来一些什么样的便利?
第三,CIS 的技术方案。
第四,CIS 如何和现有的 TKE 集群进行对接,让我们更方便的使用 K8s。
第五,讲讲 Clear Container。
01 为什么会有 CIS?Docker 很好用,编排很复杂
CIS 的产生要从 Docker 说起。Docker 非常好用,我们可以通过 Dockerfile 或者 Docker build 命令来打包一个镜像,同时可以通过 Docker pull、Docker push 命令把它和容器的仓库进行对接,最终 docker 可以跨平台的运行。
但是大量 Docker 镜像管理起来非常复杂。K8s 的产生可以简化 Docker 的编排。当然,Docker 公司本来出的 Swarm 也是可以进行编排的,经过近几年的角逐,K8s 成为了各大云厂商选择的主流编排软件。
K8s 比较复杂,主要有两点。第一是安装起来比较复杂,你需要有若干台机器,并在这些机器上安装满足 k8s 网络需求的组件,。第二使用起来比较复杂,K8s 有一些特别复杂的概念和一系列的资源。入门起来还需要一定的时间。这是 CIS 产生的第一个原因,Docker 很好用,但是编排很复杂。
TKE 简化编排,节点扩展不灵活
我们有个 TKE(原来的 CCS)集群,能够帮助用户一键创建 K8s 集群。只要在腾讯云控制台上点一下创建集群,满足网络需求的 K8s 集群就创建出来了,同时依托于腾讯云的 TKE 还可以和腾讯云的 cbs,cfs,监控等对接,另外我们提供了 hpa-metrics-server、cluster autoscater 能够帮助用户进行 pod 和节点的扩缩容,也提供了 log-collector 组件方便用户使用日志服务。
这些确实给我们的 K8s 使用带来了便利,但是这些远远不够。我们设想一个场景,现在的集群节点突然不够用了,机器的 cpu 和内存被容器占满了,这个时候我们需要一个紧急的计算服务,怎么办?就算是现在去购买节点,等待部署完成,至少也需要几十秒才能开启我这边紧急的计算服务。
当然,我们可以使用 hpa 资源,对 pod 资源进行横向伸缩容,也可以用 K8s 开源的 CA,我们将它和腾讯云的弹性伸缩组进行了对接,当我们觉得节点不够用的时候,可以通过 CA 来扩容节点。
hpa 和 ca 伸缩容虽然可以解决一定的灵活问题,但是这还远远不够,离我们想快速通过一个简单 API 创建一个服务,这还是有一定距离的。
我们看一下这些简单的运算场景。例如批量运算场景、快速验证镜像场景、TKE 快速对接场景。这些都是 CIS 产生的原因。CIS 实际上就是 Serverless Kubenetes 服务,它也对标了很多其他公有云厂商,比如说微软的 ACI,也和 AWS 的 Fargate 有点相似。它的主要功能是把 K8s 集群交给腾讯来管理,将集群交给云厂商管理,用户只需要关注 Docker 使用本身。这就是我们的 CIS 产品。
02 CIS 是怎样一个产品?CIS 主要特性
CIS 是一种使用用户承载工作负载,不需要用户管理、维护服务器的全托管容器服务。用户可以通过 Cloud Dashboard、Cloud API、Kubernetes API 创建一个容器,而这个容器实际上是落地在腾讯运维的大 CIS 集群中,我们选用 k8s 对这些容器进行管理,大家只用关注自己想用的时候调用我们的 cis api 就行了,而集群的管理交给腾讯来进行。
我们的 CIS 具有便捷、安全、便宜、灵活这四个特性。
便捷:主要是两个方面,第一是无须购买底层资源,直接通过简单的配置,就可以通过 Docker image 生成一个容器实例。第二是不需要手动删除一个容器实例,容器实例结束后,资源就会被释放。当然,您也可以配置这个容器实例长久存在。
安全:因为这是腾讯自己维护的 CIS 的 K8s 集群,可能大家会考虑有很多用户在使用腾讯云的产品,就有多租户安全的问题。这里请大家放心,是绝对安全的,我们基于 VM 级别的虚拟化隔离。而且 CIS 实例是具有 VPC 网络属性,也就是说你可以在 VPC 网络中配置一些安全组以及 ACL 策略进行访问控制。
便宜:从 Docker 来说,本来是基于 namespace 和 cgroup 进行隔离,也就是说它本来就是非常灵活的,你的 CPU 和内存限制可以以毫核和兆为单位。我们购买的 cis 实例 CPU 和内存量可以选择 0.5 核、0.5G,。第二,我们的计费是根据消耗资源进行秒级计费的。
灵活:它可以支持购买超强资源,一个实例里面也可以有多个容器,就是一个 pod 里面可以跑多个容器。
CIS 产品应用场景介绍
CIS 的主要应用场景有两个,一可以用于批量计算的场景,因为它支持秒级的批量解冻,同时逻辑结束就会自动释放,如果你有一些突然来的大批量计算业务,可以使用 CIS,能够方便大家的计算作业。
二是可以有一些镜像的快速验证产品。比如说现在有一个镜像,想快速验证这个镜像是否 OK,你就直接起一个 CIS 运行,然后进行快速的验证。
03 CIS 技术方案 CIS 产品技术架构
使用 CIS,用户只需要关注容器实例本身,而腾讯工程师是运维 CIS 所属的落地 K8s 集群。也就是说,用户要启动一个 CIS 的时候,cis 后台会对应在 K8s 集群中创建一个 cvm,再在这个 cvm 上创建一区一的 pod,这个 pod 里面会有对应的容器,最终用户就可以访问这个容器了。虽然说 CIS 资源是在腾讯的 K8s 集群里面管理,但实际上它有用户的 VPC 属性,用户可以直接通过网络访问他所购买的 CIS 实例。当然,它还会和我们的 TencentHub 和 ccr 去进行对接。这是整体的技术架构。
CIS 网络方案
cis 的网络用到了 VPC 的弹性网卡的功能。弹性网卡是腾讯云 vpc 的一款产品,借助于 vpc 的路由能力,腾讯云 cvm 上的一张网卡可以属于另外一个 vpc 网络,我们将这张网卡塞到 cis 容器所属的网络 namespace,就能实现 cis 具有 vpc 属性。
CIS 日志收集
我们通常都是通过日志来判断实例的运行情况,但是 K8s pod 中的容器如果销毁,容器中的日志真实文件肯定也会消失,pod 所属的 CVM 可能会被其他人复用,因此我们需要把日志保存下来。我们这里采用的是时序型数据库储存 cis 日志。在 cis 集群中启动一个 filebeat 的 daemonset,通过 Filebeat 来收集到 CIS 日志,再吐到 es 集群中。用户查询日志的时候,就直接通过 ES 集群中的相关 API 进行查询。这是 CIS 日志收集过程中的技术实现。
CIS 与 Serverless Kubernetes 集群
Virtual Kubelet
讲到 CIS 技术实现的时候,大家可能也会好奇,好象没什么用吧,和我们本地搭个 Docker 没什么区别?实际上开源有一个特别好的东西叫 Virtual Kubelet ,通过 Virtual Kubelet 可以和现有的 K8s 集群进行对接。例如我们可以和原来的 CCS,现在的 TKE 搭配使用,让 CIS 能够扩展运行在一个假设有无限资源的 Virtual Kubelet 节点上。
这是怎么实现的呢?首先简介一下 Virtual Kubelet。Virtual Kubelet 是一个可以通过和现有 Kubernetes 集群节点对接,并把该集群的 pod 调度到“无限资源”的虚拟 virtual-kubelet 节点的开源项目。现在是微软 ACI 和亚马逊的 fargate 已经支持了该项目,我们将这个项目和 cis 的 api 进行对接,大家可以直接体验我们现在放在 TencentHub 上的 virtual-kubelet 镜像。
K8s 现有一些 node 节点。现在部署一个 Virtual Kubelet 节点,我们也可以部署一些 pod 或者 deployment,让它运行在 Virtual Kubelet 节点上。Virtual Kubelet 节点上 pod 的落地是通过 CIS 集群,也就是说它会有一个 CIS 的 API 过来,最终创建的一个 pod 是运行在 CIS 集群上,同时因为这个 pod 上有一个属于用户 k8s 集群的弹性网卡,用户所拥有的 k8s 集群得到了扩展。
具体是怎么做的呢?我们可以看一下步骤。首先,我们可以在 CCS 节点上部署一个 Virtual Kubelet pod,它会注册一个叫 virtual-kubelet 的 node,virtual-kubelet 和 Kubelet 的功能类似,Kubelet 最终的落地创建 pod,是通过 DockerD 把 pod 的容器创建出来,virtual-kubelet 是通过 CIS 的云 API 把 CIS 的实例创建起来。第二步和第三步,是我们新建一个 Deployment\Job 之类的东西,yaml 文件定义它管理的 pod 要运行在 virtual-kubelet 节点,资源创建后,K8s 的 Master 调度器开始工作,将 pod 调度到 virtual-kubelet 节点上。
当然,我们最终可以看到是这样的图, virtual-kubelet 可以无限放大,实际上运行个很多 CIS 资源,因为它实际上不在用 CPU 内存,真正的 CPU 在用的是 CIS 集群本身。如果 Deployment 删掉,对应的这些实例也会被删掉。也就是说,通过 virtual-kubelet 这个中间件,你就可以实现 CIS 和 TKE 的对接,这对很多用户来说还是很方便的。
这是现在 CIS 的一些基本功能。总结一下,CIS 是用户只用关注 Docker 本身的一种容器服务,它所落地的 K8s 是我们腾讯自己在维护的,这样做的好处是,用户可以不关注 K8s 的运维,同时也可以通过这些 API,能够快速的对接现有的 K8s 集群,实现快速对接的功能。
04 Clear Container 什么是 Docker?什么是 K8s?
我们先回顾一下什么是 Docker,什么是 K8s。K8s 是业界主流的 paas 平台,用户可以通过 kubectl 创建一些资源,这些资源的最主流落地是通过 DockerD 把 pod 的 runtime(容器)创建出来。Docker 是一个轻量级的虚拟化项目,同时 Docker 是 K8s 的 pod 的 runtime。当然,K8s 还支持例如 gvisor 等其他 runtime。
CIS 的整体架构
CIS 的架构是每个容器实例是运行在一个 cvm 节点上面的。这样做带来一个问题,实际上用户只需要它的容器,但是我们为了能保证多租户之间的隔离,为了保证安全,我们实际上起了一个厚重的虚拟机。尽管我们有一个强大的 buffer 池在这里,创建的请求热启动也是在 30 秒之内,性能能够保证,但是对于腾讯自己来说,这个运维成本确实是挺多的,用户只需要容器,我们却提供了一个虚拟机。
有了这个问题,我们应该该怎么改进呢?如果把 Docker 替换成 Clear Containers 会怎样?
先介绍一下 Clear Containers,或者说现在的 kata Containers。左边图是 Docker 架构,Docker 是基于 linux namespace 和 cgroup 技术的 runtime,namespace 保障隔离,cgroup 控制 CPU 和内存资源。docker 在业界最大的安全诟病是共内核。相反,虚拟机的主流技术,KVM 结合硬件辅助虚拟化技术,将 x86 虚拟机 kernel 运行于 non-root ring 0 态,和 host 有一个很好的隔离。实际上这里的虚拟机,我们可以直接把它当作 kata 或者 clear Containers。不同的是 clear container 有一个很小的内核,基于中间件,再构造虚拟化后的 APP。
总结一下 Clear Containers 和 Docker 的区别,Clear Containers 不共内核,更安全。
用 Clear Containers 替换 Docker?
如果我们用 Clear Containers 替换 Docker,这时候会怎样呢?这时还是有一个 K8s 的集群,但是现在不是虚拟机,而是真实的物理机,实际上我们也有这一款黑石产品,真正的 Node 节点落地是在物理机上面。这是一个物理机的 Node 节点,Clear Containers 作为 Kubelet runtime,也就是说,这个 Clear Containers 代替了原来的 Docker 在给用户提供服务。这样做的好处有两点。
第一,相比于原来的虚拟机起动厚重的虚拟机,虚拟机上再起动 Docker 提供服务,现在直接在物理机上起动轻量的 Clear Containers 直接给用户提供服务,虚拟机层级变小,这样就比较节约资源。
第二,因为层级变小,也会提高性能。这么做当然是有很大好处的。但是有一个问题,Clear Containers 或者 kata Container 能够和现在原生的 Docker 进行对接的吗?答案是可以的。也就是说,你可以使用 Clear Container 这个底层基于 KVM 的虚拟化技术,也可以复用原来的 docker image。具体是怎么实现的,这是 Clear Containers 的细节。左边是原来的 Docker 细节,Docker 的分层有一个 Containerd,接下来是各个 shim,最后的实际落地是 runshim,它结合 namespace 隔离调用了 linux 的 clone 系统调用。现在相当于 runshim 变成了 cc-runtime,前面部分的 Docker 镜像都是相同的,但是最终的落地,cc-runtime 原来是基于 clone 系统调用去创一个 Docker 容器,现在我们用 cc-runtime 结合 qemu 去创一个虚拟机。这样做到底有什么好处呢?就是虚拟化更安全了。
它为什么可以复用 Docker 的生态,这一部分都不变呢?这就是得益于 Clear Containers 或者 kata Containers 组件的拆解。原来 Clear Containers 包含 cc-runtime、cc-shim、cc-proxy、cc-agent、miniOS。所谓 miniOS,虚拟机起来的时候需要一个最小内核和 rootfs。相比hyper.sh,它是 runV,但是它不能够兼容 Docker 生态,Clear Container 只实现 runtime,把原来的 runshim 分成 cc-runtime 和 cc-agent,这样还会有 vm 带来的额外通信机制。原来 Docker 文件系统是通过 virtio-blk/9pfs 机制挂在虚拟机里面,这样就可以实现复用 Docker 生态,同时也能带来基于 KVM 隔离虚拟化的安全。
第二个问题,大家比较关心的是 kata Containers 或者 Clear Container 的网络到底是怎么进行的。我们知道,Docker 的网络有一个 VETH 设备,通过 veth 设备联通 docker0 网桥进入 host 协议栈。但是虚拟机就不一样了,基于 KVM 的虚拟机不支持 veth 设备,往往是虚拟机里面有一个虚拟网络设备,host 上更多是一个 tap 设备。如果我们要复用 Docker 的网络生态,需要创建一个 VETH 设备链接 cc-bridge 网桥,再和 host 上的 tap 设备,网络流量就通过到 host 的 tap0—cc-bridge—eth0—veth0—Docker0,再进 host 协议栈出去。
还有一个问题,Clear Containers 原来是每个容器都会起一个虚拟机,这样就会带来一个问题,pod 有多个容器的概念,也就是说一个 pod 里面会有多个中期,如果每个 pod 都要起一个虚拟机,一个 pod 多容器,就有若干个虚拟机吗?答案是不一定的,因为 Clear Containers 可以借助 CRI-O 和 K8s 进行对接。
原来 Kubelet 是这样的,如果我们要创建 pod,直接是 Kubelet 和 Docker 进行访问,然后把这个容器创出来。加了 CRI-O 这个组件之后,Kubelet 作为 client,有个 CRI-O Server 在这里,CRI-O 会控制起一个 runc,基于 Docker 的 pod 就起来了。当然,如果是 Clound Containers 或者 kata Containers,就要调用 cc-runtime 创建 clear container。同时你也可以根据自己的应用编排安全需要,控制 pod 的容器是共虚拟机还是多个虚拟机。
本文转载自公众号云加社区(ID:QcloudCommunity)。
原文链接:
https://mp.weixin.qq.com/s/a18DDdV6Q2JozZKtwRHswQ
评论