Configure a project in an IBM Cloud Red Hat OpenShift cluster to access the IBM Cloud Container Registry

This cheat sheet is about, how to configure a project in an IBM Cloud Red Hat OpenShift to access the IBM Cloud Container Registry. We use an image pull secret to access container images from IBM Cloud Container Registries. The cheat sheet combines different steps, which are available in the IBM Cloud documentation you find here.

We configure a created project in OpenShift to access two different IBM Cloud Container Registries.

The IBM Cloud Red Hat OpenShift cluster is a part of IBM Cloud Account ONE.

The image below shows a simplified architecture overview:

Note: The cheat sheet references to source code, which is available in that example GitHub project. In case you want to follow the steps, you can clone the GitHub project to your local computer.

The blog post is organized in five following sections:

  1. Setup the IBM Cloud Container Registry of IBM Cloud Account TWO
  2. Build and push the container image to the IBM Cloud Container Registry of IBM Cloud Account TWO
  3. Configure the OpenShift project to access the IBM Cloud Container Registry of IBM Cloud Account ONE
  4. Configure the OpenShift project to access the IBM Cloud Container Registry of IBM Cloud Account TWO
  5. Deploy the container image to the OpenShift project

1. Setup the IBM Cloud Container Registry of IBM Cloud Account TWO

On our local computer we use the IBM Cloud CLI and the IBM Cloud "container-registry" CLI plug-in for the configuration of the container registry, and Docker to build and push the image.

Step 1: Log in to IBM Cloud (IBM Cloud Account TWO)

ibmcloud login (-sso)

Step 2: Log in to IBM Cloud Container Registry

ibmcloud cr login

Example output:

Logging in to 'us.icr.io'...
Logged in to 'us.icr.io'.
OK

Step 3: Create a Namespace inside the IBM Cloud Container Registry

Let us name the Namespacevend-openshift.

ibmcloud cr namespace-add vend-openshift


2. Build and push the container image to the IBM Cloud Container Registry (IBM Cloud Account TWO)

Now we build the container image locally and push the image to the IBM Cloud Container Registry.

Step 1: Build the container image locally

We name our container image close to the naming convention of Red Hat.

Format <Registry[:Port]>/<Namespace>/<image>:<tag>

We use the us region (us).icr.io of the container registry, with the newly created namespace called vend-openshift

docker build -t "us.icr.io/vend-openshift/vend:v1" -f Dockerfile .

Step 2: Push the container image to the IBM Cloud Container Registry

docker push "us.icr.io/vend-openshift/vend:v1"

Step 3: List the existing container images

ibmcloud cr image-list


3. Configure the OpenShift project to access the IBM Cloud Container Registry of IBM Cloud Account ONE

Now we will configure the newly created OpenShift project to access the IBM Cloud Container Registry from IBM Cloud Account ONE. The following image is a simplified architecture overview:

Step 1: Log in to the OpenShift custer

Step 2: Get the existing projects

oc get projects

Step 3: Create a new project

Name the project vend-ibm

oc new-project vend-ibm

Step 3: Get the existing secrect for the IBM Cloud Container Registry (icr-io) from the default project in the OpenShift cluster

The secrect is called all-icr-io. (i[IBM]c[Container].r[Registry].io)

oc get secrets -n default | grep icr-io

Example output:

all-icr-io                          kubernetes.io/dockerconfigjson        1      5d21h

Step 4: Copy the all-icr-io image pull secret from the default project to our newly created.

oc get secret all-icr-io -n default -o yaml | sed 's/default/vend-ibm/g' | oc create -n vend-ibm -f -  

In the secret content we do rename the namespace value from default to vend-ibm the yaml below.

apiVersion: v1
data:
  .dockerconfigjson: aU5LifX19Q1g
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: '{"apiVersion":"v1","data":{".dockerconfigjson":"eyJ1TmlJTUo4aVpxnekdzdZKaU5LQ1gifX19"},"kind":"Secret","metadata":{"name":"all-icr-io","namespace":"default"},"type":"kubernetes.io/dockerconfigjson"}'
  creationTimestamp: "2021-10-29T16:33:57Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:.dockerconfigjson: {}
      f:metadata:
        f:annotations:
          .: {}
          f:kubectl.kubernetes.io/last-applied-configuration: {}
      f:type: {}
    manager: OpenAPI-Generator
    operation: Update
    time: "2021-10-29T16:33:57Z"
  name: all-icr-io
  namespace: default
  resourceVersion: "5381"
  selfLink: /api/v1/namespaces/default/secrets/all-icr-io
  uid: 30defa59-8890-f-a51f-565ee8291c34
