Red Hat Training
A Red Hat training course is available for OpenShift Container Platform
クラスター管理
OpenShift Container Platform 3.11 クラスター管理
概要
第1章 概要
OpenShift クラスター管理では、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 ノードの状態
条件 | 説明 |
---|---|
|
ノードは |
| ノードはマスターから実行されるヘルスチェックをパスしていません。 |
| ノードへの 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. ...
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
を使用して、そのファイルの場所を指定する必要があります。
ノードの推奨の最大数については、クラスターの最大値 のセクションを参照してください。
手順
openshift-ansible パッケージを更新して最新の Playbook を取得します。
# yum update openshift-ansible
/etc/ansible/hosts ファイルを編集し、new_<host_type> を [OSEv3:children] セクションに追加します。たとえば、新規ノードホストを追加するには、new_nodes を追加します。
[OSEv3:children] masters nodes new_nodes
新規マスターホストを追加するには、new_masters を追加します。
[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 をどこにも配置できなくなります。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 を実行すると、新規ノードのみが更新されます。クラスター内の既存ノードを更新するために実行することはできません。
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
EFK スタックをクラスターにデプロイしている場合は、ノードラベルを
logging-infra-fluentd=true
に設定します。# oc label node/new-node.example.com logging-infra-fluentd=true
- Playbook の実行後に、インストールの検証 を行います。
[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 クラスターからノードを削除するには、以下を実行します。
- 削除しようとしているノードから Pod を退避 します。
ノードオブジェクトを削除します。
$ oc delete node <node>
ノードがノード一覧から削除されていることを確認します。
$ oc get nodes
Pod は、Ready 状態にある残りのノードに対してのみスケジュールされる必要があります。
- すべての 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、ジョブ、DeamonSet、または 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 つのレジストリーをそれぞれ実行します。他の 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
この例では、コンテナーイメージレジストリー Pod に docker-registry=default
のラベルがあることを想定しています。Pod の非アフィニティーでは任意の Kubernetes の一致式を使用できます。
最後に必要となる手順として、/etc/origin/master/scheduler.json で MatchInterPodAffinity
スケジューラーの述語を有効にします。これが有効になっていると、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 8 volumeConfig: localQuota: perFSGroup: null 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-subnet
、ovs-multitenant プラグインはredhat/openshift-ovs-multitenant
、または ovs-networkpolicy プラグインはredhat/openshift-ovs-networkpolicy
にそれぞれ設定します。 - 7
- ノードの証明書情報です。
- 8
- オプション: PEM でエンコードされた証明書バンドルです。これが設定されている場合、要求ヘッダーのユーザー名をチェックする前に、有効なクライアント証明書が提示され、指定ファイルで認証局に対して検証される必要があります。
/etc/origin/node/node-config.yaml ファイルは手動で変更できません。
2.11.1. ノードリソースの設定
ノードのリソースは、kubelet 引数をノード設定マップに追加して設定することができます。
設定マップを編集します。
$ oc edit cm node-config-compute -n openshift-node
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"
利用可能なすべての kubelet オプションを表示するには、以下を実行します。
$ hyperkube kubelet -h
2.11.2. ノードあたりの最大 Pod 数の設定
OpenShift Container Platform の各バージョンでサポートされている最大制限については、Cluster maximums ページを参照してください。
/etc/origin/node/node-config.yaml ファイルでは、1 つのパラメーターでノードにスケジュールできる Pod の最大数 max-pods
を制御します。max-pods
オプションを使用すると、ノード上の Pod の数が制限されます。この値を超えると、次の結果になる可能性があります。
- OpenShift Container Platform と Docker の両方で CPU 使用率が増加する。
- Pod のスケジューリングの速度が遅くなる。
- メモリー不足のシナリオが生じる可能性がある (ノードのメモリー量によって異なる)。
- IP アドレスのプールを消費する。
- リソースのオーバーコミット、およびこれによるアプリケーションのパフォーマンスの低下。
Kubernetes では、単一コンテナーを保持する Pod は実際には 2 つのコンテナーを使用します。2 つ目のコンテナーは実際のコンテナーの起動前にネットワークを設定するために使用されます。そのため、10 の Pod を使用するシステムでは、実際には 20 のコンテナーが実行されていることになります。
max-pods
は、ノードのプロパティーにかかわらず、ノードが実行できる Pod 数を固定値に設定します。クラスターの制限 では、max-pods
のサポートされる最大値について説明しています。
kubeletArguments: max-pods: - "250"
上記の例を使用すると、max-pods
のデフォルト値は 250
です。
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 ストレージを再起動するノードで、以下を実行します。
以下のコマンドを実行して、ノードをスケジュール対象外としてマークします。
$ oc adm manage-node <node> --schedulable=false
以下のコマンドを実行して Docker および atomic-openshift-node サービスをシャットダウンします。
$ systemctl stop docker atomic-openshift-node
以下のコマンドを実行して、ローカルのボリュームディレクトリーを削除します。
$ rm -rf /var/lib/origin/openshift.local.volumes
このコマンドは、ローカルイメージのキャッシュをクリアします。その結果、
ose-*
イメージを含むイメージが再度プルする必要があります。これにより、イメージストアは回復しますが、Pod の起動時間が遅くなる可能性があります。/var/lib/docker ディレクトリーを削除します。
$ rm -rf /var/lib/docker
以下のコマンドを実行して Docker ストレージをリセットします。
$ docker-storage-setup --reset
以下のコマンドを実行して Docker ストレージを再作成します。
$ docker-storage-setup
/var/lib/docker ディレクトリーを再作成します。
$ mkdir /var/lib/docker
以下のコマンドを実行して、Docker および atomic-openshift-node サービスを再起動します。
$ systemctl start docker atomic-openshift-node
ホストを再起動してノードサービスを再起動します。
# systemctl restart atomic-openshift-node.service
以下のコマンドを実行して、ノードをスケジュール対象としてマークします。
$ oc adm manage-node <node> --schedulable=true
第3章 OpenShift Container Platform コンポーネントの復元
3.1. 概要
OpenShift Container Platform では、クラスターおよびそのコンポーネントの 復元 は、ノードおよびアプリケーションなどの要素を別のストレージから再作成することで実行できます。
クラスターを復元するには、まず バックアップを作成 します。
以下のプロセスでは、アプリケーションおよび OpenShift Container Platform クラスターを復元するための通常の方法について説明しています。ここではカスタム要件は考慮されません。クラスターを復元するために追加のアクションを実行する必要がある可能性があります。
3.2. クラスターの復元
クラスターを復元するには、まず OpenShift Container Platform を再インストールします。
手順
- 最初に OpenShift Container Platform をインストールしたのと 同じ方法 で OpenShift Container Platform を再インストールします。
- OpenShift Container Platform の制御下にないサービスを変更したり、モニターエージェントなどの追加サービスのインストールなど、インストール後のカスタム手順すべてを実行します。
3.3. マスターホストのバックアップの復元
重要なマスターホストファイルのバックアップを作成した後に、それらのファイルが破損するか、または間違って削除された場合は、それらのファイルをマスターにコピーし直してファイルを復元し、それらに適切なコンテンツが含まれることを確認し、影響を受けるサービスを再起動して実行できます。
手順
/etc/origin/master/master-config.yaml
ファイルを復元します。# MYBACKUPDIR=*/backup/$(hostname)/$(date +%Y%m%d)* # cp /etc/origin/master/master-config.yaml /etc/origin/master/master-config.yaml.old # cp /backup/$(hostname)/$(date +%Y%m%d)/origin/master/master-config.yaml /etc/origin/master/master-config.yaml # master-restart api # master-restart controllers
警告マスターサービスの再起動によりダウンタイムが生じる場合があります。ただし、マスターホストを可用性の高いロードバランサープールから削除し、復元操作を実行することができます。サービスが適切に復元された後に、マスターホストをロードバランサープールに再び追加することができます。
注記影響を受けるインスタンスを完全に再起動して、
iptables
設定を復元します。パッケージがないために OpenShift Container Platform を再起動できない場合は、パッケージを再インストールします。
現在インストールされているパッケージの一覧を取得します。
$ rpm -qa | sort > /tmp/current_packages.txt
パッケージの一覧の間に存在する差分を表示します。
$ diff /tmp/current_packages.txt ${MYBACKUPDIR}/packages.txt > ansible-2.4.0.0-5.el7.noarch
足りないパッケージを再インストールします。
# yum reinstall -y <packages> 1
- 1
<packages>
は、パッケージの一覧ごとに異なるパッケージに置き換えます。
システム証明書を
/etc/pki/ca-trust/source/anchors/
ディレクトリーにコピーして復元し、update-ca-trust
を実行します。$ MYBACKUPDIR=*/backup/$(hostname)/$(date +%Y%m%d)* $ sudo cp ${MYBACKUPDIR}/etc/pki/ca-trust/source/anchors/<certificate> /etc/pki/ca-trust/source/anchors/ 1 $ sudo update-ca-trust
- 1
<certificate>
は、復元するシステム証明書のファイル名に置き換えます。
注記ファイルをコピーし直す時に、ユーザー ID およびグループ ID だけでなく、
SELinux
コンテキストも復元されていることを常に確認してください。
3.4. ノードホストバックアップの復元
重要なノードホストファイルのファイルのバックアップを作成した後に、それらのファイルが破損するか、または間違って削除された場合、これらのファイルをコピーし直してファイルを復元し、適切なコンテンツが含まれることを確認してから、影響を受けるサービスを再起動します。
手順
/etc/origin/node/node-config.yaml
ファイルを復元します。# MYBACKUPDIR=/backup/$(hostname)/$(date +%Y%m%d) # cp /etc/origin/node/node-config.yaml /etc/origin/node/node-config.yaml.old # cp /backup/$(hostname)/$(date +%Y%m%d)/etc/origin/node/node-config.yaml /etc/origin/node/node-config.yaml # reboot
サービスの再起動によりダウンタイムが生じる場合があります。このプロセスを容易にするためのヒントについては、ノードの保守 を参照してください。
影響を受けるインスタンスを完全に再起動して、iptables
設定を復元します。
パッケージがないために OpenShift Container Platform を再起動できない場合は、パッケージを再インストールします。
現在インストールされているパッケージの一覧を取得します。
$ rpm -qa | sort > /tmp/current_packages.txt
パッケージの一覧の間に存在する差分を表示します。
$ diff /tmp/current_packages.txt ${MYBACKUPDIR}/packages.txt > ansible-2.4.0.0-5.el7.noarch
足りないパッケージを再インストールします。
# yum reinstall -y <packages> 1
- 1
<packages>
は、パッケージの一覧ごとに異なるパッケージに置き換えます。
システム証明書を
/etc/pki/ca-trust/source/anchors/
ディレクトリーにコピーして復元し、update-ca-trust
を実行します。$ MYBACKUPDIR=*/backup/$(hostname)/$(date +%Y%m%d)* $ sudo cp ${MYBACKUPDIR}/etc/pki/ca-trust/source/anchors/<certificate> /etc/pki/ca-trust/source/anchors/ $ sudo update-ca-trust
<certificate>
は、復元するシステム証明書のファイル名に置き換えます。
注記ファイルをコピーし直す時に、適切なユーザー ID およびグループ ID だけでなく、
SELinux
コンテキストも復元されていることを常に確認してください。
3.5. etcd の復元
3.5.1. etcd 設定ファイルの復元
etcd ホストが破損し、/etc/etcd/etcd.conf
ファイルがなくなった場合は、以下の手順を使用してこれを復元します。
etcd ホストにアクセスします。
$ ssh master-0 1
- 1
master-0
は etcd ホストの名前に置き換えます。
etcd.conf
のバックアップファイルを/etc/etcd/
にコピーします。# cp /backup/etcd-config-<timestamp>/etcd/etcd.conf /etc/etcd/etcd.conf
ファイルに必要なパーミッションおよび selinux コンテキストを設定します。
# restorecon -RvF /etc/etcd/etcd.conf
この例では、バックアップファイルは、外部の NFS 共有、S3 バケットまたは他のストレージソリューションとして使用できる /backup/etcd-config-<timestamp>/etcd/etcd.conf
パスに保存されます。
etcd 設定ファイルの復元後に、静的 Pod を再起動する必要があります。これは、etcd データの復元後に実行されます。
3.5.2. etcd データの復元
静的 Pod で etcd を復元する前に、以下を確認します。
etcdctl
バイナリーが利用可能であるか、またはコンテナー化インストールの場合はrhel7/etcd
コンテナーが利用可能でなければなりません。以下のコマンドを実行して etcd パッケージで
etcdctl
バイナリーをインストールできます。# yum install etcd
このパッケージは systemd サービスもインストールします。etcd を静的 Pod で実行時に systemd サービスとして実行されないようにサービスを無効にしてマスクします。サービスを無効にしてマスクすることで、誤って開始したり、システムの再起動時に自動的にサービスの再起動がされないようにします。
# systemctl disable etcd.service
# systemctl mask etcd.service
静的 Pod で etcd を復元するには、以下を実行します。
Pod が実行中の場合、Pod のマニフェスト YAML ファイルを別のディレクトリーに移動して etcd Pod を停止します。
# mkdir -p /etc/origin/node/pods-stopped
# mv /etc/origin/node/pods/etcd.yaml /etc/origin/node/pods-stopped
古いデータはすべて移動します。
# mv /var/lib/etcd /var/lib/etcd.old
etcdctl を使用して、Pod を復元するノードでデータを再作成します。
etcd スナップショットを etcd Pod のマウントパスに復元します。
# export ETCDCTL_API=3
# etcdctl snapshot restore /etc/etcd/backup/etcd/snapshot.db \ --data-dir /var/lib/etcd/ \ --name ip-172-18-3-48.ec2.internal \ --initial-cluster "ip-172-18-3-48.ec2.internal=https://172.18.3.48:2380" \ --initial-cluster-token "etcd-cluster-1" \ --initial-advertise-peer-urls https://172.18.3.48:2380 \ --skip-hash-check=true
バックアップの etcd.conf ファイルからクラスターの適切な値を取得します。
データディレクトリーに必要なパーミッションおよび selinux コンテキストを設定します。
# restorecon -RvF /var/lib/etcd/
Pod のマニフェスト YAML ファイルを必要なディレクトリーに移動して etcd Pod を再起動します。
# mv /etc/origin/node/pods-stopped/etcd.yaml /etc/origin/node/pods/
3.6. etcd ノードの追加
etcd の復元後、他の etcd ノードをクラスターに追加できます。Ansible Playbook を使用するか、または手動の手順を実行して etcd ホストを追加できます。
3.6.1. Ansible を使用した新規 etcd ホストの追加
手順
Ansible インベントリーファイルで、
[new_etcd]
という名前の新規グループおよび新規ホストを作成します。次に、new_etcd
グループを[OSEv3]
グループの子として追加します。[OSEv3:children] masters nodes etcd new_etcd 1 ... [OUTPUT ABBREVIATED] ... [etcd] master-0.example.com master-1.example.com master-2.example.com [new_etcd] 2 etcd0.example.com 3
注記インベントリーファイル内の古い
etcd host
エントリーを新しいetcd host
エントリーに置き換えます。古いetcd host
を置き換えるときに、/etc/etcd/ca/
ディレクトリーのコピーを作成する必要があります。または、etcd hosts
をスケールアップする前に、etcd ca と証明書を再デプロイすることもできます。OpenShift Container Platform をインストールし、Ansible インベントリーファイルをホストするホストから、Playbook ディレクトリーに移動し、etcd
scaleup
Playbook を実行します。$ cd /usr/share/ansible/openshift-ansible $ ansible-playbook playbooks/openshift-etcd/scaleup.yml
Playbook が実行された後に、新規 etcd ホストを
[new_etcd]
グループから[etcd]
グループに移行し、現在のステータスを反映するようにインベントリーファイルを変更します。[OSEv3:children] masters nodes etcd new_etcd ... [OUTPUT ABBREVIATED] ... [etcd] master-0.example.com master-1.example.com master-2.example.com etcd0.example.com
Flannel を使用する場合には、OpenShift Container Platform のホストごとに、
/etc/sysconfig/flanneld
にあるflanneld
サービス設定を変更し、新しい etcd ホストを追加します。FLANNEL_ETCD_ENDPOINTS=https://master-0.example.com:2379,https://master-1.example.com:2379,https://master-2.example.com:2379,https://etcd0.example.com:2379
flanneld
サービスを再起動します。# systemctl restart flanneld.service
3.6.2. 新規 etcd ホストの手動による追加
etcd をマスターノードで静的 Pod として実行しない場合、別の etcd ホストを追加する必要が生じる場合があります。
手順
現在の etcd クラスターの変更
etcd 証明書を作成するには、値を環境の値に置き換えて openssl
コマンドを実行します。
環境変数を作成します。
export NEW_ETCD_HOSTNAME="*etcd0.example.com*" export NEW_ETCD_IP="192.168.55.21" export CN=$NEW_ETCD_HOSTNAME export SAN="IP:${NEW_ETCD_IP}, DNS:${NEW_ETCD_HOSTNAME}" export PREFIX="/etc/etcd/generated_certs/etcd-$CN/" export OPENSSLCFG="/etc/etcd/ca/openssl.cnf"
注記etcd_v3_ca_*
として使用されるカスタムのopenssl
拡張には、subjectAltName
としての $SAN 環境変数が含まれます。詳細は、/etc/etcd/ca/openssl.cnf
を参照してください。設定および証明書を保存するディレクトリーを作成します。
# mkdir -p ${PREFIX}
サーバー証明書要求を作成し、これに署名します (server.csr および server.crt)。
# openssl req -new -config ${OPENSSLCFG} \ -keyout ${PREFIX}server.key \ -out ${PREFIX}server.csr \ -reqexts etcd_v3_req -batch -nodes \ -subj /CN=$CN # openssl ca -name etcd_ca -config ${OPENSSLCFG} \ -out ${PREFIX}server.crt \ -in ${PREFIX}server.csr \ -extensions etcd_v3_ca_server -batch
ピア証明書要求を作成し、これに署名します (peer.csr および peer.crt)。
# openssl req -new -config ${OPENSSLCFG} \ -keyout ${PREFIX}peer.key \ -out ${PREFIX}peer.csr \ -reqexts etcd_v3_req -batch -nodes \ -subj /CN=$CN # openssl ca -name etcd_ca -config ${OPENSSLCFG} \ -out ${PREFIX}peer.crt \ -in ${PREFIX}peer.csr \ -extensions etcd_v3_ca_peer -batch
後で変更できるように、現在の etcd 設定および
ca.crt
ファイルをサンプルとして現在のノードからコピーします。# cp /etc/etcd/etcd.conf ${PREFIX} # cp /etc/etcd/ca.crt ${PREFIX}
存続する etcd ホストから、新規ホストをクラスターに追加します。etcd メンバーをクラスターに追加するには、まず最初のメンバーの
peerURLs
値のデフォルトの localhost ピアを調整する必要があります。member list
コマンドを使用して最初のメンバーのメンバー ID を取得します。# etcdctl --cert-file=/etc/etcd/peer.crt \ --key-file=/etc/etcd/peer.key \ --ca-file=/etc/etcd/ca.crt \ --peers="https://172.18.1.18:2379,https://172.18.9.202:2379,https://172.18.0.75:2379" \ 1 member list
- 1
--peers
パラメーター値でアクティブな etcd メンバーのみの URL を指定するようにしてください。
etcd がクラスターピアについてリッスンする IP アドレスを取得します。
$ ss -l4n | grep 2380
直前の手順で取得されたメンバー ID および IP アドレスを渡して、
etcdctl member update
コマンドを使用してpeerURLs
の値を更新します。# etcdctl --cert-file=/etc/etcd/peer.crt \ --key-file=/etc/etcd/peer.key \ --ca-file=/etc/etcd/ca.crt \ --peers="https://172.18.1.18:2379,https://172.18.9.202:2379,https://172.18.0.75:2379" \ member update 511b7fb6cc0001 https://172.18.1.18:2380
-
member list
コマンドを再実行し、ピア URL に localhost が含まれなくなるようにします。
新規ホストを etcd クラスターに追加します。新規ホストはまだ設定されていないため、新規ホストを設定するまでステータスが
unstarted
のままであることに注意してください。警告各メンバーを追加し、1 回に 1 つずつメンバーをオンライン状態にします。各メンバーをクラスターに追加する際に、現在のピアの
peerURL
一覧を調整する必要があります。peerURL
一覧はメンバーが追加されるたびに拡張します。etcdctl member add
コマンドは、以下に説明されているように、メンバーを追加する際に etcd.conf ファイルで設定する必要のある値を出力します。# etcdctl -C https://${CURRENT_ETCD_HOST}:2379 \ --ca-file=/etc/etcd/ca.crt \ --cert-file=/etc/etcd/peer.crt \ --key-file=/etc/etcd/peer.key member add ${NEW_ETCD_HOSTNAME} https://${NEW_ETCD_IP}:2380 1 Added member named 10.3.9.222 with ID 4e1db163a21d7651 to cluster ETCD_NAME="<NEW_ETCD_HOSTNAME>" ETCD_INITIAL_CLUSTER="<NEW_ETCD_HOSTNAME>=https://<NEW_HOST_IP>:2380,<CLUSTERMEMBER1_NAME>=https:/<CLUSTERMEMBER2_IP>:2380,<CLUSTERMEMBER2_NAME>=https:/<CLUSTERMEMBER2_IP>:2380,<CLUSTERMEMBER3_NAME>=https:/<CLUSTERMEMBER3_IP>:2380" ETCD_INITIAL_CLUSTER_STATE="existing"
- 1
- この行で、
10.3.9.222
は etcd メンバーのラベルです。ホスト名、IP アドレスまたは単純な名前を指定できます。
サンプル
${PREFIX}/etcd.conf
ファイルを更新します。以下の値を直前の手順で生成された値に置き換えます。
- ETCD_NAME
- ETCD_INITIAL_CLUSTER
- ETCD_INITIAL_CLUSTER_STATE
以下の変数は、直前の手順で出力された新規ホストの IP に変更します。
${NEW_ETCD_IP}
は、値として使用できます。ETCD_LISTEN_PEER_URLS ETCD_LISTEN_CLIENT_URLS ETCD_INITIAL_ADVERTISE_PEER_URLS ETCD_ADVERTISE_CLIENT_URLS
- メンバーシステムを etcd ノードとして使用していた場合には、/etc/etcd/etcd.conf ファイルの現在の値を上書きする必要があります。
ファイルで構文エラーや欠落している IP アドレスがないかを確認します。 エラーや欠落がある場合には、etced サービスが失敗してしまう可能性があります。
# vi ${PREFIX}/etcd.conf
-
インストールファイルをホストするノードでは、/etc/ansible/hosts インベントリーファイルの
[etcd]
ホストグループを更新します。古い etcd ホストを削除し、新規ホストを追加します。 証明書、サンプル設定ファイル、および
ca
を含むtgz
ファイルを作成し、これを新規ホストにコピーします。# tar -czvf /etc/etcd/generated_certs/${CN}.tgz -C ${PREFIX} . # scp /etc/etcd/generated_certs/${CN}.tgz ${CN}:/tmp/
新規 etcd ホストの変更
iptables-services
をインストールして etcd の必要なポートを開くために iptables ユーティリティーを指定します。# yum install -y iptables-services
etcd の通信を許可する
OS_FIREWALL_ALLOW
ファイアウォールルールを作成します。- クライアントのポート 2379/tcp
ピア通信のポート 2380/tcp
# systemctl enable iptables.service --now # iptables -N OS_FIREWALL_ALLOW # iptables -t filter -I INPUT -j OS_FIREWALL_ALLOW # iptables -A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 2379 -j ACCEPT # iptables -A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 2380 -j ACCEPT # iptables-save | tee /etc/sysconfig/iptables
注記この例では、新規チェーン
OS_FIREWALL_ALLOW
が作成されます。 これは、OpenShift Container Platform インストーラーがファイアウォールルールに使用する標準の名前になります。警告環境が IaaS 環境でホストされている場合には、インスタンスがこれらのポートに入ってくるトラフィックを許可できるように、セキュリティーグループを変更します。
etcd をインストールします。
# yum install -y etcd
バージョン
etcd-2.3.7-4.el7.x86_64
以降がインストールされていることを確認します。etcd Pod 定義を削除して、etcd サービスが実行されていない状態にします。
# mkdir -p /etc/origin/node/pods-stopped # mv /etc/origin/node/pods/* /etc/origin/node/pods-stopped/
etcd 設定およびデータを削除します。
# rm -Rf /etc/etcd/* # rm -Rf /var/lib/etcd/*
証明書および設定ファイルを展開します。
# tar xzvf /tmp/etcd0.example.com.tgz -C /etc/etcd/
新規ホストで etcd を起動します。
# systemctl enable etcd --now
ホストがクラスターの一部であることと現在のクラスターの正常性を確認します。
v2 etcd api を使用する場合は、以下のコマンドを実行します。
# etcdctl --cert-file=/etc/etcd/peer.crt \ --key-file=/etc/etcd/peer.key \ --ca-file=/etc/etcd/ca.crt \ --peers="https://*master-0.example.com*:2379,\ https://*master-1.example.com*:2379,\ https://*master-2.example.com*:2379,\ https://*etcd0.example.com*:2379"\ cluster-health member 5ee217d19001 is healthy: got healthy result from https://192.168.55.12:2379 member 2a529ba1840722c0 is healthy: got healthy result from https://192.168.55.8:2379 member 8b8904727bf526a5 is healthy: got healthy result from https://192.168.55.21:2379 member ed4f0efd277d7599 is healthy: got healthy result from https://192.168.55.13:2379 cluster is healthy
v3 etcd api を使用する場合は、以下のコマンドを実行します。
# ETCDCTL_API=3 etcdctl --cert="/etc/etcd/peer.crt" \ --key=/etc/etcd/peer.key \ --cacert="/etc/etcd/ca.crt" \ --endpoints="https://*master-0.example.com*:2379,\ https://*master-1.example.com*:2379,\ https://*master-2.example.com*:2379,\ https://*etcd0.example.com*:2379"\ endpoint health https://master-0.example.com:2379 is healthy: successfully committed proposal: took = 5.011358ms https://master-1.example.com:2379 is healthy: successfully committed proposal: took = 1.305173ms https://master-2.example.com:2379 is healthy: successfully committed proposal: took = 1.388772ms https://etcd0.example.com:2379 is healthy: successfully committed proposal: took = 1.498829ms
各 OpenShift Container Platform マスターの変更
すべてのマスターの
/etc/origin/master/master-config.yaml
ファイルのetcClientInfo
セクションでマスター設定を変更します。新規 etcd ホストを、データを保存するために OpenShift Container Platform が使用する etcd サーバーの一覧に追加し、失敗したすべての etcd ホストを削除します。etcdClientInfo: ca: master.etcd-ca.crt certFile: master.etcd-client.crt keyFile: master.etcd-client.key urls: - https://master-0.example.com:2379 - https://master-1.example.com:2379 - https://master-2.example.com:2379 - https://etcd0.example.com:2379
マスター API サービスを再起動します。
すべてのマスターのインストールに対しては、以下を実行します。
# master-restart api # master-restart controllers
警告etcd ノードの数は奇数でなければなりません。 そのため、2 つ以上のホストを追加する必要があります。
Flannel を使用する場合、新規 etcd ホストを組み込むために、すべての OpenShift Container Platform ホストの
/etc/sysconfig/flanneld
にあるflanneld
サービス設定を変更します。FLANNEL_ETCD_ENDPOINTS=https://master-0.example.com:2379,https://master-1.example.com:2379,https://master-2.example.com:2379,https://etcd0.example.com:2379
flanneld
サービスを再起動します。# systemctl restart flanneld.service
3.7. OpenShift Container Platform サービスの再オンライン化
変更を終了した後に、OpenShift Container Platform をオンラインに戻します。
手順
それぞれの OpenShift Container Platform マスターで、バックアップからマスターおよびノード設定を復元し、すべての関連するサービスを有効にしてから再起動します。
# cp ${MYBACKUPDIR}/etc/origin/node/pods/* /etc/origin/node/pods/ # cp ${MYBACKUPDIR}/etc/origin/master/master.env /etc/origin/master/master.env # cp ${MYBACKUPDIR}/etc/origin/master/master-config.yaml.<timestamp> /etc/origin/master/master-config.yaml # cp ${MYBACKUPDIR}/etc/origin/node/node-config.yaml.<timestamp> /etc/origin/node/node-config.yaml # cp ${MYBACKUPDIR}/etc/origin/master/scheduler.json.<timestamp> /etc/origin/master/scheduler.json # master-restart api # master-restart controllers
各 OpenShift Container Platform ノードで、必要に応じて ノードの設定マップ を更新し、atomic-openshift-node サービスを有効にして再起動します。
# cp /etc/origin/node/node-config.yaml.<timestamp> /etc/origin/node/node-config.yaml # systemctl enable atomic-openshift-node # systemctl start atomic-openshift-node
3.8. プロジェクトの復元
プロジェクトの復元には、oc create -f <file_name>
を実行して新規プロジェクトを作成してから、エクスポートされたファイルを復元します。
手順
プロジェクトを作成します。
$ oc new-project <project_name> 1
- 1
- この
<project_name>
の値は、バックアップされたプロジェクトの名前と同じである必要があります。
プロジェクトオブジェクトをインポートします。
$ oc create -f project.yaml
ロールバインディング、シークレット、サービスアカウント、および永続ボリューム要求 (PVC) など、プロジェクトのバックアップ時にエクスポートされた他のリソースをインポートします。
$ oc create -f <object>.yaml
別のオブジェクトが必要な場合に、インポートに失敗するリソースもあります。これが発生した場合は、エラーメッセージを確認し、最初にインポートする必要のあるリソースを特定します。
Pod およびデフォルトサービスアカウントなどの一部のリソースは、作成できない場合があります。
3.9. アプリケーションデータの復元
rsync
がコンテナーイメージ内にインストールされていることを前提とすると、アプリケーションデータは oc rsync
コマンドを使用してバックアップできます。Red Hat rhel7 ベースイメージには rsync
が含まれます。したがって、rhel7 をベースとするすべてのイメージにはこれが含まれることになります。Troubleshooting and Debugging CLI Operations - rsync を参照してください。
これは、アプリケーションデータの 汎用的な 復元についての説明であり、データベースシステムの特殊なエクスポート/インポートなどのアプリケーション固有のバックアップ手順については考慮に入れられていません。
使用する永続ボリュームのタイプ (Cinder、NFS、Gluster など) によっては、他の復元手段を使用できる場合もあります。
手順
Jenkins デプロイメントのアプリケーションデータの復元例
バックアップを確認します。
$ ls -la /tmp/jenkins-backup/ total 8 drwxrwxr-x. 3 user user 20 Sep 6 11:14 . drwxrwxrwt. 17 root root 4096 Sep 6 11:16 .. drwxrwsrwx. 12 user user 4096 Sep 6 11:14 jenkins
oc rsync
ツールを使用して、データを実行中の Pod にコピーします。$ oc rsync /tmp/jenkins-backup/jenkins jenkins-1-37nux:/var/lib
注記アプリケーションによっては、アプリケーションを再起動する必要があります。
必要に応じて、新規データを使ってアプリケーションを再起動します。
$ oc delete pod jenkins-1-37nux
または、デプロイメントを 0 にスケールダウンしてから再びスケールアップすることもできます。
$ oc scale --replicas=0 dc/jenkins $ oc scale --replicas=1 dc/jenkins
3.10. Persistent Volume Claim (永続ボリューム要求、PVC) の復元
このトピックでは、データを復元するための 2 つの方法について説明します。最初の方法ではファイルを削除してから、ファイルを予想される場所に戻します。2 つ目の例では、PVC を移行する方法を示します。この移行は、ストレージを移動する必要がある場合や、バックアップストレージがなくなるなどの障害発生時の状況で実行されます。
データをアプリケーションに復元する手順について、特定のアプリケーションについての復元手順を確認してください。
3.10.1. ファイルの既存 PVC への復元
手順
ファイルを削除します。
$ oc rsh demo-2-fxx6d sh-4.2$ ls */opt/app-root/src/uploaded/* lost+found ocp_sop.txt sh-4.2$ *rm -rf /opt/app-root/src/uploaded/ocp_sop.txt* sh-4.2$ *ls /opt/app-root/src/uploaded/* lost+found
PVC にあったファイルの rsync バックアップが含まれるサーバーのファイルを置き換えます。
$ oc rsync uploaded demo-2-fxx6d:/opt/app-root/src/
oc rsh
を使用してファイルが Pod に戻されていることを確認し、Pod に接続してディレクトリーのコンテンツを表示します。$ oc rsh demo-2-fxx6d sh-4.2$ *ls /opt/app-root/src/uploaded/* lost+found ocp_sop.txt
3.10.2. データの新規 PVC への復元
以下の手順では、新規 pvc
が作成されていることを前提としています。
手順
現在定義されている
claim-name
を上書きします。$ oc set volume dc/demo --add --name=persistent-volume \ --type=persistentVolumeClaim --claim-name=filestore \ --mount-path=/opt/app-root/src/uploaded --overwrite
Pod が新規 PVC を使用していることを確認します。
$ oc describe dc/demo Name: demo Namespace: test Created: 3 hours ago Labels: app=demo Annotations: openshift.io/generated-by=OpenShiftNewApp Latest Version: 3 Selector: app=demo,deploymentconfig=demo Replicas: 1 Triggers: Config, Image(demo@latest, auto=true) Strategy: Rolling Template: Labels: app=demo deploymentconfig=demo Annotations: openshift.io/container.demo.image.entrypoint=["container-entrypoint","/bin/sh","-c","$STI_SCRIPTS_PATH/usage"] openshift.io/generated-by=OpenShiftNewApp Containers: demo: Image: docker-registry.default.svc:5000/test/demo@sha256:0a9f2487a0d95d51511e49d20dc9ff6f350436f935968b0c83fcb98a7a8c381a Port: 8080/TCP Volume Mounts: /opt/app-root/src/uploaded from persistent-volume (rw) Environment Variables: <none> Volumes: persistent-volume: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) *ClaimName: filestore* ReadOnly: false ...omitted...
デプロイメント設定では新規の
pvc
を使用しているため、oc rsync
を実行してファイルを新規のpvc
に配置します。$ oc rsync uploaded demo-3-2b8gs:/opt/app-root/src/ sending incremental file list uploaded/ uploaded/ocp_sop.txt uploaded/lost+found/ sent 181 bytes received 39 bytes 146.67 bytes/sec total size is 32 speedup is 0.15
oc rsh
を使用してファイルが Pod に戻されていることを確認し、Pod に接続してディレクトリーのコンテンツを表示します。$ oc rsh demo-3-2b8gs sh-4.2$ ls /opt/app-root/src/uploaded/ lost+found ocp_sop.txt
第4章 マスターホストの置き換え
失敗したマスターホストを置き換えることができます。
まず、失敗したマスターホストをクラスターから削除し、次に置き換えマスターホストを追加します。失敗したマスターホストが etcd を実行していた場合、etcd を新規のマスターホストに追加して etcd を拡張します。
このトピックのすべてのセクションを完了する必要があります。
4.1. マスターホストの使用の終了
マスターホストは OpenShift Container Platform API およびコントローラーサービスなどの重要なサービスを実行します。マスターホストの使用を終了するには、これらのサービスが停止している必要があります。
OpenShift Container Platform API サービスはアクティブ/アクティブサービスであるため、サービスを停止しても、要求が別のマスターサーバーに送信される限り環境に影響はありません。ただし、OpenShift Container Platform コントローラーサービスはアクティブ/パッシブサービスであり、サービスは etcd を利用してアクティブなマスターを判別します。
複数マスターアーキテクチャーでマスターホストの使用を終了するには、新しい接続でのマスターの使用を防ぐためにマスターをロードバランサープールから削除することが関係します。このプロセスは使用されるロードバランサーによって大きく異なります。以下の手順では、マスターの haproxy
からの削除についての詳しく説明しています。OpenShift Container Platform がクラウドプロバイダーで実行されている場合や、F5
アプライアンスを使用する場合は、特定の製品ドキュメントを参照してマスターをローテーションから削除するようにしてください。
手順
/etc/haproxy/haproxy.cfg
設定ファイルでbackend
セクションを削除します。たとえば、haproxy
を使用してmaster-0.example.com
という名前のマスターの使用を終了する場合は、ホスト名が以下から削除されていることを確認します。backend mgmt8443 balance source mode tcp # MASTERS 8443 server master-1.example.com 192.168.55.12:8443 check server master-2.example.com 192.168.55.13:8443 check
次に、
haproxy
サービスを再起動します。$ sudo systemctl restart haproxy
マスターがロードバランサーから削除される場合、定義ファイルを静的 Pod のディレクトリー /etc/origin/node/pods から移動して API およびコントローラーサービスを無効にします。
# mkdir -p /etc/origin/node/pods/disabled # mv /etc/origin/node/pods/controller.yaml /etc/origin/node/pods/disabled/: +
- マスターホストはスケジュール可能な OpenShift Container Platform ノードであるため、ノードホストの使用の終了 セクションの手順に従ってください。
マスターホストを
/etc/ansible/hosts
Ansible インベントリーファイルの[masters]
および[nodes]
グループから削除し、このインベントリーファイルを使用して Ansible タスクを実行する場合の問題を回避できます。警告Ansible インベントリーファイルに一覧表示される最初のマスターホストの使用を終了するには、とくに注意が必要になります。
/etc/origin/master/ca.serial.txt
ファイルは Ansible ホストインベントリーに一覧表示される最初のマスターでのみ生成されます。最初のマスターホストの使用を終了する場合は、このプロセスの実行前に/etc/origin/master/ca.serial.txt
ファイルを残りのマスターホストにコピーします。重要複数のマスターを実行する OpenShift Container Platform 3.11 クラスターでは、マスターノードのいずれかの
/etc/origin/master
、/etc/etcd/ca
および/etc/etcd/generated_certs
に追加の CA 証明書が含まれます。これらは、アプリケーションノードおよび etcd ノードのスケールアップ操作に必要であり、CA ホストマスターが非推奨になっている場合は、別のマスターノードで復元する必要があります。kubernetes
サービスにはマスターホスト IP がエンドポイントとして含まれています。マスターの使用が適切に終了していることを確認するには、kubernetes
サービスの出力を確認して、使用が終了したマスターが削除されているかどうかを確認します。$ oc describe svc kubernetes -n default Name: kubernetes Namespace: default Labels: component=apiserver provider=kubernetes Annotations: <none> Selector: <none> Type: ClusterIP IP: 10.111.0.1 Port: https 443/TCP Endpoints: 192.168.55.12:8443,192.168.55.13:8443 Port: dns 53/UDP Endpoints: 192.168.55.12:8053,192.168.55.13:8053 Port: dns-tcp 53/TCP Endpoints: 192.168.55.12:8053,192.168.55.13:8053 Session Affinity: ClientIP Events: <none>
マスターの使用が正常に終了した後、マスターが以前に実行されていたホストを安全に削除することができます。
4.2. ホストの追加
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
を使用して、そのファイルの場所を指定する必要があります。
ノードの推奨の最大数については、クラスターの最大値 のセクションを参照してください。
手順
openshift-ansible パッケージを更新して最新の Playbook を取得します。
# yum update openshift-ansible
/etc/ansible/hosts ファイルを編集し、new_<host_type> を [OSEv3:children] セクションに追加します。たとえば、新規ノードホストを追加するには、new_nodes を追加します。
[OSEv3:children] masters nodes new_nodes
新規マスターホストを追加するには、new_masters を追加します。
[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 をどこにも配置できなくなります。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 を実行すると、新規ノードのみが更新されます。クラスター内の既存ノードを更新するために実行することはできません。
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
EFK スタックをクラスターにデプロイしている場合は、ノードラベルを
logging-infra-fluentd=true
に設定します。# oc label node/new-node.example.com logging-infra-fluentd=true
- Playbook の実行後に、インストールの検証 を行います。
[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]
4.3. etcd のスケーリング
etcd クラスターは、リソースを etcd ホストに追加して垂直的に拡張することも、etcd ホストを追加して水平的に拡張することもできます。
etcd が使用する投票システムのために、クラスターには常に奇数のメンバーが含まれている必要があります。
奇数の etcd ホストを含むクラスターの場合、フォールトトレランスに対応できます。奇数の etcd ホストがあることで、クォーラム (定足数) に必要な数が変わることはありませんが、障害発生時の耐性が高まります。たとえば、クラスターが 3 メンバーで設定される場合、クォーラム (定足数) は 2 で、1 メンバーが障害耐性用になります。これにより、クラスターはメンバーの 2 つが正常である限り、機能し続けます。
3 つの etcd ホストで設定される実稼働クラスターの使用が推奨されます。
新規ホストには、新規の Red Hat Enterprise Linux version 7 専用ホストが必要です。etcd ストレージは最大のパフォーマンスを達成できるように SSD ディスクおよび /var/lib/etcd
でマウントされる専用ディスクに置かれる必要があります。
前提条件
- 新規 etcd ホストを追加する前に、etcd 設定およびデータのバックアップ を行ってデータの損失を防ぎます。
新規ホストが正常でないクラスターに追加されないように、現在の etcd クラスターステータスを確認します。以下のコマンドを実行します。
# ETCDCTL_API=3 etcdctl --cert="/etc/etcd/peer.crt" \ --key=/etc/etcd/peer.key \ --cacert="/etc/etcd/ca.crt" \ --endpoints="https://*master-0.example.com*:2379,\ https://*master-1.example.com*:2379,\ https://*master-2.example.com*:2379" endpoint health https://master-0.example.com:2379 is healthy: successfully committed proposal: took = 5.011358ms https://master-1.example.com:2379 is healthy: successfully committed proposal: took = 1.305173ms https://master-2.example.com:2379 is healthy: successfully committed proposal: took = 1.388772ms
scaleup
Playbook を実行する前に、新規ホストが適切な Red Hat ソフトウェアチャンネルに登録されていることを確認します。# subscription-manager register \ --username=*<username>* --password=*<password>* # subscription-manager attach --pool=*<poolid>* # subscription-manager repos --disable="*" # subscription-manager repos \ --enable=rhel-7-server-rpms \ --enable=rhel-7-server-extras-rpms
etcd は
rhel-7-server-extras-rpms
ソフトウェアチャンネルでホストされています。すべての未使用の etcd メンバーが etcd クラスターから削除されていることを確認します。これは、
scaleup
Playbook を実行する前に完了する必要があります。etcd メンバーを一覧表示します。
# etcdctl --cert="/etc/etcd/peer.crt" --key="/etc/etcd/peer.key" \ --cacert="/etc/etcd/ca.crt" --endpoints=ETCD_LISTEN_CLIENT_URLS member list -w table
該当する場合は、未使用の etcd メンバー ID をコピーします。
以下のコマンドで ID を指定して、未使用のメンバーを削除します。
# etcdctl --cert="/etc/etcd/peer.crt" --key="/etc/etcd/peer.key" \ --cacert="/etc/etcd/ca.crt" --endpoints=ETCD_LISTEN_CLIENT_URL member remove UNUSED_ETCD_MEMBER_ID
現在の etcd ノードで etcd および iptables をアップグレードします。
# yum update etcd iptables-services
- etcd ホストの /etc/etcd 設定をバックアップします。
- 新規 etcd メンバーが OpenShift Container Platform ノードでもある場合は、必要な数のホストをクラスターに追加 します。
- この手順の残りでは 1 つのホストを追加していることを前提としていますが、複数のホストを追加する場合は、各ホストですべての手順を実行します。
4.3.1. Ansible を使用した新規 etcd ホストの追加
手順
Ansible インベントリーファイルで、
[new_etcd]
という名前の新規グループおよび新規ホストを作成します。次に、new_etcd
グループを[OSEv3]
グループの子として追加します。[OSEv3:children] masters nodes etcd new_etcd 1 ... [OUTPUT ABBREVIATED] ... [etcd] master-0.example.com master-1.example.com master-2.example.com [new_etcd] 2 etcd0.example.com 3
注記インベントリーファイル内の古い
etcd host
エントリーを新しいetcd host
エントリーに置き換えます。古いetcd host
を置き換えるときに、/etc/etcd/ca/
ディレクトリーのコピーを作成する必要があります。または、etcd hosts
をスケールアップする前に、etcd ca と証明書を再デプロイすることもできます。OpenShift Container Platform をインストールし、Ansible インベントリーファイルをホストするホストから、Playbook ディレクトリーに移動し、etcd
scaleup
Playbook を実行します。$ cd /usr/share/ansible/openshift-ansible $ ansible-playbook playbooks/openshift-etcd/scaleup.yml
Playbook が実行された後に、新規 etcd ホストを
[new_etcd]
グループから[etcd]
グループに移行し、現在のステータスを反映するようにインベントリーファイルを変更します。[OSEv3:children] masters nodes etcd new_etcd ... [OUTPUT ABBREVIATED] ... [etcd] master-0.example.com master-1.example.com master-2.example.com etcd0.example.com
Flannel を使用する場合には、OpenShift Container Platform のホストごとに、
/etc/sysconfig/flanneld
にあるflanneld
サービス設定を変更し、新しい etcd ホストを追加します。FLANNEL_ETCD_ENDPOINTS=https://master-0.example.com:2379,https://master-1.example.com:2379,https://master-2.example.com:2379,https://etcd0.example.com:2379
flanneld
サービスを再起動します。# systemctl restart flanneld.service
4.3.2. 新規 etcd ホストの手動による追加
etcd をマスターノードで静的 Pod として実行しない場合、別の etcd ホストを追加する必要が生じる場合があります。
手順
現在の etcd クラスターの変更
etcd 証明書を作成するには、値を環境の値に置き換えて openssl
コマンドを実行します。
環境変数を作成します。
export NEW_ETCD_HOSTNAME="*etcd0.example.com*" export NEW_ETCD_IP="192.168.55.21" export CN=$NEW_ETCD_HOSTNAME export SAN="IP:${NEW_ETCD_IP}, DNS:${NEW_ETCD_HOSTNAME}" export PREFIX="/etc/etcd/generated_certs/etcd-$CN/" export OPENSSLCFG="/etc/etcd/ca/openssl.cnf"
注記etcd_v3_ca_*
として使用されるカスタムのopenssl
拡張には、subjectAltName
としての $SAN 環境変数が含まれます。詳細は、/etc/etcd/ca/openssl.cnf
を参照してください。設定および証明書を保存するディレクトリーを作成します。
# mkdir -p ${PREFIX}
サーバー証明書要求を作成し、これに署名します (server.csr および server.crt)。
# openssl req -new -config ${OPENSSLCFG} \ -keyout ${PREFIX}server.key \ -out ${PREFIX}server.csr \ -reqexts etcd_v3_req -batch -nodes \ -subj /CN=$CN # openssl ca -name etcd_ca -config ${OPENSSLCFG} \ -out ${PREFIX}server.crt \ -in ${PREFIX}server.csr \ -extensions etcd_v3_ca_server -batch
ピア証明書要求を作成し、これに署名します (peer.csr および peer.crt)。
# openssl req -new -config ${OPENSSLCFG} \ -keyout ${PREFIX}peer.key \ -out ${PREFIX}peer.csr \ -reqexts etcd_v3_req -batch -nodes \ -subj /CN=$CN # openssl ca -name etcd_ca -config ${OPENSSLCFG} \ -out ${PREFIX}peer.crt \ -in ${PREFIX}peer.csr \ -extensions etcd_v3_ca_peer -batch
後で変更できるように、現在の etcd 設定および
ca.crt
ファイルをサンプルとして現在のノードからコピーします。# cp /etc/etcd/etcd.conf ${PREFIX} # cp /etc/etcd/ca.crt ${PREFIX}
存続する etcd ホストから、新規ホストをクラスターに追加します。etcd メンバーをクラスターに追加するには、まず最初のメンバーの
peerURLs
値のデフォルトの localhost ピアを調整する必要があります。member list
コマンドを使用して最初のメンバーのメンバー ID を取得します。# etcdctl --cert-file=/etc/etcd/peer.crt \ --key-file=/etc/etcd/peer.key \ --ca-file=/etc/etcd/ca.crt \ --peers="https://172.18.1.18:2379,https://172.18.9.202:2379,https://172.18.0.75:2379" \ 1 member list
- 1
--peers
パラメーター値でアクティブな etcd メンバーのみの URL を指定するようにしてください。
etcd がクラスターピアについてリッスンする IP アドレスを取得します。
$ ss -l4n | grep 2380
直前の手順で取得されたメンバー ID および IP アドレスを渡して、
etcdctl member update
コマンドを使用してpeerURLs
の値を更新します。# etcdctl --cert-file=/etc/etcd/peer.crt \ --key-file=/etc/etcd/peer.key \ --ca-file=/etc/etcd/ca.crt \ --peers="https://172.18.1.18:2379,https://172.18.9.202:2379,https://172.18.0.75:2379" \ member update 511b7fb6cc0001 https://172.18.1.18:2380
-
member list
コマンドを再実行し、ピア URL に localhost が含まれなくなるようにします。
新規ホストを etcd クラスターに追加します。新規ホストはまだ設定されていないため、新規ホストを設定するまでステータスが
unstarted
のままであることに注意してください。警告各メンバーを追加し、1 回に 1 つずつメンバーをオンライン状態にします。各メンバーをクラスターに追加する際に、現在のピアの
peerURL
一覧を調整する必要があります。peerURL
一覧はメンバーが追加されるたびに拡張します。etcdctl member add
コマンドは、以下に説明されているように、メンバーを追加する際に etcd.conf ファイルで設定する必要のある値を出力します。# etcdctl -C https://${CURRENT_ETCD_HOST}:2379 \ --ca-file=/etc/etcd/ca.crt \ --cert-file=/etc/etcd/peer.crt \ --key-file=/etc/etcd/peer.key member add ${NEW_ETCD_HOSTNAME} https://${NEW_ETCD_IP}:2380 1 Added member named 10.3.9.222 with ID 4e1db163a21d7651 to cluster ETCD_NAME="<NEW_ETCD_HOSTNAME>" ETCD_INITIAL_CLUSTER="<NEW_ETCD_HOSTNAME>=https://<NEW_HOST_IP>:2380,<CLUSTERMEMBER1_NAME>=https:/<CLUSTERMEMBER2_IP>:2380,<CLUSTERMEMBER2_NAME>=https:/<CLUSTERMEMBER2_IP>:2380,<CLUSTERMEMBER3_NAME>=https:/<CLUSTERMEMBER3_IP>:2380" ETCD_INITIAL_CLUSTER_STATE="existing"
- 1
- この行で、
10.3.9.222
は etcd メンバーのラベルです。ホスト名、IP アドレスまたは単純な名前を指定できます。
サンプル
${PREFIX}/etcd.conf
ファイルを更新します。以下の値を直前の手順で生成された値に置き換えます。
- ETCD_NAME
- ETCD_INITIAL_CLUSTER
- ETCD_INITIAL_CLUSTER_STATE
以下の変数は、直前の手順で出力された新規ホストの IP に変更します。
${NEW_ETCD_IP}
は、値として使用できます。ETCD_LISTEN_PEER_URLS ETCD_LISTEN_CLIENT_URLS ETCD_INITIAL_ADVERTISE_PEER_URLS ETCD_ADVERTISE_CLIENT_URLS
- メンバーシステムを etcd ノードとして使用していた場合には、/etc/etcd/etcd.conf ファイルの現在の値を上書きする必要があります。
ファイルで構文エラーや欠落している IP アドレスがないかを確認します。 エラーや欠落がある場合には、etced サービスが失敗してしまう可能性があります。
# vi ${PREFIX}/etcd.conf
-
インストールファイルをホストするノードでは、/etc/ansible/hosts インベントリーファイルの
[etcd]
ホストグループを更新します。古い etcd ホストを削除し、新規ホストを追加します。 証明書、サンプル設定ファイル、および
ca
を含むtgz
ファイルを作成し、これを新規ホストにコピーします。# tar -czvf /etc/etcd/generated_certs/${CN}.tgz -C ${PREFIX} . # scp /etc/etcd/generated_certs/${CN}.tgz ${CN}:/tmp/
新規 etcd ホストの変更
iptables-services
をインストールして etcd の必要なポートを開くために iptables ユーティリティーを指定します。# yum install -y iptables-services
etcd の通信を許可する
OS_FIREWALL_ALLOW
ファイアウォールルールを作成します。- クライアントのポート 2379/tcp
ピア通信のポート 2380/tcp
# systemctl enable iptables.service --now # iptables -N OS_FIREWALL_ALLOW # iptables -t filter -I INPUT -j OS_FIREWALL_ALLOW # iptables -A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 2379 -j ACCEPT # iptables -A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 2380 -j ACCEPT # iptables-save | tee /etc/sysconfig/iptables
注記この例では、新規チェーン
OS_FIREWALL_ALLOW
が作成されます。 これは、OpenShift Container Platform インストーラーがファイアウォールルールに使用する標準の名前になります。警告環境が IaaS 環境でホストされている場合には、インスタンスがこれらのポートに入ってくるトラフィックを許可できるように、セキュリティーグループを変更します。
etcd をインストールします。
# yum install -y etcd
バージョン
etcd-2.3.7-4.el7.x86_64
以降がインストールされていることを確認します。etcd Pod 定義を削除して、etcd サービスが実行されていない状態にします。
# mkdir -p /etc/origin/node/pods-stopped # mv /etc/origin/node/pods/* /etc/origin/node/pods-stopped/
etcd 設定およびデータを削除します。
# rm -Rf /etc/etcd/* # rm -Rf /var/lib/etcd/*
証明書および設定ファイルを展開します。
# tar xzvf /tmp/etcd0.example.com.tgz -C /etc/etcd/
新規ホストで etcd を起動します。
# systemctl enable etcd --now
ホストがクラスターの一部であることと現在のクラスターの正常性を確認します。
v2 etcd api を使用する場合は、以下のコマンドを実行します。
# etcdctl --cert-file=/etc/etcd/peer.crt \ --key-file=/etc/etcd/peer.key \ --ca-file=/etc/etcd/ca.crt \ --peers="https://*master-0.example.com*:2379,\ https://*master-1.example.com*:2379,\ https://*master-2.example.com*:2379,\ https://*etcd0.example.com*:2379"\ cluster-health member 5ee217d19001 is healthy: got healthy result from https://192.168.55.12:2379 member 2a529ba1840722c0 is healthy: got healthy result from https://192.168.55.8:2379 member 8b8904727bf526a5 is healthy: got healthy result from https://192.168.55.21:2379 member ed4f0efd277d7599 is healthy: got healthy result from https://192.168.55.13:2379 cluster is healthy
v3 etcd api を使用する場合は、以下のコマンドを実行します。
# ETCDCTL_API=3 etcdctl --cert="/etc/etcd/peer.crt" \ --key=/etc/etcd/peer.key \ --cacert="/etc/etcd/ca.crt" \ --endpoints="https://*master-0.example.com*:2379,\ https://*master-1.example.com*:2379,\ https://*master-2.example.com*:2379,\ https://*etcd0.example.com*:2379"\ endpoint health https://master-0.example.com:2379 is healthy: successfully committed proposal: took = 5.011358ms https://master-1.example.com:2379 is healthy: successfully committed proposal: took = 1.305173ms https://master-2.example.com:2379 is healthy: successfully committed proposal: took = 1.388772ms https://etcd0.example.com:2379 is healthy: successfully committed proposal: took = 1.498829ms
各 OpenShift Container Platform マスターの変更
すべてのマスターの
/etc/origin/master/master-config.yaml
ファイルのetcClientInfo
セクションでマスター設定を変更します。新規 etcd ホストを、データを保存するために OpenShift Container Platform が使用する etcd サーバーの一覧に追加し、失敗したすべての etcd ホストを削除します。etcdClientInfo: ca: master.etcd-ca.crt certFile: master.etcd-client.crt keyFile: master.etcd-client.key urls: - https://master-0.example.com:2379 - https://master-1.example.com:2379 - https://master-2.example.com:2379 - https://etcd0.example.com:2379
マスター API サービスを再起動します。
すべてのマスターのインストールに対しては、以下を実行します。
# master-restart api # master-restart controllers
警告etcd ノードの数は奇数でなければなりません。 そのため、2 つ以上のホストを追加する必要があります。
Flannel を使用する場合、新規 etcd ホストを組み込むために、すべての OpenShift Container Platform ホストの
/etc/sysconfig/flanneld
にあるflanneld
サービス設定を変更します。FLANNEL_ETCD_ENDPOINTS=https://master-0.example.com:2379,https://master-1.example.com:2379,https://master-2.example.com:2379,https://etcd0.example.com:2379
flanneld
サービスを再起動します。# systemctl restart flanneld.service
第5章 ユーザーの管理
5.1. 概要
ユーザーとは、OpenShift Container Platform API と対話するエンティティーです。ユーザーは、アプリケーションを開発する開発者の場合もあれば、クラスターを管理する管理者の場合もあります。ユーザーは、グループのすべてのメンバーに適用されるパーミッションを設定するグループに割り当てることができます。たとえば、API アクセスをグループに付与して、そのグループのすべてのメンバーに API アクセスを付与することができます。
このトピックでは、ユーザー アカウントの管理について説明します。 これには、OpenShift Container Platform で新規ユーザーアカウントを作成する方法およびそれらを削除する方法が含まれます。
5.2. ユーザーの作成
ユーザーの作成プロセスは、設定される アイデンティティープロバイダー によって異なります。デフォルトで、OpenShift Container Platform は、すべてのユーザー名およびパスワードのアクセスを拒否する DenyAll
アイデンティティープロバイダーを使用します。
以下のプロセスでは、新規ユーザーを作成してからロールをそのユーザーに追加します。
-
アイデンティティープロバイダーに応じたユーザーアカウントを作成します。これは、アイデンティティープロバイダー設定 の一部として使用される
mappingmethod
によって異なります。 新規ユーザーに必要なロールを付与します。
# oc create clusterrolebinding <clusterrolebinding_name> \ --clusterrole=<role> --user=<user>
ここで、
--clusterrole
オプションは必要なクラスターロールになります。たとえば、新規ユーザーに対して、クラスター内のすべてに対するアクセスを付与するcluster-admin
権限を付与するには、以下を実行します。# oc create clusterrolebinding registry-controller \ --clusterrole=cluster-admin --user=admin
ロールの説明および一覧については、アーキテクチャーガイドの クラスターロールおよびローカルロール のセクションを参照してください。
クラスター管理者は、各ユーザーのアクセスレベルの管理 も実行できます。
アイデンティティープロバイダーおよび定義されたグループ構造によっては、一部のロールがユーザーに自動的に付与される場合があります。詳細は、グループの LDAP との同期 についてのセクションを参照してください。
5.3. ユーザーおよび ID リストの表示
OpenShift Container Platform のユーザー設定は、OpenShift Container Platform 内の複数の場所に保存されます。アイデンティティープロバイダーの種類を問わず、OpenShift Container Platform はロールベースのアクセス制御 (RBAC) 情報およびグループメンバーシップなどの詳細情報を内部に保存します。ユーザー情報を完全に削除するには、ユーザーアカウントに加えてこのデータも削除する必要があります。
OpenShift Container Platform では、2 つのオブジェクトタイプ (user
および identity
) に、アイデンティティープロバイダー外のユーザーデータが含まれます。
ユーザーの現在のリストを取得するには、以下を実行します。
$ oc get user NAME UID FULL NAME IDENTITIES demo 75e4b80c-dbf1-11e5-8dc6-0e81e52cc949 htpasswd_auth:demo
ID の現在のリストを取得するには、以下を実行します。
$ oc get identity NAME IDP NAME IDP USER NAME USER NAME USER UID htpasswd_auth:demo htpasswd_auth demo demo 75e4b80c-dbf1-11e5-8dc6-0e81e52cc949
2 つのオブジェクトタイプ間で一致する UID があることに注意してください。OpenShift Container Platform の使用を開始した後に認証プロバイダーの変更を試行する場合で重複するユーザー名がある場合、そのユーザー名は、ID リストに古い認証方式を参照するエントリーがあるために機能しなくなります。
5.4. グループの作成
ユーザーは OpenShift Container Platform に要求するエンティティーである一方で、ユーザーのセットで設定される 1 つの以上のグループに編成することもできます。グループは、許可ポリシーなどの場合のように数多くのユーザーを 1 度に管理する際や、パーミッションを複数のユーザーに 1 度に付与する場合などに役立ちます。
組織が LDAP を使用している場合、LDAP レコードの OpenShift Container Platform に対する同期を実行し、複数のグループを 1 つの場所で設定できるようにすることができます。この場合、ユーザーについての情報が LDAP サーバーにあることを仮定します。詳細は、グループの LDAP との同期 についてのセクションを参照してください。
LDAP を使用していない場合は、以下の手順を使用してグループを手動で作成します。
新規グループを作成するには、以下を実行します。
# oc adm groups new <group_name> <user1> <user2>
たとえば、west
グループを作成し、そのグループ内に john
および betty
ユーザーを置くには、以下を実行します。
# oc adm groups new west john betty
グループが作成されたことを確認し、グループに関連付けられたユーザーを一覧表示するには、以下を実行します。
# oc get groups NAME USERS west john, betty
次のステップ:
5.5. ユーザーおよびグループラベルの管理
ラベルをユーザーまたはグループに追加するには、以下を実行します。
$ oc label user/<user_name> <label_name>=<label_value>
たとえば、ユーザー名が theuser で、ラベルが level=gold の場合には、以下のようになります。
$ oc label user/theuser level=gold
ラベルを削除するには、以下を実行します。
$ oc label user/<user_name> <label_name>-
ユーザーまたはグループのラベルを表示するには、以下を実行します。
$ oc describe user/<user_name>
5.6. ユーザーの削除
ユーザーを削除するには、以下を実行します。
ユーザーレコードを削除します。
$ oc delete user demo user "demo" deleted
ユーザー ID を削除します。
ユーザーの ID は使用するアイデンティティープロバイダーに関連付けられます。
oc get user
でユーザーレコードからプロバイダー名を取得します。この例では、アイデンティティープロバイダー名は htpasswd_auth です。コマンドは、以下のようになります。
# oc delete identity htpasswd_auth:demo identity "htpasswd_auth:demo" deleted
この手順を省略すると、ユーザーは再度ログインできなくなります。
上記の手順の完了後は、ユーザーが再びログインすると、新規のアカウントが OpenShift Container Platform に作成されます。
ユーザーの再ログインを防ごうとする場合 (たとえば、ある社員が会社を退職し、そのアカウントを永久に削除する必要がある場合)、そのユーザーを、設定されたアイデンティティープロバイダーの認証バックエンド (htpasswd、kerberos その他) から削除することもできます。
たとえば htpasswd を使用している場合、該当のユーザー名とパスワードで OpenShift Container Platform に設定された htpasswd ファイルのエントリーを削除します。
Lightweight Directory Access Protocol (LDAP) または Red Hat Identity Management (IdM) などの外部 ID 管理については、ユーザー管理ツールを使用してユーザーエントリーを削除します。
第6章 プロジェクトの管理
6.1. 概要
OpenShift Container Platform では、プロジェクトは関連オブジェクトを分類し、分離するために使用されます。管理者は、開発者に特定プロジェクトへのアクセスを付与し、開発者の独自プロジェクトの作成を許可したり、個別プロジェクト内の管理者権限を付与したりできます。
6.2. プロジェクトのセルフプロビジョニング
開発者の独自プロジェクトの作成を許可することができます。テンプレート に基づいてプロジェクトをプロビジョニングするエンドポイントがあります。Web コンソールおよび oc new-project
コマンドは、開発者による 新規プロジェクトの作成 時にこのエンドポイントを使用します。
6.2.1. 新規プロジェクトのテンプレートの変更
API サーバーは、master-config.yaml ファイル の projectRequestTemplate
パラメーターで識別されるテンプレートに基づいてプロジェクトを自動的にプロビジョニングします。パラメーターが定義されない場合、API サーバーは要求される名前でプロジェクトを作成するデフォルトテンプレートを作成し、要求するユーザーをプロジェクトの admin (管理者) ロールに割り当てます。
独自のカスタムプロジェクトテンプレートを作成するには、以下を実行します。
現在のデフォルトプロジェクトテンプレートを使って開始します。
$ oc adm create-bootstrap-project-template -o yaml > template.yaml
- オブジェクトを追加するか、または既存オブジェクトを変更することにより、テキストエディターを使用して template.yaml ファイルを変更します。
テンプレートを読み込みます。
$ oc create -f template.yaml -n default
読み込まれたテンプレートを参照するよう master-config.yaml ファイルを変更します。
... projectConfig: projectRequestTemplate: "default/project-request" ...
プロジェクト要求が送信されると、API はテンプレートで以下のパラメーターを置き換えます。
パラメーター | 説明 |
---|---|
PROJECT_NAME | プロジェクトの名前。必須。 |
PROJECT_DISPLAYNAME | プロジェクトの表示名。空にできます。 |
PROJECT_DESCRIPTION | プロジェクトの説明。空にできます。 |
PROJECT_ADMIN_USER | 管理ユーザーのユーザー名。 |
PROJECT_REQUESTING_USER | 要求するユーザーのユーザー名。 |
API へのアクセスは、self-provisioner
ロール と self-provisioners
のクラスターのロールバインディングで開発者に付与されます。デフォルトで、このロールはすべての認証された開発者が利用できます。
6.2.2. セルフプロビジョニングの無効化
認証されたユーザーグループによる新規プロジェクトのセルフプロビジョニングを禁止することができます。
- cluster-admin 権限を持つユーザーとしてログインします。
self-provisioners
clusterrolebinding usage を確認します。以下のコマンドを実行してから、self-provisioners
セクションの Subjects を確認します。$ oc describe clusterrolebinding.rbac self-provisioners Name: self-provisioners Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: self-provisioner Subjects: Kind Name Namespace ---- ---- --------- Group system:authenticated:oauth
self-provisioner
クラスターロールをグループsystem:authenticated:oauth
から削除します。self-provisioners
クラスターロールバインディングがself-provisioner
ロールのみをsystem:authenticated:oauth
グループにバインドする場合、以下のコマンドを実行します。$ oc patch clusterrolebinding.rbac self-provisioners -p '{"subjects": null}'
self-provisioners
クラスターロールバインディングがself-provisioner
ロールをsystem:authenticated:oauth
グループ以外のユーザー、グループまたはサービスアカウントにバインドする場合、以下のコマンドを実行します。$ oc adm policy remove-cluster-role-from-group self-provisioner system:authenticated:oauth
projectRequestMessage
パラメーター値を master-config.yaml ファイルに設定し、開発者に対して新規プロジェクトの要求方法を指示します。このパラメーター値は、ユーザーのプロジェクトのセルフプロビジョニング試行時に web コンソールやコマンドラインに表示される文字列です。以下のメッセージのいずれかを使用できる可能性があります。-
プロジェクトを要求するには、システム管理者 (
projectname@example.com
) に問い合わせてください。 -
新規プロジェクトを要求するには、
https://internal.example.com/openshift-project-request
にあるプロジェクト要求フォームに記入します。
サンプル YAML ファイル
... projectConfig: ProjectRequestMessage: "message" ...
-
プロジェクトを要求するには、システム管理者 (
ロールへの自動更新を防ぐには、
self-provisioners
クラスターロールバインディングを編集します。自動更新により、クラスターロールがデフォルトの状態にリセットされます。ロールバインディングをコマンドラインで更新するには、以下を実行します。
次のコマンドを実行します。
$ oc edit clusterrolebinding.rbac self-provisioners
表示されるロールバインディングで、以下の例のように
rbac.authorization.kubernetes.io/autoupdate
パラメーター値をfalse
に設定します。apiVersion: authorization.openshift.io/v1 kind: ClusterRoleBinding metadata: annotations: rbac.authorization.kubernetes.io/autoupdate: "false" ...
単一コマンドを使用してロールバインディングを更新するには、以下を実行します。
$ oc patch clusterrolebinding.rbac self-provisioners -p '{ "metadata": { "annotations": { "rbac.authorization.kubernetes.io/autoupdate": "false" } } }'
6.3. ノードセレクターの使用
ノードセレクターは、Pod の配置を制御するためにラベルが付けられたノードと併用されます。
ラベルは、クラスターインストールの実行時 に割り当てるか、または インストール後にノードに追加 することができます。
6.3.1. クラスター全体でのデフォルトノードセレクターの設定
クラスター管理者は、クラスター全体でのノードセレクターを使用して Pod の配置を特定ノードに制限することができます。
/etc/origin/master/master-config.yaml でマスター設定ファイルを編集し、デフォルトノードセレクターの値を追加します。これは、指定された nodeSelector
値なしにすべてのプロジェクトで作成された Pod に適用されます。
... projectConfig: defaultNodeSelector: "type=user-node,region=east" ...
変更を有効にするために OpenShift サービスを再起動します。
# master-restart api # master-restart controllers
6.3.2. プロジェクト全体でのノードセレクターの設定
ノードセレクターを使って個々のプロジェクトを作成するには、プロジェクトの作成時に --node-selector
オプションを使用します。たとえば、複数のリージョンを含む OpenShift Container Platform トポロジーがある場合、ノードセレクターを使用して、特定リージョンのノードにのみ Pod をデプロイするよう特定の OpenShift Container Platform プロジェクトを制限することができます。
以下では、myproject
という名前の新規プロジェクトを作成し、Pod を user-node
および east
のラベルが付けられたノードにデプロイするように指定します。
$ oc adm new-project myproject \ --node-selector='type=user-node,region=east'
このコマンドが実行されると、これが指定プロジェクト内にあるすべての Pod に対して管理者が設定するノードセレクターになります。
new-project
サブコマンドはクラスター管理者および開発者コマンドの oc adm
と oc
の両方で利用できますが、oc adm
コマンドのみがノードセレクターを使った新規プロジェクトの作成に利用できます。new-project
サブコマンドは、プロジェクトのセルフプロビジョニング時にプロジェクト開発者が利用することはできません。
oc adm new-project
コマンドを使用すると、annotation
セクションがプロジェクトに追加されます。プロジェクトを編集し、デフォルトを上書きするように openshift.io/node-selector
値を編集できます。
... metadata: annotations: openshift.io/node-selector: type=user-node,region=east ...
また、以下のコマンドを使用して、既存プロジェクトの namespace のデフォルト値を上書きできます。
# oc patch namespace myproject -p \ '{"metadata":{"annotations":{"openshift.io/node-selector":"node-role.kubernetes.io/infra=true"}}}'
openshift.io/node-selector
が空の文字列 (oc adm new-project --node-selector=""
) に設定される場合、プロジェクトには、クラスター全体のデフォルトが設定されている場合でも、管理者設定のノードセレクターはありません。これは、クラスター管理者はデフォルトを設定して開発者のプロジェクトをノードのサブセットに制限したり、インフラストラクチャーまたは他のプロジェクトでクラスター全体をスケジュールしたりできることを意味します。
6.3.3. 開発者が指定するノードセレクター
OpenShift Container Platform 開発者は、追加でノードを制限する必要がある場合に Pod 設定でのノードセレクターの設定 を行うことができます。これはプロジェクトノードセレクターに追加されるものです。 つまり、ノードセレクターの値を持つすべてのプロジェクトについて依然としてノードセレクターの値を指定できることを意味します。
たとえば、プロジェクトが上記のアノテーションで作成 (openshift.io/node-selector: type=user-node,region=east
) されており、開発者が別のノードセレクターをそのプロジェクトの Pod に設定する場合 (例: clearance=classified
)、Pod はこれらの 3 つのラベル (type=user-node
、region=east
、および clearance=classified
) を持つノードにのみスケジュールされます。region=west
が Pod に設定されている場合、Pod はラベル region=east
および region=west
を持つノードを要求しても成功しません。ラベルは 1 つの値にのみ設定できるため、Pod はスケジュールされません。
6.4. ユーザーあたりのセルフプロビジョニングされたプロジェクト数の制限
指定されるユーザーが要求するセルフプロビジョニングされたプロジェクトの数は、ProjectRequestLimit
受付制御プラグイン で制限できます。
OpenShift Container Platform 3.1 で、プロジェクトの要求テンプレートが 新規プロジェクトのテンプレートの変更 で説明されるプロセスを使用して作成される場合、生成されるテンプレートには、ProjectRequestLimitConfig
に使用されるアノテーション openshift.io/requester: ${PROJECT_REQUESTING_USER}
が含まれません。アノテーションは追加する必要があります。
ユーザーの制限を指定するには、設定をマスター設定ファイル (/etc/origin/master/master-config.yaml) 内のプラグインに指定する必要があります。プラグインの設定は、ユーザーラベルのセレクターの一覧および関連付けられるプロジェクト要求の最大数を取ります。
セレクターは順番に評価されます。現在のユーザーに一致する最初のセレクターは、プロジェクトの最大数を判別するために使用されます。セレクターが指定されていない場合、制限はすべてのユーザーに適用されます。プロジェクトの最大数が指定されていない場合、無制限のプロジェクトが特定のセレクターに対して許可されます。
以下の設定は、ユーザーあたりのグローバル制限を 2 プロジェクトに設定し、ラベル level=advanced
を持つユーザーに対して 10 プロジェクトを、ラベル level=admin
を持つユーザーに対しては無制限のプロジェクトを許可します。
admissionConfig: pluginConfig: ProjectRequestLimit: configuration: apiVersion: v1 kind: ProjectRequestLimitConfig limits: - selector: level: admin 1 - selector: level: advanced 2 maxProjects: 10 - maxProjects: 2 3
ユーザーおよびグループラベルの管理 では、ユーザーおよびグループのラベルを追加し、削除し、表示する方法について詳述しています。
変更を加えたら、OpenShift Container Platform を再起動して、変更を有効にします。
# master-restart api # master-restart controllers
6.5. サービスアカウント別のセルフプロビジョニングされたプロジェクトの有効化および制限
デフォルトで、サービスアカウントはプロジェクトを作成できません。ただし、管理者はサービスアカウント別にこの機能を有効でき、指定されるサービスアカウントが要求するセルフプロビジョニングされたプロジェクトの数は、ProjectRequestLimit
受付制御プラグイン で制限できます。
サービスアカウントがプロジェクトを作成することを許可される場合、プロジェクトエディターがラベルを操作する可能性があるため、プロジェクトのそれらのラベルを信頼することはできません。
プロジェクトにサービスアカウントを作成します (存在しない場合)。
$ oc create sa <sa_name>
cluster-admin
権限を持つユーザーとして、self-provisioner
クラスターロールをサービスアカウントに追加します。$ oc adm policy \ add-cluster-role-to-user self-provisioner \ system:serviceaccount:<project>:<sa_name>
/etc/origin/master/master-config.yaml のマスター設定ファイルを編集し、
ProjectRequestLimit
セクションのmaxProjectsForServiceAccounts
パラメーター値を、任意の指定のセルフプロビジョニングされたサービスが作成できるプロジェクトの最大数に設定します。たとえば、以下の設定は、サービスアカウントごとにグローバル制限の 3 つのプロジェクトを設定します。
admissionConfig: pluginConfig: ProjectRequestLimit: configuration: apiVersion: v1 kind: ProjectRequestLimitConfig maxProjectsForServiceAccounts: 3
変更を保存した後に、それらの変更を有効にするには、OpenShift Container Platform を再起動します。
# master-restart api # master-restart controllers
サービスアカウントとしてログインし、新規プロジェクトを作成して、変更が適用されていることを確認します。
トークンを使用し、サービスアカウントとしてログインします。
$ oc login --token <token>
新しいプロジェクトを作成します。
$ oc new-project <project_name>
第7章 Pod の管理
7.1. 概要
このトピックでは、Pod を 1 回実行する場合の期間や使用可能な帯域幅を含む Pod の管理について説明します。
7.2. Pod の表示
コンテナーのランタイム環境を提供する、Pod についての使用状況の統計を表示できます。これらの使用状況の統計には CPU、メモリー、およびストレージの消費量が含まれます。
使用状況の統計を表示するには、以下を実行します。
$ oc adm top pods NAME CPU(cores) MEMORY(bytes) hawkular-cassandra-1-pqx6l 219m 1240Mi hawkular-metrics-rddnv 20m 1765Mi heapster-n94r4 3m 37Mi
ラベルを持つ Pod の使用状況の統計を表示するには、以下を実行します。
$ oc adm top pod --selector=''
フィルターに使用するセレクター (ラベルクエリー) を選択する必要があります。=
、==
、および !=
をサポートします。
使用状況の統計を閲覧するには、cluster-reader
パーミッションがなければなりません。
使用状況の統計を閲覧するには、metrics-server
がインストールされている必要があります。Horizontal Pod Autoscaler の要件 を参照してください。
7.3. 1 回実行 (run-once) Pod 期間の制限
OpenShift Container Platform は 1 回実行 (run-once) Pod を使用して Pod のデプロイやビルドの実行などのタスクを実行します。1 回実行 (run-once) Pod は、RestartPolicy
が Never
または OnFailure
の Pod です。
クラスター管理者は RunOnceDuration の受付制御プラグインを使用し、1 回実行 (run-once) Pod の有効期間の制限を強制的に実行できます。期限が切れると、クラスターはそれらの Pod をアクティブに終了しようとします。このような制限を設ける主な理由は、ビルドなどのタスクが長い時間にわたって実行されることを防ぐことにあります。
7.3.1. RunOnceDuration プラグインの設定
このプラグインの設定には、1 回実行 (run-once) Pod のデフォルト有効期限を含める必要があります。この期限はグローバルに実施されますが、プロジェクトごとに置き換えられることができます。
admissionConfig:
pluginConfig:
RunOnceDuration:
configuration:
apiVersion: v1
kind: RunOnceDurationConfig
activeDeadlineSecondsOverride: 3600 1
....
- 1
- 1 回実行 (run-once) Pod のグローバルのデフォルト値 (秒単位) を指定します。
7.3.2. プロジェクト別のカスタム期間の指定
1 回実行 (run-once) Pod のグローバルな最長期間を設定することに加え、管理者はアノテーション (openshift.io/active-deadline-seconds-override
) を特定プロジェクトに追加し、グローバルのデフォルト値を上書きすることができます。
新規プロジェクトの場合、プロジェクト仕様の .yaml ファイルにアノテーションを定義します。
apiVersion: v1 kind: Project metadata: annotations: openshift.io/active-deadline-seconds-override: "1000" 1 name: myproject
- 1
- 1 回実行 (run-once) Pod のデフォルト有効期限 (秒単位) を 1000 秒に上書きします。上書きに使用する値は、文字列形式で指定される必要があります。
既存プロジェクトの場合、以下を実行します。
oc edit
を実行し、openshift.io/active-deadline-seconds-override: 1000
アノテーションをエディターで追加します。$ oc edit namespace <project-name>
または
oc patch
コマンドを使用します。$ oc patch namespace <project_name> -p '{"metadata":{"annotations":{"openshift.io/active-deadline-seconds-override":"1000"}}}'
7.3.2.1. Egress ルーター Pod のデプロイ
例7.1 Egress ルーターの Pod 定義の例
apiVersion: v1 kind: Pod metadata: name: egress-1 labels: name: egress-1 annotations: pod.network.openshift.io/assign-macvlan: "true" spec: containers: - name: egress-router image: openshift3/ose-egress-router securityContext: privileged: true env: - name: EGRESS_SOURCE 1 value: 192.168.12.99 - name: EGRESS_GATEWAY 2 value: 192.168.12.1 - name: EGRESS_DESTINATION 3 value: 203.0.113.25 nodeSelector: site: springfield-1 4
pod.network.openshift.io/assign-macvlan annotation
はプライマリーネットワークインターフェイスに Macvlan ネットワークインターフェイスを作成してから、それを Pod のネットワーク namespace に移行し、egress-router コンテナーを起動します。
"true"
の周りの引用符をそのまま残します。これらを省略するとエラーが生じます。
Pod には openshift3/ose-egress-router イメージを使用する単一コンテナーが含まれ、そのコンテナーは特権モードで実行されるので、Macvlan インターフェイスを設定したり、iptables
ルールをセットアップしたりできます。
環境変数は egress-router イメージに対し、使用するアドレスを指示します。 これは、EGRESS_SOURCE
を IP アドレスとして、また EGRESS_GATEWAY
をゲートウェイとして使用するよう Macvlan を設定します。
NAT ルールが設定され、Pod のクラスター IP アドレスの TCP または UDP ポートへの接続が EGRESS_DESTINATION
の同じポートにリダイレクトされるようにします。
クラスター内の一部のノードのみが指定されたソース IP アドレスを要求でき、指定されたゲートウェイを使用できる場合、受け入れ可能なノードを示す nodeName
または nodeSelector
を指定することができます。
7.3.2.2. Egress ルーターサービスのデプロイ
通常は、egress ルーターを参照するサービスを作成する必要があります (ただし、これは必ずしも必須ではありません)。
apiVersion: v1 kind: Service metadata: name: egress-1 spec: ports: - name: http port: 80 - name: https port: 443 type: ClusterIP selector: name: egress-1
Pod がこのサービスに接続できるようになります。これらの接続は、予約された egress IP アドレスを使用して外部サーバーの対応するポートにリダイレクトされます。
7.3.3. Egress ファイアウォールでの Pod アクセスの制限
OpenShift Container Platform クラスター管理者は egress ポリシーを使用して、一部またはすべての Pod がクラスターからアクセスできる外部アドレスを制限できます。 これにより、以下が可能になります。
Pod の対話を内部ホストに制限し、パブリックインターネットへの接続を開始できないようにする。
または
Pod の対話をパブリックインターネットに制限し、(クラスター外の) 内部ホストへの接続を開始できないようにする。
または
- Pod が接続する理由のない指定された内部サブネット/ホストに到達できないようにする。
プロジェクトは複数の異なる egress ポリシーで設定でき、たとえば指定された IP 範囲への <project A>
のアクセスを許可する一方で、同じアクセスを <project B>
に対して拒否することができます。
egress ポリシーで Pod のアクセスを制限するには、ovs-multitenant プラグイン を有効にする必要があります。
プロジェクト管理者は、EgressNetworkPolicy
オブジェクトを作成することも、プロジェクトで作成するオブジェクトを編集することもできません。また、EgressNetworkPolicy
の作成に関連して他のいくつかの制限があります。
-
デフォルト
プロジェクト (およびoc adm pod-network make-projects-global
でグローバルにされたその他のプロジェクト) には egress ポリシーを設定することができません。 -
(
oc adm pod-network join-projects
を使用して) 2 つのプロジェクトをマージする場合、マージしたプロジェクトのいずれでも egress ポリシーを使用することはできません。 - いずれのプロジェクトも複数の egress ポリシーオブジェクトを持つことができません。
上記の制限のいずれかに違反すると、プロジェクトの egress ポリシーに障害が発生し、すべての外部ネットワークトラフィックがドロップされる可能性があります。
7.3.3.1. Pod アクセス制限の設定
Pod アクセス制限を設定するには、oc
コマンドまたは REST API を使用する必要があります。oc [create|replace|delete]
を使用すると、EgressNetworkPolicy
オブジェクトを操作できます。api/swagger-spec/oapi-v1.json ファイルには、オブジェクトを実際に機能させる方法についての API レベルの詳細情報が含まれます。
Pod のアクセス制限を設定するには、以下を実行します。
- 対象とするプロジェクトに移動します。
Pod の制限ポリシーの JSON ファイルを作成します。
# oc create -f <policy>.json
ポリシーの詳細情報を使って JSON ファイルを設定します。以下に例を示します。
{ "kind": "EgressNetworkPolicy", "apiVersion": "v1", "metadata": { "name": "default" }, "spec": { "egress": [ { "type": "Allow", "to": { "cidrSelector": "1.2.3.0/24" } }, { "type": "Allow", "to": { "dnsName": "www.foo.com" } }, { "type": "Deny", "to": { "cidrSelector": "0.0.0.0/0" } } ] } }
上記のサンプルがプロジェクトに追加されると、IP 範囲
1.2.3.0/24
およびドメイン名www.foo.com
へのトラフィックが許可されますが、その他のすべての外部 IP アドレスへのアクセスは拒否されます。(このポリシーは外部トラフィックにのみ適用されるため、その他すべての Pod へのトラフィックは影響を受けません。)EgressNetworkPolicy
のルールは順番にチェックされ、一致する最初のルールが実施されます。上記の例の 3 つの例を逆順に定義した場合、0.0.0.0/0
ルールが最初にチェックされ、すべてのトラフィックに一致し、それらすべてを拒否するため、1.2.3.0/24
およびwww.foo.com
へのトラフィックは許可されません。ドメイン名の更新は 30 秒以内に反映されます。上記の例で
www.foo.com
は10.11.12.13
に解決されますが、20.21.22.23
に変更されたとします。OpenShift Container Platform では最長 30 秒後にこれらの DNS 更新に対応します。
7.4. Pod で利用可能な帯域幅の制限
QoS (Quality-of-Service) トラフィックシェーピングを Pod に適用し、その利用可能な帯域幅を効果的に制限することができます。(Pod からの) Egress トラフィックは、設定したレートを超えるパケットを単純にドロップするポリシングによって処理されます。(Pod への) Ingress トラフィックは、データを効果的に処理できるようシェーピングでパケットをキューに入れて処理されます。Pod に設定する制限は、他の Pod の帯域幅には影響を与えません。
Pod の帯域幅を制限するには、以下を実行します。
オブジェクト定義 JSON ファイルを作成し、
kubernetes.io/ingress-bandwidth
およびkubernetes.io/egress-bandwidth
アノテーションを使用してデータトラフィックの速度を指定します。たとえば、 Pod の egress および ingress の両方の帯域幅を 10M/s に制限するには、以下を実行します。制限が設定された Pod オブジェクト定義
{ "kind": "Pod", "spec": { "containers": [ { "image": "openshift/hello-openshift", "name": "hello-openshift" } ] }, "apiVersion": "v1", "metadata": { "name": "iperf-slow", "annotations": { "kubernetes.io/ingress-bandwidth": "10M", "kubernetes.io/egress-bandwidth": "10M" } } }
オブジェクト定義を使用して Pod を作成します。
$ oc create -f <file_or_dir_path>
7.5. Pod の Disruption Budget (停止状態の予算) の設定
Pod の Disruption Budget (停止状態の予算) は、 Kubernetes API の一部であり、他の オブジェクトタイプ のように oc
コマンドで管理できます。この設定により、メンテナーンスのためのノードのドレイン (解放) などの操作時に Pod への安全面の各種の制約を指定できます。
PodDisruptionBudget
は、同時に起動している必要のあるレプリカの最小数またはパーセンテージを指定する API オブジェクトです。これらをプロジェクトに設定することは、ノードのメンテナーンス (クラスターのスケールダウンまたはクラスターのアップグレードなどの実行) 時に役立ち、この設定は (ノードの障害時ではなく) 自発的なエビクションの場合にのみ許可されます。
PodDisruptionBudget
オブジェクトの設定は、以下の主要な部分で設定されています。
- 一連の Pod に対するラベルのクエリー機能であるラベルセレクター。
- 同期に利用可能にする必要のある Pod の最小数を指定する可用性レベル。
以下は、PodDisruptionBudget
リソースのサンプルです。
apiVersion: policy/v1beta1 1 kind: PodDisruptionBudget metadata: name: my-pdb spec: selector: 2 matchLabels: foo: bar minAvailable: 2 3
上記のオブジェクト定義で YAML ファイルを作成した場合、これを以下のようにプロジェクトに追加することができます。
$ oc create -f </path/to/file> -n <project_name>
以下を実行して、Pod の Disruption Budget をすべてのプロジェクトで確認することができます。
$ oc get poddisruptionbudget --all-namespaces NAMESPACE NAME MIN-AVAILABLE SELECTOR another-project another-pdb 4 bar=foo test-project my-pdb 2 foo=bar
PodDisruptionBudget
は、最低でも minAvailable
Pod がシステムで実行されている場合は正常であるとみなされます。この制限を超えるすべての Pod は エビクション の対象となります。
Pod の優先順位およびプリエンプション の設定に基づいて、優先順位の低い Pod は Pod の Disruption Budget (停止状態の予算) の要件を無視して削除される可能性があります。
7.6. Critical Pod の設定
DNS など、クラスターの完全な機能に欠かせないコアコンポーネントであるものの、マスターではなく通常のクラスターノードで実行されるコアコンポーネントが多数あります。クラスターは重要なアドオンがエビクトされると正常な機能を停止する可能性があります。scheduler.alpha.kubernetes.io/critical-pod
アノテーションを Pod 仕様に追加し、descheduler がこれらの Pod を削除できないようにすることで、Pod を Critical Pod にすることができます。
spec: template: metadata: name: critical-pod annotations: scheduler.alpha.kubernetes.io/critical-pod: "true"
第8章 ネットワークの管理
8.1. 概要
このトピックでは、プロジェクトの分離および発信トラフィックの制御を含む、全般的な クラスターネットワーク の管理について説明します。
Pod ごとの帯域幅の制限などの Pod レベルのネットワーク機能については、Pod の管理 で説明されています。
8.2. Pod ネットワークの管理
クラスターが ovs-multitenant SDN プラグイン を使用するように設定されている場合、管理者 CLI を使用してプロジェクトの別個の Pod オーバーレイネットワークを管理することができます。必要な場合は、プラグイン設定手順について Configuring the SDN セクションを参照してください。
8.2.1. プロジェクトネットワークへの参加
プロジェクトを既存のプロジェクトネットワークに参加させるには、以下を実行します。
$ oc adm pod-network join-projects --to=<project1> <project2> <project3>
上記の例で、<project2>
および <project3>
のすべての Pod およびサービスから、<project1>
のすべての Pod およびサービスへのアクセスが可能となり、その逆の場合も可能になります。サービスは、IP または完全修飾 DNS 名 (<service>.<pod_namespace>.svc.cluster.local
) のいずれかでアクセスできます。たとえば、プロジェクト myproject
の db
という名前のサービスにアクセスするには、db.myproject.svc.cluster.local
を使用します。
または、特定のプロジェクト名を指定する代わりに --selector=<project_selector>
オプションを使用することもできます。
組み合わせたネットワークを確認するには、以下を実行します。
$ oc get netnamespaces
次に NETID 列を確認します。同じ Pod ネットワークのプロジェクトには同じ NetID があります。
8.3. プロジェクトネットワークの分離
プロジェクトネットワークをクラスターから分離したり、その逆を実行するには、以下を実行します。
$ oc adm pod-network isolate-projects <project1> <project2>
上記の例では、<project1>
および <project2>
のすべての Pod およびサービスは、クラスター内のグローバル以外のプロジェクトの Pod およびサービスに アクセスできず、その逆も実行できません。
または、特定のプロジェクト名を指定する代わりに --selector=<project_selector>
オプションを使用することもできます。
8.3.1. プロジェクトネットワークのグローバル化
プロジェクトからクラスター内のすべての Pod およびサービスにアクセスできるようにするか、その逆を可能にするには、以下を実行します。
$ oc adm pod-network make-projects-global <project1> <project2>
上記の例では、<project1>
および <project2>
のすべての Pod およびサービスは、クラスター内のすべての Pod およびサービスにアクセスできるようになり、その逆の場合も可能になります。
または、特定のプロジェクト名を指定する代わりに --selector=<project_selector>
オプションを使用することもできます。
8.4. ルートおよび Ingress オブジェクトにおけるホスト名の競合防止の無効化
OpenShift Container Platform では、ルートおよび ingress オブジェクトのホスト名の競合防止はデフォルトで有効にされています。これは、cluster-admin ロールのないユーザーは、作成時にのみルーターまたは ingress オブジェクトのホスト名を設定でき、その後は変更できなくなることを意味しています。ただし、ルートおよび ingress オブジェクトのこの制限は、一部またはすべてのユーザーに対して緩和することができます。
OpenShift Container Platform はオブジェクト作成のタイムスタンプを使用して特定のホスト名の最も古いルートや ingress オブジェクトを判別するため、ルートまたは ingress オブジェクトは、古いルートがそのホスト名を変更したり、ingress オブジェクトが導入される場合に新規ルートのホスト名をハイジャックする可能性があります。
OpenShift Container Platform クラスター管理者は、作成後でもルートのホスト名を編集できます。また、特定のユーザーがこれを実行できるようにロールを作成することもできます。
$ oc create clusterrole route-editor --verb=update --resource=routes.route.openshift.io/custom-host
次に、新規ロールをユーザーにバインドできます。
$ oc adm policy add-cluster-role-to-user route-editor user
ingress オブジェクトのホスト名の競合防止を無効にすることもできます。これを実行することで、cluster-admin ロールを持たないユーザーが作成後も ingress オブジェクトのホスト名を編集できるようになります。これは、ingress オブジェクトのホスト名の編集を許可する場合などに Kubernetes の動作に依存する OpenShift Container Platform のインストールで役に立ちます。
以下を
master.yaml
ファイルに追加します。admissionConfig: pluginConfig: openshift.io/IngressAdmission: configuration: apiVersion: v1 allowHostnameChanges: true kind: IngressAdmissionConfig location: ""
変更を有効にするために、マスターサービスを再起動します。
$ master-restart api $ master-restart controllers
8.5. Egress トラフィックの制御
クラスター管理者は、ホストレベルで数多くの静的 IP アドレスを特定ノードに割り当てることができます。アプリケーション開発者がそれぞれのアプリケーションサービスに専用 IP アドレスを必要とする場合、ファイアウォールアクセスを要求するプロセスでこのアドレスを要求することができます。その後、開発者はデプロイメント設定の nodeSelector
を使用して、開発者のプロジェクトから egress ルーターをデプロイし、静的 IP アドレスが事前に割り当てられたホストに Pod が到達することを確認できます。
egress Pod のデプロイメントでは、宛先に到達するために必要なソース IP のいずれか、保護されるサービスの宛先 IP、およびゲートウェイ IP を宣言します。Pod のデプロイ後は、サービスを作成 して、egress ルーター Pod にアクセスし、そのソース IP を企業ファイアウォールに追加できます。その後、開発者はプロジェクトで作成された egress ルーターサービスへのアクセス情報を取得します (例: service.project.cluster.domainname.com
)。
開発者が外部の firewalled サービスにアクセスする必要がある場合、実際の保護されたサービス URL ではなくアプリケーション (例: JDBC 接続情報) で、egress ルーター Pod のサービス (service.project.cluster.domainname.com
) に対して呼び出し実行することができます。
さらに、静的 IP アドレスをプロジェクトに割り当て、指定されたプロジェクトからの発信外部接続すべてに認識可能な起点を設定できます。これは、トラフィックと特定の宛先に送信するために使用されるデフォルトの egress ルーターとは異なります。
詳細は、外部プロジェクトトラフィックの固定 IP の有効化 セクションを参照してください。
OpenShift Container Platform クラスター管理者は、以下を使用して egress トラフィックを制御できます。
- ファイアウォール
- egress ファイアウォールを使用すると、受け入れ可能な発信トラフィックポリシーを実施し、特定のエンドポイントまたは IP 範囲 (サブネット) のみを動的エンドポイント (OpenShift Container Platform 内の Pod) が通信できる受け入れ可能なターゲットとすることができます。
- ルーター
- egress ルーターを使用することで、識別可能なサービスを作成し、トラフィックを特定の宛先に送信できます。これにより、それらの外部の宛先はトラフィックを既知のソースから送られるものとして処理します。 これにより namespace の特定の Pod のみがトラフィックをデータベースにプロキシー送信するサービス (egress ルーター) と通信できるよう外部データベースが保護されるため、セキュリティー対策として役立ちます。
- iptables
- 上記の OpenShift Container Platform 内のソリューションのほかにも、発信トラフィックに適用される iptables ルールを作成することができます。これらのルールは、egress ファイアウォールよりも多くのオプションを許可しますが、特定のプロジェクトに制限することはできません。
8.6. 外部リソースへのアクセスを制限するための Egress ファイアウォールの使用
OpenShift Container Platform クラスター管理者は egress ファイアウォールを使用して、一部またはすべての Pod がクラスター内からアクセスできる外部 IP アドレスを制限できます。egress ファイアウォールポリシーは以下のシナリオをサポートします。
- Pod の接続を内部ホストに制限し、パブリックインターネットへの接続を開始できないようにする。
- Pod の接続をパブリックインターネットに制限し、OpenShift Container Platform クラスター外にある内部ホストへの接続を開始できないようにする。
- Pod が到達不能な状態の指定された内部サブネットまたはホストに到達できないようにする。
egress ポリシーは、IP アドレス範囲を CIDR 形式で指定するか、または DNS 名を指定して設定できます。たとえば、指定された IP 範囲への <project_A>
アクセスを許可しつつ、<project_B>
への同じアクセスを拒否することができます。または、アプリケーション開発者が (Python) pip mirror からの更新を制限したり、更新を承認されたソースからの更新のみに強制的に制限したりすることができます。
Pod アクセスを egress ポリシーで制限するには、ovs-multitenant または ovs-networkpolicy プラグインを有効にする 必要があります。
ovs-multitenant プラグインを使用している場合、egress ポリシーはプロジェクトごとに 1 つのポリシーとのみ互換性を持ち、グローバルプロジェクトなどのネットワークを共有するプロジェクトでは機能しません。
プロジェクト管理者は、EgressNetworkPolicy
オブジェクトを作成することも、プロジェクトで作成するオブジェクトを編集することもできません。また、EgressNetworkPolicy
の作成に関連して他のいくつかの制限があります。
-
デフォルト
プロジェクト (およびoc adm pod-network make-projects-global
でグローバルにされたその他のプロジェクト) には egress ポリシーを設定することができません。 -
(
oc adm pod-network join-projects
を使用して) 2 つのプロジェクトをマージする場合、マージしたプロジェクトのいずれでも egress ポリシーを使用することはできません。 - いずれのプロジェクトも複数の egress ポリシーオブジェクトを持つことができません。
上記の制限のいずれかに違反すると、プロジェクトの egress ポリシーに障害が発生し、すべての外部ネットワークトラフィックがドロップされる可能性があります。
oc
コマンドまたは REST API を使用して egress ポリシーを設定します。oc [create|replace|delete]
を使用すると、EgressNetworkPolicy
オブジェクトを操作できます。api/swagger-spec/oapi-v1.json ファイルには、オブジェクトを実際に機能させる方法についての API レベルの詳細情報が含まれます。
egress ポリシーを設定するには、以下を実行します。
- 対象とするプロジェクトに移動します。
以下の例のように、使用する必要のあるポリシー設定で JSON ファイルを作成します。
{ "kind": "EgressNetworkPolicy", "apiVersion": "v1", "metadata": { "name": "default" }, "spec": { "egress": [ { "type": "Allow", "to": { "cidrSelector": "1.2.3.0/24" } }, { "type": "Allow", "to": { "dnsName": "www.foo.com" } }, { "type": "Deny", "to": { "cidrSelector": "0.0.0.0/0" } } ] } }
上記のサンプルがプロジェクトに追加されると、IP 範囲
1.2.3.0/24
およびドメイン名www.foo.com
へのトラフィックが許可されますが、その他のすべての外部 IP アドレスへのアクセスは拒否されます。このポリシーは外部トラフィックにのみ適用されるため、その他すべての Pod へのトラフィックは影響を受けません。EgressNetworkPolicy
のルールは順番にチェックされ、一致する最初のルールが実施されます。上記の例の 3 つの例を逆順に定義した場合、0.0.0.0/0
ルールが最初にチェックされ、すべてのトラフィックに一致し、それらすべてを拒否するため、1.2.3.0/24
およびwww.foo.com
へのトラフィックは許可されません。ドメイン名の更新は、ローカルの非権威サーバーのドメインの TTL (time to live) 値に基づいてポーリングされます。Pod は必要な場合には、同じローカルのネームサーバーのドメインを解決する必要もあります。そうしないと、egress ネットワークポリシーコントローラーと Pod で認識されるドメインの IP アドレスが異なり、egress ネットワークが予想通りに実施されない場合があります。egress ネットワークポリシーコントローラーおよび Pod は同じローカルネームサーバーを非同期にポーリングするため、Pod が egress コントローラーの前に更新された IP を取得するという競合状態が発生する可能性があります。この現時点の制限により、
EgressNetworkPolicy
のドメイン名の使用は、IP アドレスの変更が頻繁に生じないドメインの場合にのみ推奨されます。注記egress ファイアウォールは、DNS 解決用に Pod が置かれるノードの外部インターフェイスに Pod が常にアクセスできるようにします。DNS 解決がローカルノード上のいずれかによって処理されない場合は、Pod でドメイン名を使用している場合には DNS サーバーの IP アドレスへのアクセスを許可する egress ファイアウォールを追加する必要があります。
JSON ファイルを使用して EgressNetworkPolicy オブジェクトを作成します。
$ oc create -f <policy>.json
ルート を作成してサービスを公開すると、EgressNetworkPolicy
は無視されます。Egress ネットワークポリシーサービスのエンドポイントのフィルターは、ノード kubeproxy
で実行されます。ルーターが使用される場合は、kubeproxy
はバイパスされ、egress ネットワークポリシーの施行は適用されません。管理者は、ルートを作成するためのアクセスを制限してこのバイパスを防ぐことができます。
8.6.1. 外部リソースから Pod トラフィックを認識可能にするための Egress ルーターの使用
OpenShift Container Platform egress ルーターは、他の用途で使用されていないプライベートソース IP アドレスを使用して、指定されたリモートサーバーにトラフィックをリダイレクトするサービスを実行します。このサービスにより、Pod はホワイトリスト IP アドレスからのアクセスのみを許可するように設定されたサーバーと通信できるようになります。
egress ルーターはすべての発信接続のために使用されることが意図されていません。多数の egress ルーターを作成することで、ネットワークハードウェアの制限を引き上げる可能性があります。たとえば、すべてのプロジェクトまたはアプリケーションに egress ルーターを作成すると、ソフトウェアの MAC アドレスのフィルターにフォールバックする前にネットワークインターフェイスが処理できるローカル MAC アドレス数の上限を超えてしまう可能性があります。
現時点で、egress ルーターには Amazon AWS, Azure Cloud またはレイヤー 2 操作をサポートしないその他のクラウドプラットフォームとの互換性がありません。 それらに macvlan トラフィックとの互換性がないためです。
デプロイメントに関する考慮事項
Egress ルーターは 2 つ目の IP アドレスおよび MAC アドレスをノードのプライマリーネットワークインターフェイスに追加します。OpenShift Container Platform をベアメタルで実行していない場合は、ハイパーバイザーまたはクラウドプロバイダーが追加のアドレスを許可するように設定する必要があります。
- Red Hat OpenStack Platform
OpenShift Container Platform を Red Hat OpenStack Platform にデプロイしている場合、OpenStack 環境で IP および MAC アドレスのホワイトリストを作成する必要があります。作成しないと、通信は失敗します。
neutron port-update $neutron_port_uuid \ --allowed_address_pairs list=true \ type=dict mac_address=<mac_address>,ip_address=<ip_address>
- Red Hat Enterprise Virtualization
-
Red Hat Enterprise Virtualization を使用している場合は、
EnableMACAntiSpoofingFilterRules
をfalse
に設定する必要が あります。 - VMware vSphere
- VMware vSphere を使用している場合は、vSphere 標準スイッチのセキュリティー保護についての VMWare ドキュメント を参照してください。vSphere Web クライアントからホストの仮想スイッチを選択して、VMWare vSphere デフォルト設定を表示し、変更します。
とくに、以下が有効にされていることを確認します。
Egress ルーターモード
egress ルーターは、リダイレクトモード と HTTP プロキシーモード および DNS プロキシーモード の 3 つの異なるモードで実行できます。リダイレクトモードは、HTTP および HTTPS 以外のすべてのサービスで機能します。HTTP および HTTPS サービスの場合は、HTTP プロキシーモードを使用します。IP アドレスまたはドメイン名を持つ TCP ベースのサービスの場合は、DNS プロキシーモードを使用します。
8.6.1.1. リダイレクトモードでの Egress ルーター Pod のデプロイ
リダイレクトモードでは、egress ルーターは、トラフィックを独自の IP アドレスから 1 つ以上の宛先 IP アドレスにリダイレクトするために iptables ルールをセットアップします。予約されたソース IP アドレスを使用する必要のあるクライアント Pod は、宛先 IP に直接接続するのでなく、egress ルーターに接続するように変更される必要があります。
以下を使用して Pod 設定を作成します。
apiVersion: v1 kind: Pod metadata: name: egress-1 labels: name: egress-1 annotations: pod.network.openshift.io/assign-macvlan: "true" 1 spec: initContainers: - name: egress-router image: registry.redhat.io/openshift3/ose-egress-router securityContext: privileged: true env: - name: EGRESS_SOURCE 2 value: 192.168.12.99/24 - name: EGRESS_GATEWAY 3 value: 192.168.12.1 - name: EGRESS_DESTINATION 4 value: 203.0.113.25 - name: EGRESS_ROUTER_MODE 5 value: init containers: - name: egress-router-wait image: registry.redhat.io/openshift3/ose-pod nodeSelector: site: springfield-1 6
- 1
- プライマリーネットワークインターフェイスで Macvlan ネットワークインターフェイスを作成し、これを Pod のネットワークプロジェクトに移行してから egress-router コンテナーを起動します。
"true"
の周りの引用符をそのまま残します。これらを省略すると、エラーが発生します。プライマリーネットワークインターフェイス以外のネットワークインターフェイスで Macvlan インターフェイスを作成するには、アノテーションの値を該当インターフェイスの名前に設定します。たとえば、eth1
を使用します。 - 2
- ノードが置かれており、クラスター管理者がこの Pod で使用するために予約している物理ネットワークの IP アドレスです。オプションとして、サブネットの長さ
/24
接尾辞を組み込み、ローカルサブネットへの適切なルートがセットアップされるようにできます。サブネットの長さを指定しない場合、egress ルーターはEGRESS_GATEWAY
変数で指定されたホストにのみアクセスでき、サブネットの他のホストにはアクセスできません。 - 3
- ノードで使用されるデフォルトゲートウェイと同じ値です。
- 4
- トラフィックの送信先となる外部サーバー。この例では、Pod の接続は 203.0.113.25 にリダイレクトされます。 ソース IP アドレスは 192.168.12.99 です。
- 5
- これは egress ルーターイメージに対して、これが init コンテナーとしてデプロイされていることを示しています。以前のバージョンの OpenShift Container Platform (および egress ルーターイメージ) はこのモードをサポートしておらず、通常のコンテナーとして実行される必要がありました。
- 6
- Pod はラベル
site=springfield-1
の設定されたノードにのみデプロイされます。
上記の定義を使用して Pod を作成します。
$ oc create -f <pod_name>.json
Pod が作成されているかどうかを確認するには、以下を実行します。
$ oc get pod <pod_name>
egresss ルーターを参照するサービスを作成し、他の Pod が Pod の IP アドレスを見つけられるようにします。
apiVersion: v1 kind: Service metadata: name: egress-1 spec: ports: - name: http port: 80 - name: https port: 443 type: ClusterIP selector: name: egress-1
Pod がこのサービスに接続できるようになります。これらの接続は、予約された egress IP アドレスを使用して外部サーバーの対応するポートにリダイレクトされます。
egress ルーターのセットアップは、openshift3/ose-egress-router イメージで作成される init コンテナーで実行され、このコンテナーは Macvlan インターフェイスを設定し、iptables
ルールをセットアップできるように特権モード実行されます。iptables
ルールのセットアップ終了後に、これは終了し、openshift3/ose-pod コンテナーが Pod が強制終了されるまで (特定のタスクを実行しない) 実行状態になります。
環境変数は egress-router イメージに対し、使用するアドレスを指示します。 これは、EGRESS_SOURCE
を IP アドレスとして、また EGRESS_GATEWAY
をゲートウェイとして使用するよう Macvlan を設定します。
NAT ルールが設定され、Pod のクラスター IP アドレスの TCP または UDP ポートへの接続が EGRESS_DESTINATION
の同じポートにリダイレクトされるようにします。
クラスター内の一部のノードのみが指定されたソース IP アドレスを要求でき、指定されたゲートウェイを使用できる場合、受け入れ可能なノードを示す nodeName
または nodeSelector
を指定することができます。
8.6.1.2. 複数の宛先へのリダイレクト
前の例では、任意のポートでの egress Pod (またはその対応するサービス) への接続は単一の宛先 IP にリダイレクトされます。ポートに応じて異なる宛先 IP を設定することもできます。
apiVersion: v1 kind: Pod metadata: name: egress-multi labels: name: egress-multi annotations: pod.network.openshift.io/assign-macvlan: "true" spec: initContainers: - name: egress-router image: registry.redhat.io/openshift3/ose-egress-router securityContext: privileged: true env: - name: EGRESS_SOURCE 1 value: 192.168.12.99/24 - name: EGRESS_GATEWAY value: 192.168.12.1 - name: EGRESS_DESTINATION 2 value: | 80 tcp 203.0.113.25 8080 tcp 203.0.113.26 80 8443 tcp 203.0.113.26 443 203.0.113.27 - name: EGRESS_ROUTER_MODE value: init containers: - name: egress-router-wait image: registry.redhat.io/openshift3/ose-pod
EGRESS_DESTINATION
の各行は、以下の 3 つのタイプのいずれかになります。
-
<port> <protocol> <IP_address>
: これは、指定される<port>
への着信接続が指定される<IP_address>
の同じポートにリダイレクトされる必要があることを示しています。<protocol>
はtcp
またはudp
のいずれかになります。上記の例では、最初の行がローカルポート 80 から 203.0.113.25 のポート 80 にトラフィックをリダイレクトしています。 -
<port> <protocol> <IP_address> <remote_port>
: 接続が<IP_address>
の別の<remote_port>
にリダイレクトされるのを除き、上記と同じになります。この例では、2 番目と 3 番目の行ではローカルポート 8080 および 8443 を 203.0.113.26 のリモートポート 80 および 443 にリダイレクトしています。 -
<fallback_IP_address>
:EGRESS_DESTINATION
の最後の行が単一 IP アドレスである場合、それ以外のポートの接続はその IP アドレス (上記の例では 203.0.113.27) の対応するポートにリダイレクトされます。フォールバック IP アドレスがない場合、他のポートでの接続は単純に拒否されます。 )
8.6.1.3. ConfigMap の使用による EGRESS_DESTINATION の指定
宛先マッピングのセットのサイズが大きいか、またはこれが頻繁に変更される場合、ConfigMap を使用して一覧を外部で維持し、egress ルーター Pod がそこから一覧を読み取れるようにすることができます。これには、プロジェクト管理者が ConfigMap を編集できるという利点がありますが、これには特権付きコンテナーが含まれるため、管理者は Pod 定義を直接編集することはできません。
EGRESS_DESTINATION
データを含むファイルを作成します。$ cat my-egress-destination.txt # Egress routes for Project "Test", version 3 80 tcp 203.0.113.25 8080 tcp 203.0.113.26 80 8443 tcp 203.0.113.26 443 # Fallback 203.0.113.27
空の行とコメントをこのファイルに追加できることに注意してください。
このファイルから ConfigMap オブジェクトを作成します。
$ oc delete configmap egress-routes --ignore-not-found $ oc create configmap egress-routes \ --from-file=destination=my-egress-destination.txt
ここで、
egress-routes
は作成される ConfigMap オブジェクトの名前で、my-egress-destination.txt
はデータの読み取り元のファイルの名前です。前述のように egress ルーター Pod 定義を作成しますが、ConfigMap を環境セクションの
EGRESS_DESTINATION
に指定します。... env: - name: EGRESS_SOURCE 1 value: 192.168.12.99/24 - name: EGRESS_GATEWAY value: 192.168.12.1 - name: EGRESS_DESTINATION valueFrom: configMapKeyRef: name: egress-routes key: destination - name: EGRESS_ROUTER_MODE value: init ...
- 1
- ノードが置かれており、クラスター管理者がこの Pod で使用するために予約している物理ネットワークの IP アドレスです。オプションとして、サブネットの長さ
/24
接尾辞を組み込み、ローカルサブネットへの適切なルートがセットアップされるようにできます。サブネットの長さを指定しない場合、egress ルーターはEGRESS_GATEWAY
変数で指定されたホストにのみアクセスでき、サブネットの他のホストにはアクセスできません。
egress ルーターは、ConfigMap が変更されても自動的に更新されません。更新を取得するには Pod を再起動します。
8.6.1.4. Egress ルーター HTTP プロキシー Pod のデプロイ
HTTP プロキシーモードでは、egress ルーターはポート 8080
で HTTP プロキシーとして実行されます。これは、HTTP または HTTPS ベースのサービスと通信するクライアントの場合にのみ機能しますが、通常それらを機能させるのにクライアント Pod への多くの変更は不要です。環境変数を設定することで、プログラムは HTTP プロキシーを使用するように指示されます。
例として以下を使用して Pod を作成します。
apiVersion: v1 kind: Pod metadata: name: egress-http-proxy labels: name: egress-http-proxy annotations: pod.network.openshift.io/assign-macvlan: "true" 1 spec: initContainers: - name: egress-router-setup image: registry.redhat.io/openshift3/ose-egress-router securityContext: privileged: true env: - name: EGRESS_SOURCE 2 value: 192.168.12.99/24 - name: EGRESS_GATEWAY 3 value: 192.168.12.1 - name: EGRESS_ROUTER_MODE 4 value: http-proxy containers: - name: egress-router-proxy image: registry.redhat.io/openshift3/ose-egress-http-proxy env: - name: EGRESS_HTTP_PROXY_DESTINATION 5 value: | !*.example.com !192.168.1.0/24 *
- 1
- プライマリーネットワークインターフェイスで Macvlan ネットワークインターフェイスを作成してから、これを Pod のネットワークプロジェクトに移行し、egress-router コンテナーを起動します。
"true"
の周りの引用符をそのまま残します。これらを省略すると、エラーが発生します。 - 2
- ノードが置かれており、クラスター管理者がこの Pod で使用するために予約している物理ネットワークの IP アドレスです。オプションとして、サブネットの長さ
/24
接尾辞を組み込み、ローカルサブネットへの適切なルートがセットアップされるようにできます。サブネットの長さを指定しない場合、egress ルーターはEGRESS_GATEWAY
変数で指定されたホストにのみアクセスでき、サブネットの他のホストにはアクセスできません。 - 3
- ノード自体で使用されるデフォルトゲートウェイと同じ値。
- 4
- これは egress ルーターイメージに対し、これが HTTP プロキシーの一部としてデプロイされているため、iptables のリダイレクトルールを設定できないことを示します。
- 5
- プロキシーの設定方法を指定する文字列または YAML の複数行文字列です。これは、init コンテナーの他の環境変数ではなく、HTTP プロキシーコンテナーの環境変数として指定されることに注意してください。
EGRESS_HTTP_PROXY_DESTINATION
値に以下のいずれかを指定できます。また、*
を使用することができます。これはすべてのリモート宛先への接続を許可することを意味します。 設定の各行には、許可または拒否する接続の 1 つのグループを指定します。-
IP アドレス (例:
192.168.1.1
) は該当する IP アドレスへの接続を許可します。 -
CIDR 範囲 (例:
192.168.1.0/24
) は CIDR 範囲への接続を許可します。 -
ホスト名 (例:
www.example.com
) は該当ホストへのプロキシーを許可します。 -
*.
が先に付けられるドメイン名 (例:*.example.com
) は該当ドメインおよびそのサブドメインのすべてへのプロキシーを許可します。 -
上記のいずれかに
!
を付けると、接続は許可されるのではなく、拒否されます。 -
最後の行が
*
の場合、拒否されていないすべてのものが許可されます。または、許可されていないすべてのものが拒否されます。
egresss ルーターを参照するサービスを作成し、他の Pod が Pod の IP アドレスを見つけられるようにします。
apiVersion: v1 kind: Service metadata: name: egress-1 spec: ports: - name: http-proxy port: 8080 1 type: ClusterIP selector: name: egress-1
- 1
http
ポートが常に8080
に設定されていることを確認します。
http_proxy
またはhttps_proxy
変数を設定して、クライアント Pod (egress プロキシー Pod ではない) を HTTP プロキシーを使用するように設定します。... env: - name: http_proxy value: http://egress-1:8080/ 1 - name: https_proxy value: http://egress-1:8080/ ...
- 1
- 手順 2 で作成されたサービス。
注記すべてのセットアップに
http_proxy
およびhttps_proxy
環境変数が必要になる訳ではありません。上記を実行しても作業用セットアップが作成されない場合は、Pod で実行しているツールまたはソフトウェアについてのドキュメントを参照してください。
リダイレクトする egress ルーターの上記の例 と同様に、ConfigMap を使用して EGRESS_HTTP_PROXY_DESTINATION
を指定することもできます。
8.6.1.5. Egress ルーター DNS プロキシー Pod のデプロイ
DNS プロキシーモードでは、egress ルーターは、トラフィックを独自の IP アドレスから 1 つ以上の宛先 IP アドレスに送信する TCP ベースのサービスの DNS プロキシーとして実行されます。予約されたソース IP アドレスを使用する必要のあるクライアント Pod は、宛先 IP に直接接続するのでなく、egress ルーターに接続するように変更される必要があります。これにより、外部の宛先でトラフィックが既知のソースから送信されているかのように処理されます。
例として以下を使用して Pod を作成します。
apiVersion: v1 kind: Pod metadata: name: egress-dns-proxy labels: name: egress-dns-proxy annotations: pod.network.openshift.io/assign-macvlan: "true" 1 spec: initContainers: - name: egress-router-setup image: registry.redhat.io/openshift3/ose-egress-router securityContext: privileged: true env: - name: EGRESS_SOURCE 2 value: 192.168.12.99/24 - name: EGRESS_GATEWAY 3 value: 192.168.12.1 - name: EGRESS_ROUTER_MODE 4 value: dns-proxy containers: - name: egress-dns-proxy image: registry.redhat.io/openshift3/ose-egress-dns-proxy env: - name: EGRESS_DNS_PROXY_DEBUG 5 value: "1" - name: EGRESS_DNS_PROXY_DESTINATION 6 value: | # Egress routes for Project "Foo", version 5 80 203.0.113.25 100 example.com 8080 203.0.113.26 80 8443 foobar.com 443
- 1
pod.network.openshift.io/assign-macvlan annotation
を使用することで、プライマリーネットワークインターフェイスで Macvlan ネットワークインターフェイスが作成され、これを Pod のネットワーク namespace に移行してから、egress-router-setup コンテナーを起動します。"true"
の周りの引用符をそのまま残します。これらを省略すると、エラーが発生します。- 2
- ノードが置かれており、クラスター管理者がこの Pod で使用するために予約している物理ネットワークの IP アドレスです。オプションとして、サブネットの長さ
/24
接尾辞を組み込み、ローカルサブネットへの適切なルートがセットアップされるようにできます。サブネットの長さを指定しない場合、egress ルーターはEGRESS_GATEWAY
変数で指定されたホストにのみアクセスでき、サブネットの他のホストにはアクセスできません。 - 3
- ノード自体で使用されるデフォルトゲートウェイと同じ値。
- 4
- これは egress ルーターイメージに対し、これが DNS プロキシーの一部としてデプロイされているため、iptables のリダイレクトルールを設定できないことを示します。
- 5
- オプション。この変数を設定すると、DNS プロキシーログ出力が 標準出力 (stdout) で表示されます。
- 6
- ここでは、複数行の文字列に YAML 構文を使用しています。詳細は以下を参照してください。
注記EGRESS_DNS_PROXY_DESTINATION
の各行は、以下の 2 つの方法のいずれかで設定できます。-
<port> <remote_address>
: これは、指定の<port>
への受信接続が指定の<remote_address>
の同じ TCP ポートにプロキシー送信される必要があることを示しています。<remote_address>
は IP アドレスまたは DNS 名を指定できます。DNS 名の場合、DNS 解決は起動時に行われます。上記の例では、最初の行はローカルポート 80 から 203.0.113.25 のポート 80 に TCP トラフィックをプロキシー送信します。2 つ目の行は、TCP トラフィックをローカルポート 100 から example.com のポート 100 にプロキシー送信しています。 -
<port> <remote_address> <remote_port>
: 接続が<remote_address>
の別の<remote_port>
にプロキシー送信されるのを除き、上記と同じになります。この例では、3 番目の行ではローカルポート 8080 を 203.0.113.26 のリモートポート 80 にプロキシー送信し、4 番目の行ではローカルポート 8443 を footbar.com のリモートポートおよび 443 にプロキシー送信しています。
egresss ルーターを参照するサービスを作成し、他の Pod が Pod の IP アドレスを見つけられるようにします。
apiVersion: v1 kind: Service metadata: name: egress-dns-svc spec: ports: - name: con1 protocol: TCP port: 80 targetPort: 80 - name: con2 protocol: TCP port: 100 targetPort: 100 - name: con3 protocol: TCP port: 8080 targetPort: 8080 - name: con4 protocol: TCP port: 8443 targetPort: 8443 type: ClusterIP selector: name: egress-dns-proxy
Pod がこのサービスに接続できるようになります。これらの接続は、予約された egress IP アドレスを使用して外部サーバーの対応するポートにプロキシー送信されます。
リダイレクトする egress ルーターの上記の例 と同様に、ConfigMap を使用して EGRESS_DNS_PROXY_DESTINATION
を指定することもできます。
8.6.1.6. Egress ルーター Pod のフェイルオーバーの有効化
レプリケーションコントローラーを使用し、ダウンタイムを防ぐために egress ルーター Pod の 1 つのコピーを常に確保できるようにします。
以下を使用してレプリケーションコントローラーの設定ファイルを作成します。
apiVersion: v1 kind: ReplicationController metadata: name: egress-demo-controller spec: replicas: 1 1 selector: name: egress-demo template: metadata: name: egress-demo labels: name: egress-demo annotations: pod.network.openshift.io/assign-macvlan: "true" spec: initContainers: - name: egress-demo-init image: registry.redhat.io/openshift3/ose-egress-router env: - name: EGRESS_SOURCE 2 value: 192.168.12.99/24 - name: EGRESS_GATEWAY value: 192.168.12.1 - name: EGRESS_DESTINATION value: 203.0.113.25 - name: EGRESS_ROUTER_MODE value: init securityContext: privileged: true containers: - name: egress-demo-wait image: registry.redhat.io/openshift3/ose-pod nodeSelector: site: springfield-1
- 1
- 特定の
EGRESS_SOURCE
値を使用できる Pod は常に 1 つだけであるため、replicas
が1
に設定されていることを確認します。これは、ルーターの単一コピーのみがラベルsite=springfield-1
が設定されたノードで実行されることを意味します。 - 2
- ノードが置かれており、クラスター管理者がこの Pod で使用するために予約している物理ネットワークの IP アドレスです。オプションとして、サブネットの長さ
/24
接尾辞を組み込み、ローカルサブネットへの適切なルートがセットアップされるようにできます。サブネットの長さを指定しない場合、egress ルーターはEGRESS_GATEWAY
変数で指定されたホストにのみアクセスでき、サブネットの他のホストにはアクセスできません。
定義を使用して Pod を作成します。
$ oc create -f <replication_controller>.json
検証するには、レプリケーションコントローラー Pod が作成されているかどうかを確認します。
$ oc describe rc <replication_controller>
8.6.2. 外部リソースへのアクセスを制限するための iptables ルールの使用
クラスター管理者の中には、EgressNetworkPolicy
のモデルや egress ルーターの対象外の発信トラフィックに対してアクションを実行する必要のある管理者がいる場合があります。この場合には、iptables ルールを直接作成してこれを実行することができます。
たとえば、特定の宛先へのトラフィックをログに記録するルールを作成したり、1 秒ごとに設定される特定数を超える発信接続を許可しないようにしたりできます。
OpenShift Container Platform はカスタム iptables ルールを自動的に追加する方法を提供していませんが、管理者がこのようなルールを手動で追加できる場所を提供します。各ノードは起動時に、filter
テーブルに OPENSHIFT-ADMIN-OUTPUT-RULES
という空のチェーンを作成します (チェーンがすでに存在していないと仮定します)。管理者がこのチェーンに追加するすべてのルールは、Pod からクラスター外にある宛先へのすべてのトラフィックに適用されます (それ以外のトラフィックには適用されません)。
この機能を使用する際には、注意すべきいくつかの点があります。
- 各ノードにルールが作成されていることを確認するのは管理者のタスクになります。 OpenShift Container Platform はこれを自動的に確認する方法は提供しません。
-
ルールは egress ルーターによってクラスターを退出するトラフィックには適用されず、ルールは
EgressNetworkPolicy
ルールが適用された後に実行されます (そのため、EgressNetworkPolicy
で拒否されるトラフィックは表示されません)。 - ノードには外部 IP アドレスと内部 SDN IP アドレスの両方があるため、Pod からノードまたはノードからマスターへの接続の処理は複雑になります。そのため、一部の Pod とノード間/Pod とマスター間のトラフィックはこのチェーンを通過しますが、他の Pod とノード間/Pod とマスター間のトラフィックはこれをバイパスする場合があります。
8.7. 外部プロジェクトトラフィックの静的 IP の有効化
クラスター管理者は特定の静的 IP アドレスをプロジェクトに割り当て、トラフィックが外部から容易に識別できるようにできます。これは、トラフィックと特定の宛先に送信するために使用されるデフォルトの egress ルーターとは異なります。
識別可能な IP トラフィックは起点を可視化することで、クラスターのセキュリティーを強化します。これが有効にされると、指定されたプロジェクトからのすべての発信外部接続は同じ固定ソース IP を共有します。 つまり、すべての外部リソースがこのトラフィックを認識できるようになります。
egress ルーターの場合とは異なり、これは EgressNetworkPolicy
ファイアウォールルールに基づいて実行されます。
クラスターのプロジェクトに静的 IP アドレスを割り当てるには、SDN が ovs-networkpolicy または ovs-multitenant ネットワークプラグインのいずれかを使用する必要があります。
OpenShift SDN をマルチテナントモードで使用する場合、それらに関連付けられたプロジェクトによって別の namespace に参加している namespace と共に egress IP アドレスを使用することはできません。たとえば、project1
および project2
に oc adm pod-network join-projects --to=project1 project2
コマンドを実行して参加している場合、どちらもプロジェクトも egress IP アドレスを使用できません。詳細は、BZ#1645577 を参照してください。
静的ソース IP を有効にするには、以下を実行します。
必要な IP で
NetNamespace
を更新します。$ oc patch netnamespace <project_name> -p '{"egressIPs": ["<IP_address>"]}'
たとえば、
MyProject
プロジェクトを IP アドレス 192.168.1.100 に割り当てるには、以下を実行します。$ oc patch netnamespace MyProject -p '{"egressIPs": ["192.168.1.100"]}'
egressIPs
フィールドは配列です。egressIPs
を異なるノードの 2 つ以上の IP アドレスに設定し、高可用性を確保することができます。複数の egress IP アドレスが設定される場合、Pod は egress の一覧にある最初の IP を使用しますが、IP アドレスをホストするノードが失敗する場合、Pod は短時間の遅延の後に一覧にある次の IP の使用に切り替えます。egress IP を必要なノードホストに手動で割り当てます。ノードホストの
HostSubnet
オブジェクトのegressIPs
フィールドを設定します。そのノードホストに割り当てる必要のある任意の数の IP を含めることができます。$ oc patch hostsubnet <node_name> -p \ '{"egressIPs": ["<IP_address_1>", "<IP_address_2>"]}'
たとえば、
node1
に egress IP 192.168.1.100、192.168.1.101、および 192.168.1.102 が必要な場合は、以下のようになります。$ oc patch hostsubnet node1 -p \ '{"egressIPs": ["192.168.1.100", "192.168.1.101", "192.168.1.102"]}'
重要egress IP はプライマリーネットワークインターフェイスの追加の IP アドレスとして実装され、ノードのプライマリー IP と同じサブネットに置かれる必要があります。さらに、外部 IP は、ifcfg-eth0 などの Linux ネットワーク設定ファイルで設定することはできません。
一部のクラウドまたは仮想マシンソリューションを使用する場合に、プライマリーネットワークインターフェイスで追加の IP アドレスを許可するには追加の設定が必要になる場合があります。
プロジェクトに対して上記が有効にされる場合、そのプロジェクトからのすべての egress トラフィックはその egress IP をホストするノードにルーティングされ、(NAT を使用して) その IP アドレスに接続されます。egressIPs
が NetNamespace
で設定されているものの、その egress IP をホストするノードがない場合、namespace からの egress トラフィックはドロップされます。
8.8. 自動 Egress IP の有効化
外部プロジェクトトラフィックの静的 IP の有効化 の場合のように、クラスター管理者として、egressIPs
パラメーターを NetNamespace
リソースに設定して egress IP アドレスを namespace に割り当てることができます。単一 IP アドレスのみをプロジェクトに関連付けることができます。
OpenShift SDN をマルチテナントモードで使用する場合、それらに関連付けられたプロジェクトによって別の namespace に参加している namespace と共に egress IP アドレスを使用することはできません。たとえば、project1
および project2
に oc adm pod-network join-projects --to=project1 project2
コマンドを実行して参加している場合、どちらもプロジェクトも egress IP アドレスを使用できません。詳細は、BZ#1645577 を参照してください。
完全に自動化された egress IP により、各ノードの HostSubnet
リソースの egressCIDRs
パラメーターを設定し、ホストできる egress IP アドレスの範囲を示唆することができます。egress IP アドレスを要求した namespace はそれらの egress IP アドレスをホストできるノードに一致し、その後に egress IP アドレスはそれらのノードに割り当てられます。
高可用性は自動的に実行されます。egress IP アドレスをホストしているノードが停止し、HostSubnet
リソースの egressCIDR
値をベースとしてそれらの egress IP アドレスをホストできるノードがある場合、egress IP アドレスは新規ノードに移行します。元の egress IP アドレスノードが再びオンラインに戻ると、ノード間で egress IP アドレスのバランスを図るために egress IP アドレスは自動的に移行します。
手動で割り当てられた egress IP アドレスと自動的に割り当てられた egress IP アドレスの両方を同じノードで使用したり、同じ IP アドレス範囲で使用したりすることはできません。
NetNamespace
を egress IP アドレスで更新します。$ oc patch netnamespace <project_name> -p '{"egressIPs": ["<IP_address>"]}'
egressIPs
パラメーターに指定できる IP アドレスは 1 つだけです。複数の IP アドレスの使用はサポートされていません。たとえば、
project1
を IP アドレスの 192.168.1.100 に、project2
を IP アドレスの 192.168.1.101 に割り当てるには、以下を実行します。$ oc patch netnamespace project1 -p '{"egressIPs": ["192.168.1.100"]}' $ oc patch netnamespace project2 -p '{"egressIPs": ["192.168.1.101"]}''
egressCIDRs
フィールドを設定して、egress IP アドレスをホストできるノードを示します。$ oc patch hostsubnet <node_name> -p \ '{"egressCIDRs": ["<IP_address_range_1>", "<IP_address_range_2>"]}'
たとえば、
node1
およびnode2
を、192.168.1.0 から 192.168.1.255 の範囲で egress IP アドレスをホストするように設定するには、以下を実行します。$ oc patch hostsubnet node1 -p '{"egressCIDRs": ["192.168.1.0/24"]}' $ oc patch hostsubnet node2 -p '{"egressCIDRs": ["192.168.1.0/24"]}'
-
OpenShift Container Platform は、バランスを取りながら特定の egress IP アドレスを利用可能なノードに自動的に割り当てます。この場合、egress IP アドレス 192.168.1.100 を
node1
に、egress IP アドレス 192.168.1.101 をnode2
に割り当て、その逆も行います。
8.9. マルチキャストの有効化
現時点で、マルチキャストは低帯域幅の調整またはサービスの検出での使用に最も適しており、高帯域幅のソリューションとしては適していません。
OpenShift Container Platform の Pod 間のマルチキャストトラフィックはデフォルトで無効にされます。ovs-multitenant または ovs-networkpolicy プラグインを使用している場合、アノテーションをプロジェクトの対応する netnamespace
オブジェクトに設定して、プロジェクトごとにマルチキャストを有効にできます。
$ oc annotate netnamespace <namespace> \ netnamespace.network.openshift.io/multicast-enabled=true
アノテーションを削除してマルチキャストを無効にします。
$ oc annotate netnamespace <namespace> \ netnamespace.network.openshift.io/multicast-enabled-
ovs-multitenant プラグインを使用する場合:
- 分離したプロジェクトでは、Pod で送信されるマルチキャストパケットはプロジェクト内の他のすべての Pod に送信されます。
-
ネットワークを結合 している場合、すべてのプロジェクトで有効にされるようにマルチキャストを各プロジェクトの
netnamespace
で有効にする必要があります。結合されたネットワークの Pod で送信されるマルチキャストはすべての結合されたネットワークのすべての Pod に送信されます。 -
マルチキャストを
default
プロジェクトで有効にするには、これをkube-service-catalog
プロジェクトおよび グローバルにされた 他のすべてのプロジェクトで有効にする必要もあります。グローバルプロジェクトの Pod で送信されるマルチキャストパケットはすべてのプロジェクトのすべての Pod にではなく、他のグローバルプロジェクトの Pod に送信されます。同様に、グローバルプロジェクトの Pod はすべてのプロジェクトのすべての Pod からではなく、他のグローバルプロジェクトの Pod から送信されるマルチキャストパケットのみを受信します。
ovs-networkpolicy プラグインを使用する場合:
-
Pod によって送信されるマルチキャストパケットは、
NetworkPolicy
オブジェクトに関係なく、プロジェクトの他のすべての Pod に送信されます。(Pod はユニキャストで通信できない場合でもマルチキャストで通信できます。) -
1 つのプロジェクトの Pod によって送信されるマルチキャストパケットは、
NetworkPolicy
オブジェクトがプロジェクト間の通信を許可する場合であっても、それ以外のプロジェクトの Pod に送信されることはありません。
8.10. NetworkPolicy の有効化
ovs-subnet および ovs-multitenant プラグインにはネットワークの分離についての独自のレガシーモデルがありますが、Kubernetes NetworkPolicy
はサポートしません。ただし、NetworkPolicy
サポートは、ovs-networkpolicy プラグインを使用すると利用できます。
Egress
ポリシータイプ、ipBlock
パラメーター、および podSelector
パラメーターと namespaceSelector
パラメーターを組み合わせる機能は、OpenShift Container Platform では使用できません。
NetworkPolicy
機能はクラスターとの通信に障害を発生させる可能性があるため、これらの機能をデフォルトの OpenShift Container Platform プロジェクトに適用しないでください。
NetworkPolicy
ルールは、ホストネットワーク namespace には適用されません。ホストネットワークが有効にされている Pod は NetworkPolicy
ルールによる影響を受けません。
ovs-networkpolicy プラグインを使用するように設定されている クラスターでは、ネットワークの分離は NetworkPolicy
オブジェクト によって完全に制御されます。デフォルトで、プロジェクトのすべての Pod は他の Pod およびネットワークのエンドポイントからアクセスできます。プロジェクトで 1 つ以上の Pod を分離するには、そのプロジェクトで NetworkPolicy
オブジェクトを作成し、許可する着信接続を指定します。プロジェクト管理者は独自のプロジェクト内で NetworkPolicy
オブジェクトの作成および削除を実行できます。
Pod を参照する NetworkPolicy
オブジェクトを持たない Pod は完全にアクセスできますが、Pod を参照する 1 つ以上の NetworkPolicy
オブジェクトを持つ Pod は分離されます。これらの分離された Pod は 1 つ以上の NetworkPolicy
オブジェクトで許可される接続のみを受け入れます。
複数の異なるシナリオに対応するいくつかの NetworkPolicy
オブジェクト定義のいくつかを見てみましょう。
すべてのトラフィックを拒否
プロジェクトに deny by default (デフォルトで拒否) を実行させるには、すべての Pod に一致するが、トラフィックを一切許可しない
NetworkPolicy
オブジェクトを追加します。kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: deny-by-default spec: podSelector: ingress: []
プロジェクト内の Pod からの接続のみを許可
Pod が同じプロジェクト内の他の Pod からの接続を受け入れるが、他のプロジェクトの Pod からの接続を拒否するように設定するには、以下を実行します。
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: allow-same-namespace spec: podSelector: ingress: - from: - podSelector: {}
Pod ラベルに基づいて HTTP および HTTPS トラフィックのみを許可
特定のラベル (以下の例の
role=frontend
) の付いた Pod への HTTP および HTTPS アクセスのみを有効にするには、以下と同様のNetworkPolicy
オブジェクトを追加します。kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: allow-http-and-https spec: podSelector: matchLabels: role: frontend ingress: - ports: - protocol: TCP port: 80 - protocol: TCP port: 443
NetworkPolicy
オブジェクトは加算されるものです。つまり、複数の NetworkPolicy
オブジェクトを組み合わせて複雑なネットワーク要件を満すことができます。
たとえば、先の例で定義された NetworkPolicy
オブジェクトの場合、同じプロジェト内に allow-same-namespace
と allow-http-and-https
ポリシーの両方を定義することができます。これにより、ラベル role=frontend
の付いた Pod は各ポリシーで許可されるすべての接続を受け入れます。つまり、同じ namespace の Pod からのすべてのポート、および すべての namespace の Pod からのポート 80
および 443
での接続を受け入れます。
8.10.1. NetworkPolicy の効率的な使用
NetworkPolicy
オブジェクトは、namespace 内でラベルで相互に区別される Pod を分離することを許可します。
NetworkPolicy
オブジェクトを単一 namespace 内の多数の個別 Pod に適用することは効率的ではありません。Pod ラベルは IP レベルには存在しないため、NetworkPolicy
オブジェクトは、podSelector
で選択されるすべての Pod 間のすべてのリンクについての別個の OVS フロールールを生成します。
たとえば、spec
podSelector
および ingress
podSelector
within a NetworkPolicy
オブジェクトのそれぞれが 200 Pod に一致する場合、40000 (200*200) OVS フロールールが生成されます。これにより、マシンの速度が低下する可能性があります。
OVS フロールールの量を減らすには、namespace を使用して分離する必要のある Pod のグループを組み込みます。
namespace 全体を選択する NetworkPolicy
オブジェクトは、namespaceSelectors
または空の podSelectors
を使用して、namespace の VXLAN VNID に一致する単一の OVS フロールールのみを生成します。
分離する必要のない Pod は元の namespace に維持し、分離する必要のある Pod は 1 つ以上の異なる namespace に移します。
追加のターゲット設定された namespace 間のポリシーを作成し、分離された Pod から許可する必要のある特定のトラフィックを可能にします。
8.10.2. NetworkPolicy およびルーター
ovs-multitenant プラグインを使用する場合、ルーターからすべての namespace へのトラフィックは自動的に許可されます。これは、ルーターは通常 デフォルトの namespace にあり、すべての namespace がその namespace の Pod からの接続を許可するためです。ただし ovs-networkpolicy プラグインを使用すると、これは自動的に実行されません。そのため、デフォルトで namespace を分離するポリシーがある場合は、ルーターがこれにアクセスできるように追加の手順を実行する必要があります。
1 つのオプションとして、すべてのソースからのアクセスを許可する各サービスのポリシーを作成できます。以下は例になります。
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: allow-to-database-service spec: podSelector: matchLabels: role: database ingress: - ports: - protocol: TCP port: 5432
これにより、ルーターはサービスにアクセスできますが、同時に他のユーザーの namespace にある Pod もこれにアクセスできます。これらの Pod は通常はパブリックルーターを使用してサービスにアクセスできるため、これによって問題が発生することはないはずです。
または、ovs-multitenant プラグインの場合のように、デフォルト namespace からの完全アクセスを許可するポリシーを作成することもできます。
ラベルをデフォルト namespace に追加します。
重要直前の手順でデフォルトプロジェクトに
default
ラベルを付けた場合、この手順を省略します。クラスター管理者ロールは、ラベルを namespace に追加する必要があります。$ oc label namespace default name=default
その namespace からの接続を許可するポリシーを作成します。
注記接続を許可するそれぞれの namespace についてこの手順を実行します。プロジェクト管理者ロールを持つユーザーがポリシーを作成できます。
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: allow-from-default-namespace spec: podSelector: ingress: - from: - namespaceSelector: matchLabels: name: default
8.10.3. 新規プロジェクトのデフォルト NetworkPolicy の設定
クラスター管理者は、新規プロジェクトの作成時に、デフォルトのプロジェクトテンプレートを変更してデフォルトの NetworkPolicy
オブジェクト (1 つ以上) の自動作成を有効にできます。これを実行するには、以下を行います。
- カスタムプロジェクトテンプレートを作成し、マスターがこれを使用するように設定します。
default
プロジェクトにdefault
ラベルを付けます。重要直前の手順でデフォルトプロジェクトに
default
ラベルを付けた場合、この手順を省略します。クラスター管理者ロールは、ラベルを namespace に追加する必要があります。$ oc label namespace default name=default
必要な
NetworkPolicy
オブジェクトを含むようにテンプレートを編集します。$ oc edit template project-request -n default
注記NetworkPolicy
オブジェクトを既存テンプレートに含めるには、oc edit
コマンドを使用します。現時点では、oc patch
を使用してオブジェクトをTemplate
リソースに追加することはできません。それぞれのデフォルトポリシーを
objects
配列の要素として追加します。objects: ... - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-from-same-namespace spec: podSelector: ingress: - from: - podSelector: {} - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-from-default-namespace spec: podSelector: ingress: - from: - namespaceSelector: matchLabels: name: default ...
8.11. HTTP Strict Transport Security の有効化
HTTP Strict Transport Security (HSTS) ポリシーは、ホストで HTTPS トラフィックのみを許可するセキュリティーの拡張機能です。デフォルトで、すべての HTTP 要求はドロップされます。これは、web サイトとの対話の安全性を確保したり、ユーザーのためにセキュアなアプリケーションを提供するのに役立ちます。
HSTS が有効にされると、HSTS はサイトから Strict Transport Security ヘッダーを HTTPS 応答に追加します。リダイレクトするルートで insecureEdgeTerminationPolicy
値を使用し、HTTP を HTTPS に送信するようにします。ただし、HSTS が有効にされている場合は、要求の送信前にクライアントがすべての要求を HTTP URL から HTTPS に変更するためにリダイレクトの必要がなくなります。これはクライアントでサポートされる必要はなく、max-age=0
を設定することで無効にできます。
HSTS はセキュアなルート (edge termination または re-encrypt) でのみ機能します。この設定は、HTTP またはパススルールートには適していません。
ルートに対して HSTS を有効にするには、haproxy.router.openshift.io/hsts_header
値を edge termination または re-encrypt ルートに追加します。
apiVersion: v1 kind: Route metadata: annotations: haproxy.router.openshift.io/hsts_header: max-age=31536000;includeSubDomains;preload
haproxy.router.openshift.io/hsts_header
値にパラメーターのスペースやその他の値が入っていないことを確認します。max-age
のみが必要になります。
必須の max-age
パラメーターは、HSTS ポリシーの有効期間 (秒単位) を示します。クライアントは、ホストから HSTS ヘッダーのある応答を受信する際には常に max-age
を更新します。max-age
がタイムアウトになると、クライアントはポリシーを破棄します。
オプションの includeSubDomains
パラメーターは、クライアントに対し、ホストのすべてのサブドメインがホストど同様に処理されるように指示します。
max-age
が 0 より大きい場合、オプションの preload
パラメーターは外部サービスがこのサイトをそれぞれの HSTS プリロードのリストに含めることを許可します。たとえば、Google などのサイトは preload
が設定されているサイトの一覧を作成します。ブラウザーはこれらのリストを使用し、サイトと対話する前でも HTTPS 経由でのみ通信するサイトを判別できます。preload
設定がない場合、ブラウザーはヘッダーを取得するために HTTPS 経由でサイトと通信している必要があります。
8.12. スループットの問題のトラブルシューティング
OpenShift Container Platform でデプロイされるアプリケーションでは、特定のサービス間で非常に長い待ち時間が発生するなど、ネットワークのスループットの問題が生じることがあります。
Pod のログが問題の原因を指摘しない場合は、以下の方法を使用してパフォーマンスの問題を分析します。
ping または tcpdump などのパケットアナライザーを使用して Pod とそのノード間のトラフィックを分析します。
たとえば、問題を生じさせる動作を再現している間に各ノードで tcpdump ツールを実行します。両サイトでキャプチャーしたデータを確認し、送信および受信タイムスタンプを比較して Pod への/からのトラフィックの待ち時間を分析します。待ち時間は、ノードのインターフェイスが他の Pod やストレージデバイス、またはデータプレーンからのトラフィックでオーバーロードする場合に OpenShift Container Platform で発生する可能性があります。
$ tcpdump -s 0 -i any -w /tmp/dump.pcap host <podip 1> && host <podip 2> 1
- 1
podip
は Pod の IP アドレスです。以下のコマンドを実行して Pod の IP アドレスを取得します。
# oc get pod <podname> -o wide
tcpdump は、これらの 2 つの Pod 間のすべてのトラフィックが含まれる /tmp/dump.pcap のファイルを生成します。理想的には、ファイルサイズを最小限に抑えるために問題を再現するすぐ前と問題を再現したすぐ後ににアナライザーを実行することが良いでしょう。以下のようにノード間でパケットアナライザーを実行することもできます (式から SDN を排除する)。
# tcpdump -s 0 -i any -w /tmp/dump.pcap port 4789
- ストリーミングのスループットおよび UDP スループットを測定するために iperf などの帯域幅測定ツールを使用します。ボトルネックの特定を試行するには、最初に Pod から、次にノードからツールを実行します。iperf3 ツールは RHEL 7 の一部として組み込まれています。
iperf3 のインストールおよび使用についての詳細は、こちらの Red Hat ソリューション を参照してください。
第9章 サービスアカウントの設定
9.1. 概要
ユーザーが OpenShift Container Platform CLI または web コンソールを使用する場合、API トークンはユーザーを OpenShift Container Platform API に対して認証します。ただし、一般ユーザーの認証情報を利用できない場合、以下のようにコンポーネントが API 呼び出しを行うのが通例になります。以下に例を示します。
- レプリケーションコントローラーが Pod を作成するか、または削除するために API 呼び出しを実行する。
- コンテナー内のアプリケーションが検出目的で API 呼び出しを実行する。
- 外部アプリケーションがモニターまたは統合目的で API 呼び出しを実行する。
サービスアカウントは、一般ユーザーの認証情報を共有せずに API アクセスをより柔軟に制御する方法を提供します。
9.2. ユーザー名およびグループ
すべてのサービスアカウントには、一般ユーザーのようにロールを付与できるユーザー名が関連付けられています。ユーザー名はそのプロジェクトおよび名前から派生します。
system:serviceaccount:<project>:<name>
たとえば、view (表示) ロールを top-secret プロジェクトの robot サービスアカウントに追加するには、以下を実行します。
$ oc policy add-role-to-user view system:serviceaccount:top-secret:robot
プロジェクトで特定のサービスアカウントにアクセスを付与する必要がある場合は、-z
フラグを使用できます。サービスアカウントが属するプロジェクトから -z
フラグを使用し、<serviceaccount_name>
を指定します。これによりタイプミスの発生する可能性が減り、アクセスを指定したサービスアカウントのみに付与できるため、この方法を使用することを強くお勧めします。以下に例を示します。
$ oc policy add-role-to-user <role_name> -z <serviceaccount_name>
プロジェクトから実行しない場合は、以下の例に示すように -n
オプションを使用してこれが適用されるプロジェクトの namespace を指定します。
すべてのサービスアカウントは 2 つのグループのメンバーでもあります。
- system:serviceaccounts
- システムのすべてのサービスアカウントが含まれます。
- system:serviceaccounts:<project>
- 指定されたプロジェクトのすべてのサービスアカウントが含まれます。
たとえば、すべてのプロジェクトのすべてのサービスアカウントが top-secret プロジェクトのリソースを表示できるようにするには、以下を実行します。
$ oc policy add-role-to-group view system:serviceaccounts -n top-secret
managers プロジェクトのすべてのサービスアカウントが top-secret プロジェクトのリソースを編集できるようにするには、以下を実行します。
$ oc policy add-role-to-group edit system:serviceaccounts:managers -n top-secret
9.3. サービスアカウントの管理
サービスアカウントは、各プロジェクトに存在する API オブジェクトです。サービスアカウントを管理するには、sa
または serviceaccount
オブジェクトタイプと共に oc
コマンドを使用するか、または web コンソールを使用することができます。
現在のプロジェクトの既存のサービスアカウントの一覧を取得するには、以下を実行します。
$ oc get sa NAME SECRETS AGE builder 2 2d default 2 2d deployer 2 2d
新規のサービスアカウントを作成するには、以下を実行します。
$ oc create sa robot serviceaccount "robot" created
サービスアカウントの作成後すぐに、以下の 2 つのシークレットが自動的に追加されます。
- API トークン
- OpenShift Container レジストリーの認証情報
これらはサービスアカウントを記述すると表示できます。
$ oc describe sa robot Name: robot Namespace: project1 Labels: <none> Annotations: <none> Image pull secrets: robot-dockercfg-qzbhb Mountable secrets: robot-token-f4khf robot-dockercfg-qzbhb Tokens: robot-token-f4khf robot-token-z8h44
システムは、サービスアカウントが常に API トークンとレジストリーの認証情報を持っていることを保証します。
生成される API トークンとレジストリーの認証情報は期限切れになることはありませんが、シークレットを削除することで取り消すことができます。シークレットが削除されると、新規のシークレットが自動生成され、これに置き換わります。
9.4. サービスアカウント認証の有効化
サービスアカウントは、プライベート RSA キーで署名されるトークンを使用して API に対して認証されます。認証層では一致するパブリック RSA キーを使用して署名を検証します。
サービスアカウントトークンの生成を有効にするには、マスターで /etc/origin/master/master-config.yml ファイルの serviceAccountConfig
スタンザを更新し、(署名 用に) privateKeyFile
と publicKeyFiles
一覧の一致するパブリックキーファイルを指定します。
serviceAccountConfig: ... masterCA: ca.crt 1 privateKeyFile: serviceaccount.private.key 2 publicKeyFiles: - serviceaccount.public.key 3 - ...
9.5. 管理サービスアカウント
サービスアカウントは、ビルド、デプロイメントおよびその他の Pod を実行するために各プロジェクトで必要になります。マスターの /etc/origin/master/master-config.yml ファイルの managedNames
設定は、すべてのプロジェクトに自動作成されるサービスアカウントを制御します。
serviceAccountConfig: ... managedNames: 1 - builder 2 - deployer 3 - default 4 - ...
- 1
- すべてのプロジェクトで自動作成するサービスアカウントの一覧。
- 2
- 各プロジェクトの builder サービスアカウントはビルド Pod で必要になり、system:image-builder ロールが付与されます。 このロールは、内部コンテナーイメージレジストリーを使用してイメージをプロジェクトのイメージストリームにプッシュすることを可能にします。
- 3
- 各プロジェクトの deployer サービスアカウントはデプロイメント Pod で必要になり、レプリケーションコントローラーおよびプロジェクトの Pod の表示および変更を可能にする system:deployer ロールが付与されます。
- 4
- デフォルトのサービスアカウントは、別のサービスアカウントが指定されない限り、他のすべての Pod で使用されます。
プロジェクトのすべてのサービスアカウントには system:image-puller ロールが付与されます。 このロールは、内部コンテナーイメージレジストリーを使用してイメージをイメージストリームからプルすることを可能にします。
9.6. インフラストラクチャーサービスアカウント
一部のインフラストラクチャーコントローラーは、サービスアカウント認証情報を使用して実行されます。以下のサービスアカウントは、サーバーの起動時に OpenShift Container Platform インフラストラクチャープロジェクト (openshift-infra) に作成され、クラスター全体で以下のロールが付与されます。
サービスアカウント | 説明 |
---|---|
replication-controller | system:replication-controller ロールの割り当て |
deployment-controller | system:deployment-controller ロールの割り当て |
build-controller | system:build-controller ロールの割り当て。さらに、build-controller サービスアカウントは、特権付きの ビルド Pod を作成するために特権付きセキュリティーコンテキストに組み込まれます。 |
これらのサービスアカウントが作成されるプロジェクトを設定するには、マスターで /etc/origin/master/master-config.yml ファイルの openshiftInfrastructureNamespace
フィールドを設定します。
policyConfig: ... openshiftInfrastructureNamespace: openshift-infra
9.7. サービスアカウントおよびシークレット
マスターで /etc/origin/master/master-config.yml ファイルの limitSecretReferences
フィールドを true
に設定し、Pod のシークレット参照をサービスアカウントでホワイトリストに入れることが必要になるようにします。この値を false
に設定すると、Pod がプロジェクトのすべてのシークレットを参照できるようになります。
serviceAccountConfig: ... limitSecretReferences: false
第10章 ロールベースアクセス制御 (RBAC) の管理
10.1. 概要
CLI を使用して RBAC リソース を表示し、管理者 CLI を使用して ロールとバインディング を管理することができます。
10.2. ロールとバインディングの表示
ロール は、クラスター全体 および プロジェクトのスコープ の両方で各種のアクセスレベルを付与するために使用できます。ユーザーおよびグループ は、1 度に複数のロールに関連付けるか、または バインド することができます。oc describe
コマンドを使用して、ロールおよびそれらのバインディングの詳細を確認できます。
クラスター全体でバインドされた cluster-admin のデフォルトクラスターロール を持つユーザーはすべてのリソースに対してすべてのアクションを実行できます。ローカルにバインドされた admin のデフォルトクラスターロール を持つユーザーはそのプロジェクト内のロールとバインディングをローカルに管理できます。
Evaluating Authorization セクションで動詞の詳細リストを確認してください。
10.2.1. クラスターロールの表示
クラスターロールおよびそれらの関連付けられたルールセットを表示するには、以下を実行します。
$ oc describe clusterrole.rbac Name: admin Labels: <none> Annotations: openshift.io/description=A user that has edit rights within the project and can change the project's membership. rbac.authorization.kubernetes.io/autoupdate=true PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- appliedclusterresourcequotas [] [] [get list watch] appliedclusterresourcequotas.quota.openshift.io [] [] [get list watch] bindings [] [] [get list watch] buildconfigs [] [] [create delete deletecollection get list patch update watch] buildconfigs.build.openshift.io [] [] [create delete deletecollection get list patch update watch] buildconfigs/instantiate [] [] [create] buildconfigs.build.openshift.io/instantiate [] [] [create] buildconfigs/instantiatebinary [] [] [create] buildconfigs.build.openshift.io/instantiatebinary [] [] [create] buildconfigs/webhooks [] [] [create delete deletecollection get list patch update watch] buildconfigs.build.openshift.io/webhooks [] [] [create delete deletecollection get list patch update watch] buildlogs [] [] [create delete deletecollection get list patch update watch] buildlogs.build.openshift.io [] [] [create delete deletecollection get list patch update watch] builds [] [] [create delete deletecollection get list patch update watch] builds.build.openshift.io [] [] [create delete deletecollection get list patch update watch] builds/clone [] [] [create] builds.build.openshift.io/clone [] [] [create] builds/details [] [] [update] builds.build.openshift.io/details [] [] [update] builds/log [] [] [get list watch] builds.build.openshift.io/log [] [] [get list watch] configmaps [] [] [create delete deletecollection get list patch update watch] cronjobs.batch [] [] [create delete deletecollection get list patch update watch] daemonsets.extensions [] [] [get list watch] deploymentconfigrollbacks [] [] [create] deploymentconfigrollbacks.apps.openshift.io [] [] [create] deploymentconfigs [] [] [create delete deletecollection get list patch update watch] deploymentconfigs.apps.openshift.io [] [] [create delete deletecollection get list patch update watch] deploymentconfigs/instantiate [] [] [create] deploymentconfigs.apps.openshift.io/instantiate [] [] [create] deploymentconfigs/log [] [] [get list watch] deploymentconfigs.apps.openshift.io/log [] [] [get list watch] deploymentconfigs/rollback [] [] [create] deploymentconfigs.apps.openshift.io/rollback [] [] [create] deploymentconfigs/scale [] [] [create delete deletecollection get list patch update watch] deploymentconfigs.apps.openshift.io/scale [] [] [create delete deletecollection get list patch update watch] deploymentconfigs/status [] [] [get list watch] deploymentconfigs.apps.openshift.io/status [] [] [get list watch] deployments.apps [] [] [create delete deletecollection get list patch update watch] deployments.extensions [] [] [create delete deletecollection get list patch update watch] deployments.extensions/rollback [] [] [create delete deletecollection get list patch update watch] deployments.apps/scale [] [] [create delete deletecollection get list patch update watch] deployments.extensions/scale [] [] [create delete deletecollection get list patch update watch] deployments.apps/status [] [] [create delete deletecollection get list patch update watch] endpoints [] [] [create delete deletecollection get list patch update watch] events [] [] [get list watch] horizontalpodautoscalers.autoscaling [] [] [create delete deletecollection get list patch update watch] horizontalpodautoscalers.extensions [] [] [create delete deletecollection get list patch update watch] imagestreamimages [] [] [create delete deletecollection get list patch update watch] imagestreamimages.image.openshift.io [] [] [create delete deletecollection get list patch update watch] imagestreamimports [] [] [create] imagestreamimports.image.openshift.io [] [] [create] imagestreammappings [] [] [create delete deletecollection get list patch update watch] imagestreammappings.image.openshift.io [] [] [create delete deletecollection get list patch update watch] imagestreams [] [] [create delete deletecollection get list patch update watch] imagestreams.image.openshift.io [] [] [create delete deletecollection get list patch update watch] imagestreams/layers [] [] [get update] imagestreams.image.openshift.io/layers [] [] [get update] imagestreams/secrets [] [] [create delete deletecollection get list patch update watch] imagestreams.image.openshift.io/secrets [] [] [create delete deletecollection get list patch update watch] imagestreams/status [] [] [get list watch] imagestreams.image.openshift.io/status [] [] [get list watch] imagestreamtags [] [] [create delete deletecollection get list patch update watch] imagestreamtags.image.openshift.io [] [] [create delete deletecollection get list patch update watch] jenkins.build.openshift.io [] [] [admin edit view] jobs.batch [] [] [create delete deletecollection get list patch update watch] limitranges [] [] [get list watch] localresourceaccessreviews [] [] [create] localresourceaccessreviews.authorization.openshift.io [] [] [create] localsubjectaccessreviews [] [] [create] localsubjectaccessreviews.authorization.k8s.io [] [] [create] localsubjectaccessreviews.authorization.openshift.io [] [] [create] namespaces [] [] [get list watch] namespaces/status [] [] [get list watch] networkpolicies.extensions [] [] [create delete deletecollection get list patch update watch] persistentvolumeclaims [] [] [create delete deletecollection get list patch update watch] pods [] [] [create delete deletecollection get list patch update watch] pods/attach [] [] [create delete deletecollection get list patch update watch] pods/exec [] [] [create delete deletecollection get list patch update watch] pods/log [] [] [get list watch] pods/portforward [] [] [create delete deletecollection get list patch update watch] pods/proxy [] [] [create delete deletecollection get list patch update watch] pods/status [] [] [get list watch] podsecuritypolicyreviews [] [] [create] podsecuritypolicyreviews.security.openshift.io [] [] [create] podsecuritypolicyselfsubjectreviews [] [] [create] podsecuritypolicyselfsubjectreviews.security.openshift.io [] [] [create] podsecuritypolicysubjectreviews [] [] [create] podsecuritypolicysubjectreviews.security.openshift.io [] [] [create] processedtemplates [] [] [create delete deletecollection get list patch update watch] processedtemplates.template.openshift.io [] [] [create delete deletecollection get list patch update watch] projects [] [] [delete get patch update] projects.project.openshift.io [] [] [delete get patch update] replicasets.extensions [] [] [create delete deletecollection get list patch update watch] replicasets.extensions/scale [] [] [create delete deletecollection get list patch update watch] replicationcontrollers [] [] [create delete deletecollection get list patch update watch] replicationcontrollers/scale [] [] [create delete deletecollection get list patch update watch] replicationcontrollers.extensions/scale [] [] [create delete deletecollection get list patch update watch] replicationcontrollers/status [] [] [get list watch] resourceaccessreviews [] [] [create] resourceaccessreviews.authorization.openshift.io [] [] [create] resourcequotas [] [] [get list watch] resourcequotas/status [] [] [get list watch] resourcequotausages [] [] [get list watch] rolebindingrestrictions [] [] [get list watch] rolebindingrestrictions.authorization.openshift.io [] [] [get list watch] rolebindings [] [] [create delete deletecollection get list patch update watch] rolebindings.authorization.openshift.io [] [] [create delete deletecollection get list patch update watch] rolebindings.rbac.authorization.k8s.io [] [] [create delete deletecollection get list patch update watch] roles [] [] [create delete deletecollection get list patch update watch] roles.authorization.openshift.io [] [] [create delete deletecollection get list patch update watch] roles.rbac.authorization.k8s.io [] [] [create delete deletecollection get list patch update watch] routes [] [] [create delete deletecollection get list patch update watch] routes.route.openshift.io [] [] [create delete deletecollection get list patch update watch] routes/custom-host [] [] [create] routes.route.openshift.io/custom-host [] [] [create] routes/status [] [] [get list watch update] routes.route.openshift.io/status [] [] [get list watch update] scheduledjobs.batch [] [] [create delete deletecollection get list patch update watch] secrets [] [] [create delete deletecollection get list patch update watch] serviceaccounts [] [] [create delete deletecollection get list patch update watch impersonate] services [] [] [create delete deletecollection get list patch update watch] services/proxy [] [] [create delete deletecollection get list patch update watch] statefulsets.apps [] [] [create delete deletecollection get list patch update watch] subjectaccessreviews [] [] [create] subjectaccessreviews.authorization.openshift.io [] [] [create] subjectrulesreviews [] [] [create] subjectrulesreviews.authorization.openshift.io [] [] [create] templateconfigs [] [] [create delete deletecollection get list patch update watch] templateconfigs.template.openshift.io [] [] [create delete deletecollection get list patch update watch] templateinstances [] [] [create delete deletecollection get list patch update watch] templateinstances.template.openshift.io [] [] [create delete deletecollection get list patch update watch] templates [] [] [create delete deletecollection get list patch update watch] templates.template.openshift.io [] [] [create delete deletecollection get list patch update watch] Name: basic-user Labels: <none> Annotations: openshift.io/description=A user that can get basic information about projects. rbac.authorization.kubernetes.io/autoupdate=true PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- clusterroles [] [] [get list] clusterroles.authorization.openshift.io [] [] [get list] clusterroles.rbac.authorization.k8s.io [] [] [get list watch] projectrequests [] [] [list] projectrequests.project.openshift.io [] [] [list] projects [] [] [list watch] projects.project.openshift.io [] [] [list watch] selfsubjectaccessreviews.authorization.k8s.io [] [] [create] selfsubjectrulesreviews [] [] [create] selfsubjectrulesreviews.authorization.openshift.io [] [] [create] storageclasses.storage.k8s.io [] [] [get list] users [] [~] [get] users.user.openshift.io [] [~] [get] Name: cluster-admin Labels: <none> Annotations: authorization.openshift.io/system-only=true openshift.io/description=A super-user that can perform any action in the cluster. When granted to a user within a project, they have full control over quota and membership and can perform every action... rbac.authorization.kubernetes.io/autoupdate=true PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- [*] [] [*] *.* [] [] [*] Name: cluster-debugger Labels: <none> Annotations: authorization.openshift.io/system-only=true rbac.authorization.kubernetes.io/autoupdate=true PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- [/debug/pprof] [] [get] [/debug/pprof/*] [] [get] [/metrics] [] [get] Name: cluster-reader Labels: <none> Annotations: authorization.openshift.io/system-only=true rbac.authorization.kubernetes.io/autoupdate=true PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- [*] [] [get] apiservices.apiregistration.k8s.io [] [] [get list watch] apiservices.apiregistration.k8s.io/status [] [] [get list watch] appliedclusterresourcequotas [] [] [get list watch] ...
10.2.2. クラスターのロールバインディングの表示
各種のロールにバインドされたユーザーおよびグループを示す、クラスターのロールバインディングの現在のセットを表示するには、以下を実行します。
$ oc describe clusterrolebinding.rbac Name: admin Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: admin Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount template-instance-controller openshift-infra Name: basic-users Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: basic-user Subjects: Kind Name Namespace ---- ---- --------- Group system:authenticated Name: cluster-admin Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: cluster-admin Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount pvinstaller default Group system:masters Name: cluster-admins Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: cluster-admin Subjects: Kind Name Namespace ---- ---- --------- Group system:cluster-admins User system:admin Name: cluster-readers Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: cluster-reader Subjects: Kind Name Namespace ---- ---- --------- Group system:cluster-readers Name: cluster-status-binding Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: cluster-status Subjects: Kind Name Namespace ---- ---- --------- Group system:authenticated Group system:unauthenticated Name: registry-registry-role Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: system:registry Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount registry default Name: router-router-role Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: system:router Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount router default Name: self-access-reviewers Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: self-access-reviewer Subjects: Kind Name Namespace ---- ---- --------- Group system:authenticated Group system:unauthenticated Name: self-provisioners Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: self-provisioner Subjects: Kind Name Namespace ---- ---- --------- Group system:authenticated:oauth Name: system:basic-user Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: system:basic-user Subjects: Kind Name Namespace ---- ---- --------- Group system:authenticated Group system:unauthenticated Name: system:build-strategy-docker-binding Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: system:build-strategy-docker Subjects: Kind Name Namespace ---- ---- --------- Group system:authenticated Name: system:build-strategy-jenkinspipeline-binding Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: system:build-strategy-jenkinspipeline Subjects: Kind Name Namespace ---- ---- --------- Group system:authenticated Name: system:build-strategy-source-binding Labels: <none> Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: system:build-strategy-source Subjects: Kind Name Namespace ---- ---- --------- Group system:authenticated Name: system:controller:attachdetach-controller Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: system:controller:attachdetach-controller Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount attachdetach-controller kube-system Name: system:controller:certificate-controller Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate=true Role: Kind: ClusterRole Name: system:controller:certificate-controller Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount certificate-controller kube-system Name: system:controller:cronjob-controller Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate=true ...
10.2.3. ローカルのロールおよびバインディングの表示
すべての デフォルトクラスターロール は、ユーザーまたはグループにローカルにバインドできます。
カスタムローカルロール を作成できます。
ローカルのロールバインディングも表示することができます。
各種のロールにバインドされたユーザーおよびグループを示す、ローカルのロールバインディングの現在のセットを表示するには、以下を実行します。
$ oc describe rolebinding.rbac
デフォルトでは、ローカルのロールバインディングを表示する際に現在のプロジェクトが使用されます。または、プロジェクトは -n
フラグで指定できます。これは、ユーザーに admin の デフォルトクラスターロール がすでにある場合、別のプロジェクトのローカルのロールバンディングを表示するのに役立ちます。
$ oc describe rolebinding.rbac -n joe-project Name: admin Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: admin Subjects: Kind Name Namespace ---- ---- --------- User joe Name: system:deployers Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: system:deployer Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount deployer joe-project Name: system:image-builders Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: system:image-builder Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount builder joe-project Name: system:image-pullers Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: system:image-puller Subjects: Kind Name Namespace ---- ---- --------- Group system:serviceaccounts:joe-project
10.3. ロールバインディングの管理
ロール を ユーザーまたはグループ に追加するか、または バインド することにより、そのユーザーまたはグループにそのロールによって付与される関連アクセスが提供されます。oc adm policy
コマンドを使用して、ユーザーおよびグループに対するロールの追加および削除を実行できます。
以下の操作を使用し、ローカルのロールバインディングでのユーザーまたはグループの関連付けられたロールを管理する際に、プロジェクトは -n
フラグで指定できます。これが指定されていない場合には、現在のプロジェクトが使用されます。
表10.1 ローカルのロールバインディング操作
コマンド | 説明 |
---|---|
| リソースに対してアクションを実行できるユーザーを示します。 |
| 指定されたロールを現在のプロジェクトの指定ユーザーにバインドします。 |
| 現在のプロジェクトの指定ユーザーから指定されたロールを削除します。 |
| 現在のプロジェクトの指定ユーザーとそれらのロールのすべてを削除します。 |
| 指定されたロールを現在のプロジェクトの指定グループにバインドします。 |
| 現在のプロジェクトの指定グループから指定されたロールを削除します。 |
| 現在のプロジェクトの指定グループとそれらのロールのすべてを削除します。 |
|
ユーザーまたはグループに割り当てられたロールバインディング名を保持するために |
以下の操作を使用して、クラスターのロールバインディングも管理できます。クラスターのロールバインディングは namespace を使用していないリソースを使用するため、-n
フラグはこれらの操作に使用されません。
表10.2 クラスターのロールバインディング操作
コマンド | 説明 |
---|---|
| 指定されたロールをクラスターのすべてのプロジェクトの指定ユーザーにバインドします。 |
| 指定されたロールをクラスターのすべてのプロジェクトの指定ユーザーから削除します。 |
| 指定されたロールをクラスターのすべてのプロジェクトの指定グループにバインドします。 |
| 指定されたロールをクラスターのすべてのプロジェクトの指定グループから削除します。 |
|
ユーザーまたはグループに割り当てられたロールバインディング名を保持するために |
たとえば、以下を実行して admin ロールを joe-project の alice ユーザーに追加できます。
$ oc adm policy add-role-to-user admin alice -n joe-project
次に、ローカルのロールバインディングを表示し、出力に追加されていることを確認します。
$ oc describe rolebinding.rbac -n joe-project Name: admin Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: admin Subjects: Kind Name Namespace ---- ---- --------- User joe Name: admin-0 1 Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: admin Subjects: Kind Name Namespace ---- ---- --------- User alice 2 Name: system:deployers Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: system:deployer Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount deployer joe-project Name: system:image-builders Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: system:image-builder Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount builder joe-project Name: system:image-pullers Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: system:image-puller Subjects: Kind Name Namespace ---- ---- --------- Group system:serviceaccounts:joe-project
10.4. ローカルロールの作成
プロジェクトのローカルロールを作成し、これをユーザーにバインドできます。
プロジェクトのローカルロールを作成するには、以下のコマンドを実行します。
$ oc create role <name> --verb=<verb> --resource=<resource> -n <project>
このコマンドで、以下を指定します: *
<name>
、ローカルロールの名前 *<verb>
、ロールに適用する動詞のコンマ区切りの一覧 *<resource>
、ロールが適用されるリソース *<project>
、プロジェクト名+ たとえば、ユーザーが
blue
プロジェクトで Pod を閲覧できるようにするローカルロールを作成するには、以下のコマンドを実行します。+
$ oc create role podview --verb=get --resource=pod -n blue
- 新規ロールをユーザーにバインドするには、以下のコマンドを実行します。
$ oc adm policy add-role-to-user podview user2 --role-namespace=blue -n blue
10.5. クラスターロールの作成
クラスターロールを作成するには、以下のコマンドを実行します。
$ oc create clusterrole <name> --verb=<verb> --resource=<resource>
このコマンドで以下を指定します。
-
<name>
: ローカルのロール名です。 -
<verb>
: ロールに適用する動詞のコンマ区切りの一覧です。 -
<resource>
: ロールが適用されるリソースです。
たとえば、ユーザーが Pod を閲覧できるようにするクラスターロールを作成するには、以下のコマンドを実行します。
$ oc create clusterrole podviewonly --verb=get --resource=pod
10.6. クラスターおよびローカルのロールバインディング
クラスターのロールバインディングは、クラスターレベルで存在するバインディングです。ロールバインディングは、プロジェクトレベルで存在します。クラスターの view (表示) ロールは、ユーザーがプロジェクトを表示できるようローカルのロールバインディングを使用してユーザーにバインドする必要があります。ローカルロールは、クラスターのロールが特定の状況に必要なパーミッションのセットを提供しない場合にのみ作成します。
一部のクラスターのロール名は最初は判別しにくい場合があります。クラスターロール cluster-admin
は、ローカルのロールバインディングを使用してユーザーにバインドでき、このユーザーがクラスター管理者の特権を持っているように見せます。しかし、実際はそうではありません。cluster-admin
を特定のプロジェクトにバインドすることにより、そのプロジェクトのスーパーユーザー管理者の場合と同様に、クラスターロール admin
のパーミッションを付与し、レート制限を編集する機能など、いくつかの追加パーミッションが付与されます。このバインディングは、クラスター管理者にバインドされるクラスターのロールバインディングを一覧表示しない Web コンソール UI を使うと分かりにくくなります。ただし、これは、cluster-admin
をローカルにバインドするために使用するローカルのロールバインディングを一覧表示します。
10.7. ポリシー定義の更新
クラスターのアップグレード時に、また任意のマスターの再起動時は常に、デフォルトのクラスターロール が欠落しているパーミッションを復元するために自動的に調整されます。
デフォルトクラスターロールをカスタマイズしており、ロールの調整によってそれらが変更されないようにするには、以下を実行します。
各ロールを調整から保護します。
$ oc annotate clusterrole.rbac <role_name> --overwrite rbac.authorization.kubernetes.io/autoupdate=false
警告この設定を含むロールがアップグレード後に新規または必須のパーミッションを組み込むように手動で更新する必要があります。
デフォルトのブートストラップポリシーテンプレートを生成します。
$ oc adm create-bootstrap-policy-file --filename=policy.json
注記ファイルの内容は OpenShift Container Platform バージョンによって異なりますが、ファイルにはデフォルトポリシーのみが含まれます。
- policy.json ファイルを、クラスターロールのカスタマイズを組み込むように更新します。
ポリシーを使用し、調整から保護されていないロールおよびロールバインディングを自動的に調整します。
$ oc auth reconcile -f policy.json
SCC (Security Context Constraints) を調整します。
# oc adm policy reconcile-sccs \ --additive-only=true \ --confirm
第11章 イメージポリシー
11.1. 概要
インポートするイメージや、タグ付けしたり、クラスターで実行したりするイメージを制御することができます。この目的のために使用できる 2 つの機能があります。
インポート用に許可されるレジストリー は、イメージの起点 (origin) を特定の外部レジストリーのセットに制限できるイメージポリシー設定です。このルールセットはイメージストリームにインポートされるか、またはタグ付けされるすべてのイメージに適用されます。したがって、ルールセットと一致しないレジストリーを参照するイメージは拒否されます。
ImagePolicy 受付プラグイン を使用すると、クラスターでの実行を許可するイメージを指定できます。これは現時点ではベータ機能と見なされています。この機能により、以下を制御することができます。
- イメージソース: イメージのプルに使用できるレジストリーについての指定。
- イメージの解決: イメージが再タグ付けによって変更されないよう Pod のイミュータブルなダイジェストでの実行を強制する。
- コンテナーイメージラベルの制限: イメージのラベルを制限するか、または要求する。
- イメージアノテーションの制限: 統合コンテナーイメージレジストリーでイメージのアノテーションを制限するか、または要求する。
11.2. インポート用に許可されるレジストリーの設定
以下の例に示されるように、imagePolicyConfig:allowedRegistriesForImport
セクション以下にある master-config.yaml にインポート用に許可されるレジスターを設定できます。この設定がない場合は、すべてのイメージが許可されます。 これはデフォルトになります。
例11.1 インポート用に許可されるレジストリーの設定例
imagePolicyConfig: allowedRegistriesForImport: - domainName: registry.redhat.io 1 - domainName: *.mydomain.com insecure: true 2 - domainName: local.registry.corp:5000 3
各ルールは以下の属性で設定されています。
-
domainName
: ホスト名であり、オプションでその最後は:<port>
接尾辞になり、ここで特殊なワイルドカード文字 (?
、*
) が認識されます。ワイルドカード文字は : 区切り文字の前後の両方に置くことができます。ワイルドカード文字は:
セパレーターの前後に置くことができます。ワイルドカードは、セパレーターの存在に関係なく、セパレーターの前後の部分にのみ適用されます。 -
insecure
::<port>
の部分がdomainName
にない場合、一致するポートを判別するために使用されるブール値です。true の場合、domainName
はインポート時に非セキュアなフラグが使用されている限り、接尾辞が:80
のポートが設定されているか、またはポートが未指定のレジストリーに一致します。false の場合、接尾辞が:443
のポートか、またはポートが未指定のレジストリーが一致します。
ルールが同じドメインのセキュアなポートと非セキュアなポートの両方に一致する場合、ルールは 2 回一覧表示されるはずです (1 回は insecure=true
が設定され、もう 1 回は insecure=false
が設定されます)。
修飾されていないイメージ参照は、ルールの評価前に docker.io
に対して修飾されます。これらをホワイトリストに追加するには、domainName: docker.io
を使用します。
domainName: *
ルールは任意のレジストリーのホスト名に一致しますが、ポートは依然として 443
に制限された状態になります。任意のポートで機能する任意のレジストリーに一致させるには、domainName: *:*
を使用します。
インポート用に許可されるレジストリーの設定例 で設定されるルールに基づいて、以下が実行されます。
-
oc tag --insecure reg.mydomain.com/app:v1 app:v1
は、mydomain.com
ルールの処理によってホワイトリストに追加されます。 -
oc import-image --from reg1.mydomain.com:80/foo foo:latest
もホワイトリストに追加されます。 -
oc tag local.registry.corp/bar bar:latest
は、ポートが 3 番目のルールの5000
に一致しないために拒否されます。
拒否されたイメージのインポートにより、以下のテキストのようなエラーメッセージが生成されます。
The ImageStream "bar" is invalid: * spec.tags[latest].from.name: Forbidden: registry "local.registry.corp" not allowed by whitelist: "local.registry.corp:5000", "*.mydomain.com:80", "registry.redhat.io:443" * status.tags[latest].items[0].dockerImageReference: Forbidden: registry "local.registry.corp" not allowed by whitelist: "local.registry.corp:5000", "*.mydomain.com:80", "registry.redhat.io:443"
11.3. ImagePolicy 受付プラグインの設定
クラスターで実行できるイメージを設定するには、ImagePolicy 受付プラグインを master-config.yaml
ファイルで設定します。1 つまたは複数のルールを必要に応じて設定できます。
特定のアノテーションを持つイメージの拒否:
このルールを使用して、特定のアノテーションが設定されたすべてのイメージを拒否します。以下は、
images.openshift.io/deny-execution
アノテーションを使用してすべてのイメージを拒否します。- name: execution-denied onResources: - resource: pods - resource: builds reject: true matchImageAnnotations: - key: images.openshift.io/deny-execution 1 value: "true" skipOnResolutionFailure: true
- 1
- 特定のイメージが有害であるとみなされる場合、管理者はそれらのイメージにフラグを付けるためにこのアノテーションを設定できます。
ユーザーの Docker Hub からのイメージの実行を許可:
このルールを使用して、ユーザーが Docker Hub からのイメージを使用できるようにします。
- name: allow-images-from-dockerhub onResources: - resource: pods - resource: builds matchRegistries: - docker.io
以下は、複数の ImagePolicy 受付プラグインルールを master-config.yaml
ファイルに設定する設定例です。
アノテーション付きのサンプルファイル
admissionConfig: pluginConfig: openshift.io/ImagePolicy: configuration: kind: ImagePolicyConfig apiVersion: v1 resolveImages: AttemptRewrite 1 executionRules: 2 - name: execution-denied # Reject all images that have the annotation images.openshift.io/deny-execution set to true. # This annotation may be set by infrastructure that wishes to flag particular images as dangerous onResources: 3 - resource: pods - resource: builds reject: true 4 matchImageAnnotations: 5 - key: images.openshift.io/deny-execution value: "true" skipOnResolutionFailure: true 6 - name: allow-images-from-internal-registry # allows images from the internal registry and tries to resolve them onResources: - resource: pods - resource: builds matchIntegratedRegistry: true - name: allow-images-from-dockerhub onResources: - resource: pods - resource: builds matchRegistries: - docker.io resolutionRules: 7 - targetResource: resource: pods localNames: true policy: AttemptRewrite - targetResource: 8 group: batch resource: jobs localNames: true 9 policy: AttemptRewrite
- 1
- イミュータブルなイメージダイジェストを使用してイメージを解決し、Pod でイメージのプル仕様を更新します。
- 2
- 着信リソースに対して評価するルールの配列です。
reject: true
ルールのみがある場合、デフォルトは allow all になります。reject: false
である accept ルールがルールのいずれかに含まれる場合、ImagePolicy のデフォルト動作は deny all に切り替わります。 - 3
- ルールを実施するリソースを示します。何も指定されていない場合、デフォルトは pods になります。
- 4
- このルールが一致する場合、Pod は拒否されることを示します。
- 5
- イメージオブジェクトのメタデータで一致するアノテーションの一覧。
- 6
- イメージを解決できない場合に Pod は失敗しません。
- 7
- Kubernetes リソースでのイメージストリームの使用を許可するルールの配列。デフォルト設定は、pods、replicationcontrollers、replicasets、statefulsets、daemonsets、deployments および jobs がイメージフィールドで同じプロジェクトイメージストリームのタグ参照を使用することを許可します。
- 8
- このルールが適用されるグループおよびリソースを特定します。リソースが
*
の場合、このルールはそのグループのすべてのリソースに適用されます。 - 9
LocalNames
は、単一のセグメント名 (例:ruby:2.5
) が、リソースまたはターゲットイメージストリームでlocal name resolution
が有効にされている場合にのみ namespace のローカルイメージストリームタグとして解釈されるようにします。
デフォルトのレジストリー接頭辞 (docker.io または registry.redhat.io など) を使用してプルされるインフラストラクチャーイメージを通常使用する場合、レジストリー接頭辞がないイメージは matchRegistries
値には一致しません。インフラストラクチャーイメージにイメージポリシーに一致するレジストリー接頭辞を持たせるには、master-config.yaml
ファイルに imageConfig.format 値を設定します。
11.4. 受付コントローラーを使用した Always Pull イメージの使用
イメージがノードにプルされると、任意のユーザーのノード上の Pod は、イメージに対する承認チェックなしにイメージを使用できます。Pod が認証情報を持たないイメージを使用しないようにするには、AlwaysPullImages 受付コントローラーを使用します。
この受付コントローラー はすべての新規 Pod を変更して、イメージプルポリシーを Always
に強制的に適用し、Pod 仕様が Never
の イメージプルポリシーを使用する場合でも、プライベートイメージを、それらをプルするための認証情報がある場合のみが使用できるようにします。
AlwaysPullImages 受付コントローラーを有効にするには、以下を実行します。
以下を
master-config.yaml
に追加します。admissionConfig: pluginConfig: AlwaysPullImages: 1 configuration: kind: DefaultAdmissionConfig apiVersion: v1 disable: false 2
master-restart
コマンドを使用してコントロールプレーンの静的 Pod で実行されているマスターサービスを再起動します。$ master-restart api $ master-restart controllers
11.5. ImagePolicy 受付プラグインのテスト
openshift/image-policy-check
を使用して設定をテストします。たとえば、上記の情報を使用して、以下のようにテストします。
$ oc import-image openshift/image-policy-check:latest --confirm
この YAML を使用して Pod を作成します。Pod が作成されるはずです。
apiVersion: v1 kind: Pod metadata: generateName: test-pod spec: containers: - image: docker.io/openshift/image-policy-check:latest name: first
別のレジストリーを参照する別の Pod を作成します。Pod は拒否されます。
apiVersion: v1 kind: Pod metadata: generateName: test-pod spec: containers: - image: different-registry/openshift/image-policy-check:latest name: first
インポートされたイメージを使用して、内部レジストリーを参照する Pod を作成します。Pod は作成され、イメージ仕様を確認すると、タグの位置にダイジェストが表示されます。
apiVersion: v1 kind: Pod metadata: generateName: test-pod spec: containers: - image: <internal registry IP>:5000/<namespace>/image-policy-check:latest name: first
インポートされたイメージを使用して、内部レジストリーを参照する Pod を作成します。Pod は作成され、イメージ仕様を確認すると、タグが変更されていないことを確認できます。
apiVersion: v1 kind: Pod metadata: generateName: test-pod spec: containers: - image: <internal registry IP>:5000/<namespace>/image-policy-check:v1 name: first
oc get istag/image-policy-check:latest
からダイジェストを取得し、これをoc annotate images/<digest> images.openshift.io/deny-execution=true
に使用します。以下に例を示します。$ oc annotate images/sha256:09ce3d8b5b63595ffca6636c7daefb1a615a7c0e3f8ea68e5db044a9340d6ba8 images.openshift.io/deny-execution=true
この Pod を再作成すると、Pod が拒否されたことがわかります。
apiVersion: v1 kind: Pod metadata: generateName: test-pod spec: containers: - image: <internal registry IP>:5000/<namespace>/image-policy-check:latest name: first
第12章 イメージの署名
12.1. 概要
Red Hat Enterprise Linux (RHEL) システムでのコンテナーイメージの署名により、以下を実行できます。
- コンテナーイメージの起点の検証
- イメージが改ざんされていないことの確認
- ホストにプルできる検証済みイメージを判別するポリシーの設定
RHEL システムでのコンテナーイメージの署名についてのアーキテクチャーの詳細は、Container Image Signing Integration Guide を参照してください。
OpenShift Container レジストリーは、REST API 経由で署名を保存する機能を提供します。oc
CLI を使用して、検証済みのイメージを web コンソールまたは CLI に表示し、イメージの署名を検証することができます。
12.2. Atomic CLI を使用したイメージの署名
OpenShift Container Platform はイメージの署名を自動化しません。署名には、通常はワークステーションに安全に保存される開発者のプライベート GPG キーが必要になります。本書では、このワークフローについて説明します。
atomic
コマンドラインインターフェイス (CLI)(バージョン 1.12.5 以降) は、OpenShift Container レジストリーにプッシュできるコンテナーイメージに署名するためのコマンドを提供します。atomic
CLI は、Red Hat ベースのディストリビューション (RHEL、Centos、および Fedora) で利用できます。atomic
CLI は RHEL Atomic Host システムには事前にインストールされます。atomic パッケージの RHEL ホストへのインストールについての詳細は、イメージ署名サポートの有効化 を参照してください。
atomic
CLI は、oc login
で認証された証明書を使用します。atomic
および oc
コマンドの両方で同じホストの同じユーザーを使用するようにしてください。たとえば、atomic
CLI を sudo
として使用する場合、OpenShift Container Platform に sudo oc login
を使用してログインします。
署名をイメージに割り当てるには、ユーザーに image-signer
クラスターロールがなければなりません。クラスター管理者は、以下を使用してこれを追加できます。
$ oc adm policy add-cluster-role-to-user system:image-signer <user_name>
イメージにはプッシュ時に署名できます。
$ atomic push [--sign-by <gpg_key_id>] --type atomic <image>
署名は、atomic
トランスポートタイプの引数が指定される際に OpenShift Container Platform に保存されます。詳細は、Signature Transports を参照してください。
atomic
CLI を使用してイメージをセットアップし、実行する方法についての詳細は、RHEL Atomic Host Managing Containers: Signing Container Images ドキュメントか、または atomic push --help
出力で引数の詳細を参照してください。
atomic
CLI および OpenShift Container レジストリーの使用についてのワークフローの特定の例については、Container Image Signing Integration Guide で説明されています。
12.3. OpenShift CLI を使用したイメージ署名の検証
oc adm verify-image-signature
コマンドを使用して、OpenShift Container レジストリーにインポートされたイメージの署名を検証できます。このコマンドは、イメージ署名に含まれるイメージ ID が信頼できるかどうかを検証します。 ここでは、パブリック GPG キーを使用して署名自体を検証し、提供される予想 ID と指定イメージの ID (プル仕様) のマッチングが行われます。
デフォルトで、このコマンドは通常 $GNUPGHOME/pubring.gpg にあるパブリック GPG キーリングをパス ~/.gnupg で使用します。デフォルトで、このコマンドは検証結果をイメージオブジェクトに保存し直すことはありません。これを実行するには、以下に示すように --save
フラグを指定する必要があります。
イメージの署名を検証するには、ユーザーに image-auditor
クラスターロールがなければなりません。クラスター管理者は、以下を使用してこれを追加できます。
$ oc adm policy add-cluster-role-to-user system:image-auditor <user_name>
検証済みのイメージで無効な GPG キーまたは無効な予想 ID と共に --save
フラグを使用すると、保存された検証ステータスおよびすべての署名が削除され、イメージは未検証の状態になります。
誤ってすべての署名を削除してしまうことを避けるために、最初は --save
フラグなしでコマンドを実行し、ログで潜在的な問題の有無を確認できます。
イメージ署名を検証するには、以下の形式を使用します。
$ oc adm verify-image-signature <image> --expected-identity=<pull_spec> [--save] [options]
<pull_spec>
はイメージストリームを記述することで確認でき、<image>
はイメージストリームタグを記述して確認することができます。以下のコマンド出力例を参照してください。
イメージ署名の検証例
$ oc describe is nodejs -n openshift Name: nodejs Namespace: openshift Created: 2 weeks ago Labels: <none> Annotations: openshift.io/display-name=Node.js openshift.io/image.dockerRepositoryCheck=2017-07-05T18:24:01Z Docker Pull Spec: 172.30.1.1:5000/openshift/nodejs ... $ oc describe istag nodejs:latest -n openshift Image Name: sha256:2bba968aedb7dd2aafe5fa8c7453f5ac36a0b9639f1bf5b03f95de325238b288 ... $ oc adm verify-image-signature \ sha256:2bba968aedb7dd2aafe5fa8c7453f5ac36a0b9639f1bf5b03f95de325238b288 \ --expected-identity 172.30.1.1:5000/openshift/nodejs:latest \ --public-key /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release \ --save
oc adm verify-image-signature
コマンドが、x509: certificate signed by unknown authority
エラーを返す場合、レジストリーの認証局 (CA) をシステム上で信頼される CA の一覧に追加する必要がある場合があります。これには、以下の手順を実行します。
CA 証明書をクラスターからクライアントマシンに転送します。
たとえば、docker-registry.default.svc の CA を追加するには、/etc/docker/certs.d/docker-registry.default.svc\:5000/node-client-ca.crt にあるファイルを転送します。
CA 証明書を /etc/pki/ca-trust/source/anchors/ ディレクトリーにコピーします。以下に例を示します。
# cp </path_to_file>/node-client-ca.crt \ /etc/pki/ca-trust/source/anchors/
update-ca-trust
を実行して、信頼できる CA の一覧を更新します。# update-ca-trust
12.4. レジストリー API の使用によるイメージ署名へのアクセス
OpenShift Container レジストリーは、イメージ署名の書き込みおよび読み取りを実行できる extensions
エンドポイントを提供します。イメージ署名は、コンテナーイメージレジストリー API 経由で OpenShift Container Platform の KVS (key-value store) に保存されます。
このエンドポイントは実験段階にあり、アップストリームのコンテナーイメージレジストリープロジェクトではサポートされていません。コンテナーイメージレジストリー API の一般的な情報については、アップストリーム API のドキュメント を参照してください。
12.4.1. API 経由でのイメージ署名の書き込み
新規署名をイメージに追加するには、HTTP PUT
メソッドを使用して JSON ペイロードを extensions
エンドポイントに送信できます。
PUT /extensions/v2/<namespace>/<name>/signatures/<digest>
$ curl -X PUT --data @signature.json http://<user>:<token>@<registry_endpoint>:5000/extensions/v2/<namespace>/<name>/signatures/sha256:<digest>
署名コンテンツを含む JSON ペイロードの構造は以下のようになります。
{ "version": 2, "type": "atomic", "name": "sha256:4028782c08eae4a8c9a28bf661c0a8d1c2fc8e19dbaae2b018b21011197e1484@cddeb7006d914716e2728000746a0b23", "content": "<cryptographic_signature>" }
name
フィールドには、一意で <digest>@<name>
形式でなければならないイメージ署名の名前が含まれます。<digest>
はイメージ名を表し、<name>
は署名の名前になります。署名名には 32 文字の長さが必要です。<cryptographic_signature>
は、コンテナー/イメージ ライブラリーで説明されている仕様に従っている必要があります。
12.4.2. API 経由でのイメージ署名の読み取り
署名済みのイメージが OpenShift Container レジストリーにすでにプッシュされていると仮定すると、以下のコマンドを使って署名を読み取ることができます。
GET /extensions/v2/<namespace>/<name>/signatures/<digest>
$ curl http://<user>:<token>@<registry_endpoint>:5000/extensions/v2/<namespace>/<name>/signatures/sha256:<digest>
<namespace>
は OpenShift Container Platform プロジェクト名またはレジストリーのリポジトリー名を表し、<name>
はイメージリポジトリーの名前を指します。digest
はイメージの SHA-256 チェックサムを表します。
指定されたイメージに署名データが含まれる場合、上記のコマンド出力により、以下の JSON 応答が生成されます。
{ "signatures": [ { "version": 2, "type": "atomic", "name": "sha256:4028782c08eae4a8c9a28bf661c0a8d1c2fc8e19dbaae2b018b21011197e1484@cddeb7006d914716e2728000746a0b23", "content": "<cryptographic_signature>" } ] }
name
フィールドには、一意で <digest>@<name>
形式でなければならないイメージ署名の名前が含まれます。<digest>
はイメージ名を表し、<name>
は署名の名前になります。署名名には 32 文字の長さが必要です。<cryptographic_signature>
は、コンテナー/イメージ ライブラリーで説明されている仕様に従っている必要があります。
12.4.3. 署名ストアからのイメージ署名の自動インポート
OpenShift Container Platform は、署名ストアがすべての OpenShift Container Platform マスターノードに設定されている場合に、レジストリー設定ディレクトリーを使用してイメージ署名を自動インポートします。
レジストリー設定ディレクトリーには、各種レジストリー (リモートコンテナーイメージを保存するサーバー) およびそれらに保存されるコンテンツの設定が含まれます。この単一ディクトリーを使用すると、設定がコンテナー/イメージのすべてのユーザー間で共有されるように、各コマンドのコマンドラインオプションでその設定を指定する必要がありません。
デフォルトのレジストリー設定ディレクトリーは、/etc/containers/registries.d/default.yaml ファイルにあります。
すべての Red Hat イメージに対してイメージ署名の自動インポートを実行する設定例:
docker:
registry.redhat.io:
sigstore: https://registry.redhat.io/containers/sigstore 1
- 1
- 署名ストアの URL を定義します。この URL は、既存署名の読み取りに使用されます。
OpenShift Container Platform によって自動的にインポートされる署名は、デフォルトで 未検証 の状態になり、イメージ管理者による検証が必要になります。
レジストリー設定ディレクトリーについての詳細は、Registries Configuration Directory を参照してください。
第13章 スコープ付きトークン
13.1. 概要
ユーザーは、他のエンティティーに対し、自らと同様に機能する権限を制限された方法で付与する必要があるかもしれません。たとえば、プロジェクト管理者は Pod の作成権限を委任する必要があるかもしれません。これを実行する方法の 1 つとして、スコープ付きトークンを作成することができます。
スコープ付きトークンは、指定されるユーザーを識別するが、そのスコープによって特定のアクションに制限するトークンです。現時点で、cluster-admin のみがスコープ付きトークンを作成できます。
13.2. 評価
スコープは、トークンの一連のスコープを PolicyRules のセットに変換して評価されます。次に、要求がそれらのルールに対してマッチングされます。要求属性は、追加の許可検査のために標準承認者に渡せるよう、スコープルールのいずれかに一致している必要があります。
13.3. ユーザースコープ
ユーザースコープでは、指定されたユーザーについての情報を取得することにフォーカスが置かれます。それらはインテントベースであるため、ルールは自動的に作成されます。
-
user:full
: ユーザーのすべてのパーミッションによる API の完全な読み取り/書き込みアクセスを許可します。 -
user:info
: ユーザー (名前、グループなど) についての情報の読み取り専用アクセスを許可します。 -
user:check-access
: self-localsubjectaccessreviews および self-subjectaccessreviews へのアクセスを許可します。これらは、要求オブジェクトの空のユーザーおよびグループを渡す変数です。 -
user:list-projects
: ユーザーがアクセスできるプロジェクトを一覧表示するための読み取り専用アクセスを許可します。
13.4. ロールスコープ
ロールスコープにより、 namespace でフィルターされる指定ロールと同じレベルのアクセスを持たせることができます。
role:<cluster-role name>:<namespace or * for all>
: 指定された namespace のみにあるクラスターロール (cluster-role) で指定されるルールにスコープを制限します。注記注意: これは、アクセスのエスカレートを防ぎます。ロールはシークレット、ロールバインディング、およびロールなどのリソースへのアクセスを許可しますが、このスコープはそれらのリソースへのアクセスを制限するのに役立ちます。これにより、予期しないエスカレーションを防ぐことができます。edit (編集) などのロールはエスカレートされるロールと見なされないことが多いですが、シークレットのアクセスを持つロールの場合はロールのエスカレーションが生じます。
-
role:<cluster-role name>:<namespace or * for all>:!
: bang (!) を含めることでこのスコープでアクセスのエスカレートを許可されますが、それ以外には上記の例と同様になります。
第14章 イメージのモニターリング
14.1. 概要
14.2. イメージ統計の表示
OpenShift Container Platform が管理するすべてのイメージの使用状況についてのいくつかの統計を表示できます。つまり、直接 または ビルド によって内部レジストリーにプッシュされるすべてのイメージの統計を表示できます。
使用状況の統計を表示するには、以下を実行します。
$ oc adm top images NAME IMAGESTREAMTAG PARENTS USAGE METADATA STORAGE sha256:80c985739a78b openshift/python (3.5) yes 303.12MiB sha256:64461b5111fc7 openshift/ruby (2.2) yes 234.33MiB sha256:0e19a0290ddc1 test/ruby-ex (latest) sha256:64461b5111fc71ec Deployment: ruby-ex-1/test yes 150.65MiB sha256:a968c61adad58 test/django-ex (latest) sha256:80c985739a78b760 Deployment: django-ex-1/test yes 186.07MiB
コマンドにより、以下の情報が表示されます。
- イメージ ID
-
プロジェクト、名前、および付随する
ImageStreamTag
のタグ - イメージ ID で一覧表示されるイメージの潜在的な親
- イメージが使用される場所についての情報
- イメージに適切な Docker メタデータ情報が含まれるかどうかを示すフラグ
- イメージのサイズ
14.3. ImageStreams 統計の表示
すべての ImageStreams
の使用状況についてのいくつかの統計を表示できます。
使用状況の統計を表示するには、以下を実行します。
$ oc adm top imagestreams NAME STORAGE IMAGES LAYERS openshift/python 1.21GiB 4 36 openshift/ruby 717.76MiB 3 27 test/ruby-ex 150.65MiB 1 10 test/django-ex 186.07MiB 1 10
コマンドにより、以下の情報が表示されます。
-
プロジェクトおよび
ImageStream
の名前 -
内部 Red Hat Container レジストリー に保存される
ImageStream
全体のサイズ -
この特定の
ImageStream
が参照しているイメージの数 -
ImageStream
を設定する層の数
14.4. イメージのプルーニング
上記のコマンドで返される情報は、イメージのプルーニングを実行する際に役立ちます。
第15章 SCC (Security Context Constraints) の管理
15.1. 概要
SCC (Security Context Constraints) により、管理者は Pod のパーミッションを制御できます。この API タイプについての詳細は、SCC (security context constraints) アーキテクチャーのドキュメントを参照してください。SCC は、CLI を使用し、インスタンスで通常の API オブジェクト として管理できます。
SCC を管理するには、cluster-admin 権限 が必要です。
デフォルトの SCC を変更しないでください。デフォルトの SCC をカスタマイズすると、アップグレード時に問題が生じる可能性があります。代わりに 新規 SCC を作成 してください。
15.2. SCC (Security Context Constraints) の一覧表示
SCC の現在の一覧を取得するには、以下を実行します。
$ oc get scc NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP PRIORITY READONLYROOTFS VOLUMES anyuid false [] MustRunAs RunAsAny RunAsAny RunAsAny 10 false [configMap downwardAPI emptyDir persistentVolumeClaim secret] hostaccess false [] MustRunAs MustRunAsRange MustRunAs RunAsAny <none> false [configMap downwardAPI emptyDir hostPath persistentVolumeClaim secret] hostmount-anyuid false [] MustRunAs RunAsAny RunAsAny RunAsAny <none> false [configMap downwardAPI emptyDir hostPath nfs persistentVolumeClaim secret] hostnetwork false [] MustRunAs MustRunAsRange MustRunAs MustRunAs <none> false [configMap downwardAPI emptyDir persistentVolumeClaim secret] nonroot false [] MustRunAs MustRunAsNonRoot RunAsAny RunAsAny <none> false [configMap downwardAPI emptyDir persistentVolumeClaim secret] privileged true [*] RunAsAny RunAsAny RunAsAny RunAsAny <none> false [*] restricted false [] MustRunAs MustRunAsRange MustRunAs RunAsAny <none> false [configMap downwardAPI emptyDir persistentVolumeClaim secret]
15.3. SCC (Security Context Constraints) オブジェクトの検査
特定の SCC についての情報 (SCC が適用されるユーザー、サービスアカウントおよびグループを含む) を表示できます。
たとえば、restricted SCC を検査するには、以下を実行します。
$ oc describe scc restricted Name: restricted Priority: <none> Access: Users: <none> 1 Groups: system:authenticated 2 Settings: Allow Privileged: false Default Add Capabilities: <none> Required Drop Capabilities: KILL,MKNOD,SYS_CHROOT,SETUID,SETGID Allowed Capabilities: <none> Allowed Seccomp Profiles: <none> Allowed Volume Types: configMap,downwardAPI,emptyDir,persistentVolumeClaim,projected,secret Allow Host Network: false Allow Host Ports: false Allow Host PID: false Allow Host IPC: false Read Only Root Filesystem: false Run As User Strategy: MustRunAsRange UID: <none> UID Range Min: <none> UID Range Max: <none> SELinux Context Strategy: MustRunAs User: <none> Role: <none> Type: <none> Level: <none> FSGroup Strategy: MustRunAs Ranges: <none> Supplemental Groups Strategy: RunAsAny Ranges: <none>
アップグレード時にカスタマイズされた SCC を保持するには、優先順位、ユーザー、グループ、ラベル、およびアノテーション以外にはデフォルトの SCC の設定を編集しないでください。
15.4. 新規 SCC (Security Context Constraints) の作成
新規 SCC を作成するには、以下を実行します。
JSON または YAML ファイルで SCC を定義します。
SCC (Security Context Constraints) オブジェクトの定義
kind: SecurityContextConstraints apiVersion: v1 metadata: name: scc-admin allowPrivilegedContainer: true runAsUser: type: RunAsAny seLinuxContext: type: RunAsAny fsGroup: type: RunAsAny supplementalGroups: type: RunAsAny users: - my-admin-user groups: - my-admin-group
オプションとして、
requiredDropCapabilities
フィールドに必要な値を設定して、ドロップ機能を SCC に追加することができます。指定された機能はコンテナーからドロップされることになります。たとえば、SCC をKILL
、MKNOD
、およびSYS_CHROOT
の必要なドロップ機能を使って作成するには、以下を SCC オブジェクトに追加します。requiredDropCapabilities: - KILL - MKNOD - SYS_CHROOT
使用できる値の一覧は、Docker ドキュメント で確認できます。
ヒント機能は Docker に渡されるため、特殊な
ALL
値を使用してすべての機能をドロップすることができます。次に、作成するファイルを渡して
oc create
を実行します。$ oc create -f scc_admin.yaml securitycontextconstraints "scc-admin" created
SCC が作成されていることを確認します。
$ oc get scc scc-admin NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP PRIORITY READONLYROOTFS VOLUMES scc-admin true [] RunAsAny RunAsAny RunAsAny RunAsAny <none> false [awsElasticBlockStore azureDisk azureFile cephFS cinder configMap downwardAPI emptyDir fc flexVolume flocker gcePersistentDisk glusterfs iscsi nfs persistentVolumeClaim photonPersistentDisk quobyte rbd secret vsphere]
15.5. SCC (Security Context Constraints) の削除
SCC を削除するには、以下を実行します。
$ oc delete scc <scc_name>
デフォルトの SCC を削除する場合、これは再起動時に再生成されます。
15.6. SCC (Security Context Constraints) の更新
既存 SCC を更新するには、以下を実行します。
$ oc edit scc <scc_name>
アップグレード時にカスタマイズされた SCC を保持するには、優先順位、ユーザー、グループ以外にデフォルトの SCC の設定を編集しないでください。
15.6.1. SCC (Security Context Constraints) 設定のサンプル
明示的な runAsUser 設定がない場合
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext: 1
containers:
- name: sec-ctx-demo
image: gcr.io/google-samples/node-hello:1.0
- 1
- コンテナーまたは Pod が実行時に使用するユーザー ID を要求しない場合、有効な UID はこの Pod を作成する SCC よって異なります。制限付き SCC はデフォルトですべての認証ユーザーに付与されるため、ほとんどの場合はすべてのユーザーおよびサービスアカウントで利用でき、使用されます。この制限付き SCC は、
securityContext.runAsUser
フィールドの使用できる値を制限し、これをデフォルトに設定するためにMustRunAsRange
ストラテジーを使用します。受付プラグインではこの範囲を指定しないため、現行プロジェクトでopenshift.io/sa.scc.uid-range
アノテーションを検索して範囲フィールドにデータを設定します。最終的にコンテナーのrunAsUser
は予測が困難な範囲の最初の値と等しい値になります。予測が困難であるのはすべてのプロジェクトにはそれぞれ異なる範囲が設定されるためです。詳細は、Understanding Pre-allocated Values and Security Context Constraints (事前に割り当てられた値および SCC (Security Context Constraint) について) を参照してください。
明示的な runAsUser 設定がある場合
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000 1
containers:
- name: sec-ctx-demo
image: gcr.io/google-samples/node-hello:1.0
- 1
- 特定のユーザー ID を要求するコンテナーまたは Pod が、OpenShift Container Platform によって受け入れられるのは、サービスアカウントまたはユーザーにそのユーザー ID を許可する SCC へのアクセスが付与されている場合のみです。SCC は、任意の ID や特定の範囲内にある ID、または要求に固有のユーザー ID を許可します。
これは SELinux、fsGroup、および Supplemental Groups で機能します。詳細は、Volume Security (ボリュームセキュリティー) を参照してください。
15.7. デフォルト SCC (Security Context Constraints) の更新
デフォルト SCC は、それらが見つからない場合にはマスターの起動時に作成されます。SCC をデフォルトにリセットするか、またはアップグレード後に既存の SCC を新規のデフォルト定義に更新するには、以下を実行します。
- リセットする SCC を削除し、マスターを再起動してその再作成を実行します。
-
oc adm policy reconcile-sccs
コマンドを使用します。
oc adm policy reconcile-sccs
コマンドは、すべての SCC ポリシーをデフォルト値に設定しますが、すでに設定した可能性のある追加ユーザー、グループ、ラベル、アノテーションおよび優先順位を保持します。変更される SCC を表示するには、オプションなしでコマンドを実行するか、または -o <format>
オプションで優先する出力を指定してコマンドを実行します。
確認後は、既存 SCC のバックアップを取ってから --confirm
オプションを使用してデータを永続化します。
優先順位や許可をリセットする場合は、--additive-only=false
オプションを使用します。
SCC に優先順位、ユーザー、グループ、ラベル、またはアノテーション以外のカスタマイズ設定がある場合、これらの設定は調整時に失われます。
15.8. 使用方法
以下では、SCC を使用する一般的なシナリオおよび手順について説明します。
15.8.1. 特権付き SCC のアクセス付与
管理者が管理者グループ外のユーザーまたはグループに対して 特権付き Pod を追加作成するためのアクセスを付与することが必要になることがあります。これを実行するには、以下を行います。
SCC へのアクセスを付与するユーザーまたはグループを決定します。
警告ユーザーへのアクセス付与は、ユーザーが Pod を直接作成する場合にのみ可能です。ほとんどの場合、システム自体がユーザーの代わりに作成する Pod については、関連するコントローラーの作動に使用される サービスアカウントにアクセスを付与する必要があります。ユーザーの代わりに Pod を作成するリソースの例として、Deployments、StatefulSets、DaemonSets などが含まれます。
以下のコマンドを実行します。
$ oc adm policy add-scc-to-user <scc_name> <user_name> $ oc adm policy add-scc-to-group <scc_name> <group_name>
たとえば、e2e-user の 特権付き SCC へのアクセスを許可するには、以下を実行します。
$ oc adm policy add-scc-to-user privileged e2e-user
-
特権モードを要求するようにコンテナーの
SecurityContext
を変更します。
15.8.2. 特権付き SCC のサービスアカウントアクセスの付与
最初に、サービスアカウント を作成します。たとえば、サービスアカウント mysvcacct
をプロジェクト myproject
で作成するには、以下を実行します。
$ oc create serviceaccount mysvcacct -n myproject
次に、サービスアカウントを privileged
SCC に追加します。
$ oc adm policy add-scc-to-user privileged system:serviceaccount:myproject:mysvcacct
その後は、リソースがサービスアカウントの代わりに作成されていることを確認します。これを実行するには、spec.serviceAccountName
フィールドをサービスアカウント名に設定します。サービスアカウント名を空のままにすると、デフォルト
のサービスアカウントが使用されます。
次に、少なくとも 1 つの Pod のコンテナーがセキュリティーコンテキストで特権モードを要求していることを確認します。
15.8.3. Dokerfile の USER によるイメージ実行の有効化
特権付き SCC へのアクセスをすべての人に与えることなく、イメージが事前割り当て UID で強制的に実行されないようにクラスターのセキュリティーを緩和するには、以下を実行します。
すべての認証されたユーザーに anyuid SCC へのアクセスを付与します。
$ oc adm policy add-scc-to-group anyuid system:authenticated
これにより、USER が Dockerfile に指定されていない場合は、イメージをルート ID として実行することができます。
15.8.4. ルートを要求するコンテナーイメージの有効化
一部のコンテナーイメージ (例: postgres
および redis
) には root アクセスが必要であり、ボリュームの保有方法についてのいくつかの予測が設定されています。これらのイメージについては、サービスアカウントを anyuid
SCC に追加します。
$ oc adm policy add-scc-to-user anyuid system:serviceaccount:myproject:mysvcacct
15.8.5. レジストリーでの --mount-host の使用
PersistentVolume
および PersistentVolumeClaim
オブジェクトを使用する 永続ストレージ を レジストリーのデプロイメント に使用することが推奨されます。テストを実行中で、oc adm registry
コマンドを --mount-host
オプションと共に使用する必要がある場合には、まずレジストリーの新規 サービスアカウント を作成し、これを特権付き SCC に追加する必要があります。詳細の説明については、Administrator Guide を参照してください。
15.8.6. 追加機能の提供
場合によっては、Docker が追加設定なしの機能として提供していない機能がイメージで必要になることがあります。この場合、Pod 仕様で追加機能を要求することができ、これは SCC に対して検証されます。
これによりイメージを昇格された機能を使って実行できますが、これは必要な場合にのみ実行する必要があります。追加機能を有効にするためにデフォルトの restricted SCC を編集することはできません。
非 root ユーザーによって使用される場合、setcap
コマンドを使用して、追加機能を要求するファイルに該当する機能が付与されていることを確認する必要もあります。たとえば、イメージの Dockerfile では、以下のようになります。
setcap cap_net_raw,cap_net_admin+p /usr/bin/ping
さらに機能が Docker のデフォルトとして提供されている場合には、これを要求するために Pod 仕様を変更する必要はありません。たとえば、NET_RAW
がデフォルトで指定されており、機能がすでに ping
で設定されている場合、ping
を実行するのに特別な手順は必要ありません。
追加機能を提供するには、以下を実行します。
- 新規 SCC を作成します。
-
allowedCapabilities
フィールドを使用して許可された機能を追加します。 -
Pod の作成時に、
securityContext.capabilities.add
フィールドで機能を要求します。
15.8.7. クラスターのデフォルト動作の変更
すべてのユーザーに対して anyuid SCC のアクセスを付与する場合、クラスターは以下のようになります。
- UID を事前に割り当てない
- コンテナーの任意ユーザーとしての実行を許可する
- 特権付きコンテナーを禁止する
$ oc adm policy add-scc-to-group anyuid system:authenticated
UID を事前に割り当てないようにし、コンテナーが root で実行されないようにクラスターを変更するには、すべてのユーザーに対して nonroot SCC のアクセスを付与します。
$ oc adm policy add-scc-to-group nonroot system:authenticated
クラスター全体に影響を与える変更を行う際には十分に注意してください。直前の例のようにすべての認証ユーザーに SCC を付与したり、制限付き SCC のようにすべてのユーザーに適用される SCC を変更する場合には、Web コンソールや統合コンテナーイメージレジストリーなどの Kubernetes および OpenShift Container Platform コンポーネントにも影響を与えます。これらの SCC に関する変更により、これらのコンポーネントの機能は停止する可能性があります。
代わりに、カスタム SCC を作成し、このターゲットを特定のユーザーまたはグループのみに指定します。これにより、潜在的な問題の影響を特定の影響を受けるユーザーまたはグループに制限し、重要なクラスターコンポーネントに影響が及ばないようにすることができます。
15.8.8. hostPath ボリュームプラグインの使用
privileged、hostaccess、または hostmount-anyuid などの特権付き SCC へのアクセスをすべての人に付与することなく、Pod で hostPath
ボリュームプラグインを使用できるようにクラスターのセキュリティーを緩和するには、以下を実行します。
-
hostpath
という名前の 新規 SCC を作成 します。 新規 SCC の
allowHostDirVolumePlugin
パラメーターをtrue
に設定します。$ oc patch scc hostpath -p '{"allowHostDirVolumePlugin": true}'
この SCC へのアクセスをすべてのユーザーに付与します。
$ oc adm policy add-scc-to-group hostpath system:authenticated
これで、hostPath
ボリュームを要求するすべての Pod は hostpath
SCC で許可されます。
15.8.9. 受付を使用した特定 SCC の初回使用
SCC の Priority
フィールドを設定し、受付コントローラーで SCC の並び替え順序を制御することができます。並び替えについての詳細は、SCC Prioritization セクションを参照してください。
15.8.10. SCC のユーザー、グループまたはプロジェクトへの追加
SCC をユーザーまたはグループに追加する前に、まず scc-review
オプションを使用してユーザーまたはグループが Pod を作成できるかどうかをチェックできます。詳細は、Authorization のトピックを参照してください。
SCC はプロジェクトに直接付与されません。代わりに、サービスアカウントを SCC に追加し、Pod にサービスアカウント名を指定するか、または指定されない場合は default
サービスアカウントを使用して実行します。
SCC をユーザーに追加するには、以下を実行します。
$ oc adm policy add-scc-to-user <scc_name> <user_name>
SCC をサービスアカウントに追加するには、以下を実行します。
$ oc adm policy add-scc-to-user <scc_name> \ system:serviceaccount:<serviceaccount_namespace>:<serviceaccount_name>
現在の場所がサービスアカウントが属するプロジェクトの場合、-z
フラグを使用し、<serviceaccount_name>
のみを指定することができます。
$ oc adm policy add-scc-to-user <scc_name> -z <serviceaccount_name>
上記の -z
フラグについては、誤字を防ぎ、アクセスが指定されたサービスアカウントのみに付与されるため、使用することを強く推奨します。プロジェクトにいない場合は、-n
オプションを使用して、それが適用されるプロジェクトの namespace を指定します。
SCC をグループに追加するには、以下を実行します。
$ oc adm policy add-scc-to-group <scc_name> <group_name>
SCC を namespace のすべてのサービスアカウントに追加するには、以下を実行します。
$ oc adm policy add-scc-to-group <scc_name> \ system:serviceaccounts:<serviceaccount_namespace>
第16章 スケジューリング
16.1. 概要
16.1.1. 概要
Pod のスケジューリングは、クラスター内のノードへの新規 Pod の配置を決定する内部プロセスです。
スケジューラーコードは、新規 Pod の作成時にそれらを確認し、それらをホストするのに最も適したノードを識別します。次に、マスター API を使用して Pod のバインディング (Pod とノードのバインディング) を作成します。
16.1.2. デフォルトスケジューリング
OpenShift Container Platform には、ほとんどのユーザーのニーズに対応するデフォルトスケジューラーが同梱されます。デフォルトスケジューラーは、Pod に最適なノードを判別するための固有のツールおよびカスタマイズ可能なツールの両方を使用します。
デフォルトスケジューラーが Pod の配置と利用できるカスタマイズ可能なパラメーターを判別する方法についての詳細は、デフォルトスケジューリング を参照してください。
16.1.3. 詳細スケジューリング
新規 Pod の配置場所に対する制御を強化する必要がある場合、OpenShift Container Platform の詳細スケジューリング機能を使用すると、Pod が特定ノード上か、または特定の Pod と共に実行されることを要求する (または実行されることが優先される) よう Pod を設定することができます。また詳細設定により、Pod をノードに配置することや他の Pod と共に実行することを防ぐこともできます。
詳細スケジューリングについての詳細は、詳細スケジューリング を参照してください。
16.1.4. カスタムスケジューリング
OpenShift Container Platform では、Pod 仕様を編集してユーザー独自のスケジューラーまたはサードパーティーのスケジューラーを使用することもできます。
詳細は、カスタムスケジューラー を参照してください。
16.2. デフォルトスケジューリング
16.2.1. 概要
OpenShift Container Platform のデフォルトの Pod スケジューラーは、クラスター内のノードにおける新規 Pod の配置場所を判別します。スケジューラーは Pod からのデータを読み取り、設定されるポリシーに基づいて適切なノードを見つけようとします。これは完全に独立した機能であり、スタンドアロン/プラグ可能ソリューションです。Pod を変更することはなく、Pod を特定ノードに関連付ける Pod のバインディングのみを作成します。
16.2.2. 汎用スケジューラー
既存の汎用スケジューラーはプラットフォームで提供されるデフォルトのスケジューラー エンジン であり、Pod をホストするノードを 3 つの手順で選択します。
- スケジューラーは 述語を使用して不適切なノードをフィルターに掛けて除外します。
- スケジューラーは ノードのフィルターされた一覧の優先順位付けを行います。
- スケジューラーは、Pod の 最も優先順位の高い Pod を選択します。
16.2.3. ノードのフィルター
利用可能なノードは、指定される制約や要件に基づいてフィルターされます。フィルターは、各ノードで 述語 というフィルター関数の一覧を使用して実行されます。
16.2.3.1. フィルターされたノード一覧の優先順位付け
優先順位付けは、各ノードに一連の 優先度関数 を実行することによって行われます。この関数は 0 -10 までのスコアをノードに割り当て、0 は不適切であることを示し、10 は Pod のホストに適していることを示します。スケジューラー設定は、それぞれの優先度関数について単純な 重み (正の数値) を取ることができます。各優先度関数で指定されるノードのスコアは重み (ほとんどの優先度のデフォルトの重みは 1) で乗算され、すべての優先度で指定されるそれぞれのノードのスコアを追加して組み合わされます。この重み属性は、一部の優先度により重きを置くようにするなどの目的で管理者によって使用されます。
16.2.3.2. 最適ノードの選択
ノードの並び替えはそれらのスコアに基づいて行われ、最高のスコアを持つノードが Pod をホストするように選択されます。複数のノードに同じ高スコアが付けられている場合、それらのいずれかがランダムに選択されます。
16.2.4. スケジューラーポリシー
述語 と 優先度 の選択によって、スケジューラーのポリシーが定義されます。
スケジューラー設定ファイルは、スケジューラーが反映する述語と優先度を指定する JSON ファイルです。
スケジューラーポリシーファイルがない場合、デフォルトの設定ファイル /etc/origin/master/scheduler.json が適用されます。
スケジューラー設定ファイルで定義される述語および優先度は、デフォルトのスケジューラーポリシーを完全に上書きします。デフォルトの述語および優先度のいずれかが必要な場合、スケジューラー設定ファイルにその関数を明示的に指定する必要があります。
デフォルトのスケジューラー設定ファイル
{ "apiVersion": "v1", "kind": "Policy", "predicates": [ { "name": "NoVolumeZoneConflict" }, { "name": "MaxEBSVolumeCount" }, { "name": "MaxGCEPDVolumeCount" }, { "name": "MaxAzureDiskVolumeCount" }, { "name": "MatchInterPodAffinity" }, { "name": "NoDiskConflict" }, { "name": "GeneralPredicates" }, { "name": "PodToleratesNodeTaints" }, { "argument": { "serviceAffinity": { "labels": [ "region" ] } }, "name": "Region" } ], "priorities": [ { "name": "SelectorSpreadPriority", "weight": 1 }, { "name": "InterPodAffinityPriority", "weight": 1 }, { "name": "LeastRequestedPriority", "weight": 1 }, { "name": "BalancedResourceAllocation", "weight": 1 }, { "name": "NodePreferAvoidPodsPriority", "weight": 10000 }, { "name": "NodeAffinityPriority", "weight": 1 }, { "name": "TaintTolerationPriority", "weight": 1 }, { "argument": { "serviceAntiAffinity": { "label": "zone" } }, "name": "Zone", "weight": 2 } ] }
16.2.4.1. スケジューラーポリシーの変更
デフォルトで、スケジューラーポリシーはマスター設定ファイルの kubernetesMasterConfig.schedulerConfigFile
フィールドで上書きされない限り、/etc/origin/master/scheduler.json というマスターのファイルの定義されます。
変更されたスケジューラー設定ファイルのサンプル
kind: "Policy" version: "v1" "predicates": [ { "name": "PodFitsResources" }, { "name": "NoDiskConflict" }, { "name": "MatchNodeSelector" }, { "name": "HostName" }, { "argument": { "serviceAffinity": { "labels": [ "region" ] } }, "name": "Region" } ], "priorities": [ { "name": "LeastRequestedPriority", "weight": 1 }, { "name": "BalancedResourceAllocation", "weight": 1 }, { "name": "ServiceSpreadingPriority", "weight": 1 }, { "argument": { "serviceAntiAffinity": { "label": "zone" } }, "name": "Zone", "weight": 2 } ]
スケジューラーポリシーを変更するには、以下を実行します。
- 必要な デフォルトの述語および優先度 を設定するためにスケジューラー設定ファイルを編集します。カスタム設定を作成したり、サンプルのポリシー設定 のいずれかを使用または変更したりすることができます。
- 必要な 設定可能な述語 と 設定可能な優先度 を追加します。
変更を有効にするために OpenShift Container Platform を再起動します。
# master-restart api # master-restart controllers
16.2.5. 利用可能な述語
述語は、不適切なノードをフィルターに掛けるルールです。
OpenShift Container Platform には、デフォルトでいくつかの述語が提供されています。これらの述語の一部は、特定のパラメーターを指定してカスタマイズできます。複数の述語を組み合わせてノードの追加フィルターを指定できます。
16.2.5.1. 静的な述語
これらの述語はユーザーから設定パラメーターまたは入力を取りません。これらはそれぞれの正確な名前を使用してスケジューラー設定に指定されます。
16.2.5.1.1. デフォルトの述語
デフォルトのスケジューラーポリシーには以下の述語が含まれます。
NoVolumeZoneConflict は、Pod が要求するボリュームがゾーンで利用可能であることを確認します。
{"name" : "NoVolumeZoneConflict"}
MaxEBSVolumeCount は、AWS インスタンスに割り当てることのできるボリュームの最大数を確認します。
{"name" : "MaxEBSVolumeCount"}
MaxGCEPDVolumeCount は、Google Compute Engine (GCE) 永続ディスク (PD) の最大数を確認します。
{"name" : "MaxGCEPDVolumeCount"}
MatchInterPodAffinity は、Pod のアフィニティー/非アフィニティールールが Pod を許可するかどうかを確認します。
{"name" : "MatchInterPodAffinity"}
NoDiskConflict は、Pod が要求するボリュームが利用可能であるかどうかを確認します。
{"name" : "NoDiskConflict"}
PodToleratesNodeTaints は Pod がノードのテイントを許容できるかどうかを確認します。
{"name" : "PodToleratesNodeTaints"}
16.2.5.1.2. 他の静的な述語
OpenShift Container Platform は以下の述語もサポートしています。
CheckVolumeBinding は、バインドされた PVC とバインドされていない PVC の両方について、Pod が要求するボリュームに基づいて Pod が適切かどうかを評価します。* バインドされる PVC の場合、述語は対応する PV のノードアフィニティーが指定ノードで満たされていることを確認します。* バインドされない PVC の場合、述語は PVC 要件を満たし、PV ノードのアフィニティーが指定ノードで満たされる利用可能な PV を検索します。
述語は、すべてのバインドされる PVC にノードと互換性のある PV がある場合や、すべてのバインドされていない PVC が利用可能なノードとの互換性のある PV に一致する場合に true を返します。
{"name" : "CheckVolumeBinding"}
CheckVolumeBinding
述語は、デフォルト以外のスケジューラーで有効にする必要があります。
CheckNodeCondition は、out of disk (ディスク不足)、network unavailable (ネットワークが使用不可)、または not ready (準備できていない) 状態を報告するノードで Pod をスケジュールできるかどうかを確認します。
{"name" : "CheckNodeCondition"}
PodToleratesNodeNoExecuteTaints は、Pod の容認がノードの NoExecute テイントを容認できるかどうかを確認します。
{"name" : "PodToleratesNodeNoExecuteTaints"}
CheckNodeLabelPresence は、すべての指定されたラベルがノードに存在するかどうかを確認します (その値が何であるかは問わない)。
{"name" : "CheckNodeLabelPresence"}
checkServiceAffinity は、ServiceAffinity ラベルがノードでスケジュールされる Pod について同種のものであることを確認します。
{"name" : "checkServiceAffinity"}
MaxAzureDiskVolumeCount は Azure ディスクボリュームの最大数を確認します。
{"name" : "MaxAzureDiskVolumeCount"}
16.2.5.2. 汎用的な述語
以下の汎用的な述語は、非クリティカル述語とクリティカル述語が渡されるかどうかを確認します。非クリティカル述語は、非 Critical Pod のみが渡す必要のある述語であり、クリティカル述語はすべての Pod が渡す必要のある述語です。
デフォルトのスケジューラーポリシーには、この汎用的な述語が含まれます。
汎用的な非クリティカル述語
PodFitsResources は、リソースの可用性 (CPU、メモリー、GPU など) に基づいて適切な候補を判別します。ノードはそれらのリソース容量を宣言し、Pod は要求するリソースを指定できます。使用されるリソースではなく、要求されるリソースに基づいて適切な候補が判別されます。
{"name" : "PodFitsResources"}
必須の汎用的な述語
PodFitsHostPorts は、ノードに要求される Pod ポートの空きポートがある (ポートの競合がない) かどうかを判別します。
{"name" : "PodFitsHostPorts"}
HostName は、ホストパラメーターの有無と文字列のホスト名との一致に基づいて適切なノードを判別します。
{"name" : "HostName"}
MatchNodeSelector は、Pod で定義される ノードセレクター (nodeSelector) のクエリーに基づいて適したノードを判別します。
{"name" : "MatchNodeSelector"}
16.2.5.3. 設定可能な述語
これらの述語はスケジューラー設定 /etc/origin/master/scheduler.json (デフォルト) に設定し、述語の機能に影響を与えるラベルを追加することができます。
これらは設定可能であるため、ユーザー定義の名前が異なる限り、同じタイプ (ただし設定パラメーターは異なる) の複数の述語を組み合わせることができます。
これらの優先度の使用方法についての情報は、スケジューラーポリシーの変更 を参照してください。
ServiceAffinity は、Pod で実行されるサービスに基づいて Pod をノードに配置します。同じノードまたは併置されているノードに同じサービスの複数の Pod を配置すると、効率が向上する可能性があります。
この述語は ノードセレクター の特定ラベルを持つ Pod を同じラベルを持つノードに配置しようとします。
Pod がノードセレクターでラベルを指定していない場合、最初の Pod は可用性に基づいて任意のノードに配置され、該当サービスの後続のすべての Pod はそのノードと同じラベルの値を持つノードにスケジュールされます。
"predicates":[ { "name":"<name>", 1 "argument":{ "serviceAffinity":{ "labels":[ "<label>" 2 ] } } } ],
以下に例を示します。
"name":"ZoneAffinity", "argument":{ "serviceAffinity":{ "labels":[ "rack" ] } }
たとえば、ノードセレクター rack
を持つサービスの最初の Pod がラベル region=rack
を持つノードにスケジュールされている場合、同じサービスに属するその他すべての後続の Pod は同じ region=rack
ラベルを持つノードにスケジュールされます。詳細は、Pod 配置の制御 を参照してください。
複数レベルのラベルもサポートされています。ユーザーは同じリージョン内および (リージョン下の) 同じゾーン内のノードでスケジュールされるようサービスのすべての Pod を指定することもできます。
labelsPresence
パラメーターは特定のノードに特定のラベルがあるかどうかをチェックします。ラベルは、LabelPreference
の優先順位が使用するノード グループ を作成します。ラベルでのマッチングは、ノードにラベルで定義されている物理的な場所またはステータスがある場合などに役立ちます。
"predicates":[ { "name":"<name>", 1 "argument":{ "labelsPresence":{ "labels":[ "<label>" 2 ], "presence": true 3 } } } ],
以下に例を示します。
"name":"RackPreferred", "argument":{ "labelsPresence":{ "labels":[ "rack", "region" ], "presence": true } }
16.2.6. 利用可能な優先度
優先度は、設定に応じて残りのノードにランクを付けるルールです。
優先度のカスタムセットは、スケジューラーを設定するために指定できます。OpenShift Container Platform ではデフォルトでいくつかの優先度があります。他の優先度は、特定のパラメーターを指定してカスタマイズできます。優先順位に影響を与えるために、複数の優先度を組み合わせ、異なる重みをそれぞれのノードに指定することができます。
16.2.6.1. 静的優先度
静的優先度は、重みを除き、ユーザーからいずれの設定パラメーターも取りません。重みは指定する必要があり、0 または負の値にすることはできません。
これらはスケジューラー設定 /etc/origin/master/scheduler.json (デフォルト) に指定されます。
16.2.6.1.1. デフォルトの優先度
デフォルトのスケジューラーポリシーには、以下の優先度が含まれています。それぞれの優先度関数は、重み 10000
を持つ NodePreferAvoidPodsPriority
以外は重み 1
を持ちます。
SelectorSpreadPriority は、Pod に一致するサービス、レプリケーションコントローラー (RC)、レプリケーションセット (RS)、およびステートフルなセットを検索し、次にそれらのセレクターに一致する既存の Pod を検索します。スケジューラーは、一致する既存の Pod が少ないノードを優先します。次に、Pod のスケジュール時に、それらのセレクターに一致する Pod 数の最も少ないノードで Pod をスケジュールします。
{"name" : "SelectorSpreadPriority", "weight" : 1}
InterPodAffinityPriority は、ノードの対応する PodAffinityTerm が満たされている場合に weightedPodAffinityTerm
要素を使った繰り返し処理や 重み の合計への追加によって合計を計算します。合計値の最も高いノードが最も優先されます。
{"name" : "InterPodAffinityPriority", "weight" : 1}
LeastRequestedPriority は要求されたリソースの少ないノードを優先します。これは、ノードでスケジュールされる Pod によって要求されるメモリーおよび CPU のパーセンテージを計算し、利用可能な/残りの容量の値の最も高いノードを優先します。
{"name" : "LeastRequestedPriority", "weight" : 1}
BalancedResourceAllocation は、均衡が図られたリソース使用率に基づいてノードを優先します。これは、容量の一部として消費済み CPU とメモリー間の差異を計算し、2 つのメトリクスがどの程度相互に近似しているかに基づいてノードの優先度を決定します。これは常に LeastRequestedPriority
と併用する必要があります。
{"name" : "BalancedResourceAllocation", "weight" : 1}
NodePreferAvoidPodsPriority は、レプリケーションコントローラー以外のコントローラーによって所有される Pod を無視します。
{"name" : "NodePreferAvoidPodsPriority", "weight" : 10000}
NodeAffinityPriority は、ノードアフィニティーのスケジューリング設定に応じてノードの優先順位を決定します。
{"name" : "NodeAffinityPriority", "weight" : 1}
TaintTolerationPriority は、Pod についての 容認不可能な テイント数の少ないノードを優先します。容認不可能なテイントとはキー PreferNoSchedule
のあるテイントのことです。
{"name" : "TaintTolerationPriority", "weight" : 1}
16.2.6.1.2. 他の静的優先度
OpenShift Container Platform は以下の優先度もサポートしています。
EqualPriority は、優先度の設定が指定されていない場合に、すべてのノードに等しい重み 1
を指定します。この優先順位はテスト環境にのみ使用することを推奨します。
{"name" : "EqualPriority", "weight" : 1}
MostRequestedPriority は、要求されたリソースの最も多いノードを優先します。これは、ノードでスケジュールされる Pod で要求されるメモリーおよび CPU のパーセンテージを計算し、容量に対して要求される部分の平均の最大値に基づいて優先度を決定します。
{"name" : "MostRequestedPriority", "weight" : 1}
ImageLocalityPriority は、Pod コンテナーのイメージをすでに要求しているノードを優先します。
{"name" : "ImageLocalityPriority", "weight" : 1}
ServiceSpreadingPriority は、同じマシンに置かれる同じサービスに属する Pod 数を最小限にすることにより Pod を分散します。
{"name" : "ServiceSpreadingPriority", "weight" : 1}
16.2.6.2. 設定可能な優先度
これらの優先度は、デフォルトでスケジューラー設定 /etc/origin/master/scheduler.json で設定し、これらの優先度に影響を与えるラベルを追加できます。
優先度関数のタイプは、それらが取る引数によって識別されます。これらは設定可能なため、ユーザー定義の名前が異なる場合に、同じタイプの (ただし設定パラメーターは異なる) 設定可能な複数の優先度を組み合わせることができます。
これらの優先度の使用方法についての情報は、スケジューラーポリシーの変更 を参照してください。
ServiceAntiAffinity はラベルを取り、ラベルの値に基づいてノードのグループ全体に同じサービスに属する Pod を適正に分散します。これは、指定されたラベルの同じ値を持つすべてのノードに同じスコアを付与します。また Pod が最も集中していないグループ内のノードにより高いスコアを付与します。
"priorities":[ { "name":"<name>", 1 "weight" : 1 2 "argument":{ "serviceAntiAffinity":{ "label":[ "<label>" 3 ] } } } ]
以下に例を示します。
"name":"RackSpread", 1 "weight" : 1 2 "argument":{ "serviceAntiAffinity":{ "label": "rack" 3 } }
カスタムラベルに基づいて ServiceAntiAffinity
を使用しても Pod を予想通りに展開できない場合があります。Red Hat ソリューション を参照してください。
*labelPreference
パラメーターは指定されたラベルに基づいて優先順位を指定します。ラベルがノードにある場合、そのノードに優先度が指定されます。ラベルが指定されていない場合、優先度はラベルを持たないノードに指定されます。
"priorities":[ { "name":"<name>", 1 "weight" : 1, 2 "argument":{ "labelPreference":{ "label": "<label>", 3 "presence": true 4 } } } ]
16.2.7. 使用例
OpenShift Container Platform 内でのスケジューリングの重要な使用例として、柔軟なアフィニティーと非アフィニティーポリシーのサポートを挙げることができます。
16.2.7.1. インフラストラクチャーのトポロジーレベル
管理者は、ノードのラベル (例: region=r1
、zone=z1
、rack=s1
) を指定してインフラストラクチャーの複数のトポロジーレベルを定義することができます。
これらのラベル名には特別な意味はなく、管理者はそれらのインフラストラクチャーラベルに任意の名前 (例: 都市/建物/部屋) を付けることができます。また、管理者はインフラストラクチャートポロジーに任意の数のレベルを定義できます。通常は、(regions
→ zones
→ racks
) などの 3 つのレベルが適切なサイズです。管理者はこれらのレベルのそれぞれにアフィニティーと非アフィニティールールを任意の組み合わせで指定することができます。
16.2.7.2. アフィニティー
管理者は、任意のトポロジーレベルまたは複数のレベルでもアフィニティーを指定できるようにスケジューラーを設定することができます。特定レベルのアフィニティーは、同じサービスに属するすべての Pod が同じレベルに属するノードにスケジュールされることを示します。これは、管理者がピア Pod が地理的に離れ過ぎないようにすることでアプリケーションの待機時間の要件に対応します。同じアフィニティーグループ内で Pod をホストするために利用できるノードがない場合、Pod はスケジュールされません。
Pod がスケジュールされる場所に対する制御を強化する必要がある場合は、ノードアフィニティーの使用 および Pod のアフィニティーおよび非アフィニティーの使用 を参照してください。これらの詳細スケジューリング機能により、管理者は Pod をスケジュールできるノードを指定し、他の Pod に関連してスケジューリングを強制的に実行したり、拒否したりできます。
16.2.7.3. 非アフィニティー
管理者は、任意のトポロジーレベルまたは複数のレベルでも非アフィニティーを設定できるようスケジューラーを設定することができます。特定レベルの非アフィニティー (または分散) は、同じサービスに属するすべての Pod が該当レベルに属するノード全体に分散されることを示します。これにより、アプリケーションが高可用性の目的で適正に分散されます。スケジューラーは、可能な限り均等になるようにすべての適用可能なノード全体にサービス Pod を配置しようとします。
Pod がスケジュールされる場所に対する制御を強化する必要がある場合は、ノードアフィニティーの使用 および Pod のアフィニティーおよび非アフィニティーの使用 を参照してください。これらの詳細スケジューリング機能により、管理者は Pod をスケジュールできるノードを指定し、他の Pod に関連してスケジューリングを強制的に実行したり、拒否したりできます。
16.2.8. ポリシー設定のサンプル
以下の設定は、スケジューラーポリシーファイルを使って指定される場合のデフォルトのスケジューラー設定を示しています。
kind: "Policy" version: "v1" predicates: ... - name: "RegionZoneAffinity" 1 argument: serviceAffinity: 2 labels: 3 - "region" - "zone" priorities: ... - name: "RackSpread" 4 weight: 1 argument: serviceAntiAffinity: 5 label: "rack" 6
以下の設定例のいずれの場合も、述語と優先度関数の一覧は、指定された使用例に関連するもののみを含むように切り捨てられます。実際には、完全な/分かりやすいスケジューラーポリシーには、上記のデフォルトの述語および優先度のほとんど (すべてではなくても) が含まれるはずです。
以下の例は、region (affinity) → zone (affinity) → rack (anti-affinity) の 3 つのトポロジーレベルを定義します。
kind: "Policy" version: "v1" predicates: ... - name: "RegionZoneAffinity" argument: serviceAffinity: labels: - "region" - "zone" priorities: ... - name: "RackSpread" weight: 1 argument: serviceAntiAffinity: label: "rack"
以下の例は、city (affinity) → building (anti-affinity) → room (anti-affinity) の 3 つのトポロジーレベルを定義します。
kind: "Policy" version: "v1" predicates: ... - name: "CityAffinity" argument: serviceAffinity: labels: - "city" priorities: ... - name: "BuildingSpread" weight: 1 argument: serviceAntiAffinity: label: "building" - name: "RoomSpread" weight: 1 argument: serviceAntiAffinity: label: "room"
以下の例では、region ラベルが定義されたノードのみを使用し、zone ラベルが定義されたノードを優先するポリシーを定義します。
kind: "Policy" version: "v1" predicates: ... - name: "RequireRegion" argument: labelsPresence: labels: - "region" presence: true priorities: ... - name: "ZonePreferred" weight: 1 argument: labelPreference: label: "zone" presence: true
以下の例では、静的および設定可能な述語および優先度を組み合わせています。
kind: "Policy" version: "v1" predicates: ... - name: "RegionAffinity" argument: serviceAffinity: labels: - "region" - name: "RequireRegion" argument: labelsPresence: labels: - "region" presence: true - name: "BuildingNodesAvoid" argument: labelsPresence: labels: - "building" presence: false - name: "PodFitsPorts" - name: "MatchNodeSelector" priorities: ... - name: "ZoneSpread" weight: 2 argument: serviceAntiAffinity: label: "zone" - name: "ZonePreferred" weight: 1 argument: labelPreference: label: "zone" presence: true - name: "ServiceSpreadingPriority" weight: 1
16.3. 再スケジュール (Descheduling)
16.3.1. 概要
再スケジュール (Descheduling) には、Pod がより適切なノードに再スケジュールされるように 特定のポリシー に基づいて Pod をエビクトすることが関係しています。
クラスターは、さまざまな理由で、すでに実行中の Pod のスケジュールを解除および再スケジュールすることで恩恵を受けることができます。
- ノードの使用率が低くなっているか、または高くなっている。
- テイントまたはラベルなどの、Pod およびノードアフィニティーの各種要件が変更され、当初のスケジューリングの意思決定が特定のノードに適さなくなっている。
- ノードの障害により、Pod を移動する必要がある。
- 新規ノードがクラスターに追加されている。
Descheduler はエビクトされた Pod の置き換えをスケジュールしません。スケジューラー は、エビクトされた Pod に対してこのタスクを自動的に実行します。
DNS など、クラスターの完全な機能に欠かせないコアコンポーネントであるものの、マスターではなく通常のクラスターノードで実行されるコアコンポーネントが多数あることに留意する必要があります。クラスターはコンポーネントがエビクトされると正常な機能を停止する可能性があります。Descheduler がこれらの Pod を削除することを防ぐには、 scheduler.alpha.kubernetes.io/critical-pod
アノテーションを Pod 仕様に追加して、Pod を Critical Pod として設定します。
Descheduler ジョブは Critical Pod としてみなされ、これは Descheduler Pod が Descheduler のエビクトの対象になることを防ぎます。
Descheduler ジョブおよび Descheduler Pod は、デフォルトで作成される kube-system
プロジェクトに作成されます。
descheduler はテクノロジープレビュー機能です。テクノロジープレビュー機能は、Red Hat の実稼働環境でのサービスレベルアグリーメント (SLA) ではサポートされていないため、Red Hat では実稼働環境での使用を推奨していません。テクノロジープレビューの機能は、最新の製品機能をいち早く提供して、開発段階で機能のテストを行いフィードバックを提供していただくことを目的としています。
Red Hat のテクノロジープレビュー機能のサポートについての詳細は、https://access.redhat.com/support/offerings/techpreview/ を参照してください。
Descheduler は以下のタイプの Pod をエビクトしません。
-
Critical Pod (
scheduler.alpha.kubernetes.io/critical-pod
アノテーションを持つ)。 - レプリカセット、レプリケーションコントローラー、デプロイメント、またはジョブに関連付けられていない Pod (静的およびミラー Pod またはスタンドアロンモードの Pod) (これらの Pod 再作成されないため)。
- DaemonSet に関連付けられた Pod。
- ローカルストレージを持つ Pod。
- Pod の Disruption Budget (PDB) が適用される Pod は、スケジュール解除が PDB に違反する場合にエビクトされません。Pod は、エビクションポリシー を使用してエビクトできます。
Best Effort Pod は、Burstable および Guaranteed Pod の前にエビクトされます。
以下のセクションでは、Descheduler を設定し、実行するプロセスについて説明します。
- ロールを作成します。
- ポリシーファイル にスケジュール解除動作を定義します。
- ポリシーファイルを参照するための参照マップ を作成します。
- Descheduler ジョブ設定 を作成します。
- Descheduler ジョブを実行します。
16.3.2. クラスターロールの作成
Descheduler が Pod で機能するために必要なパーミッションを設定するには、以下を実行します。
以下のルールで クラスターロール を作成します。
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: descheduler-cluster-role rules: - apiGroups: [""] resources: ["nodes"] verbs: ["get", "watch", "list"] 1 - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list", "delete"] 2 - apiGroups: [""] resources: ["pods/eviction"] 3 verbs: ["create"]
ジョブを実行するために使用される サービスアカウント を作成します。
# oc create sa <file-name>.yaml -n kube-system
以下に例を示します。
# oc create sa descheduler-sa.yaml -n kube-system
クラスターロールをサービスアカウントにバインドします。
# oc create clusterrolebinding descheduler-cluster-role-binding \ --clusterrole=<cluster-role-name> \ --serviceaccount=kube-system:<service-account-name>
以下に例を示します。
# oc create clusterrolebinding descheduler-cluster-role-binding \ --clusterrole=descheduler-cluster-role \ --serviceaccount=kube-system:descheduler-sa
16.3.3. Descheduler ポリシーの作成
Descheduler は、YAML ポリシーファイルの strategies で定義されるルールに違反するノードから Pod を削除するように設定できます。次に、設定マップを使用して特定のスケジュール解除ストラテジーを適用するためにポリシーファイルへのパスと ジョブ仕様 が含まれる 設定マップ を作成します。
Descheduler ポリシーファイルのサンプル
apiVersion: "descheduler/v1alpha1" kind: "DeschedulerPolicy" strategies: "RemoveDuplicates": enabled: false "LowNodeUtilization": enabled: true params: nodeResourceUtilizationThresholds: thresholds: "cpu" : 20 "memory": 20 "pods": 20 targetThresholds: "cpu" : 50 "memory": 50 "pods": 50 numberOfNodes: 3 "RemovePodsViolatingInterPodAntiAffinity": enabled: true "RemovePodsViolatingNodeAffinity": enabled: true params: nodeAffinityType: - "requiredDuringSchedulingIgnoredDuringExecution"
Descheduler で使用できるデフォルトストラテジーとして、3 つのストラテジーがあります。
ストラテジーに関連付けられたパラメーターを必要に応じて設定し、無効にすることができます。
16.3.3.1. 重複 Pod の削除
RemoveDuplicates
ストラテジーでは、1 つの Pod のみが同じノードで実行されている レプリカセット、レプリケーションコントローラー、デプロイメント設定、または ジョブ に関連付けられます。これらのオブジェクトに関連付けられている他の Pod がある場合、重複 Pod はエビクトされます。重複 Pod をエビクトすると、Pod をクラスター内により効果的に分散できます。
たとえば、ノードが失敗し、ノード上の Pod が別のノードに移行した場合に、複数の Pod が同じノードで実行されているレプリカセットまたはレプリケーションコントローラーに関連付けられると、重複 Pod が発生する可能性があります。失敗したノードが再び準備可能になると、それらの重複 Pod をエビクトするためにこのストラテジーが使用される可能性があります。
このストラテジーに関連付けられるパラメーターはありません。
apiVersion: "descheduler/v1alpha1"
kind: "DeschedulerPolicy"
strategies:
"RemoveDuplicates":
enabled: false 1
- 1
- このポリシーを使用するには、この値を
enabled: true
に設定します。このポリシーを無効にするには、false
に設定します。
16.3.3.2. ノードの低使用率ポリシー (Low Node Utilization Policy) の作成
LowNodeUtilization
ストラテジーは、使用率の低いノードを検出し、他のノードから Pod をエビクトして、エビクトされた Pod がそれらの使用率の低いノードにスケジュールされるようにします。
ノードの使用率は、CPU、メモリーまたは Pod 数の設定可能なしきい値 thresholds
(パーセンテージベース) で決定されます。ノードの使用率がこれらのしきい値のすべてを下回る場合、ノードの使用率は低いとみなされ、Descheduler は Pod を他のノードからエビクトする可能性があります。Pod の要求リソース要件は、ノードのリソース使用率を計算する際に考慮されます。
高いしきい値の targetThresholds
は、使用率が適性なノードを判別するために使用されます。thresholds と targetThresholds 間にあるノードの使用率は適性であるとみなされ、エビクションの対象にはなりません。しきい値 targetThresholds
は、CPU、メモリーおよび Pod 数について設定できます (パーセンテージベース)。
これらのしきい値はクラスター要件に合わせて調整できます。
numberOfNodes
パラメーターは、使用率の低いノードの数が設定された値を上回る場合にのみストラテジーをアクティブにするために設定できます。いくつかのノードの使用率が低くなることが許容される場合にこのパラメーターを設定します。デフォルトで、numberOfNodes
はゼロに設定されます。
apiVersion: "descheduler/v1alpha1" kind: "DeschedulerPolicy" strategies: "LowNodeUtilization": enabled: true params: nodeResourceUtilizationThresholds: thresholds: 1 "cpu" : 20 "memory": 20 "pods": 20 targetThresholds: 2 "cpu" : 50 "memory": 50 "pods": 50 numberOfNodes: 3 3
16.3.3.3. Pod 間の非アフィニティー (Inter-Pod Anti-Affinity) に違反する Pod の削除
RemovePodsViolatingInterPodAntiAffinity
ストラテジーは、Pod 間の非アフィニティー (inter-pod anti-affinity) に違反する Pod がノードから削除されるようにします。
たとえば、Node1 には、podA、podB、および podC があります。podB および podC には非アフィニティールールがあり、これにより podA と同じノードでの実行が禁止されます。podA はノードからエビクトされ、podB および podC がそのノードで実行できるようになります。この状況は、podB および podC がノード上で実行されている際に、非アフィニティールールが適用される場合に生じます。
apiVersion: "descheduler/v1alpha1"
kind: "DeschedulerPolicy"
strategies:
"RemovePodsViolatingInterPodAntiAffinity": 1
enabled: true
- 1
- このポリシーを使用するには、この値を
enabled: true
に設定します。このポリシーを無効にするには、false
に設定します。
16.3.3.4. ノードアフィニティーに違反する Pod の削除
RemovePodsViolatingNodeAffinity
ストラテジーにより、ノードアフィニティーに違反するすべての Pod がノードから確実に削除されます。この状態は、ノードが Pod のアフィニティールールを満たさなくなる場合に生じる可能性があります。アフィニティールールを満たす別のノードが利用可能な場合、Pod はエビクトされます。
たとえば、podA は、スケジューリング時に requiredDuringSchedulingIgnoredDuringExecution
ノードアフィニティールールを満たしているために nodeA にスケジュールされます。nodeA がルールの条件を満たさなくなり、ノードアフィニティールールを満たす別のノードが利用可能な場合は、ストラテジーは nodeA から podA をエビクトし、これを他のノードに移動します。
apiVersion: "descheduler/v1alpha1" kind: "DeschedulerPolicy" strategies: "RemovePodsViolatingNodeAffinity": 1 enabled: true params: nodeAffinityType: - "requiredDuringSchedulingIgnoredDuringExecution" 2
16.3.4. Descheduler ポリシーの設定マップの作成
kube-system
プロジェクトで Descheduler ポリシーファイルの 設定マップ を作成し、これが Descheduler ジョブで参照されるようにします。
# oc create configmap descheduler-policy-configmap \
-n kube-system --from-file=<path-to-policy-dir/policy.yaml> 1
- 1
- 作成したポリシーファイルのパスです。
16.3.5. ジョブ仕様の作成
Descheduler の ジョブ設定 を作成します。
apiVersion: batch/v1 kind: Job metadata: name: descheduler-job namespace: kube-system spec: parallelism: 1 completions: 1 template: metadata: name: descheduler-pod 1 annotations: scheduler.alpha.kubernetes.io/critical-pod: "true" 2 spec: containers: - name: descheduler image: registry.access.redhat.com/openshift3/ose-descheduler volumeMounts: 3 - mountPath: /policy-dir name: policy-volume command: - "/bin/sh" - "-ec" - | /bin/descheduler --policy-config-file /policy-dir/policy.yaml 4 restartPolicy: "Never" serviceAccountName: descheduler-sa 5 volumes: - name: policy-volume configMap: name: descheduler-policy-configmap
ポリシーファイルは、設定マップからボリュームとしてマウントされます。
16.3.6. Descheduler の実行
Descheduler を Pod のジョブとして実行するには、以下を実行します。
# oc create -f <file-name>.yaml
以下に例を示します。
# oc create -f descheduler-job.yaml
16.4. カスタムスケジューリング
16.4.1. 概要
デフォルトのスケジューラーと共に複数のカスタムスケジューラーを実行し、各 Pod に使用できるスケジューラーを設定できます。
特定のスケジューラーを使用して指定された Pod をスケジュールするには、Pod 仕様にスケジューラーの名前を指定します。
スケジューラーバイナリーの作成方法に関する情報は、本書では扱っておりません。たとえば、Kubernetes ドキュメントの Configure Multiple Schedulers を参照してください。
16.4.2. スケジューラーのパッケージ化
クラスターにカスタムスケジューラーを含む一般的なプロセスでは、イメージを作成し、そのイメージをデプロイメントに含める必要があります。
- スケジューラーバイナリーをコンテナーイメージにパッケージ化します。
スケジューラーバイナリーを含む コンテナーイメージを作成します。
以下に例を示します。
FROM <source-image> ADD <path-to-binary> /usr/local/bin/kube-scheduler
ファイルを Dockerfile として保存し、イメージをビルドし、レジストリーにプッシュします。
以下に例を示します。
docker build -t <dest_env_registry_ip>:<port>/<namespace>/<image name>:<tag> docker push <dest_env_registry_ip>:<port>/<namespace>/<image name>:<tag>
OpenShift Container Platform で、カスタムスケジューラーのデプロイメントを作成します。
apiVersion: v1 kind: ServiceAccount metadata: name: custom-scheduler namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: custom-scheduler subjects: - kind: ServiceAccount name: custom-scheduler namespace: kube-system roleRef: kind: ClusterRole name: system:kube-scheduler apiGroup: rbac.authorization.k8s.io --- apiVersion: apps/v1 kind: Deployment metadata: name: custom-scheduler namespace: kube-system labels: app: custom-scheduler spec: replicas: 1 selector: matchLabels: app: custom-scheduler template: metadata: labels: app: custom-scheduler spec: serviceAccount: custom-scheduler containers: - name: custom-scheduler image: "<namespace>/<image name>:<tag>" 1 imagePullPolicy: Always
- 1
- カスタムスケジューラー用に作成したコンテナーイメージを指定します。
16.4.3. カスタムスケジューラーを使用した Pod のデプロイ
カスタムスケジューラーをクラスターにデプロイした後、デフォルトのスケジューラーではなくそのスケジューラーを使用するように Pod を設定できます。
Pod 設定を作成するか、または編集し、
schedulerName
パラメーターでスケジューラーの名前を指定します。名前は一意である必要があります。スケジューラーを含む Pod 仕様のサンプル
apiVersion: v1 kind: Pod metadata: name: custom-scheduler-example labels: name: custom-scheduler-example spec: schedulerName: custom-scheduler 1 containers: - name: pod-with-second-annotation-container image: docker.io/ocpqe/hello-pod
- 1
- 使用するスケジューラーの名前です。スケジューラー名が指定されていない場合、Pod はデフォルトのスケジューラーを使用して自動的にスケジュールされます。
以下のコマンドを実行して Pod を作成します。
$ oc create -f <file-name>.yaml
以下に例を示します。
$ oc create -f custom-scheduler-example.yaml
以下のコマンドを実行して、Pod が作成されていることを確認します。
$ oc get pod <file-name>
以下に例を示します。
$ oc get pod custom-scheduler-example NAME READY STATUS RESTARTS AGE custom-scheduler-example 1/1 Running 0 4m
以下のコマンドを実行して、カスタムスケジューラーが Pod をスケジュールしていることを確認します。
$ oc describe pod <pod-name>
以下に例を示します。
$ oc describe pod custom-scheduler-example
以下の切り捨てられた出力に示されるように、スケジューラーの名前が一覧表示されます。
... Events: FirstSeen LastSeen Count From SubObjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 1m 1m 1 custom-scheduler Normal Scheduled Successfully assigned custom-scheduler to <$node1> ...
16.5. Pod 配置の制御
16.5.1. 概要
クラスター管理者は、特定のロールを持つアプリケーション開発者が Pod のスケジュール時に特定ノードをターゲットとすることを防ぐポリシーを設定できます。
Pod ノード制約の受付コントローラーは、Pod がラベルを使用して指定されたノードホストのみにデプロイされるようにし、特定のロールを持たないユーザーが nodeSelector
フィールドを使用して Pod をスケジュールできないようにします。
16.5.2. ノード名の使用による Pod 配置の制約
Pod ノード制約の受付コントローラーを使用し、Pod にラベルを割り当て、これを Pod 設定の nodeName
設定に指定することで、Pod が指定されたノードホストにのみデプロイされるようにします。
必要なラベル (詳細は、ノードでのラベルの更新 を参照) および ノードセレクター が環境にセットアップされていることを確認します。
たとえば、Pod 設定が必要なラベルを示す
nodeName
値を持つことを確認します。apiVersion: v1 kind: Pod spec: nodeName: <value>
マスター設定ファイル (/etc/origin/master/master-config.yaml) を変更して
PodNodeConstraints
をadmissionConfig
セクションに追加します。... admissionConfig: pluginConfig: PodNodeConstraints: configuration: apiversion: v1 kind: PodNodeConstraintsConfig ...
変更を有効にするために OpenShift Container Platform を再起動します。
# master-restart api # master-restart controllers
16.5.3. ノードセレクターの使用による Pod 配置の制約
ノードセレクター を使用して、Pod が特定のラベルを持つノードにのみ配置されるようにすることができます。クラスター管理者は、Pod ノード制約の受付コントローラーを使用して、pods/binding パーミッションのないユーザーがノードセレクターを使用して Pod をスケジュールできないようにするポリシーを設定できます。
マスター設定ファイルの nodeSelectorLabelBlacklist
フィールドを使用して、一部のロールが Pod 設定の nodeSelector
フィールドで指定できるラベルを制御できます。pods/binding パーミッション ロール を持つユーザー、サービスアカウントおよびグループは任意のノードセレクターを指定できます。pods/binding パーミッションがない場合は、nodeSelectorLabelBlacklist
に表示されるすべてのラベルに nodeSelector
を設定することは禁止されます。
たとえば、OpenShift Container Platform クラスターは、2 つの地域にまたがる 5 つのデータセンターで設定される場合があります。米国の us-east、us-central、および us-west、およびアジア太平洋 (APAC) の apac-east および apac-west です。それぞれの地理的地域の各ノードには、それらに応じたラベルが付けられます。たとえば、region: us-east
のようになります。
ラベルの割り当ての詳細は、ノードでのラベルの更新 を参照してください。
クラスター管理者は、アプリケーション開発者が地理的に最も近い場所にあるノードにのみ Pod をデプロイできるインフラストラクチャーを作成できます。ノードセレクターを作成し、米国のデータセンターを superregion: us
に、APAC のデータセンターを superregion: apac
に分類できます。
データセンターごとのリソースの均等なロードを維持するには、必要な region
をマスター設定の nodeSelectorLabelBlacklist
セクションに追加できます。その後は、米国の開発者が Pod を作成するたびに、Pod は superregion: us
ラベルの付いた地域のいずれかにあるノードにデプロイされます。開発者が Pod に特定の region (地域) をターゲットに設定しようとすると (例: region: us-east
)、エラーが出されます。これを Pod にノードセレクターを設定せずに試行すると、ターゲットとした region (地域) にデプロイすることができます。 それは superregion: us
がプロジェクトレベルのノードセレクターとして設定されており、region: us-east
というラベルが付けられたノードには superregion: us
というラベルも付けられているためです。
必要なラベル (詳細は、ノードでのラベルの更新 を参照) および ノードセレクター が環境にセットアップされていることを確認します。
たとえば、Pod 設定が必要なラベルを示す
nodeSelector
値を持つことを確認します。apiVersion: v1 kind: Pod spec: nodeSelector: <key>: <value> ...
マスター設定ファイル /etc/origin/master/master-config.yaml を変更し、
nodeSelectorLabelBlacklist
を、Pod の配置を拒否する必要のあるノードホストに割り当てられるラベルと共にadmissionConfig
セクションに追加します。... admissionConfig: pluginConfig: PodNodeConstraints: configuration: apiversion: v1 kind: PodNodeConstraintsConfig nodeSelectorLabelBlacklist: - kubernetes.io/hostname - <label> ...
変更を有効にするために OpenShift Container Platform を再起動します。
# master-restart api # master-restart controllers
16.5.4. プロジェクトへの Pod 配置の制御
Pod ノードセレクターの受付コントローラーを使用して、Pod を特定のプロジェクトに関連付けられたノードに対して強制的に適用したり、Pod がそれらのノードでスケジュールされないようにしたりできます。
Pod ノードセレクターの受付コントローラーは、プロジェクトのラベル と Pod で指定されるノードセレクターを使用して Pod を配置する場所を決定します。新規 Pod は、Pod のノードセレクターがプロジェクトのラベルに一致する場合にのみプロジェクトに関連付けられたノードに配置されます。
Pod の作成後に、ノードセレクターは Pod にマージされ、Pod 仕様に元々含まれていたラベルとノードセレクターの新規ラベルが含まれるようにします。以下の例は、マージの結果について示しています。
Pod ノードセレクターの受付コントローラーにより、特定のプロジェクトで許可されるラベルの一覧を作成することもできます。この一覧は開発者がプロジェクトで使用できるラベルを認識するための ホワイトリスト として機能し、管理者がクラスターでのラベル設定の制御を強化するのに役立ちます。
Pod ノードセレクター の受付コントローラーをアクティブにするには、以下を実行します。
以下の方法のいずれかを使用して Pod ノードセレクター の受付コントローラーとホワイトリストを設定します。
以下をマスター設定ファイル (/etc/origin/master/master-config.yaml) に追加します。
admissionConfig: pluginConfig: PodNodeSelector: configuration: podNodeSelectorPluginConfig: 1 clusterDefaultNodeSelector: "k3=v3" 2 ns1: region=west,env=test,infra=fedora,os=fedora 3
受付コントローラーの情報を含むファイルを作成します。
podNodeSelectorPluginConfig: clusterDefaultNodeSelector: "k3=v3" ns1: region=west,env=test,infra=fedora,os=fedora
次に、マスター設定でファイルを参照します。
admissionConfig: pluginConfig: PodNodeSelector: location: <path-to-file>
注記プロジェクトにノードセレクターが指定されていない場合、そのプロジェクトに関連付けられた Pod はデフォルトのノードセレクター (
clusterDefaultNodeSelector
) を使用してマージされます。
変更を有効にするために OpenShift Container Platform を再起動します。
# master-restart api # master-restart controllers
scheduler.alpha.kubernetes.io/node-selector
アノテーションおよびラベルを含むプロジェクトオブジェクトを作成します。apiVersion: v1 kind: Namespace metadata name: ns1 annotations: scheduler.alpha.kubernetes.io/node-selector: env=test,infra=fedora 1 spec: {}, status: {}
- 1
- プロジェクトのラベルセレクターに一致するラベルを作成するためのアノテーションです。ここで、キー/値のラベルは
env=test
およびinfra=fedora
になります。
注記Pod Node Selector 受付コントローラーを使用している場合、プロジェクトノードセレクターを設定するるために
oc adm new-project <project-name>
を設定することはできません。oc adm new-project myproject --node-selector='type=user-node,region=<region>
コマンドを使用してプロジェクトノードセレクターを設定する場合、OpenShift Container Platform はopenshift.io/node-selector
アノテーションを設定します。 これは NodeEnv 受付プラグインで処理されます。ノードセレクターにラベルを含む Pod 仕様を作成します。以下は例になります。
apiVersion: v1 kind: Pod metadata: labels: name: hello-pod name: hello-pod spec: containers: - image: "docker.io/ocpqe/hello-pod:latest" imagePullPolicy: IfNotPresent name: hello-pod ports: - containerPort: 8080 protocol: TCP resources: {} securityContext: capabilities: {} privileged: false terminationMessagePath: /dev/termination-log dnsPolicy: ClusterFirst restartPolicy: Always nodeSelector: 1 env: test os: fedora serviceAccount: "" status: {}
- 1
- プロジェクトラベルに一致するノードセレクター。
プロジェクトに Pod を作成します。
# oc create -f pod.yaml --namespace=ns1
ノードセレクターのラベルが Pod 設定に追加されていることを確認します。
get pod pod1 --namespace=ns1 -o json nodeSelector": { "env": "test", "infra": "fedora", "os": "fedora" }
ノードセレクターは Pod にマージされ、Pod は適切なプロジェクトでスケジュールされます。
プロジェクト仕様で指定されていないラベルを使って Pod を作成する場合、Pod はノードでスケジュールされません。
たとえば、ここでラベル env: production
は、いずれのプロジェクト仕様にも含まれていません。
nodeSelector: "env: production" "infra": "fedora", "os": "fedora"
ノードセレクターのアノテーションのないノードがある場合は、Pod はそこにスケジュールされます。
16.6. Pod の優先順位とプリエンプション
16.6.1. Pod の優先順位およびプリエンプションの適用
クラスターで Pod の優先順位およびプリエンプションを有効にできます。Pod の優先順位は、他の Pod との対比で Pod の重要度を示し、その優先順位に基づいて Pod をキューに入れます。Pod のプリエンプションは、クラスターが優先順位の低い Pod のエビクトまたはプリエンプションを実行することを可能にするため、適切なノードに利用可能な領域がない場合に優先順位のより高い Pod をスケジュールできます。Pod の優先順位は Pod のスケジューリングの順序にも影響を与え、リソース不足の場合のノード上でのエビクションの順序に影響を与えます。
優先順位およびプリエンプションを使用するには、Pod の相対的な重みを定義する優先順位クラスを作成します。次に Pod 仕様で優先順位クラスを参照し、スケジューリングの重みを適用します。
プリエンプションはスケジューラー設定ファイルの disablePreemption
パラメーターで制御されます。 これはデフォルトで false
に設定されます。
16.6.2. Pod の優先順位について
Pod の優先順位およびプリエンプション機能が有効にされる場合、スケジューラーは優先順位に基づいて保留中の Pod を順序付け、保留中の Pod はスケジューリングのキューで優先順位のより低い他の保留中の Pod よりも前に置かれます。その結果、より優先順位の高い Pod は、スケジューリングの要件を満たす場合に優先順位の低い Pod よりも早くスケジュールされる可能性があります。Pod をスケジュールできない場合、スケジューラーは引き続き他の優先順位の低い Pod をスケジュールします。
16.6.2.1. Pod の優先順位クラス
Pod には優先順位クラスを割り当てることができます。これは、名前から優先順位の整数値へのマッピングを定義する namespace を使用していないオブジェクトです。値が高いと優先順位が高くなります。
優先順位およびプリエンプションは、1000000000 (10 億) 以下の 32 ビットの整数値を取ることができます。プリエンプションやエビクションを実行すべきでない Critical Pod 用に 10 億より大きい数を予約します。デフォルトで、OpenShift Container Platform には 2 つの予約された優先順位クラスがあり、これらは重要なシステム Pod で保証されたスケジューリングが適用されるために使用されます。
- System-node-critical: この優先順位クラスには 2000001000 の値があり、ノードからエビクトすべきでないすべての Pod に使用されます。この優先順位クラスを持つ Pod の例として、sdn-ovs、sdn などがあります。
-
System-cluster-critical: この優先順位クラスには 2000000000 (20 億) の値があり、クラスターに重要な Pod に使用されます。この優先順位クラスの Pod は特定の状況でノードからエビクトされる可能性があります。たとえば、
system-node-critical
優先順位クラスで設定される Pod が優先される可能性があります。この場合でも、この優先順位クラスではスケジューリングが保証されます。この優先順位クラスを持つ可能性のある Pod の例として、fluentd、descheduler などのアドオンコンポーネントなどがあります。
既存クラスターをアップグレードする場合、既存 Pod の優先順位はゼロになります。ただし、scheduler.alpha.kubernetes.io/critical-pod
アノテーションを持つ既存 Pod は system-cluster-critical
クラスに自動的に変換されます。
16.6.2.2. Pod の優先順位名
1 つ以上の優先順位クラスを準備した後に、Pod 仕様に優先順位クラス名を指定する Pod を作成できます。優先順位の受付コントローラーは、優先順位クラス名フィールドを使用して優先順位の整数値を設定します。名前付きの優先順位クラスが見つからない場合、Pod は拒否されます。
以下の YAML は、前述の例で作成された優先順位クラスを使用する Pod 設定の例です。優先順位の受付コントローラーは仕様をチェックし、Pod の優先順位を 1000000 に解決します。
16.6.3. Pod プリエンプションについて
開発者が Pod を作成する場合、Pod はキューに入れられます。Pod の優先順位およびプリエンプション機能が有効にされている場合、スケジューラーはキューから Pod を選択し、Pod をノードにスケジュールしようとします。スケジューラーが Pod について指定されたすべての要件を満たす適切なノードに領域を見つけられない場合、プリエンプションロジックが保留中の Pod についてトリガーされます。
スケジューラーがノードで 1 つ以上の Pod のプリエンプションを実行する場合、優先順位の高い Pod 仕様の nominatedNodeName
フィールドは、nodename
フィールドと共にノードの名前に設定されます。スケジューラーは nominatedNodeName
フィールドを使用して Pod の予約されたリソースを追跡し、またクラスターのプリエンプションについての情報をユーザーに提供します。
スケジューラーが優先順位の低い Pod のプリエンプションを実行した後に、スケジューラーは Pod の正常な終了期間を許可します。スケジューラーが優先順位の低い Pod の終了を待機する間に別のノードが利用可能になると、スケジューラーはそのノードに優先順位の高い Pod をスケジュールできます。その結果、Pod 仕様の nominatedNodeName
フィールドおよび nodeName
フィールドが異なる可能性があります。
さらに、スケジューラーがノード上で Pod のプリエンプションを実行し、終了を待機している場合で、保留中の Pod よりも優先順位の高い Pod をスケジュールする必要がある場合、スケジューラーは代わりに優先順位の高い Pod をスケジュールできます。その場合、スケジューラーは保留中の Pod の nominatedNodeName
をクリアし、その Pod を他のノードの対象とすることができます。
プリエンプションは、ノードから優先順位の低いすべての Pod を削除する訳ではありません。スケジューラーは、優先順位の低い Pod の一部を削除して保留中の Pod をスケジュールできます。
スケジューラーは、保留中の Pod をノードにスケジュールできる場合にのみ、Pod のプリエンプションを実行するノードを考慮します。
16.6.3.1. Pod プリエンプションおよび他のスケジューラーの設定
Pod の優先順位およびプリエンプションを有効にする場合、他のスケジューラー設定を考慮します。
- Pod の優先順位および Pod の Disruption Budget (停止状態の予算)
- Pod の Disruption Budget (停止状態の予算) は一度に稼働している必要のあるレプリカの最小数またはパーセンテージを指定します。Pod の Disruption Budget (停止状態の予算) を指定する場合、OpenShift Container Platform は、 Best Effort レベルで Pod のプリエンプションを実行する際にそれらを適用します。スケジューラーは、Pod の Disruption Budget (停止状態の予算) に違反しない範囲で Pod のプリエンプションを試行します。該当する Pod が見つからない場合には、Pod の Disruption Budget (停止状態の予算) の要件を無視して優先順位の低い Pod のプリエンプションが実行される可能性があります。
- Pod の優先順位およびアフィニティー
- Pod のアフィニティーは、新規 Pod が同じラベルを持つ他の Pod と同じノードにスケジュールされることを要求します。
保留中の Pod にノード上の 1 つ以上の優先順位の低い Pod との Pod 間のアフィニティーがある場合、スケジューラーはアフィニティーの要件を違反せずに優先順位の低い Pod のプリエンプションを実行することはできません。この場合、スケジューラーは保留中の Pod をスケジュールするための別のノードを探します。ただし、スケジューラーが適切なノードを見つけることは保証できず、保留中の Pod がスケジュールされない可能性があります。
この状態を防ぐには、優先順位が等しい Pod との Pod のアフィニティーの設定を慎重に行ってください。
16.6.3.2. プリエンプションが実行された Pod の正常な終了
Pod のプリエンプションの実行中、スケジューラーは Pod の 正常な終了期間 が期限切れになるのを待機します。その後、Pod は機能を完了し、終了します。Pod がこの期間後も終了しない場合、スケジューラーは Pod を強制終了します。 この正常な終了期間により、スケジューラーによる Pod のプリエンプションの実行時と保留中の Pod のノードへのスケジュール時に時間差が出ます。
この時間差を最小限にするには、優先順位の低い Pod の正常な終了期間を短く設定します。
16.6.4. Pod の優先順位のシナリオ例
Pod の優先順位およびプリエンプションはスケジューリングに使用する優先順位を Pod に割り当てます。スケジューラーは優先順位の高い Pod をスケジュールするために優先順位の低い Pod のプリエンプション (エビクト) を実行します。
- 通常のプリエンプションシナリオ
Pod P は保留中の Pod です。
- スケジューラーは ノード N を見つけます。 ここでは、1 つ以上の Pod が削除され、Pod P がそのノードにスケジュールされます。
- スケジューラーは ノード N から優先順位の低い Pod を削除し、Pod P をこのノードにスケジュールします。
-
Pod P の
nominatedNodeName
フィールドは、ノード N の名前に設定されます。
Pod P は必ずしも指定したノードにスケジュールされる訳ではありません。
- プリエンプションおよび終了期間
プリエンプションが実行された Pod には長い終了期間が設定されます。
- スケジューラーは ノード N で優先順位の低い Pod のプリエンプションを実行します。
- スケジューラーは、Pod が正常に終了するのを待機します。
- 他のスケジューリングの理由により、ノード M が利用可能になります。
- スケジューラーは Pod P を ノード M にスケジュールできます。
16.6.5. 優先順位およびプリエンプションの設定
priorityClassName
を Pod 仕様で使用し、優先順位クラスオブジェクトを作成し、Pod を優先順位に関連付けることで、Pod の優先順位およびプリエンプションを適用できます。
優先順位クラスオブジェクトのサンプル
apiVersion: scheduling.k8s.io/v1beta1 kind: PriorityClass metadata: name: high-priority 1 value: 1000000 2 globalDefault: false 3 description: "This priority class should be used for XYZ service pods only." 4
- 1
- 優先順位クラスオブジェクトの名前です。
- 2
- オブジェクトの優先順位の値です。
- 3
- この優先順位クラスが優先順位クラス名が指定されない状態で Pod に使用されるかどうかを示すオプションのフィールドです。このフィールドはデフォルトで
false
です。globalDefault
がtrue
に設定される 1 つの優先順位クラスのみがクラスター内に存在できます。globalDefault:true
が設定された優先順位クラスがない場合、優先順位クラス名が設定されていない Pod の優先順位はゼロになります。globalDefault:true
が設定された優先順位クラスを追加すると、優先順位クラスが追加された後に作成された Pod のみがその影響を受け、これによって既存 Pod の優先順位は変更されません。 - 4
- 開発者がこの優先順位クラスで使用する必要のある Pod を記述するオプションのテキスト文字列です。
優先順位クラス名を持つ Pod 仕様サンプル
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
priorityClassName: high-priority 1
- 1
- この Pod で使用する優先順位クラスを指定します。
優先順位およびプリエンプションを使用するようにクラスターを設定するには、以下を実行します。
1 つ以上の優先順位クラスを作成します。
- 優先順位の名前および値を指定します。
-
優先順位クラスおよび説明に
globalDefault
フィールドをオプションで指定します。
- Pod を作成するか、または優先順位クラスの名前を含むように既存 Pod を編集します。優先順位名は Pod 設定または Pod テンプレートに直接追加できます。
16.6.6. 優先順位およびプリエンプションの無効化
Pod の優先順位およびプリエンプション機能を無効にできます。
この機能が無効にされた後に、既存 Pod はそれらの優先順位フィールドを維持しますが、プリエンプションは無効にされ、優先順位フィールドは無視されます。この機能が無効にされると、新規 Pod に優先順位クラス名を設定できません。
クラスターがリソース不足の状態にある場合、Critical Pod のスケジューリングにはスケジューラーのプリエンプションが使用されます。このため、プリエンプションを無効にしないことが推奨されています。DaemonSet Pod は DaemonSet コントローラーによってスケジュールされるため、プリエンプションを無効にしても影響を受けません。
クラスターのプリエンプションを無効にするには、以下を実行します。
schedulerArgs
セクションのdisablePreemption
パラメーターをfalse
に設定するようにmaster-config.yaml
を変更します。disablePreemption=false
変更を有効にするために OpenShift Container Platform マスターサービスおよびスケジューラーを再起動します。
# master-restart api # master-restart scheduler
16.7. 詳細スケジューリング
16.7.1. 概要
詳細スケジューリングには、Pod が特定ノードで実行されることを要求したり、Pod が特定ノードで実行されることが優先されるように Pod を設定することが関係します。
OpenShift Container Platform は Pod を適切な方法で自動的に配置するため、通常、詳細スケジューリングは必要ありません。たとえば、デフォルトスケジューラーは Pod をノード間で均等に分散し、ノードの利用可能なリソースを考慮します。ただし、Pod を配置する場所についてはさらに制御を強化することをお勧めします。
Pod をより高速なディスクが搭載されたマシンに配置する必要ある場合 (またはそのマシンに配置するのを防ぐ場合)、または 2 つの異なるサービスの Pod が相互に通信できるように配置する必要がある場合、詳細スケジューリングを使用してそれを可能にすることができます。
適切な新規 Pod を特定のノードグループにスケジュールし、その他の新規 Pod がそれらのノードでスケジュールされるのを防ぐには、必要に応じてこれらの方法を組み合わせることができます。
16.7.2. 詳細スケジューリングの使用
クラスターで詳細スケジューリングを起動する方法はいくつかあります。
- Pod のアフィニティーおよび非アフィニティー
Pod のアフィニティーにより、Pod がその配置に使用できるアフィニティー (または非アフィニティー) を、(セキュリティー上の理由によるアプリケーションの待機時間の要件などのために) Pod のグループに対して指定できるようにします。ノード自体は配置に対して制御を行いません。
Pod のアフィニティーはノードのラベルと Pod のラベルセレクターを使用して Pod 配置のルールを作成します。ルールは mandatory (必須) または best-effort (優先) のいずれかにすることができます。
Pod のアフィニティーおよび非アフィニティーの使用 を参照してください。
- ノードのアフィニティー
ノードのアフィニティーにより、Pod がその配置に使用できるアフィニティー (または非アフィニティー) を、(高可用性のための特殊なハードウェア、場所、要件などにより) ノード のグループに対して指定できるようにします。ノード自体は配置に対して制御を行いません。
ノードのアフィニティーはノードのラベルと Pod のラベルセレクターを使用して Pod 配置のルールを作成します。ルールは mandatory (必須) または best-effort (優先) のいずれかにすることができます。
ノードアフィニティーの使用 を参照してください。
- ノードセレクター
ノードセレクターは詳細スケジューリングの最も単純な形態です。ノードのアフィニティーのように、ノードセレクターはノードのラベルと Pod のラベルセレクターを使用し、Pod がその配置に使用する ノード を制御できるようにします。ただし、ノードセレクターにはノードのアフィニティーが持つ required (必須) ルールまたは preferred (優先) ルールはありません。
ノードセレクターの使用 を参照してください。
- テイントおよび容認 (Toleration)
テイント/容認により、ノード はノード上でスケジュールする必要のある (またはスケジュールすべきでない) Pod を制御できます。テイントはノードのラベルであり、容認は Pod のラベルです。スケジュールを可能にするには、Pod のラベルは ノードのラベル (テイント) に一致する (またはこれを許容する) 必要があります。
テイント/容認にはアフィニティーと比較して 1 つ利点があります。たとえばアフィニティーの場合は、異なるラベルを持つノードの新規グループをクラスターに追加する場合、ノードにアクセスさせたい Pod と新規ノードを使用させたくない Pod のそれぞれに対してアフィニティーを更新する必要があります。テイント/容認の場合には、新規ノードに到達させる必要のある Pod のみを更新すれば、他の Pod は拒否されることになります。
テイントおよび容認の使用 を参照してください。
16.8. 詳細スケジューリングおよびノードのアフィニティー
16.8.1. 概要
ノードのアフィニティー は、Pod の配置場所を判別するためにスケジューラーによって使用されるルールのセットです。ルールはカスタムの ノードのラベル と Pod で指定されるラベルセレクターを使って定義されます。ノードのアフィニティーにより、Pod がその配置に使用できるノードのグループに対してアフィニティー (または非アフィニティー) を指定できます。ノード自体は配置に対して制御を行いません。
たとえば、Pod を特定の CPU を搭載したノードまたは特定のアベイラビリティーゾーンにあるノードでのみ実行されるよう設定することができます。
ノードのアフィニティールールには、required (必須) および preferred (優先) の 2 つのタイプがあります。
Pod をノードにスケジュールする前に、required (必須) ルールを 満たしている必要があります。preferred (優先) ルールは、ルールを満たす場合に、スケジューラーはルールの実施を試行しますが、その実施が必ずしも保証される訳ではありません。
ランタイム時にノードのラベルに変更が生じ、その変更により Pod でのノードのアフィニティールールを満たさなくなる状態が生じるでも、Pod はノードで引き続き実行されます。
16.8.2. ノードのアフィニティーの設定
ノードのアフィニティーは、Pod 仕様で設定することができます。required (必須) ルール、preferred (優先) ルール のいずれかまたはその両方を指定することができます。両方を指定する場合、ノードは最初に required (必須) ルールを満たす必要があり、その後に preferred (優先) ルールを満たそうとします。
以下の例は、Pod をキーが e2e-az-NorthSouth
で、その値が e2e-az-North
または e2e-az-South
のいずれかであるラベルの付いたノードに Pod を配置することを求めるルールが設定された Pod 仕様です。
ノードのアフィニティーの required (必須) ルールが設定された Pod 設定ファイルのサンプル
apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: 1 requiredDuringSchedulingIgnoredDuringExecution: 2 nodeSelectorTerms: - matchExpressions: - key: e2e-az-NorthSouth 3 operator: In 4 values: - e2e-az-North 5 - e2e-az-South 6 containers: - name: with-node-affinity image: docker.io/ocpqe/hello-pod
以下の例は、キーが e2e-az-EastWest
で、その値が e2e-az-East
または e2e-az-West
のラベルが付いたノードに Pod を配置すること優先する preferred (優先) ルールが設定されたノード仕様です。
ノードのアフィニティーの preferred (優先) ルールが設定された Pod 設定ファイルのサンプル
apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: 1 preferredDuringSchedulingIgnoredDuringExecution: 2 - weight: 1 3 preference: matchExpressions: - key: e2e-az-EastWest 4 operator: In 5 values: - e2e-az-East 6 - e2e-az-West 7 containers: - name: with-node-affinity image: docker.io/ocpqe/hello-pod
ノードの非アフィニティー についての明示的な概念はありませんが、NotIn
または DoesNotExist
演算子を使用すると、動作が複製されます。
同じ Pod 設定でノードのアフィニティーと ノードのセレクター を使用している場合は、以下に注意してください。
-
nodeSelector
とnodeAffinity
の両方を設定する場合、Pod が候補ノードでスケジュールされるにはどちらの条件も満たしている必要があります。 -
nodeAffinity
タイプに関連付けられた複数のnodeSelectorTerms
を指定する場合、nodeSelectorTerms
のいずれかが満たされている場合に Pod をノードにスケジュールすることができます。 -
nodeSelectorTerms
に関連付けられた複数のmatchExpressions
を指定する場合、すべてのmatchExpressions
が満たされている場合にのみ Pod をノードにスケジュールすることができます。
16.8.2.1. ノードアフィニティーの required (必須) ルールの設定
Pod をノードにスケジュールする前に、required (必須) ルールを 満たしている必要があります。
以下の手順は、ノードとスケジューラーがノードに配置する必要のある Pod を作成する単純な設定を示しています。
ノード設定を編集するか、または
oc label node
コマンドを使用して、ラベルをノードに追加します。$ oc label node node1 e2e-az-name=e2e-az1
注記クラスターのノードを変更するには、ノード設定マップ を必要に応じて更新します。
node-config.yaml
ファイルは手動で変更しないようにしてください。Pod
仕様では、nodeAffinity
スタンザを使用してrequiredDuringSchedulingIgnoredDuringExecution パラメーターを設定します
。-
満たしている必要のあるキーおよび値を指定します。新規 Pod を編集したノードにスケジュールする必要がある場合、ノードのラベルと同じ
key
およびvalue
パラメーターを使用します。 operator
を指定します。演算子はIn
、NotIn
、Exists
、DoesNotExist
、Lt
、またはGt
にすることができます。たとえば、演算子In
を使用して、ラベルがノードにあることを要求します。spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: e2e-az-name operator: In values: - e2e-az1 - e2e-az2
-
満たしている必要のあるキーおよび値を指定します。新規 Pod を編集したノードにスケジュールする必要がある場合、ノードのラベルと同じ
Pod を作成します。
$ oc create -f e2e-az2.yaml
16.8.2.2. ノードアフィニティーの preferred (優先) ルールの設定
preferred (優先) ルールは、ルールを満たす場合に、スケジューラーはルールの実施を試行しますが、その実施が必ずしも保証される訳ではありません。
以下の手順は、ノードとスケジューラーがノードに配置しようとする Pod を作成する単純な設定を示しています。
ノード設定を編集するか、または
oc label node
コマンドを実行して、ラベルをノードに追加します。$ oc label node node1 e2e-az-name=e2e-az3
注記クラスターのノードを変更するには、ノード設定マップ を必要に応じて更新します。
node-config.yaml
ファイルは手動で変更しないようにしてください。Pod 仕様では、
nodeAffinity
スタンザを使用してpreferredDuringSchedulingIgnoredDuringExecution
パラメーターを設定します。- ノードの重みを数字の 1-100 で指定します。最も高い重みを持つノードが優先されます。
満たしている必要のあるキーおよび値を指定します。新規 Pod を編集したノードにスケジュールする必要がある場合、ノードのラベルと同じ
key
およびvalue
パラメーターを使用します。preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: e2e-az-name operator: In values: - e2e-az3
-
operator
を指定します。演算子はIn
、NotIn
、Exists
、DoesNotExist
、Lt
、またはGt
にすることができます。たとえば、演算子In
を使用してラベルをノードで必要になるようにします。 Pod を作成します。
$ oc create -f e2e-az3.yaml
16.8.3. 例
以下の例は、ノードのアフィニティーを示しています。
16.8.3.1. 一致するラベルを持つノードのアフィニティー
以下の例は、一致するラベルを持つノードと Pod のノードのアフィニティーを示しています。
Node1 ノードにはラベル
zone:us
があります。$ oc label node node1 zone=us
Pod pod-s1 にはノードアフィニティーの required (必須) ルールの下に
zone
とus
のキー/値のペアがあります。$ cat pod-s1.yaml apiVersion: v1 kind: Pod metadata: name: pod-s1 spec: containers: - image: "docker.io/ocpqe/hello-pod" name: hello-pod affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: "zone" operator: In values: - us
標準コマンドを使用して Pod を作成します。
$ oc create -f pod-s1.yaml pod "pod-s1" created
Pod pod-s1 を Node1 にスケジュールできます。
$ oc get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE pod-s1 1/1 Running 0 4m IP1 node1
16.8.3.2. 一致するラベルのないノードのアフィニティー
以下の例は、一致するラベルを持たないノードと Pod のノードのアフィニティーを示しています。
Node1 ノードにはラベル
zone:emea
があります。$ oc label node node1 zone=emea
Pod pod-s1 にはノードアフィニティーの required (必須) ルールの下に
zone
とus
のキー/値のペアがあります。$ cat pod-s1.yaml apiVersion: v1 kind: Pod metadata: name: pod-s1 spec: containers: - image: "docker.io/ocpqe/hello-pod" name: hello-pod affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: "zone" operator: In values: - us
Pod pod-s1 は Node1 にスケジュールすることができません。
$ oc describe pod pod-s1 ... Events: FirstSeen LastSeen Count From SubObjectPath Type Reason --------- -------- ----- ---- ------------- -------- ------ 1m 33s 8 default-scheduler Warning FailedScheduling No nodes are available that match all of the following predicates:: MatchNodeSelector (1).
16.9. 詳細スケジューリングおよび Pod のアフィニティーと非アフィニティー
16.9.1. 概要
Pod のアフィニティー および Pod の非アフィニティー により、他の Pod との関連で Pod を配置する方法についてのルールを指定できます。ルールはカスタムの ノードのラベル と Pod で指定されるラベルセレクターを使って定義されます。Pod のアフィニティー/非アフィニティーにより、Pod はアフィニティー (または非アフィニティー) を、その配置に使用できる Pod のグループに対して指定できます。ノード自体は配置に対して制御を行いません。
たとえば、アフィニティールールを使用することで、サービス内で、または他のサービスの Pod との関連で Pod を分散したり、パックしたりすることができます。非アフィニティールールにより、特定のサービスの Pod がそののサービスの Pod のパフォーマンスに干渉すると見なされる別のサービスの Pod と同じノードでスケジュールされることを防ぐことができます。または、関連する障害を減らすために複数のノードまたはアベイラビリティーゾーン間でサービスの Pod を分散することもできます。
Pod のアフィニティー/非アフィニティーにより、他の Pod のラベルに基づいて Pod のスケジュール対象とするノードを制限することができます。ラベル はキー/値のペアです。
- Pod のアフィニティーはスケジューラーに対し、新規 Pod のラベルセレクターが現在の Pod のラベルに一致する場合に他の Pod と同じノードで新規 Pod を見つけるように指示します。
- Pod の非アフィニティーは、新規 Pod のラベルセレクターが現在の Pod のラベルに一致する場合に、同じラベルを持つ Pod と同じノードで新規 Pod を見つけることを禁止します。
Pod のアフィニティーには、required (必須) および preferred (優先) の 2 つのタイプがあります。
Pod をノードにスケジュールする前に、required (必須) ルールを 満たしている必要があります。preferred (優先) ルールは、ルールを満たす場合に、スケジューラーはルールの実施を試行しますが、その実施が必ずしも保証される訳ではありません。
Pod の優先順位およびプリエンプション の設定により、スケジューラーはアフィニティーの要件に違反しなければ Pod の適切なノードを見つけられない可能性があります。その場合、Pod はスケジュールされない可能性があります。
この状態を防ぐには、優先順位が等しい Pod との Pod のアフィニティーの設定を慎重に行ってください。
16.9.2. Pod のアフィニティーおよび非アフィニティーの設定
Pod のアフィニティー/非アフィニティーは Pod 仕様ファイルで設定します。required (必須) ルール、preferred (優先) ルール のいずれかまたはその両方を指定することができます。両方を指定する場合、ノードは最初に required (必須) ルールを満たす必要があり、その後に preferred (優先) ルールを満たそうとします。
以下の例は、Pod のアフィニティーおよび非アフィニティーに設定される Pod 仕様を示しています。
この例では、Pod のアフィニティールールは ノードにキー security
と値 S1
を持つラベルの付いた 1 つ以上の Pod がすでに実行されている場合にのみ Pod をノードにスケジュールできることを示しています。Pod の非アフィニティールールは、ノードがキー security
と値 S2
を持つラベルが付いた Pod がすでに実行されている場合は Pod をノードにスケジュールしないように設定することを示しています。
Pod のアフィニティーが設定された Pod 設定のサンプル
apiVersion: v1 kind: Pod metadata: name: with-pod-affinity spec: affinity: podAffinity: 1 requiredDuringSchedulingIgnoredDuringExecution: 2 - labelSelector: matchExpressions: - key: security 3 operator: In 4 values: - S1 5 topologyKey: failure-domain.beta.kubernetes.io/zone containers: - name: with-pod-affinity image: docker.io/ocpqe/hello-pod
Pod の非アフィニティーが設定された Pod 設定のサンプル
apiVersion: v1 kind: Pod metadata: name: with-pod-antiaffinity spec: affinity: podAntiAffinity: 1 preferredDuringSchedulingIgnoredDuringExecution: 2 - weight: 100 3 podAffinityTerm: labelSelector: matchExpressions: - key: security 4 operator: In 5 values: - S2 topologyKey: kubernetes.io/hostname containers: - name: with-pod-affinity image: docker.io/ocpqe/hello-pod
ノードのラベルに、Pod のノードのアフィニティールールを満たさなくなるような結果になる変更がランタイム時に生じる場合も、Pod はノードで引き続き実行されます。
16.9.2.1. アフィニティールールの設定
以下の手順は、ラベルの付いた Pod と Pod のスケジュールを可能にするアフィニティーを使用する Pod を作成する 2 つの Pod の単純な設定を示しています。
Pod 仕様の特定のラベルの付いた Pod を作成します。
$ cat team4.yaml apiVersion: v1 kind: Pod metadata: name: security-s1 labels: security: S1 spec: containers: - name: security-s1 image: docker.io/ocpqe/hello-pod
他の Pod の作成時に、以下のように Pod 仕様を編集します。
-
podAffinity
スタンザを使用して、requiredDuringSchedulingIgnoredDuringExecution
パラメーターまたはpreferredDuringSchedulingIgnoredDuringExecution
パラメーターを設定します。 満たしている必要のあるキーおよび値を指定します。新規 Pod を他の Pod と共にスケジュールする必要がある場合、最初の Pod のラベルと同じ
key
およびvalue
パラメーターを使用します。podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - S1 topologyKey: failure-domain.beta.kubernetes.io/zone
-
operator
を指定します。演算子はIn
、NotIn
、Exists
、またはDoesNotExist
にすることができます。たとえば、演算子In
を使用してラベルをノードで必要になるようにします。 -
topologyKey
を指定します。これは、システムがトポロジードメインを表すために使用する事前にデータが設定された Kubernetes ラベル です。
-
Pod を作成します。
$ oc create -f <pod-spec>.yaml
16.9.2.2. 非アフィニティールールの設定
以下の手順は、ラベルの付いた Pod と Pod のスケジュールの禁止を試行する非アフィニティーの preferred (優先) ルールを使用する Pod を作成する 2 つの Pod の単純な設定を示しています。
Pod 仕様の特定のラベルの付いた Pod を作成します。
$ cat team4.yaml apiVersion: v1 kind: Pod metadata: name: security-s2 labels: security: S2 spec: containers: - name: security-s2 image: docker.io/ocpqe/hello-pod
- 他の Pod の作成時に、Pod 仕様を編集して以下のパラメーターを設定します。
podAffinity
スタンザを使用して、requiredDuringSchedulingIgnoredDuringExecution
パラメーターまたはpreferredDuringSchedulingIgnoredDuringExecution
パラメーターを設定します。- ノードの重みを 1-100 で指定します。最も高い重みを持つノードが優先されます。
満たしている必要のあるキーおよび値を指定します。新規 Pod を他の Pod と共にスケジュールされないようにする必要がある場合、最初の Pod のラベルと同じ
key
およびvalue
パラメーターを使用します。podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: security operator: In values: - S2 topologyKey: kubernetes.io/hostname
- preferred (優先) ルールの場合、重みを 1-100 で指定します。
-
operator
を指定します。演算子はIn
、NotIn
、Exists
、またはDoesNotExist
にすることができます。たとえば、演算子In
を使用してラベルをノードで必要になるようにします。
-
topologyKey
を指定します。これは、システムがトポロジードメインを表すために使用する事前にデータが設定された Kubernetes ラベル です。 Pod を作成します。
$ oc create -f <pod-spec>.yaml
16.9.3. 例
以下の例は、Pod のアフィニティーおよび非アフィニティーについて示しています。
16.9.3.1. Pod のアフィニティー
以下の例は、一致するラベルとラベルセレクターを持つ Pod についての Pod のアフィニティーを示しています。
Pod team4 にはラベル
team:4
が付けられています。$ cat team4.yaml apiVersion: v1 kind: Pod metadata: name: team4 labels: team: "4" spec: containers: - name: ocp image: docker.io/ocpqe/hello-pod
Pod team4a には、
podAffinity
の下にラベルセレクターteam:4
が付けられています。$ cat pod-team4a.yaml apiVersion: v1 kind: Pod metadata: name: team4a spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: team operator: In values: - "4" topologyKey: kubernetes.io/hostname containers: - name: pod-affinity image: docker.io/ocpqe/hello-pod
- team4a Pod は team4 Pod と同じノードにスケジュールされます。
16.9.3.2. Pod の非アフィニティー
以下の例は、一致するラベルとラベルセレクターを持つ Pod についての Pod の非アフィニティーを示しています。
Pod pod-s1 にはラベル
security:s1
が付けられています。$ cat pod-s1.yaml apiVersion: v1 kind: Pod metadata: name: pod-s1 labels: security: s1 spec: containers: - name: ocp image: docker.io/ocpqe/hello-pod
Pod pod-s2 には、
podAntiAffinity
の下にラベルセレクターsecurity:s1
が付けられています。$ cat pod-s2.yaml apiVersion: v1 kind: Pod metadata: name: pod-s2 spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - s1 topologyKey: kubernetes.io/hostname containers: - name: pod-antiaffinity image: docker.io/ocpqe/hello-pod
-
Pod pod-s2 は
pod-s1
と同じノードにスケジュールできません。
16.9.3.3. 一致するラベルのない Pod のアフィニティー
以下の例は、一致するラベルとラベルセレクターのない Pod についての Pod のアフィニティーを示しています。
Pod pod-s1 にはラベル
security:s1
が付けられています。$ cat pod-s1.yaml apiVersion: v1 kind: Pod metadata: name: pod-s1 labels: security: s1 spec: containers: - name: ocp image: docker.io/ocpqe/hello-pod
Pod pod-s2 にはラベルセレクター
security:s2
があります。$ cat pod-s2.yaml apiVersion: v1 kind: Pod metadata: name: pod-s2 spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - s2 topologyKey: kubernetes.io/hostname containers: - name: pod-affinity image: docker.io/ocpqe/hello-pod
Pod pod-s2 は、
security:s2
ラベルの付いた Pod を持つノードがない場合はスケジュールされません。そのラベルの付いた他の Pod がない場合、新規 Pod は保留状態のままになります。NAME READY STATUS RESTARTS AGE IP NODE pod-s2 0/1 Pending 0 32s <none>
16.10. 詳細スケジューリングおよびノードセレクター
16.10.1. 概要
ノードセレクター はキーと値のペアのマップを指定します。ルールは、カスタムの ノードのラベル および Pod で指定されるセレクターを使用して定義されます。
Pod がノードで実行する要件を満たすには、Pod はノードのラベルとして示されるキーと値のペアを持っている必要があります。
同じ Pod 設定でノードのアフィニティーと ノードセレクター を使用している場合は、以下の 重要な考慮事項 を参照してください。
16.10.2. ノードセレクターの設定
Pod 設定で nodeSelector
を使用することで、Pod を特定のラベルの付いたノードのみに配置することができます。
必要なラベル (詳細は、ノードでのラベルの更新 を参照) および ノードセレクター が環境にセットアップされていることを確認します。
たとえば、Pod 設定が必要なラベルを示す
nodeSelector
値を持つことを確認します。apiVersion: v1 kind: Pod spec: nodeSelector: <key>: <value> ...
マスター設定ファイル /etc/origin/master/master-config.yaml を変更し、
nodeSelectorLabelBlacklist
を、Pod の配置を拒否する必要のあるノードホストに割り当てられるラベルと共にadmissionConfig
セクションに追加します。... admissionConfig: pluginConfig: PodNodeConstraints: configuration: apiversion: v1 kind: PodNodeConstraintsConfig nodeSelectorLabelBlacklist: - kubernetes.io/hostname - <label> ...
変更を有効にするために OpenShift Container Platform を再起動します。
# master-restart api # master-restart controllers
同じ Pod 設定でノードセレクターと ノードのアフィニティー を使用している場合は、以下に注意してください。
-
nodeSelector
とnodeAffinity
の両方を設定する場合、Pod が候補ノードでスケジュールされるにはどちらの条件も満たしている必要があります。 -
nodeAffinity
タイプに関連付けられた複数のnodeSelectorTerms
を指定する場合、nodeSelectorTerms
のいずれかが満たされている場合に Pod をノードにスケジュールすることができます。 -
nodeSelectorTerms
に関連付けられた複数のmatchExpressions
を指定する場合、すべてのmatchExpressions
が満たされている場合にのみ Pod をノードにスケジュールすることができます。
16.11. 詳細スケジューリングおよび容認
16.11.1. 概要
テイントおよび容認により、ノード はノード上でスケジュールする必要のある (またはスケジュールすべきでない) Pod を制御できます。
16.11.2. テイントおよび容認 (Toleration)
テイント により、ノードは Pod に一致する 容認 がない場合に Pod のスケジュールを拒否することができます。
テイントはノード仕様 (NodeSpec
) でノードに適用され、容認は Pod 仕様 (PodSpec
) で Pod に適用されます。ノードのテイントはノードに対し、テイントを容認しないすべての Pod を拒否するよう指示します。
テイントおよび容認は、key、value、および effect.で設定されています。演算子により、これらの 3 つのパラメーターのいずれかを空のままにすることができます。
表16.1 テイントおよび容認コンポーネント
パラメーター | 説明 | ||||||
---|---|---|---|---|---|---|---|
|
| ||||||
|
| ||||||
| effect は以下のいずれかにすることができます。
| ||||||
|
|
容認はテイントと一致します。
operator
パラメーターがEqual
に設定されている場合:-
key
パラメーターは同じになります。 -
value
パラメーターは同じになります。 -
effect
パラメーターは同じになります。
-
operator
パラメーターがExists
に設定されている場合:-
key
パラメーターは同じになります。 -
effect
パラメーターは同じになります。
-
16.11.2.1. 複数テイントの使用
複数のテイントを同じノードに、複数の容認を同じ Pod に配置することができます。OpenShift Container Platform は複数のテイントと容認を以下のように処理します。
- Pod に一致する容認のあるテイントを処理します。
残りの一致しないテイントは Pod について以下の effect を持ちます。
-
effect が
NoSchedule
の一致しないテイントが 1 つ以上ある場合、OpenShift Container Platform は Pod をノードにスケジュールできません。 -
effect が
NoSchedule
の一致しないテイントがなく、effect がPreferNoSchedule
の一致しない テイントが 1 つ以上ある場合、OpenShift Container Platform は Pod のノードへのスケジュールを試行しません。 effect が
NoExecute
のテイントが 1 つ以上ある場合、OpenShift Container Platform は Pod をノードからエビクトするか (ノードですでに実行中の場合)、または Pod のそのノードへのスケジュールが実行されません (ノードでまだ実行されていない場合)。- テイントを容認しない Pod はすぐにエビクトされます。
-
容認の仕様に
tolerationSeconds
を指定せずにテイントを容認する Pod は永久にバインドされたままになります。 -
指定された
tolerationSeconds
を持つテイントを容認する Pod は指定された期間バインドされます。
-
effect が
以下に例を示します。
ノードには以下のテイントがあります。
$ oc adm taint nodes node1 key1=value1:NoSchedule $ oc adm taint nodes node1 key1=value1:NoExecute $ oc adm taint nodes node1 key2=value2:NoSchedule
Pod には以下の容認があります。
tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule" - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute"
この場合、3 つ目のテイントに一致する容認がないため、Pod はノードにスケジュールできません。Pod はこのテイントの追加時にノードですでに実行されている場合は実行が継続されます。 3 つ目のテイントは 3 つのテイントの中で Pod で容認されない唯一のテイントであるためです。
16.11.3. テイントの既存ノードへの追加
テイントおよび容認コンポーネント の表で説明されているパラメーターと共に oc adm taint
コマンドを使用してテイントをノードに追加します。
$ oc adm taint nodes <node-name> <key>=<value>:<effect>
以下に例を示します。
$ oc adm taint nodes node1 key1=value1:NoExecute
この例では、キー key1
、値 value1
、およびテイント effect NoExecute
を持つ node1
にテイントを配置します。
16.11.4. 容認の Pod への追加
容認を Pod に追加するには、Pod 仕様を tolerations
セクションを含めるように編集します。
Equal
演算子を含む Pod 設定ファイルのサンプル
tolerations: - key: "key1" 1 operator: "Equal" 2 value: "value1" 3 effect: "NoExecute" 4 tolerationSeconds: 3600 5
- 1 2 3 4
- テイントおよび容認コンポーネント の表で説明されている toleration パラメーターです。
- 5
tolerationSeconds
パラメーターは、Pod がエビクトされる前にノードにバインドされる期間を指定します。以下の Pod エビクションを遅延させる容認期間 (秒数) の使用 を参照してください。
Exists
演算子を含む Pod 設定ファイルのサンプル
tolerations: - key: "key1" operator: "Exists" effect: "NoExecute" tolerationSeconds: 3600
これらの容認のいずれも 上記の oc adm taint
コマンドで作成されるテイント に一致します。いずれかの容認のある Pod は node1
にスケジュールできます。
16.11.4.1. Pod のエビクションを遅延させる容認期間 (秒数) の使用
Pod 仕様に tolerationSeconds
パラメーターを指定して、Pod がエビクトされる前にノードにバインドされる期間を指定できます。effect NoExecute
のあるテイントがノードに追加される場合、テイントを容認しない Pod は即時にエビクトされます (テイントを容認する Pod はエビクトされません)。ただし、エビクトされる Pod に tolerationSeconds
パラメーターがある場合、Pod は期間切れになるまでエビクトされません。
以下に例を示します。
tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute" tolerationSeconds: 3600
ここで、この Pod が実行中であるものの、一致するテイントがない場合、Pod は 3,600 秒間バインドされたままとなり、その後にエビクトされます。テイントが期限前に削除される場合、Pod はエビクトされません。
16.11.4.1.1. 容認の秒数のデフォルト値の設定
このプラグインは、node.kubernetes.io/not-ready:NoExecute
および node.kubernetes.io/unreachable:NoExecute
テイントを 5 分間容認するための Pod のデフォルトの容認を設定します。
ユーザーが提供する Pod 設定にいずれかの容認がある場合、デフォルトは追加されません。
デフォルトの容認の秒数を有効にするには、以下を実行します。
マスター設定ファイル (/etc/origin/master/master-config.yaml) を変更して、
DefaultTolerationSeconds
を admissionConfig セクションに追加します。admissionConfig: pluginConfig: DefaultTolerationSeconds: configuration: kind: DefaultAdmissionConfig apiVersion: v1 disable: false
変更を有効にするために、OpenShift を再起動します。
# master-restart api # master-restart controllers
デフォルトが追加されていることを確認します。
Pod を作成します。
$ oc create -f </path/to/file>
以下に例を示します。
$ oc create -f hello-pod.yaml pod "hello-pod" created
Pod の容認を確認します。
$ oc describe pod <pod-name> |grep -i toleration
以下に例を示します。
$ oc describe pod hello-pod |grep -i toleration Tolerations: node.kubernetes.io/not-ready=:Exists:NoExecute for 300s
16.11.5. ノード問題の Pod エビクション
OpenShift Container Platform は、node unreachable および node not ready 状態をテイントとして表示するよう設定できます。これにより、デフォルトの 5 分を使用するのではなく、unreachable (到達不能) または not ready (準備ができていない) 状態になるノードにバインドされたままになる期間を Pod 仕様ごとに指定することができます。
テイントベースのエビクション機能が有効にされた状態で、テイントはノードコントローラーによって自動的に追加され、Pod を Ready
ノードからエビクトするための通常のロジックは無効にされます。
-
ノードが not ready (準備ができていない) 状態になると、
node.kubernetes.io/not-ready:NoExecute
テイントは追加され、Pod はノードでスケジュールできなくなります。既存 Pod は容認期間 (秒数) 中はそのまま残ります。 -
ノードが not reachable (到達不能) の状態になると、
node.kubernetes.io/unreachable:NoExecute
テイントは追加され、Pod はノードでスケジュールできません。既存 Pod は容認期間 (秒数) 中はそのまま残ります。
テイントベースのエビクションを有効にするには、以下を実行します。
マスター設定ファイル (/etc/origin/master/master-config.yaml) を変更して、以下を
kubernetesMasterConfig
セクションに追加します。kubernetesMasterConfig: controllerArguments: feature-gates: - TaintBasedEvictions=true
テイントがノードに追加されていることを確認します。
$ oc describe node $node | grep -i taint Taints: node.kubernetes.io/not-ready:NoExecute
変更を有効にするために、OpenShift を再起動します。
# master-restart api # master-restart controllers
容認を Pod に追加します。
tolerations: - key: "node.kubernetes.io/unreachable" operator: "Exists" effect: "NoExecute" tolerationSeconds: 6000
または
tolerations: - key: "node.kubernetes.io/not-ready" operator: "Exists" effect: "NoExecute" tolerationSeconds: 6000
ノードの問題の発生時に Pod エビクションの既存の レート制限 の動作を維持するために、システムはテイントをレートが制限された方法で追加します。これにより、マスターがノードからパーティション化される場合などのシナリオで発生する大規模な Pod エビクションを防ぐことができます。
16.11.6. Daemonset および容認
Daemonset Pod は、Default Toleration Seconds (デフォルトの容認期間の秒数) 機能が無効にされている場合でも、tolerationSeconds
のない node.kubernetes.io/unreachable
および node.kubernetes.io/not-ready
の NoExecute
容認で作成され、DeamonSet Pod がこの問題が原因でエビクトされないようにします。
16.11.7. 例
テイントおよび容認は、Pod をノードから切り離し、ノードで実行されるべきでない Pod をエビクトする柔軟性のある方法として使用できます。以下は典型的なシナリオのいくつかになります。
16.11.7.1. ノードをユーザー専用にする
ノードのセットを特定のユーザーセットが排他的に使用するように指定できます。
専用ノードを指定するには、以下を実行します。
テイントをそれらのノードに追加します。
以下に例を示します。
$ oc adm taint nodes node1 dedicated=groupName:NoSchedule
カスタム受付コントローラーを作成して対応する容認を Pod に追加します。
容認のある Pod のみが専用ノードを使用することを許可されます。
16.11.7.2. ユーザーのノードへのバインド
特定ユーザーが専用ノードのみを使用できるようにノードを設定することができます。
ノードをユーザーの使用可能な唯一のノードとして設定するには、以下を実行します。
テイントをそれらのノードに追加します。
以下に例を示します。
$ oc adm taint nodes node1 dedicated=groupName:NoSchedule
カスタム受付コントローラーを作成して対応する容認を Pod に追加します。
受付コントローラーは、Pod が
key:value
ラベル (dedicated=groupName
) が付けられたノードのみにスケジュールされるようにノードのアフィニティーを追加します。-
テイントと同様のラベル (
key:value
ラベルなど) を専用ノードに追加します。
16.11.7.3. 特殊ハードウェアを持つノード
ノードの小規模なサブセットが特殊ハードウェア (GPU など) を持つクラスターでは、テイントおよび容認を使用して、特殊ハードウェアを必要としない Pod をそれらのノードから切り離し、特殊ハードウェアを必要とする Pod をそのままにすることができます。また、特殊ハードウェアを必要とする Pod に対して特定のノードを使用することを要求することもできます。
Pod が特殊ハードウェアからブロックされるようにするには、以下を実行します。
以下のコマンドのいずれかを使用して、特殊ハードウェアを持つノードにテイントを設定します。
$ oc adm taint nodes <node-name> disktype=ssd:NoSchedule $ oc adm taint nodes <node-name> disktype=ssd:PreferNoSchedule
- 受付コントローラー を使用して特殊ハードウェアを使用する Pod に対応する容認を追加します。
たとえば受付コントローラーは容認を追加することで、Pod の一部の特徴を使用し、Pod が特殊ノードを使用できるかどうかを判別できます。
Pod が特殊ハードウェアのみを使用できるようにするには、追加のメカニズムが必要です。たとえば、特殊ハードウェアを持つノードにラベルを付け、ハードウェアを必要とする Pod でノードのアフィニティーを使用できます。
第17章 クォータの設定
17.1. 概要
ResourceQuota
オブジェクトで定義されるリソースクォータは、プロジェクトごとにリソース消費量の総計を制限する制約を指定します。これは、タイプ別にプロジェクトで作成できるオブジェクトの数量を制限すると共に、そのプロジェクトのリソースが消費できるコンピュートリソースおよびストレージの合計量を制限することができます。
コンピュートリソースについての詳細は、Developer Guide を参照してください。
17.2. クォータで管理されるリソース
以下では、クォータで管理できる一連のコンピュートリソースとオブジェクトタイプについて説明します。
status.phase in (Failed, Succeeded)
が true の場合、Pod は終了状態にあります。
表17.1 クォータで管理されるコンピュートリソース
リソース名 | 説明 |
---|---|
|
非終了状態のすべての Pod での CPU 要求の合計はこの値を超えることができません。 |
|
非終了状態のすべての Pod でのメモリー要求の合計はこの値を超えることができません。 |
|
非終了状態のすべての Pod におけるローカルの一時ストレージ要求の合計は、この値を超えることができません。 |
|
非終了状態のすべての Pod での CPU 要求の合計はこの値を超えることができません。 |
|
非終了状態のすべての Pod でのメモリー要求の合計はこの値を超えることができません。 |
|
非終了状態のすべての Pod における一時ストレージ要求の合計は、この値を超えることができません。 |
| 非終了状態のすべての Pod での CPU 制限の合計はこの値を超えることができません。 |
| 非終了状態のすべての Pod でのメモリー制限の合計はこの値を超えることができません。 |
| 非終了状態のすべての Pod における一時ストレージ制限の合計は、この値を超えることができません。このリソースは、一時ストレージのテクノロジープレビュー機能が有効にされている場合にのみ利用できます。この機能はデフォルトでは無効になっています。 |
表17.2 クォータで管理されるストレージリソース
リソース名 | 説明 |
---|---|
| 任意の状態のすべての永続ボリューム要求 (PVC) でのストレージ要求の合計は、この値を超えることができません。 |
| プロジェクトに存在できる永続ボリューム要求 (PVC) の合計数です。 |
| 一致するストレージクラスを持つ、任意の状態のすべての永続ボリューム要求 (PVC) でのストレージ要求の合計はこの値を超えることができません。 |
| プロジェクトに存在できる、一致するストレージクラスを持つ Persistent Volume Claim (永続ボリューム要求、PVC) の合計数です。 |
表17.3 クォータで管理されるオブジェクト数
リソース名 | 説明 |
---|---|
| プロジェクトに存在できる非終了状態の Pod の合計数です。 |
| プロジェクトに存在できるレプリケーションコントローラーの合計数です。 |
| プロジェクトに存在できるリソースクォータの合計数です。 |
| プロジェクトに存在できるサービスの合計数です。 |
| プロジェクトに存在できるシークレットの合計数です。 |
|
プロジェクトに存在できる |
| プロジェクトに存在できる永続ボリューム要求 (PVC) の合計数です。 |
| プロジェクトに存在できるイメージストリームの合計数です。 |
クォータの作成 時に、count/<resource>.<group>
構文を使用して、これらの標準的な namespace を使用しているリソースタイプのオブジェクトカウントクォータを設定できます。
$ oc create quota <name> --hard=count/<resource>.<group>=<quota> 1
- 1
<resource>
はリソースの名前であり、<group>
は API グループです (該当する場合)。リソースおよびそれらの関連付けられた API グループの一覧にkubectl api-resources
コマンドを使用します。
17.2.1. 拡張リソースのリソースクォータの設定
リソースのオーバーコミットは拡張リソースには許可されません。そのため、クォータで同じ拡張リソースの requests
および limits
を指定する必要があります。現時点で、接頭辞 requests.
のあるクォータ項目のみが拡張リソースに許可されます。以下は、GPU リソース nvidia.com/gpu
のリソースクォータを設定する方法についてのシナリオ例です。
手順
クラスター内のノードで利用可能な GPU の数を判別します。以下に例を示します。
# oc describe node ip-172-31-27-209.us-west-2.compute.internal | egrep 'Capacity|Allocatable|gpu' openshift.com/gpu-accelerator=true Capacity: nvidia.com/gpu: 2 Allocatable: nvidia.com/gpu: 2 nvidia.com/gpu 0 0
この例では、2 つの GPU が利用可能です。
namespace
nvidia
にクォータを設定します。この例では、クォータは1
です。# cat gpu-quota.yaml apiVersion: v1 kind: ResourceQuota metadata: name: gpu-quota namespace: nvidia spec: hard: requests.nvidia.com/gpu: 1
クォータを作成します。
# oc create -f gpu-quota.yaml resourcequota/gpu-quota created
namespace に正しいクォータが設定されていることを確認します。
# oc describe quota gpu-quota -n nvidia Name: gpu-quota Namespace: nvidia Resource Used Hard -------- ---- ---- requests.nvidia.com/gpu 0 1
単一 GPU を要求する Pod を実行します。
# oc create pod gpu-pod.yaml
apiVersion: v1 kind: Pod metadata: generateName: gpu-pod- namespace: nvidia spec: restartPolicy: OnFailure containers: - name: rhel7-gpu-pod image: rhel7 env: - name: NVIDIA_VISIBLE_DEVICES value: all - name: NVIDIA_DRIVER_CAPABILITIES value: "compute,utility" - name: NVIDIA_REQUIRE_CUDA value: "cuda>=5.0" command: ["sleep"] args: ["infinity"] resources: limits: nvidia.com/gpu: 1
Pod が実行されていることを確認します。
# oc get pods NAME READY STATUS RESTARTS AGE gpu-pod-s46h7 1/1 Running 0 1m
クォータ
Used
のカウンターが正しいことを確認します。# oc describe quota gpu-quota -n nvidia Name: gpu-quota Namespace: nvidia Resource Used Hard -------- ---- ---- requests.nvidia.com/gpu 1 1
nvidia
namespace で 2 番目の GPU Pod の作成を試行します。2 つの GPU があるので、これをノード上で実行することは可能です。# oc create -f gpu-pod.yaml Error from server (Forbidden): error when creating "gpu-pod.yaml": pods "gpu-pod-f7z2w" is forbidden: exceeded quota: gpu-quota, requested: requests.nvidia.com/gpu=1, used: requests.nvidia.com/gpu=1, limited: requests.nvidia.com/gpu=1
クォータが 1 GPU であり、この Pod がそのクォータを超える 2 つ目の GPU の割り当てを試行したため、Forbidden エラーメッセージが表示されることが予想されます。
17.3. クォータのスコープ
各クォータには スコープ のセットが関連付けられます。クォータは、列挙されたスコープの交差部分に一致する場合にのみリソースの使用状況を測定します。
スコープをクォータに追加すると、クォータが適用されるリソースのセットを制限できます。許可されるセット以外のリソースを設定すると、検証エラーが発生します。
スコープ | 説明 |
---|---|
Terminating |
|
NotTerminating |
|
BestEffort |
|