kubeapiserver源码剖析与开发(三):KubeServer初始化之GenericConfig创建(二)

2023年 7月 19日 32.7k 0

上一篇我们说了,初始化一个 kube-apiserver 首先需要创建 kubeAPIServerConfig,而 kubeAPIServerConfig 的重点又在创建 genericConfig 上,genericConfig 创建流程包括 etcd 配置初始化,认证初始化,鉴权初始化,审计初始化,准入初始化,流控初始化。
这一篇我们来说说审计初始化,准入初始化,流控初始化。

审计初始化

// cmd/kube-apiserver/app/server.go

func buildGenericConfig(
  s *options.ServerRunOptions,
  proxyTransport *http.Transport,
) (...) {
    lastErr = s.Audit.ApplyTo(genericConfig)
  if lastErr != nil {
    return
  }
}

下面是初始化审计的步骤,包括

  • 规则评估器创建
  • 日志存储后端创建(在本地保存日志)
  • webhook 后端创建(远程保存或处理日志)
func (o *AuditOptions) ApplyTo(
  c *server.Config,
) error {
    ...
    
  // 1. Build policy evaluator
  evaluator, err := o.newPolicyRuleEvaluator()
  if err != nil {
    return err
  }

  // 2. Build log backend
  var logBackend audit.Backend
  w, err := o.LogOptions.getWriter()
  if err != nil {
    return err
  }
  if w != nil {
    if evaluator == nil {
      klog.V(2).Info("No audit policy file provided, no events will be recorded for log backend")
    } else {
      logBackend = o.LogOptions.newBackend(w)
    }
  }

  // 3. Build webhook backend
  var webhookBackend audit.Backend
  if o.WebhookOptions.enabled() {
    if evaluator == nil {
      klog.V(2).Info("No audit policy file provided, no events will be recorded for webhook backend")
    } else {
      if c.EgressSelector != nil {
        var egressDialer utilnet.DialFunc
        egressDialer, err = c.EgressSelector.Lookup(egressselector.ControlPlane.AsNetworkContext())
        if err != nil {
          return err
        }
        webhookBackend, err = o.WebhookOptions.newUntruncatedBackend(egressDialer)
      } else {
        webhookBackend, err = o.WebhookOptions.newUntruncatedBackend(nil)
      }
      if err != nil {
        return err
      }
    }
  }

  groupVersion, err := schema.ParseGroupVersion(o.WebhookOptions.GroupVersionString)
  if err != nil {
    return err
  }

  // 4. Apply dynamic options.
  var dynamicBackend audit.Backend
  if webhookBackend != nil {
    // if only webhook is enabled wrap it in the truncate options
    dynamicBackend = o.WebhookOptions.TruncateOptions.wrapBackend(webhookBackend, groupVersion)
  }

  // 5. Set the policy rule evaluator
  c.AuditPolicyRuleEvaluator = evaluator

  // 6. Join the log backend with the webhooks
  c.AuditBackend = appendBackend(logBackend, dynamicBackend)

  if c.AuditBackend != nil {
    klog.V(2).Infof("Using audit backend: %s", c.AuditBackend)
  }
  return nil
}

审计策略创建

所谓审计策略,就是根据用户提供的审计配置文件,提取需要记录到审计日志的规则,即什么请求的什么阶段和什么资源的什么操作需要记录,审计策略配置文件可以通过如下参数指定

--audit-policy-file="/path/to/audit/policy"

该文件主要包含了什么事件、什么数据需要被记录
,具体的配置可以参考官方说明

前面我们在介绍认证、鉴权的时候也说到了,他们是在请求处理前在 DefaultBuildHandlerChain 这条链上被执行的,我们这说的审计在请求处理被处理前也是在这条链上执行的

func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
  ...
  handler = filterlatency.TrackCompleted(handler)
  handler = genericapifilters.WithAudit(handler, c.AuditBackend, c.AuditPolicyRuleEvaluator, c.LongRunningFunc)
  handler = filterlatency.TrackStarted(handler, "audit")
    ...
}

审计执行分为下面几个阶段

const (
  StageRequestReceived Stage = "RequestReceived"
  StageResponseStarted Stage = "ResponseStarted"
  StageResponseComplete Stage = "ResponseComplete"
  StagePanic Stage = "Panic"
)

可以在 --audit-policy-file 参数指定的配置中指定哪些规则需要在哪些特定执行审计,或者忽略哪些阶段。在 DefaultBuildHandlerChain 执行的是 RequestReceived 阶段的审计日志记录。

审计后端创建
这里所谓的后端就是审计日志存储的驱动。他通过下面接口来定义

type Sink interface {
ProcessEvents(events ...*auditinternal.Event) bool
}

type Backend interface {
Sink
Run(stopCh

相关文章

KubeSphere 部署向量数据库 Milvus 实战指南
探索 Kubernetes 持久化存储之 Longhorn 初窥门径
征服 Docker 镜像访问限制!KubeSphere v3.4.1 成功部署全攻略
那些年在 Terraform 上吃到的糖和踩过的坑
无需 Kubernetes 测试 Kubernetes 网络实现
Kubernetes v1.31 中的移除和主要变更

发布评论