まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:upgrade

エアギャップ(インターネット接続無し)環境での OCP(Openshift Container Platform) の導入/運用手順を紹介するシリーズです。今回は「エアギャップ環境にインストールした OCP をアップグレードする」手順を紹介します。OCP はバグ修正を含むメンテナンスが随時行われており、比較的バージョンアップ頻度が高い印象があります。これはこれで安心して使えることになるのですが、バージョンアップ頻度が高いということは、サポート中バージョンがサポート切れになるスピードも比較的早い、ということを意味しています。そのため運用環境のサポート状態を維持するには OCP のアップグレードが欠かせません。 

インターネット接続環境であれば(インターネット上で RedHat 社が提供している仕組みを使って)比較的簡単にアップグレードできるのですが、エアギャップ環境となるとそうはいかなくなります。エアギャップ環境での OCP インストール手順はググればいくつかの情報が見つかるのですが、私が調べた限りでは(英語含めて)エアギャップ環境での OCP アップグレード手順は(詳しくは記事内で紹介しますが)ちとややこしい手順が必要なせいか、見つけることはできませんでした。詳しそうな人に聞いても「理論的にはできると思う」という答や、「できるかどうかで言うとできるんだけど、ケース・バイ・ケースの対応が多くてドキュメント化が難しい」という回答の多い作業のようでした。事例的にもあまり多くないのだと思っています。 

今回のブログはそんなエアギャップ環境での OCP アップグレード手順の紹介します。おそらくですが、公開されているドキュメントという観点でもかなり貴重なもののはず、だと思っています。


【大まかな流れ】
エアギャップ環境の OCP クラスタアップグレードする場合、大きくは以下の流れを実施することになります:
(0)最終的にアップグレードしたい OCP バージョンを確定させ、アップグレードパスを確認
(1)インターネット接続環境下でアップグレードに必要なイメージファイルを取得する
(2)(1)で取得したイメージファイルをエアギャップ環境に持ちこんでミラーレジストリを更新し、OCP をアップグレードする
(3)(1)と(2)をアップグレードパスに必要な回数だけ繰り返す


ではこの流れで実際にエアギャップ環境の OCP をアップグレードする手順を紹介します。


【(0)最終的にアップグレードしたい OCP バージョンを確定させ、アップグレードパスを確認】
以前のブログでエアギャップ OCP クラスタをインストールする手順を紹介した際は OCP 4.13.0 というバージョンでの手順を紹介しました。これを「どのバージョンに上げるか?」を確定させる必要があります。この辺りはバージョンアップ戦略やポリシーにも依存する部分があり、「常に最新バージョンにする」という場合は現時点でリリースされている最新バージョン(数字がもっとも大きいもの)が目的のバージョンになります。一方で「契約内容やバージョンによる長期サポートの有無、延長サポートの有無を考慮して、最も長い期間サポートされるバージョン(数字が大きいものとは限らない)」が目的になることもあります。この辺りは個別事情になるのですが、今回は LTS でもある OCP 4.14 を目指すこととして、(OCP 4.13.0 から)OCP 4.14.0 へのアップグレードを紹介することとします。この辺り、個別の環境と異なっている場合は適宜読み替えてください。

現在のバージョンと、アップグレード先のバージョンが確定したら、次はアップグレードパスを確認します。OCP は現在のバージョンとアップグレード先バージョンの組み合わせによって、1回のアップグレード作業で実現できたり、できなかったり(2回になるか、3回になるか、・・・)します。その点を考慮した上で、目的のバージョンまで1回の作業でアップグレードできるのか、できない場合は間にどのようなバージョンアップを挟んで実現するのか、を決める必要があるのですが、この「間にどのようなバージョンアップを挟んで実現するのか」のことをアップグレードパスと呼びます。以前に私のブログでもアップグレードパスの調べ方含めて紹介したことがありました:
https://dotnsf.blog.jp/archives/1083194426.html


実際に OCP 4.13.0 から OCP 4.14.0 へのアップグレードを実施するという前提でのアップグレードパスを確認してみましょう。インターネット接続がある環境でこちらにアクセスします(RedHat アカウントでのログインが必要です):
https://access.redhat.com/labs/ocpupgradegraph/update_path


以下のような画面が表示されます:
2024072801


この画面内にアップグレード作業の内容を入力していきます。まず Current Channel は現在稼働中の環境のチャネルなので "stable-4.13" 、Architecture は "x86_64" を指定します。そして "Current OpenShift Version" に現在のバージョンである "4.13.0" を、"Target OpenShift Version" には "4.14.0" をそれぞれ指定し、最後に "Generate" ボタンをクリックします:
2024072802


すると画面下部に以下のような結果が表示されます。つまり 4.13.0 から 4.14.0 へのアップグレードパスは 4.13.0 → 4.13.19 → 4.14.0 と、間に一度 4.13.19 へのアップグレードを挟んで2回に分けて実施する必要がある、ということがわかります:
2024072803


このアップグレードパスを理解した上で実際に OCP をアップグレードしていきましょう。



【(1)インターネット接続環境下でアップグレードに必要なイメージファイルを取得する】
4.13.0 を 4.14.0 にアップグレードする手順として、最初に 4.13.0 を 4.13.19 にアップグレードする必要があることがわかりました。というわけで、まずは 4.13.0 から 4.13.19 へのアップグレードを想定した準備を行います。

ここでの作業はインターネット接続環境下で実施します。以前に OCP 4.13.0 をインストールした時のブログエントリでも説明したインターネット接続環境と同様の準備を実施します(podman や oc、oc-mirror などもインストールします)。4.13.0 インストールの時はバスチョンサーバーに /data/imageset-config-4.13.0.yaml というOCP 4.13.0 向けイメージファイル取得用のファイルを以下の内容で用意しました:
kind: ImageSetConfiguration
apiVersion: mirror.openshift.io/v1alpha2
storageConfig:
  local:
    path: /data/mirror-ocp
mirror:
  platform:
#    architectures:
#      - "x86_64"
    channels:
    - name: stable-4.13
      type: ocp
      minVersion: '4.13.0'
      maxVersion: '4.13.0'
    graph: true
  operators:
  - catalog: registry.redhat.io/redhat/redhat-operator-index:v4.13
    full: false
    packages:
    - name: local-storage-operator
      channels:
      - name: stable
  additionalImages:
  - name: registry.redhat.io/ubi8/ubi:latest
  - name: gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.2
  - name: docker.io/rancher/busybox:1.31.1
  helm: {}

実はここがエアギャップ OCP アップグレードのややこしい所ではあるのですが、この「以前に OCP をインストールした時」の環境がそのまま残っていて、同ファイル( /data/imageset-4.13.0.yaml )を使ってダウンロードしたイメージファイル /data/mirror-ocp/mirror_seq1_000000.tar が残っている場合は再度 OCP 4.13.0 用のイメージファイルをダウンロードする必要はありません。逆に残っていない場合(そもそも異なるマシンが用意されていたり、同じマシンでも /data/mirror-ocp/mirror_seq1_000000.tar が残っていない場合)は再度同ファイルをダウンロードする必要があります。この辺りは少しわかりにくい部分ですが、最初に(OCP インストール時に) /data/mirror-ocp/mirror_seq1_000000.tar をダウンロードした時の /data/mirror-ocp/ フォルダ内に記録された関連ファイル含めてイメージファイルが残っている場合は、ここからの差分ファイルだけを用意するだけでアップグレードできます。逆に関連ファイルがなかったりする場合は(既に 4.13.0 環境があるので、なんとなく無駄なような気がするかもしれませんが)4.13.0 インストール用のイメージファイル /data/mirror-ocp/mirror_seq1_000000.tar を再度ダウンロードし直す所から実施する必要がある、という点に注意してください。イメージファイルのダウンロード手順はインストール手順を確認してください。

ここまでできたら、改めて 4.13.0 インストール用のイメージダウンロードファイル /data/imageset-4.13.0.yaml の、 4.13.0 から 4.13.19 へのアップグレード版に相当する /data/imageset-4.13.0-4.13.19.yaml を以下の内容で用意します:
kind: ImageSetConfiguration
apiVersion: mirror.openshift.io/v1alpha2
storageConfig:
  local:
    path: /data/mirror-ocp
mirror:
  platform:
#    architectures:
#      - "x86_64"
    channels:
    - name: stable-4.13
      type: ocp
      minVersion: '4.13.0'
      maxVersion: '4.13.19'
      shortestPath: true
    graph: true
  operators:
  - catalog: registry.redhat.io/redhat/redhat-operator-index:v4.13
    full: false
    packages:
    - name: local-storage-operator
      channels:
      - name: stable
  additionalImages:
  - name: registry.redhat.io/ubi8/ubi:latest
  - name: gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.2
  - name: docker.io/rancher/busybox:1.31.1
  helm: {}

元のファイル imageset-4.13.0.yaml からの違いが2か所あります(赤字で記しています)。まず maxVersion の値を '4.13.0' から '4.13.19' に変えています。今回必要なのは(4.13.0 のイメージが存在している前提で)4.13.0 から 4.13.19 への差分となるイメージなので minVersion は '4.13.0' のままでいいのですが、maxVersion は '4.13.19' に変更します。また途中のバージョンのイメージは不要なので shortestPath: true の行を追加しています。他は 4.13 ベースのままの差分ということもあってそのままです。

そしてこのファイルを使って以下を実行し、4.13.0 から 4.13.19 へアップグレードするための差分イメージファイルを作成します:
# umask 0022

# mkdir -p /data/mirror-ocp

# cd /data

# oc mirror --config=imageset-config-4.13.0-4.13.19.yaml file:///data/mirror-ocp

コマンド実行が成功すると /data/mirror-ocp/mirror_seq2_000000.tar という巨大なファイルが作られます。ここで重要な点は、できあがるファイル名の seq に続く数字が1ではなく2になっていることです。これは単にファイル名だけの問題ではなく(作った後にファイル名を変えればいいという問題ではなく)既に1に該当するファイルやフォルダが(/data/mirror-ocp/ 以下に)作成されていて、その続きであることを認識して2が生成されている、ということです。「1があっての2」として作られたファイルであることを再度認識しておく必要があります。


同様にして 4.13.19 から 4.14.0 にアップグレードするための差分イメージファイルも用意します。まずは /data/imageset-4.13.19-4.14.0.yaml を以下の内容で作成します:
kind: ImageSetConfiguration
apiVersion: mirror.openshift.io/v1alpha2
storageConfig:
  local:
    path: /data/mirror-ocp
mirror:
  platform:
#    architectures:
#      - "x86_64"
    channels:
    - name: stable-4.14
      type: ocp
      minVersion: '4.13.19'
      maxVersion: '4.14.0'
      shortestPath: true
    graph: true
  operators:
  - catalog: registry.redhat.io/redhat/redhat-operator-index:v4.14
    full: false
    packages:
    - name: local-storage-operator
      channels:
      - name: stable
  additionalImages:
  - name: registry.redhat.io/ubi8/ubi:latest
  - name: gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.2
  - name: docker.io/rancher/busybox:1.31.1
  helm: {}

imageset-4.13.0-4.13.19.yaml からの変更点として、チャネルはアップグレード先である "stable-4.14" に変更します。また 4.13.19 から 4.14.0 への最小差分を取得したいので minVersion を "4.13.19"、maxVersion を "4.14.0" にして shortestPath を true にします。加えてオペレーターも 4.14 ベースに変えたいのでカタログ URL のタグ部分を "v4.14" に変更します。

このファイルを使って 4.13.19 から 4.14.0 への差分イメージファイルを作成します:
# umask 0022

# mkdir -p /data/mirror-ocp

# cd /data

# oc mirror --config=imageset-config-4.13.19-4.14.0.yaml file:///data/mirror-ocp

このコマンドが成功すると /data/mirror-ocp/mirror_seq3_000000.tar という差分イメージファイルが作成されます。このファイルも上述と同様に「2があっての3」のファイルです。


次にアップグレード後のバージョンの「ダイジェスト値」を調べます。インストール時にはダイジェスト値を意識する必要はなかったのですが、アップグレード時はこのダイジェスト値を指定してアップグレードを実行することになります(例えば 4.13.19 にアップグレードする場合は、"4.13.19" という文字列を指定するのではなく、"4.13.19 のダイジェスト値"(正確には x86_64 アーキテクチャの "4.13.19 のダイジェスト値")を指定してアップグレードを実行します)。この値もインターネットに接続された環境で調べる必要があります。

(x86_64 アーキテクチャの)4.13.19 のダイジェスト値は以下のコマンドで調べることができます:
# oc adm release info quay.io/openshift-release-dev/ocp-release:4.13.19-x86_64 | sed -n 's/Pull From: .*@//p' > /data/4.13.19.digest

実行後に /data/4.13.19.digest というテキストファイルが作られ、その中は "sha256:" で始まる1行の内容になっています:

2024072804


この "sha256:" に続く部分が 4.13.19 のダイジェスト値です。この値もアップグレード時に必要なものです。

同様にして 4.14.0 のダイジェスト値も調べて /data/4.14.0.digest というファイルに格納しておきます:
# oc adm release info quay.io/openshift-release-dev/ocp-release:4.14.0-x86_64 | sed -n 's/Pull From: .*@//p' > /data/4.14.0.digest


ここまでできればインターネット接続環境で実施するアップグレードのための手順はほぼ終わりですが、インターネット接続環境で実施する作業の最後にアップグレード後のバージョンに合わせた oc や oc-mirror を用意します。

今回の場合は 4.14.0 向けの oc や oc-mirror ツールを用意します。それぞれ /data/oc-4.14.0, /data/oc-mirror-4.14.0 という名前でファイルを用意します:
# mkdir -p /tmp/oc

# cd /tmp/oc

# wget https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/4.14.0/oc-mirror.tar.gz

# tar -xf oc-mirror.tar.gz

# chmod +x oc-mirror

# cp oc-mirror /data/oc-mirror-4.14.0

# wget https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/4.14.0/openshift-client-linux-4.14.0.tar.gz

# tar xzvf openshift-client-linux-4.14.0.tar.gz oc

# cp oc /data/oc-4.14.0


ここまでの手順で以下のファイルが /data/ 以下に揃っているはずです(赤字はコメント):
- /data/mirror-ocp/mirror_seq1_000000.tar (OCP 4.13.0 のミラーイメージ)
- /data/mirror-ocp/mirror_seq2_000000.tar (OCP 4.13.0 から 4.13.19 の差分ミラーイメージ)
- /data/mirror-ocp/mirror_seq3_000000.tar (OCP 4.13.19 から 4.14.0 の差分ミラーイメージ)
- /data/oc-4.14.0             (oc 4.14.0)
- /data/oc-mirror-4.14.0          (oc-mirror 4.14.0)
- /data/4.13.19.digest           (4.13.19 のダイジェスト値が記載されたファイル)
- /data/4.14.0.digest           (4.14.0 のダイジェスト値が記載されたファイル)

