OpenShift 4.6 UPI install on bare metal

## 概要

おうちKubernetes・OpenShift勢の皆さん、こんにちは！！
OpenShift 4.6 のベアメタルへのUPIインストールを実施しましたので、手順を紹介します。

**OpenShift 4.7、OpenShift 4.11 以降については以下記事もご参照ください。**

https://qiita.com/loftkun/items/9de7708128caa760ccfd

https://qiita.com/loftkun/items/03ca887ace88ef10496f

[ちょいと早い忘年会 OpenShift.Run Winter 2020 #11 - connpass](https://openshift.connpass.com/event/191402/)で発表した以下スライドもご参照ください。
[OpenShift from Easy way to Hard ? Way - Speaker Deck](https://speakerdeck.com/loftkun/openshift-from-easy-way-to-hard-way)
[![](https://files.speakerdeck.com/presentations/40f90956750c41f5bd1eeacc8438f7ef/slide_0.jpg)](https://speakerdeck.com/loftkun/openshift-from-easy-way-to-hard-way)

発表の模様はYouTubeで中継されましたので、大まかな手順の概要を知りたい方は以下動画をご覧いただくのが良いかと思います( 私の発表開始の再生時刻にリンクしています )。
[ちょいと早い忘年会！OpenShift.Run Winter 2020 - YouTube](https://www.youtube.com/watch?v=9oH2TBYaQ9A&feature=youtu.be&t=6462)
[![](http://img.youtube.com/vi/9oH2TBYaQ9A/sddefault.jpg)](https://www.youtube.com/watch?v=9oH2TBYaQ9A&feature=youtu.be&t=6462)

## 参考ドキュメント

- openshift.com の 英語版ドキュメント
  - [Installing a cluster on bare metal - Installing on bare metal | Installing | OpenShift Container Platform 4.6](https://docs.openshift.com/container-platform/4.6/installing/installing_bare_metal/installing-bare-metal.html)
- redhat.com の 日本語版ドキュメント
  - [第1章 ベアメタルへのインストール 4.6 | Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.6/html/installing_on_bare_metal/installing-on-bare-metal)
      - **本記事の章番号はこのドキュメントに合わせていますので併せて参照いただくと良いです。**

## 参考文献

- [OpenShift 4.1をベアメタルへUPIインストールする - 赤帽エンジニアブログ](https://rheb.hatenablog.com/entry/openshift41-baremetal-upi)
  - ネット上にあるUPIインストールの構築記事はほぼこの記事を参考元とされているように思います。この分野の原典とも言える記事です。
      - 当記事も参考にさせていただいています。

- [OpenShift 4.1をIntelの超小型PC「NUC」にインストールする - Qiita](https://qiita.com/daihiraoka/items/ada36baef875805f004f)
  - ESXiで構築されており、参考にさせていただきました。

## 構成図

家庭内ネットワークにあるベアメタルにESXi 7.0を入れています。
踏み台サーバー(`bastion`)やOpenShiftの各ノードはVMとして構築しています。

![env-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/018cdfd0-9894-3daa-f393-695041497aff.png)

## ベアメタルのスペック

|  項目   |                       値                        |
| ------- | ----------------------------------------------- |
| CPU     | Intel Core i7-8700K 3.7GHz 6core/12thread |
| RAM     | 64GB                                            |
| STORAGE | HDD 2TB                                         |

## 1.1.1. 前提条件

- OpenShift 4.6 は Bare metal への user-provisioned infrastructure によるインストールが可能
- クラスターがアクセスを必要とするサイトを許可するようにファイアウォールを設定する必要がある

## 1.1.2. OpenShift Container Platform のインターネットアクセスおよび Telemetry アクセス

クラスターをインストールするためにインターネットへのアクセスが必要である旨が記載されています。
なお、インターネットへのアクティブな接続を必要としないインストール方法は、
別の章( [1.3. ネットワークが制限された環境でのクラスターのベアメタルへのインストール 4.6 | Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.6/html/installing_on_bare_metal/installing-restricted-networks-bare-metal) )に記載されています。

## 1.1.3. ユーザーによってプロビジョニングされOるインフラストラクチャーを使用する場合のクラスターのマシン要件

### 1.1.3.1. 必要なマシン

マシン種別と台数を確認します。必要なマシンは以下とされています。

```
1 つの一時的なブートストラップマシン
3 つのコントロールプレーン、またはマスター、マシン
少なくとも 2 つのコンピュートマシン (ワーカーマシンとしても知られる)。
```

ブートストラップマシンはクラスターのインストール完了後、削除できます。

高可用性のためには別個の物理ホストを使用するとよいとのことですが、本手順ではVMを使用します。

### 1.1.3.2. ネットワーク接続の要件

クラスターのマシン起動時に、ignition設定ファイルを提供する必要があります。

本手順で構築する踏み台サーバで以下を提供します。

- Webサーバ
- DHCP

### 1.1.3.3. 最小リソース要件

最小リソース要件を確認します。

|      ノード      |  OS   | vCPU | RAM [GB] | STORAGE [GB] | 台数 |
| ---------------- | ----- | ---- | -------- | ------------ | ---- |
| ブートストラップ | RHCOS | 4    | 16       | 120          | 1    |
| コントロール     | RHCOS | 4    | 16       | 120          | 3    |
| コンピュート     | RHCOS | 2    | 8        | 120          | 2    |
| 合計             | -     | 20   | 80       | 720          | 6    |

上記のリソース要件に対して、今回の検証環境では以下ノードを構築しています。

インフラの要件を満たすために、1台サーバー(踏み台サーバー)を追加しています。
このサーバーには、DNS/DHCP/LoadBalancer/Webサーバを構築します。
また、クラスタへアクセスするための踏み台サーバーを兼ねています。

|      ノード      |  OS   | vCPU | RAM [GB] | STORAGE [GB] | 台数 |
| ---------------- | ----- | ---- | -------- | ------------ | ---- |
| ブートストラップ | RHCOS | 4    | 16       | 120          | 1    |
| コントロール     | RHCOS | 4    | 16       | 120          | 3    |
| コンピュート     | RHCOS | 2    | 8        | 120          | 2    |
| 踏み台サーバー   | RHEL8 | 2    | 8        | 50           | 1    |
| 合計             | -     | 22   | 84       | 770          | 7    |

今回用意したベアメタルのスペックは以下です。

|    ノード     |  OS  | vCPU | RAM [GB] | STORAGE [GB] | 台数 |
| ------------- | ---- | ---- | -------- | ------------ | ---- |
| My bare metal | ESXi | 12   | 64       | 2000        | 1    |

CPUコア数とメモリ搭載量が不足しています。
今回、各ノードや踏み台サーバーはVMとして構築しており、オーバーコミットの状態となっていますが、
OpenShiftをインストールして、チュートリアルのWebアプリをデプロイした限りでは正常に動作しているように見えています。

#### VMの作成

予め以下のVMを作成しておき、MACアドレスを控えておきます。

- MACアドレスは1回VMを起動すると付与され、VM設定画面で確認できます。
- 以下も設定しておきます
  - `Hardware virtualization`の `Expose hardware assisted virtualization to the guest OSHardware virtualization` を有効化
  - `Performance counters`の `Enable virtualized CPU performance counters`を有効化

本手順書内で下記MACアドレスを記載している箇所は適宜書き換えが必要です。

|   VM名    |     MACアドレス     |
| --------- | ------------------- |
| bootstrap | `00:0c:29:64:c8:5f` |
| master-0  | `00:0c:29:43:7b:f5` |
| master-1  | `00:0c:29:5f:bf:43` |
| master-2  | `00:0c:29:99:23:79` |
| worker-0  | `00:0c:29:d7:84:ef` |
| worker-1  | `00:0c:29:a4:a2:15` |

## 1.1.4. ユーザーによってプロビジョニングされるインフラストラクチャーの作成

ドキュメントでは以下について記載されています。

1. 各ノードに DHCP を設定するか、または静的 IP アドレスを設定します。
1. 必要なロードバランサーをプロビジョニングします。
1. マシンのポートを設定します。
1. DNS を設定します。
1. ネットワーク接続を確認します。

インフラストラクチャーの作成は、本手順書では踏み台サーバーの構築に相当しており、以下実施順で構築しています。

- サブスクリプション登録
- IPv6無効化、IPv4ルーティング
- SELinux
- 不要なサービスの停止
- NIC設定
- firewalld
- DNSとDHCP
- ロードバランサー
- Webサーバー

### サブスクリプション登録

`Status`が`Subscribed`(or `サブスクライブ済み`)となっている場合、登録済みです。

登録していない場合は`subscription-manager register`コマンドで登録します。

```sh
[loft@bastion ~]$ subscription-manager register
登録中: subscription.rhsm.redhat.com:443/subscription
ユーザー名: loftkun
パスワード:
このシステムは、次の ID で登録されました: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
登録したシステム名: bastion
[loft@bastion ~]$
```

### IPv6無効化、IPv4ルーティング

```sh
[root@bastion loft]# cat <<EOF > /etc/sysctl.d/99-custom.conf
> net.ipv6.conf.all.disable_ipv6 = 1
> net.ipv4.ip_forward = 1
> EOF
[root@bastion loft]# sysctl -p /etc/sysctl.d/99-custom.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv4.ip_forward = 1
[root@bastion loft]#
```

### SELinux

```sh
[root@bastion loft]# setsebool -P httpd_read_user_content 1
[root@bastion loft]# setsebool -P haproxy_connect_any 1
```

### 不要なサービスの停止

```sh
[root@bastion loft]# systemctl disable avahi-daemon.service
Removed /etc/systemd/system/multi-user.target.wants/avahi-daemon.service.
Removed /etc/systemd/system/sockets.target.wants/avahi-daemon.socket.
Removed /etc/systemd/system/dbus-org.freedesktop.Avahi.service.
[root@bastion loft]# systemctl stop avahi-daemon*
[root@bastion loft]#
[root@bastion loft]# systemctl stop cups.service
[root@bastion loft]# systemctl disable cups.service
Removed /etc/systemd/system/multi-user.target.wants/cups.path.
Removed /etc/systemd/system/multi-user.target.wants/cups.service.
Removed /etc/systemd/system/sockets.target.wants/cups.socket.
Removed /etc/systemd/system/printer.target.wants/cups.service.
[root@bastion loft]#
[root@bastion loft]# systemctl stop rpcbind.service
Warning: Stopping rpcbind.service, but it can still be activated by:
  rpcbind.socket
[root@bastion loft]# systemctl stop rpcbind.socket
[root@bastion loft]# systemctl disable rpcbind.service
Removed /etc/systemd/system/multi-user.target.wants/rpcbind.service.
[root@bastion loft]# systemctl disable rpcbind.socket
Removed /etc/systemd/system/sockets.target.wants/rpcbind.socket.
[root@bastion loft]#
[root@bastion loft]# systemctl stop libvirtd.service
Warning: Stopping libvirtd.service, but it can still be activated by:
  libvirtd-admin.socket
  libvirtd.socket
  libvirtd-ro.socket
[root@bastion loft]# systemctl disable libvirtd.service
Removed /etc/systemd/system/multi-user.target.wants/libvirtd.service.
Removed /etc/systemd/system/sockets.target.wants/virtlogd.socket.
Removed /etc/systemd/system/sockets.target.wants/virtlockd.socket.
Removed /etc/systemd/system/sockets.target.wants/libvirtd.socket.
Removed /etc/systemd/system/sockets.target.wants/libvirtd-ro.socket.
[root@bastion loft]#
```

### NIC設定

NICに固定IPアドレスを設定しておきます。

|  NIC   |    IPアドレス    | ESXi ポートグループ | ESXi 仮想スイッチ |
| ------ | ---------------- | ------------------- | ----------------- |
| ens192 | 192.168.3.101/24 | VM Network          | vSwitch0          |
| ens224 | 172.16.0.1/24    | OCP Network         | vSwitch1          |

```sh
[root@bastion loft]# nmcli
ens192: 接続済み to ens192
        "VMware VMXNET3"
        ethernet (vmxnet3), 00:0C:29:66:82:2C, hw, mtu 1500
        ip4 デフォルト
        inet4 192.168.3.101/24
        route4 192.168.3.0/24
        route4 0.0.0.0/0

ens224: 接続済み to ens224
        "VMware VMXNET3"
        ethernet (vmxnet3), 00:0C:29:66:82:36, hw, mtu 1500
        inet4 172.16.0.1/24
        route4 172.16.0.0/24

lo: 管理無し
        "lo"
        loopback (unknown), 00:00:00:00:00:00, sw, mtu 65536

DNS configuration:
        servers: 192.168.3.1
        interface: ens192

既知のデバイスに関する情報を取得するには、"nmcli device show" を使用します。
アクティブな接続プロファイルの概要を取得するには、"nmcli connection show" を使用します。

使用方法の詳細情報については、nmcli(1) と nmcli-examples(5) の man ページを参照してください。
[root@bastion loft]#
```

### firewalld

```sh
[root@bastion loft]# firewall-cmd --get-active-zones
public
  interfaces: ens192 ens224
[root@bastion loft]# firewall-cmd --set-default-zone=trusted
success
[root@bastion loft]#
[root@bastion loft]#
[root@bastion loft]# firewall-cmd --get-active-zones
trusted
  interfaces: ens192 ens224
[root@bastion loft]# firewall-cmd --add-masquerade --zone=trusted --permanent
success
[root@bastion loft]# firewall-cmd --reload
success
[root@bastion loft]# firewall-cmd --get-active-zones
trusted
  interfaces: ens224 ens192
[root@bastion loft]# firewall-cmd --list-all --permanent --zone=trusted
trusted
  target: ACCEPT
  icmp-block-inversion: no
  interfaces:
  sources:
  services:
  ports:
  protocols:
  masquerade: yes
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

[root@bastion loft]#
```

### DNSとDHCP

`/etc/dnsmasq.conf` に以下を追記します。

```sh
port=53
domain-needed
bogus-priv
resolv-file=/etc/resolv.dnsmasq
no-poll
address=/apps.test.example.local/172.16.0.1
#user=dnsmasq
#group=dnsmasq
no-dhcp-interface=ens192
expand-hosts
domain=test.example.local
dhcp-range=172.16.0.100,172.16.0.200,255.255.255.0,12h
dhcp-host=00:0c:29:64:c8:5f,bootstrap,172.16.0.100
dhcp-host=00:0c:29:43:7b:f5,master-0,172.16.0.101
dhcp-host=00:0c:29:5f:bf:43,master-1,172.16.0.102
dhcp-host=00:0c:29:99:23:79,master-2,172.16.0.103
dhcp-host=00:0c:29:d7:84:ef,worker-0,172.16.0.104
dhcp-host=00:0c:29:a4:a2:15,worker-1,172.16.0.105
dhcp-option=option:dns-server,172.16.0.1
dhcp-option=option:netmask,255.255.255.0
dhcp-leasefile=/var/lib/dnsmasq/dnsmasq.leases
srv-host=_etcd-server-ssl._tcp.test.example.local,etcd-0.test.example.local,2380,0,10
srv-host=_etcd-server-ssl._tcp.test.example.local,etcd-1.test.example.local,2380,0,10
srv-host=_etcd-server-ssl._tcp.test.example.local,etcd-2.test.example.local,2380,0,10
log-dhcp
log-facility=/var/log/dnsmasq.log
#conf-dir=/etc/dnsmasq.d,.rpmnew,.rpmsave,.rpmorig
```

`resolv.conf`の編集と`/etc/resolv.dnsmasq`の新規作成

```sh
[root@bastion loft]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 8.8.8.8
[root@bastion loft]# vim /etc/resolv.conf
[root@bastion loft]# cat /etc/resolv.conf
# Generated by NetworkManager
#nameserver 8.8.8.8
nameserver 127.0.0.1
[root@bastion loft]#

[root@bastion loft]# cat <<EOF > /etc/resolv.dnsmasq
> nameserver 8.8.8.8
> EOF
[root@bastion loft]# cat /etc/resolv.dnsmasq
nameserver 8.8.8.8
[root@bastion loft]#
```

`/etc/hosts`に以下を追記します。

```sh
192.168.3.101   api
172.16.0.1      api-int
172.16.0.101    etcd-0
172.16.0.102    etcd-1
172.16.0.103    etcd-2

172.16.0.100    bootstrap
172.16.0.101    master-0
172.16.0.102    master-1
172.16.0.103    master-2
172.16.0.104    worker-0
172.16.0.105    worker-1
```

サービス起動

```sh
[root@bastion loft]# systemctl enable dnsmasq.service
[root@bastion loft]# systemctl status dnsmasq.service
● dnsmasq.service - DNS caching server.
   Loaded: loaded (/usr/lib/systemd/system/dnsmasq.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Sun 2020-11-15 10:24:27 JST; 1min 27s ago
  Process: 16843 ExecStart=/usr/sbin/dnsmasq -k (code=exited, status=1/FAILURE)
 Main PID: 16843 (code=exited, status=1/FAILURE)

11月 15 10:24:27 bastion systemd[1]: Started DNS caching server..
11月 15 10:24:27 bastion dnsmasq[16843]: dnsmasq: illegal repeated keyword at line 678 of /etc/dnsmasq.conf
11月 15 10:24:27 bastion dnsmasq[16843]: illegal repeated keyword at line 678 of /etc/dnsmasq.conf
11月 15 10:24:27 bastion systemd[1]: dnsmasq.service: Main process exited, code=exited, status=1/FAILURE
11月 15 10:24:27 bastion dnsmasq[16843]: FAILED to start up
11月 15 10:24:27 bastion systemd[1]: dnsmasq.service: Failed with result 'exit-code'.
[root@bastion loft]# systemctl start dnsmasq.service
[root@bastion loft]# systemctl status dnsmasq.service
● dnsmasq.service - DNS caching server.
   Loaded: loaded (/usr/lib/systemd/system/dnsmasq.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2020-11-15 10:25:58 JST; 1s ago
 Main PID: 16863 (dnsmasq)
    Tasks: 1 (limit: 23860)
   Memory: 748.0K
   CGroup: /system.slice/dnsmasq.service
           └─16863 /usr/sbin/dnsmasq -k

11月 15 10:25:58 bastion systemd[1]: Started DNS caching server..
[root@bastion loft]#
```

### ロードバランサー

```sh
[root@bastion loft]# yum install haproxy
Updating Subscription Management repositories.
メタデータの期限切れの最終確認: 0:32:35 時間前の 2020年11月15日 09時55分33秒 に実施しました。
依存関係が解決しました。

( 略 )
インストール済み:
  haproxy-1.8.23-5.el8.x86_64

完了しました!
[root@bastion loft]#
```

`/etc/haproxy/haproxy.cfg`に以下を追記します。
既存の設定( `frontend main`, `backend static`, `backend app` ) はコメントアウトします。

```conf
frontend K8s-api
    bind *:6443
    option tcplog
    mode tcp
    default_backend     api-6443

frontend Machine-config
    bind *:22623
    option tcplog
    mode tcp
    default_backend     config-22623

frontend Ingress-http
    bind *:80
    option tcplog
    mode tcp
    default_backend http-80

frontend Ingress-https
    bind *:443
    option tcplog
    mode tcp
    default_backend     https-443


backend api-6443
    mode tcp
    balance     roundrobin
    option  ssl-hello-chk 
    server  bootstrap bootstrap.test.example.local:6443 check
    server  master-0 master-0.test.example.local:6443 check
    server  master-1 master-1.test.example.local:6443 check
    server  master-2 master-2.test.example.local:6443 check

backend config-22623
    mode tcp
    balance     roundrobin
    server  bootstrap bootstrap.test.example.local:22623 check
    server  master-0 master-0.test.example.local:22623 check
    server  master-1 master-1.test.example.local:22623 check
    server  master-2 master-2.test.example.local:22623 check

backend http-80
    mode tcp
    balance     roundrobin
    server  worker-0 worker-0.test.example.local:80 check
    server  worker-1 worker-1.test.example.local:80 check

backend https-443
    mode tcp
    balance     roundrobin
    option      ssl-hello-chk
    server  worker-0 worker-0.test.example.local:443 check
    server  worker-1 worker-1.test.example.local:443 check
```

```sh
[root@bastion loft]# systemctl enable haproxy.service
Created symlink /etc/systemd/system/multi-user.target.wants/haproxy.service → /usr/lib/systemd/system/haproxy.service.
[root@bastion loft]# systemctl status haproxy.service
● haproxy.service - HAProxy Load Balancer
   Loaded: loaded (/usr/lib/systemd/system/haproxy.service; enabled; vendor preset: disabled)
   Active: inactive (dead)
[root@bastion loft]# systemctl start haproxy.service
[root@bastion loft]# systemctl status haproxy.service
● haproxy.service - HAProxy Load Balancer
   Loaded: loaded (/usr/lib/systemd/system/haproxy.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2020-11-15 10:44:33 JST; 2s ago
  Process: 12836 ExecStartPre=/usr/sbin/haproxy -f $CONFIG -c -q $OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 12838 (haproxy)
    Tasks: 2 (limit: 23860)
   Memory: 3.2M
   CGroup: /system.slice/haproxy.service
           ├─12838 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
           └─12839 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid

11月 15 10:44:32 bastion systemd[1]: Starting HAProxy Load Balancer...
11月 15 10:44:33 bastion haproxy[12838]: [WARNING] 319/104433 (12838) : config : 'option forwardfor' ignored for frontend 'K8s-api' as it requires HTTP mode.
11月 15 10:44:33 bastion haproxy[12838]: [WARNING] 319/104433 (12838) : config : 'option forwardfor' ignored for frontend 'Machine-config' as it requires HTTP mode.
11月 15 10:44:33 bastion haproxy[12838]: [WARNING] 319/104433 (12838) : config : 'option forwardfor' ignored for frontend 'Ingress-http' as it requires HTTP mode.
11月 15 10:44:33 bastion haproxy[12838]: [WARNING] 319/104433 (12838) : config : 'option forwardfor' ignored for frontend 'Ingress-https' as it requires HTTP mode.
11月 15 10:44:33 bastion haproxy[12838]: [WARNING] 319/104433 (12838) : config : 'option forwardfor' ignored for backend 'api-6443' as it requires HTTP mode.
11月 15 10:44:33 bastion haproxy[12838]: [WARNING] 319/104433 (12838) : config : 'option forwardfor' ignored for backend 'config-22623' as it requires HTTP mode.
11月 15 10:44:33 bastion haproxy[12838]: [WARNING] 319/104433 (12838) : config : 'option forwardfor' ignored for backend 'http-80' as it requires HTTP mode.
11月 15 10:44:33 bastion haproxy[12838]: [WARNING] 319/104433 (12838) : config : 'option forwardfor' ignored for backend 'https-443' as it requires HTTP mode.
11月 15 10:44:33 bastion systemd[1]: Started HAProxy Load Balancer.
[root@bastion loft]#
```

### Webサーバー

```sh
[root@bastion loft]# yum install nginx
Updating Subscription Management repositories.
メタデータの期限切れの最終確認: 0:50:51 時間前の 2020年11月15日 09時55分33秒 に実施しました。
依存関係が解決しました。

( 略 )

インストール済み:
  nginx-1:1.14.1-9.module+el8.0.0+4108+af250afe.x86_64                                  nginx-all-modules-1:1.14.1-9.module+el8.0.0+4108+af250afe.noarch
  nginx-mod-stream-1:1.14.1-9.module+el8.0.0+4108+af250afe.x86_64                       nginx-mod-http-image-filter-1:1.14.1-9.module+el8.0.0+4108+af250afe.x86_64
  nginx-mod-http-xslt-filter-1:1.14.1-9.module+el8.0.0+4108+af250afe.x86_64             nginx-mod-http-perl-1:1.14.1-9.module+el8.0.0+4108+af250afe.x86_64
  nginx-filesystem-1:1.14.1-9.module+el8.0.0+4108+af250afe.noarch                       nginx-mod-mail-1:1.14.1-9.module+el8.0.0+4108+af250afe.x86_64

完了しました!
[root@bastion loft]#
```

`/etc/nginx/nginx.conf`に対して`# edit for ocp`の行(4箇所)を編集します。

```conf
    server {
        listen        8008 default_server;     # edit for ocp
        #listen       80 default_server;       # edit for ocp
        #listen       [::]:80 default_server;  # edit for ocp
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
        disable_symlinks off;   # edit for ocp
    }
```

```sh
[root@bastion loft]# systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
[root@bastion loft]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: inactive (dead)

11月 15 10:46:32 bastion systemd[1]: nginx.service: Unit cannot be reloaded because it is inactive.
[root@bastion loft]# systemctl start nginx
[root@bastion loft]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2020-11-15 10:52:13 JST; 2s ago
  Process: 13143 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
  Process: 13140 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
  Process: 13139 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
 Main PID: 13144 (nginx)
    Tasks: 3 (limit: 23860)
   Memory: 8.0M
   CGroup: /system.slice/nginx.service
           ├─13144 nginx: master process /usr/sbin/nginx
           ├─13145 nginx: worker process
           └─13146 nginx: worker process

11月 15 10:52:13 bastion systemd[1]: Starting The nginx HTTP and reverse proxy server...
11月 15 10:52:13 bastion nginx[13140]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
11月 15 10:52:13 bastion nginx[13140]: nginx: configuration file /etc/nginx/nginx.conf test is successful
11月 15 10:52:13 bastion systemd[1]: Started The nginx HTTP and reverse proxy server.
[root@bastion loft]#
```

## 1.1.5. SSH プライベートキーの生成およびエージェントへの追加

```sh
[root@bastion loft]# ssh-keygen -t rsa -b 4096 -N '' -f ~/.ssh/new_rsa
Generating public/private rsa key pair.
Created directory '/root/.ssh'.
Your identification has been saved in /root/.ssh/new_rsa.
Your public key has been saved in /root/.ssh/new_rsa.pub.
The key fingerprint is:
SHA256:KED2BrIIaokKYkQjRKohAbvFX55ZoPcWykjTCSxuTl0 root@bastion
The key's randomart image is:
+---[RSA 4096]----+
|@*+.. .          |
|OO+o.+Eo         |
|%=+o*.= o        |
|O++=.B B .       |
|++  + B S        |
|  .  . .         |
|                 |
|                 |
|                 |
+----[SHA256]-----+
[root@bastion loft]# ls -Fla ~/.ssh/new_rsa
-rw-------. 1 root root 3381 11月 15 10:58 /root/.ssh/new_rsa
[root@bastion loft]#
```

## 1.1.6. インストールプログラムの取得

以下より取得します。

[Install OpenShift 4 | Red Hat OpenShift Cluster Manager | Bare Metal User-Provisioned Infrastructure](https://cloud.redhat.com/openshift/install/metal/user-provisioned)

踏み台サーバー上でブラウザで以下ファイルをダウンロードします。

|          種別          |           ファイル名           |
| ---------------------- | ------------------------------ |
| OpenShift installer    | openshift-install-linux.tar.gz |
| Pull secret            | pull-secret.txt                |
| Command line interface | openshift-client-linux.tar.gz  |

ファイルは`/root/ocp`に格納するようにしています。

```sh
[root@bastion loft]# mkdir /root/ocp
[root@bastion loft]# mv /home/${USER}/Downloads/openshift-install-linux.tar.gz /root/ocp/
[root@bastion loft]# mv /home/${USER}/Downloads/pull-secret /root/ocp/
[root@bastion loft]# mv /home/${USER}/Downloads/openshift-client-linux.tar.gz /root/ocp/
[root@bastion loft]# cd /root/ocp/
[root@bastion ocp]# tar xvf openshift-install-linux.tar.gz
[root@bastion ocp]# tar zxvf openshift-client-linux.tar.gz
[root@bastion ocp]# ls -Fla
合計 598976
drwxr-xr-x. 2 root root       171 11月 15 11:48 ./
dr-xr-x---. 7 root root       264 11月 15 11:06 ../
-rw-r--r--. 1 root root       954 11月  1 01:23 README.md
-rwxr-xr-x. 2 root root  74528264 11月  1 01:23 kubectl*
-rwxr-xr-x. 2 root root  74528264 11月  1 01:23 oc*
-rw-rw-r--. 1 loft  loft   24316569 11月 15 11:19 openshift-client-linux.tar.gz
-rwxr-xr-x. 1 root root 353038336 11月  1 01:23 openshift-install*
-rw-r--r--. 1 loft  loft   86925136 11月 15 11:02 openshift-install-linux.tar.gz
-rw-r--r--. 1 loft  loft       2767 11月 15 11:02 pull-secret.txt
[root@bastion ocp]#
```

RHCOSのISOはESXiのdatastoreに格納します。
本手順書では、`rhcos-installer.x86_64.iso`を使用しています。(ISO名にバージョン番号は入らないようになったようです)。

なお、`Donwload RHCOS RAW`ボタンをクリックすると、`rhcos-metal.x86_64.raw.gz`をダウンロードできますが、本手順書では使用しません。(rawは使用しなくなったようです。)

## 1.1.7. バイナリーのダウンロードによる CLI のインストール

前章で実施済みです。

## 1.1.8. インストール設定ファイルの手動作成

`pullSecret`と`sshKey`の値を確認しておきます。

```log
[root@bastion ocp]# cat pull-secret
{"auths":{"cloud.openshift.com": ( 略 ),"email":"xxxxxx"}}}
[root@bastion ocp]# cat ~/.ssh/new_rsa.pub
ssh-rsa ( 略 ) == root@bastion
[root@bastion ocp]#
```

installation_directory(`/root/ocp/bare-metal`とした) を作成し、`install-config.yaml`を作成します。

`pullSecret`と`sshKey`の値は書き換えが必要です。

```log
[root@bastion ocp]# mkdir /root/ocp/bare-metal
[root@bastion ocp]# cd /root/ocp/bare-metal
[root@bastion bare-metal]# cat <<EOF > install-config.yaml
> apiVersion: v1
> baseDomain: example.local
> compute:
> - hyperthreading: Enabled
>   name: worker
>   replicas: 0
> controlPlane:
>   hyperthreading: Enabled
>   name: master
>   replicas: 3
> metadata:
>   name: test
> networking:
>   clusterNetworks:
>   - cidr: 10.128.0.0/14
>     hostPrefix: 23
>   networkType: OpenShiftSDN
>   serviceNetwork:
>   - 172.30.0.0/16
> platform:
>   none: {}
> fips: false
> pullSecret: '{"auths":{"cloud.openshift.com": ( 略 ),"email":"xxxxxx"}}}'
> sshKey: 'ssh-rsa ( 略 ) == root@bastion'
> EOF
[root@bastion bare-metal]# cat install-config.yaml
apiVersion: v1
baseDomain: example.local
compute:
- hyperthreading: Enabled
  name: worker
  replicas: 0
controlPlane:
  hyperthreading: Enabled
  name: master
  replicas: 3
metadata:
  name: test
networking:
  clusterNetworks:
  - cidr: 10.128.0.0/14
    hostPrefix: 23
  networkType: OpenShiftSDN
  serviceNetwork:
  - 172.30.0.0/16
platform:
  none: {}
fips: false
pullSecret: '{"auths":{"cloud.openshift.com": ( 略 ),"email":"xxxxxx"}}}'
sshKey: 'ssh-rsa ( 略 ) == root@bastion'
[root@bastion bare-metal]#
```

## 1.1.9. 3 ノードクラスターの設定

特に作業無し

## 1.1.10. Kubernetes マニフェストおよび Ignition 設定ファイルの作成

マニフェストを作成します。

```sh
[root@bastion ocp]# pwd
/root/ocp
[root@bastion ocp]#  ./openshift-install create manifests --dir=bare-metal
INFO Consuming Install Config from target directory
WARNING Making control-plane schedulable by setting MastersSchedulable to true for Scheduler cluster settings
INFO Manifests created in: bare-metal/manifests and bare-metal/openshift
[root@bastion ocp]#
[root@bastion ocp]# ls -Fla bare-metal/
合計 184
drwxr-xr-x. 4 root root    107 11月 15 12:14 ./
drwxr-xr-x. 3 root root    189 11月 15 11:54 ../
-rw-r--r--. 1 root root  24084 11月 15 12:14 .openshift_install.log
-rw-r-----. 1 root root 155141 11月 15 12:14 .openshift_install_state.json
drwxr-x---. 2 root root   4096 11月 15 12:14 manifests/
drwxr-x---. 2 root root   4096 11月 15 12:14 openshift/
[root@bastion ocp]# ls -Fla bare-metal/manifests/
合計 96
drwxr-x---. 2 root root 4096 11月 15 12:14 ./
drwxr-xr-x. 4 root root  107 11月 15 12:14 ../
-rw-r-----. 1 root root  169 11月 15 12:14 04-openshift-machine-config-operator.yaml
-rw-r-----. 1 root root 1596 11月 15 12:14 cluster-config.yaml
-rw-r-----. 1 root root  147 11月 15 12:14 cluster-dns-02-config.yml
-rw-r-----. 1 root root  422 11月 15 12:14 cluster-infrastructure-02-config.yml
-rw-r-----. 1 root root  152 11月 15 12:14 cluster-ingress-02-config.yml
-rw-r-----. 1 root root  513 11月 15 12:14 cluster-network-01-crd.yml
-rw-r-----. 1 root root  272 11月 15 12:14 cluster-network-02-config.yml
-rw-r-----. 1 root root  142 11月 15 12:14 cluster-proxy-01-config.yaml
-rw-r-----. 1 root root  170 11月 15 12:14 cluster-scheduler-02-config.yml
-rw-r-----. 1 root root  264 11月 15 12:14 cvo-overrides.yaml
-rw-r-----. 1 root root 1335 11月 15 12:14 etcd-ca-bundle-configmap.yaml
-rw-r-----. 1 root root 3958 11月 15 12:14 etcd-client-secret.yaml
-rw-r-----. 1 root root 4009 11月 15 12:14 etcd-metric-client-secret.yaml
-rw-r-----. 1 root root 1359 11月 15 12:14 etcd-metric-serving-ca-configmap.yaml
-rw-r-----. 1 root root 3917 11月 15 12:14 etcd-metric-signer-secret.yaml
-rw-r-----. 1 root root  156 11月 15 12:14 etcd-namespace.yaml
-rw-r-----. 1 root root  334 11月 15 12:14 etcd-service.yaml
-rw-r-----. 1 root root 1336 11月 15 12:14 etcd-serving-ca-configmap.yaml
-rw-r-----. 1 root root 3890 11月 15 12:14 etcd-signer-secret.yaml
-rw-r-----. 1 root root  118 11月 15 12:14 kube-cloud-config.yaml
-rw-r-----. 1 root root 1304 11月 15 12:14 kube-system-configmap-root-ca.yaml
-rw-r-----. 1 root root 4042 11月 15 12:14 machine-config-server-tls-secret.yaml
-rw-r-----. 1 root root 3841 11月 15 12:14 openshift-config-secret-pull-secret.yaml
[root@bastion ocp]# ls -Fla bare-metal/openshift/
合計 28
drwxr-x---. 2 root root 4096 11月 15 12:14 ./
drwxr-xr-x. 4 root root  107 11月 15 12:14 ../
-rw-r-----. 1 root root  181 11月 15 12:14 99_kubeadmin-password-secret.yaml
-rw-r-----. 1 root root 2458 11月 15 12:14 99_openshift-cluster-api_master-user-data-secret.yaml
-rw-r-----. 1 root root 2458 11月 15 12:14 99_openshift-cluster-api_worker-user-data-secret.yaml
-rw-r-----. 1 root root 1140 11月 15 12:14 99_openshift-machineconfig_99-master-ssh.yaml
-rw-r-----. 1 root root 1140 11月 15 12:14 99_openshift-machineconfig_99-worker-ssh.yaml
-rw-r-----. 1 root root  173 11月 15 12:14 openshift-install-manifests.yaml
[root@bastion ocp]#
```

`mastersSchedulable`を`false` とします。

```sh
[root@bastion ocp]# vim bare-metal/manifests/cluster-scheduler-02-config.yml
[root@bastion ocp]# cat bare-metal/manifests/cluster-scheduler-02-config.yml
apiVersion: config.openshift.io/v1
kind: Scheduler
metadata:
  creationTimestamp: null
  name: cluster
spec:
  mastersSchedulable: false
  policy:
    name: ""
status: {}
[root@bastion ocp]#
```

Ignition 設定ファイルを作成します。

```sh
[root@bastion ocp]# ./openshift-install create ignition-configs --dir=bare-metal
INFO Consuming Common Manifests from target directory
INFO Consuming Master Machines from target directory
INFO Consuming Openshift Manifests from target directory
INFO Consuming OpenShift Install (Manifests) from target directory
INFO Consuming Worker Machines from target directory
INFO Ignition-Configs created in: bare-metal and bare-metal/auth
[root@bastion ocp]# ls -Fla bare-metal/
合計 1632
drwxr-xr-x. 3 root root     163 11月 15 12:20 ./
drwxr-xr-x. 3 root root     189 11月 15 11:54 ../
-rw-r--r--. 1 root root   73257 11月 15 12:20 .openshift_install.log
-rw-r-----. 1 root root 1232701 11月 15 12:20 .openshift_install_state.json
drwxr-x---. 2 root root      50 11月 15 12:20 auth/
-rw-r-----. 1 root root  291737 11月 15 12:20 bootstrap.ign
-rw-r-----. 1 root root    1720 11月 15 12:20 master.ign
-rw-r-----. 1 root root      96 11月 15 12:20 metadata.json
-rw-r-----. 1 root root    1720 11月 15 12:20 worker.ign
[root@bastion ocp]# ls -Fla bare-metal/auth/
合計 16
drwxr-x---. 2 root root   50 11月 15 12:20 ./
drwxr-xr-x. 3 root root  163 11月 15 12:20 ../
-rw-r-----. 1 root root   23 11月 15 12:20 kubeadmin-password
-rw-r-----. 1 root root 8948 11月 15 12:20 kubeconfig
[root@bastion ocp]#
```

nginxの公開ディレクトリに配置します。


```sh
[root@bastion ocp]# mkdir /usr/share/nginx/html/ocp/rhcos/ignitions/ -p
[root@bastion ocp]# cp ./bare-metal/*.ign /usr/share/nginx/html/ocp/rhcos/ignitions/
[root@bastion ocp]# ls -Fla /usr/share/nginx/html/ocp/rhcos/ignitions/
合計 296
drwxr-xr-x. 2 root root     63 11月 15 12:24 ./
drwxr-xr-x. 4 root root     37 11月 15 11:41 ../
-rw-r-----. 1 root root 291737 11月 15 12:24 bootstrap.ign
-rw-r-----. 1 root root   1720 11月 15 12:24 master.ign
-rw-r-----. 1 root root   1720 11月 15 12:24 worker.ign
[root@bastion ocp]#
```

24時間の期限の証明書が含まれているので、24時間を超えて作業する場合はもう一度bare-metalディレクトリの削除、作成からやりなおす必要があるようです。

nginxからignファイルをGETできるか確認しておきます。
GETできない場合はnginx公開ディレクトリのパーミッション設定を行います。

```sh
[root@bastion ocp]# cd ~/
[root@bastion ~]# curl 172.16.0.1:8008/ocp/rhcos/ignitions/master.ign
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.14.1</center>
</body>
</html>
[root@bastion ~]# chmod o+r /usr/share/nginx/html/ -R
[root@bastion ~]# curl 172.16.0.1:8008/ocp/rhcos/ignitions/master.ign
{"ignition":{"config": ( 略 ) },"version":"3.1.0"}}[root@bastion ~]#
[root@bastion ~]#
```

## 1.1.11. Red Hat Enterprise Linux CoreOS (RHCOS) マシンの作成

### 1.1.11.1. ISO イメージを使用した Red Hat Enterprise Linux CoreOS (RHCOS) マシンの作成

それぞれのVMにISO(`rhcos-installer.x86_64.iso`)をマウントしておきます。

- bootstrap
- master-0
- master-1
- master-2
- worker-0
- worker-1

#### bootstrap VM の 起動

bootstrap の VM を起動します。CoreOSが起動し、コマンド待ち受け状態になることを確認します。
`coreos-installer install`コマンドに`bootstrap.ign`のURLを指定します。

```sh
# bootstrap の VM で実施
$ sudo coreos-installer install --ignition-url=http://172.16.0.1:8008/ocp/rhcos/ignitions/bootstrap.ign /dev/sda --insecure-ignition

# install complete と表示されたら再起動する( 備考 : 自動的に再起動はしなかったため、手動で実施した。 )
$ sudo reboot
```

再起動後、踏み台VM(bastion)からbootstarpにsshで入り、bootstrap処理の進行状況を表示しておきます。
( 最初は多数のエラーが目につくが、構築初期のエラーはあまり気にしなくてよいです。)

```log
[root@bastion loft]# ssh -i /root/.ssh/new_rsa core@bootstrap.test.example.local
Red Hat Enterprise Linux CoreOS 46.82.202010091720-0
  Part of OpenShift 4.6, RHCOS is a Kubernetes native operating system
  managed by the Machine Config Operator (`clusteroperator/machine-config`).

WARNING: Direct SSH access to machines is not recommended; instead,
make configuration changes via `machineconfig` objects:
  https://docs.openshift.com/container-platform/4.6/architecture/architecture-rhcos.html

---
This is the bootstrap node; it will be destroyed when the master is fully up.

The primary services are release-image.service followed by bootkube.service. To watch their status, run e.g.

  journalctl -b -f -u release-image.service -u bootkube.service
Last login: Sun Nov 15 04:12:21 2020 from 172.16.0.1
[core@bootstrap ~]$

[core@bootstrap ~]$ journalctl -b -f -u release-image.service -u bootkube.service
-- Logs begin at Sun 2020-11-15 04:04:49 UTC. --
Nov 15 04:08:37 bootstrap bootkube.sh[2455]: Created "configmap-admin-kubeconfig-client-ca.yaml" configmaps.v1./admin-kubeconfig-client-ca -n openshift-config
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: Created "configmap-initial-etcd-serving-ca.yaml" configmaps.v1./initial-etcd-ca -n openshift-config
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: [#102] failed to create some manifests:
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: "99_openshift-machineconfig_99-master-ssh.yaml": unable to get REST mapping for "99_openshift-machineconfig_99-master-ssh.yaml": n          o matches for kind "MachineConfig" in version "machineconfiguration.openshift.io/v1"
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: "99_openshift-machineconfig_99-worker-ssh.yaml": unable to get REST mapping for "99_openshift-machineconfig_99-worker-ssh.yaml": n          o matches for kind "MachineConfig" in version "machineconfiguration.openshift.io/v1"
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: [#103] failed to create some manifests:
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: "99_openshift-machineconfig_99-master-ssh.yaml": unable to get REST mapping for "99_openshift-machineconfig_99-master-ssh.yaml": n          o matches for kind "MachineConfig" in version "machineconfiguration.openshift.io/v1"
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: "99_openshift-machineconfig_99-worker-ssh.yaml": unable to get REST mapping for "99_openshift-machineconfig_99-worker-ssh.yaml": n          o matches for kind "MachineConfig" in version "machineconfiguration.openshift.io/v1"
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: Created "99_openshift-machineconfig_99-master-ssh.yaml" machineconfigs.v1.machineconfiguration.openshift.io/99-master-ssh -n
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: Created "99_openshift-machineconfig_99-worker-ssh.yaml" machineconfigs.v1.machineconfiguration.openshift.io/99-worker-ssh -n
```

#### master VM の 起動

同様に master の VMを1台ずつ起動していきます。

`master.ign`のURLを指定してインストールします。

```sh
# master の VM で実施
$ sudo coreos-installer install --ignition-url=http://172.16.0.1:8008/ocp/rhcos/ignitions/master.ign /dev/sda --insecure-ignition

# install complete と表示されたら再起動する( 備考 : 自動的に再起動はしなかったため、手動で実施した。 )
$ sudo reboot
```

#### worker VM の 起動

同様に worker の VMを1台ずつ起動していきます。

`worker.ign`のURLを指定してインストールします。

```sh
# master の VM で実施
$ sudo coreos-installer install --ignition-url=http://172.16.0.1:8008/ocp/rhcos/ignitions/worker.ign /dev/sda --insecure-ignition

# install complete と表示されたら再起動する( 備考 : 自動的に再起動はしなかったため、手動で実施した。 )
$ sudo reboot
```

## 1.1.12. クラスターの作成

bootstrap処理の進行状況に`bootkube.service complete`が表示されればOKです。これは1時間弱かかりました。

```sh
[core@bootstrap ~]$ journalctl -b -f -u release-image.service -u bootkube.service
-- Logs begin at Sun 2020-11-15 04:04:49 UTC. --
Nov 15 04:08:37 bootstrap bootkube.sh[2455]: Created "configmap-admin-kubeconfig-client-ca.yaml" configmaps.v1./admin-kubeconfig-client-ca -n openshift-config
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: Created "configmap-initial-etcd-serving-ca.yaml" configmaps.v1./initial-etcd-ca -n openshift-config
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: [#102] failed to create some manifests:
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: "99_openshift-machineconfig_99-master-ssh.yaml": unable to get REST mapping for "99_openshift-machineconfig_99-master-ssh.yaml": n          o matches for kind "MachineConfig" in version "machineconfiguration.openshift.io/v1"
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: "99_openshift-machineconfig_99-worker-ssh.yaml": unable to get REST mapping for "99_openshift-machineconfig_99-worker-ssh.yaml": n          o matches for kind "MachineConfig" in version "machineconfiguration.openshift.io/v1"
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: [#103] failed to create some manifests:
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: "99_openshift-machineconfig_99-master-ssh.yaml": unable to get REST mapping for "99_openshift-machineconfig_99-master-ssh.yaml": n          o matches for kind "MachineConfig" in version "machineconfiguration.openshift.io/v1"
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: "99_openshift-machineconfig_99-worker-ssh.yaml": unable to get REST mapping for "99_openshift-machineconfig_99-worker-ssh.yaml": n          o matches for kind "MachineConfig" in version "machineconfiguration.openshift.io/v1"
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: Created "99_openshift-machineconfig_99-master-ssh.yaml" machineconfigs.v1.machineconfiguration.openshift.io/99-master-ssh -n
Nov 15 04:08:38 bootstrap bootkube.sh[2455]: Created "99_openshift-machineconfig_99-worker-ssh.yaml" machineconfigs.v1.machineconfiguration.openshift.io/99-worker-ssh -n
( 略 )
Nov 15 05:00:21 bootstrap bootkube.sh[17079]: Skipped "cvo-overrides.yaml" clusterversions.v1.config.openshift.io/version -n openshift-cluster-version as it already exists
Nov 15 05:00:21 bootstrap bootkube.sh[17079]: Skipped "etcd-ca-bundle-configmap.yaml" configmaps.v1./etcd-ca-bundle -n openshift-config as it already exists
Nov 15 05:00:22 bootstrap bootkube.sh[17079]: Skipped "etcd-client-secret.yaml" secrets.v1./etcd-client -n openshift-config as it already exists
Nov 15 05:00:22 bootstrap bootkube.sh[17079]: Skipped "etcd-metric-client-secret.yaml" secrets.v1./etcd-metric-client -n openshift-config as it already exists
Nov 15 05:00:22 bootstrap bootkube.sh[17079]: Skipped "etcd-metric-serving-ca-configmap.yaml" configmaps.v1./etcd-metric-serving-ca -n openshift-config as it already exists
Nov 15 05:00:23 bootstrap bootkube.sh[17079]: Sending bootstrap-finished event.Tearing down temporary bootstrap control plane...
Nov 15 05:00:24 bootstrap bootkube.sh[17079]: Waiting for CEO to finish...
Nov 15 05:00:29 bootstrap bootkube.sh[17079]: I1115 05:00:29.772499       1 waitforceo.go:67] waiting on condition EtcdRunningInCluster in etcd CR /cluster to be True.
Nov 15 05:00:54 bootstrap bootkube.sh[17079]: I1115 05:00:54.071938       1 waitforceo.go:67] waiting on condition EtcdRunningInCluster in etcd CR /cluster to be True.
Nov 15 05:01:01 bootstrap bootkube.sh[17079]: I1115 05:01:01.076028       1 waitforceo.go:67] waiting on condition EtcdRunningInCluster in etcd CR /cluster to be True.
Nov 15 05:02:31 bootstrap bootkube.sh[17079]: I1115 05:02:31.511993       1 waitforceo.go:67] waiting on condition EtcdRunningInCluster in etcd CR /cluster to be True.
Nov 15 05:02:51 bootstrap bootkube.sh[17079]: I1115 05:02:51.213273       1 waitforceo.go:67] waiting on condition EtcdRunningInCluster in etcd CR /cluster to be True.
Nov 15 05:03:19 bootstrap bootkube.sh[17079]: I1115 05:03:19.621074       1 waitforceo.go:67] waiting on condition EtcdRunningInCluster in etcd CR /cluster to be True.
Nov 15 05:03:31 bootstrap bootkube.sh[17079]: I1115 05:03:31.838247       1 waitforceo.go:67] waiting on condition EtcdRunningInCluster in etcd CR /cluster to be True.
Nov 15 05:03:31 bootstrap bootkube.sh[17079]: I1115 05:03:31.891774       1 waitforceo.go:67] waiting on condition EtcdRunningInCluster in etcd CR /cluster to be True.
Nov 15 05:03:40 bootstrap bootkube.sh[17079]: I1115 05:03:40.380992       1 waitforceo.go:64] Cluster etcd operator bootstrapped successfully
Nov 15 05:03:40 bootstrap bootkube.sh[17079]: I1115 05:03:40.381071       1 waitforceo.go:58] cluster-etcd-operator bootstrap etcd
Nov 15 05:03:40 bootstrap bootkube.sh[17079]: bootkube.service complete
```

踏み台サーバー上で、ブートストラップの完了待ちコマンドを実行します。
`It is now safe to remove the bootstrap resources`が表示されればOKです。

```sh
[root@bastion ocp]# ./openshift-install --dir=bare-metal wait-for bootstrap-complete --log-level=debug
DEBUG OpenShift Installer 4.6.3
DEBUG Built from commit a4f0869e0d2a5b2d645f0f28ef9e4b100fa8f779
INFO Waiting up to 20m0s for the Kubernetes API at https://api.test.example.local:6443...
INFO API v1.19.0+9f84db3 up
INFO Waiting up to 30m0s for bootstrapping to complete...
DEBUG Bootstrap status: complete
INFO It is now safe to remove the bootstrap resources
INFO Time elapsed: 0s
[root@bastion ocp]#
```

## 1.1.13. クラスターへのログイン

```sh
[root@bastion ocp]# pwd
/root/ocp
[root@bastion ocp]# export KUBECONFIG=bare-metal/auth/kubeconfig
[root@bastion ocp]# ./oc -h
OpenShift Client

This client helps you develop, build, deploy, and run your applications on any
OpenShift or Kubernetes cluster. It also includes the administrative
commands for managing a cluster under the 'adm' subcommand.

Usage:
  oc [flags]

Basic Commands:
  login           Log in to a server
  new-project     Request a new project
  new-app         Create a new application
  status          Show an overview of the current project
  project         Switch to another project
  projects        Display existing projects
  explain         Documentation of resources

Build and Deploy Commands:
  rollout         Manage a Kubernetes deployment or OpenShift deployment config
  rollback        Revert part of an application back to a previous deployment
  new-build       Create a new build configuration
  start-build     Start a new build
  cancel-build    Cancel running, pending, or new builds
  import-image    Imports images from a container image registry
  tag             Tag existing images into image streams

Application Management Commands:
  create          Create a resource from a file or from stdin.
  apply           Apply a configuration to a resource by filename or stdin
  get             Display one or many resources
  describe        Show details of a specific resource or group of resources
  edit            Edit a resource on the server
  set             Commands that help set specific features on objects
  label           Update the labels on a resource
  annotate        Update the annotations on a resource
  expose          Expose a replicated application as a service or route
  delete          Delete resources by filenames, stdin, resources and names, or by resources and label selector
  scale           Set a new size for a Deployment, ReplicaSet or Replication Controller
  autoscale       Autoscale a deployment config, deployment, replica set, stateful set, or replication controller
  secrets         Manage secrets
  serviceaccounts Manage service accounts in your project

Troubleshooting and Debugging Commands:
  logs            Print the logs for a container in a pod
  rsh             Start a shell session in a container.
  rsync           Copy files between local filesystem and a pod
  port-forward    Forward one or more local ports to a pod
  debug           Launch a new instance of a pod for debugging
  exec            Execute a command in a container
  proxy           Run a proxy to the Kubernetes API server
  attach          Attach to a running container
  run             Run a particular image on the cluster
  cp              Copy files and directories to and from containers.
  wait            Experimental: Wait for a specific condition on one or many resources.

Advanced Commands:
  adm             Tools for managing a cluster
  replace         Replace a resource by filename or stdin
  patch           Update field(s) of a resource using strategic merge patch
  process         Process a template into list of resources
  extract         Extract secrets or config maps to disk
  observe         Observe changes to resources and react to them (experimental)
  policy          Manage authorization policy
  auth            Inspect authorization
  convert         Convert config files between different API versions
  image           Useful commands for managing images
  registry        Commands for working with the registry
  idle            Idle scalable resources
  api-versions    Print the supported API versions on the server, in the form of "group/version"
  api-resources   Print the supported API resources on the server
  cluster-info    Display cluster info
  diff            Diff live version against would-be applied version
  kustomize       Build a kustomization target from a directory or a remote url.

Settings Commands:
  logout          End the current server session
  config          Modify kubeconfig files
  whoami          Return information about the current session
  completion      Output shell completion code for the specified shell (bash or zsh)

Other Commands:
  ex              Experimental commands under active development
  help            Help about any command
  plugin          Provides utilities for interacting with plugins.
  version         Print the client and server version information

Use "oc <command> --help" for more information about a given command.
Use "oc options" for a list of global command-line options (applies to all commands).
[root@bastion ocp]#
[root@bastion ocp]# ./oc whoami
system:admin
[root@bastion ocp]#
```

## 1.1.14. マシンの CSR の承認

起動直後はmasterノードのみでworkerノードは見えなかったです。
表示されるcsrも少なく、`Pending`のものが見えてこないので、少々待つ必要があるかもしれません( `watch ./oc get csr` で監視すると良い。) 。
しばらくすると`Pending`のcsrが見えるようになりました。

`Pending`のcsrに対して`./oc adm certificate approve <NAME>`を実行します。
approveすると、引き続き`Pending`のcsrが表示されるようになるので、適宜approveしていきます。

approveが終わると、workerノードも見えるようになりました。
NotReadyのノードもしばらくするとReadyとなりました。

```sh
[root@bastion ocp]# ./oc get no
NAME       STATUS     ROLES    AGE   VERSION
master-0   Ready      master   63m   v1.19.0+9f84db3
master-1   Ready      master   36m   v1.19.0+9f84db3
master-2   Ready      master   31m   v1.19.0+9f84db3
worker-0   NotReady   worker   44s   v1.19.0+9f84db3
worker-1   NotReady   worker   62s   v1.19.0+9f84db3
[root@bastion ocp]#
[root@bastion ocp]# ./oc get csr
NAME        AGE     SIGNERNAME                                    REQUESTOR                                                                   CONDITION
csr-5wghd   34m     kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Approved,Issued
csr-797h4   9m38s   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending
csr-8tlmj   30m     kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Approved,Issued
csr-f2jdl   29m     kubernetes.io/kubelet-serving                 system:node:master-2                                                        Approved,Issued
csr-lbwcg   34m     kubernetes.io/kubelet-serving                 system:node:master-1                                                        Approved,Issued
csr-mfntj   9m13s   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending
csr-smzlr   62m     kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Approved,Issued
csr-wj6xk   61m     kubernetes.io/kubelet-serving                 system:node:master-0                                                        Approved,Issued
[root@bastion ocp]#
[root@bastion ocp]#
[root@bastion ocp]# ./oc adm certificate approve csr-797h4
certificatesigningrequest.certificates.k8s.io/csr-797h4 approved
[root@bastion ocp]# ./oc adm certificate approve csr-mfntj
certificatesigningrequest.certificates.k8s.io/csr-mfntj approved
[root@bastion ocp]# ./oc adm certificate approve csr-dfj47
certificatesigningrequest.certificates.k8s.io/csr-dfj47 approved
certificatesigningrequest.certificates.k8s.io/csr-px8f9 approved
[root@bastion ocp]# ./oc get csr
NAME        AGE   SIGNERNAME                                    REQUESTOR                                                                   CONDITION
csr-5wghd   37m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Approved,Issued
csr-797h4   12m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Approved,Issued
csr-8tlmj   32m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Approved,Issued
csr-dfj47   98s   kubernetes.io/kubelet-serving                 system:node:worker-1                                                        Approved,Issued
csr-f2jdl   32m   kubernetes.io/kubelet-serving                 system:node:master-2                                                        Approved,Issued
csr-lbwcg   37m   kubernetes.io/kubelet-serving                 system:node:master-1                                                        Approved,Issued
csr-mfntj   11m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Approved,Issued
csr-px8f9   80s   kubernetes.io/kubelet-serving                 system:node:worker-0                                                        Approved,Issued
csr-smzlr   64m   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Approved,Issued
csr-wj6xk   64m   kubernetes.io/kubelet-serving                 system:node:master-0                                                        Approved,Issued
[root@bastion ocp]#
```

## 1.1.15. Operator の初期設定

全ての`AVAILABLE` が `TRUE`、`DEGRADED`が`FALSE`になればOKです。
この処理も数十分かかるようです。

```sh
[root@bastion ocp]# ./oc get clusteroperators
NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE
authentication                             4.6.3     False       True          True       71m
cloud-credential                           4.6.3     True        False         False      88m
cluster-autoscaler                         4.6.3     True        False         False      68m
config-operator                            4.6.3     True        False         False      72m
console                                    4.6.3     False       True          True       102s
csi-snapshot-controller                    4.6.3     True        False         False      4m28s
dns                                        4.6.3     True        False         False      65m
etcd                                       4.6.3     True        False         False      41m
image-registry                             4.6.3     True        False         False      28m
ingress                                    4.6.3     True        False         False      7m41s
insights                                   4.6.3     True        False         False      71m
kube-apiserver                             4.6.3     True        True          True       30m
kube-controller-manager                    4.6.3     True        False         False      66m
kube-scheduler                             4.6.3     True        False         False      67m
kube-storage-version-migrator              4.6.3     True        False         False      7m4s
machine-api                                4.6.3     True        False         False      67m
machine-approver                           4.6.3     True        False         False      66m
machine-config                             4.6.3     True        False         False      66m
marketplace                                4.6.3     True        False         False      67m
monitoring                                           False       True          True       64m
network                                    4.6.3     True        False         False      73m
node-tuning                                4.6.3     True        False         False      70m
openshift-apiserver                        4.6.3     True        False         False      28m
openshift-controller-manager               4.6.3     True        False         False      66m
openshift-samples                          4.6.3     True        False         False      26m
operator-lifecycle-manager                 4.6.3     True        False         False      68m
operator-lifecycle-manager-catalog         4.6.3     True        False         False      66m
operator-lifecycle-manager-packageserver   4.6.3     True        False         False      2m51s
service-ca                                 4.6.3     True        False         False      71m
storage                                    4.6.3     True        False         False      72m
[root@bastion ocp]# ./oc get clusteroperators
NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE
authentication                             4.6.3     False       False         True       74m
cloud-credential                           4.6.3     True        False         False      91m
cluster-autoscaler                         4.6.3     True        False         False      71m
config-operator                            4.6.3     True        False         False      74m
console                                    4.6.3     True        False         False      66s
csi-snapshot-controller                    4.6.3     True        False         False      7m11s
dns                                        4.6.3     True        False         False      68m
etcd                                       4.6.3     True        False         False      43m
image-registry                             4.6.3     True        False         False      31m
ingress                                    4.6.3     True        False         False      10m
insights                                   4.6.3     True        False         False      74m
kube-apiserver                             4.6.3     True        True          False      32m
kube-controller-manager                    4.6.3     True        False         False      68m
kube-scheduler                             4.6.3     True        False         False      70m
kube-storage-version-migrator              4.6.3     True        False         False      9m47s
machine-api                                4.6.3     True        False         False      70m
machine-approver                           4.6.3     True        False         False      69m
machine-config                             4.6.3     True        False         False      69m
marketplace                                4.6.3     True        False         False      70m
monitoring                                 4.6.3     True        False         False      31s
network                                    4.6.3     True        False         False      75m
node-tuning                                4.6.3     True        False         False      73m
openshift-apiserver                        4.6.3     True        False         False      31m
openshift-controller-manager               4.6.3     True        False         False      69m
openshift-samples                          4.6.3     True        False         False      29m
operator-lifecycle-manager                 4.6.3     True        False         False      70m
operator-lifecycle-manager-catalog         4.6.3     True        False         False      69m
operator-lifecycle-manager-packageserver   4.6.3     True        False         False      5m34s
service-ca                                 4.6.3     True        False         False      74m
storage                                    4.6.3     True        False         False      75m
[root@bastion ocp]#
[root@bastion ocp]# ./oc get clusteroperators
NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE
authentication                             4.6.3     True        False         False      27s
cloud-credential                           4.6.3     True        False         False      95m
cluster-autoscaler                         4.6.3     True        False         False      75m
config-operator                            4.6.3     True        False         False      79m
console                                    4.6.3     True        False         False      5m22s
csi-snapshot-controller                    4.6.3     True        False         False      11m
dns                                        4.6.3     True        False         False      72m
etcd                                       4.6.3     True        False         False      48m
image-registry                             4.6.3     True        False         False      35m
ingress                                    4.6.3     True        False         False      14m
insights                                   4.6.3     True        False         False      78m
kube-apiserver                             4.6.3     True        False         False      37m
kube-controller-manager                    4.6.3     True        False         False      73m
kube-scheduler                             4.6.3     True        False         False      74m
kube-storage-version-migrator              4.6.3     True        False         False      14m
machine-api                                4.6.3     True        False         False      74m
machine-approver                           4.6.3     True        False         False      73m
machine-config                             4.6.3     True        False         False      73m
marketplace                                4.6.3     True        False         False      74m
monitoring                                 4.6.3     True        False         False      4m47s
network                                    4.6.3     True        False         False      80m
node-tuning                                4.6.3     True        False         False      77m
openshift-apiserver                        4.6.3     True        False         False      35m
openshift-controller-manager               4.6.3     True        False         False      73m
openshift-samples                          4.6.3     True        False         False      33m
operator-lifecycle-manager                 4.6.3     True        False         False      75m
operator-lifecycle-manager-catalog         4.6.3     True        False         False      73m
operator-lifecycle-manager-packageserver   4.6.3     True        False         False      9m50s
service-ca                                 4.6.3     True        False         False      78m
storage                                    4.6.3     True        False         False      79m
[root@bastion ocp]#
```

## 1.1.16. ユーザーによってプロビジョニングされるインフラストラクチャーでのインストールの完了

`Install complete!`と表示され、パスワード等の情報が表示されればOKです。

```sh
[root@bastion ocp]# ./openshift-install --dir=bare-metal wait-for install-complete --log-level=info
INFO Waiting up to 40m0s for the cluster at https://api.test.example.local:6443 to initialize...
INFO Waiting up to 10m0s for the openshift-console route to be created...
INFO Install complete!
INFO To access the cluster as the system:admin user when using 'oc', run 'export KUBECONFIG=/root/ocp/bare-metal/auth/kubeconfig'
INFO Access the OpenShift web-console here: https://console-openshift-console.apps.test.example.local
INFO Login to the console with user: "kubeadmin", and password: "hNfq3-eLfje-6Nw2N-eFMiN"
INFO Time elapsed: 2m26s
[root@bastion ocp]#
```

### WebUIの確認

踏み台サーバーでブラウザを起動し、`https://console-openshift-console.apps.test.example.local`にアクセスしてみます。
WebUIが表示され、ログインできればOKです。

ユーザ名、パスワードは`wait-for install-complete`コマンド実行結果に表示されています。

![192.168.3.100_ui_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/45814db2-bdc6-e487-26ab-c258d2767fab.png)

## 1.1.17. 次のステップ

インストールは終了です、お疲れさまでした。
ここまで、OpenShift 4.6 のベアメタルへのUPIインストール手順をご紹介しました。
おうちKubernetes・OpenShiftを活用していきたいですね。