Red Hat Training

A Red Hat training course is available for OpenShift Container Platform

第2章 ノードの管理

2.1. 概要

インスタンスのノードは、CLI を使用して管理することができます。

ノードの管理操作を実行する際、CLI は実際のノードホストの表現であるノードオブジェクトと対話します。マスターはノードオブジェクトの情報を使用し、ヘルスチェックでノードの検証を実行します。

2.2. ノードの一覧表示

マスターに認識されるすべてのノードを一覧表示するには、以下を実行します。

$ oc get nodes

出力例

NAME                   STATUS    ROLES     AGE       VERSION
master.example.com     Ready     master    7h        v1.9.1+a0ce1bc657
node1.example.com      Ready     compute   7h        v1.9.1+a0ce1bc657
node2.example.com      Ready     compute   7h        v1.9.1+a0ce1bc657

ノードの情報を含むプロジェクトの Pod デプロイメントについての情報と共にすべてのノードを一覧表示するには、以下を実行します。

$ oc get nodes -o wide

出力例

NAME                           STATUS    ROLES     AGE       VERSION           EXTERNAL-IP      OS-IMAGE                                      KERNEL-VERSION          CONTAINER-RUNTIME
ip-172-18-0-39.ec2.internal    Ready     infra     1d        v1.10.0+b81c8f8   54.172.185.130   Red Hat Enterprise Linux Server 7.5 (Maipo)   3.10.0-862.el7.x86_64   docker://1.13.1
ip-172-18-10-95.ec2.internal   Ready     master    1d        v1.10.0+b81c8f8   54.88.22.81      Red Hat Enterprise Linux Server 7.5 (Maipo)   3.10.0-862.el7.x86_64   docker://1.13.1
ip-172-18-8-35.ec2.internal    Ready     compute   1d        v1.10.0+b81c8f8   34.230.50.57     Red Hat Enterprise Linux Server 7.5 (Maipo)   3.10.0-862.el7.x86_64   docker://1.13.1

単一ノードについての情報のみを一覧表示するには、<node> を完全なノード名に置き換えます。

$ oc get node <node>

これらのコマンドの出力にある STATUS 列には、ノードの以下の状態が表示されます。

表2.1 ノードの状態

条件説明

Ready

ノードは StatusOK を返し、マスターから実行されるヘルスチェックをパスしています。

NotReady

ノードはマスターから実行されるヘルスチェックをパスしていません。

SchedulingDisabled

ノードへの Pod の配置をスケジュールできません。

注記

STATUS 列には、CLI でノードの状態を検索できない場合にノードについて Unknown が表示されます。

現在の状態の理由を含む特定ノードについての詳細情報を取得するには、以下を実行します。

$ oc describe node <node>

例:

$ oc describe node node1.example.com

出力例

Name:               node1.example.com 1
Roles:              compute 2
Labels:             beta.kubernetes.io/arch=amd64 3
                    beta.kubernetes.io/os=linux
                    kubernetes.io/hostname=m01.example.com
                    node-role.kubernetes.io/compute=true
                    node-role.kubernetes.io/infra=true
                    node-role.kubernetes.io/master=true
                    zone=default
Annotations:        volumes.kubernetes.io/controller-managed-attach-detach=true  4
CreationTimestamp:  Thu, 24 May 2018 11:46:56 -0400
Taints:             <none>   5
Unschedulable:      false
Conditions:                  6
  Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----             ------  -----------------                 ------------------                ------                       -------
  OutOfDisk        False   Tue, 17 Jul 2018 11:47:30 -0400   Tue, 10 Jul 2018 15:45:16 -0400   KubeletHasSufficientDisk     kubelet has sufficient disk space available
  MemoryPressure   False   Tue, 17 Jul 2018 11:47:30 -0400   Tue, 10 Jul 2018 15:45:16 -0400   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure     False   Tue, 17 Jul 2018 11:47:30 -0400   Tue, 10 Jul 2018 16:03:54 -0400   KubeletHasNoDiskPressure     kubelet has no disk pressure
  Ready            True    Tue, 17 Jul 2018 11:47:30 -0400   Mon, 16 Jul 2018 15:10:25 -0400   KubeletReady                 kubelet is posting ready status
  PIDPressure      False   Tue, 17 Jul 2018 11:47:30 -0400   Thu, 05 Jul 2018 10:06:51 -0400   KubeletHasSufficientPID      kubelet has sufficient PID available
Addresses:                   7
  InternalIP:  192.168.122.248
  Hostname:    node1.example.com
Capacity:                    8
 cpu:            2
 hugepages-2Mi:  0
 memory:         8010336Ki
 pods:           40
