@@ -393,6 +393,12 @@ The image policy marker format is:
393393* `{"$imagepolicy": "<policy-namespace>:<policy-name>"}`
394394* `{"$imagepolicy": "<policy-namespace>:<policy-name>:tag"}`
395395* `{"$imagepolicy": "<policy-namespace>:<policy-name>:name"}`
396+ * `{"$imagepolicy": "<policy-namespace>:<policy-name>:digest"}`
397+
398+ > **Note**: The digest is only made available for `ImagePolicy` resources that
399+ > have `spec.digestReflectionPolicy` set to `IfNotPresent` or `Always`. When
400+ > set to `Never` (the default), the digest will not be reflected in the
401+ > `ImagePolicy` status.
396402
397403These markers are placed inline in the target YAML, as a comment. The "Setter" strategy refers to
398404[kyaml setters](https://github.com/fluxcd/flux2/discussions/107#discussioncomment-82746)
@@ -414,6 +420,7 @@ spec:
414420 image:
415421 repository: ghcr.io/stefanprodan/podinfo # {"$imagepolicy": "flux-system:podinfo:name"}
416422 tag: 5.0.0 # {"$imagepolicy": "flux-system:podinfo:tag"}
423+ digest: sha256:ec0119616bb8be9199575c05bfc23a6bf0fbdb0690ee15834e7b43bc3f4f6017 # {"$imagepolicy": "flux-system:podinfo:digest"}
417424` ` `
418425
419426Tekton `Task` example :
@@ -662,8 +669,8 @@ Two methods are available for authenticating container registers as
662669* [Automated authentication](../components/image/imagerepositories.md#provider)
663670mechanisms (where the controller retrieves the credentials itself and is only
664671available for the three major cloud providers), or
665- * a [`CronJob`](cron-job- image-auth .md) which does not rely on native platform support in Flux,
666- (instead storing credentials as Kubernetes secrets which are periodically refreshed.)
672+ * [Secret-based authentication](../components/ image/imagerepositories .md#secret-reference)
673+ where the user creates a Kubernetes secret with the credentials.
667674
668675Native authentication mechanisms have been implemented in Flux for the three major
669676cloud providers, but they have to be set in the individual `ImageRepository`
@@ -757,3 +764,112 @@ spec:
757764 alphabetical:
758765 order: asc
759766` ` `
767+
768+ # # Digest pinning
769+
770+ # ## Following `latest` tags
771+
772+ In some cases you may want to use the `latest` tag for some container images.
773+ A recommended GitOps way to do this is pinning the image digest after the
774+ tag in the image reference in your Git repository. For example :
775+
776+ ` ` ` yaml
777+ image: ghcr.io/stefanprodan/podinfo:latest@sha256:ec0119616bb8be9199575c05bfc23a6bf0fbdb0690ee15834e7b43bc3f4f6017
778+ ` ` `
779+
780+ This gives you control over the image version that is deployed in your cluster,
781+ simply restarting pods will no longer pull the latest image automatically and
782+ change the underlying software without you knowing. This also makes the updates
783+ traceable in your Git history.
784+
785+ With the right `ImagePolicy` configuration Flux is capable of polling image
786+ digests for a fixed tag. To configure Flux to watch the digest for `latest`,
787+ you can use an `ImagePolicy` like the following :
788+
789+ ` ` ` yaml
790+ apiVersion: image.toolkit.fluxcd.io/v1beta2
791+ kind: ImagePolicy
792+ metadata:
793+ name: podinfo
794+ namespace: flux-system
795+ spec:
796+ imageRepositoryRef:
797+ name: podinfo
798+ filterTags:
799+ pattern: '^latest$'
800+ policy:
801+ alphabetical: {}
802+ digestReflectionPolicy: Always
803+ interval: 10m
804+ ` ` `
805+
806+ The trick is filtering a single tag, the one you want to follow, and setting
807+ ` digestReflectionPolicy` to `Always`, which will tell Flux to fetch the digest
808+ for that tag according to the specified `interval`, once every ten minutes in
809+ the example above.
810+
811+ Then in the manifest where you want to use the `latest` tag, you can do the
812+ following :
813+
814+ ` ` ` yaml
815+ apiVersion: apps/v1
816+ kind: Deployment
817+ metadata:
818+ name: podinfo
819+ namespace: default
820+ spec:
821+ selector:
822+ matchLabels:
823+ app: podinfo
824+ template:
825+ metadata:
826+ labels:
827+ app: podinfo
828+ spec:
829+ containers:
830+ - name: podinfo
831+ image: ghcr.io/stefanprodan/podinfo:latest@sha256:ec0119616bb8be9199575c05bfc23a6bf0fbdb0690ee15834e7b43bc3f4f6017 # {"$imagepolicy": "flux-system:podinfo"}
832+ ` ` `
833+
834+ Or if you have a `HelmRelease` where `repository`, `tag` and `digest` are separate values :
835+
836+ ` ` ` yaml
837+ apiVersion: helm.toolkit.fluxcd.io/v2
838+ kind: HelmRelease
839+ metadata:
840+ name: podinfo
841+ namespace: default
842+ spec:
843+ values:
844+ image:
845+ repository: ghcr.io/stefanprodan/podinfo # {"$imagepolicy": "flux-system:podinfo:name"}
846+ tag: latest # {"$imagepolicy": "flux-system:podinfo:tag"}
847+ digest: sha256:ec0119616bb8be9199575c05bfc23a6bf0fbdb0690ee15834e7b43bc3f4f6017 # {"$imagepolicy": "flux-system:podinfo:digest"}
848+ ` ` `
849+
850+ # ## Achieving immutability for tags
851+
852+ Another common use case is preventing images from ever changing after a new tag
853+ is released. If later for whatever reason this tag is pushed with a different image,
854+ i.e. a different digest, and you don't want it to be updated e.g. due to the reasons
855+ of how you test and ship your software, you can set `digestReflectionPolicy` to
856+ `IfNotPresent` in the `ImagePolicy` :
857+
858+ ` ` ` yaml
859+ apiVersion: image.toolkit.fluxcd.io/v1beta2
860+ kind: ImagePolicy
861+ metadata:
862+ name: podinfo
863+ namespace: flux-system
864+ spec:
865+ imageRepositoryRef:
866+ name: podinfo
867+ policy:
868+ semver:
869+ range: 5.0.x
870+ digestReflectionPolicy: IfNotPresent
871+ ` ` `
872+
873+ In this case the digest will only be updated in the `ImagePolicy` status if a new
874+ tag is elected as latest, in which case both the tag and the digest will be updated
875+ together. Setting an `interval` in this case is not allowed.
0 commit comments