K8是AMD第8代处理器系列的通称,也是从32位的x86平台与64位的AMD64平台的过渡时代。
在K8系列的变化中,较值得注意的地方是其整合内存控制器与x86-64指令。
K8架构原先分为Socket754、Socket939和Socket940接口,Socket754主要面向桌面中低端用户,Socket939面向桌面中高端主流用户,而Socket940为早期服务器Opteron专用(后来服务器也改用Socket939接口)。新K8处理器统一为Socket AM2(940针)接口。
纽曼MP4:
纽曼的一款MP4(现已停产);纽曼靓影K8(1G)主要参数:存储容量1GB接口类型USB2.0影片播放AVI音频播放MP3、WMA音频录制WAV、AMR图片查看jpg、gif、png、bmp系统要求Windows 98/2000/XP/2003纽曼 靓影K8(1G)。
众所周知,任意一个系统的安全机制的核心都是基于 认证与授权 (Authentication and Authorization),即首先通过某种方式确认“你”的身份,再根据一定的授权策略确定“你”在我的系统里面能做什么操作。对于K8S来说,就是体现为客户端对于 kube-apiserver 的api接口操作的鉴权(客户端可以是集群内的工作负载pod,任意服务器上的kubectl程序,或是计算节点上的kubelet组件等等)。Kubernets项目作为一个成熟的开源云计算基础设施项目,让我们来看看他们是如何解决认证与授权这两个核心问题的:
k8s的用户认证机制的官方文档地址: https://kubernetes.io/docs/reference/access-authn-authz/authentication/ 。
Kubernetes中的用户类型分为 service accounts 和 normal users 两类。service accounts是k8s内部自建的一套用户认证体系,主要用于pod里直接调用kube-apiserver过程中的认证。而普通用户类型依赖于外部认证服务,k8本身不关心。
当创建service account对象时,会对应的创建一个secret对象,内含了这个用户的认证token,当pod启动时,只要yaml里申明了绑定特定的service account账号,那么系统会自动把secret的token注入到pod中的指定目录,接下来当pod调用apiserver接口时,系统都会自动的附加上这个token,这样apiserver就可以识别出这个pod的身份,结合role和rolebinding的配置信息,就可以正确的授权了。service account是基于k8内部的认证体系,使用起来比较方便,直接在集群内创建sa资源即可。此种类型的用户不是本篇文章讨论的重点,想了解具体的操作可以参考我之前的这篇文章: 构建云原生微服务网关系列-篇二:Zuul ,里面有详细的service account的使用说明。
本文讨论的重点,针对普通用户类型,很多人的理解会比较模糊,对此官网有一段说明:
也就是说,k8项目认为普通用户认证应该由外部服务供应商解决,k8本身不关心认证过程,只要告诉他最终的认证结果,即这个用户是“谁”。认证方式可以用公私钥对,或者openstack 的 keystone认证服务、google的Google Accounts服务,甚至是一个有着用户名和密码列表的文件,对于k8s来说,都是一样的。不管用何种方式去认证,最终结果都是告诉k8s,这个用户是“谁”,也就是它的用户id。这里需要注意的时,对于普通用户类型,k8是不会存储用户信息的,而对于service account类型的用户,k8会保存在etcd里面。普通用户也无法通过api调用直接创建。
Kubernetes 支持使用客户端证书、bearer token、认证代理或者http basic auth等方式进行认证,而无论使用哪种方式,认证插件都需要将以下的用户信息和http请求进行关联:
api-server目前支持的认证方式有:
使用由 k8s 根 CA 签发的证书,提取cn字段作为用户id,O字段作为用户组。我们可以使用openssl工具来进行证书的签发(kubernetes 1.4之后支持了证书中携带用户组信息):
上述操作会生成一个证书请求,username为 jbeda ,并同时属于两个用户组 app1 和 app2 。
静态token列表文件,需要预先在 API Server 服务器上放置该文件,并且在api server的启动参数中加上 --token-auth-file=SOMEFILE ,token文件为csv格式,应至少包含token, user name, user uid这三个字段(逗号分隔)以及一个可选的group names字段,例如:
注意如果用户组有多个的话,整个用户组需要用双引号括起来。
1.18版本进入稳定版的新特性,支持可以在集群启动时动态的创建和管理token,配置比较多,这里不多赘述,有兴趣直接参考官方文档
跟静态 Token 文件类似,只是使用了用户名密码的形式进行认证,使用的是http basic auth类型的认证方式,启动参数为 --basic-auth-file=SOMEFILE ,文件格式为:
很好理解,不多说了
之前介绍过了,k8s内部用户体系 Service Account 使用的 Token,认证方式也是bearer token。这里需要注意的是官方文档有一个描述:
因为api-server本身并不关注流量是从哪里过来的,所以基于service account创建的token,只要你拿到了这个token,是可以从 集群外部 发起请求的,api-server会将此请求认证为对应的service account用户。拿到token的方式官网也做了说明:
注意和serviceaccount绑定的secret类型为 kubernetes.io/service-account-token ,其中token字段即为我们需要的令牌(jwt格式),拿着这个令牌就可以直接发起请求了。 注意在secret中保存的token是经过base64编码的,实际使用时还需要先进行base64解码操作,可以使用jwt.io网站来查看这个令牌,以下是k8s签发的一个jwt令牌payload部分字段的示例:
新出来的一种认证方式,基于Oauth2,比较复杂,有兴趣可以参考官方文档,这里不介绍了。对于Oauth2认证以及JWT技术比较感兴趣的,可以参考我之前的博文 深入理解Spring Cloud Security OAuth2及JWT 。(阅读量4万多了,也算爆款了:)
搞定了认证,接下来就是授权了。得益于k8s优良的设计,认证和授权是解耦的,所以只要k8系统识别出了用户身份(username或者uid),接下来要做的事情就是一样的了。关于授权部分的官方文档地址: https://kubernetes.io/docs/reference/access-authn-authz/rbac/
事实上k8s本身也支持多种授权类型,比如rbac,abac,node,dynamic admission 等等。这里只介绍下最常用的rbac(基于角色的访问控制),实际使用中,api-server开启 --authorization-mode=RBAC 参数,即启动了rbac功能。
如果你对于rbac本身已经比较了解,那么其实k8s里面的rbac功能就非常容易理解了。涉及rbac的有两个api对象,role定义了一个角色,申明了此角色可以操作的功能列表,rolebinding其实就是把用户和角色做了一个绑定。
role的api对象示例:
这个yaml定义了一个Role对象,名称为 pod-reader , 作用域为 default 这个namespace,可以对 pods 这个对象进行 get 、 watch 、 list 操作。
kubernetes完整的操作类型列表如下,都很好理解,不一一说明了:
值得注意的是,有些资源还有子类型,比如pod的logs,如果需要查看,也是需要授权的(添加 pods/log 资源类型)
RoleBinding资源的作用也非常容易理解, 就是绑定Role和用户。下面是一个RoleBinding的示例:
这个例子里把一个类型为User,name叫做jane的用户,和pod-reader的Role做了绑定。注意subjects里面的 kind 字段,即用户类型,前面介绍过了,分别是 User 、 Group 和 ServiceAccount 。绑定完成之后,当使用 jane 这个用户身份对k8s的api进行调用,就可以进行指定的 watch 、 get 、 list 操作了。
这两资源其实和Role、RoleBinding的配置方式是完全一样的,区别在于ClusterRole和ClusterRoleBinding的作用域是集群范围的,并且可以操作 node 这样的集群范围资源,而Role、RoleBinding在metadata中需要指定namespace字段,其他方面没有区别。
弄清原理之后,现在让我们来实际操作一下,目标是使用kubectl客户端工具对于给定的k8集群进行受限操作。基于上述的认证策略的介绍,我们使用 客户端证书 方式来进行用户认证,即使用K8集群的根证书来签发一个用户证书,使用该证书来进行用户认证及授权操作。
关于RSA证书的制作,可以参考官网文档: https://kubernetes.io/docs/concepts/cluster-administration/certificates/ ,这里我们使用常用的openssl工具来制作证书:
1、创建一个2048位长度的RSA格式私钥
2、创建证书签名请求(csr),CN-对应Username O-对应用户组,上面的文章中已经介绍过
3、使用集群根证书签发这个证书请求(days是证书到期时间,可根据实际需要配置)
首先先找到一台准备作为客户端访问k8集群的linux服务器(或者windows、mac都可以),确保客户端与集群的api-server端口网络联通(一般为6443端口,注意必须是https连接),出于安全考虑,最好开一个操作k8的专用的操作系统账号。把集群master节点中的kubectl二进制文件拷贝至此服务器/usr/bin目录内,同时拷贝release.csr、release.key、ca.pem这三个文件至服务器上的指定目录。
在新建用户的home目录下创建.kube目录,在此目录下新建config文件(或者直接执行kubectl config set-cluster test操作,kubectl会自动创建该文件),编辑该文件填写如下内容:
完成之后可以执行 kubectl config view 来验证一下配置是否正确。
使用管理员登陆k8集群,进行权限配置,这里以添加集群范围的运维用户权限为例:
可以看到,我们定义了一个角色 release ,用于应用的部署及日常运维操作。为了满足日常运维,给其分配了一组受限的资源权限。
具体来说,该角色对"deployments","services","configmap","pvc"资源有全部的操作权限,对于"nodes","events","pods","pods/log","endpoints"只有查看权限,对于其他资源没有任何权限。
这里我们定义了一个ClusterRoleBinding,把User和ClusterRole进行了绑定,到这里全部操作就完成了。
登陆客户端,一切顺利的话,执行 kubectl get pods 就可以返回远程集群的default命名空间下的pods列表了,其他配置的权限应该也可以正常操作。而如果这个用户想访问受限资源,比如想查看secrets信息,则会出现如下的报错信息(403 Forbidden):
验证成功!
基于上述的描述,可以知道,其实在集群里面创建一个service account,把它的token拷贝出来,配置在客户端的kubectl配置文件中,可以达到同样的效果,这里就不再演示了。
因为service account的token机密信息实际上都是存放于secret对象中,而secret经常被人吐槽的是存放的数据是明文(只是做了base64编码),所以这里多说一句secret的安全性问题。其实k8s是支持secret加密存放的,支持的加密类型还挺多,具体可以看我这篇文章: 使用加密插件加密secrets中的数据 。但其实我并不建议使用这种方式,原因是使用加密插件只能加密存放在etcd里面的数据,而使用api server调取出的数据仍然是解密过后的,这意味着你执行 kubectl get secrets 或者是进入容器的环境变量查看,仍然可以看到明文数据。k8s项目更推荐的权限管理方式是:
做好上面两点,对于一般公司的安全管控来讲已经足够,毕竟集群管理员的权限只是掌握在很小一部分人的手中。而对于安全审计要求更高的企业(比如金融机构),审计可能会有要求敏感数据必须加密存放,此时可使用api-server的加密插件。
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)