OpenShift on Power 完全オフライン環境でのインストール

(更新) バージョン4.18での手順にアップデートしました。

# はじめに
本記事ではOpenShift on Powerの完全オフライン環境でのインストールの手順を紹介します。

OpenShiftのBastionノードのみがインターネットに接続できる、といった一部のノードがインターネット接続できる環境ではなく、すべてのノードがインターネットアクセスが不可の完全オフライン環境でのインストール手順となります。

そのため、まずインストールに必要なファイル群を別環境にて、ダウンロードする必要があります。ダウンロードしたファイル群はリムーバブルメディアなどでオフライン環境に持ち込み、インストールを行う流れとなります。

今回は環境をPower10 S1022上に構築しました。バージョンは4.18を使用しています。

# 環境構成

以下の環境構成でLPARをHMCより作成しました。Master3台 / Worker2台の標準構成となります。

|LPAR           |OS      | CPU(EC/VP) | Memory | Storage  |
|---------------|--------|-----------:|-------:|---------:|
|Bastion        |RHEL 9.3|0.5/2       | 16GB   | 200GB    |
|Bootstrap      |RHCOS   |0.5/2       | 16GB   | 100GB    |
|Master x 3     |RHCOS   |0.5/2       | 16GB   | 100GB    |
|Worker x 2     |RHCOS   |0.5/2       | 16GB   | 100GB    |

またネットワーク構成はローカルネットワークのみで192.168.82.0/24のネットワークとなります。

なお、今回はbastionのセットアップにRed Hat社提供のocp4-helpernode
https://github.com/redhat-cop/ocp4-helpernode
各種ミラーレポジトリの作成に同じくRed Hat社提供のocp-mirror version 2
https://github.com/openshift/oc-mirror
を使用しています。
これらのツールの使用により、手順がかなり簡略化できます。

# 事前準備
まずインターネットに接続できる別環境にて、インストールに必要なファイル群をダウンロードします。
別環境もPowerアーキテクチャーの環境が推奨となりますが、追加のOperatorを導入しないといった単純インストールであれば、x86環境でもファイル群のダウンロードは可能です。

今回はPower環境にて、RHEL9.3のLPARを使用してファイル準備を行いました。

