Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OCIRepository] Optimise OCI artifacts reconciliation #913

Merged
merged 3 commits into from
Sep 26, 2022

Conversation

stefanprodan
Copy link
Member

@stefanprodan stefanprodan commented Sep 23, 2022

Improvements

  • Fetch the upstream digest instead of pulling the whole artifact before verifying the Cosign signatures.
  • Pull the upstream artifact only if the fetched digest is different from the one in storage.
  • Add the image tag to the revision string <tag>/<digest-hex> for a better UX.
  • Add on optional field to the OCIRepository.spec.layerSelector called operation that accepts one of the following values: extract or copy. When the operation is set to copy, instead of extracting the compressed layer, the controller copies the compressed blob as-is to storage, thus keeping the original content unaltered.
  • Extract the layer selection to a dedicated function.

WIP Proposal

If we chose to add OCIRepository as a source to HelmReleases, then we'll enable chart verification (cosgin + keyless), insecure registries which are blocked upstream in Helm, reuse of the same chart between multiple HelmReleases, and easier debugging experience (no more hidden HelmChart objects, nor HelmRepositories).

With .spec.layerSelector Flux is compatible with package managers which bundle in the same OCI artifact an app container image with a helm chart, Flux will pick only the chart layer based on the specified media type and will copy the chart tarball to storage for helm-controller to consume.

Example of an OCIRepository which produces valid and verified Helm charts:

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
  name: podinfo-chart-signed
  namespace: apps
spec:
  interval: 5m
  url: oci://ghcr.io/stefanprodan/charts/podinfo
  ref:
    semver: "6.2.x"
  layerSelector:
    mediaType: "application/vnd.cncf.helm.chart.content.v1.tar+gzip"
  verify:
    provider: cosign # keyless (signed in CI with GitHub Actions OIDC)

Example of how a HelmRelease using the OCIRepository could look like:

apiVersion: helm.toolkit.fluxcd.io/v2beta2
kind: HelmRelease
metadata:
  name: podinfo
  namespace: apps
spec:
  interval: 10m
  chartFrom: 
    kind: OCIRepository
    name: podinfo-chart-signed
  valuesFrom:
  - kind: ConfigMap
    name: podinfo-values

@stefanprodan stefanprodan added the area/oci OCI related issues and pull requests label Sep 23, 2022
api/v1beta2/ocirepository_types.go Outdated Show resolved Hide resolved
controllers/ocirepository_controller.go Outdated Show resolved Hide resolved
controllers/ocirepository_controller.go Outdated Show resolved Hide resolved
controllers/ocirepository_controller.go Outdated Show resolved Hide resolved
@stefanprodan stefanprodan marked this pull request as ready for review September 23, 2022 15:55
Add on optional field to the `OCIRepository.spec.layerSelector` called `operation` that accepts one of the following values: `extract` or `copy`. When the operation is set to `copy`, instead of extracting the compressed layer, the controller copies the compressed blob as it is to storage, thus keeping the original content unaltered.

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
- Fetch the upstream digest before validation and pulling
- Pull artifact only if the upstream digest is different from the one in storage
- Add the image tag to the revision string `<tag>/<digest-hex>` for a better UX
- Extract the layer processing to a dedicated function

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
@stefanprodan stefanprodan changed the title [OCIRepository] Add option to copy the OCI layer to storage [OCIRepository] Optimise OCI artifacts reconciliation Sep 24, 2022
@stefanprodan stefanprodan added the enhancement New feature or request label Sep 24, 2022
docs/spec/v1beta2/ocirepositories.md Outdated Show resolved Hide resolved
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
@darkowlzz
Copy link
Contributor

I think I found a bug in this.
When I create a new artifact with copy operation:

spec:
  interval: 1m0s
  layerSelector:
    mediaType: application/vnd.docker.image.rootfs.diff.tar.gzip
    operation: copy
  provider: generic
  ref:
    tag: 6.1.6
  timeout: 60s
  url: oci://ghcr.io/stefanprodan/manifests/podinfo