type: kubernetes.io/dockerconfigjson

Note: In the future we will use following format <project_name>-icr-<region>-io for secret names related to container registries.

Step 5: Verify that the secret is copied/created successfully to the new project.

Now we can use the default associated IBM Cloud Container Registry as an input for our deployments.

oc get secrets -n vend-ibm | grep icr-io

Example output:

all-icr-io                 kubernetes.io/dockerconfigjson        1      87s


4. Configure the OpenShift project to access the IBM Cloud Container Registry of IBM Cloud Account TWO and deploy the container image to OpenShift

The following image shows a simplified architecture overview:

Note: For more details please visit the IBM Cloud documentation Creating an image pull secret with different IAM API key credentials for more control or access to images in other IBM Cloud accounts.

Step 1: Check if an image pull secret already exists for your default service account.

oc describe serviceaccount default -n vend-ibm

Example output:

In our example we have Image pull secrets: default-dockercfg-76z7g.

Name:                default
Namespace:           vend-ibm
Labels:              <none>
Annotations:         <none>
Image pull secrets:  default-dockercfg-76z7g
Mountable secrets:   default-token-7zkd7
                     default-dockercfg-76z7g
Tokens:              default-token-7zkd7
                     default-token-hvgg9
Events:              <none>

Step 2: Log on to IBM Cloud Account TWO

ibmcloud login [-sso]

Step 3: Create an IAM new service id

I like the naming convention <cluster_name>-<project>-id, which is provided by the IBM Cloud documentation. In this our the name of the service id is <roks-gen2-suedbro>-<vend-ibm>-id.

ibmcloud iam service-id-create <cluster_name>-<project>-id --description "Service ID for IBM Cloud Container Registry in cluster <cluster_name> project <project>"

Example command:

ibmcloud iam service-id-create roks-gen2-suedbro-vend-ibm-id --description "Service ID for IBM Cloud Container Registry in cluster roks-gen2-suedbro project vend-ibm"

Example output:

OK
Service ID roks-gen2-suedbro-vend-ibm-id is created successfully
ID            ServiceId-57b78691-24a7-48f1-b263-b1cbad87cbc0   
Name          roks-gen2-suedbro-vend-ibm-id   
Description   Service ID for IBM Cloud Container Registry in cluster roks-gen2-suedbro project vend-ibm   
CRN           crn:v1:bluemix:public:iam-identity::a/641ebfffbac35c8385e1d79b45279e::serviceid:ServiceId-57b78691-24a7-48f1-b263-b1cbad87cbc0   
Version       1-be4cfdb528d201078035b25a81ec7f44   
Locked        false 

Step 4: Create a custom IBM Cloud IAM policy for the newly created cluster service ID that grants access to IBM Cloud Container Registry.

ibmcloud iam service-policy-create <cluster_service_ID> --roles <service_access_role> --service-name container-registry [--region <IAM_region>] [--resource-type namespace --resource <registry_namespace>]

ibmcloud iam service-policy-create roks-gen2-suedbro-vend-ibm-id --roles Manager --service-name container-registry --region us-south --resource-type namespace --resource vend-openshift

Example output:

Creating policy under current account for service ID roks-gen2-suedbro-vend-ibm-id as thomas.suedbroecker@...
OK
Service policy is successfully created
Policy ID:   33748d99-ae5c-ed42-9c-5c7e96e836a3   
Version:     1-c3692a57cc9c45043965c6f44e2eda   
Roles:       Manager   
Resources:                         
             Service Name    container-registry      
             Region          us-south      
             Resource Type   namespace      
             Resource        vend-openshift 

Step 5: Create an image pull secret to save the API key credentials in the newly created OpenShift project.

We need following parameters and values for the oc command:

  • <project> : Project name vend-ibm
  • <secret_name> : We reuse service policy name roks-gen2-suedbro-vend-ibm-id.
  • <registry_URL> : That is our URL us.icr.io.
  • <api_key_value> : We need to create an new IAM Key.
  • <docker_email> : We should insert an email address.