まず関連パッケージの導入をしておきます。
```
# dnf repolist
# dnf install git
```
ocp4-helpernodeで使用するansible rpmをダウンロードします。
```
# mkdir -p /download/rpms
# cd /download/rpms
# wget https://dl.fedoraproject.org/pub/epel/9/Everything/ppc64le/Packages/a/ansible-7.7.0-1.el9.noarch.rpm
# mkdir /data
# cp /download/rpms/ansible-7.7.0-1.el9.noarch.rpm /data
```
ocp4-helpernodeおよびnfs provisionerのgitレポジトリをダウンロードします。
```
# mkdir /download/git
# cd /download/git
# git clone https://github.com/RedHatOfficial/ocp4-helpernode
# tar czvf ocp4-helpernode.tgz ocp4-helpernode; rm -rf ocp4-helpernode
# git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner.git nfs-subdir
# tar czvf nfs-subdir.tgz nfs-subdir; rm -rf nfs-subdir
# cp ocp4-helpernode.tgz nfs-subdir.tgz /data
```
OpenShiftのインストールファイル各種をダウンロードします。
```
# mkdir /download/ocp-files
# cd /download/ocp-files
# wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.18/4.18.1/rhcos-live-rootfs.ppc64le.img
# wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.18/4.18.1/rhcos-live-initramfs.ppc64le.img
# wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.18/4.18.1/rhcos-live-kernel-ppc64le
# wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/clients/ocp/4.18.1/openshift-client-linux-4.18.1.tar.gz
# wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/clients/ocp/4.18.1/openshift-install-linux-4.18.1.tar.gz
# wget https://get.helm.sh/helm-v3.17.0-linux-ppc64le.tar.gz
# cp -r /download/ocp-files /data
```
完全オフライン環境では、ミラーレジストリーサーバーが必要となります。今回はOpenShiftのツールとして提供されているmirror-registryを使用します。
```
# mkdir /download/registry
# cd /download/registry
# wget https://mirror.openshift.com/pub/cgw/mirror-registry/latest/mirror-registry-ppc64le.tar.gz
# cp /download/registry/mirror-registry-ppc64le.tar.gz /data
```
次にミラーレジストリーサーバーの中身、つまりミラーするコンテナイメージをoc-mirrorにより一括ダウンロードしていきます。まず、oc-mirror本体をダウンロードします。
```
# mkdir /download/oc-mirror
# cd /download/oc-mirror
# wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/clients/ocp/latest/oc-mirror.rhel9.tar.gz
# cp /download/oc-mirror/oc-mirror.rhel9.tar.gz /data
```
oc-mirrorはoc clientのプラグインとなるため、oc-mirrorを使用するためにoc clientを導入し、oc-mirrorをセットアップします。
```
# tar xzvf /download/ocp-files/openshift-client-linux-4.18.1.tar.gz oc
# mv oc /usr/local/bin
# tar xzvf /download/oc-mirror/oc-mirror.rhel9.tar.gz oc-mirror
# chown root.root oc-mirror; chmod 755 oc-mirror
# mv oc-mirror /usr/local/bin
```
一括ダウンロードに必要なyaml設定ファイルを作成します。今回はimageset-config.yamlという名前で下記のファイルを作成しました。
* OpenShiftインストールに必要な4.18.1イメージ
* gitops operator
* ibm common service operator
* UBI8コンテナイメージ
* UBI9コンテナイメージ
* NFS provisionerコンテナイメージ
* NFS provisionerのテストに必要なbusyboxコンテナイメージ
を一括ダウンロードする設定ファイルとなります。
```yaml:imageset-config.yaml
kind: ImageSetConfiguration
apiVersion: mirror.openshift.io/v2alpha1
mirror:
  platform:
    architectures:
    - "ppc64le"
    channels:
    - name: stable-4.18 
      minVersion: 4.18.1
      maxVersion: 4.18.1
    graph: true 
  operators:
  - catalog: registry.redhat.io/redhat/redhat-operator-index:v4.18 
    packages: 
    - name: openshift-gitops-operator
      channels:
      - name: latest
  - catalog: icr.io/cpopen/ibm-operator-catalog:latest
    packages:
    - name: ibm-common-service-operator
      channels:
      - name: v3.23
  additionalImages: 
  - name: registry.redhat.io/ubi8/ubi:latest
  - name: registry.redhat.io/ubi9/ubi:latest
  - name: gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.2
  - name: docker.io/library/busybox:stable
```
ダウンロードには少なくともOpenShiftのpull secretが必要となるため、下記よりダウンロードを行い、/root/.docker/config.jsonに保存をしておきます。
https://cloud.redhat.com/openshift/install/pull-secret

IBMのコンテナレジストリ(icr.io)のコンテナイメージをダウンロードするためには下記よりEntitlementKeyを取得し、base64にてエンコードを行います。
https://myibm.ibm.com/products-services/containerlibrary
```
# printf "cp:(entitlementkey)" | base64 -w0
```
上記のエンコードを使用して/root/.docker/config.jsonを更新します
```
# jq -c '.auths += {"cp.icr.io": {"auth": "(上記のエンコード)","email": "(mail address)"}}' < ~/.docker/config.json > /root/pull-secret-updated
# cp /root/pull-secret-updated /root/.docker/config.json
```

一括ダウンロードを以下のコマンドで行います。今回はoc-mirrorのversion 2を使用しています。
```
# mkdir /download/mirror-ocp
# export PATH=/usr/local/bin:$PATH
# oc mirror -c imageset-config.yaml file:///download/mirror-ocp --v2
# cp -r /download/mirror-ocp /data
# cp imageset-config.yaml /data
```
上記設定ファイルだと、1つのtarファイルにまとめてくれるのですが、ファイルサイズが大きくなる(今回は20GB程度)となるため、ファイルサイズを抑えたい場合は、"archiveSize: x"オプションをyamlに指定することで指定したサイズの分割が可能です。

これで/dataディレクトリにすべてのファイルをダウンロードできたので、こちらのファイル群をオフライン環境に持ち込みます。

# Bastionの構築・設定
ここからは完全オフライン環境での作業となります。