Allocatable:
 cpu:            2
 hugepages-2Mi:  0
 memory:         7907936Ki
 pods:           40
System Info:                 9
 Machine ID:                         b3adb9acbc49fc1f9a7d6
 System UUID:                        B3ADB9A-B0CB-C49FC1F9A7D6
 Boot ID:                            9359d15aec9-81a20aef5876
 Kernel Version:                     3.10.0-693.21.1.el7.x86_64
 OS Image:                           OpenShift Enterprise
 Operating System:                   linux
 Architecture:                       amd64
 Container Runtime Version:          docker://1.13.1
 Kubelet Version:                    v1.10.0+b81c8f8
 Kube-Proxy Version:                 v1.10.0+b81c8f8
ExternalID:                          node1.example.com
Non-terminated Pods:                 (14 in total)       10
  Namespace                          Name                                  CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ---------                          ----                                  ------------  ----------  ---------------  -------------
  default                            docker-registry-2-w252l               100m (5%)     0 (0%)      256Mi (3%)       0 (0%)
  default                            registry-console-2-dpnc9              0 (0%)        0 (0%)      0 (0%)           0 (0%)
  default                            router-2-5snb2                        100m (5%)     0 (0%)      256Mi (3%)       0 (0%)
  kube-service-catalog               apiserver-jh6gt                       0 (0%)        0 (0%)      0 (0%)           0 (0%)
  kube-service-catalog               controller-manager-z4t5j              0 (0%)        0 (0%)      0 (0%)           0 (0%)
  kube-system                        master-api-m01.example.com            0 (0%)        0 (0%)      0 (0%)           0 (0%)
  kube-system                        master-controllers-m01.example.com    0 (0%)        0 (0%)      0 (0%)           0 (0%)
  kube-system                        master-etcd-m01.example.com           0 (0%)        0 (0%)      0 (0%)           0 (0%)
  openshift-ansible-service-broker   asb-1-hnn5t                           0 (0%)        0 (0%)      0 (0%)           0 (0%)
  openshift-node                     sync-dvhvs                            0 (0%)        0 (0%)      0 (0%)           0 (0%)
  openshift-sdn                      ovs-zjs5k                             100m (5%)     200m (10%)  300Mi (3%)       400Mi (5%)
  openshift-sdn                      sdn-zr4cb                             100m (5%)     0 (0%)      200Mi (2%)       0 (0%)
  openshift-template-service-broker  apiserver-s9n7t                       0 (0%)        0 (0%)      0 (0%)           0 (0%)
  openshift-web-console              webconsole-785689b664-q7s9j           100m (5%)     0 (0%)      100Mi (1%)       0 (0%)
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ------------  ----------  ---------------  -------------
  500m (25%)    200m (10%)  1112Mi (14%)     400Mi (5%)
Events:                                                  11
  Type     Reason                   Age                From                      Message
  ----     ------                   ----               ----                      -------
  Normal   NodeHasSufficientPID     6d (x5 over 6d)    kubelet, m01.example.com  Node m01.example.com status is now: NodeHasSufficientPID
  Normal   NodeAllocatableEnforced  6d                 kubelet, m01.example.com  Updated Node Allocatable limit across pods
  Normal   NodeHasSufficientMemory  6d (x6 over 6d)    kubelet, m01.example.com  Node m01.example.com status is now: NodeHasSufficientMemory
  Normal   NodeHasNoDiskPressure    6d (x6 over 6d)    kubelet, m01.example.com  Node m01.example.com status is now: NodeHasNoDiskPressure
  Normal   NodeHasSufficientDisk    6d (x6 over 6d)    kubelet, m01.example.com  Node m01.example.com status is now: NodeHasSufficientDisk
  Normal   NodeHasSufficientPID     6d                 kubelet, m01.example.com  Node m01.example.com status is now: NodeHasSufficientPID
  Normal   Starting                 6d                 kubelet, m01.example.com  Starting kubelet.
 ...

1
ノードの名前。
2
ノードのロール。mastercompute、または infra のいずれか。
3
ノードに適用されるラベル
4
ノードに適用されるアノテーション。
5
ノードに適用されるテイント
6
7
ノードの IP アドレスおよびホスト名。
8
9
ノードホストについての情報。
10
ノードの Pod。
11
ノードで報告されるイベント

2.3. ノードの表示

コンテナーのランタイム環境を提供する、ノードについての使用状況の統計を表示できます。これらの使用状況の統計には CPU、メモリー、およびストレージの消費量が含まれます。

使用状況の統計を表示するには、以下を実行します。

$ oc adm top nodes

