OpenShift 上に Cluster Logging をインストールする

# 1.はじめに

`Red Hat` が提供する `Kubernetes` のパッケージである `OpenShift` では、ログ収集用のセットを [`Cluster Logging`] (https://docs.openshift.com/container-platform/4.5/logging/cluster-logging.html)と呼んでいます。

`Cluster Logging` の実体は、`Elastic Search`、`Kibana`、`fluentd`と`Curator`です。`OpenShift`では、この `Cluster Logging`を導入する事で、基本的なログ収集環境ができあがるようになっています。

ここでは、商用版の `OpenShift`4.5を使用して、`Cluster Logging`を導入していきます。

# 2.サイジング

`Cluster Logging`を導入するには、メモリのスペックとして`32GB` の `Workerノード` x 3 が必要とされています。
テストした限りでは、`16GB` ノードの場合は、メモリの不足でコンテナのスケジュールが失敗すると思います。

必要なディスク領域は、ログ容量に依存するいので、基準はありませんがここではノード辺り`200G`用意する事にします。


| サーバー                    | vCPU(HT-on)   | Memory       |  OS Disk |  OS   |         ホスト名            | IP Address  
|:---------------------------|:--------------|:-------------|:--------|:--------|:---------------------------|:------------
|Infraノード 1               | 4vCPU         | 32GByte     | 120G    |  CoreOS |i1.ocp45.example.localdomain |172.16.0.51 |     | 
|Infraノード 2                | 4vCPU         | 32GByte     | 120G    |  CoreOS |i2.ocp45.example.localdomain|172.16.0.52 |     | 
|Infraノード 3                | 4vCPU         | 32GByte     | 120G    | CoreOS |i3.ocp45.example.localdomain|172.16.0.53 |     | 

この手順では、Cluster Logging用のWorkerノードを、インフラコンポーネント用のノードという意味でInfraノードと呼ぶ事にします。(この呼び方は、OpenShift独自の呼び方です）

# 3.環境の設計

`Cluster Logging`は、比較的重たいコンポーネントであるため、ユーザーコンテナ向けのワークロードとは被らないようにスケジュールするのが理想です。

そのために`Infraノード`という専用の`Workerノード`を準備します。
実環境を考えた場合いに`label`や`nodeSelector`、`taint`を使って、`Pod`を配置していく必要があり、そのための設計が必要になります。

この手順では、以下のような環境に、`Cluster Logging`をインストールする事を考えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/8b9597ce-6eab-f048-fabd-5a072b358c03.png)


`Cluster Logging`のメインのコンポーネントは、緑色の三本の`ノード`に`nodeSelector`を指定してインストールします。

一方で、この三本の`ノード`に他のコンポーネントがスケジュールされないように`taint`を付ける必要があります。同時に自分自身がその`taint`の影響を受けないようにする必要があります。

Log収集用の`fluentd`は、全ての`ノード`にインストールする必要があるので、`taint`が付いている`ノード`に対する`toleration`が必要になってきます。

例えば上記の例では、`OCS(Open Container Storage)` が、自分の`ノード`にユーザーのアプリケーションコンテナが配置されないように`taint`を付けていますが、`fluetnd`は配置する必要があるので、`fluentd`に対して`OCSノード`が付けている`taint`に対する`toleration`を付けてあげる必要があります。

この例で`Masterノード`に`taint`が付いてますが、この`taint`については、デフォルトで考慮されているので、ユーザーが`Cluster Logging`のインストール時に考慮する必要はありません。

**補則**

`taint`や`toleration`の話は最初は複雑なのでガイドから抜いていたのですが、実運用を考えると必ず必要で、私自身がやってみてかなり嵌まったので、事前に考えるべき事として、この項目を入れました。もし、テスト環境などで、まず動かしてみたいという方は、特に`Pod`を追い出したり動きを制限する`taint`の部分は全てスキップするのが良いと思います。思わぬ環境破壊につながる事があります。

# 4.環境の準備

## 4.1.Cluster Logging インストールのための前提

`Cluster Logging`をインストールするための前提が２つあります。

1. `ElasticSearch`用の`PV(Persistent Volume)`が作成できるようになっている事
2. 専用の`Workerノード`が3本、準備されている事

1.に関しては、この手順では`OCS(OpenShift Container Storage)`が存在している事が前提になっていますが、`PV`が作成できる環境であれば、`PVC`を行う時の`Storage Class`名が異なる以外は同じ手順になります。

2.に関しては、ユーザーアプリケーションのコンテナが動く`Workerノード`にインストールする事も可能ですが、実運用を考えると現実的な選択とは言えないため、この手順では、[2.サイジング](2.サイジング)に書いてある通り、専用の`Workerノード`が用意されているものとします。

### 4.2.1.Cluster Logging 用Workerノードに infra Role のラベルを貼る

※この作業は既に行っている場合は必要ありません。

`Cluster Logging`用の`Workerノード`に対して、`Infraノード`としてのラベルを振ります。
このラベルがある所に`Cluster Logging`の幾つかのコンポーネントを`nodeSelector`を使ってスケジュールします。

また、このラベルはユーザーの目に見える部分で動作に影響するものではありませんが、`OpenShift`が内部的に、ユーザーアプリケーション用の`Workerノード`と区別するために使われます。

以下のコマンドを実行します。

```
# oc label node i1.ocp45.example.localdomain node-role.kubernetes.io/infra=
# oc label node i2.ocp45.example.localdomain node-role.kubernetes.io/infra=
# oc label node i3.ocp45.example.localdomain node-role.kubernetes.io/infra=
```

`infra`のラベルが貼られている事を確認します。

```
[root@bastion openshift]#  oc get nodes
NAME                           STATUS   ROLES          AGE   VERSION
i1.ocp45.example.localdomain   Ready    infra,worker   15h   v1.18.3+47c0e71
i2.ocp45.example.localdomain   Ready    infra,worker   15h   v1.18.3+47c0e71
i3.ocp45.example.localdomain   Ready    infra,worker   15h   v1.18.3+47c0e71
m1.ocp45.example.localdomain   Ready    master         15h   v1.18.3+47c0e71
m2.ocp45.example.localdomain   Ready    master         15h   v1.18.3+47c0e71
m3.ocp45.example.localdomain   Ready    master         15h   v1.18.3+47c0e71
s1.ocp45.example.localdomain   Ready    infra,worker   66m   v1.18.3+47c0e71
s2.ocp45.example.localdomain   Ready    infra,worker   66m   v1.18.3+47c0e71
s3.ocp45.example.localdomain   Ready    infra,worker   66m   v1.18.3+47c0e71
w1.ocp45.example.localdomain   Ready    worker         15h   v1.18.3+47c0e71
w2.ocp45.example.localdomain   Ready    worker         15h   v1.18.3+47c0e71
w3.ocp45.example.localdomain   Ready    worker         15h   v1.18.3+47c0e71
[root@bastion openshift]# 
```
`OpenShift`では、`kubernetes`と違い、`Workerノード`の部分に明示的に`worker`という`role`が振られています。

Webを検索すると`worker`としてのラベルを外す手順が出てくる場合がありますが、`worker` Role のラベルはここでは外さないでそのままにしておきます。(`worker`のラベルは、`OpenShift`が提供している特殊な`Operator`が認識に使用しているため、外す場合は、`Maching Config Pool`という追加リソースを作成する必要がでてきます。)

# 5.Cluster Loggingのインストール

## 5.1 Elasticsearch Operator のインストール

`OperatorHub` から、`Elasticsearch Operator`を探します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/1cc6f3f3-8ed3-d164-1733-02de967ce15b.png)