まずBastionサーバーを構築します。今回ミラーレジストリーサーバーもBastion上に構築しました。BastionサーバーはRHEL9.3を仮想DVDにて"Server with GUI"オプションにてインストールしました。

まず仮想DVDを使用したyumレポジトリを作成します。
DVDをmountします。
```
# mkdir /media/rhel9dvd
# mount /dev/cdrom /media/rhel9dvd
```
下記の内容の/etc/yum.repos.d/dvd.repoファイルを作成して完成です。
```
[dvd-BaseOS]
name=DVD for RHEL9 - BaseOS
baseurl=file:///media/rhel9dvd/BaseOS
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

[dvd-AppStream]
name=DVD for RHEL9 - AppStream
baseurl=file:///media/rhel9dvd/AppStream
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
```
この時点で/dataに持ち込んだファイルを展開しておきます。
必要なrpmをインストールします。
```
# dnf repolist
# dnf install git tree podman
# dnf install /data/ansible-7.7.0-1.el9.noarch.rpm
```
ミラーレジストリーサーバーをセットアップします。Bastionホスト名はFQDNで指定します。
```
# mkdir /mirror-registry
# cd /mirror-registry
# tar xzvf /data/mirror-registry-ppc64le.tar.gz
# ./mirror-registry install --quayHostname (Bastionホスト名) --quayRoot /mirror-registry
INFO[2025-04-27 23:31:15] Quay installed successfully, config data is stored in /mirror-registry
INFO[2025-04-27 23:31:15] Quay is available at https://(Bastionホスト名):8443 with credentials (init, xxxxx)
```
rootCA証明書をBastionにインポートします。
```
# cp /mirror-registry/quay-rootCA/rootCA.pem /etc/pki/ca-trust/source/anchors/
# update-ca-trust
```
podmanによるアクセス確認をします。https:(Bastionホスト名):8443でもアクセスできます。
```
# podman login -u init -p (password) (Bastionホスト名):8443
```

ocp4-helpernodeを使用して各種セットアップを行います。
まずgitレポジトリを展開します。
```
# cd
# tar xzvf /data/ocp4-helpernode.tgz
# cd ocp4-helpernode
```
設定ファイルをvars.yamlという名前で作成します。
```yaml:vars.yaml
---
disk: sda
helper:
  name: "bastion"
  ipaddr: "192.168.82.21"
  networkifacename: "env3"
dns:
  domain: "ocptest.com"
  clusterid: "ocp4"
#  forwarder1: "8.8.8.8"
#  forwarder2: "8.8.4.4"
dhcp:
  router: "192.168.82.21"
  bcast: "192.168.127.255"
  netmask: "255.255.128.0"
  poolstart: "192.168.82.22"
  poolend: "192.168.82.27"
  ipid: "192.168.0.0"
  netmaskid: "255.255.128.0"
chronyconfig:
  enabled: true
  content:
    - server: 192.168.82.21
      options: iburst
bootstrap:
  name: "bootstrap"
  ipaddr: "192.168.82.22"
  macaddr: "xx:xx:xx:xx:xx:xx"
masters:
  - name: "master0"
    ipaddr: "192.168.82.23"
    macaddr: "xx:xx:xx:xx:xx:xx"
  - name: "master1"
    ipaddr: "192.168.82.24"
    macaddr: "xx:xx:xx:xx:xx:xx"
  - name: "master2"
    ipaddr: "192.168.82.25"
    macaddr: "xx:xx:xx:xx:xx:xx"
workers:
  - name: "worker0"
    ipaddr: "192.168.82.26"
    macaddr: "xx:xx:xx:xx:xx:xx"
  - name: "worker1"
    ipaddr: "192.168.82.27"
    macaddr: "xx:xx:xx:xx:xx:xx"
ppc64le: true
ocp_bios: "file:///data/ocp-files/rhcos-live-rootfs.ppc64le.img"
ocp_initramfs: "file:///data/ocp-files/rhcos-live-initramfs.ppc64le.img"
ocp_install_kernel: "file:///data/ocp-files/rhcos-live-kernel-ppc64le"
ocp_client: "file:///data/ocp-files/openshift-client-linux-4.18.1.tar.gz"
ocp_installer: "file:///data/ocp-files/openshift-install-linux-4.18.1.tar.gz"
helm_source: "file:///data/ocp-files/helm-v3.17.0-linux-ppc64le.tar.gz"
```
LPARの各MACアドレスはHMCから以下のコマンドで確認できます。HMCではアドレスは大文字のコロンなしで表示されますが、vars.yamlには小文字のコロンありで記載します。
```
hscroot@hmc:~> lshwres -m <MANAGED-SYSTEM> -r virtualio --rsubtype eth --level lpar -F lpar_name,mac_addr
```
pull-secretをセットアップします。
ミラーレジストリーのアクセス情報により下記のように作成します。
```
# cd 
# mkdir .openshift
# printf "init:(registry password)" | base64 -w0
# jq -n -c '.auths = {"(Bastionホスト名):8443": {"auth": "(上記base64エンコード)","email": "(mail address)"}}' > .openshift/pull-secret
```
Ansibleプレイブックを実行します。
```
# cd ocp4-helpernode
# ansible-playbook -e @vars.yaml tasks/main.yml
```
プレイブックの実行が終わると、以下の構成が完了します。
* bind　(DNS) の導入、設定
* dhcpdの導入、設定
* tftpdの導入、設定
* httpdの導入、設定
* haproxyの導入、設定
* NFS v4の導入、設定
* ネットワークインストール用の設定ファイルの生成(grub.cfgなど)
* ocコマンドのダウンロードと導入
* openshift-installコマンドのダウンロードと導入
* firewallの構成
* PXEブート用のmetal rawイメージ、initramfsイメージ、カーネル・イメージのダウンロードと配置
* RHCOSで使用するSSHキーの生成

