[关闭]
@gaoxiaoyunwei2017 2018-08-24T11:06:59.000000Z 字数 13436 阅读 732

DevOps中军:腾讯基于容器的持续集成实践与安全挑战--马全一

黄晓轩


讲师 | 马全一
编辑 | 黄晓轩

讲师简介

马全一
腾讯资深产品经理,资深容器技术和DevOps专家,负责容器类产品和DevOps产品。国内早期的容器开源技术和Golang语言布道师,多次在国内外技术会议上演讲,专注于利用容器构建高效和安全的DevOps体系。

前言

大家好,我是马全一。我现在在腾讯的SNG的腾讯云做容器还有DevOps的产品经理。因为我以前一直是做容器相关的,也是研发出身,所以我第一感觉就是容器在DevOps,尤其是在CI集成这一块是非常有前景的。包括国内最开始推广容器的时候,其实很多人都是把他放在CI的工具里面,比如做一些测试环境的集成。所以我后来在做容器产品的时候,比较关注DevOps。
在去年我偶然听到国内有一家比较知名的比特币交易所,他们在DevOps过程中,后来在审计中发现在build过程中,他们的线上服务被加壳被篡改,这个服务在线上在尝试提取比特币到一个不知名的账户上。但是被他们发现了,把这个漏洞补上了,但是从这个过程我觉得DevOps整个链条包括工具,在安全上是非常有影响的,所以后来我就在这个方面做了很多关注。之前我在华为,后来加入到腾讯云之后做腾讯云的服务。因为你线上服务,安全更是一个不可规避的问题,尤其是容器,容器在安全上一直被挑战。所以我就一直在关注这个话题。我本身不是做安全出身的,所以我只讲我在设计产品过程中遇到的这些安全的挑战,以及包括我们在日常开发过程中,用什么样的技术去把他能够尽量实现自己认为的安全。

image.png-852.5kB

在分享开始之前,我说一下我对DevOps的理解。我觉得DevOps只有两点:

  1. 他就是一个哲学。你如果去希望采用一个固定的形式去实现一个公司的DevOps,你多半会失败的。如果你有从事ERP经验的,你知道在实施ERP的过程中,老板的想法很好,但最后你发现投入跟产出得到的完全不是正比。所以我们在腾讯云做了很多交流,包括跟很多政企、银行客户做交流,他把我们找来,我们想听一下腾讯是怎么做这个DevOps的。发现其实这两家公司在业务形态上完全不一样的。
    在腾讯内部里面,除了工蜂Git系统和TAPD以外,剩下的各个业务线都会维护自己CI的工具。尤其是在ITD(集成技术开发)研发流程管理,都是公司制定并确定一个流程怎么做。这和DevOps理念还是不同的。所以我觉得你如果希望改进自己公司的DevOps流程,你还是根据自己公司的业务形态、产品形态做一些调整,细节上做一些改变。然后按照这个哲学一点一点改,如果你希望找一家供应商,他说我有一套很好的系统,一定能帮你把DevOps做好,那他一定是骗你的。你买去以后一定会自己改,改到最后和买的又不同,最终还是会发现DevOps流程不行。所以这种情况下一般都是你买一个通用型平台,再去买很多服务,根据业务形态找一些比较好的顾问来帮你做这些定制,这是一个方式。这是我对DevOps一个理解,他的第一点最重要的就是他是一个哲学形态,并不是规则。所以你听完腾讯怎么做DevOps的,你会发现腾讯的DevOps是很佛系的,他不会管你哪个BG用什么样的工具,只要根据业务形态自己搞就可以了。只有工蜂系统和TAPD是固定的。
  2. 可编程。所有DevOps的这些任务和流程是需要可编程的,所以我们在做DevOps产品的时候也是遵循这个规则。我前一段时间碰到华为的一个同事,我跟他聊天,我说现在运维已经不需要了。因为现在的Kubernetes在海外是非常火的,所以很多的业务形态都转成Kubernetes。运维人员在云上安装了Kubernetes之后,只要知道我yaml文件是怎么写的,你根本不需要学什么其他的。当然这就是一个笑话,最终来反映的,你要想把DevOps做好,第一,要在流程上是可显性、可定义的;第二,你要对这些Task有一个定义,能显性可编程的。这才是DevOps能做好的关键。

