How to Simplify Container Image Management in Kubernetes with OpenShift Image Streams

Over the course of the past few weeks, I have been gathering feedback around Image Streams. This feature can cause a lot of misunderstanding and confusion, even for long-time users. As a maintainer of this feature, I felt obligated to explain in detail what Image Streams are, and how regular users can benefit from using them. Hopefully, this article will help you to understand Image Streams better. If you still have questions after reading this article, please let me know – I would like to hear from you.

Pic. 1. Image Stream python pointing to two external docker registries (tags 3.5 and 3.6), one internal registry, and to a different tag.

Theory

1. What is an Image Stream?

An Image Stream contains all of the metadata information about any given image that is specified in the Image Stream specification. It is important to note that an Image Stream does not contain the actual image data. Ultimately it points either to an external registry, like registry.access.redhat.com, hub.docker.com, etc., or to OpenShift’s internal registry (if one is deployed in your cluster). Alternately, it can also point to a different Image Stream (see Pic. 1).

2. What is the benefit of using an Image Stream over a regular image?

An Image Stream provides a stable pointer to an image using various identifying qualities. This means that even if the source image changes, the Image Stream will still point to a known-good version of the image, ensuring that your application will not break unexpectedly.
How does it track a known-good version? Users tend to refer to images by one of their tags because these are easily human-readable. However, every image can also be identified by its ID, which is not really human-readable (it is a SHA256 string and image:latest reads much better than image@sha256:8698dcd8eb…). If the author of an image pushes a newer version without properly tagging the image, they can accidentally create a new distinct image (with newer version information). While there are use cases when this is desired and perfectly reasonable (like security updates), often times it can impact our application in unexpected ways (eg. configuration change causing our application not to start).

3. How can Image Streams be updated?

There are several options for updating Image Streams:

  1. Manually, by invoking oc import-image and specifying either the entire Image Stream or a particular Image Stream Tag (see how to create an Image Stream from an existing image).
  2. By setting a tag policy to scheduled (see how periodically import my tag).
  3. By pushing an image to internal registry, which will be then reflected in the appropriate image stream change (this also works for creating new Image Streams).

4. What are Image Stream Tags and Image Stream Images?

By now you should have a better understanding of what an Image Stream is – a mapping between tags and actual images stored either in the internal or external registry. Similarly, an Image Stream Tag is the actual pointer from within Image Stream to a currently recorded external image. It is always in the form <image_stream_name>:<tag_name>.
Meanwhile, the Image Stream Image is the actual pointer from within an Image Stream to a particular external image by its ID. It is always in the form <image_stream_name>@<image_id>.

5. How is an Image Stream created?

There are multiple options here; see the next section of this article for a simple overview how to create, edit and remove contents of an Image Stream.

6. Is it possible to create Image Streams automatically?

Yes. Whenever you are doing a push into internal registry an Image Stream will be created for you describing the image you just pushed.

7. What are Image Change Triggers?

Some controllers can be automatically started using Image Change Triggers. For instance, Builds and Deployments can be automatically started when a given Image Stream is modified. This is achieved by monitoring that particular Image Stream and notifying the controller (the Build or Deployment) when a change was detected.

8. How can I use images from a remote registry to trigger actions?

To use Image Change Triggers (described in the previous question) in conjunction with images stored in external registries, you should first create an Image Stream and set its policy to scheduled. Then you can use Image Change Triggers as previously mentioned. Now each time a newer version of the image is imported from the external registry, the usual triggers invoking Builds or Deployments can take place.

9. What are the three biggest advantages of using Image Streams?

  1. You can tag, rollback a tag, and quickly deal with images, without having to re-push using a docker command line.
  2. You can trigger Builds and Deployments when new image is pushed to the registry, or schedule the import to do it later.
  3. You can share images using fine-grained access and quickly distribute images across your teams.

Practice

