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 ↩