OpenShiftでWindowsOS Nodeを追加してみた

この記事は[OpenShiftアドベントカレンダー](https://qiita.com/advent-calendar/2023/openshift)の12/24の記事です。

私はアプリケーション開発部隊出身のエンジニアです。今年度からミドルウェア製品を扱う部署に異動してOpenShiftと仲良くなろうとし始めている今日この頃です。
最近、当社では[NebulaShift](https://www.scsk.jp/sp/nebulashift/)というサービスの提供を開始しておりますので、ご一読いただけますと幸いです！

# 0.はじめに

本記事では、WindowsOS のWorkerNodeをOpenShiftに追加した際の手順を紹介できればと思います。
AWS上でOpenShiftを構築し、RHEL Core OSのWorkerNodeで稼働しているプロジェクトがあるとします。実用例はないかもしれませんが、Windows OSでしか対応していないアプリケーションを追加で動かしたいとなった場合に、同一OpenShift上にWindows OSのWorkerNodeを共存させることができるかを検証する際に実施した手順です。

# 1.やったこと
AWS上にOpenShiftをIPIインストールし、MasterNode×3　WorkerNode×2　OS:Core OSを構築したのちに、WorkerNode×1　OS:Windowsを追加で構築しました。
本記事では、上記構築作業の手順を実施時の注意点を交えて記述します。

【参考】
[4.1. Windows Machine Config Operator のインストール](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.13/html/windows_container_support_for_openshift/enabling-windows-container-workloads#installing-the-wmco)
[4.2. Windows Machine Config Operator のシークレットの設定](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.13/html/windows_container_support_for_openshift/configuring-secret-for-wmco_enabling-windows-container-workloads)
[5.1. AWS 上での Windows マシンセットの作成](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.13/html-single/windows_container_support_for_openshift/index#creating-windows-machineset-aws)
[6.2.1. Route 53 の設定](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.13/html-single/installing/index#installation-aws-route53_installing-aws-account)
[6.4. クラスターの AWS へのクイックインストール](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.13/html-single/installing/index#installing-aws-default)
[6.6.10. OVN-Kubernetes を使用したハイブリッドネットワークの設定](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.13/html-single/installing/index#configuring-hybrid-ovnkubernetes_installing-aws-network-customizations)
[9.9. マシンの証明書署名要求の承認](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.13/html/machine_management/installation-approve-csrs_adding-rhel-compute)

# 2.システム構成図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3649122/4d602697-f8cb-f7b8-f5ae-c46b66325057.png)

# 3.手順

### 【AWS上にOpenShiftをIPIインストールし、MasterNode×3　WorkerNode×2　OS:Core OSを構築】

##### 1. システム構成を作成し、のせるアプリケーションに応じたスペックを確認する。


##### 2. ドメインを取得する。
<dd>
今回はお名前ドットコムで取得（年間500円程度）
</dd>

##### 3. Route53にパブリックホストゾーンを登録する。

<dd>
登録後にお名前ドットコムで対象ドメインに対してRoute53で登録したホストゾーンのルーティング先に設定されたネームサーバ情報を登録する必要あり。
</dd>

##### 4. AWSアカウントを作成する。
<dd>

:::note warn
AdministratorAccess ポリシーが付与されている必要あり
:::

</dd>

##### 5. 踏み台サーバ用EC2インスタンスを起動する。

<dd>
起動した踏み台サーバで以下の作業を行う。<br>
・AWS CLIを登録する。<br>
　4 で作成したアカウントのAWS Access Key ID、AWS Secret Access Key IDを使用する。<br>
・SSHKeyを生成する。<br>
　6 でinstall-config.yamlに設定する。<br>
・資材をダウンロードする。<br>

 　[Red Hatサイト](https://cloud.redhat.com/openshift/create)

```
 $ curl -O https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/openshift-install-linux.tar.gz
 $ tar xvf openshift-install-linux.tar.gz
```
</dd>

##### 6. install-config.yamlファイルを作成する。

<dd>
以下の要素を入れる。（ミニマムスタートで細かい設定を行わない場合）

:::note warn
install-config.yamlはインストール後削除されるためバックアップファイルを取得しておくこと
:::

　　　・ドメイン
　　　・スペック
　　　・リージョン
　　　・アプリケーションname
　　　・Masterノード数
　　　・Workerノード数
　　　・networkType
　　　・プルシークレット
　　　・sshKey　→5 で取得した値
　　　※今回、その他ネットワーク設定はデフォルトとした。

:::note warn
Windowsノードを使う場合はnetworkTypeをOVNKubernetesとする。
4.13バージョンではOVNKubernetesがデフォルト
:::
:::note warn
試用版はセルフサポート（＝サポートなし）で60日間有効。
サブスクリプション購入済みの場合は、対象のRed Hatアカウントでプルシークレットを取得すること。
インストール後に所有者を変更することもできるが変更に5日程度かかることがあるため、インストール時から設定しておく。
:::

</dd>
<dd>

```
apiVersion: v1
baseDomain: hogefuga.jp
compute:
- architecture: amd64
  hyperthreading: Enabled
  name: worker
  platform:
    aws:
      type: m6g.xlarge
  replicas: 2
controlPlane:
  architecture: amd64
  hyperthreading: Enabled
  name: master
  platform:
    aws:
      type: m6g.xlarge
  replicas: 3
metadata:
  creationTimestamp: null
  name: hogehoge
networking:
  clusterNetwork:
  - cidr: 10.128.0.0/14
    hostPrefix: 23
  machineNetwork:
  - cidr: 10.0.0.0/16
  networkType: OVNKubernetes
  serviceNetwork:
  - 172.30.0.0/16
platform:
  aws:
    region: ap-northeast-1
publish: External
pullSecret: 'XYZ~~~'
sshKey: |
  ssh-ed25519 XYZ~~~
```

</dd>

##### 7. ハイブリッドネットワークの設定用のマニュフェストファイルを作成する。
<dd>

:::note warn
クイックインストールの手順だけ見ていたらインストール前作業として漏れがちなので注意！
:::

今回はデフォルト値を設定。
```
$ ./openshift-install create manifests --dir <installation_directory>
$ cat config-network2/manifests/cluster-network-03-config.yml

apiVersion: operator.openshift.io/v1
kind: Network
metadata:
  name: cluster
spec:
  defaultNetwork:
    ovnKubernetesConfig:
      hybridOverlayConfig:
        hybridClusterNetwork: 1
        - cidr: 10.132.0.0/14
          hostPrefix: 23
        hybridOverlayVXLANPort: 9898
```

</dd>

##### 8. インストールを実施する。
<dd>
各種設定ファイルをconfigディレクトリに配置する。

```
config
　┠　install-config.yaml　★6で作成
　┠　manifests　★7で作成
　┃　┠　cluster-config.yaml
　┃　┠　cluster-dns-02-config.yml
　┃　┠　cluster-infrastructure-02-config.yml
　┃　┠　cluster-ingress-02-config.yml
　┃　┠　cluster-network-01-crd.yml
　┃　┠　cluster-network-02-config.yml
　┃　┠　cluster-network-03-config.yml
　┃　┠　cluster-proxy-01-config.yaml
　┃　┠　cluster-scheduler-02-config.yml
　┃　┠　cvo-overrides.yaml
　┃　┠　kube-cloud-config.yaml
　┃　┠　kube-system-configmap-root-ca.yaml
　┃　┠　machine-config-server-tls-secret.yaml
　┃　┗　openshift-config-secret-pull-secret.yaml
　┗　openshift　★7で作成
　　　┠　99_cloud-creds-secret.yaml
　　　┠　99_kubeadmin-password-secret.yaml
　　　┠　99_openshift-cluster-api_master-machines-0.yaml
　　　┠　99_openshift-cluster-api_master-machines-1.yaml
　　　┠　99_openshift-cluster-api_master-machines-2.yaml
　　　┠　99_openshift-cluster-api_master-user-data-secret.yaml
　　　┠　99_openshift-cluster-api_worker-machineset-0.yaml
　　　┠　99_openshift-cluster-api_worker-machineset-1.yaml
　　　┠　99_openshift-cluster-api_worker-machineset-2.yaml
　　　┠　99_openshift-cluster-api_worker-user-data-secret.yaml
　　　┠　99_openshift-machine-api_master-control-plane-machine-set.yaml
　　　┠　99_openshift-machineconfig_99-master-ssh.yaml
　　　┠　99_openshift-machineconfig_99-worker-ssh.yaml
　　　┠　99_role-cloud-creds-secret-reader.yaml
　　　┗　openshift-install-manifests.yaml
```

```
 $ ./openshift-install create cluster --dir=config --log-level=debug
```
:::note warn
インストールは40分程度かかる。
エラーになったときのためにログレベルはdebugにしておく。
完了後24時間は起動したままにする必要あり。
OpenShiftは常時起動を前提としクラスタ内部で使用する証明書の更新を自動で行っている。
今回構築した検証環境のようにコスト抑制を目的として日々サーバを停止するような運用をすると、この自動更新が動作せず、証明書の有効期限切れでOpenShiftが使用できない状態になる場合がある。
その際には、16 マシンの証明書署名要求の承認　に記載したコマンドを実行して証明書の更新を行うと起動できるようになる。
:::
 
</dd>

##### 9. ocコマンドをダウンロードする。
<dd>

```
 $ sudo cp -p oc /usr/local/bin/oc
 $ sudo cp -p kubectl /usr/local/bin/kubectl
```

</dd>

##### 10. KUBECONFIGの設定を行う。
<dd>
（設定変更前の設定ファイルのバックアップを取得しておくこと）

・環境変数のTAB補完
・KUBECONFIGのありかを設定
</dd>  

##### 11. ユーザ追加
<dd>
OpenShiftを触るメンバーが複数いる場合は、
メンバー数分の踏み台サーバログインアカウント、OpenShiftログインアカウントを作成しておく。<br>
OpenShiftログインアカウントの作成方法は以下の記事を参考に実施した。<br>
参考：<a href="https://qiita.com/Yuhkih/items/e5ef6160ac3f8caefdc8">https://qiita.com/Yuhkih/items/e5ef6160ac3f8caefdc8</a>
</dd>

##### 12. ログイン確認
<dd>
  oc login コマンド、またはWEBコンソールで確認する。
</dd>

------------------------------------------------------------
### 【WorkerNode×1　OS:Windowsを追加で構築】

##### 13. Windows Machine Config Operator (WMCO)インストール
<dd>
・WebコンソールよりOperatorをインストールする。　<br>
・Windows Machine Config Operator のシークレットを設定する。

```
$ ssh-add ~/.ssh/id_rsa_cloud_private_key
ssh-add ~/.ssh/id_rsa_cloud_private_key

Identity added: /home/ec2-user/.ssh/id_rsa_cloud_private_key (ec2-user@ip-999-999-999-999.ap-northeast-1.compute.internal)

$ oc create secret generic cloud-private-key --from-file=private-key.pem=/home/ec2-user/.ssh/id_rsa_cloud_private_key -n openshift-windows-machine-config-operator
oc create secret generic cloud-private-key --from-file=private-key.pem=/home/ec2-user/.ssh/id_rsa_cloud_private_key -n openshift-windows-machine-config-operator

secret/cloud-private-key created
```

</dd>

##### 14. Windows MachineSetオブジェクトのyaml作成
<dd>
以下の要素を入れる。（minimumスタートで細かい設定を行わない場合）

　・infrastructure_id
　・windows_container_ami
　・AWSゾーン
　・AWSリージョン

```
apiVersion: machine.openshift.io/v1beta1
kind: MachineSet
metadata:
  labels:
    machine.openshift.io/cluster-api-cluster: hogehoge-p62vj
  name: hogehoge-p62vj-windows-worker-ap-northeast-1d
  namespace: openshift-machine-api
spec:
  replicas: 1
  selector:
    matchLabels:
      machine.openshift.io/cluster-api-cluster: hogehoge-p62vj
      machine.openshift.io/cluster-api-machineset: hogehoge-p62vj-windows-worker-ap-northeast-1d
  template:
    metadata:
      labels:
        machine.openshift.io/cluster-api-cluster: hogehoge-p62vj
        machine.openshift.io/cluster-api-machine-role: worker
        machine.openshift.io/cluster-api-machine-type: worker
        machine.openshift.io/cluster-api-machineset: hogehoge-p62vj-windows-worker-ap-northeast-1d
        machine.openshift.io/os-id: Windows
    spec:
      metadata:
        labels:
          node-role.kubernetes.io/worker: ""
      providerSpec:
        value:
          ami:
            id: ami-049b14f44d51e8d1a
          apiVersion: awsproviderconfig.openshift.io/v1beta1
          blockDevices:
            - ebs:
                iops: 0
                volumeSize: 120
                volumeType: gp2
          credentialsSecret:
            name: aws-cloud-credentials
          deviceIndex: 0
          iamInstanceProfile:
            id: hogehoge-p62vj-worker-profile
          instanceType: m5a.large
          kind: AWSMachineProviderConfig
          placement:
            availabilityZone: ap-northeast-1d
            region: ap-northeast-1
          securityGroups:
            - filters:
                - name: tag:Name
                  values:
                    - hogehoge-p62vj-worker-sg
          subnet:
            filters:
              - name: tag:Name
                values:
                  - hogehoge-p62vj-private-ap-northeast-1d
          tags:
            - name: kubernetes.io/cluster/hogehoge-p62vj
              value: owned
          userDataSecret:
            name: windows-user-data
            namespace: openshift-machine-api
```


</dd>

##### 15. Windows MachineSet作成
<dd>
■作成コマンド

```
 $ oc create -f <file_name>.yaml
```
■確認コマンド
```
 $ oc get machineset -n openshift-machine-api
```
作成コマンド実行直後は以下の通り、AVAILABLEにならないが
16 の証明書署名要求を承認してから再度確認すると利用可能なマシンセットの追加完了となる。
```
$ oc get machineset -n openshift-machine-apioc get machineset -n openshift-machine-api
NAME                                        DESIRED   CURRENT   READY   AVAILABLE   AGE
hogehoge-p62vj-windows-worker-ap-northeast-1d   1         1                             8s
hogehoge-p62vj-worker-ap-northeast-1a           1         1         1       1           34d
hogehoge-p62vj-worker-ap-northeast-1c           1         1         1       1           34d

$ oc get machines -n openshift-machine-api
NAME                                              PHASE         TYPE         REGION           ZONE              AGE
hogehoge-p62vj-master-0                               Running       m5a.xlarge   ap-northeast-1   ap-northeast-1a   34d
hogehoge-p62vj-master-1                               Running       m5a.xlarge   ap-northeast-1   ap-northeast-1c   34d
hogehoge-p62vj-master-2                               Running       m5a.xlarge   ap-northeast-1   ap-northeast-1d   34d
hogehoge-p62vj-windows-worker-ap-northeast-1d-fw9zc   Provisioned   m5a.large    ap-northeast-1   ap-northeast-1d   76m
hogehoge-p62vj-worker-ap-northeast-1a-qzw4t           Running       m5a.xlarge   ap-northeast-1   ap-northeast-1a   34d
hogehoge-p62vj-worker-ap-northeast-1c-n5xsp           Running       m5a.xlarge   ap-northeast-1   ap-northeast-1c   34d
```
</dd>

##### 16. マシンの証明書署名要求の承認
<dd>
MachineSetを追加すると証明書要求が生成されるため、承認しないとREADYにならない。<br>
以下のコマンドを実行して保留中の証明書要求をすべて承認する。

```
 $ oc get csr -o go-template='{{range .items}}{{if not .status}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}' | xargs oc adm certificate approve
```

</dd>

## 4.まとめ
自身の知識不足もあり、エラー発生時に原因を調査する手順や同じケースを想定した手順がRed Hatドキュメントからは見つけられず、自分で必要箇所をピックアップして順番に実行していくのに手こずりました。
一つ一つの手順やトラブルシューティングの例からエラーの解決方法や作業手順をできる限り短時間で組み立てられるよう精進します。