一、简单理解认识apiserver
1.主要功能
认证
鉴权
准入
· mutating
· validating
· admission
限流
2.概念
![](https://img-blog.csdnimg.cn/direct/61e62baece374db5a582ac4b88726991.png)
apiserver保护etcd,缓存机制,有缓存直接返回,没缓存再去查看etcd,apiserver是担任和其他平台同信并认证
3.访问控制概览
![](https://img-blog.csdnimg.cn/direct/300e290ec12445ccb1ac8c7a81e6959e.png)
在进入之后,先注册api handler,然后会进入到认证(判断用户有没有访问我的权限)和鉴权(判定用户对我服务有没有请求权限),鉴权完之后,如果你对这个属性有其他设置,就进入到准入环节mutaing环节,这个环节要对对象进行变形,如:要设置一个pod,pod没有lables,在mutaing环节,development要控制rs,rs控制pod,rs去创建pod要求名称不能重复,所以要对pod进行随机数。可以简化通过webhook单独将mutating拎出来,自己开发mutaing插件完成资源的处理,将对象处理完成之后返回给下面流程(具体实践:传输数据时是以json格式去传输,在传输时,这个json字符串不去向api server传输,向webhook传输,在webhook里面将字符串进行二次处理,处理完之后,将字符串进行回传,然后让这个字符串继续进行后续动作),在进行突变之后查看名称、内容等是否合法,然后对一些附加值进行校验(数据范围是否合理、字符串类型是否合理,如果有很多集群,可以单拎出来,写一个插件,通过webhook进行统一实现回传),通过校验进入etcd实现落盘。
4.访问控制细节
![](https://img-blog.csdnimg.cn/direct/a3bd550d618b4c90bbc3c27bf7686913.png)
图解:
当代码进入首先执行panic recovery(作用是写一个服务的时候,不会因为一个问题导致你全部进行崩掉),然后进入request-timeout状态(请求的超时时间,会对请求设置一个缓存,设置缓存保存多长时间就是它决定的), 然后进入认证authentication,然后进入audit 审计,然后impersonation 开始做数据传输是http协议,针对header过来的时候加一点信息,集群联邦过来的时候改一点信息,max-in-flight做限流的,多少在路上,上限是多少,是否拒绝,然后是鉴权(某些用户对某些资源进行相应的操作),然后kube-aggregator&crds这里是判断request是不是标准的k8s对象,判断不是的话进入其他处理,是的话,先默认进入decoding
总结:
panic处理,不会因为某个携程panic干掉进程
audit 审计的必要性
impersonation暂时理解为一大堆k8s集群, 开始做数据传输是http协议,header过来的时候加一点信息,集群联邦过来的时候改一点信息
max-in-flight:做限流的,多少在路上,上限是多少,是否拒绝
鉴权
kube-aggregator&crds这里是判断request是不是标准的k8s对象,是的话,判断不是的话
json做反序列化为go的对象
做conversion
internal version
external version
先internel,然后admission,先webhook,没就内置validating
然后内部处理
附加validating 看有没有webhook
准入后进入etcd,然后还有个restlogic是做缓存的
二、apiserver的认证机制(你谁啊你)
1.认证概念
insecure port(认证鉴权都是不走的,直接进行准备控制)
secure port
2.认证插件
![](https://img-blog.csdnimg.cn/direct/7e69db9b3ba34f0a882809580a848631.png)
serviceaccount在进行认证时用的是token
![](https://img-blog.csdnimg.cn/direct/b72ede8a12da401894a5ffc04e472d7f.png)
生产化落地--认证集成
![](https://img-blog.csdnimg.cn/direct/ad3ee287d85242b7b8952593e69a49c6.png)
3.认证方式演示
4.基于webhook的认证服务集成
参考链接https://github.com/kubeguard/guard
集于webhook集成的一段代码
![](https://img-blog.csdnimg.cn/direct/89475581269a407494b9e24d750f0559.png)
做数据传输时,apiversion这段是实际获取的东西,实际获取的东西是从外部的webhook获取的,从webhook读取到认证信息之后,根据用户和身份信息生成一个bearertoken,在注回到原来的信息中,在将其传回本地的api server中。
外部使用webhook使用的代码:
![](https://img-blog.csdnimg.cn/direct/4ef30eb93f294e5caa7ae43ef041589f.png)
![](https://img-blog.csdnimg.cn/direct/5adc3463f8444358a8922e6262aed8cd.png)
![](https://img-blog.csdnimg.cn/direct/785ad84f7aa74cedadeee5d1279b35dd.png)
![](https://img-blog.csdnimg.cn/direct/adfa7a20b7c24209b101b4f197ada072.png)
实际文档(认证规范):
![](https://img-blog.csdnimg.cn/direct/c032f3949c8f45b580e06abb2d9bda98.png)
5.生产过程中遇到的陷阱
很多问题都是发生在23年以前的,社区在高速发展的过程中中可能有逐渐成型的解决的方案
但还是要分享出来拓宽大家的思路
![](https://img-blog.csdnimg.cn/direct/4f566ac864b84312b94ce6ec99a266f9.png)
在k8s中访问接入时,要一堆循环做访问,假如是namespace请求,会向api server请求信息,假如用token做认证(token是有有效期的,一旦过了有效期就要重新颁布,这个颁布也需要时间,一个资源对象在0.1s失效可访问20次,对于集群来说能延就不丢)
三、apiserver的授权机制(你凭啥啊你)
1.授权
如果认证过程中授权失败,会返回一个http的403
![](https://img-blog.csdnimg.cn/direct/74733a86bea6491f9a2255b3fa2acae4.png)
授权方式ABAC和RBAC
ABAC:基于属性的访问控制,不依赖于预定义的角色,根据主体、操作、属性、环境来决定的来访问的,时间、地点、网络这些策略的设置,系统会收集主体资源、环境和属性,主体访问资源,系统会查看属性,根据先定义的策略对这些属性进行评估,如果策略是通过评估允许访问,才会授予访问权限,否则会拒绝访问。做ABAC通常要停服,相较于ABAC,RBAC在集群中更加符合集群中对资源管理的方案
![](https://img-blog.csdnimg.cn/direct/3a7b7d237c254f43820d5fa1fac5bd23.png)
2.RBAC
普遍的RBAC认知
可以新画一个流程图来解释角色,权限,绑定关系
![](https://img-blog.csdnimg.cn/direct/e3bb393f18384d45aa559d5b01545ca7.png)
用户要访问集群中的某个资源,需要设置一定的权限,角色对权限有需求、用户对角色有需求,并进行绑定,这种访问时灵活的,可以随意改变用户底下所绑定的角色,而不用专门为集群设置一个具有权限的角色
![](https://img-blog.csdnimg.cn/direct/01d62eb36017464a9dceeb7a1e6409e4.png)
kubernetes的RBAC
这个得画图解释一下clusterroles和非cluster,比如说可不可以使用rolebinding绑定clusterrole
![](https://img-blog.csdnimg.cn/direct/b635fd31a9a0483eb9f1fe9a7ab08ebd.png)
rolebings:角色绑定,role:设置权限,在某个namespace中生效,clusterRole:设置权限并全局生效
假设是一个主集群,在逻辑上时通过namespace来划分资源和部门,roles就是在其中一个namespace设置一个角色roles(可以对资源进行控制),如果某个用户想在你的namespace访问资源,需要再namespace中设置rolebings,通过rolebings绑定给你认证通过的用户user/group。对所有集群进行管理的人为clusterRole,可以通过clusterbing去绑定一个角色。user/group是从subject中选择的,subject中含盖了user/group,user/group从rolebing发生一个角色和用户的绑定关系,角色中所含的权限有roles所定义。
![](https://img-blog.csdnimg.cn/direct/620cc1e2f7ea403691964a1588e99725.png)
![](https://img-blog.csdnimg.cn/direct/d993dd5126464797ace9f8a6acc13c38.png)
不用写namespace,因为其是全局生效的
![](https://img-blog.csdnimg.cn/direct/04a0017f2eab4d988704cea548add3f0.png)
kind:rolebing绑定对象,在subject中定义和那个用户发生关系,在k8s中必须有这个用户进行绑定,不能和随意一个用户绑定
![](https://img-blog.csdnimg.cn/direct/e74eb880a071448c9ae866787e46022b.png)
![](https://img-blog.csdnimg.cn/direct/10f431e5a8ec42fdb77247f43eed0058.png)
3.账户/组的管理
在角色绑定时可以是一个user、group、serviceaccount
![](https://img-blog.csdnimg.cn/direct/9f55cbff35194894b36185aa93ca5b9f.png)
![](https://img-blog.csdnimg.cn/direct/97c39ae4b2ed46f1b33cf92fc018c876.png)
4.规划系统角色
![](https://img-blog.csdnimg.cn/direct/76cb4e6bcfd24164b7c17738da5cd089.png)
管理员权限得有多大,比如能不能看用户的安全相关的信息,
租户的配置,如强隔离场景,只关心自己的ns,
或者弱隔离,相信每个用户,可以read all,只保证自己的业务不被破坏
当你入职的时候应该能做哪些操作
权限是不是越高越好
这里做授权的演示视频
大家一定要对生产系统怀有敬畏,通过RABC给其一个强隔离
最好更改代码,将源文件进行注释,你在重新写
5.自动化实现方案
apiserver能收到user info信息,提出来后数据处理存一个变量
![](https://img-blog.csdnimg.cn/direct/bbb940fd2e004987bdb3f88a7550696b.png)
![](https://img-blog.csdnimg.cn/direct/89114a4381c4456bb0091399cfae3fbd.png)
![](https://img-blog.csdnimg.cn/direct/af3ca6d5fa9e43ebbcf7362289653462.png)
6.注意避坑
![](https://img-blog.csdnimg.cn/direct/f5625e53b0c94fa2b8cc3fac07d7dd0a.png)
![](https://img-blog.csdnimg.cn/direct/3ef278dc2d284a889ca69c75cd50b52a.png)
基于k8s的扩展功能,当你定义一个新的对象进去,新的对象和传统对象并不是同一类资源,之前设置的资源很可能忘记对这个资源的操作
四、apiserver的准入控制(你行不行啊你)
1.使用场景
对ns做资源配额
限制了qos,没限制besteffort
怎么做自动化
resourcequota的实验
![](https://img-blog.csdnimg.cn/direct/850957d35d234811aeb6eb27cf757d3a.png)
resourcequota:可以限制创建的configmap,还可以限制创建多少个pod、service、ingress、service vip。
![](https://img-blog.csdnimg.cn/direct/cfe25a991cbb431bb47ac9bb8186b48c.png)
进行资源的限制,怎么做到自动化?
在创建 RBAC的时候,在创建一个resourcequota资源对象,这个对象对当前集群所用的资源进行限制,但是创建的时候,你需要把这个资源对象从你的RBAC中排除出去,以免租户可以控制这个对象
![](https://img-blog.csdnimg.cn/direct/6d73b46fdb074e89a30a0c11bfddd541.png)
2.准入控制的插件
建立pod的时候可以通过准入插件扫一下镜像是不是安全扫描通过了
k exec -it -n kube-system kube-apiserver-master1
![](https://img-blog.csdnimg.cn/direct/4139cb00132744ee85dff4e09f3f8a38.png)
always:每次遇到镜像拉取都是从远端拉取
ifNotPresent:如果找不到镜像,才进行拉取
Nerver:只用本地的镜像,从不向远端拉取
上面选项实际上是将iamgepullpolicy置为always
![](https://img-blog.csdnimg.cn/direct/1f4eb66bdf6747ffa419f9e5ba2002de.png)
![](https://img-blog.csdnimg.cn/direct/7379d287638a45e996c32d6e2c6c599b.png)
3.webhook准入插件自研
现在的突变已经很简单了
如果要开webhook必须要开https
注意这里的caBundle是要填写的,就是证书做一次base64加密
![](https://img-blog.csdnimg.cn/direct/2a49804f848a447d9e1acc4e751a2bc8.png)
流程:
api server开启了要做webhook的变形插件,插件会向远端服务器去做访问,查看你的adission是啥,有多种行为,查看这种行为对你的服务进行哪种变更,如果是变更执行变更操作,是更新就执行更新操作。如果要做变型要开启变型插件,非变型对象validatingwebhookconfigration就是做校验的
![](https://img-blog.csdnimg.cn/direct/47102b57831f489c845019af2cb1da78.png)
远端如果配置好webhook,这里只需要配置apiversion,如果设置好,ca认证记的放好证书,URl是必写的
![](https://img-blog.csdnimg.cn/direct/83048547c6a9423da94d70941d142efe.png)
五、apiserver的限流方法
1.常用的传统速率的限制算法
监听时间循环的同时要计算其流量,来确认它的流量是多少,当流量超过一定限制之后,访问给其拒绝,知道循环机制监听到下一个窗口,再去看如何处理这些访问请求
![](https://img-blog.csdnimg.cn/direct/06260659ad5449a1b40a3d108a161616.png)
![](https://img-blog.csdnimg.cn/direct/0eb23252fec24e169b1aeb659e86cac8.png)
内存挤压直接om,这种方式有弊端,因为颗粒度太粗,会经常发生局部挤压,
算法:
假设一个网络接口使用计数器固定窗口算法进行流量控制,窗口大小设置为total个数据包,窗口时间设置为win_lenth秒。
窗口为1s
如果在第一秒内发送了pkg1个数据包,第二秒内发送了pkg2个数据包,第三秒内发送了pkg3个数据包...一共5秒,请计算每个时间窗口结束时的流量是否超出限制,超出延时顺延2秒,在过则丢弃,如果超出请输出第n秒有延时,实际处理时间需要多久。
使用shell实现该计算过程
要求:
输入:
第一行读入100 1
第二行读入 90 170 80 120 60
输出:
第x x x秒有延时,总耗时x秒处理完成
总结:
判断第ns有延时,因为其有超时2s的需求,所以对每个窗口来说,需要用三个窗口来储存,储存数值分别是第一窗口的延时、第二个窗口的延时、本窗口的延时,只要写三个窗口进行判断,就知道每个窗口期处理数据包是个怎么样的分布状态,然后关于总耗时x秒完成(这个只和前两个窗口有关,只需要判断前两个窗口有没有发生过包处理,就可以判断总耗时几秒完成)
![](https://img-blog.csdnimg.cn/direct/0aab590eac14408b87c62f6ae29ffbbd.png)
此方法是为了解决颗粒度过粗的问题,每过1s就往后移动一个窗口,这样颗粒度就从1min变成1s,
这种情况下,如果qbs保证是1w,第1个窗口过了一定的服务保证,过了一定包的时候,那么在这个窗口期内就不会增添数据了,相较于固定窗口,颗粒度是细了,但是并没有解决流量挤压这个问题,将时间无限放大来看,这个窗口期是非常大的
![](https://img-blog.csdnimg.cn/direct/a44b552c08fb4d809d3ccbcbdb63a795.png)
![](https://img-blog.csdnimg.cn/direct/2a5419277071462f8684f1f69f0e5974.png)
这个漏斗算法有延时,会积压请求,很容易丢请求,就是再急也得等等,而令牌算法解决了这种弊端
![](https://img-blog.csdnimg.cn/direct/cb76a8fac50949a2a0de8d7c544fa8e7.png)
有弊端:多租户请求,租户一直发请求,一个用户直接把令牌都拿走,其他用户就拿不了令牌
2.apiserver的限流机制
![](https://img-blog.csdnimg.cn/direct/a172e475b9c949f19686d5324e5e9f1c.png)
同样时间内,给的并发数过少咋整,请求遭拒,请求受缓,延时比较长,不利于服务质量保证。
请求过大,并发数太大容易把api server打崩
3.传统限流方法的局限性
![](https://img-blog.csdnimg.cn/direct/e54a193ffbb640468e4b27ec6a249be8.png)
4.API Priority and Fairness(APF算法)
![](https://img-blog.csdnimg.cn/direct/a02e105e6011485983273bb8d666c17c.png)
每张表都有优先级,从0到n,越靠近0的优先级变大,每张表单对应一个流,流里面可以自己设置有多少个管道,也可以设置每个管道中可以缓存多少东西,所以当一个请求来的时候,先去匹配表,然后根据标的规则查看匹配那个流,然后再流里面按照优先级规则去匹配那个管道资源,每一个请求都占对应的一个管道,按照管道的空闲程度做处理,这就是api 算法
针对恶意用户,需要设置多个管道
![](https://img-blog.csdnimg.cn/direct/cf0cb89eb82e42418faab619618899b0.png)
![](https://img-blog.csdnimg.cn/direct/969d3801bc054990a3cd4f5500c31da9.png)
![](https://img-blog.csdnimg.cn/direct/461c66b04da2496f93157d0f179c72c6.png)
apf算法的概念,整个的工作机制
每个优先级维护自己的并发限制
限制了问题的影响,不会因为一个打满饿死了其他队列的
![](https://img-blog.csdnimg.cn/direct/d075fb51570e4d00ac012580757f5e71.png)
![](https://img-blog.csdnimg.cn/direct/499057a82f3c41d29484ef21a1b163a0.png)
![](https://img-blog.csdnimg.cn/direct/e223d0ce333e4d9482bfca3769b58873.png)
![](https://img-blog.csdnimg.cn/direct/e49c7e21066b4237a6ea1b706ac99da9.png)
![](https://img-blog.csdnimg.cn/direct/5d99be523c6b41daadca2fd8f7f5deb4.png)
思考,流量来自于哪里,我们要控制的是对谁的流量
保护内部之间的流量,和控制web进来的流量。
总结:
①curl一些其他的网络手段访问你的api server资源
②集群内部的资源如果访问失败,它会对你的api server发生reset服务,如果这个服务没做指数级的递增,也会发生攻击现象
③攻击api server时,顺带把etcd击穿,看似攻击api server,实际在攻击etcd。如:注入一些非常大的对象,实质用k8s内部某些流量的特性来攻击kublets,不论是直接攻击api server,还是通过k8s特性攻击,所以控制流量首先来自外来租户请求、其次内部的资源(具有控制器可以循环访问的这类资源)
5.限流必须掌握的资源对象(FlowSchema和PriorityLevelConfiguration)
默认配置1:
默认配置2:
![](https://img-blog.csdnimg.cn/direct/336d5355387641aabee90fc23660a6a1.png)
![](https://img-blog.csdnimg.cn/direct/9b1125277e7d4c949c5327923581fea6.png)
![](https://img-blog.csdnimg.cn/direct/db320cd9d3ac4dc1a282ecea5bf251c4.png)
如果都能匹配到match,就会看优先级,谁比较高,如:400、500,先走优先级高度flowschema,去看其绑定的prioritylevelconfigration,然后进行读取,可以看到queues(管道)、handsize(队列)
![](https://img-blog.csdnimg.cn/direct/bc719cbc932942f8bf3f4e87f73d415c.png)
![](https://img-blog.csdnimg.cn/direct/75f81d676363444c901e2c9b4aa8c932.png)
APF的常用的控制命令:
![](https://img-blog.csdnimg.cn/direct/df565ac7b78e491caaeae94ef7e7b2f9.png)
APF的工作细节:
![](https://img-blog.csdnimg.cn/direct/e63d9be4aad4409abc36b6ceaf64a4a2.png)
六、高可用apiserver
1.apiserver启动参数示例
rest server(无状态):显著特点,做高可用部署几个都没问题,做冗余部署
![](https://img-blog.csdnimg.cn/direct/54bc577ae0244e06875b3428875e3ca6.png)
2.构建高可用的多副本apiserver
![](https://img-blog.csdnimg.cn/direct/b5a8e8d2ddd7422991648f1873661887.png)
![](https://img-blog.csdnimg.cn/direct/b97c4bf52a4f46249b608d0f5c68768b.png)
![](https://img-blog.csdnimg.cn/direct/3eb567af0a96406d8943eae7c05ab64f.png)
速率控制,一个是控制总的读写数量,另一个是控制写请求的数量,因为写请求数量比读的数量是消耗多的,在进行总的请求之后,可以使用API分片算法,对流量进行一个细化的管理,通过这两种手段,服务器是有一定健壮性
![](https://img-blog.csdnimg.cn/direct/0fd94aa0d94f4cb288df7699977a2bfb.png)
![](https://img-blog.csdnimg.cn/direct/e518e1f36e2c42dc8a26c6ba8b24d50e.png)
空间换时间的一种手段
![](https://img-blog.csdnimg.cn/direct/31accf7d55f241419559676d43d29c6d.png)
![](https://img-blog.csdnimg.cn/direct/073cd42224b04629ac35a184a5a1a75b.png)
3.流量入站需要考虑的事情
思考如何访问apiserver
![](https://img-blog.csdnimg.cn/direct/d59fbaf97d7d44179e9ae30a509a0614.png)
![](https://img-blog.csdnimg.cn/direct/284642b63aeb4d0c865e2de1ecf6f676.png)
认证
![](https://img-blog.csdnimg.cn/direct/4bbae89edb55440789ba55f3c714e7b4.png)
![](https://img-blog.csdnimg.cn/direct/f636cb79882d4495a0cf9ec11febfb3f.png)
4.构建生产化集群要考虑的事情
规划系统角色user 、systemAccount
![](https://img-blog.csdnimg.cn/direct/4e9f49c22b884a6ba6f18cdfbc8cae1d.png)
注意把敏感信息进行剔除
![](https://img-blog.csdnimg.cn/direct/5d719f3be3bb497f9abde6af417d1f1c.png)
通过本地集群认证,通过webhook认证手段实现自动化
![](https://img-blog.csdnimg.cn/direct/be1a4edb4f534db1b60b68e29251d937.png)
![](https://img-blog.csdnimg.cn/direct/c90ab802364242c1aa6116efcc60198d.png)