K8s访问控制

张开发
2026/4/23 17:59:47 15 分钟阅读

分享文章

K8s访问控制
用cluster-admin的权限随便操作所有 Pod 之间网络全通反正测试环境怎么玩都无所谓。 但当你的集群上了生产跑了核心业务你就会发现问题开发同学误操作把线上的 Deployment 删了整个服务挂了半小时测试环境的账户不小心改了生产的配置微服务里的前端服务居然能直接访问用户的数据库一旦被攻破所有数据都泄露了这时候才意识到没有访问控制的集群就像没做任何权限管控的系统任何人都能操作任何资源太危险了。一、访问控制的整体流程请求要过哪几关Kubernetes 的所有操作最终都会落到 API Server 上不管是你用 kubectl 执行命令还是 Pod 里的程序调用 API所有请求都必须按顺序经过三个核心的处理阶段这三个阶段就是访问控制的核心认证Authentication这一步的核心是确认你是谁。API Server 会验证你请求里带的身份凭证比如客户端证书、Bearer Token、账号密码确认你的身份是合法的不是伪造的。只有通过了这一步请求才会进入下一关。授权Authorization确认完你的身份之后这一步要确认你能不能做你要做的这件事。比如你是一个开发能不能删除集群里的节点能不能修改某个 namespace 里的 Pod。Kubernetes 最常用的授权模式就是 RBAC准入控制Admission Control这是最后一关在请求要被处理、保存到集群存储之前做最后的全局检查。比如你有没有超出资源配额你用的镜像是不是合法的你有没有开启危险的特权容器。只有所有的检查都通过请求才会被最终处理。简单来说这三个阶段就是先确认你是谁再确认你能不能做这件事最后确认这件事本身合不合规矩。二、身份管理给 Pod 一个合法的身份要做权限管控首先得有身份Kubernetes 里的身份分两种一种是给人类用户用的普通 User比如运维、开发一般是通过外部的认证服务管理的另一种就是给 Pod 里的程序用的ServiceAccount服务账户。疑问为什么 Pod 里的程序不用配账号就能直接调用 Kubernetes API这就是 ServiceAccount 的功劳。ServiceAccount 是怎么工作的ServiceAccount 是集群内部管理的账户专门给 Pod 里的进程用的用来让这些程序能合法地访问 API。它的整个流程都是自动的你几乎不用做任何配置每个 namespace 创建的时候都会自动创建一个名为default的 ServiceAccount给没指定账户的 Pod 用。只要你新建了 ServiceAccountKubernetes 的 Token controller 就会自动为它生成一个 Secret里面存着身份 Token、集群的 CA 证书、当前的 namespace 信息。Pod 启动的时候会自动把这个 Secret 里的文件挂载到容器内的/var/run/secrets/kubernetes.io/serviceaccount/这个固定路径下。Pod 里的官方客户端比如 client-go、kubectl都会自动去读这个路径下的文件不用你做任何配置程序就已经带着合法的身份去访问 API 了。当然如果你需要给不同的 Pod 分配不同的权限你也可以手动创建自己的 ServiceAccount比如# 创建一个专门给订单服务用的ServiceAccount kubectl create namespace order kubectl -n order create serviceaccount order-sa这样你就可以给这个账户单独分配权限和默认的账户分开了。另外如果你有 Pod 根本不需要访问 API为了安全你可以关掉自动挂载避免凭证泄露spec: automountServiceAccountToken: false三、权限管控用 RBAC 管好 “谁能做什么”有了身份之后我们就要管权限了这个身份能做什么不能做什么这就要用到 RBAC也就是基于角色的访问控制这是 Kubernetes 最常用的授权模式。RBAC 的核心逻辑RBAC 的逻辑很简单把权限打包成角色然后把角色绑定给账户这样账户就拥有了角色里的所有权限。它有四个核心的资源两两配对分别管 namespace 级和集群级的权限资源类型作用作用范围Role定义权限规则说明这个角色能做什么操作单个 namespace只在当前 namespace 生效ClusterRole定义权限规则说明这个角色能做什么操作整个集群对所有 namespace 生效也能管理节点这类集群级资源RoleBinding把角色绑定给账户让账户拥有角色的权限单个 namespace绑定只在当前 namespace 生效ClusterRoleBinding把角色绑定给账户让账户拥有角色的权限整个集群绑定对所有 namespace 生效这里要注意两个点权限是累加的没有拒绝只要你给账户绑定的角色里有任何一个允许了某个操作这个操作就能做所有没被允许的默认都是拒绝的。RoleBinding 可以绑定 ClusterRole你可以把一个全局的 ClusterRole绑定到某个 namespace 的账户这样这个账户就只在当前 namespace 拥有这个权限不用重复写规则非常方便。实际操作给服务分配只读权限举个实际的例子我们要给之前的order-sa这个账户分配ordernamespace 里的 Pod 只读权限也就是只能看 Pod不能改、不能删怎么做首先我们创建一个 Role定义权限apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-reader namespace: order rules: - apiGroups: [] resources: [pods] verbs: [get, list, watch]这个 Role 的规则就是允许对 Pod 执行读相关的操作也就是 get、list、watch没有给创建、删除的权限。然后我们把这个 Role 绑定给order-sa账户kubectl -n order create rolebinding pod-reader-binding \ --rolepod-reader \ --serviceaccountorder:order-sa绑定完之后我们来测试一下权限# 测试能不能看Pod有权限 kubectl -n order auth can-i get pods --assystem:serviceaccount:order:order-sa yes # 测试能不能删Pod没权限 kubectl -n order auth can-i delete pods --assystem:serviceaccount:order:order-sa no这样就完成了我们的订单服务的程序就只能读 Pod不能修改或者删除就算程序出了问题也不会误删资源非常安全。四、网络隔离用 NetworkPolicy 管好 Pod 之间的访问权限管好了集群的 API 访问那 Pod 之间的网络访问呢比如我要让数据库的 Pod只能被应用服务的 Pod 访问别的都不能访问怎么做这就要用到 NetworkPolicy也就是网络策略。NetworkPolicy 的核心规则NetworkPolicy 是用来做 Pod 之间的网络隔离的它可以管控 Pod 的网络流量限制 Pod 只能和指定的对象通信。它的默认规则很重要很多新手都踩过这个坑如果你的 Pod 没有匹配到任何 NetworkPolicy那么所有流量都是全通的Pod 可以随便连别人别人也可以随便连它。只要有一个 NetworkPolicy 匹配到了这个 Pod那么所有没被明确允许的流量都会被默认拒绝也就是说你加了网络策略之后一定要把所有需要的流量都明确允许不然服务就会不通。另外NetworkPolicy 的规则也是累加的只要有任何一个策略允许了某个连接这个连接就能通规则的顺序不影响结果。还要注意不是所有的网络插件都支持 NetworkPolicy比如默认的 flannel 就不支持你需要用 Calico、Cilium 这些支持的插件不然你创建了策略也不会生效。实际操作限制数据库的访问来源举个例子我们的dbnamespace 里放了 MySQL 服务我们要让它只能被appnamespace 里的应用服务访问其他的都不能访问怎么做首先创建两个 namespacekubectl create namespace db kubectl create namespace app然后创建 NetworkPolicyapiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-app-access-db namespace: db spec: podSelector: {} # 对db namespace里的所有Pod生效 policyTypes: - Ingress # 只管控入口流量 ingress: - from: - namespaceSelector: matchLabels: name: app # 只允许来自app namespace的来源 ports: - protocol: TCP port: 3306 # 只允许访问3306端口这个策略的意思就是db里的所有 Pod只允许appnamespace 里的 Pod 访问它的 3306 端口其他的来源都被拒绝。这样配置完之后就算有别的 Pod 拿到了数据库的地址也连不上就算数据库的权限没配好也能挡住非法的访问双重安全。五、注意最小权限原则永远只给账户最小的必要权限不要随便给cluster-admin的权限很多人图方便给所有账户都开了 admin这是非常危险的。不要用 default 账户默认的defaultServiceAccount 权限太开放而且所有 Pod 默认都会用它生产环境一定要给每个服务单独创建自己的 ServiceAccount分配独立的权限。定期审计权限定期清理不用的账户、不用的角色绑定避免权限泛滥时间长了谁都不知道哪个账户有什么权限了。开启网络策略不要让所有 Pod 都全通给核心服务加上网络策略只允许必要的访问就算某个服务被攻破也能挡住横向渗透。总结Kubernetes 的访问控制是集群安全的基础从身份管理到权限管控再到网络隔离这一套体系下来就能把你的集群的安全管好避免误操作、避免非法访问让你的生产集群更安全。

更多文章