In this section we will walk through the exercise of creating an Image Stream like the one shown in Pic. 1. Per the diagram, this Image Stream points to two external images (Image Stream Tags 3.5 and 3.6). After that, we’ll create a latest Image Stream Tag pointing to another Image Stream Tag within the same Image Stream (3.6). If you want to go even further, you can then work out how to create internal Image Stream Tag on your own!.

1. How do I create an Image Stream from an existing image?

To create a new Image Stream named “python” with a single tag pointing to 3.5,
one needs to invoke following command:

oc import-image python:3.5 --from=centos/python-35-centos7 --confirm

Let us break this command into pieces:

  • python:3.5python is the new Image Stream that will be created as a result of this invocation. Additionally we are explicitly pointing that the imported image will be kept under the 3.5 Image Stream Tag of that Image Stream. If no tag part is specified the command will use latest.
  • --from=centos/python-35-centos7 – states what external image the Image Stream Tag will point to.
  • --confirm – informs the system that the python Image Stream should be created, if this is omitted and there is no python Image Stream, you will be presented with an error message.

At any point in time if you want to re-import the Image Stream, either entirely or just a single tag, use oc import-image and pass the name of the entire Image Stream or just a particular Image Stream Tag (like python:3.5 in the above example).

2. How do I get information about Image Streams?

oc describe is the universal way of getting a user-readable information about any object in the OpenShift cluster. This will give you general information about the Image Stream and detailed information about all the tags it is pointing to. In our example from the previous question we would invoke:

oc describe is/python

to get all the information available about entire Image Stream,

oc describe istag/python:latest

to get all the information available about particular Image Stream Tag.

3. How do I add more tags to the current Image Stream?

To add a latest tag that points to one of the existing tags, you can use the oc tag command:

oc tag python:3.5 python:latest

Examining the python ImageStream with oc describe should assure us that we have exactly two tags, one (3.5) pointing at the external docker image and another one (latest) pointing to a different tag in the same Image Stream.

4. How do I add a tag pointing to an external image?

All tag-related operations are performed using oc tag command, and adding tags pointing to internal or external images is not any different:

oc tag docker.io/python:3.6.0 python:3.6

This command maps the docker.io/python:3.6.0 image to the 3.6 tag in our python Image Stream. In the case when the external image is secured, you will need to create a Secret with credentials for accessing that registry. See our documentation for more details.

5. How do I update the current tag?

We have just updated our Image Stream with a new tag and now we want to update the latest tag to reflect the newer 3.6 tag in our Image Stream. Not surprisingly, we are going to use oc tag once again:

oc tag python:3.6 python:latest

6. How can I tell the system to periodically import my tag?

When we are working with an external registry, we would like to be able to periodically re-import the image to get latest security updates, etc. To do so we will use a --scheduled flag for the oc tag command like so:

oc tag docker.io/python:3.6.0 python:3.6 --scheduled

This will inform the system that this particular Image Stream Tag should be periodically checked for updates. Currently, this period is a cluster-wide setting, and by default, it is set to 15 minutes.

Only an Image Stream Tag pointing to an external docker registry can be periodically checked for updates.

To remove the periodical check, re-run above command but omit the --scheduled flag. This will reset its behavior to default.

7. How do I remove a tag from an Image Stream?

Eventually, you will want to remove old tags from your Image Stream, and yet again we are going to use oc tag for that particular use case:

oc tag -d python:3.5

Conclusions

Hopefully, this short overview will help you better understand Image Streams and how to benefit from them. I highly recommend going through our documentation to learn more about more advanced possibilities the Image Streams provide.

I would like to hear from you! If you have some ideas or you are struggling with some concepts, please do not hesitate to email or tweet me your questions.

Categories
OpenShift Container Platform, OpenShift Dedicated, OpenShift Ecosystem, OpenShift Online, OpenShift Origin, Products
Tags
, , ,
  • Raul

    I have been struggling with the imagestreams, I got them created within the oc new-app but sometimes they loose their label and I am not able to delete it by label. I have set a script to check whether the imagestream has label or not and I cannot catch when it loose it. Can you tell how the labels are managed in the IS ? they get removed when a oc delete all command is issued?