出力例

NAME       CPU(cores)   CPU%      MEMORY(bytes)   MEMORY%
node-1     297m         29%       4263Mi          55%
node-0     55m          5%        1201Mi          15%
infra-1    85m          8%        1319Mi          17%
infra-0    182m         18%       2524Mi          32%
master-0   178m         8%        2584Mi          16%

ラベルの付いたノードの使用状況の統計を表示するには、以下を実行します。

$ oc adm top node --selector=''

フィルターするのに使用するセレクター (ラベルクエリー) を選択する必要があります。===、および != をサポートします。

注記

使用状況の統計を閲覧するには、cluster-reader パーミッションがなければなりません。

注記

使用状況の統計を閲覧するには、metrics-server がインストールされている必要があります。「Horizontal Pod Autoscaler の要件」を参照してください。

2.4. ホストの追加

scaleup.yml Playbook を実行して新規ホストをクラスターに追加できます。この Playbook はマスターをクエリーし、新規ホストの新規証明書を生成し、配布してから、設定 Playbook を新規ホストにのみ実行します。scaleup.yml Playbook を実行する前に、前提条件となる「ホストの準備」手順をすべて完了してください。

重要

scaleup.yml の Playbook は新規ホストの設定のみを設定します。マスターサービスの NO_PROXY の更新やマスターサービスの再起動は行いません。

scaleup.yml Playbook を実行するには、現在のクラスター設定を表す既存のインベントリーファイル (/etc/ansible/hosts など) が必要です。以前に atomic-openshift-installer コマンドを使用してインストールを実行した場合は、~/.config/openshift/hosts を調べて、インストーラーによって生成された最新のインベントリーファイルを見つけ、そのファイルをインベントリーファイルとして使用することができます。このファイルは必要に応じて変更することができます。後で ansible-playbook を実行する際に -i オプションを使用してそのファイルの場所を指定する必要があります。

重要

ノードの推奨される最大数については、「cluster maximums」のセクションを参照してください。

手順

  1. openshift-ansible パッケージを更新して最新の Playbook を取得します。

    # yum update openshift-ansible
  2. /etc/ansible/hosts ファイルを編集し、new_<host_type>[OSEv3:children] セクションに追加します。たとえば、新規ノードホストを追加するには、new_nodes を追加します。

    [OSEv3:children]
    masters
    nodes
    new_nodes

    新規マスターホストを追加するには、new_masters を追加します。

  3. [new_<host_type>] セクションを作成して、新規ホストのホスト情報を指定します。以下の新規ノードの追加例で示されているように、既存のセクションと同じ様になフォーマットにこのセクションをフォーマットします。

    [nodes]
    master[1:3].example.com
    node1.example.com openshift_node_group_name='node-config-compute'
    node2.example.com openshift_node_group_name='node-config-compute'
    infra-node1.example.com openshift_node_group_name='node-config-infra'
    infra-node2.example.com openshift_node_group_name='node-config-infra'
    
    [new_nodes]
    node3.example.com openshift_node_group_name='node-config-infra'

    その他のオプションについては、「ホスト変数の設定」を参照してください。

    新規マスターを追加する場合は、[new_masters] セクションと [new_nodes] セクションの両方に新規ホストを追加して、新規マスターホストが OpenShift SDN の一部となるようにします。

    [masters]
    master[1:2].example.com
    
    [new_masters]
    master3.example.com
    
    [nodes]
    master[1:2].example.com
    node1.example.com openshift_node_group_name='node-config-compute'
    node2.example.com openshift_node_group_name='node-config-compute'
    infra-node1.example.com openshift_node_group_name='node-config-infra'
    infra-node2.example.com openshift_node_group_name='node-config-infra'
    
    [new_nodes]
    master3.example.com
    重要

    マスターホストに node-role.kubernetes.io/infra=true ラベルを付け、それ以外に専用インフラストラクチャーノードがない場合は、エントリーに openshift_schedulable=true を追加してホストにスケジュール可能であることを示すマークを明示的に付ける必要もあります。そうしないと、レジストリー Pod とルーター Pod をどこにも配置できなくなります。

  4. Playbook ディレクトリーに切り替え、openshift_node_group.yml Playbook を実行します。インベントリーファイルがデフォルトの /etc/ansible/hosts 以外の場所にある場合は、-i オプションで場所を指定します。

    $ cd /usr/share/ansible/openshift-ansible
    $ ansible-playbook [-i /path/to/file] \
      playbooks/openshift-master/openshift_node_group.yml

    これにより、新規ノードグループの ConfigMap が作成され、最終的にはホスト上のノードの設定ファイルが作成されます。

    注記

    openshift_node_group.yaml Playbook を実行しても、新規ノードのみが更新されます。これは、クラスター内の既存ノードを更新するために更新することはできません。

  5. scaleup.yml Playbook を実行します。インベントリーファイルがデフォルトの /etc/ansible/hosts 以外の場所にある場合は、-i オプションで場所を指定します。

    • ノードを追加する場合は、以下を指定します。

      $ ansible-playbook [-i /path/to/file] \
          playbooks/openshift-node/scaleup.yml
    • マスターを追加する場合は、以下を実行します。

      $ ansible-playbook [-i /path/to/file] \
          playbooks/openshift-master/scaleup.yml
  6. EFK スタックをクラスターにデプロイしている場合は、ノードラベルを logging-infra-fluentd=true に設定します。

    # oc label node/new-node.example.com logging-infra-fluentd=true
  7. Playbook の実行後に、「インストールの検証」を行います。
  8. [new_<host_type>] セクションで定義したホストを適切なセクションに移動します。このようにホストを移動することで、このインベントリーファイルを使用するその後の Playbook の実行で、正しくノードが処理されるようになります。[new_<host_type>] セクションは空のままにできます。たとえば、新規ノードを追加する場合は以下のように指定します。

    [nodes]
    master[1:3].example.com
    node1.example.com openshift_node_group_name='node-config-compute'
    node2.example.com openshift_node_group_name='node-config-compute'
    node3.example.com openshift_node_group_name='node-config-compute'
    infra-node1.example.com openshift_node_group_name='node-config-infra'
    infra-node2.example.com openshift_node_group_name='node-config-infra'
    
    [new_nodes]

