云原生后端开发工具微服务【免费下载链接】operator-sdkSDK for building Kubernetes applications. Provides high level APIs, useful abstractions, and project scaffolding.项目地址https://gitcode.com/gh_mirrors/op/operator-sdk点击查看免费下载导读本文以 Operator SDK 官方文档《Testing your Operator project》为核心骨架系统讲解如何为基于 Go 的 Operator 项目编写单元级集成测试EnvTest、端到端测试e2e以及声明式测试kuttl / chainsaw并覆盖 scorecard 测试框架的自定义测试能力。你将掌握controllers/suite_test.go的脚手架结构、make test与go test的运行机制、离线环境下的 envtest 二进制准备以及如何复用仓库中 memcached-operator 示例 的完整测试套路。为什么推荐 EnvTestOperator SDK 官方推荐使用 controller-runtime 的 envtest 来为 Operator 项目编写测试原因有三社区活跃度更高envtest 由 controller-runtime 项目维护贡献者社区比 Operator SDK 自身的历史测试框架更活跃、更成熟无需真实集群envtest 会启动一个本地的 Kubernetes API Server 与 etcd测试完全在进程内运行无需任何真实的 Kubernetes 集群这在 CI 场景中是巨大的优势——没有集群可用、没有权限问题测试更快更稳定与主流生态同栈controller-runtime 本身的测试也使用同一套技术栈Ginkgo Gomega EnvTest意味着你可以直接借鉴上游项目大量的测试写法与最佳实践。使用 EnvTestsuite_test.go 脚手架详解当使用operator-sdk create api创建控制器时工具会自动在controllers/目录下生成suite_test.go。该文件是集成测试的骨架内部使用 GinkgoBDD 风格测试框架与 Gomega断言库驱动。在仓库的示例项目中可以找到两个典型的脚手架文件控制器测试controllers/suite_test.goWebhook 测试webhook_suite_test.go核心结构剖析以控制器测试的 suite_test.go 为例其结构分为四个部分1. 入口函数func TestControllers(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, Controller Suite) }TestControllers是标准 Go 测试入口通过RegisterFailHandler(Fail)将 Ginkgo 的失败处理接入 Gomega再以RunSpecs启动整个测试套件。2. BeforeSuite启动测试环境var _ BeforeSuite(func() { logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) ctx, cancel context.WithCancel(context.TODO()) var err error err cachev1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) // kubebuilder:scaffold:scheme By(bootstrapping test environment) testEnv envtest.Environment{ CRDDirectoryPaths: []string{filepath.Join(.., .., config, crd, bases)}, ErrorIfCRDPathMissing: true, } // Retrieve the first found binary directory to allow running tests from IDEs if getFirstFoundEnvTestBinaryDir() ! { testEnv.BinaryAssetsDirectory getFirstFoundEnvTestBinaryDir() } cfg, err testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) k8sClient, err client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient).NotTo(BeNil()) })关键点envtest.Environment的CRDDirectoryPaths指向项目的 CRD 目录config/crd/basesenvtest 启动时会自动将这些 CRD 安装进本地 API Server从而使测试中可以真实创建自定义资源ErrorIfCRDPathMissing: true表示若 CRD 目录不存在则直接报错避免测试在静默状态下失去对 CR 的校验能力testEnv.Start()返回*rest.Config随后用它构造 controller-runtime 的client.Client测试代码中的k8sClient就是这一客户端它真实地访问本地 API Server由于 CRD 通过AddToScheme注册进全局scheme.Schemek8sClient可以正确地序列化/反序列化自定义资源。3. AfterSuite回收环境var _ AfterSuite(func() { By(tearing down the test environment) cancel() err : testEnv.Stop() Expect(err).NotTo(HaveOccurred()) })testEnv.Stop()会关闭本地 API Server 与 etcd 进程完成资源回收。4. IDE 友好的二进制定位辅助函数func getFirstFoundEnvTestBinaryDir() string { basePath : filepath.Join(.., .., bin, k8s) entries, err : os.ReadDir(basePath) if err ! nil { logf.Log.Error(err, Failed to read directory, path, basePath) return } for _, entry : range entries { if entry.IsDir() { return filepath.Join(basePath, entry.Name()) } } return }envtest 依赖 kube-apiserver、etcd、kubectl 等二进制文件。该函数会在项目的bin/k8s目录下寻找由make setup-envtest下载的二进制并将其通过BinaryAssetsDirectory注入环境从而保证在 IDE 中直接运行测试时也能找到二进制——其作用等价于手动设置KUBEBUILDER_ASSETS环境变量。Webhook 测试的额外内容若项目包含 Webhook生成的 webhook_suite_test.go 会在上述骨架之上增加testEnv envtest.Environment{ CRDDirectoryPaths: []string{filepath.Join(.., .., .., config, crd, bases)}, ErrorIfCRDPathMissing: false, WebhookInstallOptions: envtest.WebhookInstallOptions{ Paths: []string{filepath.Join(.., .., .., config, webhook)}, }, }WebhookInstallOptions.Paths指向config/webhook目录envtest 会安装其中的 WebhookConfiguration在BeforeSuite中通过ctrl.NewManager启动 Manager 并挂载 Webhook 服务器然后等待本地 Webhook 端口可用通过Eventually TLS 拨号探测确保 Webhook 真正就绪后再执行用例。运行测试这些测试本质上是原生 Go 测试可以直接运行go test controllers/ -v -ginkgo.v-v输出详细日志-ginkgo.v让 Ginkgo 输出每个 spec 的详细信息。更常用的方式是借助项目脚手架生成的 Makefile。以仓库中 memcached-operator 的 Makefile 为例.PHONY: test test: manifests generate fmt vet setup-envtest ## Run tests. KUBEBUILDER_ASSETS$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path) go test $(shell go list ./... | grep -v /test/) -coverprofile cover.out执行make test时会依次生成 manifestscontroller-gen生成 RBAC/CRD/Webhook 配置生成 DeepCopy 代码执行go fmt与go vet通过setup-envtest下载 envtest 二进制将KUBEBUILDER_ASSETS设置为二进制路径运行单元与集成测试并输出覆盖率cover.out。注意make test还会在make docker-build IMGsome-registry/project-name:tag时被执行docker-build 依赖 test 目标也就是说构建镜像前会先跑一遍测试确保质量门槛。离线/受限环境下的 envtest 准备envtest 二进制需要联网下载默认从 controller-runtime 的发布渠道获取。在断网或受限的 CI 环境中可以采用以下方式预先下载并缓存二进制在联网机器上执行setup-envtest use 版本 --bin-dir 路径将下载好的二进制目录打进 CI 缓存或作为构建产物传递显式设置 KUBEBUILDER_ASSETS将缓存的二进制目录路径通过环境变量传给测试进程如上文 Makefile 所示依赖 BinaryAssetsDirectory仓库脚手架自带的getFirstFoundEnvTestBinaryDir()会读取项目bin/k8s下的二进制因此只要把缓存二进制放到该目录即使不设置环境变量也能在 IDE/本地运行。其中ENVTEST_K8S_VERSION与ENVTEST_VERSION在 Makefile 中根据依赖自动推导ENVTEST_VERSION ? $(shell go list -m -f {{ .Version }} sigs.k8s.io/controller-runtime | awk -F[v.] {printf release-%d.%d, $$2, $$3}) ENVTEST_K8S_VERSION ? $(shell go list -m -f {{ .Version }} k8s.io/api | awk -F[v.] {printf 1.%d, $$3})即 envtest 的 setup 脚本版本跟随 controller-runtime 的 release 分支Kubernetes 版本跟随k8s.io/api的依赖版本无需手工维护版本号。编写控制器测试用例看完骨架再看一个真实用例。memcached_controller_test.go 展示了典型的控制器测试写法var _ Describe(Memcached controller, func() { Context(Memcached controller test, func() { const MemcachedName test-memcached ... SetDefaultEventuallyTimeout(2 * time.Minute) SetDefaultEventuallyPollingInterval(time.Second) BeforeEach(func() { By(Creating the Namespace to perform the tests) err : k8sClient.Create(ctx, namespace) Expect(err).NotTo(HaveOccurred()) By(Setting the Image ENV VAR which stores the Operand image) err os.Setenv(MEMCACHED_IMAGE, example.com/image:test) Expect(err).NotTo(HaveOccurred()) By(creating the custom resource for the Kind Memcached) ... }) AfterEach(func() { By(removing the custom resource for the Kind Memcached) ... }) It(should successfully reconcile a custom resource for Memcached, func() { By(Reconciling the custom resource created) memcachedReconciler : MemcachedReconciler{ Client: k8sClient, Scheme: k8sClient.Scheme(), } _, err : memcachedReconciler.Reconcile(ctx, reconcile.Request{ NamespacedName: typeNamespacedName, }) Expect(err).NotTo(HaveOccurred()) By(Checking if Deployment was successfully created in the reconciliation) Eventually(func(g Gomega) { found : appsv1.Deployment{} g.Expect(k8sClient.Get(ctx, typeNamespacedName, found)).To(Succeed()) }).Should(Succeed()) ... }) }) })值得学习的要点直接调用Reconcile测试不通过 Manager 启动控制器而是手工实例化MemcachedReconciler并直接调用其Reconcile方法配合k8sClient验证期望状态隔离性强、速度快Eventually 轮询由于控制器是异步的informer 缓存、API Server 延迟断言状态时必须用Eventually轮询而不是立即断言示例中把超时设为 2 分钟、轮询间隔 1 秒环境变量注入测试通过os.Setenv注入 operand 镜像等环境变量并在AfterEach中清理Namespace 隔离每个用例创建独立 Namespace并在用例结束后删除避免相互污染注意 envtest 删除 Namespace 存在已知限制参见 kubebuilder 文档的 testing considerations。e2e 集成测试单元/集成测试之外还需要在真实集群上验证 Operator 的完整行为。根据 Operator 语言类型e2e 测试方案不同Go Operator直接用 Go 编写 e2e 测试Ansible Operator使用 MoleculeAnsible 测试框架详见 Testing with MoleculeHelm Operator可使用 Chart testsHelm Chart 自带测试。Go e2e 示例test/e2e 目录以仓库中 memcached-operator 的 e2e 测试 为例包含三个文件e2e_suite_test.go标准 Ginkgo 入口e2e_test.go真正的端到端用例utils.gokubectl/kind 操作工具。e2e_test.go 展示的完整流程It(should run successfully, func() { By(building the manager(Operator) image) cmd : exec.Command(make, docker-build, fmt.Sprintf(IMG%s, operatorImage)) _, err utils.Run(cmd) ExpectWithOffset(1, err).NotTo(HaveOccurred()) By(loading the manager(Operator) image on Kind) err utils.LoadImageToKindClusterWithName(operatorImage) ExpectWithOffset(1, err).NotTo(HaveOccurred()) By(installing CRDs) cmd exec.Command(make, install) _, err utils.Run(cmd) ExpectWithOffset(1, err).NotTo(HaveOccurred()) By(deploying the controller-manager) cmd exec.Command(make, deploy, fmt.Sprintf(IMG%s, operatorImage)) outputMake, err : utils.Run(cmd) ExpectWithOffset(1, err).NotTo(HaveOccurred()) ... })流程概括为构建 Operator 镜像 → 加载进 Kind 集群 →make install安装 CRD →make deploy部署控制器 → 校验控制器 Pod 运行 → 创建 Memcached 自定义资源 → 校验 operand Pod 处于Running→ 校验 CR 的 status condition 被更新为Available。此外该样例还涉及 Prometheus Operator 与 cert-manager 的安装/卸载以及 Pod Security Standardsrestricted 模式的校验。配套的 Makefile 提供了便捷的 e2e 入口Makefile.PHONY: test-e2e test-e2e: setup-test-e2e manifests generate fmt vet ## Run the e2e tests. Expected an isolated environment using Kind. KIND_CLUSTER$(KIND_CLUSTER) go test ./test/e2e/ -v -ginkgo.v $(MAKE) cleanup-test-e2e其中setup-test-e2e会检查/创建 Kind 集群默认名memcached-operator-test-e2e测试结束后cleanup-test-e2e自动删除集群保证环境隔离。仓库自带的 e2e 测试test/e2e/go 与 test/e2e/helm也采用了同样的模式可作为学习参考。用 Shell 脚本做 e2eSDK 1.0.0 时代遗留方案在 Operator SDK 1.0.0 时代官方提供了基于 Shell 脚本的 e2e 测试方式与当前 Go 方案的目标相同仅实现手段不同。这些脚本位于 SDK v1.0.0 标签的hack/tests目录下示例索引见原文档检查 Go Operator 的e2e-go.sh检查 Helm Operator 的e2e-helm.sh检查 Ansible Operator 的e2e-ansible.sh。它们同样执行“构建镜像 → 部署 → 创建 CR → 验证”的流程。如果你的项目是从 SDK 1.0.0 时代迁移过来的可参考这些脚本了解历史 e2e 的写法新项目建议直接采用 Go 编写的 e2e。声明式测试kuttl 与 chainsaw除代码测试外还可以用声明式的方式编写测试kuttlkuttl 允许用 YAML 清单描述集群在 Operator 作用前后的期望状态——例如“应用某 CR 后集群中应出现某个 Deployment 且其副本数符合预期”。kuttl 的测试定义以TestAssert/TestStep资源组织天然适合验收式测试。详见 Writing Kuttl Scorecard Tests。chainsaw更现代的替代chainsaw 是 kuttl 的更现代替代方案优势在于更强的灵活性支持更复杂的断言表达式丰富的断言模型提供细粒度的资源状态校验能力积极维护社区持续活跃可自动迁移kuttl 测试可自动转换为 chainsaw 格式参见 Migration from KUTTL。scorecard面向应用语义的自定义测试scorecard 是 SDK 的测试框架用于实现应用层面的功能测试。它的关键特性是自定义测试代码被打包进容器镜像随测试套件定义一起发布并作为元数据随 Operator Bundle 分发。这意味着即使没有 Operator 的源码或项目布局只要拿到 Bundle就能对其执行功能测试——非常适合发布前的质量关卡。内置测试与配置使用 SDK 生成的 Go 项目会在config/scorecard下生成配置例如基础配置 bases/config.yamlscorecard.operatorframework.io/v1alpha3的Configurationstages[0].tests为空basic 套件补丁 patches/basic.config.yaml- op: add path: /stages/0/tests/- value: entrypoint: - scorecard-test - basic-check-spec image: quay.io/operator-framework/scorecard-test:v1.42.3 labels: suite: basic test: basic-check-spec-testolm 套件补丁 patches/olm.config.yaml包含olm-bundle-validation、olm-crds-have-validation、olm-crds-have-resources、olm-spec-descriptors、olm-status-descriptors五个测试。scorecard-test镜像中的 basic 套件实现位于仓库 internal/scorecard/tests/basic.go例如basic-check-specCheckSpecTest会遍历 Bundle 中的 CR 清单校验每个 CR 是否包含spec字段缺失则给出失败状态与建议。自定义测试当内置的 basic/olm 套件不满足需求时可以在容器镜像中携带自定义测试代码并在测试套件中引用。这使 scorecard 从通用格式检查升级为业务语义验证。仓库中提供了现成的自定义测试示例images/custom-scorecard-tests含 main.go 与 Dockerfile可作为编写自定义 scorecard 测试的起点。完整指南参见 Writing Custom Scorecard Tests。测试策略小结综合以上一个 Go Operator 项目的完整测试金字塔建议如下层级工具/方案环境对应仓库依据单元测试标准go test无集群各项目*_test.go控制器集成测试EnvTest Ginkgo Gomega本地 API Serversuite_test.goWebhook 集成测试EnvTest Manager本地 API Serverwebhook_suite_test.goe2e 测试Go Kind kubectlKind 集群test/e2e声明式测试kuttl / chainsaw任意集群见 kuttl 文档发布前功能测试scorecardBundle 环境scorecard 文档实践建议CI 中优先 EnvTest无需集群、无权限负担适合作为提交门禁e2e 放在合并前/发版前真实集群验证 Operator 与 operand 的完整生命周期离线环境提前缓存 envtest 二进制通过KUBEBUILDER_ASSETS或仓库脚手架自带的BinaryAssetsDirectory机制注入优先新方案新项目直接使用 chainsaw 替代 kuttle2e 用 Go 编写而非历史 Shell 脚本。延伸阅读Writing controller testskubebuilder 官方教程中关于控制器测试的写法与最佳实践EnvTest setup含离线环境envtest 的完整配置说明与测试注意事项Testing with MoleculeAnsible Operator 的测试指南Writing Kuttl Scorecard Tests 与 Writing Custom Scorecard Testsscorecard 测试的深入指南仓库内完整样例memcached-operator 测试目录、go e2e 套件。赞分享云原生后端开发工具微服务【免费下载链接】operator-sdkSDK for building Kubernetes applications. Provides high level APIs, useful abstractions, and project scaffolding.项目地址https://gitcode.com/gh_mirrors/op/operator-sdk点击查看免费下载相关推荐Operator SDK Scorecard测试评估Operator质量Operator SDK Scorecard测试评估Operator质量 在Kubernetes Operator开发过程中确保Operator的质量和可靠云原生后端开发工具微服务Operator SDK Ansible Operator 测试方案从 Molecule 集成到 E2E 测试实践Operator SDK Ansible Operator 测试方案从 Molecule 集成到 E2E 测试实践 导读 本篇文章基于 Operator SD云原生后端开发工具微服务GraphCast图节点特征纬度、经度与相对位置编码技术GraphCast图节点特征纬度、经度与相对位置编码技术 地理空间编码的核心挑战 你是否曾为如何在图神经网络Graph Neural Network, GN认证鉴权上一篇物联大师核心功能详解PLC协议集成、Web组态与自动控制策略全解析下一篇TIC-80终极指南从零开始掌握幻想计算机的游戏开发艺术创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考