これら全てのファイルが必要です(OCP 4.13.0 をインストールした時につかったミラーイメージファイル mirror_seq1_000000.tar と全く同じファイルがバスチョンサーバーに残っている場合は一番上のファイルは不要です)。これまでと同様に、これらのファイルを USB メディアなどを使ってバスチョンサーバーに持ち込む必要があります。

OCP アップグレードを実施する際にインターネット接続環境で行う作業は以上です。


【(2)(1)で取得したイメージファイルをエアギャップ環境に持ちこんでミラーレジストリを更新し、OCP をアップグレードする】

(1)はインターネット接続環境で実施する内容でしたが、ここから先はエアギャップ環境内での作業となります。まずは(1)の作業で用意したファイル群を USB メモリ等を使ってエアギャップ環境のバスチョンサーバー内に持ち込みます。以下ではこれらのファイルが全てバスチョンサーバーの /data/ フォルダ以下に用意されているものと仮定して説明を続けます(赤字はコメント):
- /data/mirror-ocp/mirror_seq1_000000.tar (OCP 4.13.0 のミラーイメージ)
- /data/mirror-ocp/mirror_seq2_000000.tar (OCP 4.13.0 から 4.13.19 の差分ミラーイメージ)
- /data/mirror-ocp/mirror_seq3_000000.tar (OCP 4.13.19 から 4.14.0 の差分ミラーイメージ)
- /data/oc-4.14.0             (oc 4.14.0)
- /data/oc-mirror-4.14.0          (oc-mirror 4.14.0)
- /data/4.13.19.digest           (4.13.19 のダイジェスト値が記載されたファイル)
- /data/4.14.0.digest           (4.14.0 のダイジェスト値が記載されたファイル)

エアギャップ環境の OCP をアップグレードするには、エアギャップ環境内のミラーレジストリをアップグレード先バージョンのものに更新する必要があります。今回の場合、まずはミラーレジストリを 4.13.19 仕様に更新して OCP 4.13.19 にアップグレードし、続けてミラーレジストリを 4.14.0 仕様に更新して OCP 4.14.0 にアップグレードする、という順序になります(エアギャップ環境でなければ、RedHat 提供の公開レジストリを使うことができるのでミラーレジストリを用意したり更新したりする必要はありません)。

というわけで、早速現在 4.13.0 使用のミラーレジストリを 4.13.19 仕様に更新・・・ したくなるのですが、その前に1点確認が必要です。 現在の 4.13.0 仕様のミラーレジストリ(以前のブログで 4.13.0 をインストールした時のミラーレジストリ)を作った時に使った mirror_seq1_000000.tar は、今回用意した mirror_seq1_000000.tar と全く同じファイルでしょうか? 4.13.0 から 4.13.19 への差分いらーイメージは mirror_seq2_000000.tar ですが、このファイルは「seq1 (mirror_seq1_000000.tar)がある前提での seq2」のファイルになっています。この "seq1" と全く同じファイルを使って現在のミラーレジストリが作られているのだとしたら、そのまま seq2 を適用できるのですが、同じ設定で seq1 を作り直したのだとしたら、そのままでは seq2 を適用できず、ミラーレジストリを調整する必要があります。

OCP インストール時とは違う mirror_seq1_000000.tar ファイルを用意している場合は seq2 の前提となっている seq1(今回用意した mirror_seq1_000000.tar )でミラーレジストリを上書きしてからでないと seq2 は正しく適用できないので(ごちゃごちゃ書いてますが、初期インストール時に使ったものと全く同じ環境が残っているかどうか自信がない場合はとりあえず)、まずは今回持ち込んだ /data/mirror-ocp/mirror_seq1_000000.tar を使ってミラーレジストリを上書きします。具体的には root 権限でターミナルを開き、トークンでログイン(ウェブコンソールの「ログインコマンドのコピー」からログイン)して、以下のコマンドを実行します:
# cd

# oc mirror --continue-on-error --from=/data/mirror-ocp/mirror_seq1_000000.tar docker://registry.ocp.xxx.localdomain:5000

このコマンドが正常に終了していると "~/oc-mirror-workspace/" 以下に "results-xxxxxxxxxx" という名前のフォルダが作られています("xxxxxxxxxx" 部分は実行時のタイムスタンプ)。OCP インストール時にも同様のコマンドを実行しているので、"~/oc-mirror-workspace/" 以下にはタイムスタンプの異なる複数のフォルダができているはずです。今回作られたフォルダを判別するにはフォルダの作成時タイムスタンプで判断する必要があります。注意してください。

では、新たに作成された ~/oc-mirror-workspace/results-xxxxxxxxxx/ フォルダの情報を使ってミラーレジストリを更新します:
# cd oc-mirror-workspace

# oc apply -f ~/oc-mirror-workspace/results-xxxxxxxxxx

# oc apply -f ~/oc-mirror-workspace/results-xxxxxxxxxx/release-signatures/

これでアップグレード前のミラーレジストリの調整は完了です。

ここまでの作業が完了しているとアップグレード用のミラーレジストリ差分イメージを適用することができるようになります。まずは 4.13.0 から 4.13.19 への差分イメージ(mirror_seq2_000000.tar)でミラーレジストリを上書きし、その結果できあがったフォルダ("~/oc-mirror-workspace/results-yyyyyyyyyy/"  "yyyyyyyyyy" 部分のタイムスタンプで判断)の情報を適用します(mirror_seq1_000000.tar のインポートを飛ばした場合はトークンでログインしてから実行する必要があります):
# cd

# oc mirror --continue-on-error --from=/data/mirror-ocp/mirror_seq2_000000.tar docker://registry.ocp.xxx.localdomain:5000

# cd oc-mirror-workspace

# oc apply -f ~/oc-mirror-workspace/results-yyyyyyyyyy

# oc apply -f ~/oc-mirror-workspace/results-yyyyyyyyyy/release-signatures/

これでミラーレジストリには 4.13.0 インストール用だけでなく、4.13.19 アップグレード用のイメージも上書きされています。確認する場合は以下のコマンドを実行します:
# podman image search --list-tags --limit=1000 registry.ocp.xxx.localdomain:5000/openshift/release

実行結果が以下のように "4.13.19" という文字を含む内容になっていればミラーレジストリ内に 4.13.19 アップグレード用のイメージが含まれた状態になっています:
2024072805


これでミラーレジストリは(現在の 4.13.0 から)4.13.19 にアップグレードできる状態になりました。早速アップグレードを実行してみましょう。まずはアップグレード先である 4.13.19 のダイジェスト値を確認します(青字は実行結果):
# cat /data/4.13.19.digest
sha256:f8ba6f54eae419aba17926417d950ae18e06021beae9d7947a8b8243ad48353a

"sha256:" で始まる1行のテキストが表示されます。この値を用いて以下の命令を実行することで 4.13.19 へのアップグレード指示を実行します:
# oc adm upgrade --allow-explicit-upgrade --allow-upgrade-with-warnings --to-image quay.io/openshift-release-dev/ocp-release@sha256:f8ba6f54eae419aba17926417d950ae18e06021beae9d7947a8b8243ad48353a

実行条件によっては警告が表示されることもありますが、エラーになっていなければ無視してください。最後に "Requested upgrade to ..." と表示されていれば成功です:
2024072806


アップグレードの様子はウェブブラウザから確認できます。まずは以下のコマンドでウェブコンソールにログインするためのパスワードを確認します:
# cat ~/config/auth/kubeadmin-password