我在这个PPT边上有一个图,这是英国的一家做Cloud Native安全相关的公司。他们2018年做了一个对DevOps的安全调查,看到海外,他们其实在DevOps安全的投入是在增加的。但是在国内好像这个话题,大家还在研究到底怎么做DevOps,DevOps安全可能还是在权限管理各方面没有做的很深。所以这次我来分享一些关于我们在做这件事情当中遇到的问题。

image.png-37.2kB

我会讲一下我们的方案,我们遇到的一些困境,因为是在腾讯云上提供服务,所以会有权限问题,还有供应链的问题,审计,还有你如何做安全的构建,包括使用Kubernetes过程中遇到的安全规则

01 腾讯云持续集成方案

image.png-95.5kB

腾讯云的DevOps解决方案,他的目标是要把腾讯内部好的DevOps的工具release出来,作为服务提供给所有开发者。所以我们在腾讯云产品里面重点做了编排的引擎,我们管他叫DevOps编排引擎。因为我们底层是用Kubernetes做的,所以我们把他叫做编排引擎,而没叫Pipeline,或者工作流之类的。我们因为是用容器来做,所以我们管他叫做编排引擎。
我后面会讲到很多问题,其实是因为我们这是个容器,所以他会遇到容器相关,包括Kubernetes相关的一些安全问题。但是今天我讲的并不是说Kubernetes安全的一个话题,只是大概介绍一下。
这里面我们编排引擎在上面提供有镜像扫描、构建这些能力,还有签名的工具。首先我们是提供一系列存储的机制,因为代码存储在腾讯云上我们提供的是工蜂系统,你们会用到跟腾讯内部用的一样的系统。你如果做一些编译,比如说生成一些二进制的文件,我们会有Artifact的存储。如果你用容器镜像会有Docker镜像的存储。你用的Helm Chart或者Operator,都会有特定的一些存储机制给你。
我们在这些存储里面都会有扫描,会有构建的一些在线的编辑工具。我们现在已经除了工蜂和织云以外,还集成了一些腾讯内部的研发工具。QTA是移动端的自动化测试工具,你可以用他来写一些自动化测试用例,会反馈给你一个测试报告。这主要针对移动端的功能性测试,这个QTA是SNG内部,就是在手Q还有QQ音乐都在用的产品。Wetest也是移动端测试,他比较倾向于真机测试,就是你跑在不同的机型,他会给你出一个兼容性报告,所以他会比较倾向于兼容性测试。压测大师主要是针对于你线上的服务进行压测,你的网络,你的网站能支撑多少访问,他会给你整个一套能力。织云是你作为部署来去用的,如果你线上的服务需要持续的Ops,我们整个编排引擎会调度织云来去部署,主要是这样的一个功能。
在这里面,我们重点做的就是编排的引擎,因为我们需要把所有的这些工具串起来。这是我们自己开发的,没有用Jenkins做。每次分享都会被问道为什么不用Jenkins。我们有一个同事从IEG转岗到我们部门做DevOps相关的工作,他是在IEG做DevOps的,他过来以后跟我讲,你做了这套东西,我觉得不适用,然后我们有在IEG,在游戏的业务里面,我们是怎么做的,他讲了一遍,把他的界面给我打开看了一下。
我心里感受是这样的,如果我是一个公司业务DevOps支持的一个人,我也会用Jenkins去搭建一套平台,把已有业务这些逻辑都变成很多任务让你来选,最后用Jenkins把他实现,这个完全没有问题,这就是要做的工作。但是我们在腾讯云上提供一个服务的时候,就出现一个问题,我们其实不知道你是什么样的业务,我们只能做一个通用型的。Jenkins并没有一个业务形态说你要做成什么样,他是提供一个强大的plugin生态系统给你,你可以选择。如果你看过老版的Jenkins代码,包括他那个界面,我觉得至少从我的个人感觉也是挺丑的。现在当然他演变,后来他做了一个Blue Ocean的版本,现在针对CloudNative又出了一个Jenkins X。所以他也在不停的变革,针对业务是在做,但是他之前是没有的。
对于我们来说其实遇到的问题就是,我们在腾讯云提供服务,我们不知道用户的服务形态是什么。所以我们只能提供一个相对通用型的DevOps引擎给你,帮助你做定制,然后也要提供一套生态的支持给你。
所以我们的问题就是怎么样做一个比较通用的DevOps引擎,这里有三点:通用的编排逻辑;通用的插件机制;通用的执行方式。

