Can an OpenShift CronJob benefit from ImageStream?

1.4k views Asked by At

I have my CronJob working fine without the use of an image stream.

The job runs every 15 minutes and always pulls a tagged image, e.g. my-cron:stable.

Since the image is always pulled and the schedule tells the cluster when to run my job, what do I gain from knowing that there's an updated version of my image?

If the image changes and there's a running instance of my job, I want the job to complete using the current version of the image.

In the next scheduled run the updated image is pulled (AlwaysPull). So it seems I don't gain much tracking changes to an image stream for cron jobs.

2

There are 2 answers

4
Sam Morris On BEST ANSWER

By using an ImageStream reference, you can avoid having to include the container image repository hostname hostname and port, and the project name in your Cron Job definition.

The docker repository reference looks likes this:

image-registry.openshift-image-registry.svc:5000/my-project/my-is:latest

The value of the equivalent annotation placed on a Cron Job looks like this:

[
  {
    "from": {
      "kind": "ImageStreamTag",
      "name": "my-is:latest"
    },
    "fieldPath": "spec.jobTemplate.spec.template.spec.containers[?(@.name==\"my-container\")].image"
  }
]

On the one hand, this is longer. On the other hand, it includes less redundant information.

So, compared to other types of kubernetes resources, Image Streams don't add a great deal of functionality to Cron Jobs. But you might benefit from not having to hardcode the project name if for instance you kept the Cron Job YAML in Git and wanted to apply it to several different projects.


Kubernetes-native resources which contain a pod can be updated automatically in response to an image stream tag update by adding the image.openshift.io/triggers annotation.

This annotation can be placed on CronJobs, Deployments, StatefulSets, DaemonSets, Jobs, ReplicationControllers, etc.

The easiest way to do this is with the oc command.

$ oc set triggers cronjob/my-cronjob
NAME                 TYPE    VALUE  AUTO
cronjobs/my-cronjob  config         true

$ oc set triggers cronjob/my-cronjob --from-image=my-is:latest -c my-container
cronjob.batch/my-cronjob updated

$ oc set triggers cronjob/my-cronjob
NAME                 TYPE    VALUE                        AUTO
cronjobs/my-cronjob  config                               true
cronjobs/my-cronjob  image   my-is:latest (my-container)  true

The effect of the oc set triggers command was to add the annotation to the CronJob, which we can examine with:

$ oc get cronjob/my-cronjob -o json | jq '.metadata.annotations["image.openshift.io/triggers"]' -r | jq
[
  {
    "from": {
      "kind": "ImageStreamTag",
      "name": "my-is:latest"
    },
    "fieldPath": "spec.jobTemplate.spec.template.spec.containers[?(@.name==\"my-container\")].image"
  }
]

This is documented in Images - Triggering updates on image stream changes - but the syntax in the documentation appears to be wrong, so use oc set triggers if you find that the annotation you write by hand doesn't work.

0
Andrew On

ImageStream triggers only BuildConfigs and DeploymentConfigs, as per https://docs.openshift.com/container-platform/4.7/openshift_images/image-streams-manage.html . Upstream kubernetes doesn't have a concept of ImageStream, so there is no triggering for 'vanilla' resource types. CronJob is used both in openshift and kubernetes (apiVersion: batch/v1beta1), and AFAIK the only way to access an imagestream is to use full path to internal registry, which is not that convenient. Your cronjob won't restart or won't be stopped for some reason, if imagestream is updated, because from kubernetes standpoint the image is pulled only when cronjob has been triggered, and after that it just waits for a job to complete.

As i see it - you are not gaining much from using imagestreams, because one of the main points, ability to use triggers, is not usable for cronjobs. The only reason to use it in CronJobs is if you are pushing directly to internal registry for some reason, but that's a bad practice too.

See following links for reference:

Quoting redhat solution here:

Resolution

When using an image stream inside the project to run a cronjob, specify the full path of the image:

[...]
spec:
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            image: docker-registry.default.svc:5000/my-app-namespace/cronjob-image:latest
            name: cronjob-image
[...]

Note that you can also put the ':latest' (or a specific tag) after the image.

In this example, the cronjob will use the imagestream cronjob-image from project my-app-namespace:

$ oc get is -n my-app-namespace [...]
imagestream.image.openshift.io/cronjob-image  
docker-registry.default.svc:5000/my-app-namespace/cronjob-image  
latest   27 minutes ago

Root Cause

The image was specified without its full path to the internal docker registry. If the full path is not used (i.e. putting only cronjob-image, OpenShift won't be able to find it.[...]