2.5. ノードの削除

CLI を使用してノードを削除する場合、ノードオブジェクトは Kubernetes で削除されますが、ノード自体にある Pod は削除されません。レプリケーションコントローラーでサポートされないベア Pod は OpenShift Container Platform からアクセスできなくなり、レプリケーションコントローラーでサポートされる Pod は他の利用可能なノードにスケジュール変更されます。ローカルのマニフェスト Pod は手動で削除する必要があります。

OpenShift Container Platform クラスターからノードを削除するには、以下を実行します。

  1. 削除しようとしているノードからPod を退避します。
  2. ノードオブジェクトを削除します。

    $ oc delete node <node>
  3. ノードがノード一覧から削除されていることを確認します。

    $ oc get nodes

    Pod は、Ready 状態にある残りのノードに対してのみスケジュールされます。

  4. すべての Pod およびコンテナーを含む OpenShift Container Platform のすべてのコンテンツをノードホストからアンインストールする必要がある場合は、ノードのアンインストールを継続し、uninstall.yml Playbook を使用する手順に従います。この手順では、Ansible を使用したクラスターインストールプロセスについての全般的な理解があることが前提となります。

2.6. ノードのラベルの更新

ノードでラベルを追加し、更新するには、以下を実行します。

$ oc label node <node> <key_1>=<value_1> ... <key_n>=<value_n>

詳細な使用法を表示するには、以下を実行します。

$ oc label -h

2.7. ノード上の Pod の一覧表示

1 つ以上のノードにすべてまたは選択した Pod を一覧表示するには、以下を実行します。

$ oc adm manage-node <node1> <node2> \
    --list-pods [--pod-selector=<pod_selector>] [-o json|yaml]

選択したノードのすべてまたは選択した Pod を一覧表示するには、以下を実行します。

$ oc adm manage-node --selector=<node_selector> \
    --list-pods [--pod-selector=<pod_selector>] [-o json|yaml]

2.8. ノードをスケジュール対象外 (Unschedulable) またはスケジュール対象 (Schedulable) としてマークする

デフォルトで、Ready ステータスの正常なノードはスケジュール対象としてマークされます。つまり、新規 Pod をこのノードに配置することができます。手動でノードをスケジュール対象外としてマークすると、新規 Pod のノードでのスケジュールがブロックされます。ノード上の既存 Pod には影響がありません。

1 つまたは複数のノードをスケジュール対象外としてマークするには、以下を実行します。

$ oc adm manage-node <node1> <node2> --schedulable=false

例:

$ oc adm manage-node node1.example.com --schedulable=false

出力例

NAME                 LABELS                                        STATUS
node1.example.com    kubernetes.io/hostname=node1.example.com      Ready,SchedulingDisabled

現時点でスケジュール対象外のノードをスケジュール対象としてマークするには、以下を実行します。

$ oc adm manage-node <node1> <node2> --schedulable

