Red Hat OpenShift on IBM Cloud on VPCで3台以上のノード構成時にロードバランサーのヘルスチェックに失敗するノードがある場合がある件への対応


事象

※2020年12月25日時点、OpenShift 4.5で確認しています

Red Hat OpenShift on IBM Cloud on VPCでクラスターを3台以上のノードで構成した際、デフォルトルーターのロードバランサーでヘルスチェックに失敗するノードがあります。

原因

ルーターのPodはレプリカ数2でデプロイされており、これが2つのノードに分散しています。つまり3台以上のノードがある場合は、Podがデプロイされないものが出てきます。

$ oc get pods -n openshift-ingress -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP             NODE
router-default-cf87dd6d-6s8xf   1/1     Running   0          2d19h   172.17.58.4    10.244.0.17
router-default-cf87dd6d-d2b7k   1/1     Running   0          2d19h   172.17.42.94   10.244.64.9

サービスのexternalTrafficPolicyを見てみます。

$ oc get svc router-default -n openshift-ingress -o yaml | grep " external"
  externalTrafficPolicy: Local

ここがLocalであることが原因です。このとき、ノードに到達したリクエストを転送するPodが同一ノードにないため、応答を返すことができません。

ちなみに該当ノードに直接リクエストを飛ばしてみると、次の挙動となりました。

$ curl 10.244.128.5:32727 &
[1] 4648
$ netstat -ano | grep 10.244.128.5:32727
tcp        0      0 10.244.10.7:49460       10.244.128.5:32727      ESTABLISHED keepalive (51.96/0/0)
$ kill %1

ソケットがESTABLISHEDかつkeepalivedになっているのがいまいちですね。これが何を意味するかというと、クライアント側またはサーバ側で明示的に通信を切断してくれないと、永遠に接続し続けてしまいます。

影響

結論からすると実影響はありません。該当ノードはヘルスチェックに失敗したことでロードバランサーから切り離されていますので、ユーザーからのリクエストが該当ノードに直接到達することはないからです。

影響があるとすれば、該当ノードのNodePortに直接接続したいケースですが、実運用でそのような構成をとることはないでしょう。何かしらのロードバランサーを経由するはずなので。

対応

実影響はありませんが、気持ち悪いので対応したい場合は、サービスのexternalTrafficPolicyをLocalではなくClusterに変更します。

$ oc patch svc router-default -n openshift-ingress -p '{"spec":{"externalTrafficPolicy":"Cluster"}}'
service/router-default patched
$ oc get svc router-default -n openshift-ingress -o yaml | grep " external"
  externalTrafficPolicy: Cluster

少し待つとロードバランサーのプールがヘルシーになります。

ノードへの直接接続もできるようになります。

$ curl 10.244.128.5:32727
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">

ただし、これによって通信の挙動が変わってしまうことは理解しておく必要があります。Localの場合、ロードバランサーから割り振られたノードへの通信はそのノード上のルーターPodが処理することになります。Clusterの場合、通信が割り振られたノードとは異なるノード上のルーターPodが処理をする場合があります。そのため、通信的にはわずかな遅延が発生することになります。

また、手動でサービスのマニフェストを変更していますが、OpenShiftの更新の際に戻ってしまう可能性もあります。しばらく様子を見たいと思います。