您当前的位置:首页 > 电脑百科 > 程序开发 > 容器

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

时间:2023-11-27 14:33:40  来源:微信公众号  作者:Cloud Native 101

如果你是一名 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:00       INFO    Stopping and wAIting for webhooks
...
2023-11-26T12:55:17+08:00       INFO    Wait completed, proceeding to shutdown the manager
2023-11-26T12:55:17+08:00       ERROR   setup   problem 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/samples
Error 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/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: testing-webhooks-validating-webhook-configuration
webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    service:
      name: testing-webhooks-webhook-service
      namespace: testing-webhooks-system
      path: /validate-webapp-foobar-ai-v1-guestbook
      port: 443
  failurePolicy: Fail
  matchPolicy: Equivalent
  name: vguestbook.kb.io
  rules:
  - ...
  ...

在这个配置中,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 资源的各个属性。

以 ValidatingWebhookConfiguration.webhooks.clientConfig 为例:

 kubectl explain ValidatingWebhookConfiguration.webhooks.clientConfig
GROUP:      admissionregistration.k8s.io
KIND:       ValidatingWebhookConfiguration
VERSION:    v1

FIELD: clientConfig <WebhookClientConfig>:

DESCRIPTION:
FIELDS:
     caBundle   <string>
     `caBundle` is a PEM encoded CA bundle which will be used to validate the
     webhook's server certificate. If unspecified, system tRust roots on the
     apiserver are used.

     service    <ServiceReference>
     `service` is a reference to the service for this webhook. Either `service`
     or `url` must be specified.

     If the webhook is running within the cluster, then you should use `service`.

     url        <string>
     `url` gives the location of the webhook, in standard URL form
     (`scheme://host:port/path`). Exactly one of `url` or `service` must be
     specified.

通过以上提供的详细信息,不难发现 clientConfig 它除了通过定义 Service 让 API 服务器连接到 WebhookServer 外,还有另外一种方式,那就是直接通过 URL 连接。

为了解决这个问题,我们可以将 Webhook 的配置从服务转变为直接使用 URL。

使用 URL 连接 Webhook

通过将 clientConfig 中的 service 字段替换为 url 字段,我们可以指定 Webhook 服务的外部 URL。这样一来,开发者可以在本地运行 Webhook 服务,并通过公开的 URL 使其可被 Kubernetes API 服务器访问。

例如:

webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    url: https://testing-webhooks.loca.lt/validate-webapp-foobar-ai-v1-guestbook

这种方法使得在本地开发环境中调试 Webhook 变得更加灵活和便捷。开发者可以使用本地服务器或通过隧道(如 ngrok[1] 或 localtunnel[2])暴露的服务,从而实现在本地环境中的有效调试。

事实上,我最初的首选是 ngrok,因为这玩意确实好用,它还有个 localhost:4040 非常的实用,但遗憾的是,它的 tls 能力是付费的。幸好,有很多平替工具可以选择,比如 localtunnel,用起来也非常的方便。

步骤 1: 在我们的 main.go 需要接收一个证书路径

...
var certDir string
flag.StringVar(&certDir, "webhook-cert-dir", "/tmp/k8s-webhook-server/serving-certs", "Admission webhook cert/key dir.")
...

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
    Scheme:                 scheme,
    Metrics:                metricsserver.Options{BindAddress: metricsAddr},
    HealthProbeBindAddress: probeAddr,
    WebhookServer: webhook.NewServer(webhook.Options{
        CertDir: certDir,
        Port:    9443,
    }),
    LeaderElection:   enableLeaderElection,
    LeaderElectionID: "dcc993a0.foobar.ai",
})

...

步骤 2:调整 Makefile,并启动我们的程序

修改 Makefile 文件,让其可以接收证书目录:

.PHONY: run
run: manifests generate fmt vet ## Run a controller from your host.
  go run ./cmd/main.go --webhook-cert-dir ./config/certs

启动程序:

 make run