今回は追加でBastion上にNTPサーバー(chrony)を導入します。
```
# vi /etc/chrony.conf
# firewall-cmd --add-service=ntp --permanent
# firewall-cmd --reload
# systemctl enable chronyd
# systemctl start chronyd
# systemctl status chronyd
```
今回/etc/chrony.confは以下を使用しました。
```text:/etc/chrony.conf
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
allow 192.168.0.0/17
local stratum 8
keyfile /etc/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony
```
次にミラーレジストリーサーバーに用意したミラーイメージを展開します。
oc-mirrorを使用して1コマンドで展開できます。
```
# cd
# mkdir .docker
# cp .openshift/pull-secret .docker/config.json
# tar xzvf /data/oc-mirror.rhel9.tar.gz oc-mirror
# chmod 755 oc-mirror
# mv oc-mirror /usr/local/bin/
# oc mirror version --v2
# cp /data/imageset-config.yaml .
# oc mirror -c imageset-config.yaml --from=file:///data/mirror-ocp docker://(Bastionホスト名):8443 --v2
```
コマンドが正常に終了すると、/data/mirror-ocp/working-dir/cluster-resourcesというディレクトリができます。ImageDigestMirrorSet、ImageTagMirrorSet、および CatalogSource リソースの YAML ファイルが作成されているのを確認します。

ミラーレジストリーサーバーが正常に動作しているかの確認を以下のコマンドで行います。
```
podman image search (Bastionホスト名):8443/
podman image search --list-tags (Bastionホスト名)/openshift/release --limit 200
```

# OpenShiftの導入

Bastion上にインストールされたopenshift-installコマンドを使用してOpenShiftの導入を行います。
基本的な流れはOpenShiftのインストールガイドの通りとなります。
https://docs.redhat.com/ja/documentation/openshift_container_platform/4.18/html-single/installing_on_ibm_power/index#prerequisites

