Power Systems Virtual ServerへのOpenShift 4.7導入(1): ネットワーク構成

# はじめに
この記事では、Power Systems Virtual Server(以下PowerVS)へのOpenShift 4.7導入に際してネットワーク構成を実施します。PowerVSとIBM Cloudは異なるネットワークになっており、Direct Linkで接続することが可能です。但し、PowerVSのプライベートサブネットからIBM Cloudサービスのプライベートエンドポイントに接続することはできません。
Cloud Object Storage用にリバースプロキシを構成する方法もガイドされていますが、ここでは、IBM Cloudの仮想サーバー(classic)とPowerVSの仮想サーバー(bastion)間でIPIPトンネリングし、IPマスカレードする構成とし、OpenShiftのmaster/worker/bootstrapノードのデフォルト・ゲートウェイをbastionノードにします。なお、実稼働環境を想定した冗長化は行っていません。

![01_custom.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413476/9832672b-0535-b222-c03b-0c23e7ce0ca4.png)
本記事の対象ではありませんが、OpenShiftは「openshift-install」コマンドで導入します。仮想サーバーの自動作成やbastionノードの自動構成を行う支援ツールは利用しません。

■ リバースプロキシ構成ガイド

https://cloud.ibm.com/docs/direct-link?topic=direct-link-using-ibm-cloud-direct-link-to-connect-to-ibm-cloud-object-storage&locale=ja

■ UPIインストール

https://rheb.hatenablog.com/entry/openshift41-baremetal-upi

■ 支援ツール

https://github.com/ocp-power-automation/openshift-install-power


# 1. PowerVSのプライベートサブネット内通信を許可
プライベートサブネットを作成し、サブネット内通信を許可するためにCaseを起票します。
![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413476/c7dd72af-3b99-a21e-a555-dc87d4f275fb.png)

```bash:Case
■ サブジェクト
Enable communication between PowerVS instances on private network

■ 説明
Please enable IP communication between PowerVS instances for the following private network:
  Name: ocp-net
  Type: Private
  CIDR: 192.168.25.0/24
  VLAN ID: 367
  Location: tok04
  Service Instance: Power Systems Virtual Server-ocp
```

# 2. PowerVSとIBM Cloud間をDirect Link接続
Direct Linkを作成し、Case#1とCase#2を起票します。
Case#1ではPowerVS側でDirect Linkと接続可能な状態にするよう依頼し、
Case#2ではVirtual Routing and Forwarding(VRF)を有効化にするよう依頼しています。
後者はIBM Cloud(Classic)と接続するために必要でした。IBM Cloud(VPC)の場合は不要です。
Case#1とCase#2で依頼した作業が完了した後にDirect Link内に仮想接続を作成します。

Direct Link作成については、下記の記事が詳しいです。

https://qiita.com/testnin2/items/064ddc1c076511f9ad5c

```bash:Case#1
■ サブジェクト
Power VS: Direct Link Connect 2.0 request

■ 説明
We orderd Direct Link Connect 2.0 from IBM Cloud portal and its provisionig has finished. 
The detail infomation is as follows. Please proceed the process at Power VS side to establish Direct Link Connect. Thanks.

Date created: Fri, Apr 23,2021,20:29:21 GMT+9
Resource group: Default
Provider: IBM POWER VS
Routing : Global
Speed: 5 Gbps
Billing: Unmetered
User CIDR: 169.254.0.2/30
IBM CIDR : 169.254.0.1/30
BGP ASN: 64999
IBM ASN: 13884
Port: SL-TOK04-POWERIAASLITE-1-1-(ASR1)
Location: Tokyo 4
Service key: <サービスキー>
BGP status: Idle
VLAN: <VLAN番号>
```

```bash:Case#2
■ サブジェクト
Private Network Question

■ 説明
We are requesting that account <アカウント番号> is moved to its own VRF. 
We understand the risks and approve the change. It doesn't matter when you do it.
```
作業完了後、Direct Linkは以下の状態になります。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413476/c80e66ac-45d3-5491-5beb-b4e84c60a4b0.png)
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413476/7d6495c6-b0a5-98fd-a976-8e356c573b3c.png)

# 3. PowerVSとIBM Cloud(Classic)の仮想サーバー間接続
## 3.1. PowerVSに仮想サーバーを作成
イメージカタログに登録されているcentos 8.3からbastionノードを作成します。

■ 前提
・IBM Cloud(Classic)に仮想サーバー=classicノードを作成済
・classicノードにIBM Cloud CLIとpower-iaasプラグイン導入済
・公開鍵作成済

```bash:classicノード
# SSH鍵作成
ibmcloud pi key-create sshkey --key "公開鍵文字列"

# ブート・イメージ作成
ibmcloud pi image-create Linux-CentOS-8-3

# 仮想サーバー・インスタンス作成
ibmcloud pi instance-create bastion --image Linux-CentOS-8-3 --memory 3       \
 --network "ocp-net 192.168.25.100" --processors 0.25 --processor-type shared \
 --key-name sshkey --key-name sshkey --sys-type s922 --storage-type tier3
```

## 3.2. IPIPトンネリングとIPマスカレード構成
下図の構成とします。
![nw.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413476/df0de55b-a76d-189d-ba26-0ee71156d96f.png)

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/configuring-ip-tunnels_configuring-and-managing-networking