または、特定のノード名 (例: <node1> <node2>) を指定する代わりに、--selector=<node_selector> オプションを使用して選択したノードをスケジュール対象またはスケジュール対象外としてマークすることができます。

2.9. Pod のノードからの退避

Pod を退避することで、すべての Pod または選択した Pod を 1 つの指定されたノードから移行できます。Pod の退避を実行するには、まずノードをスケジュール対象外としてマークする必要があります。

レプリケーションコントローラーでサポートされる Pod のみを退避できます。レプリケーションコントローラーは他のノードで新規 Pod を作成し、既存の Pod を指定したノードから削除します。デフォルトで、ベア Pod (レプリケーションコントローラーでサポートされていない Pod) はこの影響を受けません。Pod セレクターを指定して Pod のサブセットを退避できます。Pod セレクターはラベルをベースにしており、指定されたラベルのあるすべての Pod の退避が行われます。

ノードですべての Pod または選択した Pod を退避するには、 以下を実行します。

$ oc adm drain <node> [--pod-selector=<pod_selector>]

--force オプションを使用すると、ベア Pod の削除を強制的に実行できます。true に設定されると、Pod がレプリケーションコントローラー、ReplicaSet、ジョブ、daemonset、または StatefulSet で管理されていない場合でも削除が続行されます。

$ oc adm drain <node> --force=true

--grace-period を使用して、各 Pod を正常に終了するための期間 (秒単位) を設定できます。負の値の場合には、Pod に指定されるデフォルト値が使用されます。

$ oc adm drain <node> --grace-period=-1

--ignore-daemonsets を使用し、これを true に設定すると、Deamonset で管理された Pod を無視できます。

$ oc adm drain <node> --ignore-daemonsets=true

--timeout を使用すると、中止する前の待機期間を設定できます。値 0 は無限の時間を設定します。

$ oc adm drain <node> --timeout=5s

--delete-local-data を使用し、これを true に設定すると、Pod が emptyDir (ノードがドレイン (解放)) される場合に削除されるローカルデータ) を使用する場合でも削除が続行されます。

$ oc adm drain <node> --delete-local-data=true

退避を実行せずに移行するオブジェクトを一覧表示するには、--dry-run オプションを使用し、これを true に設定します。

$ oc adm drain <node> --dry-run=true

特定のノード名を指定する代わりに、--selector=<node_selector> オプションを使用し、セレクターに一致するノードの Pod を退避することができます。

2.10. ノードの再起動

プラットフォームで実行されるアプリケーションを停止せずにノードを再起動するには、まず Pod の退避を実行する必要があります。ルーティング階層によって可用性が高くされている Pod については、何も実行する必要はありません。ストレージ (通常はデータベース) を必要とするその他の Pod については、それらが 1 つの Pod が一時的にオフラインになっても作動したままになることを確認する必要があります。ステートフルな Pod の回復性はアプリケーションごとに異なりますが、いずれの場合でも、ノードの非アフィニティー (node anti-affinity) を使用して Pod が使用可能なノード間に適切に分散するようにスケジューラーを設定することが重要になります。

別の課題として、ルーターやレジストリーのような重要なインフラストラクチャーを実行しているノードを処理する方法を検討する必要があります。同じノードの退避プロセスが適用されますが、一部のエッジケースについて理解しておくことが重要です。

2.10.1. インフラストラクチャーノード

インフラストラクチャーノードは、OpenShift Container Platform 環境の一部を実行するためにラベルが付けられたノードです。現在、ノードの再起動を管理する最も簡単な方法として、インフラストラクチャーを実行するために利用できる 3 つ以上のノードを確保することができます。以下のシナリオでは、2 つのノードのみが利用可能な場合に OpenShift Container Platform で実行されるアプリケーションのサービスを中断しかねないよくある問題を示しています。

  • ノード A がスケジュール対象外としてマークされており、すべての Pod の退避が行われている。
  • このノードで実行されているレジストリー Pod がノード B に再デプロイされる。これは、ノード B が両方のレジストリー Pod を実行していることを意味します。
  • ノード B はスケジュール対象外としてマークされ、退避が行われる。
  • ノード B の 2 つの Pod エンドポイントを公開するサービスは、それらがノード A に再デプロイされるまでの短い期間すべてのエンドポイントを失う。

3 つのインフラストラクチャーノードを使用する同じプロセスではサービスの中断が生じません。しかし、Pod のスケジューリングにより、退避してローテーションに戻された最後のノードはゼロ (0) レジストリーを実行していることになり、他の 2 つのノードは 2 つのレジストリーと 1 つのレジストリーをそれぞれ実行します。最善の解決法として、Pod の非アフィニティーを使用できます。これは現在テスト目的で利用できる Kubernetes のアルファ機能ですが、実稼働ワークロードに対する使用はサポートされていません。