oc --namespace <project> create secret docker-registry <secret_name> --docker-server=<registry_URL> --docker-username=iamapikey --docker-password=<api_key_value> --docker-email=<docker_email>

  • Create an IAM Key
ibmcloud iam api-key-create ibmapikey-roks-gen2-suedbro-vend-ibm-id 

Example output:

Creating API key ibmapikey-roks-gen2-suedbro-vend-ibm-id under 641ebfffbac35c8385ee21d79b45279e as thomas.suedbroecker@...
OK
API key ibmapikey-roks-gen2-suedbro-vend-ibm-id was created
Please preserve the API key! It cannot be retrieved after it's created.
ID            ApiKey-d79d7054-7e2e-4bea-b718-b58fa956acc7   
Name          ibmapikey-roks-gen2-suedbro-vend-ibm-id   
Description      
Created At    2021-11-04T18:33+0000   
API Key       17CcgFyamcB7o3SNZysNoMD4RZNUCUimd2360Y   
Locked        false  

  • Set region <region>.icr.io to us.icr.io
  • Execute the command
oc --namespace vend-ibm create secret docker-registry roks-gen2-suedbro-vend-ibm-id --docker-server=us.icr.io --docker-username=iamapikey --docker-password=17CcgFyamcB7ysqNoMD4RZNUCUimd2360Y --docker-email=thomas.suedbroecker@

This is our registry secret name “roks-gen2-suedbro-vend-ibm-id” we will use later.

Example output:

secret/roks-gen2-suedbro-vend-ibm-id created

  • Verify created secret in the project
oc get secrets --namespace vend-ibm

Example output:

NAME                            TYPE                                  DATA   AGE
all-icr-io                      kubernetes.io/dockerconfigjson        1      4h35m
builder-dockercfg-qrksw         kubernetes.io/dockercfg               1      5h8m
builder-token-9gjlf             kubernetes.io/service-account-token   4      5h8m
builder-token-dlxrr             kubernetes.io/service-account-token   4      5h8m
default-dockercfg-76z7g         kubernetes.io/dockercfg               1      5h8m
default-token-7zkd7             kubernetes.io/service-account-token   4      5h8m
default-token-hvgg9             kubernetes.io/service-account-token   4      5h8m
deployer-dockercfg-9l5p9        kubernetes.io/dockercfg               1      5h8m
deployer-token-6whjj            kubernetes.io/service-account-token   4      5h8m
deployer-token-wnh5k            kubernetes.io/service-account-token   4      5h8m
pipeline-dockercfg-6cncv        kubernetes.io/dockercfg               1      5h8m
pipeline-token-ptk4t            kubernetes.io/service-account-token   4      5h8m
pipeline-token-sr2x7            kubernetes.io/service-account-token   4      5h8m
roks-gen2-suedbro-vend-ibm-id   kubernetes.io/dockerconfigjson        1      2m36s


5. Deploy example container image to the OpenShift project

The example application needs following configurations:

  • Two persistent volume claim to save logs and configurations outside the container
  • Two secrets to secure user and admin information
  • One configmap to map not secured environment information
  • One deployment to define the desired state for the pod
  • One service to access the right pod
  • One route to access the application from the internet

The following image shows a simplified overview of the dependencies of the container deployment configuration in the project:

Step 1: Create two Persistent Volume Claims

oc apply -f pvcs.yaml 

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: vend-pvc-accesscodes
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: vend-pvc-logs
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Step 2: Create secretes for the user and admin

  • User
oc create secret generic vend-user-creds \
                          --from-literal=VEND_USER=user\
                          --from-literal=VEND_USER_PASSWORD=user
oc get secret vend-user-creds -o json

  • Admin
oc create secret generic vend-admin-creds \
                          --from-literal=VEND_ADMIN=admin\
                          --from-literal=VEND_ADMIN_PASSWORD=admin
oc get secret vend-admin-creds -o json

Note: Useful OpenSource article

Step 3: Create a configmap

oc apply -f configmap.yaml 

kind: ConfigMap
apiVersion: v1
metadata:
  name: vend-usage
data:
  VEND_USAGE: "vend-demo-secret-openshift"

Step 4: Create a deployment

oc apply -f deployment.yaml 

Here we use the registry secret name “roks-gen2-suedbro-vend-ibm-id“, we defined in step 5.

kind: Deployment
apiVersion: apps/v1
metadata:
  name: vend
