kubernetes上运行着众多的应用,特别是无状态的应用,更甚有一些核心的数据。对于这些数据的访问或者管理,并不是任何人可以随意的管理使用的。因此,kubernetes对于整个系统的认证,授权,以及后续的访问控制做了非常紧密和精心的设计。
通常,客户端通过客户端工具kubectl来访问kubernetes, 对于管理员或者kubectl来讲api server是作为管理的唯一入口。
这联想起了ingress。这与ingress不同,ingress只是暴露服务端口,对于pod内应用程序来讲,客户端访问是不用经过api server。而api server中有众多资源管理平台,管理对应的对象(多组API,且自我迭代),不同于pod中应用。不论如何,任何用户试图在kubernetes平台操作资源对象时,出于安全考虑 ,在访问api server之前需要做三种安全相关的操作。如下图:
1,任何访问到api server之前需要做认证操作,用户具备正确的权限账号,并且通过2,认证通过,授权检查 认证通过,仅仅说明是一个合法的用户,是否拥有其他权限。就要查看授权的资源可能存在链接到其他资源依赖是否具备权限访问,权限是否在允许操作的范围内,就来到第三步3,准入控制器(Service Account Admission Controller ) 当权限认证通过,且检查后,尽管已经拥有了操作的权限,但是用户的操作是否运行被执行,就进行准入控制
kubernetes是模块化设计,授权以及准入控制都可以通过插件的方式,可由用户自定义选择,经由什么插件,又如何控制?取决于用户本身。
认证
这类模块认证支持多种插件认证方式,如
- API令牌(token-controller),交换共享密钥,创建等
所谓令牌认证就是双方都有共享密钥,服务端存放密码,在登陆时进行密码验证登陆,这种方式就是对称密钥认证方式。在k8s中提供的restful接口,通过http的方式,认证的协议通过http首部进行传递,这种认证首部在传递时的预共享密钥编码信息,就叫做令牌-->token。
- SSL认证
对于kubernetes来讲,ssl认证能让客户端认证,并且确认服务器身份
在与服务器通信之前,先要求发送一个证书是否是认可的CA签署。如果发送的信息与目标主机的信息保持一致没有问题, 那就可以认为服务器身份得到认证。而在k8s通信中,服务器也需要认证客户端的身份。因此kubectl也需要有一个证书和私钥,并且必须是server颁发签署的证书,而且客户端认证也要与证书中标识的身份保持一致。并且基于ssl加密会话进行通信
尽管支持多种认证,但是认证一旦通过某个插件认证通过后便认证通过,而无需向其他认证做串行检查。
授权
当认证完成就进入授权检查,在k8s 1.6后支持RBAC,以及node认证,web回调等。
使用kubeadm安装的kubernetes集群,默认强制启用RBAC认证。默认权限全部拒绝。RABC定制的权限非常灵活,可以针对名称空间做权限控制。
尽管支持多种授权,但是授权一旦通过某个插件授权通过后便获得了授权的权限,而无需向其他授权做串行检查。准入控制用于授权完成后的一些其他安全操作
账号信息
在k8s中的一个用户账号,大致需要一下信息:
当客户端对api server发起请求,在识别的过程中,凭证有:用户名,用户id,用户组。当用户携带凭证请求的时候,会请求到一个特定的api资源。在k8s server中有多组,因此,在api请求的资源中必须标识Request Path标识,如:/apis/apps/v1/namespace/default/deployments/myapp-deploy/
Request Path
- k8s兼容多个版本共存,这里的版本有多个,如:beta的版本叠加,apps/v1,apps/v1beta1,apps/v1beta2
/namespace/default/deployments/myapp-deploy/
在资源里面,要么属于名称空间,要么属于集群级别。名称空间,pv属于集群级别,而pod,serivce,pvc等等,属于名称空间级别,所有名称空间级别,所有名称空间级别访问需要指定:/名称空间/default名称空间名称/
下找deployments/名称叫myapp-deploy/
的资源。用户可以对这个资源发起增删改查操作。
kubectl create ,apply ,delete等操作,事实上都是被转换为一个Http协议的请求来请求的:如:http://10.10.240.161:6443/apis/apps/v1/namespace/default/deployments/myapp-deploy/
通常在操作kubectl时,由于kubectl自带了认证信息,所以kubectl能操作所有的操作。
- 在创建kubernetes集群时候,我们复制了一个配置文件到~/.kube/config。这个配置文件中包含了证书和私钥,所以我们在使用kubectl时候并不需要认证信息,如下:
[root@linuxea satefulset]# cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: 省略号。。。。。。。
server: https://10.10.240.161:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: 省略号。。。。。。。
client-key-data: 省略号。。。。。。。
我们可以使用curl进行curl请求这些url,但是curl的话就需要认证信息。可以使用kubectl proxy --port=8080
创建一个porxy代理8080端口,proxy自动回和kubectl进行认证,而我们curl查看便不需要认证,而后跳过
[root@linuxea satefulset]# kubectl proxy --port=8080
Starting to serve on 127.0.0.1:8080
端口已经启动
[root@linuxea volume]# ss -tlnp|grep 8080
LISTEN 0 128 127.0.0.1:8080 *:* users:(("kubectl",pid=10193,fd=3))
curl http://localhost:8080/api/v1
curl本地的8080代理端口. 会得到一个json格式的结果。此前我们知道,编写的资源清单yaml最终也会转成json格式后提交给系统使用,如下:
api/v1
此前的yaml文件的指定的apiVersion: v1
则是指定的这里
[root@linuxea volume]# curl http://localhost:8080/api/v1/namespaces
{
"kind": "NamespaceList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/namespaces",
"resourceVersion": "2003021"
},
"items": [
{
"metadata": {
"name": "default",
"selfLink": "/api/v1/namespaces/default",
"uid": "3914423a-b975-11e8-a8ab-88882fbd1028",
"resourceVersion": "5",
"creationTimestamp": "2018-09-16T05:56:15Z"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
省略..... 省略..... 省略..... 省略..... 省略.....
那么访问deploy也是如此,也是基于url进行增删改查,如:coredns
[root@linuxea volume]# kubectl get deploy -n kube-system
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
coredns 2 2 2 2 14d
对于k8s来讲,所有的api资源都起源于api的父树apis,此前的http://localhost:8080/api/v1/namespaces
特殊链接除外(核心群组特殊的访问逻辑)。我们试图获取deployments的对象列表http://localhost:8080/apis/apps/v1/namespaces/kube-system/deployments/
[root@linuxea volume]# curl http://localhost:8080/apis/apps/v1/namespaces/kube-system/deployments/
{
"kind": "DeploymentList",
"apiVersion": "apps/v1",
"metadata": {
"selfLink": "/apis/apps/v1/namespaces/kube-system/deployments/",
"resourceVersion": "2003887"
},
"items": [
{
"metadata": {
"name": "coredns",
"namespace": "kube-system",
"selfLink": "/apis/apps/v1/namespaces/kube-system/deployments/coredns",
"uid": "3bb90cc6-b975-11e8-a8ab-88882fbd1028",
"resourceVersion": "600",
"generation": 1,
"creationTimestamp": "2018-09-16T05:56:19Z",
"labels": {
"k8s-app": "kube-dns"
},
"annotations": {
"deployment.kubernetes.io/revision": "1"
}
省略..... 省略..... 省略..... 省略..... 省略.....
"spec": {
或者请求coredns
[root@linuxea volume]# curl http://localhost:8080/apis/apps/v1/namespaces/kube-system/deployments/coredns
这些都是http格式,可以编辑,查看,修改,删除这些操作的授权
- http request verb
请求动作,包括: get ,post,put,delete,这些http的方法会转换成api requets verb的方法,如:get,list,create,update,patch,watch,proxy,redirect,delete,delete collection。
resource: 请求资源的id或者名称。subresource: 子资源。namespace,api group等。这些在request path中已经包含
api server是整个访问请求进入的网关接口,用户用于身份识别,授权用于权限检查,准入控制更多的补充了授权机制,一般会在删除,创建,修改或者代理时候做补充。