image.png-87.2kB

  1. 通用的编排逻辑。我们现在整个DevOps流程里面跟大多数的DevOps产品是一样的,我们没有叫Pipeline,我们用Workflow。然后在Workflow上我们有很多设置叫Stage,这个其实在很多竞品也都叫Stage,你可以把业务进行一个划分。在我们这里你可以随便划分。有的产品会做生产、预生产,给你预设很多Stage让你去做。其实我看来,就是他相对比较固化你的DevOps流程,不够通用性,在我们这里可以随便设。他有不同的一点,Stage下你可以执行Job任务。这个任务有两种执行形态:一种执行形态是以容器的方式执行。你把一个容器镜像里面做一个任务给他,让他执行。另一种,他会去调一个第三方的API,比如说去调织云,然后说我要部署一个 Artifact的包到某一个服务器上。这个是两种方式。这个Job在整个Stage下有两种流程:一种就是顺序执行,你执行完第一个执行第二个;还有一种是并行执行。有的时候我们可能会把一个测试任务做一个划分,比如说我有10万个测试用例,我把他划分为5个任务,之间没有业务逻辑关系的就让他并行来执行,所以他是这种执行形态。在这里我们做了一个Component定义,Component在我们这里其实就是一个容器。
    为什么叫Component:Jenkins他之所以被大家接受,是因为他有一个强大的plugin。Docker之所以最后火起来,他在原先技术上做了一个AOF插件的机制,然后一层一层去折叠,还提供了Registry让你可以有地方下一些镜像,这是他比Lxc更先进的地方。当你有这样一个生态的时候,你的产品才有所成功。所以我们本着这个产品的原则,做了一个Component。
    这里一个Component其实就是一个容器的镜像。你可以传入一些输入值和输出值,然后我们做了一个定义,所有的输入值都是以T_大写字母来输入。然后你可以在里面去写任意一个程序,去读取这个环境变量,因为他是用容器的环境变量传进来的,然后来去获得他。你把你的运行结果输出到采用那种T-RESULT这样的方式,再打到你系统的标准输出里面。这样我们在运行过程中,我们会拿到容器的所有日志,正则出来你的输出值是什么。这样的话,我们在整个的Job和Job之间形成一个上下文的传递,这是我们希望做到的第一点。
    image.png-56.4kB
  2. 通用的插件机制。我们希望以一个容器镜像的方式来去做DevOps的插件给你来用。这样,你就不用再关心,你这个plugin需要运行在哪里;他的环境是什么;你怎么创建一个这样的环境;当运行的时候,你需要多少资源;怎样销毁他。这些你都不需要管,你只需要知道我要跑这个镜像,我的输入值可能是一个Git仓库的Url。我的输出值就是我的执行结果就够了。这样可以更容易share。在以前share一个plugin,我不仅需要给代码,还要有readme等等东西。现在我只要告诉你容器镜像是什么,输入值是什么,输出值是什么。你就算不用我们的引擎做这件事,你也可以直接找一台机器,装一个Docker就可以。所以这种方式是最合适的。
    我们如果做这样一个镜像,你可以任意选择你熟悉的一个baseimage来做。但是我们这里推荐的就是Phusion的baseimage。他们做的baseimage相当于轻量级虚拟机的东西,所以他的baseimage里面是有SSH的,你可以很容易的SSH进去。然后你也可以在里面做一些crond任务,这个与普通的镜像原则是不一样的。因为你Docker镜像是越小越好,他这个反而是越大越好。但是他运行起来,占用内存却很小,只有5MB。我们选他主要的原因是,当你要去写这样一个Component的时候,这个时候你总需要调试,调试的时候你直接SSH进去,这个应该是被推荐的一个原因。所以要有一个通用的编排的引擎,然后有一个机制被大家接受,然后有一个比较通用的一个插件,以Component的存在,我们也会做很多Component插件给大家来用,形成这样一个形态。
    image.png-90.2kB
  3. 通用的执行方式。前面是以容器的方式来做,所以我们认为后面应该是以一个Kubernetes调度引擎来执行。这里有个不同,我们执行前会有一个Lua脚本的解析,这里面你可以做一些判断,输入值是先到Lua引擎这里,所以可以先执行一些Lua的脚本处理一些业务逻辑。因为我们做的这个是相当简单的调度编排,所以他没有if和循环之类的,要想处理一下复杂业务逻辑的话,你可能要在这里做一些事情。当他执行的时候,第一种是你传了一个容器镜像,我就去一个Registry,把他拽下来,扔到我们Kubernetes引擎上去执行。还有一种,你去调第三方的API,这个时候我们就会去靠相关的,比如我们会在工蜂上去克隆代码,比如说我要回写一个事情,某个代码他的check是错的,那我可能要调工蜂API去写说他这个检测是不通过的,或者是调织云来去执行下一步的部署任务。当你所有执行完以后,你还是可以执行一个Lua的脚本,对你输出值再去做一次逻辑的判断,然后输出最终的这个值。所以在这里面我们去采用这种方式来去执行,然后他的好处在于很多企业里面,他的CI的资源是分到各个组的,比如说就像在腾讯也是,每个BG他自己来管理自己编译的这些东西的。但是你从在整个公司角度来看的时候,你发现很多资源会有浪费,这个时候你用一个Kubernetes来管理,他的管理资源粒度比较细,这个时候你的利用率就会提高。因为你执行他的时候,是可以指定他的CPU和内存。
    在我们做的解决方案里面,我们觉得通用性是至关重要的,这个通用性也是帮助我们要把腾讯内部的DevOps这个工具逐渐的放到腾讯云上来提供服务。

