- kubernetes学习系列快捷链接
- Kubernetes架构原则和对象设计(一)
- Kubernetes架构原则和对象设计(二)
- Kubernetes架构原则和对象设计(三)
- Kubernetes控制平面组件:etcd(一)
- Kubernetes控制平面组件:etcd(二)
- Kubernetes控制平面组件:etcd常用配置参数
- Kubernetes控制平面组件:etcd高可用集群搭建
- Kubernetes控制平面组件:etcd高可用解决方案
- Kubernetes控制平面组件:Kubernetes如何使用etcd
- Kubernetes控制平面组件:API Server详解(一)
- Kubernetes控制平面组件:APIServer 基于 X509 证书的认证机制
- Kubernetes控制平面组件:APIServer 基于 静态Token 的认证机制
- Kubernetes控制平面组件:APIServer 基于 引导Token 的认证机制
- Kubernetes控制平面组件:APIServer 基于 ServiceAccount 的认证机制
- Kubernetes控制平面组件:APIServer 基于 OpenID 的认证机制详解
- Kubernetes控制平面组件:APIServer 基于 Webhook Toeken令牌 的认证机制详解
- Kubernetes控制平面组件:APIServer 基于匿名请求的认证机制详解
- kubectl 和 kubeconfig 基本原理
- kubeadm 升级 k8s集群 1.17到1.20
- Kubernetes常见问题解答
- 查看云机器的一些常用配置
本文主要对kubernetes的控制面组件API Server进行介绍,首先总览了API Server的整个处理流程,然后对 请求超时限制、authentication认证、audit审计日志、impersonation模拟用户 模块分别进行了详细介绍
1.API Server介绍
- API Server的定位:
- 一个标准的REST服务,作为Kubernetes 控制面的 API 网关
- 核心职责:接收请求 → 转发到 etcd → 返回响应
- 通信枢纽特性:所有 Kubernetes 组件通过 API Server 交互(组件间不直连),API Server是唯一与ETCD交互的组件
- API Server的功能:
- 认证
- 鉴权
- 准入
- Mutating
- Validating
- Admission
- 限流
2.API Server 处理流程概览
2.1.API Server请求处理链
2.2.API Server处理流程概览
- HTTP Handler:每一个HTTP Server都会有http handler,为不同对象指定不同的处理函数
- 认证鉴权
- Mutating Admission:可以对请求对象做一些变形(修改)操作,并且允许挂载外部Mutating webhook插件
- 对象 Schema 校验:Kubernetes 内嵌的一些校验逻辑,保证对象是有效的
- Validating Admission:对请求对象做校验,并且允许挂载外部Validating webhook插件。注意此时已经不能再修改对象了
- Persisted to etcd:将对象持久化到etcd
2.3.API Server处理流程细节【重要】
- request-timeout:request进来,会先去做request-timeout
- authenatication:进行身份认证
- audit:认证通过后会进行 审计日志 Audit 的记录,主要是记录什么人做了什么修改操作,方便在出问题时定位请求的来源,比如对象被删时可以用来定责
- impersonation:用于模拟用户身份的字段
- 在request-header中有一个impersonation header,可以指定该值来模拟用户身份。
- 比如a用户发起的一个请求,但是它可以通过 impersonation header 把这个请求模拟成b用户,Kubernetes会把该请求认为是b用户,即a用户代替b用户来做操作,且后续的鉴权将会按照b用户进行
- 一个不太常用的功能
- max-in-flight:用于做限流(正在飞的请求–正在运行的请求)
- 可以配置 允许API Server同时处理多少请求,即允许有多少尚未返回的请求
- authorization:鉴权
- kubernetes aggregator:扩展API Server处理器
- Kubernetes为 内置资源提供了 默认的 API Server处理器,可以处理pod、deployment等内置资源
- 但如果你希望自己来处理资源,也可以自己编写一个API Server处理器,挂载上来
- 那么在kubernetes aggregator这里,就会判断使用哪个处理器,进而往下走
- resource handler
- kubernetes内置apiserver处理器的核心逻辑,包括解码、准入、校验、和etcd交互
以上就是一个请求在apiserver的完整处理流程,下面一个一个讲解
3.request-timeout请求超时时间
3.1.request-timeout介绍
request-timeout
是 Kubernetes API Server 中的一个重要配置参数,用于控制 API Server 处理单个请求的最大时间。如果请求处理时间超过该值,API Server 会终止请求并返回超时错误。- 作用
- 防止长时间运行的请求占用资源:通过设置超时时间,API Server 可以避免因某些请求长时间运行而耗尽资源,影响其他请求的处理。
- 提高系统稳定性:超时机制有助于防止因某些请求卡住而导致的系统不稳定。
- 默认值
- 默认情况下,
request-timeout
设置为 60 秒。
- 默认情况下,
- 配置方式
- 该参数可以通过 API Server 的启动参数
--request-timeout
进行配置。例如:# 这将把请求超时时间设置为 30 秒 kube-apiserver --request-timeout=30s
- 该参数可以通过 API Server 的启动参数
- 适用场景
- 长时间运行的请求:如某些复杂的查询或大规模资源操作。
- 资源密集型操作:如大规模数据导出或复杂计算。
- 注意事项
- 合理设置:超时时间过短可能导致正常请求被中断,过长则可能影响系统性能。
- 客户端重试:客户端应具备重试机制,以应对可能的超时错误。
3.2.示例
- 假设 API Server 配置为:
kube-apiserver --request-timeout=30s
- 如果一个请求处理时间超过 30 秒,API Server 将终止该请求并返回类似以下的错误:
{ "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "request did not complete within requested timeout 30s", "reason": "Timeout", "details": {}, "code": 504 }
4.authenatication认证
4.1.API Server提供了哪些认证方式?
- 一般提到认证,最常见的就是 username+password 的认证方式,还有为每个用户分配token的认证方式,如JWT Token等
- API Server 也提供了多种认证插件,并支持同时开启多个插件。只需要其中一个认证通过即可
4.2.API Server提供了认证方式详解
- Kubernetes控制平面组件:APIServer 基于 X509 证书的认证机制
- Kubernetes控制平面组件:APIServer 基于 静态Token 的认证机制
- Kubernetes控制平面组件:APIServer 基于 引导Token 的认证机制
- Kubernetes控制平面组件:APIServer 基于 ServiceAccount 的认证机制
- Kubernetes控制平面组件:APIServer 基于 OpenID 的认证机制详解
- Kubernetes控制平面组件:APIServer 基于 Webhook Toeken令牌 的认证机制详解
- Kubernetes控制平面组件:APIServer 基于匿名请求的认证机制详解
- 注:静态密码文件的认证方式,类似于静态Token方式,不做赘述
4.3.Keystone认证故障引发Kubernetes集群环境雪崩
下面记录一次企业级生产环境故障:Keystone认证故障引发Kubernetes集群环境雪崩,为我们更好的设计系统提供经验
4.3.1.故障背景
- 场景描述:
- 某企业 Kubernetes 集群使用 Keystone(OpenStack 的身份认证服务)作为 API Server 的认证插件。
- 当 Keystone 发生故障时,Kubernetes 集群的认证模块出现连锁反应,最终导致 Keystone 服务完全不可恢复,引发生产环境雪崩效应。
4.3.2.故障发生原因分析
以下是故障链路的逐步拆解:
-
Keystone 作为关键依赖
- Kubernetes 集群配置依赖 Keystone 完成用户和服务账户的 Token 认证。
- 问题:Keystone 是企业级关键服务,但其高可用性或容错能力不足,单点故障风险未消除。
-
Keystone 故障触发 401 错误
- 当 Keystone 服务不可用时,Kubernetes API Server 无法验证请求的 Token 有效性,返回 401 Unauthorized 错误。
- 问题:API Server 未对认证服务不可用的情况做降级处理,直接依赖 Keystone 的实时响应。
-
Controller 的重试逻辑加剧问题
- Kubernetes 的 Controller(如 kube-controller-manager、kubelet)在收到 401 错误后,会尝试重新获取 Token。
- 指数退避(Exponential Backoff)失效:
- 大多数 Controller 实现了指数退避(重试间隔逐渐变长),但 gophercloud(OpenStack Go SDK)在处理过期 Token 时未遵循退避策略,持续高频重试。
- 后果:大量重试请求涌入 Keystone,导致其负载激增,无法恢复。
-
请求积压与雪崩效应
- Keystone 因过载无法处理请求,Kubernetes 的持续重试进一步加剧其负载。
- 恶性循环:Keystone 无法恢复 → 更多 401 错误 → 更多重试 → Keystone 彻底崩溃。
4.3.3.根本原因总结
阶段 | 关键问题 |
---|---|
认证依赖 | Keystone 单点故障,缺乏熔断或降级机制。 |
重试策略 | gophercloud 未实现指数退避,导致重试风暴。 |
流量控制 | 缺乏对 Keystone 请求的限流保护。 |
系统设计 | Kubernetes 认证模块与 Keystone 强耦合,未考虑认证服务不可用的场景。 |
4.3.4.改进措施
4.3.4.1.熔断机制(Circuit Break)
-
目标:防止重试请求压垮 Keystone。
-
实现方式:
- 在 Kubernetes API Server 或客户端(如 gophercloud)中集成熔断器(如 Netflix Hystrix 或 Go 语言的
gobreaker
)。 - 熔断规则:
- 当连续 N 次认证失败时,触发熔断,暂停向 Keystone 发送请求。
- 熔断期间,直接返回缓存结果或错误(如 503 Service Unavailable),避免重试。
- 熔断恢复后,逐步试探性放行请求。
- 在 Kubernetes API Server 或客户端(如 gophercloud)中集成熔断器(如 Netflix Hystrix 或 Go 语言的
-
示例配置(伪代码):
// 使用 gobreaker 实现熔断 var circuitBreaker = gobreaker.NewCircuitBreaker(gobreaker.Settings{ Name: "keystone-auth", Timeout: 30 * time.Second, // 熔断持续时间 ReadyToTrip: func(counts gobreaker.Counts) bool { return counts.ConsecutiveFailures > 5 // 连续5次失败触发熔断 }, })
4.3.4.2.限流策略(Rate Limit)
-
目标:控制发送到 Keystone 的请求速率。
-
实现方式:
- 客户端限流:在 gophercloud 中为每个客户端配置请求速率限制(如令牌桶算法)。
- 服务端限流:在 Keystone 入口部署限流网关(如 Nginx、Envoy),限制每个客户端的 QPS。
- 动态调整:根据 Keystone 的健康状态(如响应延迟、错误率)动态调整限流阈值。
-
示例配置(Nginx 限流):
http { limit_req_zone $binary_remote_addr zone=keystone_limit:10m rate=100r/s; server { location /v3/auth/tokens { limit_req zone=keystone_limit burst=200; proxy_pass http://keystone-server; } } }
4.3.4.3.优化重试策略
- 目标:避免无效重试,遵循退避原则。
- 实现方式:
- 强制所有客户端(包括 gophercloud)实现指数退避 + 随机抖动(Jitter)。
- 在 Kubernetes Controller 配置中显式定义重试策略:
# kube-controller-manager 配置示例 --retry-backoff-duration=5s # 初始重试间隔 --retry-backoff-factor=2 # 指数因子 --retry-backoff-steps=5 # 最大重试次数
4.3.4.4.认证模块降级与缓存
- 目标:在 Keystone 不可用时提供有限服务。
- 实现方式:
- 短期 Token 缓存:在 API Server 本地缓存已认证的 Token,允许短期内的请求绕过 Keystone 验证。
- 只读模式降级:当 Keystone 不可用时,允许只读请求(如
GET
、LIST
)继续执行,拒绝写操作。
4.3.4.5.健康检查与主动切换
- 目标:快速检测 Keystone 状态并切换备用方案。
- 实现方式:
- 在 API Server 中增加 Keystone 健康检查探针,定期检测其可用性。
- 配置多认证插件(如 OIDC、静态 Token),当 Keystone 不可用时自动切换备用认证源。
4.3.4.6.监控与告警
- 目标:提前发现潜在风险。
- 关键监控指标:
- Keystone 的请求延迟、错误率、队列深度。
- Kubernetes API Server 的 401 错误率。
- 客户端重试次数与频率。
- 告警规则:
- 当 Keystone 错误率 > 5% 持续 1 分钟,触发 PagerDuty 告警。
- 当 API Server 401 错误数突增,通知运维团队介入。
4.3.5.架构级改进建议、
-
Keystone 高可用部署
- 部署多副本 Keystone,使用负载均衡器分发请求。
- 使用数据库集群(如 Galera)和缓存(如 Redis)提升 Keystone 的容错能力。
-
服务网格集成
- 引入 Istio 或 Linkerd,通过服务网格实现自动熔断、限流和重试策略,降低代码侵入性。
-
混沌工程验证
- 定期模拟 Keystone 故障,测试熔断、限流和降级策略的有效性。
4.3.6.总结
本次故障的根本原因在于 认证服务的强依赖性与客户端的无效重试策略,导致局部故障扩散为全局雪崩。通过熔断、限流、重试优化和架构改造,可显著提升系统的韧性。建议企业结合自身基础设施,逐步实施上述改进措施,并定期进行故障演练,确保防护机制的有效性。
5.audit审计日志模块
5.1.audit审计日志简介
审计日志(Audit Log) 是 Kubernetes API Server 的核心安全组件,用于记录所有对 API Server 的请求和响应细节。其核心目标是:
- 追踪操作:记录谁(用户/服务账号)在何时通过何种方式(HTTP 请求)操作了哪些资源。
- 安全合规:满足 GDPR、HIPAA、SOC2 等合规性要求,提供操作追溯能力。
- 故障诊断:帮助定位异常请求、权限问题或系统故障。
5.2.audit审计日志设计原理
审计日志的设计围绕 事件驱动模型 和 可扩展后端 展开:
5.2.1.核心流程
- 请求拦截:API Server 在处理请求前,拦截所有 HTTP 请求。
- 策略匹配:根据预定义的 审计策略(Audit Policy),决定是否记录该请求。
- 事件生成:对匹配策略的请求,生成结构化审计事件(Audit Event)。
- 后端处理:将事件发送到配置的后端(如文件、Webhook、日志系统)。
5.2.2.分层过滤机制
- 阶段(Stage):定义事件记录的时机,分为:
RequestReceived
:接收到请求时。ResponseStarted
:发送响应头时(适用于 Watch 等长连接)。ResponseComplete
:响应完成时。Panic
:处理请求时发生崩溃。
- 级别(Level):控制日志详细程度:
None
:不记录。Metadata
:记录请求元数据(用户、资源、操作等),不记录请求/响应体。Request
:记录元数据 + 请求体。RequestResponse
:记录元数据 + 请求体 + 响应体。
5.2.3.异步处理
- 审计日志记录采用 异步队列 机制,避免阻塞 API Server 主流程。
- 高负载时,可通过队列大小和批处理配置平衡性能与可靠性。
5.2.4.使用场景
- 安全审计
- 检测未授权访问(如 ServiceAccount 滥用)。
- 追踪敏感操作(如
kubectl delete
、Secret 读取)。
- 合规性报告
- 生成操作记录报表,证明符合监管要求。
- 故障排查
- 分析 API 请求延迟、错误率突增等问题。
- 行为分析
- 结合机器学习,识别异常操作模式(如暴力破解、横向移动)。
5.3.API Server 审计日志配置参数
Kubernetes API Server 提供了丰富的审计参数,用于控制审计日志的记录方式、存储策略、性能调优等。以下是核心参数及其配置说明
5.3.1.基础参数
5.3.1.1.审计策略文件
- 参数:
--audit-policy-file
作用:指定审计策略文件路径(YAML 格式)。
示例:# 启动参数示例 --audit-policy-file=/etc/kubernetes/audit-policy.yaml
5.3.1.2.审计日志后端
- 参数:
--audit-log-*
作用:配置日志文件后端的存储行为。
核心参数:--audit-log-path
:审计日志文件路径(默认不启用)。- 示例:
--audit-log-path=/var/log/kubernetes/audit.log
- 特殊值:设置为
-
表示输出到标准输出(stdout)。
- 示例:
--audit-log-maxage
:保留旧日志文件的最大天数(按文件名时间戳)。- 示例:
--audit-log-maxage=30
(保留 30 天)。
- 示例:
--audit-log-maxbackup
:保留的旧日志文件最大数量。- 示例:
--audit-log-maxbackup=10
(保留 10 个备份文件)。
- 示例:
--audit-log-maxsize
:单个日志文件的最大大小(MB),超过则轮转。- 示例:
--audit-log-maxsize=100
(100 MB)。
- 示例:
--audit-log-format
:日志格式,支持json
或legacy
。- 示例:
--audit-log-format=json
(默认值)。
- 示例:
5.3.2.Webhook 后端参数
- 参数:
--audit-webhook-*
作用:将审计事件发送到远程 HTTP 服务(如日志聚合系统)。
核心参数:--audit-webhook-config-file
:Webhook 配置文件路径(定义远程服务地址和 TLS 设置)。- 配置文件示例:
apiVersion: v1 kind: Config clusters: - name: audit-webhook cluster: server: https://audit-collector:8080/ certificate-authority: /path/to/ca.pem contexts: - context: cluster: audit-webhook user: "" name: default current-context: default
- 配置文件示例:
--audit-webhook-mode
:Webhook 发送模式:batch
:异步批量发送(默认,性能优先)。blocking
:同步发送(确保日志不丢失,但可能阻塞 API Server)。blocking-strict
:严格同步模式(更严格的错误处理)。- 示例:
--audit-webhook-mode=batch
--audit-webhook-batch-buffer-size
:内存队列中暂存的事件数量上限(默认 10,000)。--audit-webhook-batch-max-size
:单次批量发送的最大事件数(默认 400)。--audit-webhook-batch-max-wait
:批量发送的最大等待时间(默认 30s)。
5.3.2.动态审计配置(Dynamic Audit)
- 参数:
--audit-dynamic-configuration
- 作用:启用动态审计策略(通过 API 更新策略,无需重启 API Server)。
- 依赖条件:
- 需启用
APIServer
的dynamicaudit
Feature Gate(旧版本中可能需要)。 - 需配置
AuditConfiguration
资源(Kubernetes 1.19+)。 - 示例:
# 启动参数 --feature-gates=DynamicAuditing=true # 旧版本(如 1.18)可能需要 --audit-dynamic-configuration
- 需启用
5.3.4.性能调优参数
-
日志后端性能
--audit-log-batch-buffer-size
:内存中缓存的审计事件数量(默认 10,000)。--audit-log-batch-max-size
:单次写入日志文件的最大事件数(默认 1,000)。--audit-log-batch-max-wait
:等待批量写入的最大时间(默认 30s)。--audit-log-batch-throttle-enable
:是否启用批量写入限流(默认true
)。--audit-log-batch-throttle-qps
:批量写入的 QPS 限制(默认 10)。
-
2. Webhook 后端性能
--audit-webhook-batch-throttle-enable
:是否启用批量发送限流(默认true
)。--audit-webhook-batch-throttle-qps
:批量发送的 QPS 限制(默认 10)。
5.3.5.其他高级参数
--audit-truncate-enabled
:是否截断过大的请求/响应体(默认true
)。--audit-truncate-max-batch-size
:单个事件截断后的最大大小(默认 1MB)。--audit-truncate-max-event-size
:单个事件中请求/响应体的最大大小(默认 100KB)。
5.3.6.完整配置示例
# kube-apiserver.yaml 片段
spec:
containers:
- command:
- kube-apiserver
# 基础审计配置
- --audit-policy-file=/etc/kubernetes/audit-policy.yaml
- --audit-log-path=/var/log/kubernetes/audit.log
- --audit-log-maxage=30
- --audit-log-maxbackup=10
- --audit-log-maxsize=100
- --audit-log-format=json
# Webhook 配置
- --audit-webhook-config-file=/etc/kubernetes/audit-webhook-config.yaml
- --audit-webhook-mode=batch
- --audit-webhook-batch-max-size=500
# 性能调优
- --audit-log-batch-max-size=2000
- --audit-log-batch-max-wait=20s
# 动态审计(Kubernetes 1.19+)
- --audit-dynamic-configuration
volumeMounts:
- name: audit-policy
mountPath: /etc/kubernetes/audit-policy.yaml
- name: audit-webhook-config
mountPath: /etc/kubernetes/audit-webhook-config.yaml
- name: audit-log
mountPath: /var/log/kubernetes
volumes:
- name: audit-policy
hostPath:
path: /etc/kubernetes/audit-policy.yaml
- name: audit-webhook-config
hostPath:
path: /etc/kubernetes/audit-webhook-config.yaml
- name: audit-log
hostPath:
path: /var/log/kubernetes
5.3.7.注意事项
- 安全存储:确保审计日志文件权限为
600
,避免未授权访问。 - 性能影响:高频率的
RequestResponse
级别日志可能显著增加 I/O 压力。 - 网络可靠性:Webhook 后端需配置重试机制,防止网络抖动导致日志丢失。
- 动态配置兼容性:动态审计在 Kubernetes 1.19+ 后逐渐稳定,旧版本需谨慎使用。
5.4.数据结构
- 审计事件以 JSON 格式记录,核心字段如下:
{ "kind": "Event", "apiVersion": "audit.k8s.io/v1", "level": "RequestResponse", "auditID": "d1e3f5a0-9c7b-4a8d-9f0a-1b2c3d4e5f6g", "stage": "ResponseComplete", "requestURI": "/api/v1/namespaces/default/pods?watch=true", "verb": "watch", "user": { "username": "system:serviceaccount:kube-system:calico-node", "groups": ["system:serviceaccounts", "system:serviceaccounts:kube-system"] }, "sourceIPs": ["192.168.1.100"], "userAgent": "kubelet/v1.25.0 (linux/amd64) kubernetes/abcdef", "objectRef": { "resource": "pods", "namespace": "default", "name": "nginx-7d6877795c-abcde", "apiVersion": "v1" }, "responseStatus": { "metadata": {}, "code": 200 }, "requestObject": { ... }, // 请求体(如创建 Pod 的 YAML) "responseObject": { ... }, // 响应体(如返回的 Pod 状态) "requestReceivedTimestamp": "2023-10-01T12:34:56.789Z", "stageTimestamp": "2023-10-01T12:34:56.800Z" }
关键字段解析:
auditID
:唯一标识单个请求的审计事件链。verb
:操作类型(get
、list
、create
、delete
等)。objectRef
:操作的资源对象信息。sourceIPs
:客户端 IP,支持追踪 NAT 后的真实 IP。responseStatus.code
:HTTP 状态码(如 200、403、500)。
5.5.核心源码解析
审计日志的实现位于 Kubernetes 源码的 staging/src/k8s.io/apiserver/pkg/audit
包。
5.5.1.事件生成流程
// 拦截请求并生成审计事件
func WithAudit(handler http.Handler, sink AuditSink, policy PolicyRuleEvaluator) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
ctx := req.Context()
ae := policy.EvaluatePolicy(req) // 匹配审计策略
if ae == nil {
handler.ServeHTTP(w, req)
return
}
// 记录 RequestReceived 阶段事件
audit.ObserveEvent(ctx, ae, auditinternal.StageRequestReceived)
// 包装 ResponseWriter 以捕获响应
respWriter := audit.NewResponseWriter(w)
handler.ServeHTTP(respWriter, req)
// 记录 ResponseComplete 阶段事件
ae.ResponseStatus = &metav1.Status{Code: int32(respWriter.Status())}
audit.ObserveEvent(ctx, ae, auditinternal.StageResponseComplete)
})
}
5.5.2.审计策略匹配
策略文件示例:在apiserver的启动参数中指定 audit-policy 文件
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
users: ["system:anonymous"] # 记录匿名用户的操作
verbs: ["*"]
resources:
- group: ""
resources: ["secrets"]
- level: RequestResponse
namespaces: ["kube-system"] # 详细记录 kube-system 命名空间的操作
源码中的策略评估逻辑:
// staging/src/k8s.io/apiserver/pkg/audit/policy/checker.go
func (p *policyRuleEvaluator) EvaluatePolicyRule(req *http.Request) *auditinternal.Event {
for _, rule := range p.rules {
if rule.Matches(req) { // 匹配用户、资源、命名空间等条件
return createAuditEvent(rule.Level)
}
}
return nil
}
5.5.3.后端处理
支持多种后端,以 日志文件后端 为例:
// staging/src/k8s.io/apiserver/pkg/audit/backend/log/file.go
type backend struct {
writer io.Writer
format string // 输出格式(json、legacy)
}
func (b *backend) ProcessEvents(events ...*auditinternal.Event) {
for _, event := range events {
data := serializeEvent(event, b.format)
b.writer.Write(data) // 异步写入文件
}
}
5.6.高级特性与最佳实践
5.6.1.动态审计配置(Dynamic Audit Configuration)
- 特性:通过
AuditConfiguration
API 动态更新审计策略,无需重启 API Server。 - 使用场景:临时开启对某类资源的高级别日志记录。
5.6.2.Webhook 后端
- 配置示例:
apiVersion: audit.k8s.io/v1 kind: Policy ... webhooks: - clientConfig: url: "https://audit-collector:8080/" caBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCg==" mode: blocking # 同步模式(可能影响性能) throttle: qps: 10 burst: 15
- 注意事项:避免使用
blocking
模式在高负载场景下导致 API Server 延迟。
5.6.3.性能优化
- 批量写入:配置
--audit-batch-max-size
(默认 100)和--audit-batch-max-wait
(默认 30s)减少 I/O 开销。 - 过滤冗余事件:通过策略排除高频低价值操作(如
get
、list
)。
5.6.4.安全加固
- 日志脱敏:在策略中排除敏感字段(如 Secret 的
data
字段):- level: Request resources: - group: "" resources: ["secrets"] omitStages: ["RequestReceived"] omitManagedFields: true # 忽略 metadata.managedFields
- 加密存储:结合 KMS 对审计日志文件加密。
5.7.调试与工具
- 检查 API Server 日志:
kubectl logs -n kube-system kube-apiserver-<node-name> | grep audit
- 查看审计日志文件:
tail -f /var/log/kubernetes/audit.log | jq .
- 监控审计事件数量:
kubectl get --raw /metrics | grep apiserver_audit_event_total
6.impersonation模拟用户(不常用)
6.1.Impersonation 的核心作用
Impersonation(用户代理) 允许服务账户或用户临时模拟其他用户/组的身份发起请求。其核心目标是通过 RBAC 策略,实现细粒度的权限隔离,例如:
- 服务账户 A 需要以管理员身份创建资源。
- 某个用户需要临时以另一个用户的身份执行操作。
6.2.Impersonation 的工作原理
6.2.1.技术实现
Impersonation 通过 HTTP 请求头 实现,常见的头字段如下:
请求头 | 作用 |
---|---|
Impersonate-User | 指定要模拟的用户(如 user:default ) |
Impersonate-Group | 指定要模拟的用户组(如 group:readers ) |
Impersonate-ServiceAccount | 指定要模拟的服务账户(如 serviceaccount:default ) |
6.2.2.流程步骤
- 客户端发起请求:在请求头中附加 Impersonation 信息。
- API Server 解析头:提取
Impersonate-*
字段,验证其合法性。 - 绑定真实身份:将请求视为被模拟用户的身份处理。
- RBAC 验证:检查被模拟用户是否有对应操作的权限。
6.3.Impersonation 的实现细节
6.3.1.API Server 的拦截逻辑
API Server 在处理每个请求时,会执行以下步骤:
- 提取原始用户:通过认证(如 Token、Client Certificate)确定请求发起者的原始身份。
- 解析 Impersonation 头:从请求头中读取
Impersonate-*
字段。 - 合并身份:
- 如果存在
Impersonate-User
,则覆盖原始用户。 - 如果存在
Impersonate-Group
,则追加用户组。 - 如果存在
Impersonate-ServiceAccount
,则关联服务账户的权限。
- 如果存在
- 生成最终用户对象:构造包含模拟身份的
user.Info
对象,供后续 RBAC 验证使用。
- 核心代码片段(API Server 请求处理)
// pkg/apiserver/authenticator/request/header/header.go
func (h *HeaderAuthenticator) AuthenticateRequest(req *rest.Request) (*user.Info, error) {
// 步骤 1: 解析原始用户(通过 Token 或 Client Certificate)
originalUser, err := h.Authenticate(req)
if err != nil {
return nil, err
}
// 步骤 2: 解析 Impersonation 头
impersonatedUser := originalUser
if req.Header.Get("Impersonate-User") != "" {
impersonatedUser = &user.Info{
Username: req.Header.Get("Impersonate-User"),
Groups: originalUser.Groups,
}
}
if req.Header.Get("Impersonate-Group") != "" {
impersonatedUser.Groups = append(imcrementalGroups(originalUser.Groups, req.Header.Get("Impersonate-Group")),
}
// 类似处理 ServiceAccount...
// 步骤 3: 返回合并后的用户身份
return impersonatedUser, nil
}
6.3.2.用户身份合并规则
- 用户覆盖:
Impersonate-User
会覆盖原始用户。 - 组追加:
Impersonate-Group
会向用户组中添加新组(而非替换)。 - 服务账户优先级:若同时存在
Impersonate-User
和Impersonate-ServiceAccount
,优先使用Impersonate-User
。
6.4.配置与使用
6.4.1.启用 Impersonation
- Impersonation 功能默认开启,但需通过 RBAC 策略控制其使用范围。
- RBAC 策略示例
# 允许 serviceaccount:default 模拟用户 user=admin apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: impersonate-admin rules: - apiGroups: [""] resources: ["pods"] verbs: ["create"] subjects: - kind: ServiceAccount name: default namespace: default # 允许用户 user=admin 创建 Pod apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-binding subjects: - kind: User name: admin roleRef: kind: ClusterRole name: create-pods
6.4.2.客户端调用示例
-
使用
kubectl
# 以用户 user=admin 的身份创建 Pod kubectl create pod nginx --as=user=admin # 以服务账户 default 的身份创建 Pod kubectl create pod nginx --as=serviceaccount:default # 同时模拟用户和组 kubectl create pod nginx --as=user=admin,group=admin-group
-
通过 HTTP 请求头
curl -X POST -H "Authorization: Bearer <token>" \ -H "Impersonate-User: user=admin" \ -H "Impersonate-Group: group:readers" \ https://kubernetes.default.svc:443/api/v1/pods
6.5.使用场景:集群联邦
- 集群联邦:相当于为集群做了一个注册中心,多个集群将信息上报到一个联邦服务中。当然集群的证书信息也要上报的
- 但是集群联邦有风险,如果认证鉴权不完善,容易发生权限的泄漏。比如一个没有权限的用户,在集群联邦错误的获取了权限,就可以访问其中某个集群的一些无权限数据
- Impersonation:在集群联邦将请求下发到某个集群时,下边的集群可以通过Impersonation判定是否为模拟用户,进而调整鉴权策略,防止权限泄漏
7.常见问题解答
7.1.什么是 Kubernetes 的控制面和数据面
- 简单理解:所有运行在Kubernetes集群上的应用都是数据面,所有Kubernetes的组件都是控制面
7.2.不切换上下文时怎么使用不同User访问集群
- 使用–user参数
- 可以在kubeconfig中看到有多少种user,然后在kubectl命令中使用–user指定要使用哪个user身份访问集群
7.3.UserAccount、ServiceAccount的区别
- 简单理解:
- UserAccount:Kubernetes集群外部的用户
- ServiceAccount:Kubernetes集群内部的用户
- UserAccount 举例:
- 假设你搭建了一个Kubernetes集群,需要让公司内部所有的人都能登陆进来。但公司员工的信息都在另外一个独立的系统中存储,怎么进行认证呢?
- 可以使用 基于Webhook的认证机制,开发一个独立的 Webhook,负责将认证请求转发给第三方用户系统,并将认证结果返回给 API Server
- 那么这种来自外部的用户,都是UserAccount
- 在使用层面,UserAccount 的 RoleBinding / ClusterRoleBinding 中 subjects.kind 统一都是User
- ServiceAccount 举例:
- 假设你搭建了一个Kubernetes集群,集群内运行了很多个组件和pod,那么这些组件和pod都会有一个ServiceAccount身份,用于认证
- 比如新建一个namespace,默认会创建一个default的SA,并会自动挂载到pod中,这种来自内部的用户,都是ServiceAccount
- 在使用层面,ServiceAccount 的 RoleBinding / ClusterRoleBinding 中 subjects.kind 统一都是ServiceAccount