K8s详细学习笔记 第九章:K8s安全机制:认证、授权与准入控制
第九章:K8s安全机制:认证、授权与准入控制
随着Kubernetes成为云原生应用的事实标准,保障其安全性变得至关重要。一个配置不当的集群,如同一个门户大开的金库,不仅可能导致应用数据泄露,攻击者甚至可以利用其计算资源进行恶意活动,或者将其作为攻击内网其他系统的跳板。
Kubernetes的安全性是一个多层次的、纵深防御的体系。从物理基础设施到应用代码,每一层都需要被保护。本章将重点聚焦于集群本身的安全,特别是所有与集群交互的入口——Kubernetes API Server的安全机制。
对API Server的每一次请求,无论是来自kubectl命令,还是来自集群内部的某个Pod,都必须依次通过三道严格的安全关卡,才能被最终执行:
- 认证 (Authentication):验证请求者的身份,回答“你是谁?”。
- 授权 (Authorization):检查该身份是否有权限执行请求的操作,回答“你被允许做什么?”。
- 准入控制 (Admission Control):在请求被持久化到etcd之前,进行最后的审查、修改或拒绝,回答“这个请求是否合规?”。
理解这“三驾马车”的工作原理,是安全地设计、管理和运维Kubernetes集群的先决条件。
9.1 K8s安全概述:4C安全模型
为了更宏观地理解Kubernetes安全,社区提出了4C安全模型,它将云原生安全划分为四个层次,由内到外分别是:Code(代码)、Container(容器)、Cluster(集群)、Cloud/Corporate Data Center(云/企业数据中心)。
- Cloud / Corporate Data Center (云/企业数据中心层):这是最底层的基础设施安全。包括物理服务器的安全、数据中心的网络隔离、云服务商提供的身份认证(IAM)、虚拟网络(VPC)等。这一层的安全是后面所有层次的基石。
- Cluster (集群层):这是本章的重点。它关注的是Kubernetes集群自身的安全,主要分为两大块:
- 保护控制平面组件:确保API Server、etcd、Controller Manager、Scheduler之间的通信是加密和受信任的;严格限制对etcd的直接访问。
- 保护工作节点组件:确保Kubelet的安全,配置网络策略(Network Policies)来隔离Pod之间的网络流量。
- Container (容器层):关注容器镜像和运行时的安全。包括:
- 镜像安全:对容器镜像进行漏洞扫描,使用最小化的基础镜像,不使用来源不明的镜像。
- 运行时安全:遵循最小权限原则,禁止容器以root用户身份运行,使用安全上下文(Security Context)限制容器的能力,利用AppArmor、Seccomp等内核安全模块。
- Code (代码层):关注在容器内运行的应用程序本身的安全。包括安全的编码实践、处理好依赖库的漏洞、安全的API设计、加密处理敏感数据等。
这个模型的核心思想是**“层层设防,纵深防御”**。上一层的安全依赖于下一层的安全。即使某一层被攻破,其他层仍然可以作为防线,减缓或阻止攻击的蔓延。
9.2 认证(Authentication):确认“你是谁”
认证是API安全流程的第一步。当一个请求到达API Server时,API Server必须先确定请求者的身份。Kubernetes中有两种基本的用户类型:
-
普通用户 (Normal Users):
- 这类用户被认为是由外部、独立的服务管理的。例如,公司的LDAP、企业级的身份提供商(IdP)如Google、Okta,或者由管理员分发的客户端证书。
- Kubernetes本身没有用于表示普通用户的API对象。你无法通过
kubectl create user这样的命令来创建一个用户。
-
服务账户 (ServiceAccounts):
- 这类“用户”是由Kubernetes API管理的,专门供在Pod中运行的进程使用,以便它们可以与API Server进行通信。
- ServiceAccount是命名空间级别的资源。每个命名空间在创建时都会自动创建一个名为
default的ServiceAccount。 - 当Pod被创建时,如果没有指定ServiceAccount,它会自动使用所在命名空间的
defaultServiceAccount。 - Kubernetes会自动为ServiceAccount创建一个对应的Secret(在较新版本中是临时的Token),并将其以Token的形式挂载到Pod的
/var/run/secrets/kubernetes.io/serviceaccount/目录下,供Pod内的应用使用。
Kubernetes的认证策略
API Server可以同时启用一种或多种认证策略。它会按顺序逐一尝试,只要有一个策略成功认证了请求,认证阶段就通过了。常见的认证策略包括:
- X.509客户端证书:这是最常见的认证方式,尤其用于集群管理员和控制平面组件之间的通信。API Server通过启动时配置的CA证书来验证客户端证书的有效性。证书的Common Name (CN)字段被用作用户名,Organization (O)字段被用作该用户所属的用户组。
- 静态Token文件:管理员可以创建一个包含
token,user,uid,"group1,group2"格式的CSV文件,API Server启动时加载此文件。请求者在HTTP头的Authorization字段中提供Bearer <token>即可。这种方式简单但不灵活,修改后需要重启API Server。 - ServiceAccount Tokens:这是专门为ServiceAccount设计的认证方式。它使用签名的JWT (JSON Web Token)。Pod内的应用读取挂载的token文件,并将其包含在发往API Server的请求头中。API Server会验证这个JWT的签名和有效性。
- OpenID Connect (OIDC) Tokens:这是将Kubernetes与外部身份提供商(如Google, Auth0, Dex)集成的标准和推荐方式。用户首先在IdP上进行认证,获取一个ID Token,然后使用
kubectl时将此Token提供给API Server。API Server会与IdP通信以验证Token的有效性。这种方式使得企业可以利用现有的身份认证体系来统一管理K8s集群的用户。
9.3 授权(Authorization):判定“你能做什么”
一旦用户的身份被成功认证,授权模块就会介入,决定这个已认证的用户是否有权限执行其请求的操作。例如,用户dev-user(已认证)想要get pods在production命名空间中,授权模块会检查dev-user是否被授予了这样的权限。
与认证类似,API Server也可以配置多种授权模式,但目前社区的绝对标准和最佳实践是RBAC。
- RBAC (Role-Based Access Control):基于角色的访问控制。这是本章的重中之重。它通过将权限(Permissions)聚合到角色(Roles)中,再将角色绑定(Binding)到用户、用户组或ServiceAccount上,来实现精细化、可重用的权限管理。
【重难点】理解并掌握RBAC是保障集群安全的核心
RBAC通过四个核心的API对象来实现其强大的权限管理能力:Role、ClusterRole、RoleBinding、ClusterRoleBinding。
RBAC的四个构建基块:
-
Role (角色):
- 作用域:命名空间级别 (Namespaced)。
- 内容:包含了一组规则(rules),每条规则定义了一组可以对某些API资源执行的操作(verbs)。
- 简单来说:一个
Role就是一份在特定命名空间内的权限清单。
# pod-reader-role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default # 这个Role只在default命名空间内有效 name: pod-reader rules: - apiGroups: [""] # "" 表示核心API组 resources: ["pods"] verbs: ["get", "watch", "list"] # 允许对Pod进行读操作 -
ClusterRole (集群角色):
- 作用域:集群级别 (Cluster-scoped)。
- 内容:与
Role一样,也包含一组权限规则。 - 用途:
- 授予对集群级别的资源(如
nodes,persistentvolumes,clusterroles等)的访问权限。 - 授予对所有命名空间中的命名空间级别资源(如
pods)的访问权限。
- 授予对集群级别的资源(如
- 简单来说:一份在整个集群范围内都有效的权限清单。
# secret-reader-clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: # ClusterRole不需要namespace name: secret-reader rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"] -
RoleBinding (角色绑定):
- 作用域:命名空间级别。
- 作用:将一个
Role授予一个或多个主体(subjects)(用户、用户组或ServiceAccount)。 - 关键点:
RoleBinding只能引用在同一命名空间内的Role。 - 简单来说:在某个命名空间里,“把某张权限清单(Role)交给某个人(Subject)”。
# bind-pod-reader-role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: default # 绑定行为发生在default命名空间 subjects: - kind: User name: jane # 'jane'这个用户 apiGroup: rbac.authorization.k8s.io roleRef: # 引用要绑定的Role kind: Role name: pod-reader # 引用上面创建的pod-reader Role apiGroup: rbac.authorization.k8s.io执行这个绑定后,用户
jane就获得了在default命名空间中读取Pod的权限。 -
ClusterRoleBinding (集群角色绑定):
- 作用域:集群级别。
- 作用:将一个
ClusterRole授予一个或多个主体。 - 关键点:
ClusterRoleBinding授予的权限在所有命名空间以及集群级别都有效。 - 简单来说:在整个集群范围内,“把某张集群级权限清单(ClusterRole)交给某个人(Subject)”。
# bind-secret-reader-clusterrole.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: read-secrets-global subjects: - kind: Group name: managers # 'managers'这个用户组 apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader # 引用上面创建的secret-reader ClusterRole apiGroup: rbac.authorization.k8s.io执行这个绑定后,
managers用户组中的所有成员都获得了在集群所有命名空间中读取Secret的权限。这是一个非常高的权限,需要谨慎授予。
RBAC最佳实践与核心原则:
- 遵循最小权限原则:这是RBAC的黄金法则。永远只授予主体完成其任务所必需的最小权限。不要为了方便而授予
cluster-admin权限。 - 优先使用Role和RoleBinding:对于应用级的ServiceAccount,它们的活动范围通常只限定在自己的命名空间内。因此,应优先使用
Role和RoleBinding来限制其权限。只有在需要管理集群级资源或跨命名空间资源时,才考虑使用ClusterRole。 - 为应用创建专用的ServiceAccount:不要使用
defaultServiceAccount。为每个应用创建一个专用的ServiceAccount,并为其绑定一个精心设计的、权限最小化的Role。 - 避免使用通配符:在定义规则时,尽量避免在
resources或verbs中使用通配符["*"]。明确列出所需的资源和操作。 - 定期审计:定期审查集群中的
(Cluster)RoleBinding,检查是否存在权限过高或不再需要的主体,及时清理。
9.4 准入控制(Admission Control):API请求的最后一道防线
在请求通过认证和授权之后,但在被持久化到etcd之前,它会经过一个由准入控制器(Admission Controllers)组成的链条。准入控制器是一系列插件,它们可以对请求进行校验(Validating)或变更(Mutating)。
- 变更型准入控制器 (Mutating Admission Controllers):可以修改请求的对象。例如,自动为Pod注入一个Sidecar容器,或者为一个没有设置资源请求的Pod添加默认值。
- 校验型准入控制器 (Validating Admission Controllers):只能检查请求的对象,不能修改。如果检查不通过,就可以拒绝该请求。例如,强制要求所有Pod都必须设置资源限制(Limits)。
API Server会按预先定义的顺序依次调用这些控制器。如果链条中的任何一个控制器拒绝了请求,那么整个API请求都会失败。
一些重要的内置准入控制器:
NamespaceLifecycle: 防止在一个正在被删除的命名空间中创建新的对象。LimitRanger: 强制执行在LimitRange对象中定义的资源约束。ResourceQuota: 强制执行在ResourceQuota对象中定义的资源配额。DefaultStorageClass: 为没有指定storageClassName的PersistentVolumeClaim自动添加默认的存储类。
动态准入控制:Webhook
除了内置的控制器,Kubernetes还允许你通过Webhook来集成自定义的、外部的准入控制逻辑。
MutatingAdmissionWebhook: API Server会将请求对象发送给你自己部署的一个Web服务。你的服务可以修改这个对象,然后将其返回给API Server。ValidatingAdmissionWebhook: API Server将请求对象发送给你的Web服务,你的服务只需返回一个允许或拒绝的决定。
Webhook极大地扩展了Kubernetes的能力,使其可以集成各种企业级的安全策略和治理流程。例如:
- 校验策略:
- 强制所有容器镜像必须来自公司信任的镜像仓库。
- 禁止创建
hostPath类型的Volume。 - 要求所有Ingress对象的主机名必须以
.my-company.com结尾。
- 变更策略:
- 为所有Pod自动添加公司标准的标签(labels)和注解(annotations)。
- 自动注入用于日志收集或服务网格的Sidecar容器。
**OPA (Open Policy Agent)**是一个非常流行的开源项目,它经常与ValidatingAdmissionWebhook结合使用,以一种声明式的方式(使用Rego语言)来编写和强制执行复杂的安全策略。
总结:安全三部曲的协同工作
| 阶段 | 核心问题 | 实现机制 | 例子 |
|---|---|---|---|
| 1. 认证 | “你是谁?” | 客户端证书, ServiceAccount Token, OIDC Token… | API Server验证了请求来自用户jane。 |
| 2. 授权 (RBAC) | “你能做什么?” | Role, ClusterRole, RoleBinding, ClusterRoleBinding… | 检查发现jane通过一个RoleBinding被授予了在dev命名空间delete pods的权限。 |
| 3. 准入控制 | “这个请求合规吗?” | LimitRanger, ResourceQuota, Webhooks… | 一个Validating Webhook检查发现这个Pod使用了latest标签的镜像,根据公司策略,这不被允许,于是拒绝了该请求。 |
只有当一个API请求成功闯过这三道关卡,它才会被最终写入etcd,并触发后续的控制器逻辑。掌握这一流程,并能够熟练运用RBAC和准-入控制来实施最小权限原则和自定义安全策略,是成为一名合格的Kubernetes管理员或安全工程师的必备技能。
K8s 详细学习笔记 目录
以下是整个系列的10章目录,点击章节标题即可跳转阅读:
- K8s详细学习笔记 第一章:K8s入门与核心概念
- K8s详细学习笔记 第二章:部署你的第一个应用:Pod与Deployment
- K8s详细学习笔记 第三章:应用访问与服务发现:Service与Ingress
- K8s详细学习笔记 第四章:应用配置管理:ConfigMap与Secret
- K8s详细学习笔记 第五章:数据持久化:Volume与Persistent Storage
- K8s详细学习笔记 第六章:应用的健康检查与自愈能力
- K8s详细学习笔记 第七章:资源的限制与调度
- K8s详细学习笔记 第八章:应用的扩缩容与更新策略
- K8s详细学习笔记 第九章:K8s安全机制:认证、授权与准入控制
- K8s详细学习笔记 第十章:集群运维与故障排查
更多推荐
所有评论(0)