5.9. コンテナーでの sysctl の使用

sysctl 設定は Kubernetes 経由で公開され、ユーザーがコンテナー内の namespace の特定のカーネルパラメーターをランタイム時に変更できるようにします。namespace を使用する sysctl のみを Pod 上で独立して設定できます。sysctl に namespace が使用されていない場合 (この状態は ノードレベル と呼ばれる)、OpenShift Container Platform 内でこれを設定することはできません。さらに 安全 とみなされる sysctl のみがデフォルトでホワイトリスト化されます。 他の 安全でない sysctl はノードで手動で有効にし、ユーザーが使用できるようにできます。

5.9.1. sysctl について

Linux では、管理者は sysctl インターフェースを使ってランタイム時にカーネルパラメーターを変更することができます。パラメーターは /proc/sys/ 仮想プロセスファイルシステムで利用できます。これらのパラメーターは以下を含む各種のサブシステムを対象とします。

  • カーネル (共通のプレフィックス: kernel.)
  • ネットワーク (共通のプレフィックス: net.)
  • 仮想メモリー (共通のプレフィックス: vm.)
  • MDADM (共通のプレフィックス: dev.)

追加のサブシステムについては、カーネルのドキュメント で説明されています。すべてのパラメーターの一覧を表示するには、以下のコマンドを実行します。

$ sudo sysctl -a

5.9.1.1. namespace を使用した sysctl vs ノードレベルの sysctl

Linux カーネルでは、数多くの sysctl に namespace が使用されています。これは、それらをノードの各 Pod に対して個別に設定できることを意味します。namespace の使用は、sysctl を Kubernetes 内の Pod 環境でアクセス可能にするための要件になります。

以下の sysctl は namespace を使用するものとして知られている sysctl です。

  • kernel.shm*
  • kernel.msg*
  • kernel.sem
  • fs.mqueue.*

また、net.* グループの大半の sysctl には namespace が使用されていることが知られています。それらの namespace の使用は、カーネルのバージョンおよびディストリビューターによって異なります。

namespace が使用されていない sysctl は ノードレベル と呼ばれており、クラスター管理者がノードの基礎となる Linux ディストリビューションを使用 (例: /etc/sysctls.conf ファイルを変更) するか、または特権付きコンテナーでデーモンセットを使用することによって手動で設定する必要があります。

注記

特殊な sysctl が設定されたノードにテイントのマークを付けることを検討してください。それらの sysctl 設定を必要とするノードにのみ Pod をスケジュールします。テイントおよび容認 (Toleration) 機能を使用してノードにマークを付けます。

5.9.1.2. 安全 vs 安全でない sysctl

sysctl は 安全な および 安全でない sysctl に分類されます。

sysctl が安全であるとみなされるには、適切な namespace を使用し、同じノード上の Pod 間で適切に分離する必要があります。Pod ごとに sysctl を設定する場合は、以下の点に留意してください。

  • この設定はノードのその他の Pod に影響を与えないものである。
  • この設定はノードの正常性に負の影響を与えないものである。
  • この設定は Pod のリソース制限を超える CPU またはメモリーリソースの取得を許可しないものである。

OpenShift Container Platform は以下の sysctl を安全なセットでサポートするか、またはホワイトリスト化します。

  • kernel.shm_rmid_forced
  • net.ipv4.ip_local_port_range
  • net.ipv4.tcp_syncookies

すべての安全な sysctl はデフォルトで有効にされます。Pod 仕様を変更して、Pod で sysctl を使用できます。

OpenShift Container Platform でホワイトリスト化されない sysctl は OpenShift Container Platform で安全でないと見なされます。namespace を使用するだけで、sysctl が安全であるとみなされる訳ではありません。

すべての安全でない sysctl はデフォルトで無効にされ、ノードごとにクラスター管理者によって手動で有効にされる必要があります。無効にされた安全でない sysctl が設定された Pod はスケジュールされますが、起動されません。

$ oc get pod

出力例

NAME        READY   STATUS            RESTARTS   AGE
hello-pod   0/1     SysctlForbidden   0          14s

5.9.2. Pod の sysctl 設定

Pod の securityContextを使用して sysctl を Pod に設定できます。securityContext は同じ Pod 内のすべてのコンテナーに適用されます。

安全な sysctl はデフォルトで許可されます。安全でない sysctl が設定された Pod は、クラスター管理者がそのノードの安全でない sysctl を明示的に有効にしない限り、いずれのノードでも起動に失敗します。ノードレベルの sysctl の場合のように、それらの Pod を正しいノードにスケジュールするには、テイントおよび容認 (Toleration)、またはノードのラベルを使用します。