`Install`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/5a3788d0-37f4-0cf2-36d0-ad34399fd1c5.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/46001cf1-8476-f66d-bef3-2880c72bb5c5.png)

`Installation Mode` が 「`All namespaces on the cluster`」である事を確します。(デフォルト）
`Installed Namespace` は、「`openshift-operators-redhat`」である事を確認します。（デフォルト）
`Enable operator recommended cluster monitoring on this namespace` にチェックを入れます。

後は`Install`ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/901a139a-556c-74a6-d51d-b98d14e57a04.png)
`Installed Operator`で、`Elasticsearch Operator` が `Succeeded`になっていればOKです。

## 5.2. Cluster Logging Operator のインストール

`OperatorHub` から、`Cluster Logging Operator`を探します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/ad26d9d6-e84b-155b-165e-6b850a96fb88.png)

`Install`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/27d0a157-57cf-1796-506d-0f65721bb5c3.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/ae4d90b0-66b0-f53d-32df-f5b8190aeb0a.png)

`Installed Namepsace` は、`openshift-logging`にします。（デフォルト）
`Enable operator recommended cluster monitoring on this namespace` のチェックを入れます。
後は、`Install`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/9f4bc394-ecec-6ae2-b749-9b425a92e6ff.png)
`Installed Operator`で、`Cluster Logging` が `Succeeded`になっていればOKです。