...
go run ./cmd/main.go --webhook-cert-dir ./config/certs
2023-11-26T11:18:42+08:00       INFO    controller-runtime.builder      Registering a mutating webhook  {"GVK": "webapp.foobar.ai/v1, Kind=Guestbook", "path": "/mutate-webapp-foobar-ai-v1-guestbook"}
2023-11-26T11:18:42+08:00       INFO    controller-runtime.webhook      Registering webhook     {"path": "/mutate-webapp-foobar-ai-v1-guestbook"}
2023-11-26T11:18:42+08:00       INFO    controller-runtime.builder      Registering a validating webhook        {"GVK": "webapp.foobar.ai/v1, Kind=Guestbook", "path": "/validate-webapp-foobar-ai-v1-guestbook"}
2023-11-26T11:18:42+08:00       INFO    controller-runtime.webhook      Registering webhook     {"path": "/validate-webapp-foobar-ai-v1-guestbook"}
...
2023-11-26T11:18:42+08:00       INFO    controller-runtime.webhook      Starting webhook server
...
2023-11-26T11:18:42+08:00       INFO    controller-runtime.webhook      Serving webhook server  {"host": "", "port": 9443}
...

步骤 3:将本地主机服务器通过隧道公开

# 安装
npm install -g localtunnel

# 使用 lt 命令启动隧道
lt --port 9443 
    --local-https 
    --local-ca $(pwd)/certs/ca.crt 
    --local-cert $(pwd)/certs/tls.crt 
    --local-key $(pwd)/certs/tls.key 
    --subdomain testing-webhooks
your url is: https://testing-webhooks.loca.lt

步骤 4:修改 ValidatingWebhookConfiguration 配置

我们将默认的 service 服务。

webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    service:
      name: testing-webhooks-webhook-service
      namespace: testing-webhooks-system
      path: /validate-webapp-foobar-ai-v1-guestbook
      port: 443
...

替换换成 url 直连模式

webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    url: https://testing-webhooks.loca.lt/validate-webapp-foobar-ai-v1-guestbook
...

以上仅以 ValidatingWebhookConfiguration 为例,如果你的 controller 同时使用了 MutatingWebhookConfiguration,别忘了,处理方式是一样的。

步骤 5:看看实际效果如何

最后,我们再执行同样一个用例,就可以被当前的 ValidatingWebhook 拦截到了。

kubectl apply -f ./config/samples/webapp_v1_guestbook.yaml
The Guestbook "guestbook-sample" is invalid: metadata.name: Invalid value: "guestbook-sample": 
Guestbook name must be no more than 5 characters for test purposes

小贴士:对于那些出于安全考虑不愿将本地服务暴露在公网上的小伙伴们,这里有一个安全的替代方案。你可以使用如 docker.for.mac.host.internal 这样的特定域名,它允许在不同环境下安全地连接到你的主机。

为了实现这一点,你需要根据你所在的环境,将 docker.for.mac.host.internal 替换为能够访问到你本地主机的相应域名。此外,别忘了补充 caBundle 字段,确保使用了正确的 CA 证书的 base64 编码字符串。

示例配置如下所示:

webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    caBundle: [你的CA证书的base64编码字符串]
    url: https://docker.for.mac.host.internal:9443/validate-webapp-foobar-ai-v1-guestbook

当然,在实际开发中,手动更改 Webhook 配置显然不是理想选择。推荐大家根据项目需求,结合这里提供的策略,开发自动化的配置处理流程。这不仅提升效率,还确保了配置的准确性和项目的灵活性。

Debugging operator on Kubernetes

在以前的旧文中,我分享过 《Kubernetes 101: Debugging Microservices on Kubernetes》 这篇文章,主要介绍微服务在 K8s 环境下,在本地如何进行有效的调试。事实上,我们当前 webhook 的调试场景,完全可以利用 Nocalhost[3] 这款工具达到同样的目的。

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

在 Nocalhost 的开发模式下,我们可以直接在 K8s 集群中构建、测试和调试应用程序的,这意味着我们可以默认使用 clientConfig.service 模式,直接通过内部服务来连接,非常的方便。如果你还不太熟悉 Nocalhost,那可得抓紧时间补课了