次にinstall-config.yamlを作成します。今回は以下のように作成しています。
(実行前に~/.openshift/pull-secret, /mirror-registry/quay-rootCA/rootCA.pemおよび~/.ssh/helper_rsa.pubが存在するのを確認しておきます)
```
# cat <<EOF > install-config.yaml
apiVersion: v1
baseDomain: ocptest.com
compute:
- hyperthreading: Enabled
  name: worker
  replicas: 0
controlPlane:
  hyperthreading: Enabled
  name: master
  replicas: 3
metadata:
  name: ocp4
networking:
  clusterNetworks:
  - cidr: 10.254.0.0/16
    hostPrefix: 24
  networkType: OVNKubernetes
  serviceNetwork:
  - 172.30.0.0/16
platform:
  none: {}
pullSecret: '$(< ~/.openshift/pull-secret)'
sshKey: '$(< ~/.ssh/helper_rsa.pub)'
additionalTrustBundle: |
$(< /mirror-registry/quay-rootCA/rootCA.pem)
imageContentSources:
- mirrors:
  - (Bastionホスト名):8443/openshift/release-images
  source: quay.io/openshift-release-dev/ocp-release
- mirrors:
  - (Bastionホスト名):8443/openshift/release
  source: quay.io/openshift-release-dev/ocp-v4.0-art-dev
EOF
```
作成されたinstall-config.yamlの
BEGIN CERTIFICATE から
END CERTIFICATE　まで
の部分に2文字分の空白を入れてインデントします。
(ここはできれば自動化したいところです。。:smiley_cat:)

manifestsファイルを作成します。
```
# cd
# mkdir config
# cp install-config.yaml config
# openshift-install create manifests --dir=config
```
mastersSchedulableをfalseにしてmasterにpodがschedulingされないようにします。
```
# sed -i 's/mastersSchedulable: true/mastersSchedulable: false/g' config/manifests/cluster-scheduler-02-config.yml
```
ocp4-helpernodeで設定したNTP設定を反映させます。
```
cp ocp4-helpernode/machineconfig/* config/openshift/
```
ignitionファイルを作成して展開します。
```
# openshift-install create ignition-configs --dir=config
# tree config
config
|-- auth
|   |-- kubeadmin-password
|   `-- kubeconfig
|-- bootstrap.ign
|-- master.ign
|-- metadata.json
`-- worker.ign
# cp config/*.ign /var/www/html/ignition/
# restorecon -vR /var/www/html/
# chmod o+r /var/www/html/ignition/*.ign
```
HMCより各ノード(bootstrap/master0,1,2/worker0,1)のPXEブートを行い、OpenShiftの導入を開始します。(MACアドレスはlshwresで確認した大文字コロンなしフォーマットを指定します)
```
hscroot@hmc:~> lpar_netboot -x -t ent -m <MAC-ADDR> -s auto -d auto <LPAR-NAME> <PROFILE-NAME> <MANAGED-SYSTEM>
```
ブートストラッププロセスを以下のコマンドで確認します。
```
# openshift-install --dir=config wait-for bootstrap-complete --log-level=info
INFO Waiting up to 20m0s (until 2:30AM EDT) for the Kubernetes API at https://api.ocp4.ocptest.com:6443... 
INFO API v1.31.5 up                       
INFO Waiting up to 45m0s (until 2:55AM EDT) for bootstrapping to complete...
INFO It is now safe to remove the bootstrap resources 
```
http://(Bastion IP):9000 へアクセスすることで各サーバーの稼働状況も確認できます。
しばらくすると、クラスターへログインも可能となります。
```
# export KUBECONFIG=/root/config/auth/kubeconfig
# oc whoami
system:admin
# oc get nodes
```
以下のコマンドでCSRの状態を確認し、Pendingがあれば承認します。
```
# oc get csr
# oc adm certificate approve <csr_name>
```
clusteroperatorがすべてAvailableかつDegradedになっていないことを確認します。
```
# oc get clusteroperators
NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
authentication                             4.18.1    True        False         False      5m21s
baremetal                                  4.18.1    True        False         False      21m
cloud-controller-manager                   4.18.1    True        False         False      24m
cloud-credential                           4.18.1    True        False         False      25m
cluster-autoscaler                         4.18.1    True        False         False      21m
config-operator                            4.18.1    True        False         False      22m
console                                    4.18.1    True        False         False      11m
control-plane-machine-set                  4.18.1    True        False         False      21m
csi-snapshot-controller                    4.18.1    True        False         False      13m
dns                                        4.18.1    True        False         False      14m
etcd                                       4.18.1    True        False         False      20m
image-registry                             4.18.1    True        False         False      13m
ingress                                    4.18.1    True        False         False      12m
insights                                   4.18.1    True        False         False      22m
kube-apiserver                             4.18.1    True        False         False      18m
kube-controller-manager                    4.18.1    True        False         False      19m
kube-scheduler                             4.18.1    True        False         False      18m
kube-storage-version-migrator              4.18.1    True        False         False      13m
machine-api                                4.18.1    True        False         False      21m
machine-approver                           4.18.1    True        False         False      22m
machine-config                             4.18.1    True        False         False      20m
marketplace                                4.18.1    True        False         False      21m
monitoring                                 4.18.1    True        False         False      8m27s
network                                    4.18.1    True        False         False      22m
node-tuning                                4.18.1    True        False         False      11m
olm                                        4.18.1    True        False         False      12m
openshift-apiserver                        4.18.1    True        False         False      13m
openshift-controller-manager               4.18.1    True        False         False      18m
openshift-samples                          4.18.1    True        False         False      13m
operator-lifecycle-manager                 4.18.1    True        False         False      21m
operator-lifecycle-manager-catalog         4.18.1    True        False         False      21m
operator-lifecycle-manager-packageserver   4.18.1    True        False         False      14m
service-ca                                 4.18.1    True        False         False      22m
storage                                    4.18.1    True        False         False      22m
```
最後にクラスターのインストールプロセスの完了を確認します。
WebコンソールへログインするためのURLとユーザーID/パスワードが表示されます。
```
# openshift-install --dir=config wait-for install-complete --log-level=info
INFO Waiting up to 40m0s (until 3:18AM EDT) for the cluster at https://api.ocp4.ocptest.com:6443 to initialize... 
INFO Waiting up to 30m0s (until 3:08AM EDT) to ensure each cluster operator has finished progressing...
INFO All cluster operators have completed progressing
INFO Checking to see if there is a route at openshift-console/console...
INFO Install complete!
INFO To access the cluster as the system:admin user when using 'oc', run
INFO     export KUBECONFIG=/root/config/auth/kubeconfig
INFO Access the OpenShift web-console here: https://console-openshift-console.apps.ocp4.ocptest.com
INFO Login to the console with user: "kubeadmin", and password: "xxxxx"
```
# インストール後の作業
OperatorHubはオフライン環境では使用できないため一旦すべてのsourceをdisableにします。
```
# oc patch OperatorHub cluster --type json -p '[{"op": "add", "path": "/spec/disableAllDefaultSources", "value": true}]'
```
ミラーレジストリーの反映を行います。先ほどoc-mirrorで作られたディレクトリを参照します。
ImageDigestMirrorSet、ImageTagMirrorSet、および CatalogSource リソースの反映を行います。
```
# oc apply -f /data/mirror-ocp/working-dir/cluster-resources
```
WebコンソールのOperatorHubなどで、ミラーされたOperatorが表示されるか確認を行います。