2.10.2. Pod の非アフィニティーの使用

Pod の非アフィニティーは、ノードの非アフィニティーとは若干異なります。ノードの非アフィニティーの場合、Pod のデプロイ先となる適切な場所がほかにない場合には違反が生じます。Pod の非アフィニティーの場合は required (必須) または preferred (優先) のいずれかに設定できます。

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-antiaffinity
spec:
  affinity:
    podAntiAffinity: 1
      preferredDuringSchedulingIgnoredDuringExecution: 2
      - weight: 100 3
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: docker-registry 4
              operator: In 5
              values:
              - default
          topologyKey: kubernetes.io/hostname
1
Pod の非アフィニティーを設定するためのスタンザです。
2
preferred (優先) ルールを定義します。
3
preferred (優先) ルールの重みを指定します。最も高い重みを持つノードが優先されます。
4
非アフィニティールールが適用される時を決定する Pod ラベルの説明です。ラベルのキーおよび値を指定します。
5
演算子は、既存 Pod のラベルと新規 Pod の仕様の matchExpression パラメーターの値のセットの間の関係を表します。これには InNotInExists、または DoesNotExist のいずれかを使用できます。

この例では、コンテナーイメージレジストリー Pod に docker-registry=default のラベルがあることを想定しています。Pod の非アフィニティーでは任意の Kubernetes の一致式を使用できます。

最後に必要となる手順として、/etc/origin/master/scheduler.jsonMatchInterPodAffinity スケジューラーの述語を有効にします。これが有効にされると、2 つのインフラストラクチャーノードのみが利用可能で、1 つのノードが再起動される場合に、コンテナーイメージレジストリー Pod が他のノードで実行されることが禁じられます。oc get pods は、適切なノードが利用可能になるまでこの Pod を unready (準備ができていない) として報告します。ノードが利用可能になると、すべての Pod は Ready (準備ができている) 状態に戻り、次のノードを再起動することができます。

2.10.3. ルーターを実行するノードの処理

ほとんどの場合、OpenShift Container Platform ルーターを実行する Pod はホストのポートを公開します。PodFitsPorts スケジューラーの述語により、同じポートを使用するルーター Pod が同じノードで実行されないようにし、Pod の非アフィニティーが適用されます。ルーターの高可用性を維持するために IP フェイルオーバー を利用している場合には、他に実行することはありません。高可用性を確保するために AWS Elastic Load Balancing などの外部サービスを使用するルーター Pod の場合は、そのような外部サービスがルーター Pod の再起動に対して対応します。

ルーター Pod でホストのポートが設定されていないということも稀にあります。この場合は、インフラストラクチャーノードについての推奨される再起動プロセスに従う必要があります。

2.11. ノードの変更

インストール時に、OpenShift Container Platform はそれぞれのノードグループに対して openshift-node プロジェクトに configmap を作成します。

  • node-config-master
  • node-config-infra
  • node-config-compute
  • node-config-all-in-one
  • node-config-master-infra

既存のノードに設定の変更を加えるには、該当する設定マップを編集します。各ノードの sync pod は設定マップで変更の有無を監視します。インストール時に、同期 Pod は sync Daemonsets および /etc/origin/node/node-config.yaml ファイルを使用して作成されます。ここにノード設定パラメーターが存在し、これらは各ノードに追加されます。同期 Pod が設定マップの変更を検出すると、ノードグループのすべてのノードで node-config.yaml を更新し、該当するノードで atomic-openshift-node.service を再起動します。

$ oc get cm -n openshift-node

出力例

NAME                       DATA      AGE
node-config-all-in-one     1         1d
node-config-compute        1         1d
node-config-infra          1         1d
node-config-master         1         1d
node-config-master-infra   1         1d

node-config-computeグループの設定マップのサンプル

apiVersion: v1
authConfig:      1
  authenticationCacheSize: 1000
  authenticationCacheTTL: 5m
  authorizationCacheSize: 1000
  authorizationCacheTTL: 5m
dnsBindAddress: 127.0.0.1:53
dnsDomain: cluster.local
dnsIP: 0.0.0.0               2
dnsNameservers: null
dnsRecursiveResolvConf: /etc/origin/node/resolv.conf
dockerConfig:
  dockerShimRootDirectory: /var/lib/dockershim
  dockerShimSocket: /var/run/dockershim.sock
  execHandlerName: native
enableUnidling: true
imageConfig:
  format: registry.reg-aws.openshift.com/openshift3/ose-${component}:${version}
  latest: false
