Openshift4: Node Tuning Operatorを設定してみた

### 概要

Openshiftでアプリコンテナを稼働させるときに、
「ちょっと、kernel parameter変えてたいんだけど」
ということは多々あります。

ベアメタルなどで、Node自体も自分で立ててる場合は、NodeのOS設定値を替えてしまう手もありますが、CoreOSを使用している場合、どこまで反映が維持されるのかわかりません。
ここでは、node自体のパラメーター変更をするために、Openshift4のNode Tuning Operatorを利用してみました。

ここで設定しているのは、ベアメタル上にVMたてて構築したOCP4.3です。

※変更は自己責任でお願いします
※ [karnel parameterの資料](https://github.com/torvalds/linux/tree/v4.15/Documentation/sysctl)はこちらを参照してください。

### Node Tuning Operatorの反映順序

Node Tuning Operatorの設定は、作成したUser ProfileのPriorityとそのnodeのラベルや稼働しているPodのラベルに一致しているかどうかで判断されます。

defaultのCRですでに以下の2種類のUser Profileが設定され、追加でopenshift-tune-testのUser Profileが作成されているとします。
(抜粋しています。各Profileで設定する値は省略しています)

```yaml:default
  - match:
    - label: node-role.kubernetes.io/master
    - label: node-role.kubernetes.io/infra
    priority: 30
    profile: openshift-control-plane
  - priority: 40
    profile: openshift-node
```
```yaml:openshift-tune-test
  recommend:
  - match:
    - label: ise-test-pod
      type: pod
    priority: 20
    profile: openshift-tune-test
```
また、あるnodeでは`ise-test-pod`のlabelのついたpodがrunning状態です。
その場合、以下の図のようにprioriyとmatchで判断されてnodeに設定値が反映されます。

![ocp-nodetuning.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146314/dae1a78d-9eeb-2baa-678d-4d7f43634688.png)



### 手順

Node Tuning OperatorにはTuned/defaultのCRがすでに作成されています。
独自にkernel parameterを変更するためには、新規にUserProfileを作成します。

defaultではPriorityの30, 40が使用されているので、それよりも優先度を高く(数字を小さく)します。
また、Node Tuning Operatorは`openshift-cluster-node-tuning-operator`のNamespaceにあります。

```
$ oc get Tuned/default -o yaml -n openshift-cluster-node-tuning-operator
apiVersion: tuned.openshift.io/v1
kind: Tuned
metadata:
  creationTimestamp: "2020-09-24T12:48:50Z"
  generation: 1
  name: default
  namespace: openshift-cluster-node-tuning-operator
  resourceVersion: "8430"
  selfLink: /apis/tuned.openshift.io/v1/namespaces/openshift-cluster-node-tuning-operator/tuneds/default
  uid: e3183298-7a34-4c42-97ba-eacf04c2aed5
spec:
  profile:
  - data: |
      [main]
      summary=Optimize systems running OpenShift (parent profile)
      include=${f:virt_check:virtual-guest:throughput-performance}

      [selinux]
      avc_cache_threshold=8192

      [net]
      nf_conntrack_hashsize=131072

      [sysctl]
      net.ipv4.ip_forward=1
      kernel.pid_max=>4194304
      net.netfilter.nf_conntrack_max=1048576
      net.ipv4.conf.all.arp_announce=2
      net.ipv4.neigh.default.gc_thresh1=8192
      net.ipv4.neigh.default.gc_thresh2=32768
      net.ipv4.neigh.default.gc_thresh3=65536
      net.ipv6.neigh.default.gc_thresh1=8192
      net.ipv6.neigh.default.gc_thresh2=32768
      net.ipv6.neigh.default.gc_thresh3=65536
      vm.max_map_count=262144

      [sysfs]
      /sys/module/nvme_core/parameters/io_timeout=4294967295
      /sys/module/nvme_core/parameters/max_retries=10
    name: openshift
  - data: |
      [main]
      summary=Optimize systems running OpenShift control plane
      include=openshift

      [sysctl]
      # ktune sysctl settings, maximizing i/o throughput
      #
      # Minimal preemption granularity for CPU-bound tasks:
      # (default: 1 msec#  (1 + ilog(ncpus)), units: nanoseconds)
      kernel.sched_min_granularity_ns=10000000
      # The total time the scheduler will consider a migrated process
      # "cache hot" and thus less likely to be re-migrated
      # (system default is 500000, i.e. 0.5 ms)
      kernel.sched_migration_cost_ns=5000000
      # SCHED_OTHER wake-up granularity.
      #
      # Preemption granularity when tasks wake up.  Lower the value to
      # improve wake-up latency and throughput for latency critical tasks.
      kernel.sched_wakeup_granularity_ns=4000000
    name: openshift-control-plane
  - data: |
      [main]
      summary=Optimize systems running OpenShift nodes
      include=openshift

      [sysctl]
      net.ipv4.tcp_fastopen=3
      fs.inotify.max_user_watches=65536
      fs.inotify.max_user_instances=8192
    name: openshift-node
  recommend:
  - match:
    - label: node-role.kubernetes.io/master
    - label: node-role.kubernetes.io/infra
    priority: 30
    profile: openshift-control-plane
  - priority: 40
    profile: openshift-node
status: {}
```

以下のyamlを作成して、反映させます。

``` tuned-kernel-test.yaml
apiVersion: tuned.openshift.io/v1
kind: Tuned
metadata:
  name: openshift-tune-test
  namespace: openshift-cluster-node-tuning-operator
spec:
  profile:
  - data: |
      [main]
      summary=Optimize systems running test pod on OpenShift nodes
      include=openshift-node
      [sysctl]
      net.core.rmem_max=9999999
      net.core.wmem_max=9999999
    name: openshift-tune-test
  recommend:
  - match:
    - label: ise-test-pod
      type: pod
    priority: 20
    profile: openshift-tune-test
```

Podをdeployする前のnodeの状況を確認します。

```
$ oc debug node/worker01.ots.ocplab.com
Starting pod/worker01otsocplabcom-debug ...
To use host binaries, run `chroot /host`
Pod IP: 10.193.85.147
If you don't see a command prompt, try pressing enter.
sh-4.2# chroot /host
sh-4.4# sysctl -a | grep net.core.rmem_max
net.core.rmem_max = 212992
sh-4.4# sysctl -a | grep net.core.wmem_max
net.core.wmem_max = 212992
sh-4.4#
```
`ise-test-pod`のlabelのついたpodをdeployします。

```
$ oc get po -o wide
NAME                         READY   STATUS    RESTARTS   AGE   IP            NODE                      NOMINATED NODE   READINESS GATES
testpod-696684d4f8-hvnbx   1/1     Running   0          25m   10.131.0.21   worker01.ots.ocplab.com   <none>           <none>
```

パラメーターを確認します。

```
$ oc debug node/worker01.ots.ocplab.com
Starting pod/worker01otsocplabcom-debug ...
To use host binaries, run `chroot /host`
Pod IP: 10.193.85.147
If you don't see a command prompt, try pressing enter.
sh-4.2# chroot /host
sh-4.4# sysctl -a | grep net.core.rmem_max
net.core.rmem_max = 9999999
sh-4.4# sysctl -a | grep net.core.wmem_max
net.core.wmem_max = 9999999
sh-4.4#
```

### 参考
[Openshiftドキュメント：4.5. Node Tuning Operator の使用](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.4/html/nodes/nodes-node-tuning-operator)