OpenShiftのInfra nodeでoc debug nodeがエラーになった場合の対処方法


# 概要

Infra nodeで`oc debug node`を実行した際に、NodeAffinityのエラーで失敗した場合の対応策のメモを記載します。

```bash
[root@bastion-01 ~]# oc debug node/infra-01
Starting pod/infra-01-debug ...
To use host binaries, run `chroot /host`

Removing debug pod ...
error: debug pod could not be scheduled: Pod Predicate NodeAffinity failed. To fix this you may want to create a new namespace with empty node selector and run the debug there. For example: oc adm new-project --node-selector="" debug
[root@bastion-01 ~]#
```

# 構成

**バージョン**
```bash
[root@bastion-01 ~]# oc version
Client Version: 4.10.20
Server Version: 4.10.20
Kubernetes Version: v1.23.5+3afdacb
[root@bastion-01 ~]#
```

**Infra nodeの構成**
- 「[OpenShiftでMachine Config Pool (MCP) を使用してInfra nodeを作成する](https://qiita.com/t_sweetfish/items/a81d23f85c2c18326755)」の手順で作成しています。
- 「infra nodeの構成方法」は「[(1) infra node専用の「MCP」を作成](https://qiita.com/t_sweetfish/items/a81d23f85c2c18326755#1-infra-node%E5%B0%82%E7%94%A8%E3%81%AEmcp%E3%82%92%E4%BD%9C%E6%88%90)」で構成しています。
- 「アプリケーションPodをinfra nodeで稼働させない設定」は「[(1) nodeSelectorのみを使用](https://qiita.com/t_sweetfish/items/a81d23f85c2c18326755#1-nodeselector%E3%81%AE%E3%81%BF%E3%82%92%E4%BD%BF%E7%94%A8)」で実施しています。 

# 事象

上述の構成で、以下の条件を満たしている場合には、`oc debug node`が`node-selector`に関するエラーで失敗することがあります。
今回はこのような場合の対応策をメモとして残しておきます。

(1) defaultNodeSelector、もしくはアプリケーションPod用のProject(namespace)に、worker nodeのノードラベルを指定している

- 今回はクラスターワイドのdefaultNodeSelectorには何も指定せず、アプリケーションPod用の`test`という名前のProject(Namespace)のnode selectorにworker nodeのノードラベルを指定しています。

```bash
[root@bastion-01 ~]# oc get namespace test -o yaml
apiVersion: v1
kind: Namespace
metadata:
annotations:
    (略)
    openshift.io/node-selector: node-role.kubernetes.io/worker=
(略)
```

- クラスターワイドのdefaultNodeSelectorには特に何も設定していませんでした。

```bash
[root@bastion-01 ~]# oc get scheduler cluster -o yaml
apiVersion: config.openshift.io/v1
kind: Scheduler
metadata:
(略)
spec:
mastersSchedulable: false
policy:
    name: ""
status: {}
[root@bastion-01 ~]#
```

(2) 現在のContextがアプリケーションPod用のProject(namespace)になっている

```bash
[root@bastion-01 ~]# oc project
Using project "test" on server "https://api.cluster-01.example.local:6443".
[root@bastion-01 ~]#
```
<br>

(1)(2)を満たす場合に、`oc debug node`がエラーで失敗します。

```bash
[root@bastion-01 ~]# oc debug node/infra-01
Starting pod/infra-01-debug ...
To use host binaries, run `chroot /host`

Removing debug pod ...
error: debug pod could not be scheduled: Pod Predicate NodeAffinity failed. To fix this you may want to create a new namespace with empty node selector and run the debug there. For example: oc adm new-project --node-selector="" debug
[root@bastion-01 ~]#
```

# 対応策

対応策は以下のKBに記載されています。<br>
KBでは、OCPの古いバージョンでdefaultNodeSelectorを設定している場合の対応策が記載されていますが、アプリケーションPod用のProject(Namespace)単位でnode Selectorを設定している場合も原因は同じことなので、対応策はこのKBに記載の方法でできます。<br>

- [KB / Infrastructure Nodes in OpenShift 4](https://access.redhat.com/solutions/5034771)

    > Note: Prior to a bugfix in 4.6.1, oc debug node would not work on master or infra nodes after changing the defaultNodeSelector from the installation default. This issue is described in [RHBZ #1812813](https://bugzilla.redhat.com/show_bug.cgi?id=1812813) and [oc debug node Fails When a Default nodeSelector is Defined](https://access.redhat.com/solutions/4982331)


- [KB / oc debug node Fails When a Default nodeSelector is Defined](https://access.redhat.com/solutions/4982331)

    KBに記載の手順は、`oc debug node`に失敗した際のerrorメッセージで対応策として表示されるコマンドと同じなので、このKBの手順で対応は間違っていないと思います。

# 対応手順

node-selectorを明示的に設定しない`debug`用の新しいProject(Namespace)を作成します。

```bash
[root@bastion-01 ~]# oc adm new-project --node-selector="" debug
Created project debug
[root@bastion-01 ~]#
[root@bastion-01 ~]# oc get namespace debug -o yaml
apiVersion: v1
kind: Namespace
metadata:
  annotations:
    (略)
    openshift.io/node-selector: ""
    (略)
[root@bastion-01 ~]#
```

この`debug`用のnamespaceを指定して`oc debug node`を実行すると、infra nodeでも正常に`oc debug node`が実行できるようになりました。

```bash
[root@bastion-01 ~]# oc debug node/infra-01 -n debug
Starting pod/infra-01-debug ...
To use host binaries, run `chroot /host`
Pod IP: 172.16.100.17
If you don't see a command prompt, try pressing enter.
sh-4.4# chroot /host
sh-4.4#
sh-4.4# exit
exit
sh-4.4# exit
exit

Removing debug pod ...
[root@bastion-01 ~]#
```

また、master nodeも正常に実行できるようになっています。

# (補足)

`oc debug node`を実行する際に一時的に作成される`debug`用のPodは、現在のContextのProject(Namespace)に作成されていました。

(昔はこの[KB](https://access.redhat.com/solutions/6152592)みたいに一時的な`openshift-debug-node` namespaceに作成されてた気がするのですが変わってたんですかね...)

<br>

**対応策実施前** 
現在のContextがアプリケーションPod用のProject(Namespace)の場合には、node selectorにはworker nodeのノードラベルが指定されているので、infra nodeには`debug`用のPodが作成できずに`oc debug node`は失敗していました。

```bash
[root@bastion-01 ~]# oc get pod -n test -w
NAME             READY   STATUS    RESTARTS   AGE
infra-01-debug   0/1     Pending   0          0s
infra-01-debug   0/1     NodeAffinity   0          0s
infra-01-debug   0/1     Terminating    0          0s
infra-01-debug   0/1     Terminating    0          0s
^C[root@bastion-01 ~]#
```

**対応策実施後** 
今回の対応策を実施した後は、新規作成した`debug`用のProject(Namespace)を指定して`oc debug node`実行すると、空のnode selectorが設定されているので、エラーがなく正常にコマンドが実行することができました。
```bash
[root@bastion-01 ~]# oc get pod -n debug -w
NAME             READY   STATUS    RESTARTS   AGE
infra-01-debug   0/1     Pending   0          0s
infra-01-debug   0/1     ContainerCreating   0          0s
infra-01-debug   1/1     Running             0          1s
```