次にimage registryの設定を行います。今回はBastion上のNFSサーバーを使用しました。
以下の内容のimage-storage.yamlという名前のファイルを作成します。
```yaml:image-storage.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: image-registry-pv
spec:
  capacity:
    storage: 100Gi
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: image-registry-storage
    namespace: openshift-image-registry
  accessModes:
  - ReadWriteMany
  nfs:
    path: /export/image-registry
    server: 192.168.82.21
  persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  finalizers:
  - kubernetes.io/pvc-protection
  name: image-registry-storage
  namespace: openshift-image-registry
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 100Gi
```
registryを設定します。
```
# mkdir /export/image-registry
# chmod 777 /export/image-registry
# oc apply -f image-storage.yaml
```
registryの設定を修正します。
```
# oc edit configs.imageregistry.operator.openshift.io -n openshift-image-registry
```
**spec.managementState** を Removed から Managedに変更します
**spec.storage** を {} から以下に変更します。
```yaml
spec:
  managementState: Managed
  storage:
    pvc:
      claim: image-registry-storage
```
image registryが使用可能であることを確認します。
```
# oc get co image-registry
```
外部経路を使用可能にします。
```
# oc -n openshift-image-registry patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge
```
最後にPVのdefault storage classとしてNFS client provisionerを設定します。
こちらもBastionのNFSサーバーを使用しています。
以下のコマンドで設定ファイルを作成していきます。
```
# oc create namespace openshift-nfs-storage
# oc label namespace openshift-nfs-storage "openshift.io/cluster-monitoring=true"
# cd
# tar xzvf /data/nfs-subdir.tgz
# cd nfs-subdir/
# oc project openshift-nfs-storage
# NAMESPACE=`oc project -q`
# sed -i'' "s/namespace:.*/namespace: $NAMESPACE/g" ./deploy/rbac.yaml ./deploy/deployment.yaml
# oc adm policy add-scc-to-user hostmount-anyuid system:serviceaccount:$NAMESPACE:nfs-client-provisioner
```
deploy/deployment.yamlのcontainersとvolumesの部分を以下のように変更します。
```yaml
containers:
  - name: nfs-client-provisioner
    image: (Bastionホスト名):8443/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.2
    volumeMounts:
      - name: nfs-client-root
        mountPath: /persistentvolumes
    env:
      - name: PROVISIONER_NAME
        value: k8s-sigs.io/nfs-subdir-external-provisioner
      - name: NFS_SERVER
        value: 192.168.82.21
      - name: NFS_PATH
        value: /export
volumes:
  - name: nfs-client-root
    nfs:
      server: 192.168.82.21
      path: /export
```
deploy/class.yamlを以下のように変更します。
```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client
  annotations:
    storageclass.kubernetes.io/is-default-class: 'true'
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
  archiveOnDelete: "false"
reclaimPolicy: Delete
volumeBindingMode: Immediate
```
設定を実施し、provisionerがreadyになるまで待ちます。
```
# oc create -f deploy/rbac.yaml
# oc create -f deploy/deployment.yaml
# oc create -f deploy/class.yaml
# oc wait --for=condition=ready -n openshift-nfs-storage -l app=nfs-client-provisioner pod
pod/nfs-client-provisioner-6cc66c5945-2d2xr condition met
```
provisionerのテストを行ってみます。
まずdeploy/test-pod.yamlのimage部分を下記のように変更し、ミラーレジストリーのimageを使用するようにします。
```yaml
image: (Bastionホスト名):8443/library/busybox:stable
```
testのpod作成後、NFSサーバー側にディレクトリが作成されているか確認してみます。
```
# oc create -f deploy/test-claim.yaml -f deploy/test-pod.yaml
# oc get pods -n openshift-nfs-storage
# ls /export
# oc delete -f deploy/test-pod.yaml -f deploy/test-claim.yaml
# ls /export
```

