Power Systems Virtual ServerへのOpenShift 4.7導入(2): bastionノード等の構成

# はじめに
この記事では、Power Systems Virtual Server(以下PowerVS)へのOpenShift 4.7導入に際してbastionノード等の構成を実施します。OpenShiftは「openshift-install」コマンドでUPIインストールします。UPIインストールには、master/worker/bootstrapノードをPXE起動して、bastionノード上のRHCOSイメージファイルやignitionファイルからOpenShiftを導入する方法があります。PowerVSの仮想サーバー・インスタンスはPXEブートできませんが、bastionノードを対象にbootpで起動すればPXE同様の方法とすることが可能です。
![01_custom.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413476/3abcd3ca-97bc-7675-d75c-c94ccdd44bf4.png)
bastionノードの主な機能はWebサーバー、DNSサーバー、bootp起動対応と負荷分散です。これらは、IBM Cloudサービスで代替可能かもしれませんが、ここではすべての機能をbastionノードに集約しています。なお、実稼働環境を想定した冗長化は行っていません。

■ PXEを利用したOpenShift導入

https://rheb.hatenablog.com/entry/rhcos-matchbox

# 1. RHCOS 4.7 ブート・イメージの作成
## 1.1. ツールの準備
ppc64le版のpvsadmをcentos 8.3(ppc64le)のbastionノードに導入します。

```bash:bastionノード
curl -sL https://github.com/ppc64le-cloud/pvsadm/releases/download/v0.1/pvsadm-linux-ppc64le -o /usr/local/bin/pvsadm
chmod +x /usr/local/bin/pvsadm
yum -y install qemu-img cloud-utils-growpart
```

https://github.com/ppc64le-cloud/pvsadm

## 1.2. qcow2形式のOSイメージをダウンロードしova形式に変換
下記を実行することで、カレントディレクトリに「rhcos-47.ova.gz」が作成されます。

```bash:bastionノード
wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.7/4.7.7/rhcos-4.7.7-ppc64le-qemu.ppc64le.qcow2.gz
pvsadm image qcow2ova --image-name rhcos-47               \
  --image-url ./rhcos-4.7.7-ppc64le-qemu.ppc64le.qcow2.gz \
  --image-dist coreos
```

centos 8.3(x86_64)用のpvsadmコマンドも用意されておりRHCOSのovaイメージ作成が可能です。しかし、centosのovaイメージは作成できませんでした。ovaイメージ作成中に「yum -y update」などを実行してイメージを更新するためと思われます。処理内容は下記のコマンドで確認できます。カスタマイズも可能です。

```bash:参考
pvsadm image qcow2ova --prep-template-default | tee image-prep.template
vi image-prep.template(処理内容カスタマイズ)
pvsadm image qcow2ova --image-name <イメージ名> \
  --image-url <qcow2形式OSイメージファイル>      \
  --image-dist centos                          \
  --prep-template image-prep.template
```

## 1.3. ova形式のRHCOSをCloud Object Storageにアップロード
■ 前提
・Cloud Object Storageにバケット「ocp-prod-image」作成済

```bash:bastionノード
set +o history
export IBMCLOUD_API_KEY=<IBM Cloud APIキー>
pvsadm image upload -b ocp-prod-image -f ./rhcos-47.ova.gz -r jp-tok
set -o history
```

## 1.4. Cloud Object Storageからブート・イメージをインポート
下記はインポート依頼をするのみです。PowerVSの仮想サーバー・インスタンス作成用ブート・イメージとして利用可能となるまで30分程度かかります。

```bash:bastionノード
set +o history
export IBMCLOUD_API_KEY=<IBM Cloud APIキー>
pvsadm image import -n <PowerVSサービス名> -b ocp-prod-image --object rhcos-47.ova.gz --pvs-image-name rhcos-47 -r jp-tok
set -o history
```

# 2. PowerVS 仮想サーバー・インスタンス作成
下表のインスタンスを作成します。ブート・イメージとしてRHCOSを指定していますが、bastionノードから取得するため実際は何でも良いはずです。

