介绍

使用k8s生成资源的时候,会选择是否要添加webhook到你的 API。你可以选择 "Yes" 并按照提示进行操作。

在生成的 config/webhook 目录下,你可以找到用于 Webhook 的配置文件。编辑 MutatingWebhookConfigurationValidatingWebhookConfiguration 文件来指定你的 Webhook 应该拦截哪些资源。

---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: mutating-webhook-configuration
webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    service:
      name: webhook-service
      namespace: system
      path: /mutate-networking-k8s-io-v1-ingress
  failurePolicy: Ignore
  name: mingress.sealos.io
  namespaceSelector:
    matchExpressions:
      - key: user.sealos.io/owner
        operator: Exists
  rules:
  - apiGroups:
    - networking.k8s.io
    apiVersions:
    - v1
    operations:
    - CREATE
    - UPDATE
    resources:
    - ingresses
  sideEffects: None
- admissionReviewVersions:
  - v1
  clientConfig:
    service:
      name: webhook-service
      namespace: system
      path: /mutate--v1-namespace
  failurePolicy: Ignore
  name: mnamespace.sealos.io
  namespaceSelector:
    matchExpressions:
      - key: user.sealos.io/owner
        operator: Exists
  rules:
  - apiGroups:
    - ""
    apiVersions:
    - v1
    operations:
    - CREATE
    - UPDATE
    resources:
    - namespaces
  sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: validating-webhook-configuration
webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    service:
      name: webhook-service
      namespace: system
      path: /validate-networking-k8s-io-v1-ingress
  failurePolicy: Ignore
  name: vingress.sealos.io
  namespaceSelector:
    matchExpressions:
      - key: user.sealos.io/owner
        operator: Exists
  rules:
  - apiGroups:
    - networking.k8s.io
    apiVersions:
    - v1
    operations:
    - CREATE
    - UPDATE
    - DELETE
    resources:
    - ingresses
  sideEffects: None
- admissionReviewVersions:
  - v1
  clientConfig:
    service:
      name: webhook-service
      namespace: system
      path: /validate--v1-namespace
  failurePolicy: Ignore
  name: vnamespace.sealos.io
  namespaceSelector:
    matchExpressions:
      - key: user.sealos.io/owner
        operator: Exists
  rules:
  - apiGroups:
    - ""
    apiVersions:
    - v1
    operations:
    - CREATE

在你的 Go 代码中,需要注册 Webhook。这通常是在 setupwebhookwithmanager.go 文件中完成的,例如:

复制
func (r *MyResource) SetupWebhookWithManager(mgr ctrl.Manager) error {
    return ctrl.NewWebhookManagedBy(mgr).
        For(r).
        Complete()
}

在生成的webhook文件中,主要需要以下方法并提供实现:

在 Kubernetes 中定义一个 Admission Webhook 通常涉及实现特定的接口方法,这些方法属于 admission.Handler 接口,由 kubebuilder 提供的框架抽象。对于 Mutating Webhook 和 Validating Webhook,核心方法如下:

Mutating Webhook

  • Default 方法:这个方法用于设置请求资源的默认值。例如,可以在这个方法中为资源添加或修改注解、标签或其他字段。

    func (m *YourMutatingHandler) Default(ctx context.Context, obj runtime.Object) error {
        // 实现默认值设置逻辑
    }

Validating Webhook

  • ValidateCreate 方法:这个方法在创建资源之前被调用,用于验证新资源是否符合要求。

    func (v *YourValidatingHandler) ValidateCreate(ctx context.Context, obj runtime.Object) error {
        // 实现创建时的验证逻辑
    }
  • ValidateUpdate 方法:这个方法在更新资源之前被调用,用于验证新旧资源之间的差异是否符合要求。

    func (v *YourValidatingHandler) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) error {
        // 实现更新时的验证逻辑
    }
  • ValidateDelete 方法(可选):这个方法在删除资源之前被调用,用于执行删除前的验证逻辑。

    func (v *YourValidatingHandler) ValidateDelete(ctx context.Context, obj runtime.Object) error {
        // 实现删除时的验证逻辑
    }

其他通用方法

  • InjectDecoder 方法:这个方法用于注入一个解码器,它能够将 AdmissionReview 请求解码成具体的资源对象。

    func (h *YourHandler) InjectDecoder(d *admission.Decoder) error {
        h.decoder = d
        return nil
    }
  • Handle 方法:这是 Webhook 的核心处理方法,它接收 AdmissionReview 请求并返回 AdmissionResponse。

    func (h *YourHandler) Handle(ctx context.Context, req admission.Request, resp *admission.Response) {
        // 实现 Webhook 处理逻辑
    }

应用场景举例

发版的权限验证:拦截各种操作

既然用户唯一能使用他人镜像的地方就是系统内的发版,那么可以使用admission webhook进行限制。

工作流程:

1.当用户在前端选择发版/创建应用程序的时候,识别下镜像地址,如果发现

是我们的私有地址,那么修改yml文件,为其打上一个标签

2.配置部署admission webhook,拦截特定标签的pod create请求,拦截逻辑可以自定义:

判断试图创建pod的ns和仓库中的ns是否相同,如果相同即允许,不相同则拒绝。

获取rbac信息,对比后做判断。

还有一种情况是,假设后面可以在镜像仓库层面上做限制,仍然会有问题,比如用户a尝试创建一个用户b的镜像,被调度到节点1上进行,结果节点1上已经有了b的镜像,此时不会走镜像仓库,仍然会有问题,需要webhook进行限制。

理论上分析应该是可以的,因为镜像仓库的认证是拉取过程的认证,这种情况相当于已经把镜像从仓库中拉取到节点本地了,这时候就没有任何认证相关的问题了。不过还没有做实验。

绕开crd,访问controller

当需要crd不变更而访问controller时,可以考虑使用controller的webhook.