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

[RFC-0002] Flux OCI support for Helm #2597

Merged
merged 5 commits into from
Apr 13, 2022
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions rfcs/helm-oci/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# RFC-xxxx Flux OCI support for Helm

**Status:** provisional

**Creation date:** 2022-03-30

**Last update:** 2022-03-30

## Summary

Given that Helm v3.8 supports [OCI](https://helm.sh/docs/topics/registries/) for package distribution,
we should extend the Flux Source API to allow fetching Helm charts from container registries.

## Motivation

Helm OCI support is one of the most requested feature in Flux
as seen on this [issue](https://github.com/fluxcd/source-controller/issues/124).

With OCI support, Flux users can automate chart updates to Git in the same way
they do today for container images.

### Goals

- Add support for fetching Helm charts stored as OCI artifacts with minimal API changes to Flux.
makkes marked this conversation as resolved.
Show resolved Hide resolved
- Make it easy for users to switch from [HTTP/S Helm repositories](https://github.com/helm/helm-www/blob/416fabea6ffab8dc156b6a0c5eb5e8df5f5ef7dc/content/en/docs/topics/chart_repository.md)
to OCI repositories.

### Non-Goals

- Introduce a new API kind for referencing charts stored as OCI artifacts.

## Proposal

Introduce an optional field called `type` to the `HelmRepository` spec.

When not specified, the `spec.type` field defaults to `Default` which preserve the current `HelmRepository` API behaviour.

When the `spec.type` field is set to `OCI`, the `spec.url` field must be prefixed with `oci://` (to follow the Helm conventions).
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved
For `oci://` URLs, source-controller will use the Helm SDK and the `oras` library to connect to the OCI remote storage.
For authentication, the controller will use Kubernetes secrets of `kubernetes.io/dockerconfigjson` type.
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved

### User Stories

#### Story 1

> As a developer I want to use Flux `HelmReleases` that refer to Helm charts stored
> as OCI artifacts in GitHub Container Registry.

First create a secret using a GitHub token that allows access to GHCR:

```sh
kubectl create secret docker-registry ghcr-charts \
--docker-server=ghcr.io \
--docker-username=$GITHUB_USER \
--docker-password=$GITHUB_TOKEN
```

Then define a `HelmRepository` of type `OCI` and reference the `dockerconfig` secret:

```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
name: ghcr-charts
namespace: default
spec:
type: OCI
url: oci://ghcr.io/my-org/charts/
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved
secretRef:
name: ghcr-charts
```

And finally in Flux `HelmReleases`, refer to the ghcr-charts `HelmRepository`:

```yaml
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: my-app
namespace: default
spec:
interval: 60m
chart:
spec:
chart: my-app
version: '1.0.x'
sourceRef:
kind: HelmRepository
name: ghcr-charts
interval: 1m # check for new OCI artifacts every minute
```

#### Story 2

> As a platform admin I want to automate Helm chart updates based on a semver ranges.
> When a new patch version is available in the container registry, I want Flux to open a PR
> with the version set in the `HelmRelease` manifests.

Given that charts are stored in container registries, you can use Flux image automation
and patch the chart version in Git, in the same way Flux works for updating container image tags.

Define an image registry and a policy for the chart artifact:

```yaml
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageRepository
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved
metadata:
name: my-app
namespace: default
spec:
image: ghcr.io/my-org/charts/my-app
interval: 1m0s
---
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImagePolicy
metadata:
name: my-app
namespace: default
spec:
imageRepositoryRef:
name: my-app
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved
policy:
semver:
range: 1.0.x
```

Then add the policy marker to the `HelmRelease` manifests in Git:

```yaml
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: my-app
namespace: default
spec:
interval: 60m
chart:
spec:
chart: my-app
version: 1.0.0 # {"$imagepolicy": "default:my-app:tag"}
sourceRef:
kind: HelmRepository
name: ghcr-charts
interval: 1m
```

### Alternatives

We could introduce a new API type e.g. `HelmRegistry` to hold the reference to auth secret,
as proposed in [#2573](https://github.com/fluxcd/flux2/pull/2573).
That is considered unpractical, as there is no benefit for users in having a dedicated kind instead of
a `type` field in the current `HelmRepository` API. Adding a `type` field to the spec follows the Flux
Bucket API design, where the same Kind servers different implementations: AWS S3 vs Azure Blob vs Google Storage.

## Design Details

In source-controller we'll add a new predicate for filtering `HelmRepositories` based on the `spec.type` field.
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved

The current `HelmRepositoryReconciler` will be renamed to `HelmRepositoryDefaultReconciler`,
it's scope remains unchanged, and it will handle only objects with `type: Default`.

We'll introduce a new reconciler named `HelmRepositoryOCIReconciler`, that will handle
objects with `type: OCI`. This reconciler will set the `HelmRepository` Ready status to
`False` if the URL is not prefixed with `oci://`, otherwise the Ready status will be set to `True`.

The current `HelmChartReconciler` will be renamed to `HelmChartDefaultReconciler`,
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved
it's scope remains unchanged, and it will handle only objects that refer to `HelmRepositories` with `type: Default`.

For `type: OCI` we'll introduce a new reconciler `HelmChartOCIReconciler` that uses `oras` to download charts
and their dependencies.

### Enabling the feature

The feature is enabled by default.