| ノード | vCPU | 仮想RAM | ストレージ  | IPアドレス | ブート<br>イメージ |
|---|---|---|---|---|---|　
| master-0 | 0.5(shared) | 16GB | 120GB | 192.168.25.110 | rhos-47 |
| master-1 | 0.5(shared) | 16GB | 120GB | 192.168.25.111 | rhos-47 |
| master-2 | 0.5(shared) | 16GB | 120GB | 192.168.25.112 | rhos-47 |
| worker-0 | 0.5(shared) | 16GB | 120GB | 192.168.25.113 | rhos-47 |
| worker-1 | 0.5(shared) | 16GB | 120GB | 192.168.25.114 | rhos-47 |
| bootstrap | 0.5(shared) | 16GB | 120GB | 192.168.25.120 | rhos-47 |

```bash:classicノード
ibmcloud pi instance-create master-0 --image rhcos-47 --memory 16             \
  --network "ocp-net 192.168.25.110" --processors 0.5 --processor-type shared \
  --key-name sshkey --key-name sshkey --sys-type s922 --storage-type tier3

ibmcloud pi instance-create master-1 --image rhcos-47 --memory 16            \
 --network "ocp-net 192.168.25.111" --processors 0.5 --processor-type shared \
 --key-name sshkey --key-name sshkey --sys-type s922 --storage-type tier3

ibmcloud pi instance-create master-2 --image rhcos-47 --memory 16            \
 --network "ocp-net 192.168.25.112" --processors 0.5 --processor-type shared \
 --key-name sshkey --key-name sshkey --sys-type s922 --storage-type tier3

ibmcloud pi instance-create worker-0 --image rhcos-47 --memory 16            \
 --network "ocp-net 192.168.25.113" --processors 0.5 --processor-type shared \
 --key-name sshkey --key-name sshkey --sys-type s922 --storage-type tier3

ibmcloud pi instance-create worker-1 --image rhcos-47 --memory 16            \
 --network "ocp-net 192.168.25.114" --processors 0.5 --processor-type shared \
 --key-name sshkey --key-name sshkey --sys-type s922 --storage-type tier3

ibmcloud pi instance-create bootstrap --image rhcos-47 --memory 16           \
 --network "ocp-net 192.168.25.120" --processors 0.5 --processor-type shared \
 --key-name sshkey --key-name sshkey --sys-type s922 --storage-type tier3
```

Red Hatのドキュメントに記載されている最小要件から変更している点があります。
vCPUに関してはRedbook「Red Hat OpenShift V4.3 on IBM Power Systems Reference Guide」の「Table 2-10 CPU conversion」を参考に2vCPUを0.5coreと換算しました。workerノードの仮想RAMの容量は少し多めにしています。

| サーバー | vCPU | 仮想RAM | ストレージ
|---|---|---|---|
|コントロールプレーン | 2 | 16GB | 120GB |
|コンピュート | 2 | 8GB | 120GB |
|ブートストラップ | 2 | 16GB | 120GB |

https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html-single/installing/index#installation-requirements-user-infra_installing-ibm-power

http://www.redbooks.ibm.com/abstracts/redp5599.html

# 3. bastionノード準備
## 3.1. SELinux無効化

dnsmasqやhaproxyの起動に失敗しないようにSELinuxを無効化しています。

```bash:bastionノード
setenforce 0
cd /etc/selinux
cp -p config config.org
sed -e 's/SELINUX=enforcing/SELINUX=permissive/g' config.org > config
```

## 3.2. httpd構成
master/worker/bootstrapノードに対してRHCOSとignitionファイルを提供します。

```bash:bastionノード
yum -y install httpd
vi /etc/httpd/conf/httpd.conf(Listenポート変更)
Listen 8080 ← 80
### vi終了

cd /var/www/html
wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.7/4.7.7/rhcos-4.7.7-ppc64le-live-rootfs.ppc64le.img

systemctl --now enable httpd
```

