第2章 Managing Nodes
2.1. 概要
You can manage nodes in your instance using the CLI.
When you perform node management operations, the CLI interacts with node objects that are representations of actual node hosts. The master uses the information from node objects to validate nodes with health checks.
2.2. Listing Nodes
マスターに認識されるすべてのノードを一覧表示するには、以下を実行します。
$ 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
To only list information about a single node, replace <node>
with the full node name:
$ oc get node <node>
これらのコマンドの出力にある STATUS
列には、ノードの以下の状態が表示されます。
条件 | 説明 |
---|---|
|
ノードは |
|
ノードはマスターから実行されるヘルスチェックをパスしていません。 |
|
ノードへの Pod の配置をスケジュールできません。 |
STATUS
列には、CLI でノードの状態を検索できない場合にノードについて Unknown
が表示されます。
現在の状態の理由を含む特定ノードについての詳細情報を取得するには、以下を実行します。
$ oc describe node <node>
例:
$ oc describe node node1.example.com Name: node1.example.com Labels: kubernetes.io/hostname=node1.example.com CreationTimestamp: Wed, 10 Jun 2015 17:22:34 +0000 Conditions: Type Status LastHeartbeatTime LastTransitionTime Reason Message Ready True Wed, 10 Jun 2015 19:56:16 +0000 Wed, 10 Jun 2015 17:22:34 +0000 kubelet is posting ready status Addresses: 127.0.0.1 Capacity: memory: 1017552Ki pods: 100 cpu: 2 Version: Kernel Version: 3.17.4-301.fc21.x86_64 OS Image: Fedora 21 (Twenty One) Container Runtime Version: docker://1.6.0 Kubelet Version: v0.17.1-804-g496be63 Kube-Proxy Version: v0.17.1-804-g496be63 ExternalID: node1.example.com Pods: (2 in total) docker-registry-1-9yyw5 router-1-maytv No events.
2.3. Adding Nodes
To add nodes to your existing OpenShift Container Platform cluster, you can run an Ansible playbook that handles installing the node components, generating the required certificates, and other important steps. See the advanced installation method for instructions on running the playbook directly.
Alternatively, if you used the quick installation method, you can re-run the installer to add nodes, which performs the same steps.
2.4. Deleting Nodes
When you delete a node using the CLI, the node object is deleted in Kubernetes, but the pods that exist on the node itself are not deleted. Any bare pods not backed by a replication controller would be inaccessible to OpenShift Container Platform, pods backed by replication controllers would be rescheduled to other available nodes, and local manifest pods would need to be manually deleted.
OpenShift Container Platform クラスターからノードを削除するには、以下を実行します。
- 削除しようとしているノードからPod を退避します。
ノードオブジェクトを削除します。
$ oc delete node <node>
ノードがノード一覧から削除されていることを確認します。
$ oc get nodes
Pod は、Ready 状態にある残りのノードに対してのみスケジュールされます。
- If you want to uninstall all OpenShift Container Platform content from the node host, including all pods and containers, continue to Uninstalling Nodes and follow the procedure using the uninstall.yml playbook. The procedure assumes general understanding of the advanced installation method using Ansible.
2.5. Updating Labels on Nodes
To add or update labels on a node:
$ oc label node <node> <key_1>=<value_1> ... <key_n>=<value_n>
詳細な使用法を表示するには、以下を実行します。
$ oc label -h
2.6. Listing Pods on Nodes
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.7. Marking Nodes as Unschedulable or 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.8. Evacuating Pods on Nodes
Evacuating pods allows you to migrate all or selected pods from a given node or nodes. Nodes must first be marked unschedulable to perform pod evacuation.
Only pods backed by a replication controller can be evacuated; the replication controllers create new pods on other nodes and remove the existing pods from the specified node(s). Bare pods, meaning those not backed by a replication controller, are unaffected by default.
To evacuate all or selected pods on one or more nodes:
$ oc adm drain <node1> <node2> [--pod-selector=<pod_selector>]
--force
オプションを使用すると、ベア Pod の削除を強制的に実行できます。true
に設定されると、Pod がレプリケーションコントローラー、ReplicaSet、ジョブ、daemonset、または StatefulSet で管理されていない場合でも削除が続行されます。
$ oc adm drain <node1> <node2> --force=true
You can use --grace-period
to set a period of time in seconds for each pod to terminate gracefully. If negative, the default value specified in the pod will be used:
$ oc adm drain <node1> <node2> --grace-period=-1
--ignore-daemonsets
を使用し、これを true
に設定すると、Deamonset で管理された Pod を無視できます。
$ oc adm drain <node1> <node2> --ignore-daemonset=true
--timeout
を使用すると、中止する前の待機期間を設定できます。値 0
は無限の時間を設定します。
$ oc adm drain <node1> <node2> --timeout=5s
You can use --delete-local-data
and set it to true
to continue deletion even if there are pods using emptyDir (local data that will be deleted when the node is drained):
$ oc adm drain <node1> <node2> --delete-local-data=true
退避を実行せずに移行するオブジェクトを一覧表示するには、--dry-run
オプションを使用し、これを true
に設定します。
$ oc adm drain <node1> <node2> --dry-run=true
Instead of specifying specific node names (for example, <node1> <node2>
), you can use the --selector=<node_selector>
option to evacuate pods on selected nodes.
2.9. Rebooting Nodes
プラットフォームで実行されるアプリケーションを停止せずにノードを再起動するには、まず Pod の退避を実行する必要があります。ルーティング階層によって可用性が高くされている Pod については、何も実行する必要はありません。ストレージ (通常はデータベース) を必要とするその他の Pod については、それらが 1 つの Pod が一時的にオフラインになっても作動したままになることを確認する必要があります。ステートフルな Pod の回復性はアプリケーションごとに異なりますが、いずれの場合でも、ノードの非アフィニティー (node anti-affinity) を使用して Pod が使用可能なノード間に適切に分散するようにスケジューラーを設定することが重要になります。
別の課題として、ルーターやレジストリーのような重要なインフラストラクチャーを実行しているノードを処理する方法を検討する必要があります。同じノードの退避プロセスが適用されますが、一部のエッジケースについて理解しておくことが重要です。
2.9.1. Infrastructure Nodes
インフラストラクチャーノードは、OpenShift Container Platform 環境の一部を実行するためにラベルが付けられたノードです。現在、ノードの再起動を管理する最も簡単な方法として、インフラストラクチャーを実行するために利用できる 3 つ以上のノードを確保することができます。以下のシナリオでは、2 つのノードのみが利用可能な場合に OpenShift Container Platform で実行されるアプリケーションのサービスを中断しかねないよくある問題を示しています。
- ノード A がスケジュール対象外としてマークされており、すべての Pod の退避が行われている。
- このノードで実行されているレジストリー Pod がノード B に再デプロイされる。これは、ノード B が両方のレジストリー Pod を実行していることを意味します。
- ノード B はスケジュール対象外としてマークされ、退避が行われる。
- ノード B の 2 つの Pod エンドポイントを公開するサービスは、それらがノード A に再デプロイされるまでの短い期間すべてのエンドポイントを失う。
3 つのインフラストラクチャーノードを使用する同じプロセスではサービスの中断が生じません。しかし、Pod のスケジューリングにより、退避してローテーションに戻された最後のノードはゼロ (0) レジストリーを実行していることになり、他の 2 つのノードは 2 つのレジストリーと 1 つのレジストリーをそれぞれ実行します。最善の解決法として、Pod の非アフィニティーを使用できます。これは現在テスト目的で利用できる Kubernetes のアルファ機能ですが、実稼働ワークロードに対する使用はサポートされていません。
2.9.2. Using Pod Anti-affinity
Pod の非アフィニティーは、ノードの非アフィニティーとは若干異なります。ノードの非アフィニティーの場合、Pod のデプロイ先となる適切な場所がほかにない場合には違反が生じます。Pod の非アフィニティーの場合は required (必須) または preferred (優先) のいずれかに設定できます。
Using the docker-registry
pod as an example, the first step in enabling this feature is to set the scheduler.alpha.kubernetes.io/affinity
on the pod. Since this pod uses a deployment configuration, the most appropriate place to add the annotation is to the pod template’s metadata.
$ oc edit dc/docker-registry -o yaml ... template: metadata: annotations: scheduler.alpha.kubernetes.io/affinity: | { "podAntiAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": [{ "labelSelector": { "matchExpressions": [{ "key": "docker-registry", "operator": "In", "values":["default"] }] }, "topologyKey": "kubernetes.io/hostname" }] } }
scheduler.alpha.kubernetes.io/affinity
is internally stored as a string even though the contents are JSON. The above example shows how this string can be added as an annotation to a YAML deployment configuration.
This example assumes the Docker registry pod has a label of docker-registry=default
. Pod anti-affinity can use any Kubernetes match expression.
The last required step is to enable the MatchInterPodAffinity
scheduler predicate in /etc/origin/master/scheduler.json. With this in place, if only two infrastructure nodes are available and one is rebooted, the Docker registry pod is prevented from running on the other node. oc get pods
reports the pod as unready until a suitable node is available. Once a node is available and all pods are back in ready state, the next node can be restarted.
2.9.3. Handling Nodes Running Routers
ほとんどの場合、OpenShift Container Platform ルーターを実行する Pod はホストのポートを公開します。PodFitsPorts
スケジューラーの述語により、同じポートを使用するルーター Pod が同じノードで実行されないようにし、Pod の非アフィニティーが適用されます。ルーターの高可用性を維持するために IP フェイルオーバー を利用している場合には、他に実行することはありません。高可用性を確保するために AWS Elastic Load Balancing などの外部サービスを使用するルーター Pod の場合は、そのような外部サービスがルーター Pod の再起動に対して対応します。
In rare cases, a router pod may not have a host port configured. In those cases, it is important to follow the recommended restart process for infrastructure nodes.
2.10. ノードリソースの設定
You can configure node resources by adding kubelet arguments to the node configuration file (/etc/origin/node/node-config.yaml). Add the kubeletArguments
section and include any desired options:
kubeletArguments: max-pods: 1 - "40" resolv-conf: 2 - "/etc/resolv.conf" image-gc-high-threshold: 3 - "90" image-gc-low-threshold: 4 - "80"
利用可能なすべての kubelet オプションを表示するには、以下を実行します。
$ kubelet -h
This can also be set during an advanced installation using the openshift_node_kubelet_args
variable. For example:
openshift_node_kubelet_args={'max-pods': ['40'], 'resolv-conf': ['/etc/resolv.conf'], 'image-gc-high-threshold': ['90'], 'image-gc-low-threshold': ['80']}
2.10.1. Setting Maximum Pods Per Node
See the Cluster Limits page for the maximum supported limits for each version of OpenShift Container Platform.
/etc/origin/node/node-config.yaml ファイルでは、 pods-per-core
および max-pods
の 2 つのパラメーターがノードにスケジュールできる Pod の最大数を制御します。いずれのオプションも使用されている場合、2 つの内の小さい方の値でノードの Pod 数が制限されます。これらの値を超えると、以下の状況が発生します。
- OpenShift Container Platform と Docker の両方で CPU 使用率が増加する。
- Pod のスケジューリングの速度が遅くなる。
- メモリー不足のシナリオが生じる可能性がある (ノードのメモリー量によって異なる)。
- IP アドレスのプールを消費する。
- リソースのオーバーコミット、およびこれによるアプリケーションのパフォーマンスの低下。
Kubernetes では、単一コンテナーを保持する Pod は実際には 2 つのコンテナーを使用します。2 つ目のコンテナーは実際のコンテナーの起動前にネットワークを設定するために使用されます。そのため、10 の Pod を使用するシステムでは、実際には 20 のコンテナーが実行されていることになります。
pods-per-core
は、ノードのプロセッサーコア数に基づいてノードが実行できる Pod 数を設定します。たとえば、4 プロセッサーコアを搭載したノードで pods-per-core
が 10
に設定される場合、このノードで許可される Pod の最大数は 40 になります。
kubeletArguments: pods-per-core: - "10"
pods-per-core
を 0 に設定すると、この制限が無効になります。
max-pods
sets the number of pods the node can run to a fixed value, regardless of the properties of the node. Cluster Limits documents maximum supported values for max-pods
.
kubeletArguments: max-pods: - "250"
上記の例では、pods-per-core
のデフォルト値は 10
であり、max-pods
のデフォルト値は 250
です。これは、ノードにあるコア数が 25 以上でない限り、デフォルトでは pods-per-core
が制限を設定することになります。
2.11. Resetting Docker Storage
As you download Docker images and run and delete containers, Docker does not always free up mapped disk space. As a result, over time you can run out of space on a node, which might prevent OpenShift Container Platform from being able to create new pods or cause pod creation to take several minutes.
For example, the following shows pods that are still in the ContainerCreating
state after six minutes and the events log shows a FailedSync event.
$ 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
以下のコマンドを実行してノードをスケジュール対象としてマークします。
$ oc adm manage-node <node> --schedulable=true
2.12. Changing Node Traffic Interface
By default, DNS routes all node traffic. During node registration, the master receives the node IP addresses from the DNS configuration, and therefore accessing nodes via DNS is the most flexible solution for most deployments.
If your deployment is using a cloud provider, then the node gets the IP information from the cloud provider. However, openshift-sdn attempts to determine the IP through a variety of methods, including a DNS lookup on the nodeName (if set), or on the system hostname (if nodeName is not set).
However, you may need to change the node traffic interface. For example, where:
- OpenShift Container Platform is installed in a cloud provider where internal hostnames are not configured/resolvable by all hosts.
- The node’s IP from the master’s perspective is not the same as the node’s IP from its own perspective.
Configuring the openshift_set_node_ip
Ansible variable forces node traffic through an interface other than the default network interface.
To change the node traffic interface:
-
Set the
openshift_set_node_ip
Ansible variable totrue
. -
Set the
openshift_ip
to the IP address for the node you want to configure.
Although openshift_set_node_ip
can be useful as a workaround for the cases stated in this section, it is generally not suited for production environments. This is because the node will no longer function properly if it receives a new IP address.