好的 大家好 现在差不多时间到了我们可以正式开始今天我们的这个session是主要来看一看Cavernal Deployground它是一个online的测试的平台可以让你不用把Cavernal Deploying到你的cluster里或者是进行任何的installation的动作来让你无缝的尝试使用Cavernal然后我们是在前天release了最新的1.11 Beta3的version然后我们的小伙伴也很给力然后把它integrate到这个playground所以你现在用到的playground就是最新的Cavernal的版本好 那我们在我们今天的这个剧情内容开始之前我先简单介绍一下我自己我叫赵舒婷 大家可以叫我舒婷就好我是Cavernal的co-creator and maintainer of Cavernal现在在Nemata担任一名stuff engineerNemata是createCavernal的公司在2020年左右的时候把Cavernal这个项目捐赠给了CNCF它现在是一个CNCF incubating project这是我们今天的真的在具体进行实际操作之前我会带大家先了解一下什么是CavernalCavernal到底是干什么的它可以帮助你解决一些什么样的use case放在一些什么样的场景里可以帮助你的application进行比如说安全的验证或者是一些resource generation automation之类的动作所以今天所有的这些应用场景我们都会在playground里设计到我有一个建议如果大家感兴趣的话我们这个是一个online tour如果大家希望在手上自己实动测试一下的话是非常欢迎的我把这个slide已经传到今天的agenda上了它每一个demo都会有链接你可以去点开链接之后可以在自己的本地的环境去跑测试好 那我们首先来了解一下什么是policy为什么我们需要policy也就是我们所说的策略在cubernetes里根据它的一份CNCF的调查它显示96%的企业都正在并且即将evaluating也就是评估cubernetes然后在2026年大概拥有80%的这些software的企业都会获多获少的adopt来cubernetes的平台来进行对他们的产品进行部署那么在这个表格里大家可以看到一个cluster的misconfiguration大概平均的一个数值在300左右也就是说对于你因为cubernetes是用yaml来declare所有的你的这些配置那么它就非常容易作为一个人工的事情它就非常容易进行一些misconfiguration那么这个时候你就可以利用policy来对你的这些配置进行一些验证或者是设置一些default的一些value这个时候cubernetes可以作为你的cubernetesnative的策略引擎来对它做validation那么在你进入production之前你是非常希望把你的application的这些配置进行一个pre-deploy的这个测试来看看你到底比如说对于security的要求它满足了多少 完成了多少还有什么是你需要帮助它的那么你就可以用cubernetes提供的策略引擎包括OpacateKeeper 包括Cavernal来对它进行做一个分析这样会对你日后把你的产品部署到你的production的环境会帮你节省一些cost所以这个策略在cubernetes里它就是一个准则 就是一个标准相当是一个合同在不同的team之间比如说我们有developers我们有security team我们有operation team那么所有的team都share你同一个cluster的话你就需要对它们的workload它们部署的workload来进行一些验证那么策略在这里就提到了这样一个guardrail来帮助我们prevent一些security hole或者是刚刚我说的想设置一些default参数之类的那么下面就到了Cavernal它作为cubernetes原生的一个策略引擎它就是design for Kubernetes那么这里我们你可以看到Cavernal是一个非常蓬勃发展的社区在截止目前我们拥有超过330名的contributor在slack channel上我们拥有超过2300名的slack member截止1.10的cavernal版本我们有将近300个cavernal sample policy也就是说你在里面极有可能99%99%的情况你都会找到与你的应用场景相应的或者是有关联的这些sample policy然后你可以把它用作一个reference来进行拓展或者是自定义去应用到你的应用场景里那么刚刚说了这么多cavernal到底可以干什么相信今天来的小伙伴或多或少应该已经听过或者是有一些相应的应用的需求所以cavernal它身为一个Cavernities的原生应用引擎它使用的是Cavernities CRD来进行这个策略的定义也就是custom resource definition那么你看到cavernal policy的话你会觉得它非常熟悉因为它跟Cavernitiesnative resource的所有的定义包括metadata,API version和kind都是沿用了这个YAML的declareation那么在它cavernal的另一个功能也就是帮你生成Policy Report这个报告的功能它也是应用了Cavernities CRD我们是从cavernities的Policy Working Group衍生的一个CRD那么它运用到了cavernal以及Falco和另外的一些CNCF的这个项目中来对你的遗有的cluster或者是即将进入deploy到你的cluster上的应用做一个报告的生成这里你可以对它的security进行验证也可以对它的image的镜像进行签名和attactation的验证除了这个镜像的验证还有安全的验证cavernal也可以作为一个admission controller就是准入控制器当然它可以做一些mutation的动作除此之外cavernal的另一大亮点就是它有generate的功能具体谈到generate我说一个经典的应用场景大家就很好理解比如说我们在create一个name space的时候这个时候我们可能需要对这个name space进行一些resource的配置进行一些permission的限制那么这个时候cavernal的generate ability就可以帮助你自动化生成创建这些resource比如说row 或者是row bindingresource code as limit range这些cubernetes的resource可以在name space创建的时候做一个automation当然cavernal的generate也可以generate任何的custom resource也就是我们说的CR只要它是cubernetes已知的 已经被注册过的resourcecavernal都可以对它进行做一个创建的动作接下来一点就是我说的它cavernal support所有的cubernetes resourceincluding custom resource然后另外一个cavernal的亮点因为它是cubernetes native它所有的patterns所有的policy declaration都是reuse the cubernetes的已有的一些object比如说labels比如说annotations这样你在比如说在选择你这个policy要apply the resource的时候你就可以用这些native的object比如说annotation match或者是label selector来对它进行一个resource filter当然cavernal作为native policy engine它也是理解这个pod以及pod workload假如说你有一个policy是定义在这个pod上的那么cavernal可以把你的policy自动转换成covering你的所有的pod controllerspot core, state for setdeployment etc etc所以这个cavernal对cubernetes的理解还是一个非常原生的那么接下来我们来看一看这个一些比较热门的cavernal的应用场景首先cavernal可以分为两个部分第一个就是跑在cluster里的一个准入控制器emission controller以及比如说background scanning controllerreport生成的controller它就是跑在cluster里的一些控制器那么另一种使用cavernal的场景就是在你的cacd pipeline或者是你的local environment你可以下载cavernal的coi它是一个standalone的工具可以帮助你来verify一些static resource比如说你本地的一些压谋配置或者是你的远程的github repository里面的一些配置这个是不需要你有cubernetes cluster that running的那么另外一种就是我们今天会提到的playground它更多的是让你进行一个及时的测试比如说我今天想到我需要这样一个功能你就可以在不需要安装任何cavernal的工具的情况下来测试你的policy然后把它变成你的一个default built-in的policy好 那么我们来了解一下经典的应用场景比如说pod security相信大家在部署应用的时候或多或少都会用到一些pod security的配置covernities以前的版本是用pod security policy来控制scan这个pod security那么后来它摒弃了psp然后发展到pss也就是pod security standards它会将来有16个standards来define我们这个pod security到底要怎么样配置那么cavernal就可以不管是psp或者是pss包括cubernetes自己提供的admission controllerpod security admission controller它都是用来验证这个pod security的配置的那么cavernal是不管你是怎么样配置或如何配置它都是可以就是通过这个你给我这个pod manifest它都是可以通过进行这个validation然后来给你做出一个相应的结果以及反应还有一个经典的应用场景就是我刚刚提到了这个automation或者是generation的这个功能比如说你在create name space的时候你希望创建一个multi-tendency或者是这样virtual cluster的一个环境那么这个generation就可以帮助你create一些our back resource比如说row binding limit range network policy以及等等一系列的resource然后这样就可以在一个name space生成的时候对你的不同的team比如说devs或者是security team对它们有一个isolation那么当然在finups里也有一些应用刚刚我提到了这个resource quota或者是pod request and limits这个都是我们可能比较痛苦的因为它一旦你的pod运用过多的resource的话它的cost自然而然就会上去所以对它进行pod request and limit一个限制可以帮助你节约一些成本当然还有一些其他的应用场景我们在cabernal website里都有提到以及跟一些比如说get ops tool的一些integration, flux cd, argo cd或者是在不同的club provider上AWS, azure上来进行cabernal的安装都是有一支的经验以及现有的流程的所以它都是无缝连接的好 我们了解了cabernal的可以干什么现在我们来简单的介绍一下它到底是怎么干这件事情的它作为cabernalities的准入控制器它其实是利用了cabernalities的viphook这一项配置因为viphook它提供了mutation和validation的功能也就是在你给我送的一个request进来的时候我可以对你,比如说设置一些默认的参数在设置完了之后我会对你的pod security或者是你的image做一些镜像的签名的验证这个都是我们的validation viphook做的东西那么在准入控制之外我们还有background scanner也就是对你的eo的existing resource进行一个scan比如说我现在deploy了一系列的pod security policy我希望我所有的部署在这个cluster上的应用都是默认是安全的它是符合pod security的要求的我们就可以用background scanning来生成一个report来告诉你OK,我们现在有这些workload是安全的那么另一些workload可能会有一些validation需要相应的team做出一些不同的调整另外一个就是刚刚提到的cli对你的static resource进行一个evalidation或者是也可以用到generation所以它除了准入控制器之外它还有report controller还有generation controller然后还有在1.11里面我们新加了validating emission policy的一个支持所以在validation controller里也会有vap的这一项integration由下角这里提到的policy exception就是有时候你比如说对一个name space经典的一个问题又来了就是cooperative the pod security emission它的intrade solution是只能对你一个name space里的所有workload进行一个enforcement它没有办法让你对其中的一个比如说你的一个name space现在在deployed 3个workload它没有办法对于比如说workload 8进行一个exemption就是我要豁免这个workload我可能有一些特殊的需求我不希望pod security被scanned out但是psa是没有这一项功能的但在covernal里policy exception你还有别的办法可以来豁免这个policy application但是policy exception是可以 either 拓展到你的name space的一个某一个workflow或者是enforced你的整个classified的一个豁免的所以它这个是非常灵活它可以根据你的pod selectorlabel selector来进行配置的这样你就可以得到一个豁免在你80%的workload需要pod security保护的情况下会有20%或者是更少的workload需要进行skip的一个动作那么下面我们这个看到的是一个covernal policy的组成它这个在一个policy里面我们可以define一个到多个root也就是这个准则那么这个root我们可以define你要match the resource是什么类型的比如说pod workloadstaffoset或者是cer一些custom resource都是可以的这里我右边列的这些东西都是可以用在the match这个blocklet比如说label annotationname space labels也就是name space selector它甚至可以帮你来filter掉OK 我这个request到底是谁发送给我的比如说是clusterand then发送给我的那我就可以by default我就信任它我可以豁免掉这一条它如果是一个developer发送给我的那么我就要对它进行一些验证所以在这个user group和service account里都是可以对于who sends the request做一个filter那么下面最下面这个validate mutategenerate to verify image如是这个covernal policy的本体也就是你想要做安全验证想要做补丁想要做一些resource生成或者是镜像image的验证都是可以define在这个入的本体里的好 这就是一个covernal policy的实力你看到它是跟cubernetes resource其实是一样的我们有API version然后这里的kind是cluster policy也就是我是一个cluster wide resource跟我们的clusterrobining cluster row是一样的那么metadata你给它一个名字这就是它的metadata的部分你define kind和API group那么下面就到了spec的环节这里的spec就跟podspec是一样的是来define这个cluster policy的一些特制的比如说你看到第一条validation failure action这个就是来控制比如说我发了一个podcreation的请求那么我希望covernal来block我这个pod如果有resource violation的话还是我希望covernal就是soft control来允许这个pod的创建但是我可以相应地生成一个policy report对后续有一个历史的可以查找的记录是通过这个validation failure action define当然还有其他的一些配置在policy spec里你可以做cubcata explain来具体 inspect不同的attributes那么下面就到了这个root definition的环节你看我们有一个root name这个vidant在一个policy里这个每一个root的名字必须是unit必须是unit的但在这个match里呢我们define这个这个root是match到这个pod resource刚刚我也提到了所有covernal的pod root都会被自动转化为pod controller也就是说我们实际的应用场景很少有deploy standalone pod的情况一般都是把它封装到比如说deployment statement根据你的special storagestorage的这个请求封装到不同的workload里但是在covernal里你是不需要在这个const里define所有的workload的它会帮你自动控制当然这个也是可以page的你可以把它关掉如果你不希望这个policy或这个root可以apply到那些workload的话所以这里是一个单一的policy我就是apply到一个barepod那么validate这个本体呢就是说我要对pod的request进行一些验证那么很清楚啊这个validate一个message就是我会将来如果有一些report生成的话这个message就会embat到这个report里那么pattern就非常容易理解我的metadata labels我希望这个pod有team这个label如果没有这个team的话我前面definevalidation failure action as enforced所以当我生成这个pod的时候它就我就希望covernal帮我拒绝掉这个pod创建的请求好这个就是我们讲了这么长时间就是covernal它怎么工作它到底是什么为什么需要policy那么下面我觉得是今天比较有趣的环节这个demo如果大家有兴趣可以拿出你的电脑登录下面这个下方这个网站playgroundcovernal.io slash nextnext是我们最新的beta版本这样你就可以对covernal最新的版本进行一个测试我这里的这个截屏上是1.10我们现在已经有1.11了好那我们就看一个刚刚讲到的validate这个policy跳到另一个playground的环节希望这个大小对大家是ok的如果不ok跟我说我把它调大这个就是刚刚我们看到的这个policy它是apply到pod上我希望verify这个pod有这个team label那么右边呢你可以看到我这里是一个pod definition这个label呢我只defineroundenginex没有这个team相应的label那么刚刚我提到了这个就是我希望covernal来拒绝掉我这个pod的请求如果我这里点击start你就可以看到我有一个fail的结果那么如果你展开这个刚刚我们的message就会显现在这里说ok你的team label is required你必须把它加上之后你这个pod才会被允许创建允许生成好的就是这是一个非常简单但非常经典的一个validation的应用接下来我们来看一个mutation也就是比如说我要给我的incoming pod patch一个label上去应该怎么办呢那这里我还是同样的cluster policyapply to pod但是呢我的入本体是一个mutation policy这里我做的是一个strategic merge patch当然你可以做json patch它有不同的definition都可以support很简单我在metadata上想打一个label这个label的key是team然后你看到这个value就非常有趣了这个是request.object.metadata.namespace也就是说我希望我这个team的validationsorry这个label的value呢是这个pod自己的namespace这里我运用到了一个variable这个是cavernal支持的jamespass variable所以我希望这个pod namespace被打到这个label上那么右边就可以看到我这里有一个pod然后我的namespace是dev你可以看到它是没有任何label的那假如说我现在apply这个policy之后我期望的是它会把这个labelteam打到我的pod上并且它的value是我的dev的namespace所以如果你click on this start它就会有一个ok 我的policy已经apply了如果你点击这个标签呢它就会给你生成patch以后的resource你可以看到这里给你非常贴心的列出了这个前后的对比我这个teamlabel就已经被patch到这个pod上了也就是说你在cubernetes里deploy了这个policy之后当你每当你申请送一个pod creation的请求的时候它都会帮你把这个label打上当然你可以做一些filter不一定是所有的label你都需要你可以通过namespace或者是其他的selector来对这个pod做一个filteringok 那我们写下来就是这个mutation的sorry generation的环节就我刚刚说的比如说你想建立一个virtual cluster在你的namespace创建的时候那这个时候呢我这里的一个案例就是我做的是这里的match on namespace就是说我的namespace有任何的活动的时候我都希望这个policy被apply到我的namespace上那我们来读一下这个generate这个policy到底是在干什么这taskos cavernal我需要创建一个resource这个resource的kind就是cubernetes default的network policy那这里我给它定义了一个名字然后namespace那你可以看到我用的还是这个jamespass variable我是refer到这个encomment request也就是namespace的name这个时候我希望这个network policy被创建到我刚刚create的这个namespace里面所以这里的variable指向的是namespace自己的名字本身那么在这个network policy的具体内容是什么呢我define到这个data block下面从spec cache它就是一个cubernetesnetwork policy的definition这里有podselector我希望它select所有pod在这个namespace里然后type是 ingress和agressok 这里就是这个generate policy如果大家有什么一问可以随时制止我然后进行提问然后右边我这里就做了一个简单的namespace的一个definition我希望create一个叫staging的namespace那么作为这个policy application的结果呢我会希望最终它会在这个staging namespace里帮我create一个network policy同样的点击这个运行啊它会出来这个结果告诉你ok 这个policy也pass了然后你通过这个details如果你click on就是打开它的话你可以看到这里是cavernal创建的resource它是cubernetes network policy然后这些label是cavernal自定义的label后面这些spec是我们刚刚定义在policy里的spec也就是说任何你想要定义的speccavernal都可以帮你生成在这里插一句cavernal的这个generation是可以帮你进行synchronized假如说你的policy的spec有任何的变动那么你都是可以选择对它进行synchronized所以每当有变动的时候cavernal都会自动的把这个改动sync到你的downstream network policy就是刚刚generated好的这个network policy里所以这项功能也是对automation进行了一些改进除了generation之外另外一个就是clone的一个应用场景比如说你现在已经有了一个secret在另外一个name space里然后你对所有新的cret name space你希望把secret去复制过去因为你不想可能会有一些credential你希望某些name space共享那么我们都知道name space是一个virtual isolation你不太容易通过访问从一个name space到另外一个name space这个时候你就可以copy你已有的一些secret resource或者是其他的resource包括CR然后到你的新的name space这是generation的另外一个应用也就是clone那么同样的你对这个source也就是这个源头的secret进行改动的时候CoverNull同样也可以帮你把这个改动synchronized到你所有的downstream也就是被复制的这些secretly好 那我们接下来看CoverNull的另外一个大的功能也就是对于进向签名的验证当然CoverNull也可以验证attestation这里我的这个例子只是验证了签名同样的 我们一起来读一下这个policy这里你看到我的matching kinds同样是pod然后在verify image的这个attribute之下我会有一个image reference这里就是说我对这个pod所有的pod如果定义了或者是如果运行了这个image的话我都希望对它进行一个签名的验证所以这个image我就是对 针对今天的demo做的一个testimagetestverify image然后我们看到后面的这个信号就是worldcardmatch它可以对所有的image tags所有的image digest进行一个验证当然这里你也可以指验证比如说如果你想验证v1或者是v2你可以把它变成一个specific tag那么这个policy就只会apply到这一条image上但是我希望是一个general的验证所以这里我打的是start也就是帮我做一个valker match那么接下来呢这个type what defines notary也就是说我在对这个镜像进行签名的时候我使用的是notation这个工具cavernal还支持cosign它是两个两大cubernetes提供的这个原生的镜像的签名的工具那么根据notary的特性我这里attached了我在signing的时候就是我在签名的时候用到的certificate用到的证书那么cavernal将会用这个对于对你incoming image做一个签名的验证好 那你看到右边我有两个pod的definition一个是badpod也就是说我run了这个image但是tag是unsigned也就是说这个image我在build之外呢没有对它进行一个notation签名的动作然后下面这个pod是goodpod也就是我在生成完这个image之后用了这个certificate然后对它进行签名那同样我来跑一下这个policy你可以看到cavernal就它会生成两条结果第一条是对这个badpod它会有一个fail的结果也就是说如果你把这个鼠标放到这里它会说ok 你的image没有这个signature所以根据你的这一条policy是显示你需要的那么我们会blocking这个pod creation那下面这个pass就很容易理解了就是说你的image满足我们的需求所有的creation都是被允许的好 那我们就提到了刚刚的policy exception这里我们有goodpod 有badpod那假如说我想对这个badpod做一些货面在比如说你的name space这个scope或者是整个classified这个scope对某一些pod 或者是某一些image做货面怎么办呢这里我用的policy是刚刚一样的然后pod 这里只有badpod也就是刚刚用的那个onsignpod在advanced这里会找到policy exception的一个配置的选项那这里policy exception也是cubernetes的一个crd属于cavernal在manage这里我对它定义了说ok我的货面是针对这个policywith thisname然后这个rule with这个名字需要进行一些货面那这个pod我希望是对name space和name有一些要求所以这个货面是可以针对了你的policy的rule name和你的resource也就是pod的name或者是name space进行选择然后这里我如果再create thispod的话它就是理应应该上市被允许的你就看到我这里有一个skip的status就说明我这条policy被货面或者是skip掉了并没有apply在你的pod上那么这个时候你的pod creation就默认就是会成功的好 那我们今天最后一个demo就是我刚刚说的一点11最新的这个integration是validating admission policy的一个功能这里用到的是sell expression我不知道大家熟不熟悉在比如说对进行你的pod的进行或者你的resource进行validation的时候我们刚刚看到Kirvano都用的是这个yaml的这个形式来进行验证的当然你就会质疑它不够灵活所以后面我们又引进了jamespass operator以及jamespass the variable来帮你来帮助大家完成一些更复杂的情况那么这里的sell expression就提供了这样的一种可能性它对于你更加复杂的一些定义会有一个更好的支持吧 这样说你可以看到这个has object它的这个has operator就是说明OK 我希望我的这个object会有这个volumes并且这个volumes呢它不能是hostpass类型的因为我前面有一个非就是说不希望它是hostpass这个policy是apply到deployment上的那么你看到右边相应的我们就有一个deployment我们下滑到看到它的volume和volume months这里的volume的type就是hostpass那么刚刚好我们这个policy定义的就是我不允许有这个hostpass所以如果你apply这个policy你会发现它是一个fail的结果也就是说这个是不被允许的那假如说我把这个comment out之后呢你这个deployment相当于没有任何volume的定义那么我期待的就是这个整个policy就没有被apply到这个resource上所以它就是一个pass的结果OK 那大概这个就是我们今天所有的demo如果大家有疑问的话可以加入我们的community我们有每周的会议啊然后也有slack channel最后如果大家有问题的话欢迎发问或者是加入这个微信的群里面我们可以私下来进行交流好 谢谢大家我这里还有一些您说谢谢你的演讲啊就是我有一个问题就是你刚刚介绍的那个复制资源到另外一个Namespace这个同步的功能你说Kiwano做了一些自动化的工作对比如说我可以理解为我原Namespace下面的资源会的变动会修改到目的的Namespace那我如果单独对目的的Namespace资源做了修改之后它会被同步回来吗这是一个很好的问题刚刚漏掉了这一点如果你开启了这个synchronized的功能的话在你downstream就是目的的resource进行修改的话Kiwano是会revert这个change的也就是说他会再scan一遍你的original resource然后再把他所有的改动抹掉但是有一种场景就是比如说在正常的运萎过程当中比如说我对某一个Namespace进行这个超输挺的时候那我可能就要修改这个Ingress或者Egress那我在这个时候去如何做这个exception对刚刚就说到了如果你启用了synchronized这个功能Kiwano是会帮你revert掉但是你有一个option是不要启用它就是我没有sync的这个功能也就是你复制好了之后它就在那里你如果想改你就改它就不会帮你revert掉所有的改动好的 谢谢好 谢谢你的问题不好意思 我也有一个问题好 你们问关于那个我们知道Kiwano在Kubosystem下面默认是被一个落掉它的Policy的注入了 对吧不好意思 我听不太清楚那个话筒能拿近一点吗就是Kiwano在Kubosystem的Namespace下面它默认是一个落掉那个注入的功能对 在Kubosystem的Namespace下面默认是被ignored掉了所以如果说我要对Kubosystem的Namespace做修改的话是有什么建议对Kiwano有一个resource filter它是default会把这个KubosystemNamespace和Kiwano的Namespace同时都ignored掉你只是要把它去掉就好了在这个resource filter上所以这个移除是建议的吗当然不了因为Kubosystem里面全都是你的management的一些平台的controller假如说你的cluster会有一些failure的情况的话作为admission controller如果它没有再响应那么你的这些API server恢复可能有问题但是我们也有相应的这个配置就是把你的webhook的failure action改成ignored也就是说当你的admission controller没有response的时候它还是可以通过所有的这些request的请求不会帮你block掉也就是它的Kubosystem Namespace里的所有东西都还是可以恢复的好了 谢谢好 谢谢我这里有一些Kubosystem sticker就是贴纸如果大家需要的话可以来找我拿好 那我们今天大概就结束了有问题就线上来找我就可以了谢谢大家