## 3.3. dnsmasq構成
OpenShiftクラスターの稼働に必要なDNSです。DHCPも構成しており、dhcp-hostエントリにmaster/worker/bootstrapノードのMACアドレスとIPアドレスを定義しています。master/worker/bootstrapノードをbootp起動したとき、dnsmasqは当該ノードに対してcore.elfやgrub.cfg-01-(MACアドレス)をtftpで送信します。grub.cfg-01-(MACアドレス)は、RHCOSをインストールした後に、ignitionファイルを読み込む内容になっています。

master/worker/bootstrapノードのMACアドレスはIBM Cloudコンソールで確認します。

```bash:bastionノード
grub2-mknetdir --net-directory=/var/lib/tftpboot
cd /var/lib/tftpboot
wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.7/4.7.7/rhcos-4.7.7-ppc64le-live-kernel-ppc64le
wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.7/4.7.7/rhcos-4.7.7-ppc64le-live-initramfs.ppc64le.img

vi /var/lib/tftpboot/boot/grub2/powerpc-ieee1275/grub.cfg-01-fa-03-a3-7b-6e-20
default=0
fallback=1
timeout=1
menuentry "master-0 CoreOS (BIOS)" {
linux "rhcos-4.7.7-ppc64le-live-kernel-ppc64le" ip=192.168.25.110::192.168.25.100:255.255.255.0:master-0:env2:none nameserver=192.168.25.100 coreos.inst=yes coreos.inst.install_dev=sdacoreos.live.rootfs_url=http://192.168.25.100:8080/rhcos-4.7.7-ppc64le-liverootfs.ppc64le.img coreos.inst.ignition_url=http://192.168.25.100:8080/master.ign
initrd "rhcos-4.7.7-ppc64le-live-initramfs.ppc64le.img"
}
### vi終了

vi /var/lib/tftpboot/boot/grub2/powerpc-ieee1275/grub.cfg-01-fa-8b-cc-44-77-20
default=0
fallback=1
timeout=1
menuentry "master-1 CoreOS (BIOS)" {
linux "rhcos-4.7.7-ppc64le-live-kernel-ppc64le" ip=192.168.25.111::192.168.25.100:255.255.255.0:master-1:env2:none nameserver=192.168.25.100 coreos.inst=yes coreos.inst.install_dev=sda coreos.live.rootfs_url=http://192.168.25.100:8080/rhcos-4.7.7-ppc64le-live-rootfs.ppc64le.img coreos.inst.ignition_url=http://192.168.25.100:8080/master.ign
initrd "rhcos-4.7.7-ppc64le-live-initramfs.ppc64le.img"
}
### vi終了

vi /var/lib/tftpboot/boot/grub2/powerpc-ieee1275/grub.cfg-01-fa-8e-57-ff-d5-20
default=0
fallback=1
timeout=1
menuentry "master-2 CoreOS (BIOS)" {
linux "rhcos-4.7.7-ppc64le-live-kernel-ppc64le" ip=192.168.25.112::192.168.25.100:255.255.255.0:master-2:env2:none nameserver=192.168.25.100 coreos.inst=yes coreos.inst.install_dev=sda coreos.live.rootfs_url=http://192.168.25.100:8080/rhcos-4.7.7-ppc64le-live-rootfs.ppc64le.img coreos.inst.ignition_url=http://192.168.25.100:8080/master.ign
initrd "rhcos-4.7.7-ppc64le-live-initramfs.ppc64le.img"
}
### vi終了

vi /var/lib/tftpboot/boot/grub2/powerpc-ieee1275/grub.cfg-01-fa-23-73-dc-9d-20
default=0
fallback=1
timeout=1
menuentry "worker-0 CoreOS (BIOS)" {
linux "rhcos-4.7.7-ppc64le-live-kernel-ppc64le" ip=192.168.25.113::192.168.25.100:255.255.255.0:worker-0:env2:none nameserver=192.168.25.100 coreos.inst=yes coreos.inst.install_dev=sda coreos.live.rootfs_url=http://192.168.25.100:8080/rhcos-4.7.7-ppc64le-live-rootfs.ppc64le.img coreos.inst.ignition_url=http://192.168.25.100:8080/worker.ign
initrd "rhcos-4.7.7-ppc64le-live-initramfs.ppc64le.img"
}
### vi終了

vi /var/lib/tftpboot/boot/grub2/powerpc-ieee1275/grub.cfg-01-fa-0e-fb-39-d6-20
default=0
fallback=1
timeout=1
menuentry "worker-1 CoreOS (BIOS)" {
linux "rhcos-4.7.7-ppc64le-live-kernel-ppc64le" ip=192.168.25.114::192.168.25.100:255.255.255.0:worker-1:env2:nonenameserver=192.168.25.100 coreos.inst=yes coreos.inst.install_dev=sda coreos.live.rootfs_url=http://192.168.25.100:8080/rhcos-4.7.7-ppc64le-live-rootfs.ppc64le.img coreos.inst.ignition_url=http://192.168.25.100:8080/worker.ign
initrd "rhcos-4.7.7-ppc64le-live-initramfs.ppc64le.img"
}
### vi終了

vi /var/lib/tftpboot/boot/grub2/powerpc-ieee1275/grub.cfg-01-fa-55-2f-73-75-20
default=0
fallback=1
timeout=1
menuentry "bootstrap CoreOS (BIOS)" {
linux "rhcos-4.7.7-ppc64le-live-kernel-ppc64le" ip=192.168.25.120::192.168.25.100:255.255.255.0:bootstrap:env2:none nameserver=192.168.25.100 coreos.inst=yes coreos.inst.install_dev=sdacoreos.live.rootfs_url=http://192.168.25.100:8080/rhcos-4.7.7-ppc64le-live rootfs.ppc64le.img coreos.inst.ignition_url=http://192.168.25.100:8080/bootstrap.ign
initrd "rhcos-4.7.7-ppc64le-live-initramfs.ppc64le.img"
}
### vi終了
```

