Skip to content

Commit af9985f

Browse files
authored
Merge pull request fluxcd#2216 from fluxcd/update-digests
Add guides for image digest pinning
2 parents 8d8296f + f01d152 commit af9985f

File tree

1 file changed

+118
-2
lines changed

1 file changed

+118
-2
lines changed

content/en/flux/guides/image-update.md

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

397403
These 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

419426
Tekton `Task` example:
@@ -662,8 +669,8 @@ Two methods are available for authenticating container registers as
662669
* [Automated authentication](../components/image/imagerepositories.md#provider)
663670
mechanisms (where the controller retrieves the credentials itself and is only
664671
available 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

668675
Native authentication mechanisms have been implemented in Flux for the three major
669676
cloud 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

Comments
 (0)