尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Kubernetes(K8s)笔记Day10 :K8s 安全管理机制(认证与授权)

Kubernetes(K8s)笔记Day10 :K8s 安全管理机制(认证与授权) Kubernetes 安全机制认证、授权、准入控制一、安全管理概述Kubernetes API Server 是集群访问的唯一入口其对每一个请求都会依次执行认证 (Authentication)、授权 (Authorization)和准入控制 (Admission Control)三个阶段。这三个阶段层层把关共同构建了集群的安全防线。二、安全管理详细内容认证Authentication直接管控“能否与 APIServer 通信”能不能连上你是谁。授权Authorization 和 准入控制Admission Control管控的是“通信请求被允许之后能做什么、以及怎么做”权限范围 合规审查。2.1 认证Authentication核心问题“你是谁”认证是访问控制的第一步目的是验证客户端身份确认其是否为一个合法的用户。认证对象Kubernetes 中的客户端主要有两类类型说明使用者User Account真实的人如管理员、开发者使用的账号管理员、开发者Service Account (SA)Pod 中的进程使用用于 Pod 与 API Server 通信Pod 中的应用程序认证方式Kubernetes 支持多种认证模块只要其中一种通过即可。认证方式说明安全性HTTP Base 认证通过用户名和密码进行认证低HTTP Token 认证使用一个难以伪造的字符串Token来识别身份中HTTPS 证书认证基于 CA 根证书签名的双向数字证书认证最高生产环境推荐注意如果认证失败API Server 会返回HTTP 401状态码。2.2 授权Authorization核心问题“你能做什么”认证通过后请求进入授权阶段。此阶段决定已认证的用户是否有权限执行其请求的操作。决策依据依据说明用户与组认证阶段提供的用户名和用户组操作动词get、list、create、update、delete等资源对象正在访问的资源类型如 Pods、Services和名称命名空间操作所在的命名空间注意如果授权失败API Server 会返回HTTP 403状态码。2.3 准入控制Admission Control核心问题“请求是否合规”准入控制是最后一道防线它在请求通过认证和授权之后、对象被持久化到 etcd 之前对请求进行拦截和处理。核心作用准入控制器可以对请求进行修改或验证。类型作用示例变更Mutating修改请求中的数据为 Pod 自动添加 sidecar 容器或默认标签验证Validating校验请求是否符合集群策略确保镜像来源可信、Pod 没有使用特权模式执行顺序准入控制分为两个阶段先执行变更准入控制器再执行验证准入控制器。任何阶段失败请求都会被立即拒绝。重要特性准入控制器只拦截**修改创建、删除、更新**对象的请求不会作用于读请求get、watch、list。常见准入控制器插件插件名说明AlwaysAdmit允许所有请求通过用于测试AlwaysDeny禁止所有请求通过用于测试ResourceQuota用于 namespace 上的配额管理推荐放到准入控制器列表的最后一个NamespaceLifecycle拒绝在不存在 namespace 下创建资源删除 namespace 时清理其下所有资源三、Service Account服务账号3.1 默认 Service Account当创建 Pod 的时候如果没有指定Service Account系统会自动在与该 Pod 相同的 namespace 下为其指派一个defaultService Account。这是Pod 与 API Server 之间进行通信的账号。[rooth1 ~]# kubectl get saNAME SECRETS AGE default112d默认 Service Account 的权限限制默认的 Service Account 仅能通过 Downward API挂载文件或环境变量获取当前 Pod 自身的自身元数据对 APIServer 的所有资源包括当前命名空间的 Pod几乎没有任何 get/list/watch 权限也无法观察到其他名称空间 Pod 的相关属性信息。为什么说“几乎”没有任何权限默认的 default ServiceAccount 虽然对具体的业务资源Pod、Service、Deployment没有 get/list 权限但是为了 kubectl 工具能够正常工作比如执行 kubectl explain 或自动补全默认 SA 通常会被系统授予 discovery发现权限允许访问 /api 和 /apis 这两个端点用于获取集群支持的 API 资源列表但这种权限对业务 Pod 毫无用处只是系统内部的正常通讯需求。3.2 命令行 自定义 Service Account假设有一个 Pod 需要用于管理其他 Pod 或其他资源对象就需要手动创建一个 Service Account并在创建 Pod 时进行指定。# 创建一个 Service Account名称为 test[rooth1 ~]# kubectl create serviceaccount test#查看所有sa[roothd1 ~]# kubectl get saNAME SECRETS AGE default013d nfs-provisioner02dtest07s# 查看 Service Account 详细信息[roothd1 ~]# kubectl describe sa testName:testNamespace: default Labels:noneAnnotations:noneImage pull secrets:noneMountable secrets:noneTokens:noneEvents:none使用场景当 Pod 中的应用需要调用 Kubernetes API 进行资源管理如列出所有 Pod、创建 Deployment 等时必须使用自定义 Service Account 并授予相应权限。为什么 CLI 命令创建后 Tokens: none 且 SECRETS 为 0 这是 Kubernetes v1.24的新特性旧版v1.24 之前创建 SA 时系统会自动生成一个对应的 SecretToken所以 SECRETS 会显示1。 所以旧版本创建pod会同时生成默认的sa和secret新版v1.24 起系统不再自动创建 Secret Token。改为按需通过 TokenRequest API 动态生成短期 Token3.3 yaml 资源文件 自定义 Service Account# test-sa.yamlapiVersion: v1 kind: ServiceAccount metadata: name: test-yaml namespace: default# 可省略默认为 default# 应用创建kubectl apply-ftest-sa.yaml# 查看对比之前用命令行创建的 test两者效果完全一样kubectl get sa test-yaml3.3 进阶版 YAML SA在 YAML 中可以配置命令行 kubectl create sa 无法直接指定的参数# test-sa-advanced.yamlapiVersion: v1 kind: ServiceAccount metadata: name: test-advanced namespace: default labels: app: my-monitor# 打上标签便于筛选# 1. 控制是否自动挂载 Token 到 Podv1.24 默认不挂载此处需要显式配置automountServiceAccountToken:true# 2. 关联镜像拉取凭证如果 Pod 需要用这个 SA 拉取私有仓库镜像imagePullSecrets: - name: my-registry-secret# 需提前创建好的 docker-registry SecretautomountServiceAccountToken设为 true 时使用该 SA 的 Pod 会自动挂载 Token 到 /var/run/secrets/kubernetes.io/serviceaccount/token设为 false 则可禁用进一步收紧权限满足安全合规要求。imagePullSecrets这相当于给该 SA 绑定了“免密拉取私有镜像”的权限。Pod 只要指定了这个 SA就不用在 Pod Spec 里重复写 imagePullSecrets 了非常省事四、RBAC 授权机制给sa授权基本分为三步创建sa创建role定义了一张权限清单用一种绑定方式把role绑定到sa把“第一步的身份SA”和“第二步的权限Role”粘合在一起并指定这个权限在哪个命名空间生效但是创建Role这个步骤是可以省略的因为K8s内置了4 个非常通用的 ClusterRoleview, edit, admin, cluster-admin4.1 RBAC 概述**RBAC基于角色的访问控制**是 Kubernetes 中最核心、最主流的授权Authorization机制。它通过定义角色和绑定关系将操作权限授予给特定的用户或服务账户。核心逻辑谁Subject对什么资源Resource有什么操作权限Verb。4.2 RBAC 的四个 API 对象Kubernetes 的 RBAC 通过以下 4 个 API 对象来实现权限控制类型对象名称作用范围作用描述角色定义Role命名空间定义在某个特定命名空间内可以操作哪些资源如 Pods、Services角色定义ClusterRole集群定义整个集群范围内的权限或跨所有命名空间的公共权限也可用于定义非资源权限如/healthz角色绑定RoleBinding命名空间将Role或ClusterRole的权限授予特定用户作用域限定在该命名空间内角色绑定ClusterRoleBinding集群将ClusterRole的权限授予特定用户作用域在整个集群级别包括所有命名空间角色Role相当于规则/权限清单What角色绑定Binding相当于指定这个规则/权限的作用域WhoWhere角色权限对绑定的对象如sa组等没有限制但权限作用域对对象有限制此外角色权限的最终作用范围与作用域角色绑定相关注意命名空间级别的role权限不能授予集群级别的作用域ClusterRoleBinding权限授予逻辑Service Account 通过RoleBinding与Role绑定 → 实现对某个命名空间的访问权限Service Account 通过ClusterRoleBinding与ClusterRole绑定 → 实现对整个集群的访问权限一个 ServiceAccount 可以同时绑定多个 RoleBindings 和 ClusterRoleBindings也就是说**一个对象可以在不冲突的情况下绑定多个角色权限和作用域并且这些权限和作用域是累加的**是纯并集UNIONServiceAccount 的权限 它身上挂载的所有 RoleBinding 和 ClusterRoleBinding 所授予权限的“大合集”并集它的规则Role/ClusterRole有多大权限就多大它的绑定RoleBinding/ClusterRoleBinding作用域有多宽权限就能覆盖多宽4.3 Role的动作什么是动作简单说是这个Role被允许执行的动作被允许做的事在 Kubernetes RBAC 中角色的“动作”被称为verbs动词。它们定义了可以对资源执行的具体操作类型。最常用的核心动词如下动词 (Verb)说明类比get获取一个特定资源的详细信息。查看某个 Pod 的详情 (kubectl describe pod my-pod)list获取一类资源的列表。查看所有 Pod (kubectl get pods)watch持续监听资源的变更事件。实时监控 Pod 状态变化 (kubectl get pods -w)create创建新的资源。创建一个 Deployment (kubectl create deployment)update全量更新一个资源。修改整个 YAML 文件并应用patch部分更新一个资源。只修改镜像版本 (kubectl patch)delete删除一个资源。删除一个 Pod (kubectl delete pod my-pod)deletecollection批量删除一类资源。删除所有 Pod (kubectl delete pods --all)这些动词一起使用时是并列的或OR关系如何使用这些动词在定义 Role 或 ClusterRole 时通过verbs字段来指定动作列表。示例创建一个只读角色下面的角色定义了针对 Pod 的只读权限rules:-apiGroups:[]resources:[pods]verbs:[get,list,watch]# 只允许查看不允许创建、修改或删除特别说明通配符*代表所有动作通常在极少数需要授予完整管理员权限的场景下使用。动词与操作并非一一对应一个kubectl命令可能对应多个动词。例如kubectl scale实际上是对deployments/scale子资源执行了update动作。如何查询完整列表最权威的方法是通过命令kubectl api-resources -o wide查看输出结果中的VERBS列明确列出了该资源支持的所有动作。4.4 Role角色定义Role 就是定义在特定命名空间的权限。查看role的字段[roothd1 ~]# kubectl explain role......FIELDS: apiVersionstringkindstringmetadataObjectrules[]Object示例定义一个用于读取 Pod 的 Role[roothd1 ~]# vim role_read.yamlapiVersion:rbac.authorization.k8s.io/v1kind:Rolemetadata:namespace:defaultname:pod-readrules:#定义规则/权限-apiGroups:[]# API 组 表示核心 API 组resources:[pods]# 资源对象列表resourceNames:[]# 指定操作的资源名称空表示所有verbs:[get,watch,list]# 动作操作方法列表#创建role[roothd1 ~]# kubectl apply -f role_read.yaml#查看[roothd1 ~]# kubectl describe role pod-readName: pod-read Labels:noneAnnotations:nonePolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- pods[][][getwatchlist]rules字段参数说明字段说明apiGroups指定允许操作的API 组列表表示核心 API 组*代表所有 API 组resources指定允许操作的资源对象类型列表如pods、deployments、jobs等resourceNames指定操作资源的具体名称为空或者不写该字段表示所有资源verbs对资源对象的操作方法列表如get、list、create、update、delete、watch等查看集群所有资源及其对应的 API 版本版本只有v1 的就是核心API组的资源[rooth1 ~]# kubectl api-resourcesNAME SHORTNAMES APIVERSION NAMESPACED KIND componentstatuses cs v1falseComponentStatus configmaps cm v1trueConfigMap endpoints ep v1trueEndpoints events ev v1trueEvent daemonsets ds apps/v1trueDaemonSet deployments deploy apps/v1trueDeployment replicasets rs apps/v1trueReplicaSet statefulsets sts apps/v1trueStatefulSet4.5 ClusterRole集群角色定义ClusterRole 用于定义整个集群范围内的权限或跨所有命名空间的公共权限。示例定义一个可访问任意 Secrets 的集群角色[roothd1 ~]# vim clusterrole_secrets.yamlapiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:name:secrets-clusterrolerules:-apiGroups:[]resources:[secrets]#支持的资源类型为secretverbs:[get,watch,list][roothd1 ~]# kubectl apply -f clusterrole_secrets.yaml4.6 RoleBinding角色绑定RoleBinding 用于将Role或ClusterRole的权限授予特定的用户、组或Service Accountsa居多作用域限定在某个命名空间内。示例将pod-readRole 绑定到testService Account[roothd1 ~]# vim pod-read-bind.yamlapiVersion:rbac.authorization.k8s.io/v1kind:RoleBindingmetadata:name:pod-read-bindnamespace:defaultsubjects:#授权的目标对象-kind:ServiceAccount#授权的目标是SA账号name:test# 已创建的 Service AccountroleRef:#心部分授予什么权限kind:Role# 引用的角色类型Role命名空间级name:pod-read# 已创建的 RoleapiGroup:rbac.authorization.k8s.io# 被引用角色的 API 组固定写法因为 Role 属于此 API 组[roothd1 ~]# kubectl apply -f pod-read-bind.yaml#查看详细信息[roothd1 ~]# kubectl describe RoleBindingName: pod-read-bind Labels:noneAnnotations:noneRole:#角色的类型和名字Kind: Role Name: pod-read Subjects:#这里是我们绑定对象的类型和名字命名空间。没有指定命名空间就是默认命名空间Kind Name Namespace ---- ---- --------- ServiceAccounttest通过上述 RoleBindingtestService Account 获得了在default命名空间中读取 Pod 的权限。4.7 ClusterRoleBinding集群角色绑定ClusterRoleBinding 用于将ClusterRole的权限授予特定的用户、组或 Service Account作用域在整个集群级别。示例允许manager组的用户读取所有命名空间的 Secrets[roothd1 ~]# vim ClusterRoleBinding.yamlapiVersion:rbac.authorization.k8s.io/v1kind:ClusterRoleBinding# 资源类型集群角色绑定集群范围不局限于某个命名空间metadata:name:read-secret-global# 当前绑定对象的名称subjects:-kind:Groupname:manager# 用户组的组名apiGroup:rbac.authorization.k8s.io# 固定写法指定 RBAC 的 API 组# ⚠️ 注意这里没有 namespace 字段因为 Group用户组是集群级别的概念不属于任何命名空间roleRef:kind:ClusterRole# 引用的角色类型ClusterRole集群级name:secrets-clusterrole# 已创建的 ClusterRoleapiGroup:rbac.authorization.k8s.io集群的概念要比命名空间大或者说集群包含了命名空间。因此只有在给集群角色绑定命名空间级别作用域或者给命名空间级别的角色绑定命名空间级别作用域才需要指定命名空间namespace 字段给集群角色绑定集群级别作用域是不需要指定命名空间的[roothd1 ~]# kubectl apply -f ClusterRoleBinding.yaml#查看绑定详细信息[roothd1 ~]# kubectl describe ClusterRoleBinding read-secret-globalName: read-secret-global Labels:noneAnnotations:noneRole: Kind: ClusterRole Name: secrets-clusterrole Subjects: Kind Name Namespace ---- ---- --------- Group manager五、RBAC 授权实战5.1 步骤概览创建 Service AccountSA对 SA 进行授权RoleBinding将 SA 注入到 Pod 中验证权限5.2 详细操作步骤步骤1创建 Service Account[rooth1 ~]# kubectl create sa pod-reader-sc步骤2对 SA 进行授权创建 RoleBinding[rooth1 ~]# kubectl create rolebinding bing-pod-reader \--clusterroleview\--serviceaccountdefault:pod-reader-sc\--namespacedefault命令解析参数说明create rolebinding创建角色绑定bing-pod-reader绑定名称--clusterroleview绑定的 ClusterRole 为view是k8s内置的只读角色--serviceaccountdefault:pod-reader-sc绑定的 Service Accountnamespace:name--namespacedefault作用域为default命名空间或者用yaml实现[roothd1 ~]# vim rb_bing-pod-reader.yamlapiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: bing-pod-reader# RoleBinding的名称namespace: default# 命名空间# ---------- 核心授予给谁主体 ----------subjects: - kind: ServiceAccount name: pod-reader-sc# 对应 --serviceaccountdefault:pod-reader-sc 中的名字namespace: default# ⚠️ 这里必须显式写明对应 SA 所在命名空间命令中用 default: 前缀指定# ---------- 核心授予什么权限角色引用 ----------roleRef: kind: ClusterRole# ⚠️ 这里虽然是 ClusterRole但因为是 RoleBinding权限会被限制在 metadata.namespacedefault内name: view# 角色名为view是一个k8s内置的角色apiGroup: rbac.authorization.k8s.io#查看授权信息[roothd1 ~]# kubectl describe RoleBinding bing-pod-readerName: bing-pod-reader Labels:noneAnnotations:noneRole: Kind: ClusterRole#role权限类型为集群权限Name: view Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount pod-reader-sc default步骤3将 SA 注入到 Pod 中[rooth1 ~]# cat pod-with-sa.yamlapiVersion:v1kind:Podmetadata:name:nginxnamespace:defaultspec:serviceAccountName:pod-reader-sc# 指定 ServiceAccountcontainers:-name:nginximage:docker.io/library/nginx:latestimagePullPolicy:IfNotPresentports:-containerPort:80[rooth1 ~]# kubectl apply -f pod-with-sa.yaml步骤4查看权限# 通过 RoleBinding 查看 SA 对应的角色[roothd1 ~]# kubectl get rolebinding -o wideNAME ROLE AGE USERSGROUPSSERVICEACCOUNTS bing-pod-reader ClusterRole/view 52m default/pod-reader-sc# 查看角色对应的详细权限[rooth1 ~]# kubectl get clusterrole view -o yaml5.3 内置 ClusterRole 说明ClusterRole说明适用场景view只读权限可查看大多数资源不含 Secret普通用户/应用查看资源edit读写权限可修改大多数资源不含 RBAC开发者/应用管理资源admin管理员权限可在命名空间内完全控制不含 RBAC命名空间管理员cluster-admin超级管理员权限可控制整个集群集群管理员六、核心知识点速查安全管理三阶段阶段核心问题失败返回码作用认证Authentication“你是谁”HTTP 401验证客户端身份授权Authorization“你能做什么”HTTP 403决定是否有操作权限准入控制Admission Control“请求是否合规”HTTP 403修改或验证请求RBAC 四个 API 对象对象作用作用范围Role定义权限规则命名空间ClusterRole定义权限规则集群RoleBinding将角色授予用户/SA命名空间ClusterRoleBinding将角色授予用户/SA集群关键注意事项注意点说明认证失败返回 HTTP 401请求直接终止授权失败返回 HTTP 403不进入准入控制阶段准入控制仅拦截修改请求创建、删除、更新不影响读请求默认 Service Account权限极低仅能访问自身 Pod 信息自定义 Service Account需结合 RBAC 授予权限才能调用 API
返回列表