尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Flux 2 OCI 工件支持:将 Kubernetes 清单打包、分发与对账到容器注册表

发布时间:2026/9/25 3:16:58

资讯中心
01
ARTICLE

Flux 2 OCI 工件支持:将 Kubernetes 清单打包、分发与对账到容器注册表

Flux 2 OCI 工件支持:将 Kubernetes 清单打包、分发与对账到容器注册表
云原生CI/CD容器编排DevOps【免费下载链接】flux2Open and extensible continuous delivery solution for Kubernetes. Powered by GitOps Toolkit.项目地址https://gitcode.com/gh_mirrors/fl/flux2点击查看免费下载本文基于 Flux 2 仓库中的 RFC-0003rfcs/0003-kubernetes-oci/README.md撰写系统讲解 Flux 的 OCI 工件支持如何用flux push artifact将本地 Kubernetes 清单打包为 OCI 工件推送到容器注册表如何用OCIRepository资源在集群内拉取、验签并交由 Kustomization 对账以及私仓认证与 Cosign 签名验证的配置方式。读完本文后你可以搭建一条“Git → OCI 注册表 → 集群”的 GitOps 分发链路。1. 背景与设计目标OCI 注册表正在演变为通用的工件存储方案。Flux 的 OCI 支持RFC 状态implemented创建于 2022-03-31正是基于这一趋势允许像从 Git 和 Bucket 拉取清单一样从容器注册表拉取 Kubernetes 清单及相关配置。RFC 的目标与边界如下目标Goals为 Flux CLI 增加将 Kubernetes 清单及相关配置打包为 OCI 工件的能力为 Flux source-controller 增加从 OCI 工件拉取配置的能力让用户能够轻松地从 Git 仓库、Bucket 切换到 OCI 仓库。非目标Non-Goals不强制要求包含 Kubernetes 清单的工件使用特定的 OCI media type。这意味着 Flux 能够处理任意类型的 OCI 工件即使它不是用 Flux CLI 创建的——这是后文层选择Layer selection机制存在的原因。2. 推送工件flux push artifactFlux 用户可以将会包含 Kubernetes 配置的本地目录打包为 tarball并以 OCI 工件形式推送到容器注册表flux push artifact oci://docker.io/org/app-config:v1.0.0 \ --source$(git config --get remote.origin.url) \ --revisionsha1:$(git rev-parse HEAD) \ --path./deployFlux CLI 生成的 OCI 工件约定了两个关键 media type配置层configmedia type 为application/vnd.cncf.flux.config.v1json内容层 media type 为application/vnd.cncf.flux.content.v1.targzip即--path指向的目录以targzip格式归档压缩。来源source与修订revision以 OpenContainers 标准注解写入 manifest{ schemaVersion: 2, mediaType: application/vnd.oci.image.manifest.v1json, annotations: { org.opencontainers.image.created: 2023-02-10T09:06:09Z, org.opencontainers.image.revision: sha1:6ea3e5b4da159fcb4a1288f072d34c3315644bcc, org.opencontainers.image.source: https://github.com/fluxcd/flux2 } }2.1 完整参数说明来自源码cmd/flux/push_artifact.go 中定义了全部命令行参数比 RFC 原文多了不少实战选项参数说明--path/-f清单目录或单个文件传-时从 stdin 读取--source来源地址如 Git URL必填--revision修订格式branch\|tagsha1:commit-sha必填--creds通用注册表凭据格式username[:password]provider 为 generic 时可用--provider注册表 provider默认generic可选aws/azure/gcp--ignore-paths以.gitignore语法设置忽略路径--add-ignore-paths追加忽略路径附加在--ignore-paths之后--annotations/-a自定义 OCI 注解格式keyvalue可多次指定--output/-o输出工件摘要的格式json或yaml--debug显示底层库日志排查重试等底层请求问题时有用--reproducible将 created 时间戳固定为1970-01-01T00:00:00Z保证工件摘要可复现--insecure-registry允许向非 TLS 注册表推送--resolve-symlinks将符号链接解析为其目标并拷贝进工件从源码可以看到几个值得注意的实现细节stdin 管道输入push_artifact.go 第 176–184 行 中--path -会把 stdin 内容落盘为临时文件再打包因此可以直接用kustomize build . | flux push artifact oci://... -f -推送构建产物可复现摘要第 220–222 行 显示--reproducible会把 metadata 的 created 时间设为 Unix 纪元从而让相同内容产生相同 digest推送并签名的一行流push_artifact.go 的官方示例第 54–62 行 演示了用--output json配合jq提取repositorydigest再交给cosign sign按 digest 签名digest_url $(flux push artifact \ oci://ghcr.io/org/config/app:$(git rev-parse --short HEAD) \ --source$(git config --get remote.origin.url) \ --revision$(git branch --show-current)sha1:$(git rev-parse HEAD) \ --path./path/to/local/manifest.yaml \ --output json | \ jq -r . | .repository .digest) cosign sign $digest_urlprovider 登录当--provider不是generic时CLI 通过 cmd/flux/oci.go 中的loginWithProvider调用fluxcd/pkg/auth获取对应云厂商AWS/Azure/GCP的注册表凭据provider 取值白名单定义在 internal/flags/source_oci_provider.go 第 28–33 行generic、aws、azure、gcp。2.2 标记版本flux tag artifact为方便将某个版本从一个环境晋级promotion到另一个环境CLI 提供打标命令可为同一工件打多个 tagflux tag artifact oci://docker.io/org/app-config:v1.0.0 --taglatest --tagproductioncmd/flux/tag_artifact.go 中--tag是StringSlice参数支持--creds与--provider认证循环调用ociClient.Tag逐个打标。2.3 列出工件flux list artifactsflux list artifacts oci://docker.io/org/app-configcmd/flux/list_artifact.go 在 RFC 基础上额外支持两个过滤参数--filter-semver按 semver 范围过滤 tag--filter-regex按正则过滤 tag以及--creds、--provider、--insecure-registry。输出列为ARTIFACT、DIGEST、SOURCE、REVISION对应org.opencontainers.image.source与org.opencontainers.image.revision注解。2.4 本地构建与拉取flux build artifact/flux pull artifact为了检视工件内容CLI 提供本地生成 tarball 与从远程拉取 tarball 的命令flux build artifact --path ./deploy --output tmp/artifact.tgz flux pull artifact oci://docker.io/org/app-config:v1.0.0 --output ./manifests从 cmd/flux/build_artifact.go 第 80–85 行 可见build支持--path/-p、--output/-o默认artifact.tgz、--ignore-paths、--add-ignore-paths与--resolve-symlinkscmd/flux/pull_artifact.go 第 60–63 行 的pull支持--output/-o解包目录、--creds、--provider、--insecure-registry。3. 集群内拉取OCIRepository资源用户可以在集群内定义一个从 OCI 仓库拉取清单的 sourceapiVersion: source.toolkit.fluxcd.io/v1beta2 kind: OCIRepository metadata: name: app-config namespace: flux-system spec: interval: 10m url: oci://docker.io/org/app-config ref: tag: v1.0.0要点RFC 明确约束spec.url指向容器镜像仓库格式为oci://host:port/org-name/repo-name不允许在 URL 中指定 tag 或 digest——该值由控制器用于拉取远程仓库的 tag 列表一个OCIRepository可以通过 tag、digest 或 semver 范围引用工件spec: ref: # one of tag: latest digest: sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2 semver: 6.0.x3.1 用 CLI 创建flux create source ocicmd/flux/create_source_oci.go 实现了flux create source oci [name]生成OCIRepository资源并等待其就绪。注意当前仓库代码导入的是source-controller/api/v1见 create_source_oci.go 第 32 行即当前版本生成的是 v1 API 的资源而 RFC 早期示例使用的是v1beta2。必填校验逻辑第 114–123 行--url必填且--tag、--tag-semver、--digest三者必须至少提供一个。完整参数如下参数对应 spec 字段说明--urlspec.urlOCI 仓库地址--tagspec.ref.tag工件 tag--tag-semverspec.ref.semvertag 的 semver 范围--digestspec.ref.digest工件 digest--secret-refspec.secretRefimage pull secretkubernetes.io/dockerconfigjson--proxy-secret-refspec.proxySecretRef代理地址与凭据 secret--service-accountspec.serviceAccountName引用 image pull secret 的 ServiceAccount--cert-refspec.certSecretRefTLS 证书 secret--providerspec.providergeneric默认/aws/azure/gcp--verify-providerspec.verify.provider目前仅支持cosign--verify-secret-refspec.verify.secretRef签名验证用 secret--verify-subject/--verify-issuerspec.verify.matchOIDCIdentityOIDC subject/issuer 正则--ignore-pathsspec.ignore忽略路径--insecurespec.insecure连接非 TLS纯 HTTP注册表--layer-selectorspec.layerSelector格式media-type:operation--layer-selector的解析见 parseLayerSelector第 251–271 行必须形如media-type:operationoperation 只允许extract或copy两个值。这说明相比 RFC 初稿只有mediaType的层选择器当前实现已扩展为“media type 操作”的结构。官方示例展示了非 Flux 工件的用法拉取 Helm chart 层并拷贝# Create an OCIRepository with OIDC signature verification flux create source oci podinfo \ --urlghcr.io/stefanprodan/manifests/podinfo \ --tag6.6.2 \ --interval10m \ --verify-providercosign \ --verify-subject^https://github.com/stefanprodan/podinfo/.github/workflows/release.ymlrefs/tags/6.6.2$ \ --verify-issuer^https://token.actions.githubusercontent.com$验证参数有明确的依赖校验指定--verify-secret-ref或 OIDC issuer/subject 时必须同时指定--verify-provider第 213–217 行否则报错。4. 层选择Layer selection默认情况下Flux 假设 OCI 工件的第一个层包含 Kubernetes 配置。对于用其他工具如 oras、crane创建的多层工件用户可以指定包含清单 tarball 的层的 media typespec: layerSelector: mediaType: application/vnd.cncf.flux.content.v1.targzip规则如果层选择器匹配到多个层使用第一个匹配指定 media type 的层Flux 要求 OCI 层必须是targzip压缩格式依据 OCI 镜像规范中的 gzip media types 约定。结合上文 CLI 的--layer-selector media-type:operation在 Kustomization 对账之外copy操作还支持把匹配层内容直接落盘例如消费 Helm chart 层这进一步印证了“Flux 可消费任意工件”的设计目标。5. 私仓认证从私有仓库拉取时Flux 用户可以在“用 Kubernetes secret 提供静态凭据”与“基于云的 OIDC将 IAM 角色绑定到 source-controller 的 Kubernetes ServiceAccount”之间选择。5.1 Basic auth适用于 DockerHub、GitHub、Quay、自建 Docker Registry 等私有仓库spec: secretRef: name: regcredsecretRef指向与OCIRepository同命名空间、类型为kubernetes.io/dockerconfigjson的 secretkubectl create secret docker-registry regcred \ --docker-serveryour-registry-server \ --docker-usernameyour-name \ --docker-passwordyour-pword如果凭据已挂载为某个 ServiceAccount 的 image pull secret可以改用spec: serviceAccountName: regsaCLI 侧也有对应的 secret 生成命令flux create secret oci [name]cmd/flux/create_secret_oci.go参数为--url、--username/-u、--password/-p支持--export先落盘再用 SOPS 加密入库flux create secret oci podinfo-auth \ --urlghcr.io \ --usernameusername \ --passwordpassword \ --export repo-auth.yaml5.2 客户端证书认证Client cert auth对于需要证书认证的私有仓库可提供客户端证书、私钥以及 CA 证书自签场景spec: certSecretRef: name: regcertkubectl create secret generic regcert \ --from-filecertFileclient.crt \ --from-filekeyFileclient.key \ --from-filecaFileca.crt5.3 OIDC 认证当 Flux 运行在 AKS、EKS 或 GKE 上时可以用一个授予 ACR/ECR/GCR 只读访问的IAM 角色绑定source-controllerspec: provider: awsprovider 取值generic、aws、azure、gcp与 CLI 侧 internal/flags/source_oci_provider.go 的白名单一致。未指定时默认为generic设置为云厂商时控制器使用对应云 SDK 认证。优先级规则若spec.secretRef与非 generic 的 provider 同时存在控制器优先使用 secret 中的静态凭据。6. 签名验证Verify artifacts为保证工件真实性Flux 使用 Sigstore Go SDK实现对 Cosign 密钥签名或 Cosign keyless 方式签名工件的验证。密钥验证——提供 Cosign 公钥spec: verify: provider: cosign secretRef: name: cosign-keyKeyless 验证——对使用 keyless 方式签名的公共工件应使用spec.verify.matchOIDCIdentity字段替代spec.verify.secretRefspec: verify: provider: cosign matchOIDCIdentity: - issuer: ^https://token.actions.githubusercontent.com$ subject: ^https://github.com/org/app-repository.*$matchOIDCIdentity条目的字段要求.issuer匹配 OIDC issuer 的正则.subject匹配证书中 subject 身份的正则条目之间是OR关系——任意一条匹配成功即视为身份验证通过。使用 keyless 方式时Flux 会在 Rekor 透明度日志rekor.sigstore.dev 托管的实例中验证签名。当前仓库中验证 provider 的取值白名单只有cosign一个internal/flags/source_oci_verify_provider.go 第 26–28 行与 RFC 的实现范围一致。7. 对账工件Reconcile artifactsOCIRepository可以直接替代GitRepository和Bucket作为 source。例如让一个 Kustomization 引用它并对账工件中的清单apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 kind: Kustomization metadata: name: app namespace: flux-system spec: interval: 10m sourceRef: kind: OCIRepository name: app-config path: ./8. 设计细节工件的存储格式与内部 Artifact客户端Flux CLI与服务端source-controller均使用fluxcd/pkg/oci库完成 push、pull、tag、list tags 等 OCI 操作。CLI 认证优先读取~/.docker/config.json与 Docker credential helpers在未安装 Docker 的云主机上CLI 通过上下文context方式完成 AWS、Azure、GCP 授权。Flux CLI 生成的工件 manifest 完整结构如下RFC 设计细节原文{ schemaVersion: 2, mediaType: application/vnd.oci.image.manifest.v1json, config: { mediaType: application/vnd.cncf.flux.config.v1json, size: 233, digest: sha256:1b80ecb1c04d4a9718a6094a00ed17b76ea8ff2bb846695fa38e7492d34f505c }, layers: [ { mediaType: application/vnd.cncf.flux.content.v1.targzip, size: 19081, digest: sha256:46c2b334705cd08db1a6fa46f860cd3364fc1a3636eea37a9b35537549086a1c } ], annotations: { org.opencontainers.image.created: 2023-02-10T09:06:09Z, org.opencontainers.image.revision: sha1:6ea3e5b4da159fcb4a1288f072d34c3315644bcc, org.opencontainers.image.source: https://github.com/fluxcd/flux2 } }拉取侧的内部表示source-controller 从工件中提取第一个匹配层并重新打包为内部sourcev1.Artifact。内部 artifact 的 revision 设为 OCI SHA256 digestOpenContainers 注解被拷贝进 artifact 的 metadata。RFC 给出的完整status示例apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: OCIRepository metadata: creationTimestamp: 2022-06-22T09:14:19Z finalizers: - finalizers.fluxcd.io generation: 1 name: podinfo namespace: oci resourceVersion: 6603 uid: 42e0b9f0-021c-476d-86c7-2cd20747bfff spec: interval: 10m ref: tag: 6.1.6 timeout: 60s url: oci://ghcr.io/stefanprodan/manifests/podinfo status: artifact: checksum: d7e924b4882e55b97627355c7b3d2e711e9b54303afa2f50c25377f4df66a83b lastUpdateTime: 2022-06-22T09:14:21Z metadata: org.opencontainers.image.created: 2023-02-10T09:06:09Z org.opencontainers.image.revision: sha1:b3b00fe35424a45d373bf4c7214178bc36fd7872 org.opencontainers.image.source: https://github.com/stefanprodan/podinfo.git path: ocirepository/oci/podinfo/3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de.tar.gz revision: sha256:3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de size: 1105 url: http://source-controller.flux-system.svc.cluster.local./ocirepository/oci/podinfo/3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de.tar.gz conditions: - lastTransitionTime: 2022-06-22T09:14:21Z message: stored artifact for revision sha256:3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de observedGeneration: 1 reason: Succeeded status: True type: Ready - lastTransitionTime: 2022-06-22T09:14:21Z message: stored artifact for revision sha256:3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de observedGeneration: 1 reason: Succeeded status: True type: ArtifactInStorage observedGeneration: 1 url: http://source-controller.flux-system.svc.cluster.local./ocirepository/oci/podinfo/latest.tar.gz注意status.artifact.revision是 OCI digest、metadata中保留了推送时写入的 OCI 注解——这正是第 2 节flux list artifacts能够展示 SOURCE/REVISION 列的原因。此外OCIRepository支持通过flux export source oci导出cmd/flux/export_source_oci.go加--with-credentials可连同静态凭据一并导出仓库内 cmd/flux/testdata/oci/ 目录存放了create、export、reconcile、suspend、resume等子命令的 golden 测试数据可作为预期输出的参照。该功能默认启用RFC “Enabling the feature” 一节。9. 端到端实操以 GHCR 为例以下两个 User Story 来自 RFC 原文构成一条完整的“发布 部署”链路。Story 1开发者将应用清单发布到与容器镜像相同的 GHCR 注册表1用 Docker 登录 GHCRdocker login ghcr.io -u ${GITHUB_USER} -p ${GITHUB_TOKEN}2构建并推送应用容器镜像docker build -t ghcr.io/org/my-app:v1.0.0 . docker push ghcr.io/org/my-app:v1.0.03编辑应用部署清单、设置新的镜像 tag 后将 Kubernetes 清单推送到 GHCRflux push artifact oci://ghcr.io/org/my-app-config:v1.0.0 \ --source$(git config --get remote.origin.url) \ --revisionsha1:$(git rev-parse HEAD)\ --path./deploy4用 cosign 为配置工件签名cosign sign --key cosign.key ghcr.io/org/my-app-config:v1.0.05将v1.0.0标记为 latestflux tag artifact oci://ghcr.io/org/my-app-config:v1.0.0 --tag latest6列出工件及其元数据$ flux list artifacts oci://ghcr.io/org/my-app-config ARTIFACT DIGEST SOURCE REVISION ghcr.io/org/my-app-config:latest sha256:45b95019d30af335137977a369ad56e9ea9e9c75bb01afb081a629ba789b890c https://github.com/org/my-app-config.git sha1:20b3a674391df53f05e59a33554973d1cbd4d549 ghcr.io/org/my-app-config:v1.0.0 sha256:45b95019d30af335137977a369ad56e9ea9e9c75bb01afb081a629ba789b890c https://github.com/org/my-app-config.git sha1:3f45e72f0d3457e91e3c530c346d86969f9f4034Story 2开发者基于 GHCR 上的 OCI 工件部署应用1创建可访问 GHCR 的 docker-registry secret使用 GitHub tokenkubectl create secret docker-registry my-app-regcred \ --docker-serverghcr.io \ --docker-username$GITHUB_USER \ --docker-password$GITHUB_TOKEN2创建包含 cosign 公钥的 secretkubectl create secret generic my-app-cosgin-key \ --from-filecosign.pubcosign/my-key.pub3定义OCIRepository按 semver 拉取最新配置版本并做签名验证apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: OCIRepository metadata: name: app-config namespace: default spec: interval: 10m url: oci://ghcr.io/org/my-app-config ref: semver: 1.x secretRef: name: my-app-regcred verify: provider: cosign secretRef: name: my-app-cosgin-key4创建 Kustomization 对账应用apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 kind: Kustomization metadata: name: app namespace: default spec: interval: 10m sourceRef: kind: OCIRepository name: app-config path: ./deploy prune: true wait: true timeout: 2m10. 实现历史与延伸阅读RFC 记录的实现里程碑原文档中的外链在此以文字表述2022-08-08由 source-controller 的 PR #788 部分实现2022-08-11随 flux2 v0.32.0 发布首个实现2022-08-29随 flux2 v0.33.0 发布“按 OCI media type 选择层”2022-09-29随 flux2 v0.35.0 发布 Cosign 工件验证2023-02-20随 flux2 v0.40.0 发布自定义 OCI media type 支持2023-10-31OIDC 身份验证在 source-controller 的 PR #1250 中实现。当前仓库中与本文主题相关的可继续深入的路径路径说明rfcs/0003-kubernetes-oci/README.md本文所依据的 RFC 原文cmd/flux/push_artifact.go推送工件命令含 stdin、reproducible、provider 登录cmd/flux/build_artifact.go / cmd/flux/pull_artifact.go本地构建 / 拉取工件cmd/flux/tag_artifact.go / cmd/flux/list_artifact.go打标与列工件含 semver/regex 过滤cmd/flux/create_source_oci.go创建OCIRepository含层选择器解析cmd/flux/create_secret_oci.go / cmd/flux/export_source_oci.goOCI 认证 secret 生成与 source 导出internal/flags/source_oci_provider.go / internal/flags/source_oci_verify_provider.goprovider 与验证 provider 取值白名单cmd/flux/testdata/oci/OCI 相关子命令的 golden 测试数据适用前提与限制spec.url中不可携带 tag/digest须在spec.ref中声明层必须为targzip压缩格式当前 CLI 的签名验证 provider 仅支持cosignkeyless 验证依赖 Rekor 透明度日志的可达性。赞分享云原生CI/CD容器编排DevOps【免费下载链接】flux2Open and extensible continuous delivery solution for Kubernetes. Powered by GitOps Toolkit.项目地址https://gitcode.com/gh_mirrors/fl/flux2点击查看免费下载相关推荐Kubeapps OCI注册表支持Flux插件配置完整指南Kubeapps OCI注册表支持Flux插件配置完整指南 Kubeapps作为Kubernetes应用管理平台通过Flux插件提供了强大的OCI注册表支持云原生后端前端OpenTofu 与 OCI 注册表从 OCI Distribution 协议入门到镜像化 Provider/Module 分发OpenTofu 与 OCI 注册表从 OCI Distribution 协议入门到镜像化 Provider/Module 分发 导读 OCIOpen Co云原生DevOps基础设施ZeroClaw 插件分发指南Ed25519 清单签名与注册表发布全流程ZeroClaw 插件分发指南Ed25519 清单签名与注册表发布全流程 ZeroClaw 的插件分发体系由两个相互独立的层次构成 Ed25519 清单签名人工智能AI Agent交互助手工具调用MCP Clients本地部署Agent 工作流RAG上一篇小米MiMo-Audio开源语音大模型迎来GPT-3时刻70亿参数实现跨模态少样本泛化下一篇如何通过 ACP 把 Claude Code agent 接入 marimo 聊天面板创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。