ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Tekton Pipeline Resolver 模板实战:基于 demo 示例从零搭建自定义 Resolver

Tekton Pipeline Resolver 模板实战:基于 demo 示例从零搭建自定义 Resolver 云原生CI/CDDevOps后端【免费下载链接】pipelineA cloud-native Pipeline resource.项目地址https://gitcode.com/gh_mirrors/pipelin/pipeline点击查看免费下载本文以 Tekton Pipeline 仓库中docs/resolver-template/目录的可运行 Resolver 模板为主线讲解如何以最少的工作量复制并定制一个属于自己的 Resolver从理解framework.Resolver接口、编写main.go、配置 Deployment到用ResolutionRequest和PipelineRun验证解析结果。读完本文你将掌握在 Tekton Pipeline 中接入任意远程存储后端Git、对象存储、HTTP 等的完整套路与源码级实现细节。Resolver 模板概览一个可直接复用的最小实现docs/resolver-template/是一个可直接运行的 Resolver 最小工程它依据 docs/how-to-write-a-resolver.md 中的开发者指南编写而成目的是给你一个拿来即用的起点。这个模板不依赖任何真实的版本控制系统或云平台只返回一段硬编码的 YAML Pipeline用于演示 Resolver 的完整工作链路。模板的目录结构如下可在docs/resolver-template/下确认docs/resolver-template/ ├── README.md # 模板使用说明本文主体 ├── test-resolver-template.yaml # 用于测试的 ResolutionRequest 示例 ├── cmd/ │ ├── resolver/ │ │ ├── main.go # 基于最新框架remoteresolution的实现 │ │ └── main_test.go # 对应的测试用例 │ └── demoresolver/ │ ├── main.go # 基于旧框架已废弃的实现 │ └── main_test.go └── config/ └── demo-resolver-deployment.yaml # Kubernetes Deployment 配置Resolver Typedemo模板中的 Resolver 响应的类型为demo。这里的类型由ResolutionRequest对象上的标签resolution.tekton.dev/type: demo决定它由pkg/resolution/common/labels.go中的常量定义// pkg/resolution/common/labels.go const LabelKeyResolverType string resolution.tekton.dev/type当集群中存在多个 Resolver 时这个标签就是请求路由的依据带有resolution.tekton.dev/type: demo标签的ResolutionRequest会被送到本模板实现的控制器处理。参数模板在 README 中声明了一个参数但实际实现见下文Validate方法并不接受任何参数这里列出是为了展示 Resolver 参数的声明方式名称描述示例值url仓库地址repository urlhttps://example.com/repo/注意README 表格中的参数是预留示意。真实的cmd/resolver/main.go在Validate中直接拒绝一切参数if len(req.Params) 0 { return errors.New(no params allowed) }并校验url的 scheme 必须为demoscheme。这意味着模板向你展示了如何声明参数也展示了如何严格校验参数——当你接入真实存储后端时把这段校验替换成对url、revision等真实参数的解析即可。使用模板快速启动一个新 Resolver模板的设计目标就是复制即用把整个docs/resolver-template/子目录复制到你的新项目目录然后做三件事1. 复制目录并初始化 Go module# 将整个子目录复制到新位置 $ cp -r docs/resolver-template /path/to/your/newname # 在项目根目录初始化 go module 并整理依赖 $ go mod init your-module-name $ go mod tidy原 README 特别说明tektoncd/resolution 仓库内不需要执行go mod init因为该子模块直接复用仓库根部的go.mod与go.sum。但当你把模板复制到独立目录后就必须自己初始化 module 并拉取依赖。2. 更新 Deployment 中的镜像字段修改docs/resolver-template/config/demo-resolver-deployment.yaml将containers[].image指向你新 go module 的名字并加上ko://前缀containers: - name: controller image: ko://your-module-name/cmd/resolver # 例如 ko://example.com/demoresolver/cmd/demoresolverko://前缀是 ko 构建工具的标记部署时ko会识别该前缀、在本地完成容器镜像构建并推送到镜像仓库然后将ko://替换为真实的镜像地址。这也是模板源码文件头部均带有ko://github.com/tektoncd/pipeline/docs/resolver-template/cmd/demoresolver的原因。3. 选择实现框架模板同时提供了两套实现二者实现的是不同包下的同名接口版本代码位置接口定义位置状态最新框架Latestdocs/resolver-template/cmd/resolver/main.gopkg/remoteresolution/resolver/framework/interface.go推荐使用旧框架Previousdocs/resolver-template/cmd/demoresolver/main.gopkg/resolution/resolver/framework/interface.go已废弃Deprecated两套实现的差异集中在接口方法签名上旧框架的ValidateParams(ctx, params []pipelinev1.Param)接收的是参数切片新框架的Validate(ctx, req *v1beta1.ResolutionRequestSpec)接收的是整个请求 Spec可以访问req.URL、req.Params等完整信息信息更完整、校验能力更强。新接口源码中明确标注了废弃说明// pkg/resolution/resolver/framework/interface.go // Deprecated: Use [github.com/tektoncd/pipeline/pkg/remoteresolution/resolver/framework.Resolver] instead.核心接口framework.Resolver 的五种方法无论选择哪套框架实现的核心都是framework.Resolver接口。以最新框架 pkg/remoteresolution/resolver/framework/interface.go 为例接口共定义了 5 个方法模板对其逐一给出了 stub 实现。Initialize初始化依赖控制器实例化时被调用一次适合在此设置 resource lister 等依赖。模板不需要任何依赖直接返回nil// docs/resolver-template/cmd/resolver/main.go func (r *resolver) Initialize(context.Context) error { return nil }GetNameResolver 的名字返回一个字符串名字会出现在日志等场景中。模板返回Demofunc (r *resolver) GetName(context.Context) string { return Demo }GetSelector请求路由标签返回一个标签映射用于将请求路由到本 Resolver。模板匹配resolution.tekton.dev/type: demofunc (r *resolver) GetSelector(context.Context) map[string]string { return map[string]string{ common.LabelKeyResolverType: demo, } }它的语义是任何带有resolution.tekton.dev/type: demo标签的ResolutionRequest都会被路由到我们的示例 Resolver见 pkg/resolution/common/labels.go 中LabelKeyResolverType的定义。Validate / ValidateParams校验请求校验请求的合法性。最新框架的实现同时校验无参数与URL scheme 格式// docs/resolver-template/cmd/resolver/main.go func (r *resolver) Validate(ctx context.Context, req *v1beta1.ResolutionRequestSpec) error { if len(req.Params) 0 { return errors.New(no params allowed) } u, err : neturl.ParseRequestURI(req.URL) if err ! nil { return err } if u.Scheme ! demoscheme { return fmt.Errorf(Invalid Scheme. Want %s, Got %s, demoscheme, u.Scheme) } return nil }这里体现了自定义 Resolver 的关键设计点通过校验 URL scheme 来决定哪些请求归我处理。真实场景中Git Resolver 会校验gitscheme 并解析仓库 URL、revision 等参数HTTP Resolver 会校验http(s)scheme而本模板用demoscheme做了一个最小演示。旧框架对应的方法是ValidateParams只做参数非空校验// docs/resolver-template/cmd/demoresolver/main.go func (r *resolver) ValidateParams(ctx context.Context, params []pipelinev1.Param) error { if len(params) 0 { return errors.New(no params allowed) } return nil }Resolve执行解析并返回结果Resolve是真正干活的方法负责从远端获取内容并返回。模板直接返回一个硬编码的 Pipeline// docs/resolver-template/cmd/resolver/main.go func (r *resolver) Resolve(ctx context.Context, req *v1beta1.ResolutionRequestSpec) (frameworkV1.ResolvedResource, error) { return myResolvedResource{}, nil } // our hard-coded resolved file to return const pipeline apiVersion: tekton.dev/v1 kind: Pipeline metadata: name: my-pipeline spec: tasks: - name: hello-world taskSpec: steps: - image: alpine:3.15.1 script: | echo hello world 这段硬编码的 YAML 就是一个tekton.dev/v1版本的Pipeline包含一个名为hello-world的任务任务内联taskSpec步骤使用alpine:3.15.1镜像执行echo hello world。当你把Resolve替换为真实逻辑如调用go-git拉取仓库、用 OCI 客户端拉取 bundle时返回的ResolvedResource接口保持不变这就是模板只换后端、不动骨架的扩展点。ResolvedResource解析结果的返回契约Resolve方法的返回值类型是framework.ResolvedResource接口它只有三个方法见 pkg/resolution/resolver/framework/interface.go 中ResolvedResource的定义type ResolvedResource interface { Data() []byte Annotations() map[string]string RefSource() *pipelinev1.RefSource }模板中的myResolvedResource实现如下// Data returns the bytes of our hard-coded Pipeline func (*myResolvedResource) Data() []byte { return []byte(pipeline) } // Annotations returns any metadata needed alongside the data. None atm. func (*myResolvedResource) Annotations() map[string]string { return nil } // RefSource is the source reference of the remote data that records where the remote // file came from including the url, digest and the entrypoint. None atm. func (*myResolvedResource) RefSource() *pipelinev1.RefSource { return nil }三个方法的职责与最佳实践Data()返回解析到的资源内容字节。Tekton Pipelines 目前仅支持通过远程解析获取Pipeline资源因此返回硬编码的 Pipeline YAML 即可满足最小验证。Annotations()随数据一同返回的元数据模板暂无需求返回nil。RefSource()记录远程数据的来源url、digest、entrypoint。最佳实践为了能让 Tekton Chains 在 SLSA provenance 中记录远程数据的来源信息Resolver 应实现RefSource()并返回正确的RefSource值例如func (*myResolvedResource) RefSource() *pipelinev1.RefSource { return pipelinev1.RefSource{ URI: https://github.com/user/example, Digest: map[string]string{ sha1: example, }, EntryPoint: foo/bar/task.yaml, } }此外解析结果在写入ResolutionRequest之前还会经过ValidateResolvedResource的校验见 pkg/resolution/resolver/framework/interface.go它解包返回数据校验其必须是tekton.devgroup 下的合法 Tekton 资源类型防止非 K8s 数据如 token或非 Tekton 对象如 Secret被写入无特权的ResolutionRequest对象。主程序入口与控制器注册模板的main()函数展示了 Resolver 的启动方式docs/resolver-template/cmd/resolver/main.gofunc main() { ctx : filteredinformerfactory.WithSelectors(context.Background(), v1beta1.ManagedByLabelKey) sharedmain.MainWithContext(ctx, controller, framework.NewController(ctx, resolver{}), ) }关键点filteredinformerfactory.WithSelectors(..., v1beta1.ManagedByLabelKey)按resolution.tekton.dev/managed-by标签对 informer 做过滤只关注本 Resolver 管理的ResolutionRequest。sharedmain.MainWithContext(ctx, controller, framework.NewController(ctx, resolver{}))来自 Knative 的sharedmain负责启动带 leader election、metrics、profiling 等能力的控制器进程framework.NewController则把我们的resolver实例包装成完整的 controller。这也解释了为何 Deployment 需要SYSTEM_NAMESPACE、CONFIG_LOGGING_NAME、CONFIG_OBSERVABILITY_NAME、METRICS_DOMAIN等环境变量——它们是底层 Knative 框架的约定。部署 Resolver环境要求一台安装了kubectl和ko的机器集群中已安装tekton-pipelines命名空间和ResolutionRequest控制器。具体安装指引可参考 docs/install.md 中关于安装远程 task/pipeline resolution 的章节以及 docs/resolution-getting-started.md 的入门步骤。安装ko apply$ ko apply -f ./docs/resolver-template/config/demo-resolver-deployment.yamlDeployment 配置详解模板自带的部署清单 docs/resolver-template/config/demo-resolver-deployment.yaml 值得逐项理解apiVersion: apps/v1 kind: Deployment metadata: name: demoresolver namespace: tekton-pipelines-resolvers # 与官方 resolvers 部署在同一命名空间 spec: replicas: 1 selector: matchLabels: app: demoresolver template: metadata: labels: app: demoresolver spec: affinity: podAntiAffinity: # 多副本时尽量分散到不同节点 preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app: demoresolver topologyKey: kubernetes.io/hostname weight: 100 serviceAccountName: tekton-pipelines-resolvers # 所有 resolver 共享的默认 SA containers: - name: controller image: ko://github.com/tektoncd/pipeline/docs/resolver-template/cmd/demoresolver resources: requests: cpu: 100m memory: 100Mi limits: cpu: 1000m memory: 1000Mi ports: - name: metrics containerPort: 9090 env: - name: SYSTEM_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: CONFIG_LOGGING_NAME value: config-logging - name: CONFIG_OBSERVABILITY_NAME value: config-observability - name: METRICS_DOMAIN value: tekton.dev/resolution securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true capabilities: drop: - all要点归纳命名空间部署在tekton-pipelines-resolvers这是官方 resolversgit、hub、cluster 等所在的命名空间ServiceAccounttekton-pipelines-resolvers是tekton-pipelines-resolvers命名空间中所有 resolver 共享的默认 SA可对照 config/resolvers/200-serviceaccount.yaml镜像使用ko://前缀由 ko 构建并替换为真实镜像地址资源与端口CPU 100m/1000m、内存 100Mi/1000Mimetrics 端口 9090环境变量SYSTEM_NAMESPACE取自 pod 所在命名空间CONFIG_LOGGING_NAME/CONFIG_OBSERVABILITY_NAME指向日志与可观测性 ConfigMapMETRICS_DOMAIN为tekton.dev/resolution安全加固禁用特权提升、只读根文件系统、非 root 运行、丢弃全部 Linux capabilities。验证 ResolverResolutionRequest 全流程测试创建一个指向 demo 类型的 ResolutionRequest模板 README 给出的验证方式是创建一个不带参数的、标签为demo的ResolutionRequest$ cat EOF rrtest.yaml apiVersion: resolution.tekton.dev/v1beta1 kind: ResolutionRequest metadata: name: test-resolver-template labels: resolution.tekton.dev/type: demo EOF $ kubectl apply -f ./rrtest.yaml $ kubectl get resolutionrequest -w test-resolver-template仓库中另有一份可直接使用的示例文件 docs/resolver-template/test-resolver-template.yaml该文件使用resolution.tekton.dev/v1alpha1API 版本实践时建议按 README 示例使用v1beta1。稍等片刻你会看到ResolutionRequest变为成功状态并且一个 hello-worldPipeline的内容以base64 编码的形式出现在对象的status.data字段中$ kubectl get resolutionrequest test-request -o jsonpath{$.status.data} | base64 -d解码后即可看到模板中硬编码的那段 Pipeline YAML。失败路径的源码佐证模板附带的测试 docs/resolver-template/cmd/resolver/main_test.go 完整覆盖了成功与失败路径是用RunResolverReconcileTest驱动的端到端式单测TestResolver请求 URL 为demoscheme://foo/bar期望status.data为硬编码 Pipeline 的 base64 编码Succeeded条件为 TrueTestResolver_Failure_Wrong_SchemeURL 为wrongscheme://foo/bar期望失败Reason 为ResolutionFailed消息为Invalid Scheme. Want demoscheme, Got wrongschemeTestResolver_Failure_InvalidUrlURL 为foo/bar非法 URI期望失败消息为parse foo/bar: invalid URI for requestTestResolver_Failure_InvalidParams携带参数foobar期望失败消息为no params allowed。这四个用例精确印证了Validate方法的校验逻辑无参数 demoschemescheme 合法 URI。你在编写自己的 Resolver 时可以直接以这份测试为模板把硬编码的 Pipeline 换成 mock 的远端数据把demoscheme校验换成自己 scheme 的校验。用 PipelineRun 验证端到端解析模板 README 给出了一个使用硬编码 demo Pipeline 的PipelineRun示例apiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: name: resolver-demo spec: pipelineRef: resolver: demo这是 Tekton 远端解析remote resolution的典型用法pipelineRef.resolver: demo告诉 Tekton Pipelines 去调用名为demo的 Resolver而不像传统用法那样直接写pipelineRef.name。解析成功后Tekton 会把status.data中解码出的 Pipeline 作为本次PipelineRun的模板执行——模板结尾的Next Steps也向读者提出了同样的挑战能否让一个使用硬编码 Pipeline 的PipelineRun成功执行支持范围与下一步扩展当前模板支持什么正如 README 所言模板目前只支持一个硬编码的 Pipeline纯粹用于演示。它验证的是Resolver 的骨架可以跑通而非真实的存储后端能力。如何向真实后端演进替换Resolve将硬编码返回改为从你偏好的存储后端拉取Git 仓库、云存储桶、HTTP 端点、OCI bundle 等完善Validate按需声明并校验url、revision、pathInRepo等真实参数实现RefSource()返回真实的 URI、Digest 与 EntryPoint供 Tekton Chains 生成 SLSA provenance参考成熟实现docs/how-to-write-a-resolver.md 提供了从零编写的完整分步指南含编译报错分析与每个接口方法的讲解而仓库中的真实 Resolver 实现可参考 pkg/remoteresolution/resolver/gitGit Resolver、pkg/remoteresolution/resolver/hubHub Resolver以及 pkg/remoteresolution/resolver/cluster集群内资源解析它们展示了Validate/Resolve在生产场景下的完整形态。关于远端解析机制本身的入门可继续阅读 docs/resolution-getting-started.md 与 docs/resolution.mdResolutionRequest的 API 细节见 docs/resolver-reference.md。赞分享云原生CI/CDDevOps后端【免费下载链接】pipelineA cloud-native Pipeline resource.项目地址https://gitcode.com/gh_mirrors/pipelin/pipeline点击查看免费下载相关推荐Tekton Pipelines远程解析实战从Git、OCI到编写自定义Resolver完整指南Tekton Pipelines远程解析实战从Git、OCI到编写自定义Resolver完整指南 Tekton Pipelines 远程解析Remote R云原生CI/CDDevOps后端Prisma graphql-yoga 常见 Resolver 模式实战数据模型扩展与自定义 Resolver 实现指南Prisma graphql yoga 常见 Resolver 模式实战数据模型扩展与自定义 Resolver 实现指南 本教程系统讲解在使用 graph后端数据库GraphQL基于 tldraw 的 WebGL 着色器模板minimal 示例从零到自定义实战指南基于 tldraw 的 WebGL 着色器模板minimal 示例从零到自定义实战指南 templates/shader/src/minimal/ 是 tld前端UI组件上一篇Shopify Flash List 瀑布流布局(Masonry)实现指南下一篇深入理解kohya-ss/sd-scripts中的SDXL模型训练技术创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表