Browse Docs

๐Ÿ  OKD & OpenShift

OKD vs OpenShift

They are essentially the same Kubernetes distribution.

OKD โ€” short for “The Community Distribution of Kubernetes that powers Red Hat OpenShift” โ€” is the free, upstream/community edition: the same codebase, community support, and images pulled from quay.io.

OpenShift is Red Hat’s enterprise product: OKD plus commercial support, certifications, a longer support lifecycle, Red Hat registries (registry.redhat.io) and OperatorHub access.

Day-to-day they are nearly interchangeable โ€” both use the same oc, openshift-install and oc-mirror tooling, and the same install-config.yaml layout. Unless stated otherwise, the notes below apply to both.

Install

 1# Get latest version
 2OKD_VERSION=$(curl -s https://api.github.com/repos/okd-project/okd/releases/latest | jq -r .tag_name)
 3
 4# Download
 5curl -L https://github.com/okd-project/okd/releases/download/${OKD_VERSION}/openshift-install-linux-${OKD_VERSION}.tar.gz -O
 6curl -L https://github.com/okd-project/okd/releases/download/${OKD_VERSION}/openshift-client-linux-${OKD_VERSION}.tar.gz -O
 7
 8# Download FCOS iso
 9./openshift-install coreos print-stream-json | grep '\.iso[^.]'
10./openshift-install coreos print-stream-json | jq .architectures.x86_64.artifacts.metal.formats.iso.disk.location
11./openshift-install coreos print-stream-json | jq .architectures.x86_64.artifacts.vmware.formats.ova.disk.location
12./openshift-install coreos print-stream-json | jq '.architectures.x86_64.artifacts.digitalocean.formats["qcow2.gz"].disk.location'
13./openshift-install coreos print-stream-json | jq '.architectures.x86_64.artifacts.qemu.formats["qcow2.gz"].disk.location'
14./openshift-install coreos print-stream-json | jq '.architectures.x86_64.artifacts.metal.formats.pxe | .. | .location? // empty'

Create a cluster

1openshift-install create install-config
2
3openshift-install create manifests
4
5openshift-install create ignition-configs
6
7openshift-install create cluster --dir . --log-level=info
8openshift-install destroy cluster --log-level=info

Install bare-metal (IPI)

Official doc

 1# Pre-tasks
 2useradd kni
 3echo "kni ALL=(root) NOPASSWD:ALL" | tee -a /etc/sudoers.d/kni
 4chmod 0440 /etc/sudoers.d/kni
 5su - kni -c "ssh-keygen -t ed25519 -f /home/kni/.ssh/id_rsa -N ''"
 6sudo dnf install -y libvirt qemu-kvm python3-devel jq
 7sudo usermod --append --groups libvirt kni
 8sudo systemctl start firewalld
 9sudo firewall-cmd --zone=public --add-service=http --permanent
10sudo firewall-cmd --reload
11sudo systemctl enable libvirtd --now
12sudo virsh pool-define-as --name default --type dir --target /var/lib/libvirt/images
13sudo virsh pool-start default
14sudo virsh pool-autostart default
15
16# Pull secret (https://console.redhat.com/openshift/install/metal/installer-provisioned)
17su - kni
18vim pull-secret.txt
19
20# Network
21export PUB_CONN="cloud-init eth1"
22nmcli con down "$PUB_CONN"
23nmcli con delete "$PUB_CONN"
24nmcli connection add ifname baremetal type bridge con-name baremetal bridge.stp no
25nmcli con add type bridge-slave ifname "$PUB_CONN" master baremetal
26nohup bash -c "pkill dhclient;dhclient baremetal" &
27
28# retrieve OKD installer
29export VERSION="stable-4.15"
30export RELEASE_ARCH="amd64"
31export RELEASE_IMAGE=$(curl -s https://mirror.openshift.com/pub/openshift-v4/$RELEASE_ARCH/clients/ocp/$VERSION/release.txt | grep 'Pull From: quay.io' | awk -F ' ' '{print $3}')
32
33# Extract OKD installer
34export cmd=openshift-baremetal-install
35export pullsecret_file=~/pull-secret.txt
36export extract_dir=$(pwd)
37curl -s https://mirror.openshift.com/pub/openshift-v4/clients/ocp/$VERSION/openshift-client-linux.tar.gz | tar zxvf - oc
38mv oc $HOME/.local/bin
39oc adm release extract --registry-config "${pullsecret_file}" --command=$cmd --to "${extract_dir}" ${RELEASE_IMAGE}
40mv openshift-baremetal-install $HOME/.local/bin
41
42# Create FCOS image cache (usefull for network with limited bandwidth)
43sudo dnf install -y podman
44sudo firewall-cmd --add-port=8080/tcp --zone=public --permanent
45sudo firewall-cmd --reload
46
47mkdir /home/kni/rhcos_image_cache
48sudo semanage fcontext -a -t httpd_sys_content_t "/home/kni/rhcos_image_cache(/.*)?"
49sudo restorecon -Rv /home/kni/rhcos_image_cache/
50
51export RHCOS_QEMU_URI=$(openshift-baremetal-install coreos print-stream-json | jq -r --arg ARCH "$(arch)" '.architectures[$ARCH].artifacts.qemu.formats["qcow2.gz"].disk.location')
52export RHCOS_QEMU_NAME=${RHCOS_QEMU_URI##*/}
53export RHCOS_QEMU_UNCOMPRESSED_SHA256=$(openshift-baremetal-install coreos print-stream-json | jq -r --arg ARCH "$(arch)" '.architectures[$ARCH].artifacts.qemu.formats["qcow2.gz"].disk["uncompressed-sha256"]')
54curl -L ${RHCOS_QEMU_URI} -o ./rhcos_image_cache/${RHCOS_QEMU_NAME}
55
56# Validate httpd_sys_content_t
57ls -Z ./rhcos_image_cache
58
59# Create pod
60podman run -d --name rhcos_image_cache \
61-v rhcos_image_cache:/var/www/html \
62-p 8080:8080/tcp \
63registry.access.redhat.com/ubi9/httpd-24
64
65export BAREMETAL_IP=$(ip addr show dev eth1 | awk '/inet /{print $2}' | cut -d"/" -f1)
66export BOOTSTRAP_OS_IMAGE="http://${BAREMETAL_IP}:8080/${RHCOS_QEMU_NAME}?sha256=${RHCOS_QEMU_UNCOMPRESSED_SHA256}"
67echo "    bootstrapOSImage=${BOOTSTRAP_OS_IMAGE}"

Make an ISO boot USB for bare-metal:

1dd if=$HOME/ocp-latest/rhcos-live.iso of=/dev/sdb bs=1024k status=progress

OC Mirror

  • Need at least one Operator:
 1kind: ImageSetConfiguration
 2apiVersion: mirror.openshift.io/v1alpha2
 3archiveSize: 4
 4storageConfig:
 5  registry:
 6    imageURL: quay.example.com:8443/mirror/oc-mirror-metadata
 7    skipTLS: false
 8mirror:
 9  platform:
10    architectures:
11      - "amd64"
12    channels:
13    - name: stable-4.14
14      type: ocp
15      shortestPath: true
16    graph: true
17  operators:
18    - catalog: registry.redhat.io/redhat/redhat-operator-index:v4.14
19      packages:
20        - name: kubevirt-hyperconverged
21          channels:
22            - name: 'stable'
23        - name: serverless-operator
24          channels:
25            - name: 'stable'
26  additionalImages:
27  - name: registry.redhat.io/ubi9/ubi:latest
28  helm: {}
 1# install oc-mirror:
 2curl https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/latest/oc-mirror.rhel9.tar.gz -O
 3
 4# Get an example of imageset
 5oc-mirror init --registry quay.example.com:8443/mirror/oc-mirror-metadata
 6
 7# Find operators in the list of Operators, channels, packages
 8oc-mirror list operators --catalog=registry.redhat.io/redhat/redhat-operator-index:v4.14
 9oc-mirror list operators --catalog=registry.redhat.io/redhat/redhat-operator-index:v4.14 --package=kubevirt-hyperconverged
10oc-mirror list operators --catalog=registry.redhat.io/redhat/redhat-operator-index:v4.14 --package=kubevirt-hyperconverged --channel=stable
11
12# mirror with a jumphost which online access
13oc-mirror --config=imageset-config.yaml docker://quay.example.com:8443
14
15# mirror for airgap
16oc-mirror --config=imageSetConfig.yaml file://tmp/download
17oc-mirror --from=/tmp/upload/ docker://quay.example.com/ocp/operators
18
19# Refresh OperatorHub
20oc get pod -n openshift-marketplace
21
22# Get the index pod and delete it to refresh
23oc delete pod cs-redhat-operator-index-m2k2n -n openshift-marketplace

Add node

1export OPENSHIFT_CLUSTER_ID=$(oc get clusterversion -o jsonpath='{.items[].spec.clusterID}')
2export CLUSTER_REQUEST=$(jq --null-input --arg openshift_cluster_id "$OPENSHIFT_CLUSTER_ID" '{
3  "api_vip_dnsname": "<api_vip>",
4  "openshift_cluster_id": $openshift_cluster_id,
5  "name": "<openshift_cluster_name>"
6}')

Platform in install-config

  • Get all info on how to config
1openshift-install explain installconfig.platform.libvirt
 1## none
 2platform:
 3   none: {}
 4
 5## baremetal - use ipmi to provision baremetal
 6platform:
 7  baremetal:
 8    apiVIP: 192.168.111.5
 9    ingressVIP: 192.168.111.7
10    provisioningNetwork: "Managed"
11    provisioningNetworkCIDR: 172.22.0.0/24
12    provisioningNetworkInterface: eno1
13    clusterProvisioningIP: 172.22.0.2
14    bootstrapProvisioningIP: 172.22.0.3
15    hosts:
16      - name: master-0
17        role: master
18        bmc:
19          address: ipmi://192.168.111.1
20          username: admin
21          password: password
22        bootMACAddress: 52:54:00:a1:9c:ae
23        hardwareProfile: default
24      - name: master-1
25        role: master
26        bmc:
27          address: ipmi://192.168.111.2
28          username: admin
29          password: password
30        bootMACAddress: 52:54:00:a1:9c:af
31        hardwareProfile: default
32      - name: master-2
33        role: master
34        bmc:
35          address: ipmi://192.168.111.3
36          username: admin
37          password: password
38        bootMACAddress: 52:54:00:a1:9c:b0
39        hardwareProfile: default
40
41## vpshere - old syntax and deprecated form (new one in 4.15 with "failure domain")
42vsphere:
43    vcenter:
44    username:
45    password:
46    datacenter:
47    defaultDatastore:
48    apiVIPs:
49    - x.x.x.x
50    ingressVIPs:
51    - x.x.x.x
52
53## new syntax
54platform:
55  vsphere:
56    apiVIPs:
57    - x.x.x.x
58    datacenter: xxxxxxxxxxxx_datacenter
59    defaultDatastore: /xxxxxxxxxxxx_datacenter/datastore/Shared Storages/ssd-001602
60    failureDomains:
61     - name: CNV4
62      region: fr
63      server: xxxxxxxxxxxx.ovh.com
64      topology:
65        computeCluster: /xxxxxxxxxxxx_datacenter/host/Management Zone Cluster
66        datacenter: xxxxxxxxxxxx_datacenter
67        datastore: /xxxxxxxxxxxx_datacenter/datastore/Shared Storages/ssd-001602
68        networks:
69        - vds_mgmt
70      zone: dc
71    ingressVIPs:
72    - x.x.x.x
73    password: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
74    username: admin
75    vCenter: xxxxxxxxxxx.ovh.com
76    vcenters:
77    - datacenters:
78      - xxxxxxxxxx_datacenter
79      password: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
80      port: 443
81      server: xxxxxxx.ovh.com
82      user: admin

Utils

1# Get Cluster ID
2oc get clusterversion -o jsonpath='{.items[].spec.clusterID}'
3
4# Get Nodes which are Ready
5oc get nodes --output jsonpath='{range .items[?(@.status.conditions[-1].type=="Ready")]}{.metadata.name} {.status.conditions[-1].type}{"\n"}{end}'
6
7# get images from all pods in a namespace
8oc get pods -n <namespace> --output jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{end}'

Set OperatorHub

  • in airgap
1oc get catalogsources -n openshift-marketplace
Sunday, October 4, 2026 Tuesday, August 1, 2023