任何一个组件都是一个容器镜像,你甚至可以在单机上直接写一个yaml的文件来去执行。我们前面说的这个Flow,我们在界面上是用一个拖拽的方式让你创建,最终他是会映射成一个yaml的脚本,你可以自己写这样的一个yaml,所以他间接的说是可编程性的。

02 账号体系互通带来的认证和权限问题

这个就是我们在腾讯云上做的DevOps的解决方案,然后我们把工蜂、织云等系统在往上搬。这个过程中带来第一个问题,就是帐号和权限问题。

image.png-38.2kB

首先在腾讯云上,他就是一个比较复杂的帐号体系。他有一种叫做开发商和协作者,还有一种叫做开发商和开发者。我去了腾讯云以后,我听了这个比较晕,不知道什么意思。他们给我解释了一下,开发商是真正有钱的那个帐号,这个帐号是你的公司主帐号,你会关联到你财务的记录,你充的钱都是在这个帐号上。干活肯定不是这个帐号,会设协作者帐号。协作者账号可以是你研发或者运维的QQ号,但是这个协作者是对应的某一个QQ号,或者某一个微信帐号。
开发商账号下的开发者没有在微信或者QQ里面有直接对应的,而是他直接创建出来的某一个帐号,是一个实体账号。这两种账号的区别就是能对应实体和不对应实体。但他总的原则就是说,任何一个帐号进来,如果不是开发商帐号的话,都需要开发商给他授权,你只有授权以后才能使用腾讯云上的各种服务,比如说像我们的容器TK1的服务,或者CIS服务,然后来去做一些事。

image.png-33.4kB

我们做的这个Hub账号体系,包括工蜂,我们采用的帐号体系,跟GitHub是类似的。因为我们认为这种方式,是比较倾向于互联网用户用的。首先你有用户,用户可以创建组织,用户和组织是平级的,有一个用户叫A,就不能再有一个组织叫A。在组织下你可以创建team,然后把用户加进去并赋权限。工蜂系统也是跟这个类似的。腾讯内部的很多DevOps的工具,大部分都采用这种模式,因为我们就是互联网公司,所以GitHub的这个模式比较容易接受。我们公司内部,统一登录现在都是企业微信来直接登录,所以他是两种帐号体系。
每一个我们创立的独立的服务,都要管理自己的资源,比如像我们的Tencent Hub,他管理的容器镜像。工蜂在腾讯云上,那些Git仓库是他自己来管。但是你从Hub,要部署一个服务到腾讯其他的服务上去,比如说你要去写一个对象存储,存在腾讯的对象存储上,就要查有没有这个权限。