Tags:Kubernetes   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Kubernetes 究竟有没有 LTS?
从一个有趣的问题引出很多人都在关注的 Kubernetes LTS 的问题。有趣的问题2019 年,一个名为 apiserver LoopbackClient Server cert expired after 1 year[1] 的 issue 中提...【详细内容】
2024-03-15  Search: Kubernetes  点击:(5)  评论:(0)  加入收藏
Kubernetes 集群 CPU 使用率只有 13% :这下大家该知道如何省钱了
作者 | THE STACK译者 | 刘雅梦策划 | Tina根据 CAST AI 对 4000 个 Kubernetes 集群的分析,Kubernetes 集群通常只使用 13% 的 CPU 和平均 20% 的内存,这表明存在严重的过度...【详细内容】
2024-03-08  Search: Kubernetes  点击:(12)  评论:(0)  加入收藏
聊聊 Kubernetes 网络模型综合指南
这篇详细的博文探讨了 Kubernetes 网络的复杂性,提供了关于如何在容器化环境中确保高效和安全通信的见解。译自Navigating the Network: A Comprehensive Guide to Kubernete...【详细内容】
2024-02-19  Search: Kubernetes  点击:(37)  评论:(0)  加入收藏
Kubernetes是什么?主要特点是什么?
Kubernetes是什么?Kubernetes,也称为K8s,是一个开源的容器编排系统,由Google首次开发和维护。它允许容器化的应用程序在集群中自动部署、扩展和管理。Kubernetes提供了一种容器...【详细内容】
2024-02-01  Search: Kubernetes  点击:(153)  评论:(0)  加入收藏
开发者的Kubernetes懒人指南
你可以将本文作为开发者快速了解 Kubernetes 的指南。从基础知识到更高级的主题,如 Helm Chart,以及所有这些如何影响你作为开发者。译自Kubernetes for Lazy Developers。作...【详细内容】
2024-02-01  Search: Kubernetes  点击:(50)  评论:(0)  加入收藏
Kubernetes Informer基本原理,你明白了吗?
本文分析 k8s controller 中 informer 启动的基本流程不论是 k8s 自身组件,还是自己编写 controller,都需要通过 apiserver 监听 etcd 事件来完成自己的控制循环逻辑。如何高...【详细内容】
2024-01-30  Search: Kubernetes  点击:(37)  评论:(0)  加入收藏
Kubernetes 100个常用命令!
这篇文章是关于使用 Kubectl 进行 Kubernetes 诊断的指南。列出了 100 个 Kubectl 命令,这些命令对于诊断 Kubernetes 集群中的问题非常有用。这些问题包括但不限于:&bull; 集...【详细内容】
2024-01-03  Search: Kubernetes  点击:(76)  评论:(0)  加入收藏
一文读懂Kubernetes部署策略
在这篇文章中,我们将深入研究 Kubernetes 部署概念和一些常见策略,了解每种策略的优缺点。合适的部署策略使我们能够在发布应用程序时最大限度地减少停机时间、增强客户体验并...【详细内容】
2024-01-03  Search: Kubernetes  点击:(58)  评论:(0)  加入收藏
从Kubernetes的探针到DevOps
今天在群里又看有人问如何设置 Kubernetes 的探针,感觉要补充的话太多了,结合我们在一些 DevOps 项目中痛苦的体验,今天一劳永逸的全部说完,此外,也为大家展现一下为什么 DevOps...【详细内容】
2023-12-27  Search: Kubernetes  点击:(113)  评论:(0)  加入收藏
如何基于Kubernetes运行Nacos高可用集群
Nacos(Namings and Configuration Management)是阿里巴巴开源的一个易于构建云原生应用的动态服务发现、配置管理和服务管理平台。以下是Nacos的一些主要功能和特点: 服务发现...【详细内容】
2023-12-18  Search: Kubernetes  点击:(68)  评论:(0)  加入收藏
▌简易百科推荐
Docker 和传统虚拟机有什么区别?
我有一个程序员朋友,他每年情人节都要送女朋友一台服务器。他说:“谁不想在过节当天收到一台 4核8g 的服务器呢?”“万一对方不要,我还能留着自己用。” 给他一次过节的机会,他能...【详细内容】
2024-03-26  小白debug  微信公众号  Tags:Docker   点击:(11)  评论:(0)  加入收藏
掌握Docker网络驱动程序:优化容器通信
Docker为在容器内包装、交付和运行应用程序提供了一个强大的平台,从而彻底改变了容器化。网络是容器化的重要组成部分,Docker提供了各种网络驱动程序来支持容器之间的通信以...【详细内容】
2024-03-22    51CTO  Tags:Docker   点击:(10)  评论:(0)  加入收藏
Containerd容器管理
Nginx 指定容器名称 使用 ctr container create 命令创建容器后,容器并没有处于运行状态,其只是一个静态的容器。容器基本操作容器基本操作主要是 ctr image 命令,查看命令帮...【详细内容】
2024-03-20  云原生运维圈  微信公众号  Tags:容器   点击:(13)  评论:(0)  加入收藏
如何基于Docker镜像逆向生成Dockerfile
引言你是否曾经遇到过一个想要使用的 Docker 镜像,但却无法修改以适应你的特定需求?或者你可能发现了一个喜欢的 Docker 镜像,但想要了解它是如何构建的?在这两种情况下,将 Docke...【详细内容】
2024-03-07  云原生运维圈  微信公众号  Tags:Docker   点击:(22)  评论:(0)  加入收藏
Kubernetes是什么?主要特点是什么?
Kubernetes是什么?Kubernetes,也称为K8s,是一个开源的容器编排系统,由Google首次开发和维护。它允许容器化的应用程序在集群中自动部署、扩展和管理。Kubernetes提供了一种容器...【详细内容】
2024-02-01    简易百科  Tags:Kubernetes   点击:(153)  评论:(0)  加入收藏
我们一起聊聊容器资源自愈
在企业实际在使用容器这类资源的时候,除了技术本身,要考虑的其他问题也会很多。企业管理的容器有千千万万,出于效率考虑,对于有特殊需求的容器如何进行批量创建和管理呢,这就需要...【详细内容】
2024-01-30  匠心独运维妙维效  微信公众号  Tags:容器   点击:(47)  评论:(0)  加入收藏
Docker与Docker Compose入门:释放你应用部署的威力
今天给大家介绍一项强大而有趣的技能,那就是使用 Docker 和 Docker Compose 来释放你的应用部署的威力!无论你是一名开发人员还是系统管理员,掌握这个技能都将为你的工作带来巨...【详细内容】
2024-01-17  waynblog  微信公众号  Tags:Docker   点击:(65)  评论:(0)  加入收藏
Docker镜像与容器的交互及在容器内部执行代码的原理与实践
Docker作为一种流行的容器技术,已经成为现代应用程序开发和部署的重要工具。在Docker中,镜像是构建和运行容器的基础,而容器则是基于镜像创建的可执行实例。Docker镜像与容器的...【详细内容】
2024-01-10  编程技术汇  今日头条  Tags:Docker   点击:(75)  评论:(0)  加入收藏
如何在 Ubuntu 上安装 Docker
使用 Docker 意味着开启一个新的计算领域,但如果你刚刚开始使用 Docker,安装可能看起来是一项艰巨的任务。在 Ubuntu 上安装 Docker 有两种推荐的方法: 从 Ubuntu 的仓库安装 D...【详细内容】
2024-01-04    Linux中国  Tags:Docker   点击:(124)  评论:(0)  加入收藏
从Kubernetes的探针到DevOps
今天在群里又看有人问如何设置 Kubernetes 的探针,感觉要补充的话太多了,结合我们在一些 DevOps 项目中痛苦的体验,今天一劳永逸的全部说完,此外,也为大家展现一下为什么 DevOps...【详细内容】
2023-12-27  云云众生s  微信公众号  Tags:Kubernetes   点击:(113)  评论:(0)  加入收藏
站内最新
站内热门
站内头条