背景

kubebuilder对webhook的支持主要基于同样用kubebuilder构建的CRD,而对于非kubebuilder项目内构建的类型,还是需要一些work around来实现webhook的构建。

项目内CRD

对于kubebuilder项目生成的CRD,如果想加入一些默认值webhook、校验webhook等,可以很方便的根据官方文档来完成:Implementing defaulting/validating webhooks - The Kubebuilder Book

但是本文的重点不在于此。

非项目内CRD

本文将以kubevirt的vm crd为例,建立webhook。

官方文档对这种情况有基本的指导:Webhooks for Core Types - The Kubebuilder Book,不过还是缺少step by step的指南。

step by step guide

代码框架

  1. 创建kubebuilder项目:kubebuilder init --domain mec.io --repo mec-daemon
  2. 根据官方文档,构建结构体,实现admission.Handler接口
  3. 加webhook和rbac标记
  4. 加构造函数,在main.go里注册webhook

镜像构建

  1. 生成自签名的https证书
  2. 修改dockerfile:将自签证书放到镜像里kubebuilder webhook的默认位置COPY --chown=65532 tls* /tmp/k8s-webhook-server/serving-certs/
  3. 修改Makefile里的IMG
  4. 尝试使用make docker-build构建镜像。由于我们没有使用kubebuilder的api和controller功能,中间可能遇到缺失目录的错误,按照错误提示修改dockerfile解决即可
  5. 至此我们的webhook核心代码和镜像部分完成

集群部署

  1. kubebuilder的默认部署逻辑基于make和kustomize完成,同样由于我们没有用到api和controller功能,所以需要一些定制修改
  2. 修改config/default/kustomization.yaml:修改bases节点,选择需要部署的yaml模块。只保留rbac、manager和webhook模块
  3. 注释掉manager_auth_proxy_patch.yaml,否则会有kube-rbac-proxy容器,增加了复杂度
  4. 修改config/manager/manager.yaml:手写一个service
  5. 注释掉config/rbac/kustomization.yaml中和auth_proxy相关的yaml
  6. 默认生成的时候没有给webhook生成kustomization文件,参照其他模块,在config/webhook中创建一个kustomization
  7. 默认使用make manifes生成的MutatingWebhookConfiguration中不包含自签证书的caBundle字段,查文档没找到kubebuilder标记里怎么加,所以修改makefile,在make manifests结束后将证书读进来,加入到MutatingWebhookConfiguration相应的位置
  8. make deploy测试部署

验证

创建一个vm,查看webhook日志

总结:证书问题

k8s webhook的实现中,有了controller-runtime和kubebuilder的封装,核心代码的编写其实已经比较容易。但是难点出现在了部署时的证书方案上。由于k8s要求必须启用https且无法跳过证书认证环节,所以证书的问题难以绕过。总结起来,大致有几种方案实现证书的管理:

  1. kubebuilder官方支持的基于cert-manager管理证书。弊端是比较复杂,需要引入额外的组件和生态,可能webhook逻辑非常简单,但是却花了大量时间研究cert-manager相关的生态。且kubebuilder本身的文档也没有这块的step by step教程。
  2. 使用自签证书,并设置超长的有效期,然后固定封装到镜像中。同时配置到MutatingWebhookConfiguration中,使k8s能够信任自签证书。方案优势:一劳永逸,相比1来说学习成本低。弊端:安全性低,不符合证书设计的初衷。
  3. k8s中本身也大量使用了证书机制,最近版本的集群中也支持了用集群ca签发可信的证书。所以如果没有多集群部署的需求,可以生成csr等证书配置,直接用k8s的根证书签发证书。该方案也可用于开发调试阶段。
  4. 上一个方案有手动的因素,且无法跨集群自动完成,在搜索引擎上搜索,看到了另一种方案,是对上一方案的自动化:kubernetes 之 admission webhook生成证书 (cuisongliu.github.io),将签发证书的流程用go实现,并结合client-go存储在集群中。
  5. 进一步,可以将4的方案做成一个init-container,在webhook启动前完成证书的签发、注入和配置。

参考

Introduction - The Kubebuilder Book

文章目录