在K8S中,当我们试图通过API与集群资源交互时,必定经过集群资源管理对象入口kube-apiserver。显然不是随随便便来一个请求它都欢迎的,每个请求都需要经过合规检查,包括Authentication(身份验证)、Authorization(授权)和Admission Control(准入控制)。通过一系列验证后才能完成交互。
Kubernetes API 请求从发起到持久化到ETCD数据库中的过程如下:
“三个A”我们可以简单理解为:
-
Authentication
:你是谁?你能登录系统么? -
Authorization
:你想做什么?你有相应的权限么? -
Admission Control
: 在apiserver中准入控制会以控制器插件的方式存在,类似于各类web框架中的中间件,可以在kube-apiserver的yml中添加控制器插件--enable-admission-plugins
开启。
这篇小作文我们主要来学习K8S中关于认证与授权相关的知识,看看他们是如何实现的。包含如下内容:
- K8S 通过证书认证
- K8S 通过RBAC 授权
一、 K8S 通过证书认证
Authentication(身份认证),即核查用户能否进入K8s集群。一般来说k8s中有两类用户,普通用户和服务账户(Service Account)。
普通用户,使用者是人,即用户可以通过 kubectl 命令、或通过REST请求访问 API,但是请注意K8s不提供普通用户管理的资源对象,那所谓的普通用户哪里的?很简单只要你能通过k8s身份认证策略那么你就是一个普通用户。而Service Account 则是针对运行在 Pod 中的进程而言的。
K8S的几种验证方式:
- Certificate
- Token
- OpenID
- Web Hook
其中Certificate(证书)是在普通用户(客户端)中被广泛使用的验证方式。通过客户端证书进行身份验证时,客户端必须先获得一个有效的 x509 客户端证书,然后Kubernetes API服务器通过验证这个证书来验证你的身份。当然你的X509证书必须由集群 CA 证书签名。这其实就是HTTPS加密中的一部分,只不过是CA是K8S自签名的CA证书。
首先我们通过openssl创建一个用户私钥
openssl genrsa -out develop1.key 2048
通过user.key 生成CSR(证书签名请求),Kubernetes 使用证书中的 'subject' 的通用名称(Common Name)字段来确定用户名,Organization Name 作为组。
openssl req -new -key develop1.key -out develop1.csr -subj "/CN=develop1/O=devops"
有了CSR,我们就可以把它交给K8S admin通过集群CA签署客户端证书。kubeadm创建的集群证书对存储在master节点的 /etc/Kubernetes/pki/ 目录中,(当然如果你是admin,也可以直接通过API的方式签署证书)集群包含一个根 CA,用它签署所有集群组件相互通信所需的证书。
openssl x509 -req -in develop1.csr -CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out develop1.crt -days 30
这样我们获得了一个被集群CA签署过的证书develop1.crt
develop1.crt develop1.csr develop1.key
查看证书内容openssl x509 -noout -text -in develop1.crt
包含CN/O,以及证书过期时间。
好了,有了证书之后,下一步我们需要配置kubecofnig
使kubectl
可以正常访问apiserver,关于kubeconfig
可参考官方文档organize-cluster-access-kubeconfig 这里我们以配置为主。
默认情况下,kubectl
读取 $HOME/.kube/config
作为配置文件。也可以通过两种方式为 kubectl
指定配置文件:
- 环境变量
KUBECONFIG
- 命令行参数
--kubeconfig
现在通过kubectl来创建config中的集群入口
kubectl config set-cluster kubernetes \
--server=https://apiserver.cluster.local:6443 \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true
创建用户入口
kubectl config set-credentials develop1 \
--client-certificate=$HOME/private_key/develop1.crt \
--client-key=$HOME/private_key/develop1.key \
--embed-certs=true
创建上下文
kubectl config set-context develop1 \
--cluster=kubernetes \
--user=develop1
指定当前context
$ kubectl config set current-context develop1
Property "current-context" set.
#查看当前context,已绑定develop1
$ kubectl config current-context
develop1
通过kubectl config view
查看当前的config
这样我们kubectl
已经配置完毕,但是此时我们只完成了Authentication
,并没有获得权限
$ kubectl get pod
Error from server (Forbidden): pods is forbidden: User "develop1" cannot list resource "pods" in API group "" in thenamespace "default"
可以看到develop1没有对命名空间default
的list
权限。所以接下来我们来学习Authorization
授权相关内容。
二、K8S 通过RBAC 授权
RBAC(Role-Based Access Control)即基于角色的访问控制,在各类大型系统如虚拟化Vcenter、各类云服务以及众多toB软件访问控制中被大量使用。关于RBAC可参考一篇译文:[译] 基于角色的访问控制(RBAC):演进历史、设计理念及简洁实现(Tailscale, 2021)
k8s作为企业内部重要云基础设施并不希望每个使用平台的用户都可以不受限制的创建、修改和删除资源。同时伴随着集群节点、应用程序和团队数量的增加,你需要一种安全措施将用户或应用权限控制在某个范围内,这就K8S 在V1.8正式引入RBAC所要做的事(其他鉴权机制本文不涉及)。
K8S的RBAC 主要由Role、ClusterRole、RoleBinding 和 ClusterRoleBinding 等资源实现。模型如下:
Role、ClusterRole
角色是一组权限规则的集合,Role 用来定义某个命名空间内的访问权限,而ClusterRole 则是一个集群作用域的资源。为啥要用两个资源?因为Kubernetes 对象的作用域已经被划分为集群和命名空间两部分了。需要注意:角色只有授权没有禁止的操作。
构成一个Rule需要声明三部分:
-
apiGroups
:资源所属的API组:""
缺省为 core 组资源,如:extensions、apps、batch等。Kubernetes API 参考文档 -
resources
:资源,如: pods、deployments、services、secrets 等。 -
verbs
:动作,如: get、list、watch、create、delete、update 等。
现在我们来创建一个可以读取默认命名空间default
的Role,它的api版本为:rbac.authorization.k8s.io/v1
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: develop-defualt
rules:
- apiGroups: [""] #core api组
resources: ["pods"]
verbs: ["get", "watch", "list"]
此时还没有api交互权限,所以应该通过kube-admin来创建
# kubectl apply -f role.yml
role.rbac.authorization.k8s.io/develop-defualt created
RoleBinding、ClusterRoleBinding
上面我们已经创建了一个带权限的角色,下一步就了解如何将角色关联到用户。角色绑定是将我们角色中定义好的权限赋予一个或者一组用户,即上图Sujbect。RoleBinding 在指定的名字空间中执行授权,而 ClusterRoleBinding 在集群范围执行授权。
图中展示了三种绑定方式,除了常规的绑定各自作用域的角色外,RoleBinding还可以绑定集群级别的ClusterRole。有啥用呢?当我们要对namespace做授权时,通常可以创建namespace中的Role进行绑定,如果管理几百个NS则需创建相应数量的NS Role,显然不是很棒,所以我们将RoleBinding绑定到集群的ClusterRole,只需几个ClusterRole就可以将几百个NS做访问控制了。
我们将上面创建的develop-defualt
角色做绑定:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: develop-rolebinding
namespace: default #授权的命名空间为default
subjects:
- kind: User
name: develop1 # 绑定develop1用户
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: develop-defualt #绑定Role
apiGroup: rbac.authorization.k8s.io
通过admin创建RoleBinding
# kubectl apply -f role-binding.yml
rolebinding.rbac.authorization.k8s.io/develop-rolebinding created
ok,此时在使用kubectl get pod
时,就能获得结果了。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
web-85549dcb84-nb67c 1/1 Running 0 12d
web-85549dcb84-z95sj 1/1 Running 0 12d
ServiceAccount授权和普通用户相似,这里不再赘述。有兴趣的读者可以参考官方文档学习。
以上我们对K8S中认证和授权做了基本介绍,以及对创建一个用户并授权pod读取权限做了实践。
希望小作文对你有些许帮助,如果内容有误请指正。
您可以随意转载、修改、发布本文,无需经过本人同意。通过博客阅读:iqsing.github.io