インターネットに出られないネットワーク(オフライン環境)に OKD をインストールする手順です。インターネットに出られる踏み台サーバーを 1 台用意し、そこにミラー レジストリを立てて OKD のイメージを写しておきます。クラスタのノードは、イメージをミラー レジストリから、時刻を踏み台の NTP から取ります。
インストールの流れは オンライン環境・platform: baremetal の記事と同じです。この記事では、オフライン環境で追加・変更するところを書きます。
この記事の前提
- 踏み台サーバーの構築が終わっていること(ens19 10.30.0.1、DNS の okdoff と registry.hvdoc.lab のレコード)
- 参照: OKD Documentation(Disconnected environments、Installing an on-premise cluster with the Agent-based Installer)
構成
| 項目 | 値 |
|---|---|
| クラスタ名 | okdoff(platform: baremetal、コントロール プレーン 3 台) |
| ノードのネットワーク | 10.30.0.0/24(Proxmox VE のブリッジ hvnet0、外部に出る経路なし) |
| ノード | off-master-1〜3(10.30.0.11〜13)。ゲートウェイ・DNS・NTP は踏み台の 10.30.0.1 |
| VIP | API 10.30.0.4、Ingress 10.30.0.5 |
| ミラー レジストリ | 踏み台の registry.hvdoc.lab:5000(10.30.0.1)。registry:2 を podman で動かし、TLS と認証をかける |
| 通信 | オンライン環境 | オフライン環境(この記事) |
|---|---|---|
| OKD のイメージ | quay.io から取る | 踏み台のミラー レジストリから取る |
| 時刻 | インターネットの NTP | 踏み台の chrony |
| pull secret | ダミーでよい(quay.io の OKD は認証不要) | ミラー レジストリの認証情報 |
| install-config.yaml の追加 | なし | additionalTrustBundle(ミラーの CA)、imageDigestSources(取り先の置き換え) |
踏み台は、インターネット側(192.168.1.0/24)とオフライン側(10.30.0.0/24)の両方に足を持ちます。踏み台はルーティング(IP フォワード)をしないので、ノードから外部には出られません。
NTP サーバー(chrony)
ノードの時刻がずれると、証明書の検証やインストールが失敗します。踏み台の chrony から、オフライン側へ時刻を配ります。
実行する場所:踏み台サーバー(root)
# dnf -y install chrony httpd-tools openssl
# cat >> /etc/chrony.conf <<'EOF'
# オフラインのクラスタへ時刻を配る
allow 10.30.0.0/24
local stratum 10
EOF
# systemctl enable --now chronyd
# systemctl restart chronyd
# firewall-cmd --permanent --add-service=ntp
# firewall-cmd --reload
| 設定 | 意味 |
|---|---|
| allow 10.30.0.0/24 | このネットワークからの NTP の問い合わせに答える |
| local stratum 10 | 上位の NTP に届かないときも、自分の時計で時刻を配り続ける |
ミラー レジストリの証明書
ノードは、ミラー レジストリに TLS で接続します。自己署名の CA を作り、その CA で registry.hvdoc.lab のサーバー証明書を発行します。CA の証明書は、あとで install-config.yaml の additionalTrustBundle に入れます。
実行する場所:踏み台サーバー(root)
# mkdir -p /srv/registry/{certs,auth,data}
# cd /srv/registry/certs
# openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout ca.key -out ca.crt -subj "/CN=hvdoc-lab-ca"
# openssl req -newkey rsa:4096 -nodes -keyout registry.key -out registry.csr -subj "/CN=registry.hvdoc.lab"
# printf 'subjectAltName=DNS:registry.hvdoc.lab,IP:10.30.0.1\nextendedKeyUsage=serverAuth\n' > san.ext
# openssl x509 -req -in registry.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out registry.crt -days 3650 -sha256 -extfile san.ext
# openssl x509 -in registry.crt -noout -subject -ext subjectAltName
# cp ca.crt /etc/pki/ca-trust/source/anchors/hvdoc-lab-ca.crt
# update-ca-trust
期待する出力:
subject=CN=registry.hvdoc.lab
X509v3 Subject Alternative Name:
DNS:registry.hvdoc.lab, IP Address:10.30.0.1
証明書には、CN だけでなく subjectAltName(SAN)が必要です。SAN がないと、ノードの CRI-O が証明書を受け付けません。
ミラー レジストリ(registry:2)
認証用のユーザーを作り、registry:2 のコンテナを podman で起動します。systemd に登録して、踏み台を再起動しても自動で起動するようにします。
実行する場所:踏み台サーバー(root)
# htpasswd -bBc /srv/registry/auth/htpasswd okd 'P@ssw0rd-reg'
# podman pull docker.io/library/registry:2
# podman run -d --name mirror-registry --restart=always -p 5000:5000 \
-v /srv/registry/data:/var/lib/registry:z \
-v /srv/registry/certs:/certs:z \
-v /srv/registry/auth:/auth:z \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM=okd \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_STORAGE_DELETE_ENABLED=true \
docker.io/library/registry:2
# podman generate systemd --name mirror-registry --files --new
# mv container-mirror-registry.service /etc/systemd/system/
# systemctl daemon-reload
# systemctl enable container-mirror-registry
# firewall-cmd --permanent --add-port=5000/tcp
# firewall-cmd --reload
# curl -u okd:'P@ssw0rd-reg' https://registry.hvdoc.lab:5000/v2/_catalog
期待する出力:
{"repositories":[]}
| 設定 | 意味 |
|---|---|
| -p 5000:5000 | レジストリのポート。ノードからは registry.hvdoc.lab:5000 で接続する |
| /srv/registry/data | イメージの保存先。OKD 5.0 のリリース イメージ一式で約 18GB |
| REGISTRY_AUTH=htpasswd | ユーザー名とパスワードで認証する |
本番では、Red Hat の mirror registry for Red Hat OpenShift(Quay)や、既存の Harbor・Nexus などを使うこともできます。ここでは手順を短くするため registry:2 を使います。
OKD のイメージをミラーする
踏み台(インターネットに出られる)で oc adm release mirror を実行し、OKD のリリース イメージをミラー レジストリへ写します。
実行する場所:踏み台サーバー(root)
# REL=$(openshift-install version | awk '/release image/{print $3}')
# echo $REL
# AUTH=$(echo -n 'okd:P@ssw0rd-reg' | base64 -w0)
# echo "{\"auths\":{\"registry.hvdoc.lab:5000\":{\"auth\":\"$AUTH\"}}}" > /root/okd/pull-secret-mirror.json
# oc adm release mirror -a /root/okd/pull-secret-mirror.json \
--from=$REL \
--to=registry.hvdoc.lab:5000/okd/scos-release \
--to-release-image=registry.hvdoc.lab:5000/okd/scos-release:5.0.0-okd-scos.3 \
--keep-manifest-list=true
| オプション | 意味 |
|---|---|
| -a | ミラー レジストリへ書き込むための認証情報 |
| –from | 写すリリース イメージ(openshift-install に組み込まれているもの) |
| –to | 写し先のリポジトリ。リリースに含まれるイメージをすべてここに入れる |
| –to-release-image | リリース イメージ自体の写し先(タグ付き) |
| –keep-manifest-list=true | マニフェスト リストを、リストのまま写す(下の注意を参照) |
–keep-manifest-list=true を必ず付けます。 OKD 5.0 のリリースでは、ノードの OS のイメージ(stream-coreos・stream-coreos-extensions)がマニフェスト リスト(amd64 の 1 つだけを含む)のダイジェストで参照されています。このオプションがないと、amd64 のマニフェストだけが写されてリスト自体はミラーに入りません。そのため、インストール中にランデブー ホストの node-image-pull.service が「manifest unknown」で止まります(この環境で実際に発生しました。ほかのノードは 10.30.0.4:22623 の ignition を待ったまま進みません)。
期待する出力(最後の部分):
Success
Update image: registry.hvdoc.lab:5000/okd/scos-release:5.0.0-okd-scos.3
Mirror prefix: registry.hvdoc.lab:5000/okd/scos-release
To use the new mirrored repository to install, add the following section to the install-config.yaml:
imageContentSources:
- mirrors:
- registry.hvdoc.lab:5000/okd/scos-release
source: quay.io/okd/scos-content
- mirrors:
- registry.hvdoc.lab:5000/okd/scos-release
source: quay.io/okd/scos-release
この環境では、約 10 分・約 18GB でした。最後に表示される mirrors と source の組み合わせを、install-config.yaml に書きます(OKD 5.0 では imageContentSources ではなく imageDigestSources という名前で書きます)。
踏み台もインターネットに出られない完全なオフライン環境では、oc adm release mirror –to-dir でイメージをファイルに書き出し、媒体で運んでから –from-dir でミラー レジストリへ入れます。オペレーター(OKD Virtualization など)もミラーする場合は oc-mirror を使います。この記事では、リリース イメージ(クラスタ本体)だけをミラーします。
install-config.yaml
オンライン環境との違いは、pullSecret・additionalTrustBundle・imageDigestSources の 3 か所と、ネットワーク(machineNetwork・VIP)です。
実行する場所:踏み台サーバー(root)
# mkdir -p /root/okd/okdoff && cd /root/okd/okdoff
# CA=$(sed 's/^/ /' /srv/registry/certs/ca.crt)
# cat > install-config.yaml <<EOF
apiVersion: v1
baseDomain: hvdoc.lab
metadata:
name: okdoff
compute:
- name: worker
replicas: 0
controlPlane:
name: master
replicas: 3
networking:
networkType: OVNKubernetes
machineNetwork:
- cidr: 10.30.0.0/24
clusterNetwork:
- cidr: 10.128.0.0/14
hostPrefix: 23
serviceNetwork:
- 172.30.0.0/16
platform:
baremetal:
apiVIPs:
- 10.30.0.4
ingressVIPs:
- 10.30.0.5
pullSecret: '$(cat /root/okd/pull-secret-mirror.json)'
sshKey: '$(cat /root/.ssh/id_ed25519.pub)'
additionalTrustBundle: |
$CA
imageDigestSources:
- mirrors:
- registry.hvdoc.lab:5000/okd/scos-release
source: quay.io/okd/scos-content
- mirrors:
- registry.hvdoc.lab:5000/okd/scos-release
source: quay.io/okd/scos-release
EOF
| 項目 | 内容 |
|---|---|
| pullSecret | ミラー レジストリの認証情報(ユーザー okd) |
| additionalTrustBundle | ミラー レジストリの証明書を発行した CA。ノードがこの CA を信頼する |
| imageDigestSources | quay.io/okd/… のイメージを、ミラー レジストリから取るように置き換える |
| machineNetwork・VIP | オフライン側のネットワーク 10.30.0.0/24 と、その中の未使用の IP アドレス |
agent-config.yaml
baremetal の記事と同じ形です。IP アドレス、ゲートウェイ・DNS(踏み台 10.30.0.1)と、additionalNTPSources が違います。
実行する場所:踏み台サーバー(root)
# cat > agent-config.yaml <<'EOF'
apiVersion: v1beta1
kind: AgentConfig
metadata:
name: okdoff
rendezvousIP: 10.30.0.11
additionalNTPSources:
- 10.30.0.1
hosts:
- hostname: off-master-1
role: master
rootDeviceHints:
deviceName: /dev/disk/by-path/pci-0000:09:01.0-scsi-0:0:0:0
interfaces:
- name: ens18
macAddress: BC:24:11:0D:01:11
networkConfig:
interfaces:
- name: ens18
type: ethernet
state: up
identifier: mac-address
mac-address: BC:24:11:0D:01:11
ipv4:
enabled: true
dhcp: false
address:
- ip: 10.30.0.11
prefix-length: 24
ipv6:
enabled: false
dns-resolver:
config:
server:
- 10.30.0.1
routes:
config:
- destination: 0.0.0.0/0
next-hop-address: 10.30.0.1
next-hop-interface: ens18
(off-master-2 は 10.30.0.12・MAC BC:24:11:0D:01:12、off-master-3 は 10.30.0.13・MAC BC:24:11:0D:01:13 で同じように書く)
EOF
| 項目 | 内容 |
|---|---|
| additionalNTPSources | ノードが時刻を取る NTP サーバー(踏み台の chrony) |
| routes の next-hop-address | 既定のゲートウェイ。外部へは出られないが、インストーラーの確認のために設定する |
エージェント ISO の作成
実行する場所:踏み台サーバー(root)
# openshift-install agent create image --dir /root/okd/okdoff
期待する出力(抜粋):
INFO Extracting base ISO from release payload
WARNING Failed to extract base ISO from release payload - check registry configuration
INFO Downloading base ISO
INFO Generated ISO at /root/okd/okdoff/agent.x86_64.iso.
ベース ISO(CentOS Stream CoreOS)は、まずミラーからの取り出しを試し、失敗するとインターネットからダウンロードします。この環境では取り出しに失敗し、踏み台がインターネットに出られるためダウンロードで ISO を作れました。ISO を作るだけなので、ノード側のオフライン動作には影響しません。踏み台もインターネットに出られない場合は、ベース ISO をあらかじめ用意しておく必要があります。
ノードの起動とインストール
ISO を Proxmox VE にアップロードし、3 台の仮想マシンを作って起動します。手順は baremetal の記事と同じで、NIC をオフライン側のブリッジ(hvnet0)につなぐところだけが違います。
| 項目 | 値 |
|---|---|
| net0 | ブリッジ hvnet0、MAC BC:24:11:0D:01:11〜13(agent-config.yaml と同じ) |
| ディスク・CPU・メモリ | baremetal の記事と同じ(scsi0 120GB、8 vCPU、24GB) |
(1) ランデブー ホスト(off-master-1)の画面に「This host (10.30.0.11) is the rendezvous host.」と表示され、3 台がそろうと「Cluster installation in progress」に変わります。

