云原生小技巧 : 如何在本地调试 Kubernetes Webhook?

如果你是一名 Kube.NETes Operator 的开发者,你曾经是否面临过这样一个棘手的问题:如何在本地环境中高效地调试 Webhook,尤其是在涉及有效证书回调的情况下 。这篇文章旨在提供一种清晰的指南,帮助你克服这一挑战,优化本地开发和测试流程 。
为什么本地调试 Webhook 如此重要?当我们初步涉足 Kubernetes Webhook 时,面对的首个挑战通常是 Validation Webhook 。对于这种验证型 Webhook 来说,我们可以通过编写自动化测试来验证其功能 。
这不仅确保了我的 Webhook 按预期工作,还允许我在日常开发中临时禁用它 , 从而加快了整个开发过程 。这种方法让我能够巧妙地避免复杂的调试问题,而不对整体功能造成任何影响 。
if os.Getenv("ENABLE_WEBHOOKS") != "false" {if err = (&webAppv1.Guestbook{}).SetupWebhookWithManager(mgr); err != nil {setupLog.Error(err, "unable to create webhook", "webhook", "Guestbook")os.Exit(1)}}然而,对于 Mutating Webhook 来说,情况就变得有点复杂了 。这类 Webhook 通常负责埋点的行为甚至更深层次的集群操作,比如注入 sidecar,这时候单靠自动化测试显然是不够的 。我们需要一个更加高效的本地测试和调试方法 。
在我们团队中,有同事采用 Kind 来部署和测试服务,这种方法非常值得称赞 。它完全符合 K8s 的操作模式,为我们提供了一个接近生产环境的本地测试平台 。但是,大家可能也注意到了,这种方式存在一个效率瓶颈:每次进行代码更改后,都需要重新构建 Docker 镜像并部署到集群中,这一过程既耗时又影响开发流程的连贯性 。
作为开发工程师,我们渴望的是一个极速的内部开发循环,一个不再需要频繁的 docker build、docker push 或繁琐的部署流程,即使这些已经完全自动化 。
我们希望能够使用本地熟悉的开发工具,如 VS Code 或者 IntelliJ IDEA 进行本地调试,而不是先部署到集群环境 , 再通过日志来分析错误这种远程调试模式 。
从 Service 到 URL 的魔法变换在不禁用 Webhook 的情况下 , 我们在本地启动 controller 后会有如下错误 。这个比较好处理 , 我们只要使用自签证书 , 注入到 WebhookServer 即可,在前面的文章中我介绍过很多次,这里不再赘述 。
2023-11-26T12:55:17+08:00INFOStopping and wAIting for webhooks...2023-11-26T12:55:17+08:00INFOWait completed, proceeding to shutdown the manager2023-11-26T12:55:17+08:00ERRORsetupproblem running manager {"error": "open /var/folders/hn/v2s5bx...00000gn/T/k8s-webhook-server/serving-certs/tls.crt: no such file or directory"}...我们来运行一个示例,想必下面这个错误大家都非常熟悉吧,这个是因为 Webhook 注册的地址'不对',它是集群内的地址 。
? kubectl apply -f ./config/samplesError from server (InternalError): error when creating "config/samples/webapp_v1_guestbook.yaml": Internal error occurred: failed calling webhook "vguestbook.kb.io": failed to call webhook: Post "https://testing-webhooks-webhook-service.testing-webhooks-system.svc:443/validate-webapp-foobar-ai-v1-guestbook?timeout=10s": no endpoints available for service "testing-webhooks-webhook-service"我们再来看下 ValidatingWebhookConfiguration 的配置 。
apiVersion: admissionregistration.k8s.io/v1kind: ValidatingWebhookConfigurationmetadata:name: testing-webhooks-validating-webhook-configurationwebhooks:- admissionReviewVersions:- v1clientConfig:service:name: testing-webhooks-webhook-servicenamespace: testing-webhooks-systempath: /validate-webapp-foobar-ai-v1-guestbookport: 443failurePolicy: FailmatchPolicy: Equivalentname: vguestbook.kb.iorules:- ......在这个配置中,webhooks 字段定义了一个或多个要注册的 Webhook 。每个 Webhook 通过 clientConfig 配置与 Kubernetes API 服务器的连接方式 。
正如大家所看到的 https://testing-webhooks-webhook-service.testing-webhooks-system.svc:443/validate-webapp-foobar-ai-v1-guestbook,这个默认地址其实就是 K8s 集群内部的地址 。这恰是 K8s 中处理 Webhook 的常规方法,其中 service 字段指向集群内运行的特定服务 。
然而,在本地开发环境中 , 我们只在本地运行了我们的 Operator,直接使用内部服务是不大可能的,因为它要求 Webhook 服务必须部署在 K8s 集群中 。
使用 kubectl explain 探索 Webhook 配置当我们在 K8s 中配置 Webhook 时,了解其配置细节是非常重要的 。kubectl explain 是一个非常实用的小工具,它可以帮助我们深入理解 K8s 资源的各个属性 。


推荐阅读