前言
前面整理到这里,应用已经能运行、能暴露、能读取配置,也能做基本排障。接下来我想把视角切到安全上。
第一个问题是:Pod 里的程序能不能访问 Kubernetes API?
比如一个应用想读取同 namespace 下的 ConfigMap,或者一个控制器想监听 Pod 变化。它访问 API Server 时,总要有一个身份。
在 Kubernetes 里,给程序用的身份通常是 ServiceAccount。
1 | 人访问集群 |
有了身份之后,还要决定这个身份能做什么。这部分通常由 RBAC 控制。
1 | ServiceAccount |
我目前把它理解成:ServiceAccount 是工牌,Role 是权限清单,RoleBinding 是把权限清单发给某张工牌。
default ServiceAccount
每个 Namespace 默认都会有一个叫 default 的 ServiceAccount。
1 | kubectl get serviceaccount -n demo-dev |
如果创建 Pod 时不指定 ServiceAccount,Pod 通常会使用当前 Namespace 的 default。
1 | Pod 没写 serviceAccountName |
这点容易被忽略。不是没写身份就没有身份,而是用了默认身份。
一个明确指定 ServiceAccount 的 Pod:
1 | apiVersion: v1 |
我更倾向给重要应用单独创建 ServiceAccount,而不是所有应用都混用 default。
1 | demo-api -> demo-api ServiceAccount |
这样后面分配权限时才清楚。
ServiceAccount token
Pod 使用 ServiceAccount 后,Kubernetes 会让 Pod 拥有对应身份的凭据。应用如果访问 API Server,就可以拿这个身份认证。
可以粗略理解成:
1 | ServiceAccount |
现代 Kubernetes 更推荐使用有边界、可过期的 TokenRequest 机制,而不是长期静态 token。作为入门理解,我先记住两个边界:
- ServiceAccount 是身份;
- token 是这个身份访问 API Server 时用到的凭据。
如果某个 Pod 根本不需要访问 Kubernetes API,可以关闭自动挂载:
1 | apiVersion: v1 |
这就像一个普通同学只来上自习,不需要进资料室,就没必要给他额外门禁。
RBAC 的四个对象
RBAC 常见四个对象:
1 | Role |
先看最常见的 namespace 内授权:
1 | ServiceAccount: demo-api |
这条线是:
1 | 谁 |
Role:描述能做什么
假设只允许读取 ConfigMap:
1 | apiVersion: rbac.authorization.k8s.io/v1 |
这份 Role 可以翻译成:
1 | 在 demo-dev namespace 内 |
几个字段这样读:
1 | apiGroups |
它只是权限清单,还没有发给任何人。
RoleBinding:把权限给某个身份
RoleBinding 负责把 Role 绑定给 ServiceAccount。
1 | apiVersion: rbac.authorization.k8s.io/v1 |
可以翻译成:
1 | 把 read-configmap 这个 Role |
关系图:
1 | RoleBinding |
到这里,Pod 如果使用 demo-api 这个 ServiceAccount,就能读取 demo-dev 里的 ConfigMap。
ClusterRole 和 ClusterRoleBinding
Role 是 namespace 内的权限。ClusterRole 是集群级权限清单。
例如读取节点:
1 | apiVersion: rbac.authorization.k8s.io/v1 |
Node 是集群级资源,不属于某个 namespace,所以通常要用 ClusterRole。
ClusterRoleBinding 会把权限授予整个集群范围:
1 | apiVersion: rbac.authorization.k8s.io/v1 |
这个权限范围更大,要更谨慎。
1 | RoleBinding |
ClusterRole 也可以绑定到 namespace
ClusterRole 不一定只能通过 ClusterRoleBinding 使用。它也可以被 RoleBinding 绑定到某个 Namespace。
1 | ClusterRole |
例如 Kubernetes 内置有一些常见 ClusterRole。通过 RoleBinding 绑定时,权限仍然限定在 RoleBinding 所在的 Namespace。
这个设计一开始有点绕,但好处是可以复用权限模板:
1 | 同一个 ClusterRole: view |
最小权限原则
RBAC 最重要的习惯是最小权限。
比如应用只需要读 ConfigMap,就不要给它:
1 | secrets get/list |
权限应该像借工具:
1 | 需要螺丝刀 |
我会尽量避免这些写法:
1 | verbs: |
除非非常明确知道边界,否则通配符会让权限变得很难审计。
怎么检查权限
可以用 kubectl auth can-i 检查某个身份是否有权限。
检查当前用户:
1 | kubectl auth can-i get pods -n demo-dev |
检查某个 ServiceAccount:
1 | kubectl auth can-i get configmaps \ |
ServiceAccount 的完整用户名形式大致是:
1 | system:serviceaccount:<namespace>:<name> |
这个命令很适合排查:
1 | 应用访问 API 失败 |
不要只看 YAML 觉得“我应该配了”,用 can-i 查一下更直接。
小结
这一篇整理下来,我对 ServiceAccount 和 RBAC 的理解可以概括成几句话:
- ServiceAccount 是给 Pod 或自动化程序使用的集群身份;
- 每个 Namespace 都有默认的
defaultServiceAccount; - Pod 可以通过
serviceAccountName指定身份; - 不需要访问 API Server 的 Pod 可以关闭 token 自动挂载;
- Role 描述 namespace 内权限;
- ClusterRole 描述集群级或可复用权限;
- RoleBinding / ClusterRoleBinding 负责把权限绑定给主体;
- RBAC 要遵循最小权限原则;
kubectl auth can-i适合检查权限是否真的生效。
下一篇准备继续看 SecurityContext。RBAC 管的是“能不能访问 Kubernetes API”,SecurityContext 更关注“容器进程在节点上以什么权限运行”。
参考资料
- Service Accounts:https://kubernetes.io/docs/concepts/security/service-accounts/
- RBAC Authorization:https://kubernetes.io/docs/reference/access-authn-authz/rbac/
- Configure Service Accounts for Pods:https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
- RBAC Good Practices:https://kubernetes.io/docs/concepts/security/rbac-good-practices/