Kubernetes控制平面组件:API Server详解(一)

云原生学习路线导航页(持续更新中)

本文主要对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请求处理链

Request
认证
审计日志
鉴权
准入控制
限流
持久化到 etcd

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
      
  • 适用场景
    • 长时间运行的请求:如某些复杂的查询或大规模资源操作。
    • 资源密集型操作:如大规模数据导出或复杂计算。
  • 注意事项
    • 合理设置:超时时间过短可能导致正常请求被中断,过长则可能影响系统性能。
    • 客户端重试:客户端应具备重试机制,以应对可能的超时错误。

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提供了认证方式详解

4.3.Keystone认证故障引发Kubernetes集群环境雪崩

下面记录一次企业级生产环境故障:Keystone认证故障引发Kubernetes集群环境雪崩,为我们更好的设计系统提供经验

在这里插入图片描述

4.3.1.故障背景

  • 场景描述
    • 某企业 Kubernetes 集群使用 Keystone(OpenStack 的身份认证服务)作为 API Server 的认证插件。
    • 当 Keystone 发生故障时,Kubernetes 集群的认证模块出现连锁反应,最终导致 Keystone 服务完全不可恢复,引发生产环境雪崩效应。

4.3.2.故障发生原因分析

以下是故障链路的逐步拆解:

  1. Keystone 作为关键依赖

    • Kubernetes 集群配置依赖 Keystone 完成用户和服务账户的 Token 认证。
    • 问题:Keystone 是企业级关键服务,但其高可用性或容错能力不足,单点故障风险未消除。
  2. Keystone 故障触发 401 错误

    • 当 Keystone 服务不可用时,Kubernetes API Server 无法验证请求的 Token 有效性,返回 401 Unauthorized 错误。
    • 问题:API Server 未对认证服务不可用的情况做降级处理,直接依赖 Keystone 的实时响应。
  3. Controller 的重试逻辑加剧问题

    • Kubernetes 的 Controller(如 kube-controller-manager、kubelet)在收到 401 错误后,会尝试重新获取 Token。
    • 指数退避(Exponential Backoff)失效
      • 大多数 Controller 实现了指数退避(重试间隔逐渐变长),但 gophercloud(OpenStack Go SDK)在处理过期 Token 时未遵循退避策略,持续高频重试。
    • 后果:大量重试请求涌入 Keystone,导致其负载激增,无法恢复。
  4. 请求积压与雪崩效应

    • 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),避免重试。
      • 熔断恢复后,逐步试探性放行请求。
  • 示例配置(伪代码)

    // 使用 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 不可用时,允许只读请求(如 GETLIST)继续执行,拒绝写操作。
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.架构级改进建议、

  1. Keystone 高可用部署

    • 部署多副本 Keystone,使用负载均衡器分发请求。
    • 使用数据库集群(如 Galera)和缓存(如 Redis)提升 Keystone 的容错能力。
  2. 服务网格集成

    • 引入 Istio 或 Linkerd,通过服务网格实现自动熔断、限流和重试策略,降低代码侵入性。
  3. 混沌工程验证

    • 定期模拟 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.核心流程

  1. 请求拦截:API Server 在处理请求前,拦截所有 HTTP 请求。
  2. 策略匹配:根据预定义的 审计策略(Audit Policy),决定是否记录该请求。
  3. 事件生成:对匹配策略的请求,生成结构化审计事件(Audit Event)。
  4. 后端处理:将事件发送到配置的后端(如文件、Webhook、日志系统)。

5.2.2.分层过滤机制

  • 阶段(Stage):定义事件记录的时机,分为:
    • RequestReceived:接收到请求时。
    • ResponseStarted:发送响应头时(适用于 Watch 等长连接)。
    • ResponseComplete:响应完成时。
    • Panic:处理请求时发生崩溃。
  • 级别(Level):控制日志详细程度:
    • None:不记录。
    • Metadata:记录请求元数据(用户、资源、操作等),不记录请求/响应体。
    • Request:记录元数据 + 请求体。
    • RequestResponse:记录元数据 + 请求体 + 响应体。

5.2.3.异步处理

  • 审计日志记录采用 异步队列 机制,避免阻塞 API Server 主流程。
  • 高负载时,可通过队列大小和批处理配置平衡性能与可靠性。

5.2.4.使用场景

  1. 安全审计
    • 检测未授权访问(如 ServiceAccount 滥用)。
    • 追踪敏感操作(如 kubectl delete、Secret 读取)。
  2. 合规性报告
    • 生成操作记录报表,证明符合监管要求。
  3. 故障排查
    • 分析 API 请求延迟、错误率突增等问题。
  4. 行为分析
    • 结合机器学习,识别异常操作模式(如暴力破解、横向移动)。

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:日志格式,支持 jsonlegacy
      • 示例:--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)。
  • 依赖条件
    • 需启用 APIServerdynamicaudit 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.注意事项

  1. 安全存储:确保审计日志文件权限为 600,避免未授权访问。
  2. 性能影响:高频率的 RequestResponse 级别日志可能显著增加 I/O 压力。
  3. 网络可靠性:Webhook 后端需配置重试机制,防止网络抖动导致日志丢失。
  4. 动态配置兼容性:动态审计在 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:操作类型(getlistcreatedelete 等)。
  • 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 开销。
  • 过滤冗余事件:通过策略排除高频低价值操作(如 getlist)。

5.6.4.安全加固

  • 日志脱敏:在策略中排除敏感字段(如 Secret 的 data 字段):
    - level: Request
      resources:
      - group: ""
        resources: ["secrets"]
      omitStages: ["RequestReceived"]
      omitManagedFields: true  # 忽略 metadata.managedFields
    
  • 加密存储:结合 KMS 对审计日志文件加密。

5.7.调试与工具

  1. 检查 API Server 日志
    kubectl logs -n kube-system kube-apiserver-<node-name> | grep audit
    
  2. 查看审计日志文件
    tail -f /var/log/kubernetes/audit.log | jq .
    
  3. 监控审计事件数量
    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.流程步骤

  1. 客户端发起请求:在请求头中附加 Impersonation 信息。
  2. API Server 解析头:提取 Impersonate-* 字段,验证其合法性。
  3. 绑定真实身份:将请求视为被模拟用户的身份处理。
  4. RBAC 验证:检查被模拟用户是否有对应操作的权限。

6.3.Impersonation 的实现细节

6.3.1.API Server 的拦截逻辑

API Server 在处理每个请求时,会执行以下步骤:

  1. 提取原始用户:通过认证(如 Token、Client Certificate)确定请求发起者的原始身份。
  2. 解析 Impersonation 头:从请求头中读取 Impersonate-* 字段。
  3. 合并身份
    • 如果存在 Impersonate-User,则覆盖原始用户。
    • 如果存在 Impersonate-Group,则追加用户组。
    • 如果存在 Impersonate-ServiceAccount,则关联服务账户的权限。
  4. 生成最终用户对象:构造包含模拟身份的 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-UserImpersonate-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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值