OpenShift on Powerの3ノードクラスター環境構築

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

本記事ではOpenShift on Powerの3ノードクラスター環境のオンプレミスでの構築を試してみた時の手順を紹介します。

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

なお、こちらの構築はオンプレミス環境での構築となります。
Power Virtual ServerでのOpenShiftの構築は@hiroyuki_z_tanakaさんの記事を参照してください。
https://qiita.com/hiroyuki_z_tanaka/items/c2b279bcd23a2f0b9c4d

# 環境構成

以下の環境構成でLPARをHMCより作成しました。
3ノードクラスターと呼ばれるWorkerなし、Master3台で構成されるクラスターとなり、PodはMaster上にスケジュールされるものとなります。

|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    |

またネットワーク構成は以下の図のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2419719/d42570e6-6b31-7146-10f6-b40df8550b89.png)

# 事前準備
まず作成したBastion LPARにRHEL9.3を導入します。"Server with GUI"のオプション付きでインストールすると、Webアクセスの問題判別等に使用できます。
導入後、Subscription登録 / EPEL導入 / Ansible + gitの導入をしておきます。
(以降、特別な記載がない限りすべてBastionからのコマンド実行となります)
```
# subscription-manager register --username USERNAME --password PASSWORD
# subscription-manager status
# dnf repolist
# dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
# dnf install ansible git
```
次に[OCP4-helpernode](https://github.com/RedHatOfficial/ocp4-helpernode/)を使用して
Bastion上にAnsibleプレイブックによるOpenShiftの導入に必要なLB/DNS/DHCP/TFTP/HTTPサーバーの導入を行います。
```
# git clone https://github.com/RedHatOfficial/ocp4-helpernode
# cd ocp4-helpernode
# cp docs/examples/vars-ppc64le.yaml vars.yaml
```
環境にあわせてvars.yamlを編集します。今回のようにBastionに複数のネットワークインターフェースがある場合は、DHCPを提供するネットワークインターフェースをnetworkifacenameで指定します。
```yaml:vars.yaml
disk: sda
helper:
  name: "bastion"
  ipaddr: "10.1.0.100"
  networkifacename: "env11"
dns:
  domain: "p10test.com"
  clusterid: "ocp4"
#  forwarder1: "8.8.8.8"
#  forwarder2: "8.8.4.4"
dhcp:
  router: "10.1.0.1"
  bcast: "10.1.255.255"
  netmask: "255.255.0.0"
  poolstart: "10.1.0.100"
  poolend: "10.1.0.120"
  ipid: "10.1.0.0"
  netmaskid: "255.255.0.0"
bootstrap:
  name: "bootstrap"
  ipaddr: "10.1.0.101"
  macaddr: "xx:xx:xx:xx:xx:xx"
masters:
  - name: "master0"
    ipaddr: "10.1.0.102"
    macaddr: "xx:xx:xx:xx:xx:xx"
  - name: "master1"
    ipaddr: "10.1.0.103"
    macaddr: "xx:xx:xx:xx:xx:xx"
  - name: "master2"
    ipaddr: "10.1.0.104"
    macaddr: "xx:xx:xx:xx:xx:xx"

ppc64le: true
ocp_bios: "https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.18/4.18.1/rhcos-live-rootfs.ppc64le.img"
ocp_initramfs: "https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.18/4.18.1/rhcos-live-initramfs.ppc64le.img"
ocp_install_kernel: "https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.18/4.18.1/rhcos-live-kernel-ppc64le"
ocp_client: "https://mirror.openshift.com/pub/openshift-v4/ppc64le/clients/ocp/4.18.1/openshift-client-linux-4.18.1.tar.gz"
ocp_installer: "file:///data/ocp-files/openshift-install-linux-4.18.1.tar.gz"
helm_source: "https://get.helm.sh/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
```
Ansibleプレイブックを実行します。
```
# 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上にProxyサーバー(squid)およびNTPサーバー(chrony)を導入します。
```
# dnf install squid
# vi /etc/squid/squid.conf
# firewall-cmd --add-port=8000/tcp --zone=public --permanent
# firewall-cmd --reload
# systemctl enable squid
# systemctl start squid
# systemctl status squid
# vi /etc/chrony.conf
# firewall-cmd --add-service=ntp --permanent
# firewall-cmd --reload
# systemctl enable chronyd
# systemctl start chronyd
# systemctl status chronyd
```
今回は/etc/squid/squid.confおよび/etc/chrony.confは以下を使用しました。
```text:/etc/squid/squid.conf
acl localnet src 10.1.0.0/16
acl SSL_ports port 443
acl Safe_ports port 80		# http
acl Safe_ports port 21		# ftp
acl Safe_ports port 443		# https
acl Safe_ports port 70		# gopher
acl Safe_ports port 210		# wais
acl Safe_ports port 1025-65535	# unregistered ports
acl Safe_ports port 280		# http-mgmt
acl Safe_ports port 488		# gss-http
acl Safe_ports port 591		# filemaker
acl Safe_ports port 777		# multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localnet
http_access allow localhost
http_access deny all
http_port 10.1.0.100:8000
coredump_dir /var/spool/squid
refresh_pattern ^ftp:		1440	20%	10080
refresh_pattern ^gopher:	1440	0%	1440
refresh_pattern -i (/cgi-bin/|\?) 0	0%	0
refresh_pattern .		0	20%	4320
```
```text:/etc/chrony.conf
pool 2.rhel.pool.ntp.org iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
allow 10.1.0.0/16
keyfile /etc/chrony.keys
leapsectz right/UTC
logdir /var/log/chrony
```
# 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

まず、OpenShiftのレジストリーアクセスに必要なpull-secretをダウンロードします。
OpenShiftのライセンスをもつユーザーで以下のリンクにアクセスしてpull-secretを取得します。
https://cloud.redhat.com/openshift/install/pull-secret

次にinstall-config.yamlを作成します。今回は以下のように作成しています。
(実行前にpull-secret.txtと~/.ssh/helper_rsa.pubが存在するのを確認しておきます)
```
# cat <<EOF > install-config.yaml
apiVersion: v1
baseDomain: p10test.com
proxy:
  httpProxy: http://10.1.0.100:8000
  httpsProxy: http://10.1.0.100:8000
  noProxy: 10.1.0.0/16,172.16.0.0/16,.p10test.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: '$(< ~/pull-secret.txt)'
sshKey: '$(< ~/.ssh/helper_rsa.pub)'
EOF
```
manifestsファイルおよびignitionファイルを作成、ignitionファイルをコピーします。
```
# mkdir config
# cp install-config.yaml config
# openshift-install create manifests --dir=config
# 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)の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環境では各RHCOSの導入の後にディスクでブートするためのbootlist設定を行わないため、
各ノードが再起動したタイミングでSMSからbootlistを設定するか下記のリンクの手順にてignition追加設定を行います。
https://openshift-ppc64le.readthedocs.io/en/latest/set-bootlist-during-netinstall/

ブートストラッププロセスを以下のコマンドで確認します。
```
# 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.p10test.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
```
今回Masterのみの構成ですので、CSRの承認はありません。
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.p10test.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.p10test.com
INFO Login to the console with user: "kubeadmin", and password: "xxxxx"
```
WebコンソールからOpenShiftClusterManagerにアクセスして、Subscriptionが適切に設定されているか確認します。OpenShiftClusterManagerはWebコンソールの概要->詳細部分にリンクが表示されています。
# インストール後の作業
今回のネットワーク構成では各ノードが外部のNTPを参照できないため、BastionのNTPを使用するように変更します。この変更はOCP4-herlpernodeの設定でも可能ですが、今回は下記手動での設定を行いました。
以下の内容の99-master-chrony.buという名前のファイルを作成します。
```text:99-master-chrony.bu
variant: openshift
version: 4.10.0
metadata:
  name: 99-master-chrony 
  labels:
    machineconfiguration.openshift.io/role: master
storage:
  files:
  - path: /etc/chrony.conf
    mode: 0644 
    overwrite: true
    contents:
      inline: |
        server 10.1.0.100 iburst 
        driftfile /var/lib/chrony/drift
        makestep 1.0 3
        rtcsync
        logdir /var/log/chrony
```
NTP設定を反映させます。
```
# curl https://mirror.openshift.com/pub/openshift-v4/clients/butane/latest/butane-ppc64le --output butane
# chmod +x butane
# ./butane 99-master-chrony.bu -o 99-master-chrony.yaml
# oc apply -f 99-master-chrony.yaml
```
次に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: 10.1.0.100
  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** を {} から以下に変更します。
```
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"
# git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner.git nfs-subdir
# 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: gcr.io/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: 10.1.0.100
      - name: NFS_PATH
        value: /export
volumes:
  - name: nfs-client-root
    nfs:
      server: 10.1.0.100
      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のテストを行ってみます。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 core@bootstrap -i ~/.ssh/helper_rsa
# ssh core@master0 -i ~/.ssh/helper_rsa
```