## 5.3. Cluster Logging のインスタンスを作成する

`Administration` → `Custom Resource Definitions` から `ClusterLogging` という `CRD(Custom Resource Definition)`を探します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/4ca0e37e-f5f8-076c-0b8e-286dd67a0547.png)

`Create ClusterLogging` をクリックして、`ClusterLogging`のインスタンスを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/b8a2768b-6ee2-29e2-c0b4-c60f11bf8640.png)

デフォルトの YAMLを以下のような YAMLに書き替えます。YAMLのラベルの前の部分には、全角やタブが入らないように注意します。

また、このYAML内から`PVC(Persistent Volume Claim)`を行って、ログ収集用のボリュームを作成しています。**PVCをするだけで、PVが作成される(動的プロビジョニング(Dynamic Volume Provisioning)環境である事が前提になっています。**

`ClusterLogging`のインスタンス名(`name:`)が、`instance`と、かなり直球な名前になっていますが、マニュアルなどの例が`instance`となっているので、参照時にわかりやすいようにそのまま使う事にします。

```入力する.yaml
apiVersion: "logging.openshift.io/v1"
kind: "ClusterLogging"
metadata:
  name: "instance" 
  namespace: "openshift-logging"
spec:
  managementState: "Managed"  
  logStore:
    type: "elasticsearch"  
    retentionPolicy:  #(1) ログの保管期間
      application:
        maxAge: 1d
      infra:
        maxAge: 7d
      audit:
        maxAge: 7d
    elasticsearch:
      nodeSelector:                                 # (1) スケジュールする node を指定
          node-role.kubernetes.io/infra: ''         #      Infra node を指定
      tolerations:                                  # (2) tolerationの指定
        - effect: NoSchedule                        #
          key: infra                                #
          value: reserved                           #
        - effect: NoExecute                         #
          key: infra                                #
          value: reserved                           #
      nodeCount: 3                                      # (3) ElasticSerachのノード数。通常3 です。
      storage:
        storageClassName: "ocs-storagecluster-cephfs"   # (4) PVを作るStorage Class名。環境によって異なる。
        size: 200G                                      # (5) PVのサイズは　200G　に設定 
      redundancyPolicy: "SingleRedundancy"
  visualization:
    type: "kibana"  
    kibana:
      nodeSelector:                                 # (1) スケジュールする node を指定
          node-role.kubernetes.io/infra: ''         #     Infra node を指定
      tolerations:                                  # (2) tolerationの指定
        - effect: NoSchedule                        #
          key: infra                                #
          value: reserved                           #
        - effect: NoExecute                         #
          key: infra                                #
          value: reserved                           #
      replicas: 1
  curation:
    type: "curator"
    curator:
      nodeSelector:                                 # (1) スケジュールする node を指定
          node-role.kubernetes.io/infra: ''         #     Infra node を指定
      tolerations:                                  # (2) tolerationの指定
        - effect: NoSchedule                        #
          key: infra                                #
          value: reserved                           #
        - effect: NoExecute                         #
          key: infra                                #
          value: reserved                           #
      resources: null
      schedule: "30 3 * * *" 
  collection:
   logs:
    type: "fluentd"  
    fluentd: 
     tolerations:                                  # (6) Infra Node用 tolerationの指定
           - effect: NoSchedule                        # 
             key: infra                                #
             value: reserved                           #
           - effect: NoExecute                         #
             key: infra                                #
             value: reserved                           #
           - effect: NoSchedule                        # (7) Storage Node用 tolerationの指定
             key: node.ocs.openshift.io/storage        # 
             value: "true"                             # 

```
`(1)`の`nodeSelector`を使って`Infraノード`にコンポーネントをインストールするように指定します。
`(2)``Infraノード`には他のコンポーネントの`Pod`がスケジュールされないように`taint`が付けてあります。`taint`を無視するように`tolearation`を付けています。

`(4)` の`Storage Class`名は、環境によって異なります。この例は、`OCS`をした時に自動で追加される`Storage Class`、`ocs-storagecluster-cephfs` (CephFS)を使っています。AWSのIPIインストール環境では、"gp2"がデフォルトで使用できます。

`Storage Class`は、`PVC`が削除された時のデータの扱い(`Reclaim Ploicy`)も定義しています。上記の`Storage Class`、`ocs-storagecluster-cephfs`は、`Delete`ですので、もし`Retain`等がよければ別の`Storage Class`を作成します。

`(6)``fluentd`は、Log収集のため全てのコンポーネントに配置される必要があります。そのためこの環境で`ノード`に付けられている`taint`に対する`toleration`を指定しています。`Masterノード`については、デフォルトで考慮されているため、指定する必要はありません。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/3a1a184b-3b5b-7f5b-c647-a91162b1623a.png)