image.png-39.8kB

这个里面就涉及一个问题,你怎么知道他有权限用,或者那个帐号有没有钱。Account服务用来证明谁是谁,CAM是腾讯的另一个服务,是开发商给开发者或者协作者授权使用某些服务的权限。腾讯云上的API体系是用RPC的,我们目前是RPC3.0的API。因为在腾讯开发的迭代速度比较快,所以RPC一直在改。工蜂、织云等都是其他BG的DevOps工具,他们没有投时间和精力跟着维护RPC版本的变化,而且腾讯内部产品大部分都是RESTful API,所以我们在中间做了一个账号转换系统,就是IAC(Internal Account CAM)。所有对账号的查询,权限的查询,全部用RESTful API到IAC上查询。这个服务是只在这些服务之间内部看到的,对外的用户界面上你不知道有这个东西的,所以他都到这里来查。这个是我们采用一个方式来屏蔽,这在研发里面,你发现设计模式是很普遍的。所有的业务逻辑,我们会在IAC对内部我们导上来的服务做一层屏蔽。

image.png-91.9kB

这个过程中我们就想什么是JWT(JSON Web Token),他是一个授权的机制。他分成三段:

  1. HEADER。要标记字符串的类型和加密方式。
  2. PAYLOAD。你可以在里面加入任何的业务逻辑,这里面不限定。所以我们就可以把前面的这些授权机制里面要额外带的一些信息放作这个PAYLOAD里面。
  3. SIGNATURE,通过secret key签名,保证整个Token没有被篡改。

image.png-66.9kB

我们使用JWT模式,来处理用户查询和权限查询。
比如像Tencent Hub,我们在腾讯上有个CIS服务,你可以把一个容器镜像当做一个单容器实例,一个容器镜像你可以把他看作一个网站,一个简单的虚拟机来去运行他。所以如果在Tencent Hub上去运行CIS,我要把一个镜像push到CIS服务上,让他跑起来的时候,他就要去查询这个帐号有没有CIS的权限,主服务商有没有钱做这个事。因为CIS那边还有你要跑多少CPU,跑多少内存等,一大堆的问题。这个时候Hub是不知道我当前这个用户有没有这个权限,所以他就上IAC里面前去查,我查某个用户。IAC会根据内部API调用去查他是不是能用。假设能用,他会在Http返回里面,把整个返回JWT的Token带回来,我们就会在PAYLOAD里面放一些授权的机制,这些授权机制只有腾讯内部服务再用,例如: Kubernetes的Master IP和secret key。最后调用CIS服务。这就是我们利用JWT查询在腾讯任何系统上的帐号有没有在腾讯云上被正确授权过的方式。

image.png-49.5kB

还有一种情况,比如说像在Hub上,我们会去克隆一个工蜂的Git仓库,拉下来做build。这个时候我们就不走这个东西。腾讯内部的产品,其实都是用OAuth做授权的,所以在Hub和工蜂之间,我们直接走OAuth授权,就不再经过腾讯云那边授权。但是查询工蜂的授权,还是会到IAC去查。所以在帐号服务的过程里面,我们主要是使用OAuth2的协议和JWT的协议来保证你是被授权过的,你有某一个使用资源的权限。这是我们在做DevOps过程中第一个问题,你有没有正确的权限体系和帐号体系。

03 Supply Chain Audit

image.png-115.9kB