iptablesSyncPeriod: 30s
kind: NodeConfig
kubeletArguments: 3
  bootstrap-kubeconfig:
  - /etc/origin/node/bootstrap.kubeconfig
  cert-dir:
  - /etc/origin/node/certificates
  cloud-config:
  - /etc/origin/cloudprovider/aws.conf
  cloud-provider:
  - aws
  enable-controller-attach-detach:
  - 'true'
  feature-gates:
  - RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true
  node-labels:
  - node-role.kubernetes.io/compute=true
  pod-manifest-path:
  - /etc/origin/node/pods  4
  rotate-certificates:
  - 'true'
masterClientConnectionOverrides:
  acceptContentTypes: application/vnd.kubernetes.protobuf,application/json
  burst: 40
  contentType: application/vnd.kubernetes.protobuf
  qps: 20
masterKubeConfig: node.kubeconfig
networkConfig:   5
  mtu: 8951
  networkPluginName: redhat/openshift-ovs-subnet  6
servingInfo:                   7
  bindAddress: 0.0.0.0:10250
  bindNetwork: tcp4
  clientCA: client-ca.crt
volumeConfig:
  localQuota:
    perFSGroup: null    8
volumeDirectory: /var/lib/origin/openshift.local.volumes

1
認証および認可設定オプションを保持します。
2
Pod の /etc/resolv.conf に追加 IP アドレスです。
3
Kubelet のコマンドライン引数 に一致する Kubelet に直接渡されるキー/値のペアです。
4
Pod マニフェストまたはディレクトリーへのパスです。ディレクトリーには、1 つ以上のマニフェストファイルが含まれている必要があります。 OpenShift Container Platform はマニフェストファイルを使用してノードに Pod を作成します。
5
ノード上の Pod ネットワーク設定です。
6
SDN (Software defined network) プラグインです。ovs-subnet プラグインは redhat/openshift-ovs-subnetovs-multitenant プラグインは redhat/openshift-ovs-multitenantovs-networkpolicy プラグインは redhat/openshift-ovs-networkpolicy をそれぞれ設定します。
7
ノードの証明書情報です。
8
オプション: PEM でエンコードされた証明書バンドルです。これが設定されている場合、要求ヘッダーのユーザー名をチェックする前に、有効なクライアント証明書が提示され、指定ファイルで認証局に対して検証される必要があります。
注記

/etc/origin/node/node-config.yaml ファイルは手動で変更できません。

2.11.1. ノードリソースの設定

ノードのリソースは、kubelet 引数をノード設定マップに追加して設定することができます。

  1. 設定マップを編集します。

    $ oc edit cm node-config-compute -n openshift-node
  2. kubeletArguments セクションを追加して、オプションを指定します。

    kubeletArguments:
      max-pods: 1
        - "40"
      resolv-conf: 2
        - "/etc/resolv.conf"
      image-gc-high-threshold: 3
        - "90"
      image-gc-low-threshold: 4
        - "80"
      kube-api-qps: 5
        - "20"
      kube-api-burst: 6
        - "40"
    1
    2
    コンテナー DNS 解決設定のベースとして使用されるリゾルバーの設定ファイル。
    3
    イメージのガべージコレクションが常に実行される場合のディスク使用量のパーセント。デフォルト: 90%
    4
    イメージのガべージコレクションが一度も実行されない場合のディスク使用量のパーセント。デフォルト: 80%
    5
    Kubernetes API サーバーとの通信中に使用する 1 秒あたりのクエリー数 (QPS)。
    6
    Kubernetes API サーバーとの通信中に使用するバースト。

    利用可能なすべての kubelet オプションを表示するには、以下を実行します。

    $ hyperkube kubelet -h

2.11.2. ノードあたりの最大 Pod 数の設定

注記

OpenShift Container Platform の各バージョンでサポートされている最大の制限については、「Cluster maximums」のページを参照してください。

/etc/origin/node/node-config.yaml ファイルでは、 pods-per-core および max-pods の 2 つのパラメーターがノードにスケジュールできる Pod の最大数を制御します。いずれのオプションも使用されている場合、2 つの内の小さい方の値でノードの Pod 数が制限されます。これらの値を超えると、以下の状況が発生します。

  • OpenShift Container Platform と Docker の両方で CPU 使用率が増加する。
  • Pod のスケジューリングの速度が遅くなる。
  • メモリー不足のシナリオが生じる可能性がある (ノードのメモリー量によって異なる)。
  • IP アドレスのプールを消費する。
  • リソースのオーバーコミット、およびこれによるアプリケーションのパフォーマンスの低下。