yaml を貼り付けた後は、`Create`をクリックします。

<a href="https://access.redhat.com/documentation/en-us/openshift_container_platform/4.5/html/logging/configuring-your-cluster-logging-deployment">参考:3.1. About the Cluster Logging Custom Resource</a>

## 5.4.Cluser Logging コンポーネントのデプロイの確認



### 5.4.1.PVのデプロイの確認

`Storage` -> `Persistent Volumes` で、`elasticsearch-elasticearchi-cdm-...` という `PVC`名と紐付いた`Volume`が3つデプロイされているを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/730d8b69-98e8-da79-da59-820574e66117.png)


### 5.4.2.Podのデプロイの確認

`Workloads` -> `Pods` で、`Project`名で `openshift-logging`を選択し、`Pod`が全て `Running` になるのを待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/02fbf5ab-e633-c8c4-8f7b-4bed0ec563a8.png)

`Pod`が全て起動していれば、全てのコンポーネントのインストールが完了です。
コマンドラインでも同様に確認できます。

```
[root@bastion ~]# oc get pod -n openshift-logging
NAME                                            READY   STATUS      RESTARTS   AGE
cluster-logging-operator-d5566bd54-mww66        1/1     Running     0          6h57m
elasticsearch-cdm-2wa40yud-1-7d9ff5446f-lgrrw   2/2     Running     0          6h26m
elasticsearch-cdm-2wa40yud-2-f4f44fc9d-pm8b6    2/2     Running     0          6h26m
elasticsearch-cdm-2wa40yud-3-7fcd6c6f6c-v7bp2   2/2     Running     0          6h26m
elasticsearch-delete-app-1603892700-n6ndg       0/1     Completed   0          14m
elasticsearch-delete-audit-1603892700-sbd9p     0/1     Completed   0          14m
elasticsearch-delete-infra-1603892700-2q6kz     0/1     Completed   0          14m
elasticsearch-rollover-app-1603892700-brd9f     0/1     Completed   0          14m
elasticsearch-rollover-audit-1603892700-td8jk   0/1     Completed   0          14m
elasticsearch-rollover-infra-1603892700-f4kz9   0/1     Completed   0          14m
fluentd-666q4                                   1/1     Running     0          6h27m
fluentd-8xgkj                                   1/1     Running     0          6h27m
fluentd-9nhsn                                   1/1     Running     0          6h27m
fluentd-bjjzp                                   1/1     Running     0          6h27m
fluentd-bntmp                                   1/1     Running     0          6h27m
fluentd-bvxwj                                   1/1     Running     0          6h27m
fluentd-ffrjm                                   1/1     Running     0          6h27m
fluentd-fk7sr                                   1/1     Running     0          6h27m
fluentd-hb6hk                                   1/1     Running     0          6h27m
fluentd-l8bzv                                   1/1     Running     0          6h27m
fluentd-t9zvw                                   1/1     Running     0          6h27m
fluentd-vp5qn                                   1/1     Running     0          6h27m
kibana-5475bd69c4-n4rkd                         2/2     Running     0          6h27m
[root@bastion ~]#
```

ログ収集用の`fluentd-xxxx`の`Pod`の数は、全ての`ノード`本数分あるはずです。

`fluentd`以外のコンポーネントがどこに配置されているか確認してみます。