# TIPS
インストールの各ノードのエラーは各ノードへログインしてjournalctlコマンドで確認できます。
```
# ssh bootstrap
# ssh master0
# ssh worker0
```
ocp4-helpernodeにてインストールされるhelpernodecheckコマンドにてbastionの各種情報は参照できます。
```
# helpernodecheck
Usage:
helpernodecheck {dns-masters|dns-workers|dns-etcd|dns-other|local-registry-info|install-info|haproxy|services|nfs-info}
```
# TroubleShoot
#### NTPサーバーとの同期ができない
NTPサーバーとの接続を各ノードで確認します。(例:master0)
```
# ssh master0
# sudo -i
# chronyc sources
# chronyc sourcestats
# chronyc ntpdata
```
sourcesコマンドで?が表示されるなどNTPサーバー側に問題がありそうな場合は、Bastion上のNTPサーバーをrestartさせてみます。
```
# systemctl restart chronyd
```
# Reference
[Ristricted network install on Power](https://docs.redhat.com/en/documentation/openshift_container_platform/4.18/html/installing_on_ibm_power/installing-restricted-networks-ibm-power#installing-restricted-networks-ibm-power)
[Mirroring images for a disconnected installation using the oc-mirror plugin v2](https://docs.redhat.com/en/documentation/openshift_container_platform/4.18/html/disconnected_environments/mirroring-in-disconnected-environments#about-installing-oc-mirror-v2)
[Creating mirror registry with mirror registry for RedHat OpenShift](https://docs.redhat.com/en/documentation/openshift_container_platform/4.18/html/disconnected_environments/mirroring-in-disconnected-environments#installing-mirroring-creating-registry)
[GitHub: ocp4-helpernode](https://github.com/redhat-cop/ocp4-helpernode)
[GitHub: oc-mirror](https://github.com/openshift/oc-mirror)