中间这一段图,就是一个比较传统行业的Supply Chain他的供应链的变化。每个DevOps产品,他都是在做Pipeline、编排、Workflow,他其实都是在定义这样一个流程,他的期望值是让这个流程更加自动化,然后让他迭代速度更快,上线的速度更快,服务的效果更好。但是当出现这样很多环节的时候,你必然会带来很多的安全问题和挑战。所以在这里面有很多安全威胁,有四种类型比较普遍:

  1. 软件更新污染。最近有一个新闻,Linux的发行版Gentoo在GitHub上的帐号被攻破了,所有的服务紧急全部停了。如果他们没有发现的话,比如我要打开Gentoo,把整个系统更新一遍的时候,我就会下载下来很多不知道的东西,他可能编译以后,我很多地方都会被改掉了。所以这种类型的攻击,是在Update源来做,很多银行和公司,他相对来说是一个封闭的网络,如果你内部有这些Maven源、RPM源、NPM的源,这个时候你其实就不太会有问题,如果你是在互联网公司就会有这个问题。
  2. 软件库污染。2015年有很多IOS的APP,暴露出被装了后门,比如说滴滴,还有愤怒的小鸟,甚至腾讯也有几款软件也有问题。最后查出来是因为开发者在做IOS开发的时候,没有上苹果的网站去下载Xcode,而是在国内随便找了一个速度比较快的地方下载。那个Xcode被篡改过,所以每次在编译生成ipa包的时候加了后门。这个就是当时的问题,但是现在大家都去官方网站下载了。
  3. 固件污染。大家都有路由器,你觉得路由器固件安全吗。尤其像比如说大家要访问一些不知名网站的时候,不能说名字的网站,你需要去翻墙,这个时候你要在家里翻墙就很麻烦,我把路由器直接做了一个没名的固件,装了一个什么SSR的东西,给他更新。这个时候这些固件都是有安全威胁的,你其实根本不知道这固件里面在干嘛。你装上以后有可能就是一个非常完美的肉机,或者你在访问支付网站的时候被篡改,你根本不知道,所以这些固件是非常危险的。
  4. 水洞污染。去年爆发出来有一些勒索软件,你的文件被加密了,如果你不给他打比特币,他就给你删了。他采用的方式就是我给你发一个邮件,诱使你点某些网站,点开了以后利用浏览器的漏洞装进去一些病毒,然后把你的硬盘或文件做加密。这种威胁其实每天都在,这个是我们极力在整个DevOps流程避免的。

还有在我们开发过程中也出现了很多问题:

  1. 不停增长地、碎片化的工具集。腾讯有几万的研发,我们使用了不同的软件,使用了不同的语言,我们有使用Go、Python、Unity等等。这就有了一个碎片化的工具集,
  2. 分布式的协作。腾讯是分布式的研发模式,几万的研发要不停的分布式写作,这个时候在DevOps就会遇到很多的问题。
  3. 大量使用了开源软件。国内的公司,大部分都可以叫Open Source集成商。不管你们卖给客户是什么,最终一翻底牌都是拿某些开源软件改的,那些开源软件都会有各种各样的问题。比如我们在提供Kubernetes服务时,我们和Kubernetes security group有合作,当发现新的漏洞时,会通知合作云服务厂商,我们会紧急修复他。
  4. 业务多云服务商。现在很多架构都是多云部署,不光是我们腾讯云,也可能使用了其他云,多云部署下你做DevOps整个供应链时,也有各种各样的问题。
  5. 基础架构都是微服务。微服务比较普遍,微服务之间造成你部署的应用粒度变小,规模膨胀,这个时候也是一个非常大的安全挑战问题。

image.png-188.9kB

Google,他和IBM、RedHat、CoreOS还有一些安全的网站,他们合作在推Grafeas。
Grafeas的官方定义:“Grafeas (“scribe” in Greek) is an open-source artifact metadata API that provides a uniform way to audit and govern your software supply chain”。
他其实专门做了一个artifact metadata的一个API规范。让你来做审计。他有两种:一种叫Note;一种叫做Occurrence。Note当你定期扫整个代码仓库的时候,会告诉你有没有发现CVE漏洞。Occurrence就是描述你整个CVE漏洞具体的内容是什么。现在Grafeas是OCI下的一个项目。他的含义大致就是说叫提案,法律的解释下是提案,其实就是个规范,因为以前是没有规范的定义,这都属于标准组织,但是从OCI以后,这种规范的基金会就变多了,所以这个是一整套审计的规范。

image.png-197.8kB