以下の例では、Pod の securityContext を使用して安全な sysctl kernel.shm_rmid_forced および 2 つの安全でない sysctl net.ipv4.route.min_pmtu および kernel.msgmax を設定します。仕様では 安全な sysctl と 安全でない sysctl は区別されません。

警告

オペレーティングシステムが不安定になるのを防ぐには、変更の影響を確認している場合にのみ sysctl パラメーターを変更します。

手順

安全なおよび安全でない sysctl を使用するには、以下を実行します。

  1. 以下の例に示されるように、Pod を定義する YAML ファイルを変更し、securityContext 仕様を追加します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: sysctl-example
    spec:
      securityContext:
        sysctls:
        - name: kernel.shm_rmid_forced
          value: "0"
        - name: net.ipv4.route.min_pmtu
          value: "552"
        - name: kernel.msgmax
          value: "65536"
      ...
  2. Pod を作成します。

    $ oc apply -f <file-name>.yaml

    安全でない sysctl がノードに許可されていない場合、Pod はスケジュールされますが、デプロイはされません。

    $ oc get pod

    出力例

    NAME        READY   STATUS            RESTARTS   AGE
    hello-pod   0/1     SysctlForbidden   0          14s

5.9.3. 安全でない sysctl の有効化

クラスター管理者は、高パフォーマンスまたはリアルタイムのアプリケーション調整などの非常に特殊な状況で特定の安全でない sysctl を許可することができます。

安全でない sysctl を使用する必要がある場合、クラスター管理者は特定のタイプのノードに対してそれらを個別に有効にする必要があります。sysctl には namespace を使用する必要があります。

警告

安全でないという性質上、安全でない sysctl は各自の責任で使用されます。 場合によっては、コンテナーの正しくない動作やリソース不足、またはノードの破損などの深刻な問題が生じる可能性があります。

手順

  1. ラベルを安全でない sysctl が設定されたコンテナーが実行されるマシン設定プールに追加します。

    $ oc edit machineconfigpool worker
    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfigPool
    metadata:
      creationTimestamp: 2019-02-08T14:52:39Z
      generation: 1
      labels:
        custom-kubelet: sysctl 1
    1
    key: pair ラベルを追加します。
  2. KubeletConfig カスタムリソース (CR) を作成します。

    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: custom-kubelet
    spec:
      machineConfigPoolSelector:
        matchLabels:
          custom-kubelet: sysctl 1
      kubeletConfig:
        allowedUnsafeSysctls: 2
          - "kernel.msg*"
          - "net.ipv4.route.min_pmtu"
    1
    マシン設定プールからラベルを指定します。
    2
    許可する必要のある安全でない sysctl を一覧表示します。
  3. オブジェクトを作成します。

    $ oc apply -f set-sysctl-worker.yaml

    99-worker-XXXXXX-XXXXX-XXXX-XXXXX-kubelet 形式で指定される新規の MachineConfig オブジェクトが作成されます。

  4. machineconfigpool オブジェクトの status フィールドを使用してクラスターが再起動するのを待機します。

    以下は例になります。

    status:
      conditions:
        - lastTransitionTime: '2019-08-11T15:32:00Z'
          message: >-
            All nodes are updating to
            rendered-worker-ccbfb5d2838d65013ab36300b7b3dc13
          reason: ''
          status: 'True'
          type: Updating

    クラスターの準備ができると、以下のようなメッセージが表示されます。

       - lastTransitionTime: '2019-08-11T16:00:00Z'
          message: >-
            All nodes are updated with
            rendered-worker-ccbfb5d2838d65013ab36300b7b3dc13
          reason: ''
          status: 'True'
          type: Updated
  5. クラスターが準備状態になる場合、新規 MachineConfig オブジェクトでマージされた KubeletConfig オブジェクトを確認します。

    $ oc get machineconfig 99-worker-XXXXXX-XXXXX-XXXX-XXXXX-kubelet -o json | grep ownerReference -A7
            "ownerReferences": [
                {
                    "apiVersion": "machineconfiguration.openshift.io/v1",
                    "blockOwnerDeletion": true,
                    "controller": true,
                    "kind": "KubeletConfig",
                    "name": "custom-kubelet",
                    "uid": "3f64a766-bae8-11e9-abe8-0a1a2a4813f2"

    安全でない sysctl を必要に応じて Pod に追加することができるようになります。