Skip to content

Latest commit

 

History

History

0005-promotion-markers

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

RFC-0005 Markers in YAML Comments for Application Promotion

Status: implemented

Creation date: 2022-11-10

Last update: 2022-11-10

Summary

Provide a mechanism by which Pipelines can target the correct manifest to effect a promotion, and make the appropriate change, when using the pull-request strategy.

Motivation

RFC 0003 describes the general promotion flow and defines the possibility for several distinct promotion strategies to be implemented. One of these promotion strategies further described in this document of the same RFC is one that creates a PR for promoting an app version to the next environment. For this to work the implementation will need to determine which field in which YAML manifest file in the repository contains the app version. One such approach is described herein.

Goals

  • Define a means for discovering a specific field in one or more YAML files located in a particular directory hierarchy.
  • Define a way to update that field in-place in all of the relevant files.

Proposal

Similar to what Flux offers with image update automations this RFC proposes to use well-formatted YAML comments for discovering and updating fields pertaining to a certain Pipeline's application. Here is an example of such a comment:

apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
spec:
  postBuild:
    substitute:
      podinfoVersion: 6.2.0 # {"$promotion": "default:podinfo:prod"}
[...]

This comment is a JSON object comprised of the following parts:

  • The key $promotion designates it as pertaining to pipeline promotions.
  • The value default:podinfo:prod refers to the environment called "prod" in the Pipeline resource named "podinfo" in the Kubernetes Namespace "default".

An implementation of this RFC has the following inputs and outputs:

Inputs

  • A Pipeline that a particular promotion is supposed to represent
  • An environment name. This can either be the target environment name ("prod" in the example above) or an environment preceeding the target environment (e.g. "dev"). In the latter case the implementation would have to fetch the Pipeline from the Kubernetes API and determine the target environment by itself.
  • A field value that is used to update the field targeted by the given promotion. This can be a Helm chart version, a Git commit SHA, an image tag or any other value that makes sense in the given user scenario.

Outputs

Given the inputs above an implementation is able to precisely determine which marker comment it is supposed to discover and with which value it shall update the targeted YAML field. The output of this operation is one or more modified YAML files.

Drawbacks to the proposed approach

  • Requires update to application manifests to know about pipelines.
  • Comments are often stripped by tooling
    • This includes our own Templates capability currently. There is a potential enhancement to solve this but it has its own drawbacks beyond cost of implementation.

Alternatives

This RFC is a retroactive definition of what has been implemented in pipeline-controller. No alternatives were considered for this initial delivery, but are recorded here for potential future iteration. The initial proposed approach was deemed viable primarily given its similar use within Flux. Coupled with the desire within Weave GitOps to both build natively on top of Flux, and to optimise for velocity and iteration based on customer feedback.

Scenarios

Base Scenario

As to illustrate a couple of potential alternatives, the following base scenario will be used.

There is a pipeline definition like the following.

apiVersion: pipelines.weave.works/v1alpha1
kind: Pipeline
metadata:
  name: podinfo-01
  namespace: flux-system
spec:
  appRef:
    apiVersion: helm.toolkit.fluxcd.io/v2beta1
    kind: HelmRelease
    name: podinfo
  environments:
    - name: dev
      targets:
        - namespace: podinfo-01-dev
          clusterRef:
            kind: GitopsCluster
            name: dev
            namespace: flux-system
    - name: prod
      targets:
        - namespace: podinfo-01-prod
          clusterRef:
            kind: GitopsCluster
            name: prod
            namespace: default
  promotion:
    pull-request:
      url: https://github.com/weaveworks/weave-gitops-clusters
      secretRef:
        name: promotion-credentials

Helm releases manifests exists like

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: podinfo
spec:
  interval: 5m
  chart:
    spec:
      chart: podinfo
      version: "6.0.1"
      sourceRef:
        kind: HelmRepository
        name: podinfo
      interval: 1m

Leverage to custom layout directory

This alternative solves the base scenario by allowing the pipeline owner to define based on pipeline properties the layout of repo to use the discovery. Any of the entities within the pipeline spec coudl be referenced for discovery.

For example using flux ways of organise repo. A monorepo could be navigated with the following configuration:

promotion:
    pull-request:
      url: https://github.com/weaveworks/weave-gitops-clusters
      match: "path(apps/{environment.name}/{application.name})"
      secretRef:
        name: promotion-credentials
  1. Discover the helm release manifest to promote: it will use spec.promotion.pull-request.match to determine the path for manifest to promote.
  2. Discover the field to promote: not required as we could resolve it via the schema spec.chart.spec.version.
Evaluation

Pros

  • Manifests discovery is an explicit strategy defined within pipeline boundaries (manifest and configuration repo).
  • Loosely couple solution
    • Pipeline behaviours like promotions don't impose restrictions in application manifests
    • Application manifests does not know about pipelines.

Cons

  • Same discovery mechanism applies to any application in any deployment target within any environment so there is a need for consistency.
  • It is unlikely that a single directory-structure strategy would cover all customer scenarios. For example version set by variable and using variable substiution. It would require to either support a set of strategies or to don't support some scenarios.

Leverage labels or annotations

This alternative tries to address the same problem using a solution based on kubernetes annotations. Similar to argocd resource tracking

An example could be

promotion:
    pull-request:
      url: https://github.com/weaveworks/weave-gitops-clusters
      match: "labels(app.kubernetes.io/environment=environment, annotherLabel)"
      match: "annotations(app.kubernetes.io/environment=environment, anotherAnnotation)"
      secretRef:
        name: promotion-credentials

With the resource annotated like the following

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: podinfo
  annotations:
    app.kubernetes.io/environment: "dev"
spec:
  interval: 5m
  chart:
    spec:
      chart: podinfo
      version: "6.0.1"
      sourceRef:
        kind: HelmRepository
        name: podinfo
      interval: 1m
  1. Discover the helm release manifest to promote: it will use spec.promotion.pull-request.match to determine the resources matching by label or annotation.
  2. Discover the field to promote: not required as we could resolve it via the schema spec.chart.spec.version.
Evaluation

Pros

  • Resolution leverages a kubernetes-native metadata solution based on labels or annotations so well understood by kubernetes users and supported by standard tooling.

Cons

  • Application manifests does need to know about pipelines.
  • Resolution logic split between pipeline and application manifests.

Implementation History