```bash:bastionノード
yum -y install dnsmasq
vi /etc/hosts(DNSエントリ追加)
192.168.25.100  api api-int
192.168.25.110  master-0 etcd-0
192.168.25.111  master-1 etcd-1
192.168.25.112  master-2 etcd-2
192.168.25.113  worker-0
192.168.25.114  worker-1
192.168.25.120  bootstrap
### vi終了

vi /etc/dnsmasq.conf(DNS、DHCP設定、TFTP有効化)
bogus-priv
resolv-file=/etc/resolv.dnsmasq
expand-hosts
domain=ocp.powervs
address=/apps.ocp.powervs/192.168.25.100
dhcp-range=192.168.25.110,192.168.25.120,24h
dhcp-leasefile=/var/lib/dnsmasq/dnsmasq.leases
dhcp-host=fa:f0:9d:b1:b7:20,master-0,192.168.25.110
dhcp-host=fa:0d:65:33:9a:20,master-1,192.168.25.111
dhcp-host=fa:4c:8c:c0:31:20,master-2,192.168.25.112
dhcp-host=fa:71:d1:7f:dd:20,worker-0,192.168.25.113
dhcp-host=fa:b8:7d:d2:bf:20,worker-1,192.168.25.114
dhcp-host=fa:e0:f6:db:4a:20,bootstrap,192.168.25.120
srv-host=_etcd-server-ssl._tcp.ocp.powervs,etcd-0.ocp.powervs,2380,0,10
srv-host=_etcd-server-ssl._tcp.ocp.powervs,etcd-1.ocp.powervs,2380,0,10
srv-host=_etcd-server-ssl._tcp.ocp.powervs,etcd-2.ocp.powervs,2380,0,10

# log-dhcp
log-facility=/var/log/dnsmasq.log

# TFTP有効化
enable-tftp
tftp-root=/var/lib/tftpboot
dhcp-boot=boot/grub2/powerpc-ieee1275/core.elf

# verbose
log-queries
log-dhcp
### vi終了

echo "nameserver 127.0.0.1" > /etc/resolv.conf
echo "nameserver 10.192.36.132" > /etc/resolv.dnsmasq
systemctl --now enable dnsmasq
```

