OpenShiftを爆速でインストールしたいあなたへ

本記事は、[赤帽エンジニア Advent Calendar 2019](https://qiita.com/advent-calendar/2019/rh_engineers) の22日目です。

# はじめに

ここでは余っているサーバーがあるからOpenShiiftをまず使ってみたいといった方を対象に爆速でインストールできる方法を紹介します。

今回ご紹介する手順ではOpenShift 4.2を前提としています。

まず、OpenShiftをオンプレミスで使おうとした時に、利用される方法は下記の選択肢になると思います。

- Baremetal UPI / IPI
- OpenShift on OpenStack
- OpenShift on VMware

私はOpenStackerなので、とりあえずサーバーが3台余っていればOpenStackたてちゃうか、、、って感じなのですが、OpenShiftを構築するためにOpenStackを構築する人はそんなにいないと思ったので、まずOpenShift on OpenStackは除外します。

後、VMwareに関してはライセンスが等々あるので、と言うことでBaremetal UPI/IPIのどちらかを選択することにします。

次にUPI/IPIの説明をさせていただきます。

# UPI/IPI

IPIとは**Installer Provisioned Infrastructure**の略称です。

一般的にOpenStackやOpenShiftのようなクラスタをスケールアップさせてくようなインフラではPXE bootのような技術が必須となります、せっかくスケールアウトができるアーキテクチャーのアプリケーションでもそれを支えるインフラ基盤がないと意味がないからですね。

そこで、IPIではOpenShiftに必要なDNSであったり、PXE bootサーバーであったりがまるっとパッケージで提供される形になります。

一方UPIとは**User Provisioned Infrastructure**の略称でユーザー自身がDNSやPXE bootサーバーを提供する形になります。

どちらをやっても良かったのですが、せっかくなので内部構造や要件を知ってもらう為にも今回はUPIインストールを選択します。

あとは、個人的な意見ではありますが、すでにDCでのサーバー管理や、プロビジョニングのナレッジがある会社にとってはUPIの方が今あるシステムにインテグレーションしやすいのかなと思います。

# アーキテクチャ

![Architecture](https://github.com/konono/openshift-fast-install/blob/master/img/OpenShift_upi_architecture.png?raw=true)

基本的には[OpenShift 4.1をベアメタルへUPIインストールする](https://rheb.hatenablog.com/entry/openshift41-baremetal-upi)を参考にして今回の記事を書きました。

ただ、それでは面白くないので4.2に対応したことと、爆速でインストールできるように少し環境を工夫をしました。

- **爆速ポイントその1**: master, worker,bootstrapをVMでたてる

え？VMにしただけじゃん？って思われれましたか？違うんです！爆速インストールを前提に考えた結果だからこそ、意味があるんです！実際、HWのマシンのブート待ってたら日が暮れてしまいます。

- **爆速ポイントその2**: PXE bootを使う

この参考にした手順を見ていただけるとわかるのですが、Boot時に起動する為のbiosファイルやIgnitionファイルの指定を手で5台分打たなきゃいけないのが辛すぎるのでPXE bootにしました。

- **爆速ポイントその3**: 仮想化にすることでネットワークを固定化する

今回その1でVMでたてることで、ノード自体の起動を高速化しましたが、もう一つの恩恵としてネットワークが自由に切れるので最初から172.16.0.0/24をどんな環境でも決め打ちで使えることで設計の手間をなくすことができました。

- **爆速ポイントその4**: 手順はシェルスクリプトでできている

体は剣で出来ているではないですが、シェルスクリプトで手順が作られています、いんふらあずあこーどってやつですね()

ポチポチする部分が少ないのと、仮想環境で設定が決め打ちできる為シェルスクリプト化しやすかったのは爆速化の大きなポイントです。

同僚に「それがAnsible playbookになったら使ってやってもいい」って言われたんですよ、ほんとその通りだと思いますし、Ansible playbookにしようと思ったんですがタイムアップです、、、ごめんなさいごめんなさい。

一応年末の休みに作って、ここをアップデートする予定です。

- **爆速ポイントその5**: 使うミドルウェアを工夫して設定ポイントを減らしました

具体的には今回使っているソフトウェアスタックとしては下記のようになっています。

- iPXE
- nginx
- CoreDNS
- libvirt

今回は出来るだけこの子たちのできることをフル活用するし、過不足なく機能を使うことも目的の一つとしています。

まずはiPXEを使うことでHTTPでもPXE bootできるようになるのでTFTPサーバーを構築する手間を省くことができました。

また、WEBサーバーとしてnginxを採用したにもきちんと理由があります。

もちろんiPXEで必要なWEBサーバーを提供することもそうなのですが、あともう一つ大きな採用理由があります。

それがLoad balancerです。

いつからか利用できるようになったngx_stream_core_moduleを利用してLoad BalanceさせることでHAProxyの利用も必要がなくなりました。

Libvirtではnetwork domain xmlファイルを使うことでDestination NATとPXE用のDHCPのconfigurationを実施してくれるので活用することにしました。

本当はLibvirtから利用できるdnsmasqを使ってDNSの部分も別途のDNSサーバーの設定の手間も省略しようとしたのですが、ワイルドカードDNSレコードだけがLibvirt経由でconfigurationできないことがわかり、CoreDNSに逃げました。

https://bugzilla.redhat.com/show_bug.cgi?id=1532856

一応、Libvirt 5.6.0で対応するらしいので、そうなったらさらに爆速になります。

# インストール要件

こちらも[OpenShift 4.1をベアメタルへUPIインストールする](https://rheb.hatenablog.com/entry/openshift41-baremetal-upi)を ~~パクって~~参考にしています。

田中さん本当にありがとうございます。

### ノード

| マシン         | 台数 | OS    | vCPU | RAM  | ストレージ | 備考                      |
| -------------- | ---- | ----- | ---- | ---- | ---------- | ------------------------- |
| Bootstrap Node | 1    | RHCOS | 4    | 16GB | 120GB      | UPIインストール時のみ必要 |
| Master Node    | 3    | RHCOS | 4    | 16GB | 120GB      | 3台必須                   |
| Worker Node    | 2    | RHCOS | 2    | 8GB  | 120GB      | 2台以上                   |

### DHCP

| マシン         | ホスト名                                                     | IPアドレス                             | サブネットマスク | ゲートウェイ | DNSサーバー |
| -------------- | ------------------------------------------------------------ | -------------------------------------- | ---------------- | ------------ | ----------- |
| Bootstrap Node | bootstrap.test.lab.local                                     | 172.16.0.100                           | 255.255.255.0    | 172.16.0.1   | 172.16.0.1  |
| Master Node    | master-0.test.lab.local master-1.test.lab.local master-2.test.lab.local | 172.16.0.101 172.16.0.102 172.16.0.103 | 255.255.255.0    | 172.16.0.1   | 172.16.0.1  |
| Worker Node    | worker-0.test.lab.local worker-1.test.lab.local              | 172.16.0.104 172.16.0.105              | 255.255.255.0    | 172.16.0.1   | 172.16.0.1  |

### DNSレコード

下記の指定されたレコードの名前解決が必須です。

| コンポーネント | レコード                            | 対象ノード       |
| -------------- | ----------------------------------- | ---------------- |
| Kubernetes API | `api..` `api-int..`                 | Bootstrap,Master |
| Routes         | `*.apps..`                          | Worker           |
| etcd           | `etcd-..` `_etcd-server-ssl._tcp..` | Master           |

検証環境で登録したDNSの設定例は下記のようになります。

| ホスト名                 | IPアドレス    | 備考                                                         |
| ------------------------ | ------------- | ------------------------------------------------------------ |
| `api.test.lab.local`     | 10.64.200.111 | LBの外側アドレスを指定                                       |
| `api-int.test.lab.local` | 172.16.0.1    | LBの内側アドレスを指定                                       |
| `*.apps.test.lab.local`  | 172.16.0.1    | LBの内側アドレスを指定。ワイルドカードDNSレコード。          |
| `etcd-0.test.lab.local`  | 172.16.0.101  | システム内部でetcd-0,1,2で固定名で名前解決を行うので、 Master Nodeのホスト名とは別で登録必要 |
| `etcd-1.test.lab.local`  | 172.16.0.102  | 同上                                                         |
| `etcd-2.test.lab.local`  | 172.16.0.103  | 同上                                                         |

| レコード                               | 優先度 | 重み | ポート | DNS名                 |
| -------------------------------------- | ------ | ---- | ------ | --------------------- |
| `_etcd-server-ssl._tcp.test.lab.local` | 0      | 10   | 2380   | etcd-0.test.lab.local |
| `_etcd-server-ssl._tcp.test.lab.local` | 0      | 10   | 2380   | etcd-1.test.lab.local |
| `_etcd-server-ssl._tcp.test.lab.local` | 0      | 10   | 2380   | etcd-2.test.lab.local |

### LB

下記のポート番号のロードバランサーが必要です

| 用途                             | ポート番号 | 対象ノード       |
| -------------------------------- | ---------- | ---------------- |
| Kubernetes APIServer             | 6443       | Bootstrap,Master |
| マシン設定サーバー               | 22623      | Bootstrap,Master |
| ingressルーターのhttpアクセス用  | 80         | Worker           |
| ingressルーターのhttpsアクセス用 | 443        | Worker           |

検証環境で登録したLoad Balancerの設定は下記のようになります

| ポート番号 | SSL     | バックエンド                                                 |
| ---------- | ------- | ------------------------------------------------------------ |
| 6443       | **Yes** | bootstrap.test.lab.local master-0.test.lab.local master-1.test.lab.local master-2.test.lab.local |
| 22623      | -       | bootstrap.test.lab.local master-0.test.lab.local master-1.test.lab.local master-2.test.lab.local |
| 80         | -       | worker-0.test.lab.local worker-1.test.lab.local      |
| 443        | **Yes** | worker-0.test.lab.local worker-1.test.lab.local      |

### WEBサーバー

ディレクトリ構造としては下記のようになっています。

```
[root@ksawada nginx]# tree
.
|-- html
|   |-- ipxe
|   |   |-- boot.ipxe
|   |   |-- rhcos-4.2.0-x86_64-installer-initramfs.img
|   |   `-- rhcos-4.2.0-x86_64-installer-kernel
|   |-- ocp
|   |   `-- rhcos
|   |       |-- ignitions
|   |       |   |-- bootstrap.ign
|   |       |   |-- master.ign
|   |       |   `-- worker.ign
|   |       `-- images
|   |           |-- latest
|   |           |   `-- bios.raw.gz
```

# インストール手順

シェルスクリプトは下記URLからgit cloneし、あとは01-10までのシェルを叩くだけで、インストールは完了します。

```
git clone https://github.com/konono/openshift-fast-install
```

しかし、いけていない部分があるので、そこだけconfファイルの修正をお願いします、

Ansible化した後に変数化しようとしていたところなのですが、、、間に合わずすみません。

ocp.xml

```
<network>
  <name>ocp</name>
  <bridge name='ocp0' stp='yes' delay='0'/>
  <forward dev='eno1' mode='nat'> <--devをインターネットに疎通性のあるIF nameに書き換えてください
    <nat>
      <port start='1024' end='65535'/>
    </nat>
    <interface dev='eno1'/> <--devをインターネットに疎通性のあるIF nameに書き換えてください
  </forward>
  <ip address='172.16.0.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='172.16.0.2' end='172.16.0.254'/>
      <bootp file='http://172.16.0.1:8000/ipxe/boot.ipxe'/>
      <host mac='52:54:00:00:01:01' ip='172.16.0.100' name='bootstrap.test.lab.local'/>.
      <host mac='52:54:00:00:01:02' ip='172.16.0.101' name='master-0.test.lab.local'/>.
      <host mac='52:54:00:00:01:03' ip='172.16.0.102' name='master-1.test.lab.local'/>.
      <host mac='52:54:00:00:01:04' ip='172.16.0.103' name='master-2.test.lab.local'/>.
      <host mac='52:54:00:00:01:05' ip='172.16.0.104' name='worker-0.test.lab.local'/>.
      <host mac='52:54:00:00:01:06' ip='172.16.0.105' name='worker-1.test.lab.local'/>.
    </dhcp>
  </ip>
</network>
```

etc_conf/coredns/Corefile

```
.:53 {
    forward . 10.68.5.26:53 10.64.255.25:53 {
        except lab.local mydomain.com
        policy round_robin
    }
    bind 10.64.200.111 <--- BindIPを自分のマシンのIPに書き換えてください
    errors
    log
}

lab.local {
    file /etc/coredns/zones/db.lab.local
    bind 10.64.200.111 <--- BindIPを自分のマシンのIPに書き換えてください
    errors
    log
}
172.16.0.0/24 {
    file /etc/coredns/zones/db.172.16.0
    bind 10.64.200.111 <--- BindIPを自分のマシンのIPに書き換えてください
    errors
    log
}

10.64.200.0/23 { <--- BindIPを自分のマシンのIPに書き換えてください
    file /etc/coredns/zones/db.10.64.200 <--- BindIPを自分のマシンのIPに書き換えてください
    bind 10.64.200.111 <--- BindIPを自分のマシンのIPに書き換えてください
    errors
    log
}
```

etc_conf/coredns/zones/db.10.64.200 <---自分のマシンのセグメントに合わせてください

06_setup_openshift_install-config.sh

```
#!/bin/bash
rm -rf ./bare-metal
mkdir -p ./bare-metal
cat << EOF > /root/install-config.yaml
apiVersion: v1
baseDomain: lab.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: {}
pullSecret: '' <---ここはhttps://cloud.redhat.com/openshift/install/metal/user-provisionedにアクセスし、Copy Pull Secretを押してその内容をシングルクォートの中に入れてください
sshKey: ''　<---ここ自分の公開鍵を入力してください
EOF

cp -p /root/install-config.yaml /root/openshift-fast-install/bare-metal/
curl -LO https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/openshift-install-linux-4.2.10.tar.gz
tar zxvf openshift-install-linux-4.2.10.tar.gz
./openshift-install create ignition-configs --dir=bare-metal
rm -rf /usr/share/nginx/html/ocp/rhcos/ignitions/*
cp -p ./bare-metal/*.ign /usr/share/nginx/html/ocp/rhcos/ignitions/

```

ここまでできればあとは順番にshellを叩くだけで爆速で完成します！

各スクリプトでやっている説明は以下です。

- **01_setup_libvirtd.sh**
  - Libvirtのインストールと、virt-installコマンドのインストール、cop.xmlのデプロイを実施します
- **02_setup_firewalld.sh**
  - 利用するポートをfirewallに許可させます
- **03_install_coredns.sh**
  - CoreDNSのインストールと、systemdの起動スクリプト、設定ファイルをデプロイします
- **04_install_nginx.sh**
  - nginxのインストール、設定、ディレクトリの作成を行います
- **05_setup_ipxe.sh**
  - ipxeの設定ファイルの作成と、ipxeに必要なファイルのダウンロードが行われます
- **06_setup_openshift_install-config.sh**
  - openshift-installコマンドのダウンロードと、必要なiginitionファイルの作成、配置を行います
- **07_install_bootstrap.sh**
  - Bootstrapノードの仮想マシンの作成を行います、ここで作った後に**virsh console bootstrap**を打ち、ipxeの画面で**b**ボタンを押してbootstrapのインストールを選択してください
- **08_install_master.sh**
  - Masterノードの仮想マシンの作成を行います、ここで作った後に**virsh console master-x**を打ち、ipxeの画面で**m**ボタンを押してbootstrapのインストールを選択してください
- **09_install_worker.sh**
  - Workerノードの仮想マシンの作成を行います、ここで作った後に**virsh console worker-x**を打ち、ipxeの画面で**w**ボタンを押してbootstrapのインストールを選択してください
- **10_setup_oc_command.sh**
  - Install後のocコマンドのダウンロードとインストールを実施します

ね？簡単でしょ。

07-09の手順は少しわかりづらいですよね、ここは爆速とは程遠い実装になっているので後々修正します。

これらの手順が終わったら、下記コマンドでインストール状況の確認を行います。

```
openshift-install --dir=bare-metal wait-for bootstrap-complete
```

下記のような表示が得られればインストールは無事完了です。

```
 openshift-install --dir=bare-metal wait-for bootstrap-complete 
INFO Waiting up to 30m0s for the Kubernetes API at https://api.test.example.local:6443... 
INFO API v1.13.4+d4417a7 up                       
INFO Waiting up to 30m0s for bootstrapping to complete... 
INFO It is now safe to remove the bootstrap resources 
```

その後は下記コマンドで、動作確認を実施します。

```
$ export KUBECONFIG=bare-metal/auth/kubeconfig

$ oc whoami
system:admin
```

後の残りは下記のURLの**2.c マシンの CSR の承認**以降の手順に従ってクラスタのチェックを行ってください。
https://rheb.hatenablog.com/entry/openshift41-baremetal-upi

いかがでしたでしょうか。
爆速でインストールできなかったらクレーム入れますって言ってた同僚の方もいたので、甘んじて受けれようと思っています(諦観)

時間があればansible化と、ipxeのノード選択をスキップする手順ができたのですが、今日はここまでです。

ありがとうございました、引き続き、赤帽アドベントカレンダーをおたのしみください！