### 3.2.1. classicノード
classicノードのtun0を通過するとき、bastionノードからの通信の送信元IPアドレスは「10.0.1.2」、master/worker/bootstrapノードからの通信の送信元IPアドレスは「192.168.25.0/24」です。eth0とeth1ではこれらアドレスが送信元である場合にIPマスカレードするように設定します。

```bash:classicノード
# bastionノード(192.168.25.100)への静的経路を追加
nmcli c modify "System eth0" +ipv4.routes "192.168.25.100/32 10.192.36.129"
nmcli c up "System eth0"

# IPIPトンネリングとルーティング設定
nmcli c add type ip-tunnel ip-tunnel.mode ipip con-name tun0 ifname tun0 remote 192.168.25.100 local 10.192.36.132
nmcli c modify tun0 ipv4.addresses '10.0.1.1/30'
nmcli c modify tun0 ipv4.method manual
nmcli c modify tun0 +ipv4.routes "192.168.25.0/24 10.0.1.2"
nmcli c up tun0
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf

# eth0=プライベート接続インターフェースのIPマスカレードを設定
firewall-cmd --zone=trusted --change-interface=eth0 --permanent
firewall-cmd --zone=trusted --add-rich-rule="rule family=ipv4 source address=192.168.25.0/24 masquerade" --permanent
firewall-cmd --zone=trusted --add-rich-rule="rule family=ipv4 source address=10.0.1.2/32 masquerade" --permanent

# eth1=パブリック接続インターフェースのIPマスカレードを設定
firewall-cmd --zone=dmz --change-interface=eth1 --permanent
firewall-cmd --zone=dmz --add-rich-rule="rule family=ipv4 source address=192.168.25.0/24 masquerade" --permanent
firewall-cmd --zone=dmz --add-rich-rule="rule family=ipv4 source address=10.0.1.2/32 masquerade" --permanent

# デフォルトのまま
firewall-cmd --zone=public --change-interface=tun0 --permanent

firewall-cmd --reload
firewall-cmd --get-active-zones
### 標準出力↓
dmz
  interfaces: eth1
public
  interfaces: tun0
trusted
  interfaces: eth0

firewall-cmd --zone=dmz --list-all
### 標準出力↓
dmz (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth1
  sources:
  services: ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
        rule family="ipv4" source address="192.168.25.0/24" masquerade
        rule family="ipv4" source address="10.0.1.2/32" masquerade

firewall-cmd --zone=public --list-all
### 標準出力↓
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: tun0
  sources:
  services: cockpit dhcpv6-client https ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

firewall-cmd --zone=trusted --list-all
### 標準出力↓
trusted (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
        rule family="ipv4" source address="192.168.25.0/24" masquerade
        rule family="ipv4" source address="10.0.1.2/32" masquerade
```

### 3.2.2. bastionノード
env2でclassicノードとのトンネリングを作成し、且つ、master/worker/bootstrapノードからの通信を受ける構成としています。そのためにenv2ではclassicノード宛の静的経路を32 bitマスクで作成し、tun0のデフォルト・ゲートウェイを「10.0.1.1」にしています。

※bastionノードとmaster/worker/bootstorapノードが同一Power筐体にあるとき、TCPパケットが物理NICを通過せずcksumが「0x0000」になりました。同パケットはclassicノードのfirewalldで「STATE_INVALID_DROP」されてtun0からeth0やeth1にルーティングされないため、回避策としてcksumオフロード機能を無効化しています(ethtool.feature-rx off)。

```bash:bastionノード
# classicノード(10.192.36.132)への静的経路を追加し、デフォルト・ゲートウェイを削除
nmcli c modify "System env2" +ipv4.routes "10.192.36.132/32 192.168.25.1"
nmcli c modify "System env2" ipv4.gateway ""
nmcli con modify "System env2" ethtool.feature-rx off
nmcli c up "System env2"

# IPIPトンネリングとルーティング設定
nmcli c add type ip-tunnel ip-tunnel.mode ipip con-name tun0 ifname tun0 remote 10.192.36.132 local 192.168.25.100
nmcli c modify tun0 ipv4.addresses '10.0.1.2/30'
nmcli c modify tun0 ipv4.method manual
nmcli c modify tun0 ipv4.gateway "10.0.1.1"
nmcli c up tun0
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf

# firewalld導入(IPIPトンネリングによりインターネット接続可能)
echo "nameserver 8.8.8.8" > /etc/resolv.conf
yum -y install firewalld
systemctl --now enable firewalld

# firewalld設定
firewall-cmd --zone=trusted --change-interface=env2 --permanent
firewall-cmd --zone=trusted --change-interface=env3 --permanent
firewall-cmd --zone=public --change-interface=tun0 --permanent
firewall-cmd --reload

firewall-cmd --get-active-zones
### 標準出力↓
public
  interfaces: tun0
trusted
  interfaces: env2 env3

firewall-cmd --zone=public --list-all
### 標準出力↓
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: tun0
  sources:
  services: cockpit dhcpv6-client http https ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

firewall-cmd --zone=trusted --list-all
### 標準出力↓
trusted (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: env2 env3
  sources:
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
```