Using (customized) Red Hat entitlements / subscriptions in builds for OpenShift 4, and/or custom repositories, like via Red Hat Satellite.  


See Red Hat documentation. Which has this per-buildConfig change, as well as options on cluster-wide changes (involving MachineConfig changes)


https://developers.redhat.com/articles/2022/01/24/create-entitled-builds-red-hat-subscriptions-openshift

https://examples.openshift.pub/build/entitled/

https://cloud.redhat.com/blog/how-to-use-entitled-image-builds-to-build-drivercontainers-with-ubi-on-openshift


Background


OpenShift hosts, by default pass their entitlements through to buildConfigs. It does this by passing in a file: /etc/rhsm-host into the build containers. OpenShift 3 (OCP3) at {{clientName}} used VMs running RHEL 7, entitled to use a particular set of repositories on the {{clientName}} Red Hat Satellite server

The builds used by {{clientName}} used RHEL 7-based images. This allowed builds to easily install additional RPM packages (via the Satellite) without requiring any customization to the entitlementents.

OpenShift 4 (OCP4) at {{clientName}} uses the new Red Hat CoreOS immutable image-based VMs as hosts. These are based on RHEL 8, but using "images" instead of traditional server installs.

The buildConfigs still inherit the OpenShift hosts entitlements, however these differ from the OCP3 entitlements, in that they point to RHEL 8 and Red Hat Universal Base Image 8 (UBI8) subscriptions.

Thus the {{clientName}} builds failed during migration, due to the entitlement/repository missmatch.

Workaround


The workaround used was "Per-Build option 2", below. This supplies entitlement certificates, a custom Red Hat repository list for RHEL 7, and mask /etc/rhsm-host so that the build pods would utilize a different set of entitlements to the hosts.

Note: For each Red Hat major release, different a different set of entitlement certificates and redhat.repo file is required. If this is not done, builds could try to consume packages from RHEL7 and RHEL8 with unexpected/problematic results.

To do this the following k8s objects were required:

secret: etc-pki-entitlement, containing entitlement-key.pem and entitlement.pem.
secret: katello, containing the {{clientName}} Satellite server's identifying certificate.
secret: rhsm-conf, containing custom configuration for /etc/rhsm.conf
configMap: rhsm-mask, basically empty, to mask /etc/rhsm-host in the container
configMap: yum-repos-d, containing the appropriate set of RHEL 7-based repositories.
Changes were then made to the buildConfigs to make use of the above objects.

Additionally, some changes to the Dockerfile were recommended. These removed unnecessary or problematic steps, and reduced the number of layers used.


---------------------------


Per-Build option 1: Dockerfile changes, with entitlement certs copied in

via https://cloud.redhat.com/blog/how-to-use-entitled-image-builds-to-build-drivercontainers-with-ubi-on-openshift


This does not require buildConfig mounts/changes as the required files are pulled into the build via a COPY statement


apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
  labels:
    app: entitled-buildconfig
  name: entitled-buildconfig
spec: {}
---
apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  labels:
    app: entitled-buildconfig
  name: entitled-buildconfig
spec:
  runPolicy: "Serial"
  triggers:
    - type: "ConfigChange"
    - type: "ImageChange"
  source:
    dockerfile: "FROM registry.access.redhat.com/ubi8:latest\nCOPY *.pem /etc/pki/entitlement/entitlement.pem\nCOPY *.pem /etc/pki/entitlement/entitlement-key.pem\nRUN dnf search kernel-devel --showduplicates"
    secrets:
    - secret:
        name: entitlement
  strategy:
    dockerStrategy:
      buildArgs:
        - name: "DRIVER_VERSION"
          value: "418.87.01"
  output:
    to:
      kind: ImageStreamTag
      name: entitled-buildconfig:latest


Per-Build options 2: BuildConfig customization:

This does not require Dockerfile changes, as it supplies the required files via volumeMounts in the BuildConfig


Requires the following to be able to override the underlying host's entitlement if they exist

  • Custom redhat.repo file that gets mounted over /etc/yum.repos.d
  • Custom entitlement identifiers (key and cert) pem files as a secret mounted at /etc/pki/entitlement
  • Custom rhsm.conf which gets mounted over /etc/rhsm (and therefore needs to point configure some other locations)
  • Katello CA mounted at /etc/rhsm-workaround/ca (see above)
  • empty file or emptyDir mount to mask /etc/rhsm-host


myexample

apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  annotations: {}
  labels: {}
  name: myexample
  namespace: mynamespace
spec:
  failedBuildsHistoryLimit: 2
  nodeSelector: null
  output:
    to:
      kind: ImageStreamTag
      name: myexample:latest
  resources:
    limits:
      cpu: 500m
      memory: 500Mi
    requests:
      cpu: 250m
      memory: 100Mi
  runPolicy: SerialLatestOnly
  source:
    contextDir: build-pipeline/Dockerfiles
    git:
      ref: develop
      uri: ssh://git@git:2222/repos/myexample.git
    sourceSecret:
      name: myexample-ssh-secret
    type: Git
  strategy:
    dockerStrategy:
      dockerfilePath: myexample.dockerfile
      env:
      - name: CHECK_INTERVAL
        valueFrom:
          configMapKeyRef:
            key: check-interval
            name: environment-config
      from:
        kind: ImageStreamTag
        name: ubi8:latest
      volumes:
      - mounts:
        - destinationPath: /etc/yum.repos.d
        name: yum-repos-d
        source:
          configMap:
            defaultMode: 420
            name: yum-repos-d
          type: ConfigMap
      - mounts:
        - destinationPath: /etc/pki/entitlement
        name: etc-pki-entitlement
        source:
          secret:
            defaultMode: 420
            secretName: etc-pki-entitlement
          type: Secret
      - mounts:
        - destinationPath: /etc/rhsm
        name: rhsm-conf
        source:
          secret:
            defaultMode: 420
            secretName: rhsm-conf
          type: Secret
      - mounts:
        - destinationPath: /etc/rhsm-workaround/ca
        name: katello
        source:
          secret:
            defaultMode: 420
            secretName: katello
          type: Secret
      - mounts:
        - destinationPath: /etc/rhsm-host
        name: rhsm-host
        source:
          configMap:
            defaultMode: 420
            name: rhsm-mask
          type: ConfigMap
    type: Docker
  successfulBuildsHistoryLimit: 2
  triggers:
  - type: ConfigChange