他的审计过程是这样的。蓝色的实线就是一个DevOps流程的大多数采用的方式。我有一个code,我要做build,然后我要做镜像扫描,然后测试,然后部署,部署到不管是虚拟机也好、裸机还是容器服务也好,把他部署上去。这个过程中其实有很多审计的结构产生,他是按照metadata产生,在这个链条里面比较普遍关注的是:

所以他会产生这样一个链条的传递。然后当你事后再审计的时候,你会发现我从code一直到扫描,所有过程中我所使用的这些都是具有一致性,不会在中间过程被篡改。就像我前面讲的那个例子,如果你在build过程中被加壳了,那你SHA256的包肯定要改。如果你有这样整个审计机制,你很容易发现问题,这就是Grafeas一个比较应用的实例。
在Kubernetes,有一个叫Kritis这样一个Admission Controller,来实现Grafeas在Kubernetes里面的管理实现。所以Grafeas整套来实现一个供应链的管理,重要的一点就是说,你要能够有一个审计的原则,然后你要能够知道你整个链条里面,从开始到最终部署的是一致的,不要在过程中被篡改,这个是我们在做这个产品的过程中遇到的另一个安全的挑战。

04 容器和Artifacts的安全构建

因为我们提供了容器镜像和二进制文件build功能,所以我们要有一个安全的build环境给你。

image.png-174kB

现在你做一个Docker镜像build的安全问题,大多数来源于你要以Root权限来去执行Docker Daemon,然后靠Docker Daemon的API执行Docker build。这个时候你这个root权限其实已经映射到你容器里面。就算你把这个权限变小,他里面其实还是root权限,他会引发有很多安全问题。

解决的方式:
不以root权限做build。Google发布了一个工具Kaniko,就是不以root权限做dockerfile的build。还有一个RedHat有一个叫Buildah的项目,他是不同的实验方式,但是也是不以root权限来做build。

image.png-117.5kB
在腾讯云上,我们其实就更简单粗暴一点,我们直接用了Kata。Kata是挂在OpenStack基金会下面,他跟整个容器的不同情况,就是说现在在左侧的这边,比如我们在腾讯云上买一个Kubernetes服务,就是左侧的情况。我们反正认为你用的虚拟机都是你的,所以这些容器之间也都是共享kernel的,即使出问题也是在小范围内,不会影响到其他人。
在做Docker Hub服务的时候,他的多租户的形态,我们就不能这么干了。我们用Kata这种形式,我虽然在Kubernetes去跑,但是你每个Virtual Machine里面还是有一个隔离的,每一个容器跟容器之间是有自己的kernel,他相当于是一个KVM裁剪版。我们就在Kata Container里面使用Docker in Docker这个方式去做build。就是说Kata Container里面先跑一个容器镜像,这个容器镜像里面跑了一个Docker Daemon,我们再把build任务下给Docker Daemon。所以他整个是在一个相对比较封闭的,达到KVM隔离机制的虚拟机环境下做build。当然我们也在研究Google和RedHat的产品怎么做的。但是我们觉得这种方式来的更快,更简单粗暴一些,所以我们现在在腾讯云上是这样做的。

05 容器镜像扫描

image.png-116.3kB

我们再讲镜像扫描,这个是DevOps里面用容器去做DevOps普遍采用的流程,就是说我去做完build以后,我肯定做一个Image Scanner。在上生产环境以后,要有一个事后的审计。

image.png-59.9kB

我们先说CoreOS Clair,这是专门做容器镜像静态扫描的,会告诉你CVE漏洞是什么。腾讯云上的产品也是用Clair做的。你每次push一个镜像上来,我们都会去扫,看看有没有漏洞,有漏洞的话,直接通知你是哪个CVE的版本有漏洞。