パスワードが確認できたらウェブブラウザでウェブコンソール(https://console-openshift-console.apps.ocp.xxx.localdomain/)を開き、ID は "kubeadmin" 、パスワードは上で確認したものを指定してログインします:
2024072807


ログイン後、左上のメニューから Administration - Cluster Settings を選択します。上述のアップグレードコマンド(oc adm upgrade)が成功していると、Details タブ内で 4.13.19 へのアップグレードが進行中(Upgrade to 4.13.19 in progress)であることが分かります:
2024072808


アップグレードは少しずつ進行してゆきます。しばらく待っているとアップグレードは完了し、新しいバージョン(4.13.19) に切り替わったことが確認できます:
2024072809


同画面下部には OCP バージョンの更新履歴も表示されています:
2024072810


ここまでの作業でエアギャップ環境の OCP が 4.13.0 から 4.13.19 へアップグレードできました。ミラーレジストリ更新時のややこしさはありましたが、基本的には 「ミラーレジストリ内に更新先バージョンのイメージを上書き」→「アップグレード」 という流れでアップグレードできます。


では同様にして 4.13.19 から 4.14.0 にアップグレードしてみましょう。まずはミラーレジストリを差分イメージファイルで上書きしておきます。上記同様に 4.13.19 から 4.14.0 への差分イメージ(mirror_seq3_000000.tar)でミラーレジストリを上書きし、その結果できあがったフォルダ("~/oc-mirror-workspace/results-zzzzzzzzzz/"  "zzzzzzzzzz" 部分のタイムスタンプで判断)の情報を適用します(※):
# cd

# oc mirror --continue-on-error --from=/data/mirror-ocp/mirror_seq3_000000.tar docker://registry.ocp.xxx.localdomain:5000

# cd oc-mirror-workspace

# oc apply -f ~/oc-mirror-workspace/results-zzzzzzzzzz

# oc apply -f ~/oc-mirror-workspace/results-zzzzzzzzzz/release-signatures/

※今回のミラーレジストリ更新では 4.mm.nn の mm 部分が変わるバージョンアップを行います。それが原因なのかどうかは分からないのですが、この 4.13.19 から 4.14.0 への差分イメージである mirror_seq3_000000.tar で上書きする場合は oc mirror コマンド実行時に "--continue-on-error" オプションが必須でした。

4.14.0 イメージで上書きできているか確認する場合は以下のコマンドを実行します:
# podman image search --list-tags --limit=1000 registry.ocp.xxx.localdomain:5000/openshift/release

実行結果が以下のように "4.14.0" という文字を含んでいることを確認します:
2024072901


次に 4.14.0 のダイジェスト値を確認します(青字は出力結果):
# cat /data/4.14.0.digest
sha256:e2c70fca183e380c6121a1c847806f11e839482123277235a8579db472b9ccf2

4.14.0 のダイジェスト値を指定してアップグレード指示を実行します:
# oc adm upgrade --allow-explicit-upgrade --allow-upgrade-with-warnings --to-image quay.io/openshift-release-dev/ocp-release@sha256:e2c70fca183e380c6121a1c847806f11e839482123277235a8579db472b9ccf2

上述と同様にウェブブラウザで管理コンソールを開き、左上メニューから Administration - Cluster Settings を選択します。おそらく今回は前回のようにアップグレード実行中の画面にはならず、以下のようなエラーメッセージが表示されているはずです:
2024072811


これはエラーというよりは確認メッセージで、アップグレード前のバージョン(4.13.19)からアップグレード後のバージョン(4.14.0)に上げることで API の互換性が失われてしまうものが含まれているための警告が表示されています。今回のようにマイナーバージョンが上がるタイプのアップグレードだと起こり得るようです。

この場合、以下のコマンドを追加で実行することで「互換性がないことを理解した上で 4.13 から 4.14 へアップグレードする」ことを指示できます:
# oc -n openshift-config patch cm admin-acks --patch '{"data":{"ack-4.13-kube-1.27-api-removals-in-4.14":"true"}}' --type=merge

このコマンドを実行後に先ほどの画面に戻るとアップグレードが再開されていることが確認できます:
2024072902


しばらく待つとアップグレードが完了し、無事に 4.14.0 に切り替わったことが確認できます:
2024072903


これで OCP クラスタ(サーバー)は 4.14.0 にアップグレードできました。最後に OCP クライアントである oc, oc-mirror を 4.14.0 のものに切り替えます(cp コマンドの前の "\" は強制上書き指定):
# \cp /data/oc-4.14.0 /usr/local/bin/oc

# \cp /data/oc-mirror-4.14.0 /usr/local/bin/oc-mirror

"oc version" コマンドでサーバー・クライアントとも 4.14.0 に切り替わったことを確認します:
2024072904


無事に目的であった OCP 4.14.0 へのアップグレードがエアギャップ環境内で実現できました。 このエアギャップ環境での OCP アップグレードはミラーレジストリの状態や、現在のミラーレジストリを作った時の環境が残っているかどうかによって手順が変わったりすることもあり、手順として説明するにはかなりややこしい内容でした。そんなこともあって「理論的にはできるはずだけど、これまで資料が見つからなかった」のかもしれません。

私が知る限り、インターネットに公開された情報としてはこれが初めてだったと思っていますが、私と同じように手順が分からずに苦しんでいる人の助けになれば幸いです。


エアギャップ環境(インターネット接続のない環境)で OCP を導入/運用する上で必要な前提理解
エアギャップ環境(インターネット接続のない環境)で OCP を導入する手順
エアギャップ環境(インターネット接続のない環境)で OCP にアプリケーションを導入する手順
エアギャップ環境(インターネット接続のない環境)に導入した OCP をエアギャップ環境内でアップグレードする手順







 

エアギャップ(インターネット接続無し)環境での OCP(Openshift Container Platform) の導入/運用手順を紹介するシリーズです。今回は「エアギャップ環境にインストールした OCP へのコンテナアプリケーションデプロイ」手順を紹介します。せっかく作った OCP クラスタもアプリケーションをデプロイできなくては宝の持ち腐れです。でもアプリケーションのデプロイってインターネット接続を前提とする処理が多いのです。一部の商用アプリケーションの中にはエアギャップ環境を前提とした導入方法が提供されているものもないわけではないのですが、多くのアプリケーションの場合はそうではありません。例えばアプリケーションイメージがある DockerHub などのイメージリポジトリを指定してデプロイ・・・はエアギャップ環境だとできませんよね。OCP の機能であるソースコードと Dockerfile からデプロイ・・・も、インターネット接続が無いとベースイメージは取得できないし、"npm install" みたいな外部ライブラリのインストールもできないのです。さてどうやってアプリケーションをデプロイするのか・・・ という紹介です。


【大まかな流れ】
エアギャップ環境の OCP クラスタにアプリケーションコンテナをデプロイする場合、大きくは以下の流れを実施することになります:
(0)エアギャップ環境の OCP クラスタを用意
(1)インターネット接続環境下でコンテナアプリケーション化したコンテナイメージをイメージファイルとして保存
(2)(1)のイメージファイルをエアギャップ環境に持ち込んで、ミラーレジストリに格納してから OCP にデプロイ

ではこの流れで実際にアプリケーションをエアギャップ環境の OCP にデプロイする手順を紹介します。


【(0)エアギャップ環境の OCP クラスタを用意】
エアギャップ環境への OCP インストール方法は既にこのブログで前回紹介済みです。インターネット接続のない環境下に OCP クラスタが構築されている、という前提で以下を紹介するので、そのような OCP 環境を用意してください。


【(1)インターネット接続環境下でコンテナアプリケーション化したコンテナイメージをイメージファイルとして保存】
(1)はインターネット接続環境下で実施する手順です。インターネット接続環境がある状態で docker 環境を用意し、その docker を使ってインストールしたいコンテナアプリケーションを(ベースイメージや依存環境含めて)イメージファイル化する、という手順です。 なお今回は私が作成して公開している dotnsf/hostname というコンテナアプリケーションを例にエアギャップ OCP にデプロイする、という手順を紹介します(他のアプリケーションでも同様に応用できると思います)。

ちなみにこのアプリケーションは docker 環境があれば、
# docker run -d -p 8080:8080 dotnsf/hostname

というコマンドでデプロイして、8080 番ポートを使って動かすことができます。機能が本当にシンプルで「HTTP リクエストに対してコンテナ Pod 内の /etc/hostname を表示する」というだけのアプリケーションです。コンテナクラスタ環境では1つのアプリケーションが色々な Pod で動くので、その Pod を確認するためだけに作ったものです。実際に動かしてアクセスすると以下のような画面になる、というだけのものです(こんな感じの画面が出ればデプロイ成功だと思ってください):
2024072719


ではこのコンテナアプリケーションをエアギャップ環境の OCP にデプロイするまでの手順を紹介します。まずはインターネット接続状態で docker 導入済みの環境を用意してください。RHEL であれば "yum install podman" で docker 互換の podman をインストールしていただいても構いません。 前回の記事でもエアギャップ OCP を構築する前にインターネット接続環境でも準備を行いましたが、この時のインターネット接続環境が残っている場合はその環境でも構いません(こちらの環境であれば podman もインストール済みのはずです)。

では手順をおってこの dotnsf/hostname アプリケーションをイメージファイル化していきます。まず今回のターゲットであるイメージは公開イメージなのでそのままでもダウンロード(docker pull)できますが、認証が必要なイメージの場合はログインしておきます:
# podman login -u <username>

そして対象のイメージ(dotnsf/hostname)を pull します:
# podman pull dotnsf/hostname

pull したイメージをファイル(hostname.tar)として保存します:
# podman save dotnsf/hostname -o hostname.tar

このファイル(hostname.tar)はアプリケーションの動作に必要なイメージやライブラリが含まれたものです。このファイルをエアギャップ環境内に持ち込む必要があります。


【(2)(1)のイメージファイルをエアギャップ環境に持ち込んで、ミラーレジストリに格納してから OCP にデプロイ】

USB メディア等を使って、(1)で作成したファイルを前回のブログで作ったエアギャップ環境のバスチョンサーバーに持ち込みます。仮に /data/hostname.tar として用意できているものと仮定して以下を続けます。

バスチョンサーバーに root でログインしてターミナルを開きます。一般ユーザーでログインしてからターミナルを開いて "sudo -i" で root 権限に昇格するでも構いません。

この後 podman のイメージ操作を実行するため、podman にログインします。前回のブログで作ったエアギャップ環境の場合はユーザーもパスワードも admin で作っていたので以下のコマンドを実行します(異なるサーバー名や認証情報の場合は適宜読み替えて実行してください):
# podman login -u admin -p admin registry.ocp.xxx.localdomain:5000

まずはコンテナイメージファイルをエアギャップ環境の podman にロードします:
# podman load -i /data/hostname.tar

"podman images" を実行します。この時点では "docker.io/dotnsf/hostname.tar" という名前で登録されていることが確認できるはずです(青字は実行結果):
# podman images
REPOSITORY                                            TAG         IMAGE ID      CREATED       SIZE
docker.io/library/registry                            latest      a8781fe3b7a2  6 months ago  26 MB
docker.io/dotnsf/hostname                             latest      d7e7918516db  3 years ago   97.5 MB

このイメージに "registry.ocp.xxx.localdomain:5000/openshift/hostname" という、ミラーレジストリのサーバー名を含む名前でタグ付けを実施します:
# podman tag docker.io/dotnsf/hostname registry.ocp.xxx.localdomain:5000/openshift/hostname

再度 "podman images" を実行して以下のような状態になっていれば(最後の行が追加できていれば)タグ付けは成功です:
# podman images
REPOSITORY                                            TAG         IMAGE ID      CREATED       SIZE
docker.io/library/registry                            latest      a8781fe3b7a2  6 months ago  26 MB
docker.io/dotnsf/hostname                             latest      d7e7918516db  3 years ago   97.5 MB
registry.ocp.xxx.localdomain:5000/openshift/hostname  latest      d7e7918516db  3 years ago   97.5 MB

タグ付けした名前でイメージをプッシュします:
# podman push registry.ocp.xxx.localdomain:5000/openshift/hostname

ここまでできればアプリケーションイメージコンテナがリポジトリに登録された状態になっているので、エアギャップ環境ではない通常の方法と同様にアプリケーションがデプロイできるようになります。 エアギャップ環境に構築した OCP のウェブコンソール画面をブラウザで開いてログインし、画面左上のメニューから "Administrator" ではなく "Developer" を選択してデベロッパーモードに切り替えます:
2024072708


デベロッパーモードの画面から "+Add" を選択します。初回はプロジェクトが選択されていないと思うので("default" などを)選択します。プロジェクトが選択された画面で(アプリケーションのデプロイ方法を選択する画面で) "Container images" を選択します:
2024072709


アプリケーションのイメージ格納場所を入力する画面になります。まず "Image name from external registry" を選択し、その URL として "registry.ocp.xxx.localdomain:5000/openshift/hostname" を入力します。すると以下画面のようにエラーメッセージが表示されます。これはミラーレジストリが公開レジストリではないので(認証情報が必要なので)出ているエラーです。そこで認証情報を登録するため "create an image pull secret" と書かれたリンクをクリックします:
2024072710


レジストリサーバーとその認証情報を指定して作成します。名前は適当に入力し、サーバー名は "registry.ocp.xxx.localdomain:5000" 、ユーザー名とパスワードは "admin" として "Create" します:
2024072711


前の画面に戻り、新しいシークレットが作成された、というメッセージが表示されていることが確認できます。 まだエラーメッセージが表示されていますが、先ほどの内容とは異なっているはずです。今度は(https でアクセスするレジストリサーバーが)自己署名証明書を使っているのでセキュアではない、というメッセージです。そこで "Allow Images from insecure registry" にチェックを入れます:
2024072712


チェックを入れると赤字のエラーメッセージが消え、"Validated" というメッセージが表示されます。これでデプロイ元の情報を入力できました:
2024072713


下に画面をスクロールすると、デプロイするアプリケーションの情報入力画面になります。名前などは適当に、デフォルトのままでも構いませんが、Target port は 8080 を入力し、"Create route" にチェックを入れて、すぐにアクセスできる状態にしてください。最後に "Create" ボタンをクリックします:
2024072714


すると以下のような画面に切り替わります(青枠が表示されるまで少し時間がかかります)。この状態でアプリケーションはコンテナクラスタ内にデプロイされています。アイコン右上の小さなマークをクリックして、アプリケーションを開いてみます:
2024072715


すると(route が作成したアプリケーション公開用 URL が)開きます。自己署名証明書なので警告メッセージが表示されますが、先に進めます:
2024072717


正しくアプリケーションが開くと以下のような画面になります。味気ないですが、上記で説明した /etc/hostname ファイルの内容がそのまま表示されたような画面が開けばアプリケーションとして正しく動いています:
2024072718


これでエアギャップ環境に構築した OCP クラスタ内に、コンテナアプリケーションをデプロイして動かす(ブラウザから動作確認する)ことができました。エアギャップ環境用のインストール手順が用意されていない一般アプリケーションの場合でも、インターネット接続環境で事前に準備しておくことで導入が可能になります。

次回は本シリーズの最終回として、最も情報量の少なかった「エアギャップ環境での OCP アップグレード」手順を紹介します。


エアギャップ環境(インターネット接続のない環境)で OCP を導入/運用する上で必要な前提理解
エアギャップ環境(インターネット接続のない環境)で OCP を導入する手順
エアギャップ環境(インターネット接続のない環境)で OCP にアプリケーションを導入する手順
エアギャップ環境(インターネット接続のない環境)に導入した OCP をエアギャップ環境内でアップグレードする手順











 

エアギャップ(インターネット接続無し)環境での OCP(Openshift Container Platform) の導入/運用手順を紹介するシリーズです。今回は(ただでさえニッチな内容の本シリーズの中では最も需要がありそうな)「エアギャップ環境での OCP インストール」手順を紹介します。アプリデプロイとかアップデートとかも需要あると思ってますが、まずはプラットフォームをインストールしないことには何も始まらないので、エアギャップ環境での OCP システム構築時に必ず通る道ともいえるものです。


【大まかな流れ】
エアギャップ環境で OCP をインストールする場合、大きくは以下の流れを実施することになります:
(0)構成の検討・準備
(1)インターネット接続環境下で必要なインストールに必要なファイル群をダウンロード
(2)(1)でダウンロードしたファイルをエアギャップ環境に持ち込んで OCP を PXE インストール
(3)インストール後の作業

(0)は導入する OCP のバージョンの確定であったり、マスターノード/ワーカーノードの構成(台数)であったり、各ノードサーバーのスペック見積り、といった準備作業です。(1)以降の作業を行う上で RedHat アカウントが必要になるので、その取得なども含まれます。

(1)実際に「OCP をインストールする」と言える作業は(2)で行うことになるのですが、その準備としてインターネット接続環境下でインストールに必要なファイル群をまとめてダウンロードしておく、という作業です。具体的に必要なファイルは(0)で検討したバージョンなどにも依存しますが、単に OCP の導入に必要なファイルだけでなく、前回紹介した周辺環境をまとめてセットアップする OCP4 ヘルパーノードなどもこのタイミングでダウンロードしておきます。

(2)「OCP をインストールする」作業です。これも前回紹介しましたが、本ブログでは PXE インストールによる導入手順を紹介します。各種コマンドを実行することにはなるのですが、いわゆる "setup.exe" や "install.sh" のようなものとは異なり、「インストール自体は PXE で実行されるので、インストール状況を確認するコマンドを実行」することになります。

(3)OCP 導入後にエアギャップ環境特有の設定が必要になります。

ではこの流れで実際に OCP をエアギャップ環境でインストールしてみます。


【(0)構成の検討・準備】
今回構築する OCP は「エアギャップ環境で OCP を作る手順を確認する」ことを目的として(OCP 上で何か重いアプリケーションを動かすことを目的とはせず)、以下のスペックとしました:
・マスターノード3、ワーカーノード3
・ノードは全て仮想サーバー(x86_64)
・仮想サーバーのスペックは vCPU x 4、メモリ 16GB、ディスク 200GB
・各ノードサーバーの NIC は PXE ブートに対応したもの
・OCP バージョンは 4.13.0

ちなみに vCPU x 4 は最小スペックで、メモリはマスターノード 16GB、ワーカーノード 8GB が最小スペック。ディスクは 120 GB が最小で、これらを満たしていないとインストール時のチェックにひっかかります(引っかかった結果、どうなるかは知りません。とりあえず「満たしてない」というメッセージが出ることは確認)。ワーカーノードは(マスターノードにワーカーノードのロールを割り当てれば)0でもいいですが、マスターノードは最低3つ必要です。

これ以外にブートストラップノード(後述)やバスチョンサーバー(後述)も必要なので、1台のデスクトップ PC 内の仮想環境で作ろうとすると、vCPU やディスクはともかく、メモリがかなり厳しいはずで、最低 128GB はないと難しい(スワップしまくり)になると思います。64GB 搭載の PC だとマスターノード3、ワーカーノード0でも厳しいかも。。ちなみに私は(今更 VMWare を使うのもアレなので) VirtualBox を使って今回の作業を実施しています。

改めて、今回の OCP クラスタでは以下表の構成でサーバーを用意することにします:
サーバーホスト名vCPUメモリ(GB)ディスク(GB)OSIP アドレス
バスチョン bastion 4 4 500 RHEL 9.2 10.10.0.10/24
ブートストラップ bootstrap 4 8 200 RHCOS 4.13.0 10.10.0.32/24
マスター0 master0 4 8 200 RHCOS 4.13.0 10.10.0.33/24
マスター1 master1 4 8 200 RHCOS 4.13.0 10.10.0.34/24
マスター2 master2 4 8 200 RHCOS 4.13.0 10.10.0.35/24
ワーカー0 worker0 4 8 200 RHCOS 4.13.0 10.10.0.36/24
ワーカー1 worker1 4 8 200 RHCOS 4.13.0 10.10.0.37/24
ワーカー2 worker2 4 8 200 RHCOS 4.13.0 10.10.0.38/24

なお、ドメインは "ocp.xxx.localdomain" を使うことにします(バスチョンサーバーの FQDN は bastion.ocp.xxx.localdomain" となります)。ちょっと細かいことを言うと、この場合、OCP 導入時の「ドメイン」は "xxx.localdomain" で、"ocp" は「クラスターID」と呼ばれます。この辺り慣れていないとわかりにくいのですが、OCP 導入時は OCP 用のサブドメインを使うことが想定されているので、いわゆる一般的なドメインを使うのではなく、クラスター ID が追加されたサブドメインを使って構築する(OCP のドメインは「クラスターID + ドメイン」から成り立っている)、と理解しておくのが分かりやすいのではないかと思いました。


また今回は PXE インストールを行うため、各ノードサーバーの NIC は PXE 対応している必要があります。物理サーバーの場合は PXE に対応した物理 NIC を用意するか、ネットワークブート可能な KVM を用意してください。仮想サーバーの場合は PXE に対応した仮想 NIC を選択することになります。VirtualBox であればデフォルトの Intel PRO/1000 MT Desktop(82540EM) であれば PXE 対応しています:
2024070900


また各ノードサーバーの起動優先順位を以下のように設定します(上にあるものほど優先順位を高く設定します):
・DVD, USB メモリ
・ディスクストレージ(HDD, SDDドライブ)
・ネットワーク

今回のインストールでは使いませんが、緊急時のメンテナンスなどの目的で DVD や USB メモリから起動したくなるケースが想定されます。そのような時のために DVD や USB メモリでの起動を最優先に設定しておきます。 次にディスクストレージを優先して起動します。今の段階ではディスクには何もインストールされていません(何らかの OS がインストール済みのディスクを使う場合は削除してください。詳しくはこちら)が、この後の作業で CoreOS をインストールします。CoreOS インストール後は CoreOS を起動する、という設定です。 そしてディスクに何もインストールされていない場合は PXE インストールを実施するためネットワークブートも可能になるよう(ディスクよりも低い優先順位で)設定しておく必要があります(下図はサンプル):
2024070924



また OCP 4.13.0 は今となっては推奨バージョンとはいえないと思いますが、のちの作業で 4.14.0 へアップグレードしたいので、そのために敢えて低めのバージョンで初期インストールします。



【(1)インターネット接続環境下で必要なインストールに必要なファイル群をダウンロード】
では(0)で決めた OCP 4.13.0 をエアギャップ環境でインストールするために必要なファイルを用意します。まずはインターネットに接続できる RHEL(RedHat Enterprise Linux) 9.x を用意します。ディスクの空きは 4.13.0 の初期インストールだけなら 50GB くらい、初期インストール後に実施する 4.14.0 へのアップグレードに必要なファイルまでを同じ環境でダウンロードするつもりであれば 100GB は必要です。このダウンロードを実施するための PC のメモリは 4GB 程度ないと厳しいかも、、そのつもりで環境を準備してください。

では早速必要なファイルのダウンロード・・・なんですが、1つだけ入手方法が他と異なる特殊なファイルがあるので、まずはこれから紹介します。RedHat でアカウントを作成し(個人アカウントでも構いません)、そのアカウントでログインして pull-secret と呼ばれるファイルをダウンロードします。pull-secret は「ダウンロード」と表現していますが、正確には「ログイン済みのユーザー向けに作成されたものをダウンロード」します(つまりログインユーザー毎に内容は異なるファイルです)。ログイン時の RedHat アカウントに紐づいた内容で利用できるものですが、個人アカウントでも開発者サブスクリプションに登録することで無料で利用できるものなので、必要であれば開発者サブスクリプションに登録してください。この辺りの登録手順は前回の内容を参照してください。 

pull-secret をダウンロードするには RedHat アカウント作成後にブラウザで https://cloud.redhat.com/openshift/install/pull-secret にアクセスします(ログイン前の場合はここでログインが必要です)。そして "Download pull secret" ボタンをクリックするとダウンロードが始まります:
2024070905


ダウンロードした pull-secret は "pull-secret" または "pull-secret.txt" というファイル名でダウンロードされます。ファイル名は後者("pull-secret.txt")だった場合は前者("pull-secret")にリネームしておいてください。以降は "pull-secret" という拡張子のないファイル名でダウンロード済みであると仮定して説明を続けます。

このダウンロードした pull-secret ファイル自体もエアギャップ環境に持ち込む必要があるのですが、この後のインターネット接続環境での作業でも必要なファイルです。同 "pull-secret" ファイルを "/root/.docker/config.json" というファイル名で保存します(~/Downloads/pull-secret というファイルとしてダウンロード済みの場合の例です):
# mkdir -p /root/.docker/

# cp ~/Downloads/pull-secret /root/.docker/config.json


次にファイルをダウンロードする準備として、この後の作業の中で必要になるツール類をあらかじめまとめてインストールする、という手順を実施します。具体的には root ユーザーの CLI で以下のコマンドを実行します:
# yum install jq wget git yum-utils podman ansible-core python3-cryptography -y

またダウンロードするファイルを保管するためのフォルダ(/data)を作成しておきます:
# mkdir -p /data

# cd /data

早速ダウンロードした pull-secret も /data にコピーしておきましょう:
# cp ~/Downloads/pull-secret /data


ここからが本格的な「ファイルダウンロード」作業となります。手順は決して短くはないのですが、最初は内容の理解が甘くても構いませんので、以下で紹介されている CLI コマンドを淡々と実行いただくことで済むものです。

ではエアギャップ環境に持ち込む必要があるファイルを順にダウンロードしていきます。まず最初は OCP4 ヘルパーノードを動かすために必要な ansible-galaxy のコレクションモジュールです。以下のコマンドを実行して、~/collections/ というフォルダに community.crypto と ansible-posix モジュールをダウンロードします(ここではインストールは不要で、ダウンロードのみ実行します):
# cd

# ansible-galaxy collection download community.crypto

# ansible-galaxy collection download ansible-posix

# ls -la ~/collections/

# cp -r ~/collections /data

コマンドが正しく実行されると ~/collections/ というフォルダが作られていて、その中に community-crypto-x.x.x.tar.gz と ansible-posix-x.x.x.tar.gz というファイルが存在しているはずです(x.x.x 部分はバージョン番号で、実行したタイミングによって異なります)。上記最後のコマンドでダウンロードしたモジュールを collections/ フォルダごと /data にコピーしています。

続いてこの後バスチョンサーバーで使うことになる OCP4 ヘルパーノード本体と、NFS プロビジョナーを github からダウンロードします:
# cd /data

# 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

これらのコマンドが正しく実行されると /data 以下に ocp4-helpernode.tgz と nfs-subdir.tgz という2つのファイルが作られます。

次はいよいよ OCP 4.13.0 の OS 部分である RHCOS(RedHat CoreOS) 4.13.0 本体となるファイル群を RedHat サイトからダウンロードします:
# mkdir -p /data/ocp-files

# cd /data/ocp-files

# wget https://mirror.openshift.com/pub/openshift-v4/x86_64/dependencies/rhcos/4.13/4.13.0/rhcos-live-rootfs.x86_64.img

# wget https://mirror.openshift.com/pub/openshift-v4/x86_64/dependencies/rhcos/4.13/4.13.0/rhcos-live-initramfs.x86_64.img

# wget https://mirror.openshift.com/pub/openshift-v4/x86_64/dependencies/rhcos/4.13/4.13.0/rhcos-live-kernel-x86_64

# wget https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/4.13.0/openshift-client-linux-4.13.0.tar.gz

# wget https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/4.13.0/openshift-install-linux-4.13.0.tar.gz

# wget https://get.helm.sh/helm-v3.13.3-linux-amd64.tar.gz

/data/ocp-files/ というフォルダを作成し、その中に6つの RHCOS 4.13.0 インストール用ファイルをダウンロードしました。


OS のイメージをダウンロードした後はいよいよ OCP 本体部分のダウンロードに移ります。次はバスチョンサーバー内に構築する OCP 4.13.0 のミラーレジストリとなるコンテナイメージをダウンロードします。この実体は docker.io から提供されているコンテナイメージなので、上記手順で実行した docker 互換の podman を使い、インターネット接続環境でこのイメージを docker pull (正確には podman pull)して、その結果を tar ファイル(/data/registry.tar)にエクスポートする形でファイルの形でダウンロードします:
# cd /data

# podman pull docker.io/library/registry

# podman save docker.io/library/registry:latest -o /data/registry.tar

そしてこのミラーレジストリに展開する(ミラーリングする)中身となるミラーイメージの準備です。まずはミラーリング実行時のコマンドとなる oc と oc-mirror をダウンロードします。まずは oc-mirror から(この後実際にミラーリングするので /data だけでなく /usr/local/bin にもコピーしています):
# mkdir -p ~/oc-mirror

# cd ~/oc-mirror

# wget https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/4.13.0/oc-mirror.tar.gz

# tar -xf oc-mirror.tar.gz

# chmod +x oc-mirror

# cp oc-mirror /data

# cp oc-mirror /usr/local/bin

同様に oc コマンドを用意します。ダウンロードする必要のあるファイルは上述でダウンロード済みの openshift-client-linux-4.13.0.tar.gz なので、ここから oc コマンドだけを取り出します:
# cd ~/oc-mirror

# tar xzvf /data/ocp-files/openshift-client-linux-4.13.0.tar.gz oc

# cp oc /data

# cp oc /usr/local/bin

ここからが本作業の中で一番のメインイベントとなるミラーイメージのダウンロードとなります。インターネット接続環境にも依存しますが、最も時間のかかるダウンロード作業で、ダウンロード結果となるファイルのサイズも巨大なもの(1ファイルで 30GB 近く)となるものです。

ミラーイメージダウンロードの準備として、以下の内容で /data/imageset-config-4.13.0.yaml を作成します。このファイルに記載されている内容に従ってミラーレジストリ作成に必要なファイルがダウンロードされるもので、OCP 4.13.0 を初期インストールするための内容になっています。なお同時に local-storage-operator というオペレーターもダウンロードしています。これは今回特に使うわけではないのですが、エアギャップ環境のミラーレジストリでも OperatorHub を有効にできていることを確認する目的で指定しています(今回の OCP 4.13.0 のインストールが完了すると、Local Storage Operator だけが OperatorHub に表示されるようになります)。OCP インストール後に利用することが決まっているオペレーターがある場合はこの imageset-config-4.13.0.yaml ファイル内に記載して、一緒にダウンロードするようにしてください:
kind: ImageSetConfiguration
apiVersion: mirror.openshift.io/v1alpha2
storageConfig:
  local:
    path: /data/mirror-ocp
mirror:
  platform:
#    architectures:
#      - "x86_64"
    channels:
    - name: stable-4.13
      type: ocp
      minVersion: '4.13.0'
      maxVersion: '4.13.0'
    graph: true
  operators:
  - catalog: registry.redhat.io/redhat/redhat-operator-index:v4.13
    full: false
    packages:
    - name: local-storage-operator
      channels:
      - name: stable
  additionalImages:
  - name: registry.redhat.io/ubi8/ubi:latest
  - name: gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.2
  - name: docker.io/rancher/busybox:1.31.1
  helm: {}

上記ファイル内の赤字部分についてコメントしておきます。まず storageConfig.localpath = /data/mirror-ocp という部分でファイルのダウンロード先フォルダを指定しています。 次に mirror.platform.channels で "4.13 の安定板(stable-4.13)" を使うことを明記し、そのバージョンとして 4.13.0 から 4.13.0 まで(つまり 4.13.0)を対象にダウンロードすることを指定しています。 そして mirror.operators 内で local-storage-operator:stable オペレーターを一緒にダウンロードする旨を記載しています。必要に応じて適宜変更してください。

ではこのファイルを使ってミラーイメージを一括ダウンロードします。上述の pull-secret(~/.docker/config.json)がないとダウンロードは失敗するので注意してください:
# umask 0022

# mkdir -p /data/mirror-ocp

# cd /data

# oc mirror --config=imageset-config-4.13.0.yaml file:///data/mirror-ocp

最後のコマンドを実行すると(正しく実行されると)ファイルのダウンロードが開始されます。ここはかなり時間のかかる作業なので、ずっとこの環境のターミナルを開けない環境などの場合は tmux などでバックグラウンド実行することを推奨します。

コマンドが最後まで正しく実行されると /data/mirror-ocp/mirror_seq1_000000.tar という 30GB 前後の巨大なファイルが作られます。これがミラーイメージと呼ばれるもので、この後エアギャップ環境のミラーレジストリを作る際の中身に相当するものです。


インターネット接続環境を使って最低限ダウンロードしておくべきファイルは以上です。以下はエアギャップ環境によっては必要となるファイルであったり、事前にインターネット接続環境下で(というか、エアギャップ環境では使えるエディタも限られてしまうので、普段使っているテキストエディタが使える環境のうちに使って)用意しておくと便利なファイルです。

この後のエアギャップ環境下では主にバスチョンサーバーと呼ばれる作業マシン内に必要な環境を構築していくことになります。その際に RHEL の(yum/dnf コマンドを実行してパッケージをインストールする際の)パッケージリポジトリが必要になります。 RHEL の DVD(ISO) メディアを用意し、その DVD(ISO) を RHEL に挿入して作業することができる環境の場合はその方法でパッケージリポジトリを構築できるのでいいのですが、例えばバスチョンサーバーが物理サーバーで、かつ DVD ドライブを内蔵していないようなケースだったりすると DVD を挿入するだけでパッケージリポジトリを用意することができなくなります。そのような場合は RHEL ISO ファイルそのものをエアギャップ環境に持ち込む必要があります(サイズの小さい Boot DVD ではなく、フル DVD の ISO が必要です)。以下のサイトから RHEL DVD の ISO ファイル(例えば rhel-9.2-x86_64-dvd.iso)を事前にダウンロードして、/data フォルダに保存しておきます。なおここでもダウンロード時に RedHat アカウントでログインする必要があります:
https://developers.redhat.com/products/rhel/download


またこの ISO を使ってパッケージリポジトリを構築する場合は、以下の内容のリポジトリ構築用の設定ファイル(/data/isorepo.repo)が必要です。エアギャップ環境での作業になるとテキストエディタも自由には選べなくなるので、インターネット接続が使えるうちに設定ファイル類を作っておくことをお勧めします:
[iso-BaseOS]
name=DVD for RHEL - BaseOS
baseurl=file:///media/rheliso/BaseOS
enabled=1
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

[iso-AppStream]
name=DVD for RHEL - AppStream
baseurl=file:///media/rheliso/AppStream
enabled=1
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release

このような設定ファイルがいくつか必要なので、インターネット接続環境で作れる範囲で作ってしまうことにします。というわけで次は OCP4 ヘルパーノードを使う際のパラメータファイルである /data/vars.yaml を以下の内容で作っておきます:
---
disk: sda
helper:
  name: "bastion"
  ipaddr: "10.10.0.10"
  networkifacename: "enp0s3"
dns:
  domain: "xxx.localdomain"
  clusterid: "ocp"
#  forwarder1: "8.8.8.8"
#  forwarder2: "8.8.4.4"
dhcp:
  router: "10.10.0.10"
  bcast: "10.10.0.255"
  netmask: "255.255.255.0"
  poolstart: "10.10.0.30"
  poolend: "10.10.0.39"
  ipid: "10.10.0.0"
  netmaskid: "255.255.255.0"
chronyconfig:
  enabled: true
  content:
    - server: 10.10.0.10
      options: iburst
bootstrap:
  name: "bootstrap"
  ipaddr: "10.10.0.32"
  macaddr: ""
masters:
  - name: "master0"
    ipaddr: "10.10.0.33"
    macaddr: ""
  - name: "master1"
    ipaddr: "10.10.0.34"
    macaddr: ""
  - name: "master2"
    ipaddr: "10.10.0.35"
    macaddr: ""
workers:
  - name: "worker0"
    ipaddr: "10.10.0.36"
    macaddr: ""
  - name: "worker1"
    ipaddr: "10.10.0.37"
    macaddr: ""
  - name: "worker2"
    ipaddr: "10.10.0.38"
    macaddr: ""
setup_registry:
  deploy: true
  autosync_registry: false
  registry_image: "docker.io/registry:latest"
  local_repo: "ocp4/openshift4"
  product_repo: "openshift-release-dev"
  release_name: "ocp-release"
  release_tag: "4.13.0-x86_64"
ppc64le: false
ocp_bios: "file:///data/ocp-files/rhcos-live-rootfs.x86_64.img"
ocp_initramfs: "file:///data/ocp-files/rhcos-live-initramfs.x86_64.img"
ocp_install_kernel: "file:///data/ocp-files/rhcos-live-kernel-x86_64"
ocp_client: "file:///data/ocp-files/openshift-client-linux-4.13.0.tar.gz"
ocp_installer: "file:///data/ocp-files/openshift-install-linux-4.13.0.tar.gz"
helm_source: "file:///data/ocp-files/helm-v3.13.3-linux-amd64.tar.gz"

ここでも赤字部分についてコメントしておきます。まず2行目に disk = "sda" という記載をしていますが、これは「OCP をインストールする環境ではディスクは /dev/sda として認識されている」ことを示しています。とりあえずこの値を設定していますが、実際の環境はエアギャップ環境内のバスチョンサーバーなどで確認いただきたいのですが、異なる場合はここを編集してください。また6行目で helper.networkifname = "enp0s3" と記載しています。これはバスチョンサーバーのネットワークインターフェース名("ip a" や "ifconfig" コマンドで確認できるインターフェース名)が "enp0s3" であることを意味しています。この値も実際のものと異なる場合は編集してください。 もう1つ、今回は OCP を構築するドメインを "ocp.xxx.localdomain" とする、と書きましたが、このファイルでは dns.domain と dns.clusterip に分けてドメインを設定している点に注意してください(2つを足して <dns.clusterid>.<dns.domain> で実際に利用するドメイン名になるよう指定してください)。


次に数か所で IP アドレスを指定していますが、各ノードサーバーの想定 IP アドレスに加えて、DHCP サーバーや chronyd サーバー(時刻同期サーバー)の IP アドレスも指定しています。今回は OCP4 ヘルパーノードを使って周辺環境を構築するので、DHCP, DNS などは全てバスチョンサーバーと同じ IP アドレスを指定する必要がある点に注意ください。また macaddr が空文字列になっている行が多いですが、これらには各ノードサーバーのネットワークインターフェースが持つ MAC アドレスを指定することになります。各サーバーの MAC アドレスの値を調べて、"xx:xx:xx:xx:xx:xx" 形式で入力する必要があるのですが、今の時点では(まだ使わないので)空文字列にしていても大丈夫です。

ただこの vars.yaml ファイルはとても大事なファイルです。この中で指定する IP アドレスや MAC アドレスが(ちょっとしたミスで間違えやすいものですが)1箇所でも間違えているとうまくインストールできなくなってしまうものなので、注意して入力するよう心掛けてください。


続いて、時刻同期サーバーである chronyd の設定ファイル(/data/chrony.conf)を以下の内容で用意します(10.10.0.0/24 のアドレスからのみリクエストを受け付ける設定をしています):
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
allow 10.10.0.0/24
local stratum 8
keyfile /etc/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony

もう1つ、OCP インストール時の設定ファイル(install-config.yaml)を生成するシェルスクリプト(/data/install-config.sh)を以下の内容で用意します:
# cat < install-config.yaml
apiVersion: v1
baseDomain: xxx.localdomain
compute:
- hyperthreading: Enabled
  name: worker
  replicas: 3
controlPlane:
  hyperthreading: Enabled
  name: master
  replicas: 3
metadata:
  name: ocp
networking:
  clusterNetwork:
  - cidr: 10.254.0.0/16
    hostPrefix: 24
  machineNetwork:
  - cidr: 10.10.0.0/24
  networkType: OpenShiftSDN
  serviceNetwork:
  - 172.30.0.0/16
platform:
  none: {}
pullSecret: '$(< ~/.openshift/pull-secret-updated)'
sshKey: '$(< ~/.ssh/helper_rsa.pub)'
additionalTrustBundle: |
$(sed 's/^/  /' /opt/registry/certs/domain.crt)
imageContentSources:
- mirrors:
  - registry.ocp.xxx.localdomain:5000/openshift/release-images
  source: quay.io/openshift-release-dev/ocp-release
- mirrors:
  - registry.ocp.xxx.localdomain:5000/openshift/release
  source: quay.io/openshift-release-dev/ocp-v4.0-art-dev
EOF

上述の vars.yaml 同様、このファイルでも <metadata.name>.<baseDomain> で実際のドメイン名になるよう記載する点に注意が必要です。またこのファイルの中でマスターノードが3つ、ワーカーノードが3つそれぞれ必要になることが記載されている点にも注意してください(OCP が正しくインストールされているかどうかは、ここで指定した値の数だけノードが用意できているかどうかで判断されます)。


ここまでの作業を行うと、/data 以下に以下のファイル/フォルダができているはずです:
  (以下は必須のファイル/フォルダ)
- /data/pull-secret
- /data/collections/
- /data/ocp4-helpernode.tgz
- /data/nfs-subdir.tgz
- /data/ocp-files/
- /data/registry.tar
- /data/oc-mirror
- /data/oc
- /data/mirror-ocp/mirror_seq1_000000.tar

(以下は必須ではないが、バスチョンサーバーに RHEL DVD をセットする術がない場合に必須)
- /data/rhel-9.2-x86_64-dvd.iso
- /data/isorepo.repo

(以下は必須ではないが、使い慣れたテキストエディタで作っておくべきもの)
- /data/vars.yaml
- /data/chrony.conf
- /data/install-config.sh

上記ファイルを全て(フォルダはフォルダまるごと) USB メモリなどに入れて、この後の作業となるバスチョンサーバーにコピーする必要があります。方法は USB メモリ以外に USB ディスクでも構いません。作業用の PC を持ち込むのであれば、その作業 PC の中に入れて持ち込むのも一つの方法です。1ファイルで 30GB 近くあるものも含まれているので1枚の DVD では無理ですが、ファイルを分割すれば複数枚の DVD で持ち運ぶことはできると思います。 方法はともかく、これらのファイルをなんらかの方法でインターネット接続のないバスチョンサーバーが利用できる状態にする必要があります。場合によってはここがエアギャップ OCP 環境構築の最初の関門になると思います。

ここまでの手順ができればインターネット接続のある環境で行う作業は以上です。ここまでで既にかなり長い説明になっていますが、本番はここから。次からはいよいよインターネット接続がない環境下で実施する作業に入ります。


【(2)OCP を PXE インストール】
ここから先は全てインターネット接続のない環境で実施することになります。これまでにインターネット接続環境で用意したファイルを使って OCP 4.13.0 をインストールします。

ここで構築する OCP は以下のようなサーバー群から構成されます:
2024070906


このうち、バスチョンサーバー以外のノードは PXE インストールと呼ばれるネットワークインストールで導入します。つまり「ほぼ電源を入れるだけ」の作業です。 OCP をインストールするための作業という意味ではその大半が「バスチョンサーバーを構築する作業」となります。

ではエアギャップ環境でバスチョンサーバーを構築する手順を紹介します。まず前提としてエアギャップ環境内に RHEL がインストールされたサーバーを1台用意します(エアギャップ環境内で RedHat のサブスクリプションを有効にする手順等はこちらを参照してください)。またバスチョンサーバーは SELinux が無効になっていると OCP4 ヘルパーノード実行時にエラーとなってしまうので、SELinux はデフォルトの permissive や enforcing にするなどして無効以外の設定にしてください:
2024070925


加えてバスチョンサーバーにインストールする RHEL は("Minimum Install" ではなく)"Server with GUI" オプションでインストールしておくことを推奨します。理由はインストールされた OCP のウェブコンソール画面にアクセスする際、このバスチョンサーバーのウェブブラウザからアクセスするしかない可能性があるためです。他の作業用 Windows PC などがある環境であれば、その Windows からウェブアクセスすることも可能ですが、そのような作業マシンがない場合は全てバスチョンサーバーを使って設定する必要があり、ウェブアクセスが必要な場合もバスチョンサーバーのウェブブラウザを使う必要に迫られる可能性があるからでした(以下はバスチョンサーバーが "Server with GUI" でインストールされている前提で説明します)。

そして上述の【1】でダウンロードしたファイル群はバスチョンサーバーの /data/ 以下にコピーされているものと仮定して以下の説明を続けます。つまりバスチョンサーバーにも以下のファイルが存在しているものと仮定して以下を続けます:
  (以下は必須のファイル/フォルダ)
- /data/pull-secret
- /data/collections/
- /data/ocp4-helpernode.tgz
- /data/nfs-subdir.tgz
- /data/ocp-files/
- /data/registry.tar
- /data/oc-mirror
- /data/oc
- /data/mirror-ocp/mirror_seq1_000000.tar

(以下は必須ではないが、バスチョンサーバーに RHEL DVD をセットする術がない場合に必須)
- /data/rhel-9.2-x86_64-dvd.iso
- /data/isorepo.repo

(以下は必須ではないが、使い慣れたテキストエディタで作っておくべきもの)
- /data/vars.yaml
- /data/chrony.conf
- /data/install-config.sh

またブートストラップノードや各マスターノード/ワーカーノードのサーバーに付属している NIC の MAC アドレスも必要です。MAC アドレスの値は仮想サーバーなどであれば比較的簡単に調べることができますが、物理サーバーだと最悪の場合、実際に OS が動いている状態でないと調べる方法がない可能性もあります。このあたりの OS をインストールしなくても調べる具体的な手順はこちらでも紹介しているので参考にしてください。


改めてここからはエアギャップ環境(インターネット接続のない環境)下での、バスチョンサーバーと呼ばれる作業サーバーの準備手順を紹介します。以下のコマンドは全て root ユーザー権限で実行してください(sudo 権限のある一般ユーザーからは "sudo -i" を実行して root ユーザー権限でターミナルを準備してください)。

事前に確認する情報としてもう1点、これ以降の説明では /usr/local/bin フォルダに実行 PATH が設定されている必要があります。もし設定されていない場合は ~/.bashrc の最後に以下の1行を追加して再ログインしてください:
export PATH="$PATH:/usr/local/bin"

まずは対象サーバーにインストールした RHEL を起動します。この際に DVD ドライブに RHEL DVD を入れることができる場合は挿入しておきます(これで DVD のローカルリポジトリからパッケージがインストールできるようになります)。その様な環境ではない場合は、上述の手順で rhel-9.2-x86_64-dvd.iso と isorepo.repo ファイルをエアギャップ環境の /data フォルダ以下にコピーしているので、これらを使ってローカルリポジトリを作る作業が必要になります。 ISO ファイルを使ってローカルリポジトリを作成する場合は事前に用意した /data/isorepo.repo ファイルを併用して作成します。その場合、まずは /media/rheliso という空のフォルダを作成します:
# mkdir -p /media/rheliso

このフォルダに ISO ファイルをマウントします。一時的なマウントではなく恒久的にマウントしたいので、/etc/fstab ファイルに以下の1行を追加してバスチョンサーバーを再起動します(再起動後に /media/rheliso に DVD がマウントされているはずです):
/data/rhel-9.2-x86_64-dvd.iso  /media/rheliso  iso9660  loop,ro,auto,nofail  0  0

マウントされた DVD(ISO) を使ってローカルリポジトリを作成します。/data/isorepo.repo ファイルを /etc/yum.repos.d/ にコピーします。加えてサブスクリプションを無効にしてデフォルトのリポジトリが自動的に復元されないようにします。最後にデフォルトのリポジトリファイルを削除してからリポジトリを更新します(これでローカルリポジトリが作成され、使える状態になります):

# cp /data/isorepo.repo /etc/yum.repos.d/

# subscription-manager config --rhsm.manage_repos=0

# rm -f /etc/yum.repos.d/redhat*.repo

# yum clean all

# yum list

ローカルリポジトリが利用可能な状態になったので、ここからこの後の作業に必要なパッケージ類をインストールしていきます。以下のコマンドを実行して、ローカルリポジトリからまとめてインストールします:
# yum install -y tmux jq wget git tree yum-utils bind-utils nmstate podman python3-cryptography ansible-core

上のコマンドで ansible 系のコマンドもインストールしているので、インターネット接続環境でダウンロードした ansible collection コマンドが使えるようになります。以下のコマンドで2つのパッケージをインストールします(x.x 部分は実際にダウンロードしたファイルバージョンに合わせて指定して下さい):
# cd /data/collections/

# ansible-galaxy collection install community-crypto-2.x.x.tar.gz

# ansible-galaxy collection install ansible-posix-1.x.x.tar.gz

次にネットワークインターフェースを設定します(ネットワーク設定が済んでいる場合、ここは飛ばしてください)。まずはネットワークインターフェース名を確認するため、以下のコマンドを実行します:
# ip a

コマンドの結果、"lo" のインターフェースに関する情報と、それとは別のインターフェースに関する情報が表示されます。"lo" はローカルホスト用の設定なのでこちらではなく、もう1つのインターフェースに関する情報は実際の通信に使うインターフェースです。この後、そのインターフェース名を使って設定を行うので、インターフェース名を見つけてください。以下の例では "enp0s3" が求めるインターフェース名で、以下この前提でコマンドを実行していきますが、実際に入力するコマンドは自分の環境でのインターフェース名に合わせて変更してください:
2024070907


今回の前提ではバスチョンサーバーは IP アドレスは "10.10.0.10/24" 、FQDN は "bastion.ocp.xxx.localdomain" として構築するので、そのための設定変更を行います。なおデフォルトゲートウェイが存在する環境の場合はそのアドレスを指定する必要がありますが、特にない環境の場合は自分自身のアドレス(10.10.0.10)を指定します。また DNS はこの後 OCP4 ヘルパーノードが作る環境をそのまま使うので、ここは自分自身のアドレス(10.10.0.10)を指定します:
# nmcli con mod enp0s3 connection.autoconnect yes

# nmcli con mod enp0s3 ipv4.addresses 10.10.0.10/24

# nmcli con mod enp0s3 ipv4.method manual

# nmcli con mod enp0s3 ipv4.gateway 10.10.0.10

# nmcli con mod enp0s3 ipv4.dns 10.10.0.10

# hostnamectl set-hostname bastion.ocp.xxx.localdomain

また、このバスチョンサーバーは "registry.ocp.xxx.localdomain" という名前でもアクセスすることができるようにしておきます。そこで /etc/hosts ファイルを編集し、以下の1行を追加して保存します:
10.10.0.10  registry.ocp.xxx.localdomain

ネットワークの設定ができたら、次はミラーレジストリを作ります。ミラーレジストリとなるコンテナイメージを podman(docker)に展開して、空のミラーレジストリを作成しておきます:
# podman load -i /data/registry.tar


ミラーレジストリの中身をロードするにはいくつかのコマンドを用意する必要があるので、その辺りも含めて OCP4 ヘルパーノードの準備を先にしておきます。あらかじめダウンロードした tgz ファイルをホームディレクトリに展開し、更にあらかじめ用意しておいた設定ファイル(/data/vars.yaml)を上書きします:
# cd

# tar xzvf /data/ocp4-helpernode.tgz

# cd ocp4-helpernode/

# cp /data/vars.yaml .

OCP4 ヘルパーノードを実行する前に改めて ~/ocp4-helpernode/vars.yaml ファイルの中身を実際の環境に合わせた正しい情報に更新してください。赤字部分はコメントです。実際の環境に合わせて正しく変更してください(ここが間違っていると PXE インストールが正しく実行されなかったり、正しく導入完了を検知できなかったりします。特に MAC アドレスに注意):
---
disk: sda                        # ディスクデバイス名
helper:
  name: "bastion"                # バスチョンサーバーのホスト名
  ipaddr: "10.10.0.10"           # バスチョンサーバーの IP アドレス
  networkifacename: "enp0s3"     # ネットワークインターフェース名
dns:
  domain: "xxx.localdomain"      # clusterid.domain でドメイン名となるようにする
  clusterid: "ocp"
#  forwarder1: "8.8.8.8"         # 外部DNSを使う場合はここで指定(使わない場合はコメントアウト)
#  forwarder2: "8.8.4.4"
dhcp:
  router: "10.10.0.10"           # DHCP サーバーが設定するデフォルトゲートウェイ
  bcast: "10.10.0.255"           # DHCP サーバーが設定するブロードキャストアドレス
  netmask: "255.255.255.0"       # DHCP サーバーが設定するネットマスク
  poolstart: "10.10.0.30"        # DHCP サーバーが予約する IP アドレスの開始アドレス
  poolend: "10.10.0.39"          # DPCP サーバーが予約する IP アドレスの終了アドレス
  ipid: "10.10.0.0"
  netmaskid: "255.255.255.0"
chronyconfig:
  enabled: true
  content:
    - server: 10.10.0.10         # バスチョンサーバーの IP アドレス
      options: iburst
bootstrap:
  name: "bootstrap"              # ブートストラップノードのホスト名
  ipaddr: "10.10.0.32"           # ブートストラップノードの IP アドレス
  macaddr: "xx:xx:xx:xx:xx:xx"   # ブートストラップノードの MAC アドレス
masters:
  - name: "master0"              # master0 ノードのホスト名
    ipaddr: "10.10.0.33"         # master0 ノードの IP アドレス
    macaddr: "xx:xx:xx:xx:xx:xx" # master0 ノードの MAC アドレス(以下同様)
  - name: "master1"              # master1 ノード
    ipaddr: "10.10.0.34"
    macaddr: "xx:xx:xx:xx:xx:xx"
  - name: "master2"              # master2 ノード
    ipaddr: "10.10.0.35"
    macaddr: "xx:xx:xx:xx:xx:xx"
workers:
  - name: "worker0"              # worker0 ノード
    ipaddr: "10.10.0.36"
    macaddr: "xx:xx:xx:xx:xx:xx"
  - name: "worker1"              # worker1 ノード
    ipaddr: "10.10.0.37"
    macaddr: "xx:xx:xx:xx:xx:xx"
  - name: "worker2"              # worker2 ノード
    ipaddr: "10.10.0.38"
    macaddr: "xx:xx:xx:xx:xx:xx"
setup_registry:                  # ローカルリポジトリに関する情報(このまま使ってください)
  deploy: true
  autosync_registry: false
  registry_image: "docker.io/registry:latest"
  local_repo: "ocp4/openshift4"
  product_repo: "openshift-release-dev"
  release_name: "ocp-release"
  release_tag: "4.13.0-x86_64"
ppc64le: false                   # 以下 CoreOS や OC CLI に関する情報(このまま使ってください)
ocp_bios: "file:///data/ocp-files/rhcos-live-rootfs.x86_64.img"
ocp_initramfs: "file:///data/ocp-files/rhcos-live-initramfs.x86_64.img"
ocp_install_kernel: "file:///data/ocp-files/rhcos-live-kernel-x86_64"
ocp_client: "file:///data/ocp-files/openshift-client-linux-4.13.0.tar.gz"
ocp_installer: "file:///data/ocp-files/openshift-install-linux-4.13.0.tar.gz"
helm_source: "file:///data/ocp-files/helm-v3.13.3-linux-amd64.tar.gz"

OCP4 ヘルパーノードを実行するには(エアギャップ環境ではあるのですが) pull-secret に関する情報が必要です。以下の手順でダミーの pull-secret を作っておきます:
# cd

# mkdir -p ./.openshift

# echo "{}" > ./.openshift/pull-secret

このまま次の処理を続けてもいいはずなんですが、私が実際に試した環境だとここで一度サーバーを再起動しないといけないことがありました。自分でもどちらが正解か自信がないのですが、このまま続けて次の ansible-playbook コマンドが失敗する場合はバスチョンサーバーを再起動してください。

~/ocp4-helpernode/vars.yaml ファイルの準備ができたら OCP4 ヘルパーノードを実行します。コマンドは ansible playbook として用意されているので(その変数部分が vars.yaml に集約されているので)以下のコマンドを実行します。成功すると DNS や DHCP、TFTP、HAPROXY など、この後の PXE インストール時に必要な周辺環境に加え、oc コマンドの準備や ssh で利用する鍵の準備などもまとめて構築してくれます(完了まで数分から数十分かかります)。OCP4 ヘルパーノードを使わない場合、1つ1つこれらの環境を用意する必要があることを考えると、とても便利です:
# cd ~/ocp4-helpernode

# ansible-playbook -e @vars.yaml tasks/main.yml

ここまでできていれば事前環境準備はほぼミラーレジストリの中身をインストールイメージ(今回の例だと OCP 4.13.0 インストール用のイメージ)にするだけなんですが、NTP(時刻同期サーバー)については少し手を加える必要があります。といっても事前に用意した /data/chrony.conf で /etc/chrony.conf を更新して起動するだけです:
# cp /data/chrony.conf /etc/chrony.conf

# firewall-cmd --add-service=ntp --permanent

# firewall-cmd --reload

# systemctl enable chronyd

# systemctl start chronyd

このタイミングで OCP インストール時用の設定ファイル(install-config.yaml)を作っておくことにします。これも事前に用意した /data/install-config.sh を実行することで install-config.yaml ファイルを作ります。 なお、/data/install-config.sh を実行する際には ~/.openshift/pull-secret, ~/.ssh/helper_rsa.pub, /opt/registry/certs/domain.crt の3つのファイルが存在している必要がありますが、ここまでのコマンドが成功していれば全て作成されているはずです。

では install-config.yaml ファイルを作成します:
# cd 

# cp /data/install-config.sh .

# chmod +x ./install-config.sh

# ./install-config.sh

正しく実行されるとカレントディレクトリに install-config.yaml というファイルが生成されています。このファイルは OCP インストール時に利用します(後で使います)。


いよいよ、このバスチョンサーバー構築時におけるメイン作業ともいえる(OCP 4.13.0 用の)ミラーレジストリの構築を行います。構築時の中身となるイメージは /data/mirror_seq1_000000.tar ファイルとして用意されているので、これをレジストリにインポートすればよいのですが、そのためにはもともと用意していた pull-secret と、今回のミラーレジストリにアクセスするための鍵情報をミックスした鍵ファイルを用意する必要があります。順に行っていきます。

まずはインターネット接続環境でダウンロードした pull-secret ファイル(/data/pull-secret)を JSON 変換したものを /data/config.json というファイルで書き出しておきます:
# cd 

# cat /data/pull-secret | jq > /data/config.json

次に(ansible-playbook 実行時に作成された)~/.openshift/pull-secret-update というファイルを "# cat ~/.openshift/pull-secret-update" などで表示します(赤枠部分をこの後使います):
2024070908


そして /data/config.json をテキストエディタで開きます。以下のような内容が表示されます:
2024070909


この2行目と3行目の間に先ほど確認した ~/.openshift/pull-secret-update ファイルの赤枠部分をコピー&ペーストなどで挿入し、最後に ","(カンマ)を入力して保存します:
2024070910


こうして出来上がった /data/config.json を ~/.docker/config.json としてコピーします。これでミラーレジストリイメージをインポートする際に必要な鍵ファイルの準備ができました:
# cd 

# mkdir -p .docker

# cp /data/config.json .docker/

そしてミラーレジストリのインポート実行時に必要な oc-mirror バイナリを /data/oc-mirror から /usr/local/bin にコピーします:
# cp /data/oc-mirror /usr/local/bin

ここまでに準備した環境を使って(OCP 4.13.0 用の)ミラーイメージをミラーレジストリにインポートします(上述の ansible-playbook を実行した時と比較しても、終了まで更に長い時間がかかるコマンドです):
# cd

# oc mirror --from=/data/mirror_seq1_000000.tar docker://registry.ocp.xxx.localdomain:5000

正常に終了していると ~/oc-mirror-workspace/ というフォルダが作られ、その中に results-xxxxxxxxxx といった名称のフォルダが作られているはずです(このフォルダはインストール後の調整時に使います):
2024070911


以下のコマンドを使ってミラーレジストリが正しくインポートされ、動作していることを確認します(例のように "4.13.0-" で始まるタグ行がたくさん表示されることが確認できれば成功です):
# podman image search --list-tags registry.ocp.xxx.localdomain:5000/openshift/release

2024070912


ここまでできればバスチョンサーバーとしての準備は完了です(OCP インストールの大きな山を1つ越えた、くらいに考えてください)。後は実際に OCP をインストールする際の PXE インストール用のファイルを準備する必要がありますが、周辺環境の準備は完了した、くらいに理解していただいて大丈夫です。

PXE インストール用に用意するファイルの中にはイグニッションファイルと呼ばれるものが含まれます。これは CoreOS インストール時に必要な鍵ファイルですが、有効期限は 24 時間です。つまりここから先の手順であるイグニッションファイルの作成から OCP インストール完了までを 24 時間以内に行う必要があります。よほど貧弱な仮想環境とかでない限りは 24 時間以内に終わるのが普通の処理内容ではあるのですが、24 時間を超えてしまうとイグニッションファイルが無効になってしまうので、実行タイミングは気を付けてください(日をまたぐ可能性があるタイミングでの実行はやめたほうがいいです)。

というわけで PXE インストール用のファイルを用意します。まずは先程作成した ~/install-config.yaml ファイルと OCP4 ヘルパーノードが用意してくれた openshift-install コマンドを使ってマニフェストファイルを作成します:
# cd

# mkdir config

# cp install-config.yaml config/

# openshift-install --dir=config create manifests

このコマンドの結果、~/config/ フォルダが作られ、その中に各種マニフェストファイルが作成されるのですが、一部は OCP4 ヘルパーノードが用意したものを使う必要があります:
# cd

# cp ocp4-helpernode/machineconfig/* ./config/openshift/

ここまで用意したマニフェストファイルを使ってイグニッションファイルを作成します。繰り返しますが、ここから先 OCP のインストール完了まで 24 時間以内に実施する必要があることに注意してください:
# cd

# openshift-install --dir=config create ignition-configs

成功すると config フォルダ直下に拡張子が .ign となっているイグニッションファイルが生成されています。これを PXE インストール時に HTTP 経由で取り出せるよう、ドキュメントルートにコピーします:
# cd

# cp config/*.ign /var/www/html/ignition/

# restorecon -vR /var/www/html/

# chmod o+r /var/www/html/ignition/*.ign

これで PXE インストール実行時に必要なイグニッションファイルも用意できました。最後に PXE シーケンスの最初にファイルをダウンロードさせるための TFTP サーバーを設定します:
# firewall-cmd --permanent --add-service=tftp

# firewall-cmd --reload

# systemctl daemon-reload

# systemctl restart tftp.service

# systemctl enable tftp.service

# chown nobody:nobody /var/lib/tftpboot

これで PXE インストール前にバスチョンサーバー上で実行しておく必要のある準備は全て完了しました。

後は各ノードサーバーの電源を順次入れていきます。実際のところ、どのような順に電源を入れても構わないのですが、OCP としては以下の順に起動していくので、この順序で電源を入れていくのがいいと思われます:
・ブートストラップノード
・マスターノード
・ワーカーノード


各ノードとも PXE ブートが実行され、バスチョンサーバーに用意された環境から CoreOS をダウンロードしてインストールし、OCP を構成するサーバーとして自分自身を作り上げてゆきます。PXE ブート、慣れないとうまく行っているのかどうかもわかりにくいと思いますが、成功していると以下のような "PXE" とか "iPXE" といった文字列が表示され、RHCOS がネットワーク経由でダウンロード/インストールされていく様子が確認できます(画面は機種によって少し変わると思います。しばらく待ってもこうならない場合は何かミスってる可能性大です):
2024070926


各ノードとも以下のような "Red Hat Enterprise Linux CoreOS" で始まる以下のような画面になっていれば、用意したイグニッションファイルが適用されて、少なくとも CoreOS のインストールまでは完了していると思ってください(OCP としてはまだインストール中の可能性があります):
2024070913


なお、私の手元の環境だとブートストラップノードの画面に(以下図のように)赤字で Unable to pull OpenShift release image と表示されて、OCP インストールが先に進まなくなってしまうことが度々ありました:
2024070914


この場合はバスチョンサーバー上で
# systemctl restart local-registry

を実行すると、数秒後にブートストラップノード上の赤い文字も消え、インストールが先に進むようになりました。もし同じ現象を確認された方がいたら試してみてください。


ここからは基本的には「OCP インストール完了を待つ」作業になります。ただ OCP インストール完了前からでも、下で紹介するような一部の OCP 関連コマンドが実行できるようになるので、インストール状況を確認する意味でも試してみてください。

まずマスターノードの OCP 導入状況を確認するには openshift-install コマンドに "wait-for bootstrap-complete" オプションを付けて実行します(ついでにログレベルも debug にして、より詳細な情報を表示するようにします)。約30分間にわたり、マスターノードのインストール状況が進んでいく様子を確認できます(マスターノードは数度リブートを繰り返しながら CoreOS と OCP のインストールが進んでいきます。環境次第ですが早ければ 30 分程度あればマスターノードのインストールは完了します。このコマンドは途中で Ctrl+C で終了して、再度同じコマンドを実行することで再度インストール状況の続きを見ることができます):
# openshift-install --dir=config --log-level=debug wait-for bootstrap-complete

2024072701


以下のように "Bootstrap status: complete" と表示されればマスターノードの導入は成功しています(続けてワーカーノードの導入が進んでいます):
2024072702


また全てのマスターノードの導入が上記のように完了していると一部の oc コマンドが使えるようになります。oc コマンドを実行するには以下のようにバスチョンサーバー上で環境変数 KUBECONFIG を設定し、コマンド("oc get nodes")を実行してみます:
# export KUBECONFIG=/root/config/auth/kubeconfig

# oc get nodes

oc コマンドが使える状態になっていれば、現在までに OCP が認識しているマスターノードの一覧が表示されるはずです(この時点ではワーカーノードは表示されません)。まずは3つ全てのマスターノードが Ready のステータスで表示されるようになるのを待ちましょう:
2024072703


3つのマスターノードが全て Ready になるとワーカーノードの導入が開始されます。ただワーカーノードは自動的に "oc get nodes" で表示されるようにはならず、手動で CSR を承認する必要があります。

まずは承認が必要な状態になっているものがあるかどうかを以下のコマンドで確認します(CSR の一覧を表示し、その中に承認待ち(Pending)ステータスになっているものがあれば表示する、というコマンドです):
# oc get csr | grep Pending

このコマンドの結果、承認待ちステータスになっている CSRが存在していると以下のような画面になります(マスターノードが全て準備できてから、この状態になるまで数十分~数時間かかります):
2024070915


その場合は以下のコマンドを実行して、承認待ちの CSR をまとめて承認します:
# oc get csr -o go-template='{{range .items}}{{if not .status}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}' | xargs oc adm certificate approve

2024070916


この「承認待ち CSR があるか?」と「あったらまとめて承認する」を何度か繰り返し、数分待っても承認待ち CSR が新たに追加されなくなる状態を待ちます。本当に全ての CSR が承認されていればワーカーノードも順次 OCP に組み込まれてゆき、"oc get nodes" コマンドの結果に表示されるようになります。全てのマスターノードと全てのワーカーノードが "oc get nodes" コマンドの結果として、ステータスが Ready の状態で表示されるようになることを確認します:
2024072704


ここまで完了すれば「ゴールまであとちょっと」です。最後に OCP としての基本機能(認証とかウェブコンソールとか・・)を提供するクラスターオペレーターが全て Ready な状態になることを確認します。確認コマンドは以下で、その結果全ての行でエラーメッセージや警告メッセージが表示されず、AVAILABLE=True なステータスになる状態を待ちます(つまり待つだけです):
# oc get clusteroperators

2024072705


クラスターオペレーターが全て有効な状態になったことが確認できれば OCP のインストールは完了したことになります。確認のため、ウェブブラウザからウェブコンソール画面にアクセスしてみましょう。その前に管理者ユーザー(kubeadmin)のパスワードを確認するため、以下のコマンドを実行してログインパスワードを表示します:
# cat ~/config/auth/kubeadmin-password

ログインパスワードを確認したら改めてウェブブラウザを起動し、ウェブコンソール画面である以下の URL にアクセスします(SSL は自己署名証明書を使っているので警告画面になりますが、警告を無視して先に進めてください):
https://console-openshift-console.apps.ocp.xxx.localdomain/

すると以下のようなログイン画面が表示されます。(これが表示できた時点で OCP インストールは成功しているといえそうですが、、)ユーザー名に "kubeadmin" 、パスワードには先ほど確認したログインパスワードを入力してログインします:
2024070918


ログインが成功すると以下のようなウェブコンソールのトップ画面が表示されます:
2024070919


ここまでできれば OCP のエアギャップ環境下でのインストールは成功したと言えます! そしてイグニッションファイル作成からここまでを 24 時間以内に実行する必要がある、という点に改めて注意してください(過ぎちゃった場合は ~/config フォルダごと消してマニフェストファイルの作成からやり直し)。

なお、バスチョンサーバーであれば上述のように環境変数 KUBECONFIG を設定することで oc CLI が使えるようになりますが、他のサーバーであったり、バスチョンサーバーでも実施コマンドによってはトークンでログインしておく必要が生じます。ここでの紹介の最後にトークンでのログイン方法を紹介しておきます。

・・と言っても、トークンでのログイン方法はエアギャップ環境ではない時と同様です。まず上述の方法でウェブコンソールにログインし、画面右上のメニューから "Copy login command" を選択します:
2024070920

このような画面が表示されたら "Display Token" と書かれた箇所をクリックします:
2024070921

すると以下のような画面になるので "Log in with this token" と書かれた "oc login" で始まる文字列をコピーします:
2024070922


コピーした文字列を oc コマンドが導入された環境でペーストして実行すると CLI でのログインが完了し、"oc get nodes" や "oc get clusteroperators" などのコマンドが同様に実行できるようになります。




【(3)OCP インストール後の作業】
ここまでの手順でエアギャップ環境での OCP がインストールされて、稼働状態になりました。が、実はこの状態だとまだエアギャップ環境に対応していない箇所が残っています。最終的にそれらの部分をエアギャップ環境用の調整して作業完了とみなすことにします。

まずこの時点では OperatorHub が使えません。オフライン環境ではこの方法でインストールした OCP の OperatorHub は未対応なので、OperatorHub のオフライン対応を行います。そのため、一旦全ての Sources を disable に設定します:
# oc patch OperatorHub cluster --type json -p '[{"op":"add","path":"/spec/disableAllDefaultSources","value":true}]'

そしてミラーレジストリを構築した際にできたフォルダ(~/oc-mirror-workspace/results-xxxxxxxxxx/)の情報を使ってオフライン対応を実施します:
# cd

# oc apply -f oc-mirror-workspace/results-xxxxxxxxxx/

# oc apply -f oc-mirror-workspace/results-xxxxxxxxxx/release-signatures/

上の2番目のコマンド("oc apply -f oc-mirror-workspace/results-xxxxxxxxxx")を実行した時に以下のようなエラーメッセージが表示されますが、エアギャップ環境では無視して構いません:
2024070923


ここまで実行することで OperatorHub もエアギャップ環境に対応できました。今回の環境では imageset-config-4.13.0.yaml ファイルを作った時に入れておいた Local Storage Operator が表示されます:
2024072706


またワーカーノードをインフラノードとして利用する場合、対象ノードに以下のラベリングを行います。例えば worker0 のみインフラノードにする場合は、以下のコマンドを実行します(worker1 や worker2 を対象にする場合も同様に追加実行します):
# oc label node worker0.ocp.xxx.localdomain node-role.kubernetes.io/infra=""

そして、インストールを終えてもう使うことのないブートストラップノードをシャットダウンします。OCP 環境ではバスチョンサーバーからは各ノードの CoreOS に "core" ユーザーで(パスワードなしで)ssh ログインが可能です。また CoreOS 上では core ユーザーは sudo 権限を持っているので、以下のようにシャットダウンコマンドを実行可能です:
# ssh core@bootstrap

$ sudo shutdown -h now

なお、ブートストラップノード以外のノードについては OCP 新規インストールから 24 時間はシャットダウンしないように気を付けてください。この辺り、詳しくはこちらも参照してください:
https://www.reddit.com/r/openshift/comments/c7e5na/how_to_shutdown_all_openshift_hosts_safely_in/?rdt=44062


最後にバスチョンサーバーの haproxy(ロードバランサー)からブートストラップノードを分離します。バスチョンサーバー上で /etc/haproxy/haproxy.cfg ファイルを開き、bootstrap ノードに負荷分散する設定になっている2行を削除するかコメントアウトして保存します:
2024072707


最後に haproxy を再起動します:
# systemctl restart haproxy


これでエアギャップ環境上での OCP のインストールができました。非常に長いインストール手順でしたが、これで「エアギャップ環境で OCP を使う」ための準備ができたことになります:
2024070906


この後はエアギャップ環境の OCP 内にコンテナアプリケーションをデプロイする手順や、OCP をエアギャップ環境のままアップグレードする手順を紹介してゆく予定です。


エアギャップ環境(インターネット接続のない環境)で OCP を導入/運用する上で必要な前提理解
エアギャップ環境(インターネット接続のない環境)で OCP を導入する手順
エアギャップ環境(インターネット接続のない環境)で OCP にアプリケーションを導入する手順
エアギャップ環境(インターネット接続のない環境)に導入した OCP をエアギャップ環境内でアップグレードする手順






 

ここ数か月ほど、業務で RedHat OCP(Openshift Container Platform) の調査ばかりしていました。業務の詳しい内容は公にできないのですが、ずっとインプットする時間ばかりだったので、これから数回に分けて調査した内容の技術的な部分についてアウトプットしていこうと思います。


調査していた内容をまとめるとこんな感じ:
・エアギャップ環境(インターネット接続のない環境)で OCP を導入する手順
・エアギャップ環境(インターネット接続のない環境)で OCP にアプリケーションを導入する手順
・エアギャップ環境(インターネット接続のない環境)に導入した OCP をエアギャップ環境内でアップグレードする手順

要は「インターネットの無い環境で OCP やアプリケーションをどうやって導入し、アップグレードを含めた運用をしていくか」という内容を調査していました。特に最後の「エアギャップ環境での OCP アップグレード手順」はネット上にもあまり情報がなく、もしかすると同様に困っている人の役に立てるのではないかとお思っています。

これから数回に分けてブログエントリを書いていくつもりです。初回である今回は導入手順というよりは OCP の導入時に必要な前提知識というか、理解しておくべきことをまとめておこうと思います。このあたりに興味がなく、「理屈はいいからインストール方法だけ知りたい」という方は次回以降のブログエントリを参照し、用語とか分かりにくい点があったらこちらに戻って理解する、という順序でもいいと思います。


【OCP とは?】
OCP(Openshift Container Platform)RedHat 社が提供するコンテナクラスタ環境です。コンテナクラスタ本体は Kubernetes が使われていますが、ユーザーサポートや Operator と呼ばれる拡張機能含めて提供されています。単にアプリケーション実行環境だけあればいい、という場合は Kubernetes でも全然問題ないと思いますが、DevOps となるパイプライン機能やモニタリング、ストレージ拡張といった「実運用上で必要になるであろう機能」も標準提供されていて便利だったり、またサポートの有無が問題となるような前提条件のある運用環境にもバッチリです。更には本ブログエントリの目的でもある「エアギャップ環境でのインストール/利用」もサポートされている点が特徴といえます。

IBM Cloud や AWS など、主要なパブリッククラウド内のサービスとしても提供されています。多くのケースではこのパブリッククラウドから提供されている OCP を VPS などと組み合わせて使うことで比較的セキュアなコンテナクラスタ環境を(パブリッククラウドのサブドメインを使う形で(=DNS などをあまり意識しなくても))利用することができます。 ただし、本ブログエントリで扱う「エアギャップ環境」での利用は、このようなパブリッククラウドに用意された環境を使わない利用方法です。基本的には「必要な物理/仮想サーバーを必要な台数ぶん用意して、それぞれのサーバーに OS ごと導入する」方法となります。


【OCP のエアギャップ導入時に必要な前提環境】
OCP をエアギャップ環境にインストールする手順には大きく2つの方法があります:
(1) PXE インストール
(2) ABI(Agent Based Install)

(1) と (2) には共通部分もあって、インストールの前提条件は似ているともいえるのですが、本ブログエントリでは (1) PXE インストールの場合としての前提条件を紹介します。(2) ABI については別の機会に紹介する予定です。なお PXE は「ピクシー」と発音するようです。


最初に、本ブログの中で今後数回にわたって紹介予定の OCP は(例外的に SNO(Single Node Openshift) を紹介するケースを除いて)以下の構成であるとします:
・マスターノード3台
・ワーカーノード3台

ここで出てくる「ノード」という言葉は「OCP を構成する物理/仮想サーバーで、マスターノードまたはワーカーノードとなるもの」です。例えば「マスターノードが3台必要」というのは「(OCP の要件を満たす)物理/仮想サーバーが3台必要」という意味です。少しややこしいのは「ノードだけが OCP の構成サーバーではない」ということです。後述しますが DNS などの周辺サーバーも OCP 構成には必要です。ただ広い意味で「ノード=OCP を構成するサーバー」と理解しておくとわかりやすいと思います。

そして「マスターノード」とは「API サーバーなどの役割を持ち、OCP 全体を制御するノード」です。SNO などの例外的な構成を除くと、原則的にマスターノードは3台以上必要です(2台以下だとインストールできません)。今回はマスターノードを3台で構成することにします。

次に「ワーカーノード」とは「コンテナのデプロイ先となってアプリケーションが動くノード」です(「ワーカーノード」を更に役割によって「ワーカーノード」「インフラノード」「ストレージノード」と細かく分類することもありますが、ここでは全てまとめて「ワーカーノード」とします)。前述のマスターノードにワーカーノードの役割を持たせることもできるので、純粋なワーカーノードは必須ではありません(0台でも構いません)。ただ今回のブログではワーカーノードを3台用意して構成することにします。

そしてノードの種類としてはもう1つ「ブートストラップノード」も1台必要です。「ブートストラップノード」はインストール時に必要(正確には「マスターノードのインストール時に必要」)な OCP のコンポーネントです(なお今回紹介する PXE インストールではブートストラップノードは必要ですが、ABI の場合はブートストラップノードは不要となります)。

つまり今回構成する OCP クラスタは以下のようなサーバー構成となります(この時点で7台の物理/仮想サーバーが必要です)。ちなみに各ノードに導入する OS はコンテナ用の RedHat CoreOS です:
20240617-001


これだけのノードとなる物理/仮想サーバーがあれば OCP を構築することができるか? というと、残念ながらそうではありません。OCP の導入にはノードとなるサーバー以外にも(DNS など)いくつかの前提となる環境が必要です。PXE インストールの場合であれば、以下のようなサービスが同一ネットワーク上に用意されていることが前提条件となります:
20240617-002


各サービスの一覧と役割は以下となります:
  • Bastion: OCP インストール時の作業サーバー(例えば oc コマンドはバスチョンサーバーから実行します)です
  • DNS: OCP が利用する DNS です(つまりドメインも必要です)。ワーカーノード上にデプロイされるアプリケーションの名前解決にも使うので、ワイルドカードでの名前解決ができるような設定が必要です
  • NTP: 時刻同期サーバーです。OCP の各ノード間の時刻同期のために必要です
  • DHCP: PXE (後述)の仕組みの中で、各ノードの MAC アドレスに紐づけて IP アドレスを割り当てる、という機能の中で DHCP を使います
  • TFTP: PXE の仕組みの中でファームウェアや初期設定スクリプトのダウンロードを実施する際に必要です
  • HTTP: PXE や API 、コンテナアプリケーションなど複数の用途で使われます
  • Load Balancer: API サーバー(複数のマスターノード)やデプロイ済みアプリケーション(複数のワーカーノード)へのロードバランシングを実施します
  • Mirror Registry: OCP 導入時に必要なイメージのレジストリです。通常は RedHat がインターネット上に公開していているレジストリを使って OCP を導入しますが、エアギャップ環境の場合はエアギャップ環境内にそれらがミラーリングされた環境を用意する必要があります

OCP を導入する前にこれらのサービスおよび環境を用意しておく必要があります(DNS やロードバランサーは2重化しておくこともあります)。特に注意が必要なのはバスチョンサーバーとミラーレジストリだと思うので、これらについてはもう少し詳しく紹介します。

バスチョンサーバーは OCP インストール時の作業マシンとなるサーバー(通常は RHEL)です。実質的なインストールコマンドである openshift-install コマンドを実行したり、導入後の運用時に何度も使うことになる oc コマンドを実行したり、OCP の各ノードへ ssh 接続する必要が生じた際の接続元となるサーバーです。実質的に「インストール/運用時の各種コマンドを実行するサーバー」と考えておくと理解しやすいと思います。

一方、ミラーレジストリは RedHat が公開している OCP イメージをエアギャップ環境にミラーリングしたものです。OCP インストール時に各ノードが OCP イメージを取得する際の取得元にあたります。RedHat が公開しているレジストリは全てのバージョンに対応していますが、エアギャップ環境でのインストール向けにミラーリングするレジストリは、そのインストール対象バージョンのイメージが含まれていれば要件としては満たしています。 ただ特定の1バージョン向けのミラーレジストリを構築する場合であっても OCP イメージは膨大で(追加オペレーターが1つもなくても 30GB 近くになります)、これらのファイルは事前にインターネット接続環境を使ってあらかじめダウンロードしておく必要があります(ダウンロードしたファイルを USB メモリなどでエアギャップ環境に持ち込んでから作業することになります、具体的な手順は後述します)。


【OCP4 ヘルパーノード】
前述のように、OCP をインストールするためにはその前提となる各種サーバー(上図で緑色で示したサーバー)が必要です。これらは別々に用意する方法もありますが、「1台のサーバー内に OCP 導入の前提となるサービス群をまとめてインストールして、比較的簡単に OCP 導入環境を用意できるツール」もあります。それが OCP4 ヘルパーノードです。OCP4 ヘルパーノードの実体は Ansible スクリプトであり、設定ファイルに必要な情報を書き込んでから実行すると、その設定内容にあわせて OCP 導入前提環境※を1台のサーバー内に用意してくれる、というものです:

※OCP ヘルパーノードを使うことでミラーレジストリ用の firewalld などの設定までは行ってくれますが、ミラーレジストリ内に用意するファイルは OCP のバージョンによっても異なるため、ミラーレジストリ用のファイルだけは別途ダウンロードが必要です。
20240617-003


今回紹介するブログでは、この OCP4 ヘルパーノードを使って周辺環境を構築していきます。


【PXE / iPXE】
上述のように、OCP のインストール方法はいくつかあるのですが、今回の説明記事では「PXE インストール」による導入方法を紹介します。この PXE を理解していないと実際の作業時に戸惑うことになると思うので、分からない人向けに簡単に紹介します。

多くのシステム環境構築時において、サーバーソフトウェアやミドルウェアなどを導入する場合はセットアップ用のコマンド(setup.exe など)が用意されていて、そのコマンドを実行するとインストールが開始され、場合によっては画面の指示に従って選択肢を選んでいくことでインストールが完了する、という流れになります。PXE インストールはこの点で根本的に異なるインストール方法です。

"PXE(Preboot eXecution Environment)" 自体はハードウェア規格の名称です。一般的に NIC(Network Interface Card) と呼ばれるネットワークインターフェースカードと、そのファームウェアがこの PXE 規格に対応していると、NIC は OS の導入や起動前に DHCP や TFTP クライアントとしてふるまったり、ダウンロードしたファイルを実行することが可能になります。更に PXE 対応の NIC の多くは、PXE のオープンソース拡張実装である iPXE 規格に対応していることが多く(PXE と iPXE をまとめて PXE と呼ぶこともあります)、iPXE ではファイル転送に HTTP を使うことが可能になるためサーバーの起動時(電源投入時)に DHCP で自身の IP アドレスを一時的に設定した上で OS や OS 上にインストールするアプリケーション、そのインストール手順が書かれたシェルスクリプトや設定パラメータファイルなどを TFTP や HTTP でダウンロードして自分自身をインストールする、といったことが可能になります:
20240617-004


今回は「OCP を PXE インストール」する手順を紹介しますが、それはつまり上述のように DHCP サーバーや TFTP サーバー、HTTP サーバー、ダウンロードするファイルをあらかじめ用意した上で、サーバー起動と同時にインストールすることを意味しています。したがって OS 導入後に Setup.exe をダブルクリックしてインストールする、といった方法とは根本的に異なる導入手順となります。

更に細かく言うと、今回のケースでは OCP のノード毎に異なる役割でインストール(マスターノードにはマスターノード向けのファイルをインストール、ワーカーノードにはワーカーノード向けのファイルをインストール)することになるので、DHCP サーバーに各サーバーの MAC アドレスを登録してサーバー(DHCP クライアント)を識別可能にした上で、PXE/iPXE で異なるファイルをダウンロードさせる必要もあります。この辺りは実際の導入時には上述の OCP4 ヘルパーノードを使うことでまとめて環境を準備できるので作業者が意識する必要はないのですが、仕組みとしてはこのような点が考慮された環境を用意する必要がある、といった点に留意してください。


【RedHat 開発者サブスクリプション】
実際に OCP の導入をする上で必要なファイルのダウンロードや pull-secret と呼ばれる鍵ファイルを入手する際に RedHat アカウントが必要になります。アカウントそのものの登録は無料で、また開発者向けの開発者サブスクリプションに登録することで RHEL や OCP のダウンロード/利用が可能になります。また分からないことがあった際にググって調べた内容は(RedHat ページ内のものだったりすると) RedHat アカウントがないと詳しく表示されないこともあります。いろいろな画面で使うことになる RedHat アカウントと開発者サブスクリプションに登録しておきましょう。

RedHat アカウントに開発者サブスクリプションで登録するにはウェブブラウザで https://developer.redhat.com/ にアクセスし、"Join RedHat Developer" ボタンをクリックします。その先のページで氏名や ID 、メールアドレス、パスワードなどを入力してアカウントを作成します(登録したメールアドレスを使ったメール認証も行われます)。これで RedHat アカウントの作成は完了です:
2024070901


アカウントの作成が完了したら次にに開発者サブスクリプションに登録します。そのまま https://access.redhat.com/management/systems にアクセスします。初回はアカウントの種類を求められますが、無料の個人アカウントの場合は Personal を選択します(他の情報も適宜入力します):
2024070902


初回入力項目が完了すると以下のような画面が表示されるので、「サブスクリプション」タブを選択します:
2024070903


「サブスクリプション」タブ内には現在のアカウントで有効なサブスクプションの一覧が表示されています。この中に "RedHat Developer Subscription for Individuals" という名称のサブスクリプションが含まれていれば、これが利用可能な開発者向けサブスクリプションです(ここまで確認できればアカウントとサブスクリプションの準備は完了です):
2024070904




この後に紹介する OCP のエアギャップ環境インストール/アップグレード/運用を行う上で事前に最低限理解しておく必要がある点(OCP のエアギャップ環境での特殊な点)はざっとこんな感じだと思います。では本編をどうぞ:


エアギャップ環境(インターネット接続のない環境)で OCP を導入/運用する上で必要な前提理解
エアギャップ環境(インターネット接続のない環境)で OCP を導入する手順
エアギャップ環境(インターネット接続のない環境)で OCP にアプリケーションを導入する手順
エアギャップ環境(インターネット接続のない環境)に導入した OCP をエアギャップ環境内でアップグレードする手順



最近 OCP(Openshift Container Platform) について調べることが多かったので、何回かに分けてアウトプットしていこうと思います。

今回は「OCP のアップグレードパス」についてです。OCP のアップグレード(バージョンアップ)で特に頭の痛い問題の1つが「アップグレードパス」と呼ばれるバージョンアップ時に踏む段階のことです。

より具体的な例で考えてみましょう。例えば、現在 OCP 4.4.6 というバージョンを使っていると仮定します。なんらかの理由でこれを OCP 4.6.4 というバージョンにアップグレードしたい、という前提のもとで以下を記載していきます。


【アップグレードパス】
この辺りの事情にあまり詳しくない人だと「OCP 4.4.6 から OCP 4.6.4 へのアップグレードがそんなに不便なのか?」という疑問を持つかもしれません。わかりにくい所もあるのですが、最大の問題は「そもそも OCP 4.4.6 から OCP 4.6.4 へ直接アップグレードできるのか? 直接アップデートできない場合はどのような順で実行していけばアップデートできるのか?」という所から解決していく必要がある点にあります。この「どのような順で実行していく」のかという順序のことを「アップグレードパス」といいます。

例えばですが、仮に 4.4.6 から 4.6.4 への直接アップグレードが可能であった場合(実際はできないんですけど)、アップグレードパスは「 4.4.6 → 4.6.4 」ということになります。一方、もしも間に 4.5.0 をはさんで 4.4.6 から 4.5.0 にアップグレードし、4.5.0 から 4.6.4 にアップグレードするという2段階のアップグレードを行う必要がある場合(実際は更に複雑なんですが)、アップグレードパスは「 4.4.6 → 4.5.0 → 4.6.4 」ということになる、というわけです。


【アップグレードパスの調べ方】
さて、では実際に 4.4.6 から 4.6.4 へアップグレードする場合のアップグレードパスはどのように調べればよいのでしょうか? 実はこれが結構面倒だったりします。。

まず RedHat 提供のアップグレードパスを探すサービスがあります:
https://access.redhat.com/labs/ocpupgradegraph/update_path

ただこのサイト、比較的古いバージョンが対象だとやけに重くなってしまうのです。またアップグレード前後のバージョン差が大きいケースだと「アップグレードパスが見つからない」みたいな結果が表示されることもあり、なんかちょっとよくわからない(苦笑)感じだったりします。


というわけで、上記サービスに頼らないアップグレードパスの探し方を紹介します。具体的にはまずゴールとなるバージョン(今回だと 4.6.4)のリリースノートを調べる必要があります。OCP のバージョンごとのリリースノートはオンラインで参照することができ、その URL は以下の通りです:
https://mirror.openshift.com/pub/openshift-v4/clients/ocp/(バージョン)/release.txt

例えばバージョンが 4.6.4 であれば、以下の URL を参照します:
https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.6.4/release.txt

以下のような内容が表示されます:
2024030701


はじめの十数行だけを表示するとこのようになっています:
Client tools for OpenShift
--------------------------

These archives contain the client tooling for [OpenShift](https://docs.openshift.com).

To verify the contents of this directory, use the 'gpg' and 'shasum' tools to
ensure the archives you have downloaded match those published from this location.

The openshift-install binary has been preconfigured to install the following release:

---

Name:      4.6.4
Digest:    sha256:6681fc3f83dda0856b43cecd25f2d226c3f90e8a42c7144dbc499f6ee0a086fc
Created:   2020-11-11T15:13:14Z
OS/Arch:   linux/amd64
Manifests: 444

Pull From: quay.io/openshift-release-dev/ocp-release@sha256:6681fc3f83dda0856b43cecd25f2d226c3f90e8a42c7144dbc499f6ee0a086fc

Release Metadata:
  Version:  4.6.4
  Upgrades: 4.5.16, 4.5.17, 4.5.18, 4.5.19, 4.6.1, 4.6.2, 4.6.3
  Metadata:
    description: 
  Metadata:
    url: https://access.redhat.com/errata/RHBA-2020:4987
  :
  :

↑の赤字部分に着目します。"Release Metadata:" と書かれた部分の下にバージョンに関する情報が表示されています。まず "Version:" はこのリリースノートが対象としているバージョン(4.6.4)が表示されています。 そしてその下の行の "Upgrades:" に着目してください。この例だと "4.5.16, 4.5.17, 4.5.18, 4.5.19, 4.6.1, 4.6.2, 4.6.3" と書かれていますね。

これはつまり「バージョン 4.6.4 に直接アップグレードできるバージョンは 4.5.16, 4.5.17, 4.5.18, 4.5.19, 4.6.1, 4.6.2, 4.6.3 のいずれかのみ」であることを示しています。残念ながら元のバージョンである 4.4.6 が含まれていないので、少なくとも1回のアップグレードで 4.4.6 から 4.6.4 へはアップグレードできないことも分かります。

では最終ゴールである 4.6.4 へは(上のバージョンの中のどれでもいいんですが、なるべく回数を減らしたいので最も遠い) 4.5.16 からアップグレードするとしましょう。次に調べる必要があるのは「4.4.6 から 4.5.16 へ直接アップグレードできるのか?」です。

これも同様にして 4.5.16 のリリースノート(https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.5.16/release.txt)を開き、4.5.16 にアップグレード可能なバージョンを調べると、"4.4.13, 4.4.14, 4.4.15, 4.4.16, 4.4.17, 4.4.18, 4.4.19, 4.4.20, 4.4.21, 4.4.23, 4.4.26, 4.4.27, 4.4.28, 4.4.29, 4.4.30, 4.5.2, 4.5.3, 4.5.4, 4.5.5, 4.5.6, 4.5.7, 4.5.8, 4.5.9, 4.5.11, 4.5.13, 4.5.14, 4.5.15" という結果になることが分かります。残念ながら 4.4.6 は含まれていないので、更に段階を経たアップグレードが必要になることが分かります:
2024030702


同様にして、ここでの中継バージョンを 4.4.13 とみなし、4.4.13 のリリースノート(https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.4.13/release.txt)を調べると、、今度は "4.4.6" が含まれていることがわかります。4.4.6 から 4.4.13 へのアップグレードは可能でした:
2024030703


ここまでの結果を総合すると、4.4.6 から 4.6.4 へのアップグレードパスの1つとして
4.4.5 → 4.4.13 → 4.5.16 → 4.6.4

があることが確認できました。つまり 4.4.6 から 4.6.4 へは少なくとも3回に分けてアップグレードを実施する必要がある、ということになります。

今回の例では 4.4.6 から 4.6.4 という固定バージョンでのアップグレードパスと、その調べ方を紹介しましたが、アップグレードパスの調べ方はどのバージョンからどのバージョンへ向かう場合も同様です。上で紹介した方法を使って、目的バージョンから「このバージョンにアップグレードできる最も古いバージョンは?」を繰り返し調べていくことで、最短回数でのアップグレードパスを見つけることができるようになります。

・・・でも、ちょっと面倒ですよね。そこでこの処理をツール化してみました。


【アップグレードパスを調べるツール】
上で紹介した処理を自動的に調べるツールを Node.js で作ってみました。MIT ライセンスで公開しているので商用含めて利用・改変もご自由に:
https://github.com/dotnsf/ocp-upgrade-path


Node.js がインストールされた PC 上で、上記 URL からソースコードを clone またはダウンロードして展開します。最初の実行前に一回だけ "npm install" で外部ライブラリをインストールしておく必要があります。

実行時はコマンドラインから以下のように指定して実行します:
$ node app (現在のバージョン) (アップグレード後のバージョン)

上のように現在のバージョンが 4.4.6 、アップグレード後のバージョンが 4.6.4 であったとすると、以下のように指定して実行することになります:
$ node app 4.4.6 4.6.4

実行結果は以下のように出力されます:
$ node app 4.4.6 4.6.4
currentversion = 4.4.6
targetversion = 4.6.4

4.4.6 -> 4.4.13 -> 4.5.16 -> 4.6.4

不可能なパターンを指定するとアップグレードパスに impossible と表示されます(新しいバージョンから古いバージョンへのアップグレードを指定した例です):
$ node app 4.6.4 4.4.6
currentversion = 4.6.4
targetversion = 4.4.6

4.6.4 -> (impossible) -> 4.4.6

またバージョンで指定できるパターンは正式リリース対象の (数字).(数字).(数字) だけです。バージョン文字列内に "nightly" などの文字を含む正式リリースではないバージョンも存在していますが、このツールでは対象外としています。

ちゃんとテストしたわけではない(というかテストできない)のですが、現時点でリリースされていない未来のバージョンについても、その未来バージョンがリリースされて、リリースノートも同様に提供されていれば、その未来バージョンへのアップグレードパスも表示できるようになるはずです。

ウェブ化してもっと気軽に(Node.js がインストールされていなくても)使えるようにすることも考えたのですが、「OCP をバージョンアップする」作業が必要になるようなプロジェクトでは、それなりのエンジニアがプロジェクトに携わっていることが大半だと思ってサボっちゃいました。


「OCP アップグレード版の乗換案内」的なツールができたと思っています。役立つことがあれば嬉しいです。


【参考】
Successfully upgrade OpenShift cluster on a disconnected environment with troubleshooting guide.



このページのトップヘ