## 3.4. haproxy構成
masterノードやworkerノード宛の通信を負荷分散します。

```bash:bastionノード
yum -y install haproxy socat
vi /etc/haproxy/haproxy.cfg(frontendとbackendを置き換え)
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.ocp.powervs:6443 check
    server  master-0 master-0.ocp.powervs:6443 check
    server  master-1 master-1.ocp.powervs:6443 check
    server  master-2 master-2.ocp.powervs:6443 check

backend config-22623
    mode tcp
    balance     roundrobin
    server  bootstrap bootstrap.ocp.powervs:22623 check
    server  master-0 master-0.ocp.powervs:22623 check
    server  master-1 master-1.ocp.powervs:22623 check
    server  master-2 master-2.ocp.powervs:22623 check

backend http-80
    mode tcp
    balance     roundrobin
    server  worker-0 worker-0.ocp.powervs:80 check
    server  worker-1 worker-1.ocp.powervs:80 check

backend https-443
    mode tcp
    balance     roundrobin
    option      ssl-hello-chk
    server  worker-0 worker-0.ocp.powervs:443 check
    server  worker-1 worker-1.ocp.powervs:443 check
### vi終了

systemctl --now enable haproxy
```

## 3.5. openshiftコマンド入手
openshiftのインストールや管理のために必要なコマンドを導入します。

```bash:bastionノード
mkdir -p /root/ocp/install
cd /root/ocp/install
wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/clients/ocp/4.7.7/openshift-install-linux-4.7.7.tar.gz
wget https://mirror.openshift.com/pub/openshift-v4/ppc64le/clients/ocp/4.7.7/openshift-client-linux-4.7.7.tar.gz
tar -xvzf openshift-install-linux-4.7.7.tar.gz
tar -xvzf openshift-client-linux-4.7.7.tar.gz
cp -p ./oc /usr/local/bin/
```


# 4. classicノード準備
OpenShift導入後は、bastionノードのhaproxyの80番ポートや443番ポートにアクセスすることで、OpenShiftのコンソールやアプリケーションを利用することができます。作業端末から同ポートへアクセスするために、classicノードにsquid等を構成します。

```bash:アクセス経路
作業端末 → classicノード(squidフォワードプロキシ:3128)
        → bastionノード(haproxyリバースプロキシ:80/443)
        → OpenShiftルーターPod → OpenshiftコンソールPod
```

## 4.1. SELinux無効化

dnsmasqやsquidの起動に失敗しないようにSELinuxを無効化します。

```bash:classicノード
setenforce 0
cd /etc/selinux
cp -p config config.org
sed -e 's/SELINUX=enforcing/SELINUX=permissive/g' config.org > config
```

## 4.2. dnsmasq構成

```bash:classicノード
yum -y install dnsmasq

vi /etc/dnsmasq.conf(DNS設定)
resolv-file=/etc/resolv.dnsmasq
address=/apps.ocp.powervs/192.168.25.100
### vi終了

echo "nameserver 127.0.0.1" > /etc/resolv.conf
echo "nameserver 10.0.80.11" > /etc/resolv.dnsmasq
echo "nameserver 10.0.80.12" >> /etc/resolv.dnsmasq
systemctl --now enable dnsmasq
```

## 4.3. squid導入
本環境では作業端末からclassicノードにSSL VPNで接続しています。作業端末はclassicノードに対してプライベートIPアドレスで接続するため、squid.confに接続を許可するIPアドレスを追加する必要ありませんでした。

```bash:classicノード
yum -y install squid
systemctl --now enable squid
```

```bash:squid.conf抜粋(デフォルト)
acl localnet src 0.0.0.1-0.255.255.255  # RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8             # RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10          # RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16         # RFC 3927 link-local (directly plugged) machines
acl localnet src 172.16.0.0/12          # RFC 1918 local private network (LAN)
acl localnet src 192.168.0.0/16         # RFC 1918 local private network (LAN)

http_access allow localnet
```