注記

Kubernetes では、単一コンテナーを保持する Pod は実際には 2 つのコンテナーを使用します。2 つ目のコンテナーは実際のコンテナーの起動前にネットワークを設定するために使用されます。そのため、10 の Pod を使用するシステムでは、実際には 20 のコンテナーが実行されていることになります。

pods-per-core は、ノードのプロセッサーコア数に基づいてノードが実行できる Pod 数を設定します。たとえば、4 プロセッサーコアを搭載したノードで pods-per-core10 に設定される場合、このノードで許可される Pod の最大数は 40 になります。

kubeletArguments:
  pods-per-core:
    - "10"
注記

pods-per-core を 0 に設定すると、この制限が無効になります。

max-pods は、ノードのプロパティーにかかわらず、ノードが実行できる Pod 数を固定値に設定します。「Cluster Limits」では max-pods のサポートされる最大の値について説明しています。

kubeletArguments:
  max-pods:
    - "250"

上記の例では、pods-per-core のデフォルト値は 10 であり、max-pods のデフォルト値は 250 です。これは、ノードにあるコア数が 25 以上でない限り、デフォルトでは pods-per-core が制限を設定することになります。

2.12. Docker ストレージの再設定

コンテナーイメージをダウンロードし、コンテナーを実行して削除する際、Docker は常にマップされたディスク領域を解放する訳ではありません。結果として、一定の時間が経過するとノード上で領域不足が生じる可能性があり、これにより OpenShift Container Platform で新規 Pod を作成できなくなるか、または Pod の作成に時間がかかる可能性があります。

たとえば、以下は 6 分が経過しても ContainerCreating 状態にある Pod を示しており、イベントログは FailedSync イベントについて示しています。

$ oc get pod

出力例

NAME                               READY     STATUS              RESTARTS   AGE
cakephp-mysql-persistent-1-build   0/1       ContainerCreating   0          6m
mysql-1-9767d                      0/1       ContainerCreating   0          2m
mysql-1-deploy                     0/1       ContainerCreating   0          6m

$ oc get events

出力例

LASTSEEN   FIRSTSEEN   COUNT     NAME                               KIND                    SUBOBJECT                     TYPE      REASON                         SOURCE                                                 MESSAGE
6m         6m          1         cakephp-mysql-persistent-1-build   Pod                                                   Normal    Scheduled                      default-scheduler                                      Successfully assigned cakephp-mysql-persistent-1-build to ip-172-31-71-195.us-east-2.compute.internal
2m         5m          4         cakephp-mysql-persistent-1-build   Pod                                                   Warning   FailedSync                     kubelet, ip-172-31-71-195.us-east-2.compute.internal   Error syncing pod
2m         4m          4         cakephp-mysql-persistent-1-build   Pod                                                   Normal    SandboxChanged                 kubelet, ip-172-31-71-195.us-east-2.compute.internal   Pod sandbox changed, it will be killed and re-created.

この問題に対する 1 つの解決法として、Docker ストレージを再設定し、Docker で不要なアーティファクトを削除することができます。

Docker ストレージを再起動するノードで、以下を実行します。

  1. 以下のコマンドを実行して、ノードをスケジュール対象外としてマークします。

    $ oc adm manage-node <node> --schedulable=false
  2. 以下のコマンドを実行して Docker および atomic-openshift-node サービスをシャットダウンします。

    $ systemctl stop docker atomic-openshift-node
  3. 以下のコマンドを実行してローカルのボリュームディレクトリーを削除します。

    $ rm -rf /var/lib/origin/openshift.local.volumes

    このコマンドは、ローカルイメージのキャッシュをクリアします。その結果、ose-* イメージを含むイメージが再度プルする必要があります。これにより、イメージストアは回復しますが、Pod の起動時間が遅くなる可能性があります。

  4. /var/lib/docker ディレクトリーを削除します。

    $ rm -rf /var/lib/docker
  5. 以下のコマンドを実行して Docker ストレージを再設定します。

    $ docker-storage-setup --reset
  6. 以下のコマンドを実行して Docker ストレージを再作成します。

    $ docker-storage-setup
  7. /var/lib/docker ディレクトリーを再作成します。

    $ mkdir /var/lib/docker
  8. 以下のコマンドを実行して Docker および atomic-openshift-node サービスを再起動します。

    $ systemctl start docker atomic-openshift-node
  9. ホストを再起動してノードサービスを再起動します。

    # systemctl restart atomic-openshift-node.service
  10. 以下のコマンドを実行してノードをスケジュール対象としてマークします。

    $ oc adm manage-node <node> --schedulable=true