spec:
  selector:
    matchLabels:
      app: vend
  replicas: 1
  template:
    metadata:
      labels:
        app: vend
        version: v1
    spec:
      volumes:
      - name: vend-volume-accesscodes
        persistentVolumeClaim:
          claimName: vend-pvc-accesscodes
      - name: vend-volume-logs
        persistentVolumeClaim:
          claimName: vend-pvc-logs
      containers:
      - name: vend
        image: us.icr.io/vend-openshift/vend:v1
        livenessProbe:
          exec:
            command: ["sh", "-c", "curl http://localhost:3000/"]
          initialDelaySeconds: 20
        readinessProbe:
          exec:
            command: ["sh", "-c", "curl http://localhost:3000/health"]
          initialDelaySeconds: 40
        env:
        - name: VEND_USAGE
          valueFrom:
            configMapKeyRef:
              name: vend-usage
              key: VEND_USAGE
        - name: USER
          valueFrom:
            secretKeyRef:
              name: vend-user-creds
              key: VEND_USER
        - name: USERPASSWORD
          valueFrom:
            secretKeyRef:
              name: vend-user-creds
              key: VEND_USER_PASSWORD
        - name: ADMINUSER
          valueFrom:
            secretKeyRef:
              name: vend-admin-creds
              key: VEND_ADMIN
        - name: ADMINUSERPASSWORD
          valueFrom:
            secretKeyRef:
              name: vend-admin-creds
              key: VEND_ADMIN_PASSWORD
        volumeMounts:
          - mountPath: /usr/src/app/accesscodes
            name: vend-volume-accesscodes
          - mountPath: /usr/src/app/logs
            name: vend-volume-logs
        ports:
        - containerPort: 3000
      restartPolicy: Always
      imagePullSecrets:
      - name: roks-gen2-suedbro-vend-ibm-id 

Step 5: Apply the service configuration

oc apply -f service.yaml 

kind: Service
apiVersion: v1
metadata:
  name: vend
  labels:
    app: vend
spec:
  selector:
    app: vend
  ports:
    - port: 3000
      name: http
  type: NodePort

(optional) Step 6: Describe the service

oc describe service vend

Example output:

Name:                     vend
Namespace:                vend-ibm
Labels:                   app=vend
Annotations:              <none>
Selector:                 app=vend
Type:                     NodePort
IP Families:              <none>
IP:                       172.21.121.21
IPs:                      172.21.121.21
Port:                     http  3000/TCP
TargetPort:               3000/TCP
NodePort:                 http  30661/TCP
Endpoints:                172.17.51.152:3000
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

Step 7: Expose service

Here is a useful link to the OpenShift routing topic on an IBM Cloud Red Hat OpenShift cluster Traffic flow in a multizone VPC cluster with a public cloud service endpoint.

oc expose svc vend

Step 8: Get newly created route for our service vend

oc get route | grep "vend"

Step 9: Verify the route output in your browser

Now open the route and verify the output in your browser:

"{\"message\":\"vend test - vend-demo-secret-openshift\"}"

Step 10: Verify the vend application log file output, that’s saved in the persistent volume claim

1. Get the running pod

oc get pods | grep "vend"

Example output:

vend-6879fc49cc-fv72d   1/1     Running   0          3d3h

2. Access the running pod on it’s command line

oc exec vend-6879fc49cc-fv72d cat ./logs/log.txt

Example output:

kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX130402] VEND_USAGE : vend-demo-secret-openshift
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX30403] USER : user
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX30403] USER_PASSWORD : user
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX30403] ADMINUSER : admin
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX0403] ADMINUSER_PASSWORD : admin
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX0407] Info - envDefined==false
*** INF0: 2021-11-7 (XX:XX:30) [1636XXX1906] VEND_USAGE : vend-demo-secret-openshift

Summary

It could be useful to be able to use different container image registries for an OpenShift project, the configuration for the IBM Cloud Container Registry works pretty state forward and is good documented. The example application for my cheat sheet contains serval topics to dig into as an example for a simply container implementation using Node.js.


I hope this was useful for you and let’s see what’s next?

Greetings,

Thomas

#ibmcloudcontainerregistry, #ibmcloud, #container, #containerregistry, #openshift, #roks, #container

2 thoughts on “Configure a project in an IBM Cloud Red Hat OpenShift cluster to access the IBM Cloud Container Registry

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.