(2) ほかのノードの画面には、ランデブー ホストの IP アドレスが表示されます。

(3) インストールの完了を待ちます。
実行する場所:踏み台サーバー(root)
# openshift-install agent wait-for bootstrap-complete --dir /root/okd/okdoff
# openshift-install agent wait-for install-complete --dir /root/okd/okdoff
期待する出力(抜粋):
INFO Bootstrap Kube API Initialized
INFO Bootstrap configMap status is complete
INFO cluster bootstrap is complete
INFO Install complete!
INFO Access the OpenShift web-console here: https://console-openshift-console.apps.okdoff.hvdoc.lab
この環境では、ノードの起動から完了まで約 55 分でした(うち約 20 分は、下の「インストールが進まないとき」の対処に使った時間です)。
インストールが進まないとき
ほかのノードの画面が「rendezvous host is at …」のまま 20 分以上進まないときは、ランデブー ホストにログインし、イメージの取得に失敗していないかを確認します。
実行する場所:踏み台サーバー(root)
# ssh [email protected] sudo journalctl -u node-image-pull -u release-image --no-pager -n 20
失敗しているときの出力(抜粋):
node-image-pull.sh[8195]: level=warning msg="Failed, retrying in 1s ... (1/50). Error: (Mirrors also failed: [registry.hvdoc.lab:5000/okd/scos-release@sha256:4a1c64c2...: reading manifest sha256:4a1c64c2... in registry.hvdoc.lab:5000/okd/scos-release: manifest unknown]): quay.io/okd/scos-content@sha256:4a1c64c2...: pinging container registry quay.io: Get "https://quay.io/v2/": dial tcp 52.206.240.228:443: i/o timeout"
| 表示 | 原因と対処 |
|---|---|
| manifest unknown | ミラーにそのイメージがない。–keep-manifest-list=true を付けてミラーし直す(ミラー済みのデータは再転送されないので、この環境では 1 分半で終わった)。ノードは自動で再試行するため、ノードを作り直す必要はない |
| x509: certificate signed by unknown authority | additionalTrustBundle の CA が違う。ISO を作り直す |
| unauthorized | pullSecret の認証情報が違う。ISO を作り直す |
| i/o timeout(quay.io) | オフラインなので正常。ミラーの取得に失敗したときに、元の quay.io も試した記録 |
確認
(1) ノードとクラスタのバージョンを確認します。
実行する場所:踏み台サーバー(root)
# export KUBECONFIG=/root/okd/okdoff/auth/kubeconfig
# oc get nodes -o wide
# oc get clusterversion
# oc get co
期待する出力(抜粋):
NAME STATUS ROLES AGE VERSION INTERNAL-IP
off-master-1 Ready control-plane,master,worker 6m v1.36.3 10.30.0.11
off-master-2 Ready control-plane,master,worker 27m v1.36.3 10.30.0.12
off-master-3 Ready control-plane,master,worker 27m v1.36.3 10.30.0.13
NAME VERSION AVAILABLE PROGRESSING SINCE STATUS
version 5.0.0-okd-scos.3 True False 7m28s Cluster version is 5.0.0-okd-scos.3
oc get co で、すべてのクラスタ オペレーターの AVAILABLE が True になっていることを確認します。
(2) イメージの取り先の置き換え(ImageDigestMirrorSet)がクラスタに入っていることを確認します。install-config.yaml の imageDigestSources から自動で作られます。
# oc get imagedigestmirrorset image-digest-mirror -o yaml
期待する出力(抜粋):
spec:
imageDigestMirrors:
- mirrors:
- registry.hvdoc.lab:5000/okd/scos-release
source: quay.io/okd/scos-content
- mirrors:
- registry.hvdoc.lab:5000/okd/scos-release
source: quay.io/okd/scos-release
(3) ノードからインターネットに出られないこと、時刻を踏み台から取っていることを確認します。
# ssh [email protected] 'curl -s -m 5 https://quay.io/v2/ || echo NG; chronyc sources'
期待する出力(抜粋):
NG
^* registry.hvdoc.lab 3 6 377 90 -11us[ -155us] +/- 5206us
| 確認項目 | 結果 |
|---|---|
| quay.io への接続 | できない(NG)。イメージはすべてミラーから取っている |
| 時刻の同期先 | registry.hvdoc.lab(踏み台 10.30.0.1 の chrony)に「*」(同期中) |
ノードの crictl images では、イメージ名が quay.io/okd/scos-content と表示されます。これは「元の名前」で、実際の取得先は ImageDigestMirrorSet で置き換えたミラーです。
Web コンソール(https://console-openshift-console.apps.okdoff.hvdoc.lab)は Ingress の VIP(10.30.0.5)にあるため、10.30.0.0/24 に届く端末から開きます。画面は オンライン環境の記事と同じです。
オフライン環境で後から必要になること
| 作業 | 方法 |
|---|---|
| OperatorHub のオペレーター(OKD Virtualization など) | oc-mirror でカタログとオペレーターのイメージをミラーし、作られた CatalogSource を適用する。既定のカタログ(インターネット)は無効にする |
| クラスタの更新 | 新しいリリースを同じ手順(oc adm release mirror –keep-manifest-list=true)でミラーし、oc adm upgrade –to-image で更新する |
| ミラー レジストリの証明書の更新 | 有効期限(この手順では 10 年)の前に作り直し、クラスタの additionalTrustBundle(user-ca-bundle)も更新する |
