Azure Red Hat OpenShift (ARO) でスケーラブルなノード管理・運用

##はじめに
Azure Red Hat OpenShiftは、AzureのフルマネージドのOpenShiftサービスです。ワンコマンドで簡単にOpenShiftのKubernetesクラスターをAzureに作成でき、かつサポートもRed Hat社に個別に連絡を取る必要はなく、マイクロソフトが一元的にサポートします。以下、ARO(Azure Red Hat OpenShiftの頭文字を合わせたもの）と記述します。
以前の[記事](https://qiita.com/hatasaki/items/8a8526a3dd753e22b503)でAROの作成方法について記載しましたが、今回はOpenShiftをAzureで稼働する際の非常に大きなメリットとなる、スケーラブルなノードの管理・運用についてご紹介したいと思います。

##AROにおけるノード管理・運用の利点
一般的にOpenShiftをオンプレミス等で構築した場合、ノードの追加やスペックの変更といった作業をすぐに実施することは、サーバの追加導入や設置・設定等が必要であり難しい場合が多いと思います。これに対してAROでは、AzureとOpenShiftが密に連携することで、OpenShiftのノードの追加・変更が簡単に実施できます。特に、AROの最も重要な特徴は、**OpenShiftの管理者やアプリ開発者がAzureのポータルやAzure CLIを操作したりAzure管理者に依頼することなく、セルフサービスでノードの追加・更新等の作業を実施できる**点です。これにより、OpenShiftのユーザーが自由にクラスターのリソースを制御できるため、アプリの開発や運用に集中でき、さまざまな場面で作業の効率化とスピードアップが可能になります。
この特徴により、特に次のようなケースで大きな利点があると思います。

**(1)アプリの成長に合わせたスモールスタートとノードの拡張**
最初は小さい構成で始め、アプリやサービスの成長に合わせて次第にノードを追加したり、メモリを大量消費するアプリに対応するために大容量メモリのノードを追加することが可能です。

**(2)アプリの負荷変動に合わせたノードの自動拡張**
アプリに対する接続や要求数の変動に対応するため、アプリのインスタンス(pod)の拡張と連動してノードの自動スケールを実施することが可能です。

**(3)ノードの自動修復**
アプリが稼働するノードの障害発生時に、ノードを自動的に修復できます。

以下では、AROにおけるAzureとOpenShiftの密連携の肝となるMachine API Operatorについて説明し、続けて上記の3つのケースについてAROでの操作方法をご紹介して行きます。

##Machine API Operatorとは
[Machine API Operator](https://github.com/openshift/machine-api-operator)はOpenShiftにおいてKubernetesクラスターノードのライフサイクルを管理する機能であり、ノードの管理をKubernetesネイティブな宣言的な方法で管理可能とします。
Machine API Operatorは下図の通り、様々なコントローラとCRDで構成されています。
![MAO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255074/ebfcdbb7-aa7c-fa48-82d5-ba6eadf08983.png)
特にノード管理において利用するリソースは、[MachineSet](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/machine_management/creating-machineset-azure#machineset-yaml-azure_creating-machineset-azure)になります。ユーザーがMachineSetを定義・更新することで、対応するMachineリソースが自動的に構成されます。さらに、Machineリソースに基づきAzureのVMやノードの追加や削除、更新が実施されます。

##アプリの成長に合わせたスモールスタートとノードの拡張
###ノードの追加および削除
AROでは、OpenShiftのWebコンソールや、OpenShift CLI(OC)などを用いて簡単にノードの追加や削除が可能です。この操作は、MachineSetリソースのspec.replicas（VMインスタンス数）の値を変更するだけです。
Webコンソールの場合、Administratorモードにおいて、左側に並ぶメニューの中の```Compute```内にある```Machine Sets```を選択します。すると、下記のようにMachineSetリソースの一覧が表示されます。```Machines```欄は、リソース定義におけるVMインスタンス数のうち、何台のVMが実際に稼働中なのかを示しています。
![mslist.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255074/05d43a60-604d-8af7-510d-3549c3d9449c.png)
既定で定義されているMachineSetリソースの名前の末尾は、稼働するリージョンとアベイラビリティゾーンとなります。例えば、東日本(japaneast)リージョンのアベイラビリティゾーン1で稼働するワーカーノード用のVMの場合、```*-worker-japaneast1```などです。なお、ノードの名前は、対応するMachineSetの名前の末尾にさらにランダムな英数字が追加され、```*-worker-japaneast1-x2v7r```などとなります。(注: Webコンソールの```Machines```メニューの画面を利用すれば、ノードのVMがどのリージョンやアベイラビリティゾーンで稼働しているかを一覧表示して確認可能です。また、Machineリソースの名前と対応するノードの名前は同じものとなります。)

次に、MachineSetsの一覧画面から、ノード数を変更したいMachineSetを選択します。下記のようにMachineSetの詳細画面が表示されますので、画面の```Desired Count```のすぐ下をクリックします。Edit Machine Countというウインドウが現れますので、所望のノード数を入力して```save```を選択してください。これにより、現在のノード数との差分となるMachineリソースおよびノードが自動的に追加・削除されます。ノードの追加時間はおおよそ数分程度です。また、ノードの削除では、ノードのスケジュール不可状態への変更やpodのeviction開始も自動的に実施されます。
![msd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255074/853923e5-2988-cdf7-7e1f-07a96c2b97a7.png)
また、[OpenShift CLIを用いたノード数の変更](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/machine_management/machineset-manually-scaling_manually-scaling-machineset)は、下記を実行するだけです。

```
$ oc scale --replicas=<ノード数> machineset <MachineSetの名前> -n openshift-machine-api
```

###ノードのスペック変更
新規のMachineSetリソースを新たに定義することで、例えば大容量メモリのノードをAROクラスターに新たに追加することが可能です。MachineSetのspec.template.providerSpec.        value.vmSizeに所望のVMサイズを指定することができます。利用可能なVMサイズの一覧は[こちらのドキュメント](https://docs.microsoft.com/ja-jp/azure/openshift/support-policies-v4#supported-virtual-machine-sizes)を参照ください。
また、MachineSetリソースには、VMのOSディスク容量やアベイラビリティゾーンなど、様々なパラメータを指定することができますが、新規に全てを入力するのは大変です。そこで、VMサイズを変更するだけであれば、既定のMachineSetをコピーして、一部だけ変更するのがおすすめです。だたしその場合、VMサイズの変更だけでなく、MachineSetの名前と関連するラベルやラベルセレクターの値を変更することも必要ですので、ご注意ください。

MachineSetの新規作成は、Webコンソールの```Machine Sets```メニューを選択して表示される画面において、右上の```Create Machine Set```ボタンをクリックして作成できます。
参考に、下記に汎用VMサイズ(Standard_D4s_v3)よりメモリ容量をvCPU比で２倍搭載するVMサイズ(Standard_E4s_v3)とした新たなMachineSetの例を示します。

```
apiVersion: machine.openshift.io/v1beta1
kind: MachineSet
metadata:
  name: <name>
  namespace: openshift-machine-api
  labels:
    machine.openshift.io/cluster-api-cluster: <cluster>
    machine.openshift.io/cluster-api-machine-role: worker
    machine.openshift.io/cluster-api-machine-type: worker
spec:
  replicas: 1
  selector:
    matchLabels:
      machine.openshift.io/cluster-api-cluster: <cluster>
      machine.openshift.io/cluster-api-machineset: <name> #MachineSetの名前と一致させる
  template:
    metadata:
      labels:
        machine.openshift.io/cluster-api-cluster: <cluster>
        machine.openshift.io/cluster-api-machine-role: worker
        machine.openshift.io/cluster-api-machine-type: worker
        machine.openshift.io/cluster-api-machineset: <name> #MachineSetの名前と一致させる
    spec:
      metadata: {}
      providerSpec:
        value:
          osDisk:
            diskSizeGB: 128
            managedDisk:
              storageAccountType: Premium_LRS
            osType: Linux
          networkResourceGroup: <resourcegroup>
          publicLoadBalancer: <cluster>
          userDataSecret:
            name: worker-user-data
          vnet: <vnet>
          credentialsSecret:
            name: azure-cloud-credentials
            namespace: openshift-machine-api
          zone: '1' #アベイラビリティゾーンを指定
          metadata:
            creationTimestamp: null
          publicIP: false
          resourceGroup: <managedresourcegroup>
          kind: AzureMachineProviderSpec
          location: japaneast
          vmSize: Standard_E4s_v3 #VMサイズを指定
          image:
            <snip>
          subnet: <subnet>
          apiVersion: azureproviderconfig.openshift.io/v1beta1
```

##アプリの負荷変動に合わせたノードの自動拡張
AROでは、ノードの[自動スケーリング](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/machine_management/applying-autoscaling#cluster-autoscaler-about_applying-autoscaling)が可能です。これにより、例えばノードのリソースが不足してpodがデプロイできない場合に、自動的にノードを追加してpodをデプロイ可能とします。また、一部のノードが長い期間にわたって不要な状態が続く場合にノードの数を削減します。一般的には、podの[HPA(Horizontal Pod Autoscaler)](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/nodes/nodes-pods-autoscaling)と組み合わせて利用することが前提になると思います。

自動スケーリングに利用するには、[ClusterAutoscaler](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/machine_management/applying-autoscaling#cluster-autoscaler-about_applying-autoscaling)と[MachineAutoscaler](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/machine_management/machine-autoscaler-about_applying-autoscaling)の二種類の定義を設定する必要があります。以下それぞれの設定方法についてご紹介します。

###ClusterAutoscalerの定義
ClusterAutoscalerはクラスター全体をスコープとした自動スケーリングの設定です。Webコンソールから定義可能です。まず、Administratorモードの左側メニューの```Administration```内にある```Custom Resource Definitions```を選択します。クラスターのCRD一覧が表示されるので、```ClusterAutoscaler```を検索して選択してください。
![CRDlist.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255074/5af950c1-a31d-1855-4145-e9c417fe530a.png)
ClusterAutoscalerのCRDを選択してクリックすると、下図の画面が表示されますので、```Instances```タブを選択し、画面に表示される```Create Cluster Autoscaler```ボタンをクリックしてClusterAutoscalerリソースを定義します。
![ClusterAutoscalerdetail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255074/640d942e-2447-0a67-a131-2bb9f665b193.png)
参考に、Clusterautoscalerリソースの定義の例を下記に記載します。この例では、最大12ノードまで拡張可能で、ノードの追加または削除後は次のスケーリングまで3分間は待機する設定としています。なお、各項目の詳細は[こちらのドキュメント](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/machine_management/configuring-clusterautoscaler)に記載されていますので、ご参照ください。

```
apiVersion: "autoscaling.openshift.io/v1"
kind: "ClusterAutoscaler"
metadata:
  name: default
spec:
  podPriorityThreshold: -10 
  resourceLimits:
    maxNodesTotal: 12
    cores:
      min: 4
      max: 128 
    memory:
      min: 4 
      max: 256 
  scaleDown: 
    enabled: true 
    delayAfterAdd: 3m 
    delayAfterDelete: 3m 
    delayAfterFailure: 30s 
    unneededTime: 60s 
```

###MachineAutoscalerの定義
MachineAutoscalerは、特定のMachineSetリソースに対する自動スケーリングの設定です。ClusterAutoscalerの設定後に、少なくとも1つのMachineSetに対するMachineAutoscalerを設定する必要があります。こちらもWebコンソールから定義可能で、しかもYAMLを記述する必要なく簡単に作成することができます。
WebコンソールのAdministratorモードで、左側メニューの```Machine Sets```を選択し、MachineSetリソースの一覧を表示してください。次に、MachineAutoscalerを設定したいMachineSetリソースの右端にドットが縦に３つ連なったアイコンがありますので、そちらをクリックした際に表示されるメニューから、```Create Autoscaler```を選択してクリックします。すると、Minimum ReplicasとMaxmum Replicasの入力ウインドウが表示されるので、数値を入力して```Create```をクリックすると、MachineAutoscalerが作成されます。他のMachineSetリソースに対しても自動スケーリングを設定する場合は、同様の操作を実施してMachineAutoscalerを作成してください。
![mas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255074/3d397797-ac4e-5179-4b54-76b88d949912.png)

##ノードの自動修復
AROのワーカーノードで異常が発生した場合に、自動修復することができます。異常状態となったノードは削除され、新たなノードが追加されます。この機能を利用するには、[MachineHealthCheck](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/machine_management/deploying-machine-health-checks)リソースを定義します。
MachineHealthCheckリソースの作成はWebコンソールから可能です。WebコンソールのAdministratorモードで、左側メニューの```Compute```内にある```Machine Health Checks```を選択し、表示される画面より```Create Machine Health Cehck```ボタンをクリックしてください。
参考に、下記にMachineHealthCheckの定義例を示します。この定義では、ワーカーノードの状態がReady状態であることが5分間以上確認できない場合、ノードの修復処理が実行されます。

```
apiVersion: machine.openshift.io/v1beta1
kind: MachineHealthCheck
metadata:
  name: example
  namespace: openshift-machine-api
spec:
  selector:
    matchLabels:
      machine.openshift.io/cluster-api-machine-role: worker
      machine.openshift.io/cluster-api-machine-type: worker
  unhealthyConditions:
    - type: Ready
      status: Unknown
      timeout: 300s
    - type: Ready
      status: 'False'
      timeout: 300s
  maxUnhealthy: 1
  nodeStartupTimeout: 10m
```
(注:MachineHealthCheckリソースは特定のOpenShiftバージョンでは既定で定義されている場合があります）

##終わりに
今回の記事では、Azure Red Hat OpenShift(ARO)のノード管理についてご紹介しました。AROではAzureとOpenShiftが連携することで、ノードの追加やスペック変更、スケーリング、高可用構成および障害対応をOpenShiftからのリソース定義や操作によって制御できることをご説明しました。これにより、OpenShiftの利用者がAzureの管理者を巻き込まずに効率的かつ迅速にアプリの開発・運用に集中できると思います。

[関連資料]
[Azure のマネージドなOpenShift サービス – ARO の運用のコツ](https://event.cloudnativedays.jp/cndo2021/talks/821)
[Scale an Azure Red Hat OpenShift cluster](https://azure.microsoft.com/ja-jp/resources/videos/scale-an-azure-red-hat-openshift-cluster/)