```
[root@bastion ~]# oc describe pods cluster-logging-operator-d5566bd54-mww66 -n openshift-logging | grep Node:
Node:         w1.ocp45.example.localdomain/172.16.0.31
[root@bastion ~]# oc describe pods elasticsearch-cdm-2wa40yud-1-7d9ff5446f-crdgc  -n openshift-logging | grep Node:
Node:         i1.ocp45.example.localdomain/172.16.0.41
[root@bastion ~]# oc describe pods elasticsearch-cdm-2wa40yud-2-f4f44fc9d-vr642  -n openshift-logging | grep Node:
Node:         i2.ocp45.example.localdomain/172.16.0.42
[root@bastion ~]# oc describe pods elasticsearch-cdm-2wa40yud-3-7fcd6c6f6c-f4l72 -n openshift-logging | grep Node:
Node:         i3.ocp45.example.localdomain/172.16.0.43
[root@bastion ~]# oc describe pods elasticsearch-delete-app-1603948500-bmct2 -n openshift-logging | grep Node:
Node:         i1.ocp45.example.localdomain/172.16.0.41
[root@bastion ~]# oc describe pods elasticsearch-delete-audit-1603948500-fmq7v   -n openshift-logging | grep Node:
Node:         i2.ocp45.example.localdomain/172.16.0.42
[root@bastion ~]# oc describe pods elasticsearch-delete-infra-1603948500-phjsj  -n openshift-logging | grep Node:
Node:         i1.ocp45.example.localdomain/172.16.0.41
[root@bastion ~]# oc describe pods elasticsearch-rollover-app-1603948500-mx4hm   -n openshift-logging | grep Node:
Node:         i1.ocp45.example.localdomain/172.16.0.41
[root@bastion ~]# oc describe pods elasticsearch-rollover-audit-1603948500-wxsgk   -n openshift-logging | grep Node:
Node:         i3.ocp45.example.localdomain/172.16.0.43
[root@bastion ~]# oc describe pods elasticsearch-rollover-infra-1603948500-8c2th  -n openshift-logging | grep Node:
Node:         i2.ocp45.example.localdomain/172.16.0.42
[root@bastion ~]# oc describe pods kibana-5475bd69c4-n4rkd  -n openshift-logging | grep Node:
Node:         i3.ocp45.example.localdomain/172.16.0.43
[root@bastion ~]# 
```

`cluster-logging-operator-`が、`Workerノード`にスケジュールされている以外は、`Infraノード`にスケジュールされています。

少し気持ち悪いですが、`Elasticsearch`、`Kibana`と言った負荷の高いコンポーネントが`Infraノード`に配置されているので、一旦、これで良しとします。

### 5.4.3.Kibana へのアクセス確認

`Kibana`にアクセスしてみます。

`Networking` -> `Routes` に `Kibana`という名前の `Route` が出てきているはずです。表示されているリンクをクリックします。ログインウィンドウが出ますが、Userid / Password は、OpenShift のIDがそのまま使えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/d992f4ee-2627-8130-c48b-d7dbeb7b13f3.png)

`OAuth`の許可画面です。現在のユーザーに、表示されているアクセスを許可します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/12f51ddc-c5c3-c244-f283-66c59f11cbab.png)

`Kibana`の画面が表示されれば OKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/acea1b77-cb08-a2bd-e81f-df6521a64b74.png)

# 6.環境の再作成について

環境の構築に失敗した場合は、以下の手順で Operatorの導入直後 (この手順だと[5.3.Cluster Loggingのインスタンスを作成する](#53-cluster-logging-のインスタンスを作成する) の直前まで)戻る事ができます。

 1. ClusterLogging のインスタンスを削除する

```
oc delete clusterlogging instance -n openshift-logging
```

 2. 作成した PVC を削除する


# 7.リソースの使用量について

導入した環境では、クラスターを作成したわけではなく、特にアプリケーションを動かしているわけでは無いので、ほぼ無負荷だと思うのですが、メモリに関してはかなり消費しています。

`elasticsearch-cdm-jthway98-xxxx`に関しては、`Elasticsearch`を構成する`3ノード`にそれぞれ配置される`Pod`ですが、おのおのの`Pod`がMemoryを10GByte程度使用しているので、十分なリソースを確保した環境にインストールする必要がある事がわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/6754b45c-f472-7d58-43f2-5391a5125d5f.png)