How to use a Corporate ImageStreams as a centrally maintained trusted source of container images

OpenShift provides a single Namespace containing all the ImageStreams that could be considered part of the platform: all these images are maintained and provided by OpenShift Origin, CentOS, Software Collections Library or Red Hat.

One separate Namespace for your Images

It could be considered a good practice, to separate all the ImageStreams provided by your own organization into one namespace, declaring them to be the “officially supported ACME Corp container images”. Let’s call this namespace ‘acme-corp’ throughout this article. These container images from ‘acme-corp’ could be provided and maintained by ACME Corp’s IT DevOps Team. You can read more on the interfaces between Dev and Ops on the Red Hat Enterprise Linux Blog.

Accessing them just like they are from ‘openshift’ namespace

OpenShift references Images (the OpenShift configuration item not the container image itself) in many situations: as part of a BuildConfig or as part of a DeploymentConfig, for example to start a new deployment when an ImageChange trigger is received from an ImageStreamTag.

To receive these triggers, and to use/pull a container image from a different namespace, some configurations need to be done:

  • Project A (the project using the image from our officially supported ACME Corp container images namespace) must be authorized to pull images
  • each project needs to be authorized to pull images from there
  • This configuration must be automated

Granting access from specific actions between namespaces could be accomplished by using

oc adm add-role-to-group system:image-puller system:serviceaccounts:project-a -n acme-corp

This will enable project A to pull images from any ImageStream in namespace acme-corp. You might repeat that for each project that shall be allowed to access ‘acme-corp’, but if we assume that all projects shall be granted access to ‘acme-corp’ ImageStream, a more elegant way is to modify the project template of OpenShift.

Configuring your Project Template

Modifying OpenShift’s template for projects is a simple operation:

  • a template must be created within the default namespace, and
  • the master must be reconfigured to use this template

So let’s see what the default project template looks like. It is embedded with OpenShift, so we can not find it somewhere on disk, we need to get it out and create a file to store it: `oc adm create-bootstrap-project-template -o yaml > acme-project-template.yaml`. To create (or later on replace) a template in OpenShift use `oc create -f acme-project-template.yaml`.

What you see within this template is a set of defaults configured by OpenShift for each project that gets created. And what we want to achieve is that each newly created project has access to ImageStreams in ‘acme-corp’ namespace. To grant that access we need to extend the `system:image-pullers` RoleBinding. This is basically the same activity show above: `oc adm add-role-to-group …`

Here you see the complete RoleBinding configuration item including access to namespace ‘acme-corp’. You can find the complete project template as a gitlab snippet.

- kind: RoleBinding
 apiVersion: v1
 groupNames:
 - system:serviceaccounts:acme-corp
 - system:serviceaccounts:${PROJECT_NAME}
 metadata:
 name: system:image-pullers
 namespace: ${PROJECT_NAME}
 roleRef:
 name: system:image-puller
 subjects:
 - kind: SystemGroup
 name: system:serviceaccounts:${PROJECT_NAME}
 userNames: null

Next: `oc replace -f acme-project-template.yaml` to replace/update the template within OpenShift.

Half way done, we only need to tell the OpenShift master to use this template for each newly created project. Keep in mind, if you are running more than one OpenShift Master, you need to do it on each master, as we will modify `/etc/origin/master/master-config.yaml`. And if you are using `oc cluster up`, there is no `master-config.yaml` on your local disk.

What we need to do is to replace the empty definition of `{“projectConfig”:{“projectRequestTemplate”}}` with a value of `”default/project-request”`.

I will leave it to the read how to achieve this goal in the most efficient way, maybe you use openshift-ansible or dsh… in the end, we need to reconfigure and restart all OpenShift Masters.

New Project defaults

Each project we create from now on will have access to ImageStreams within the ‘acme-corp’ namespace. Let’s validate:

[goern]$ oc new-project is-testing
Now using project "is-testing" on server "https://openshift.example.com".
[...]

[goern]$ oc get is
No resources found.

[goern]$ oc get is -n openshift
NAME DOCKER REPO TAGS UPDATED
registry...com/jboss-fuse-6/fis-karaf-openshift latest,2.0,1.0 + 2 more... 2 weeks ago
jboss-amq-62 registry...com/jboss-amq-6/amq62-openshift 1.1,1.1-2,latest + 2 more... 2 weeks ago
[...]

[goern]$ oc get is -n acme-corp
NAME DOCKER REPO TAGS UPDATED
redis 172.30.142.230:5000/acme-corp/redis latest 6 minutes ago

At this point we are able to use the ‘redis’ ImageStream out of ‘acme-corp’ namespace. Well done.

Conclusion

By customizing OpenShift Master’s projectConfig, we can not only use a custom project template to grant access from newly created project to other namespaces per default, we can also setting cluster wide node selectors, or configure the level of overcommitment.

Have Fun!