Kubernetes 权限控制
环境信息
- Centos 7
- Kubernetes 1.24
ServiceAccount
ServiceAccount 就像 Pod、Secret、ConfigMap 等一样,都是资源,属于 namespace 级别,作用在单独的命名空间。默认情况,每个 namespace 都有一个默认的 ServiceAccount。
kubectl get serviceaccount |
namespace 中的每个 Pod 都和一个 ServiceAccount 关联,它代表了运行在 Pod 中的应用程序的身份证明。Pod 中的每个容器都会挂载此 ServiceAccount token
在 Pod 的 manifest 定义文件中,可以通过指定账户名称的方式将一个 ServiceAccount 关联到 Pod。如果不显示指定 ServiceAccount 的账户名称,Pod 会使用 namespace 中默认的 ServiceAccount。可以将不同的 ServiceAccount 关联给不同的 Pod 来控制每个 Pod 可以访问的资源。
当 API 服务接收到一个带有认证 token 的请求时, API 会用这个 token 来验证发送请求的客户端所关联的 ServiceAccount 是否允许执行请求的操作。
查看 ServiceAccount
以 rancher 相关的 ServiceAccount 为例,查看 ServiceAccount 信息
kubectl get serviceaccount -n cattle-system |
以下输出名为 rancher 的 ServiceAccount 信息
kubectl describe sa rancher -n cattle-system |
ServiceAccount 主要包含了密钥(token)信息,客户端 (Pod)请求 API Service 时使用的 token 文件(如 /var/run/secrets/kubernetes.io/serviceaccount/token)持有 ServiceAccount 的 token 。
kubectl describe secret rancher-token -n cattle-system |
在新建了 ServiceAccount 之后,若要将它赋值给 Pod,通过在 Pod 定义中的 spec.serviceAccountName 字段上配置 ServiceAccount 名称来分配。Pod 的 ServiceAccount 必须在 Pod 创建时进行配置,后续不能被修改
RBAC
从 Kubernetes 1.8.0 开始,RBAC(基于角色的权限控制)授权插件升级为 GA(通用可用性),并在大多数集群上默认开启(比如通过 kubeadm 部署的集群)。RBAC 会阻止未授权的用户查看和修改集群状态,默认的 ServiceAccount 不允许查看集群状态。
RBAC 授权规则是通过四种资源对象来进行配置的,他们可以分为 2 个组 [1]
Role、ClusterRole- 一组代表相关权限的规则,他们指定了在资源上可以执行哪些操作(动词)RoleBinding、ClusterRoleBinding- 将角色中定义的权限赋予一个或者一组用户。它包含若干主体(用户、组或者 ServiceAccount)的列表和对这些主体所获得的角色的引用。
Role和RoleBinding属于 namespace 范围的资源,必须在 namespace 中配置
ClusterRole和ClusterRoleBinding是集群作用域的资源一个 RoleBinding 可以引用某 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的名字空间。但是,RoleBinding 不能授予主体集群级别的资源的访问权限,即使它引用了一个 ClusterRoleBinding
Role
下面是一个位于 default 名字空间的 Role 的示例,可用来授予对 Pod 的读访问权限
apiVersion: rbac.authorization.k8s.io/v1 |
RoleBinding
apiVersion: rbac.authorization.k8s.io/v1 |
RBAC 配置示例
以下示例演示通过给 namespace 中默认的 ServiceAccount 配置查看 Service 的权限,学习 RBAC 的使用。
本示例中的 namespace 为 ops,示例 Pod 为 ops-centos7-bfc4d75b5-kjcfs,配置信息如下
kubectl edit pod -n ops ops-centos7-bfc4d75b5-kjcfs |
登陆到 Pod 中的容器,请求 Kubernetes API Server。默认的 token 没有查询集群信息的权限。
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://kubernetes.default.svc.cluster.local |
以上请求中,因为没有提供访问的凭据,认证系统会将请求者的身份标记为 system:anonymous,鉴权系统检查此用户是否有权限请求相应资源,没有权限则返回 403。
使用 Pod 中默认挂载的 token 进行请求,认证系统会识别请求者的身份为对应的 ServiceAccount(默认的 default),鉴权系统检查权限,返回 Unauthorized 表示请求未授权。
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \ |
创建 Role
创建以下配置的 Role,名称为 services-read,Role 属于 namespace 资源,因此必须指定 namespace [2]
apiVersion: rbac.authorization.k8s.io/v1 |
创建 RoleBinding
Role 配置了允许的操作(动作),未指定可以执行动作的主体(用户,组,ServiceAccount),必须将 Role 绑定到一个主体,通过创建 RoleBinding,来实现将 Role 绑定到主体
apiVersion: rbac.authorization.k8s.io/v1 |
通过以上配置,namespace 中默认的 ServiceAccount default 的 token 拥有了 services-read 这个 Role 的权限,而默认情况下 default 这个 ServiceAccount 的 token 被挂载到了 Pod 的容器中,可用于容器中的进程和 Kubernetes API Server 通信的身份认证。
通过以下命令访问 Kubernetes API Server,已经可以获取到 ops namespace 中的 Service 资源。
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H "Authorization: Bearer `cat /var/run/secrets/kubernetes.io/serviceaccount/token`" https://kubernetes.default.svc.cluster.local/api/v1/namespaces/ops/services |
修改 Role 为以下配置,使默认的 ServiceAccount default 可以查看 namespace 中的所有资源
apiVersion: rbac.authorization.k8s.io/v1 |
获取 Pods 资源
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \ |
在不能使用
curl的情况下,可以使用wget命令
wget --no-check-certificate --header "Authorization: Bearer `cat /var/run/secrets/kubernetes.io/serviceaccount/token`" https://172.31.30.123:10250/metrics
Connecting to 172.31.30.123:10250 (172.31.30.123:10250)
saving to 'metrics'
metrics 100% |***************************************************************************************| 135k 0:00:00 ETA
'metrics' saved
脚注
- 1.使用 RBAC 鉴权 ↩
- 2.API Role ↩