status:
  artifact:
    checksum: ad804afeae14a8a5c9a45b29f4931104a887844691d040c8737ee3cce6fd6735
    lastUpdateTime: "2022-09-26T15:33:27Z"
    metadata:
      org.opencontainers.image.created: "2022-08-08T12:31:25+03:00"
      org.opencontainers.image.revision: 6.1.6/450796ddb2ab6724ee1cc32a4be56da032d1cca0
      org.opencontainers.image.source: https://github.com/stefanprodan/podinfo.git
    path: ocirepository/default/podinfo-layer/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3.tar.gz
    revision: 6.1.6/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3
    size: 1091
    url: http://source-controller.flux-system.svc.cluster.local./ocirepository/default/podinfo-layer/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3.tar.gz
  conditions:
  - lastTransitionTime: "2022-09-26T15:33:27Z"
    message: stored artifact for digest '6.1.6/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3'
    observedGeneration: 1
    reason: Succeeded
    status: "True"
    type: Ready
  - lastTransitionTime: "2022-09-26T15:33:27Z"
    message: stored artifact for digest '6.1.6/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3'
    observedGeneration: 1
    reason: Succeeded
    status: "True"
    type: ArtifactInStorage
  observedGeneration: 1
  url: http://source-controller.flux-system.svc.cluster.local./ocirepository/default/podinfo-layer/latest.tar.gz

Note the status.artifact.checksum value.
And I change the operation to extract:

spec:
  interval: 1m0s
  layerSelector:
    mediaType: application/vnd.docker.image.rootfs.diff.tar.gzip
    operation: extract
  provider: generic
  ref:
    tag: 6.1.6
  timeout: 60s
  url: oci://ghcr.io/stefanprodan/manifests/podinfo
status:
  artifact:
    checksum: ad804afeae14a8a5c9a45b29f4931104a887844691d040c8737ee3cce6fd6735
    lastUpdateTime: "2022-09-26T15:33:27Z"
    metadata:
      org.opencontainers.image.created: "2022-08-08T12:31:25+03:00"
      org.opencontainers.image.revision: 6.1.6/450796ddb2ab6724ee1cc32a4be56da032d1cca0
      org.opencontainers.image.source: https://github.com/stefanprodan/podinfo.git
    path: ocirepository/default/podinfo-layer/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3.tar.gz
    revision: 6.1.6/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3
    size: 1091
    url: http://source-controller.flux-system.svc.cluster.local./ocirepository/default/podinfo-layer/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3.tar.gz
  conditions:
  - lastTransitionTime: "2022-09-26T15:33:27Z"
    message: stored artifact for digest '6.1.6/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3'
    observedGeneration: 2
    reason: Succeeded
    status: "True"
    type: Ready
  - lastTransitionTime: "2022-09-26T15:33:27Z"
    message: stored artifact for digest '6.1.6/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3'
    observedGeneration: 2
    reason: Succeeded
    status: "True"
    type: ArtifactInStorage
  observedGeneration: 2
  url: http://source-controller.flux-system.svc.cluster.local./ocirepository/default/podinfo-layer/latest.tar.gz

The checksum remains the same although the new generation of the object has been reconciled successfully, gen 2.

But if I create a new object from scratch with extract operation:

spec:
  interval: 1m0s
  layerSelector:
    mediaType: application/vnd.docker.image.rootfs.diff.tar.gzip
    operation: extract
  provider: generic
  ref:
    tag: 6.1.6
  timeout: 60s
  url: oci://ghcr.io/stefanprodan/manifests/podinfo
status:
  artifact:
    checksum: d7e924b4882e55b97627355c7b3d2e711e9b54303afa2f50c25377f4df66a83b
    lastUpdateTime: "2022-09-26T15:36:19Z"
    metadata:
      org.opencontainers.image.created: "2022-08-08T12:31:25+03:00"
      org.opencontainers.image.revision: 6.1.6/450796ddb2ab6724ee1cc32a4be56da032d1cca0
      org.opencontainers.image.source: https://github.com/stefanprodan/podinfo.git
    path: ocirepository/default/podinfo-layer/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3.tar.gz
    revision: 6.1.6/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3
    size: 1105
    url: http://source-controller.flux-system.svc.cluster.local./ocirepository/default/podinfo-layer/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3.tar.gz
  conditions:
  - lastTransitionTime: "2022-09-26T15:36:19Z"
    message: stored artifact for digest '6.1.6/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3'
    observedGeneration: 1
    reason: Succeeded
    status: "True"
    type: Ready
  - lastTransitionTime: "2022-09-26T15:36:19Z"
    message: stored artifact for digest '6.1.6/dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3'
    observedGeneration: 1
    reason: Succeeded
    status: "True"
    type: ArtifactInStorage
  observedGeneration: 1
  url: http://source-controller.flux-system.svc.cluster.local./ocirepository/default/podinfo-layer/latest.tar.gz

That's the actual checksum of the extracted content of the artifact.

@hiddeco hiddeco restored the oci-copy-layer branch September 28, 2022 11:22
@stefanprodan stefanprodan deleted the oci-copy-layer branch May 3, 2024 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/oci OCI related issues and pull requests enhancement New feature or request
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

3 participants