这是Docker企业级解决方案Nautilus。他跟Clair基本上是一样的。所以我们反过来讲,他到底怎么扫的?我们都知道把容器发给他,把版本发给他以后他就扫了。后来我稍微研究了一下,这个事是这样的,首先这个CVE漏洞上有一个编号,他影响到的linux版本,他相关的,比如这个图写的是openssl,后面有Heartbleed漏洞,他怎么扫呢?当你一个容器镜像上来有很多层,拿到这个层以后,因为他是tar包的格式,我就把tar包解开,每个容器镜像都有manifest文件,我同时会去扫,我会生成manifesical,其实就是描述了这一层容器镜像里面是什么?有的容器镜像你就能够Scan出来说他装的是openssl,所以采用这种方式把每一层镜像你传上来的去扫。当然我扫过来的镜像都是有哈希值的,每个哈希值我扫过的,有哈希值的我就不扫。CVE的format上会写是哪个系统版本,哪个软件,哪个版本有什么什么样的漏洞?把我扫到的结果去一一对比,形成整个CVE的报告。
所以这个模式并不是针对容器经常做的,你看到很多像产品的扫描其实都是采用这种模式来做的。所以你在市面上看到的都是静态扫描,就是说我只能对你这个软件没有运行的静态情况去做扫描,而不是我运行起来再做内存分析,这种扫描其实很少。这个就是静态扫描的功能。

然后我们再讲,我们如何构建一个运行环境?安全的运行环境,因为容器镜像是轻量级的隔离,今年在哥本哈根的一个会上,Google发起的一个gVisor项目。他就是运行了一个轻量级的沙箱。右边的图就是怎么做的。Daemon去调Containerd,Containerd再去调runc去创建。gVisor就是实现了一个新的runc叫runsc,会劫持所有在Container里面的内核调用的api,做一次虚拟的kernel。这本版本还比较初期,实现api数量比较有限。还有各种各样的问题,但是这表明了这样一个方式,他是说我从下往上把kernel的api重新实现做一个更轻量级的沙箱。因为有些api在业务层面确实是没必要调用的。
还有一种,就是我们刚才讲的Kata,Kata是从上往下,让他变成一个非常轻量级容器的沙箱,所以这是两中方式来构建一个安全的引擎。
怎么做呢?昨天我不知道孙辰星有没有讲,在(英)里面我们跟大家合作,在一个kubernetes集群里面,可以在不同的node节点部署不同的runtime。比如在一个节点用docker daemon,在一个节点用gVisor,另一个节点用Kata,我们给他设不同的label,所以当我们要执行一个build任务的时候,我们就直接告诉他这个任务是下给Kata的node节点的,所以他通过kubernetes的selector机制下到Kata那边。如果我们认为这个任务不需要那么安全级别那么高的,他就会下给docker daemon的节点。他采用kubernetes混部不同runtime方式来实现一个隔离的机制。这就是我们希望为DevOps过程中,根据你业务的情况,提供不同级别runtime。
我最后就讲我们在Kubernetes安全策略做了很多,这是他的一个模型,我有一个LB,进来跑不同的pod里面去访问,在这里面有很多很多安全的点,需要大家在使用DevOps过程中做的。
1、你的运维、研发操作的时候必须首先要用TLS,就是你的那个Master的那个点,必须要Https的。
2、你要有RBAC的授权,就是说对不同的操作者来操作这个集群的时候,给他不同的权限。
3、你可能实现自己的Admission Controller。刚才我们前面讲的日志审计,其实也是用这个来做的,这是你需要使用一些自定义。然后就是在note节点和Master节点之间,一定要使用这个证书。这个证书是这样,在安装集群的时候,会有一个根证书,你会先生成一个根证书,然后再往下签发,比如Master证书等等,所以你要有一套证书的机制,包括安全保存证书的机制来去做,保证Node节点和API节点之间是可授信的访问。
4、Network Policy。是限制pod和pod之间访问的,实现网络上的隔离。
5. Pod Security Policy。你pod节点是以什么权限运行的。

整个kubernetes在DevOps流程的任务执行过程中,我们也要设定这些Policy来保证隔离性和可用性。即便是这样,其实还是有很多问题需要我们去解决。所以这个就是我们在最底层,Kubernetes在DevOps执行任务平台上我们做了很多安全的增强。
这个就是我整个的演讲,我们设计了这样一个通用化的引擎,用容器的方式去运行DevOps,这个过程中我们设置了很多保证他的运行安全,有日志的审计,帐号权限的管理,最终在底层运行平台做了一些加强,给大家提供更安全的保证,这个是我在过程中遇到的整个安全挑战。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注