OpenShift(以下OCP)をベアメタルのUPIの方法で導入する際には、前提としてAPIのロードバランサーとアプリケーションIngressのロードバランサーが必要です。
少し昔のOCPのドキュメントでは、Kubernetes APIサーバー(Port: 6443)用とMachine Configサーバー(Port: 22623)用のAPIロードバランサーと、HTTPSトラフィック(Port: 443)用とHTTPトラフィック(Port: 80)用のアプリケーションIngressロードバランサーのどちらについても、ただ単にLayer 4のロードバランサーが必要で、ポート番号とバックエンドマシン(プールメンバー)の情報ぐらいしか記載がなかった様に思います。
但し、ちょっと(と言っても結構)前から、OCPのドキュメントには、これらのPort番号とバックエンドマシンの情報に加えて、Kubernetes APIサーバー(Port: 6443)用のロードバランサーについては、ヘルスチェックのエンドポイントの情報(/readyz
)が記載される様になっていました。
-
- (上述はインターネット非接続環境のベアメタルのUPIの場合のリンクですが、インターネット非接続ではない場合のドキュメントのリンクの場所でも記載内容は同じです。)
- (しかもこれらは現在最新のOCP 4.6のドキュメントだけではなく、OCP 4.3などの過去のOCPのバージョンのドキュメントにわたって更新されている模様です。)
ですので、今回はOCPのドキュメントに従ってHAProxyにヘルスチェックの設定を追加してみたいと思います。
(2022/09/21追記)
「Qiita / OpenShift 4.10 ベアメタルUPI (iPXE) インストール / ロードバランサー」の方では、設定内容を少し更新しました。ただ、以下の記載自体も参考になると思いますのでそのまま残しておきます。
(追記終わり)
Kubernetes APIサーバー(Port: 6443)の/readyz
エンドポイント
- master nodeが正常な場合は「ok」と表示され、HTTPの戻り値は「200」となります。
[user01@bastion-01 ~]$ curl https://master-01.test2.example.local:6443/readyz -k
ok[user01@bastion-01 ~]$
[user01@bastion-01 ~]$
[user01@bastion-01 ~]$ curl https://master-01.test2.example.local:6443/readyz -k -o /dev/null -w '%{http_code}\n' -s
200
[user01@bastion-01 ~]$
- master nodeに障害がある場合は返答がなく、HTTPの戻り値は「000」になります。(ステータスコードを返さない)
[user01@bastion-01 ~]$ curl https://master-01.test2.example.local:6443/readyz -k
curl: (7) Failed connect to master-01.test2.example.local:6443; 接続を拒否されました
[user01@bastion-01 ~]$
[user01@bastion-01 ~]$ curl https://master-01.test2.example.local:6443/readyz -k -o /dev/null -w '%{http_code}\n' -s
000
[user01@bastion-01 ~]$
前提の環境
今回はインターネット非接続環境でベアメタルのUPIの方法でOCP4.4を導入しています。
また、以下のQiitaの記事と同じ様に、役割ごとに専用のInfra nodeを構成しています。
node名 | ノードの役割 | 備考 |
---|---|---|
master-0[1-3] | master | master node |
worker-0[1-2] | worker | worker node(アプリケーションPod用) |
infra-0[1-3] | infra | ルーター、内部レジストリー用 |
infra-mon-0[1-3] | infra(logging) | モニタリング用 |
infra-log-0[1-3] | infra(monitoring) | ロギング用 |
- 検証環境のOCPのバージョンは少し古いですが、今回のロードバランサーの設定内容はOCP 4.6のドキュメントでも同じだったため、この記事ではドキュメントのリンクはOCP 4.6のリンクを添付します。)
今までの設定 (ヘルスチェックプローブの設定なし)
検証環境でベアメタルのUPIの方法でOCPを導入する際に昔はHAProxyでは大体以下の様な設定をしていました。
- Kubernetes APIサーバー(Port: 6443)の
mode
はtcp
(L4のロードバランサー) - Kubernetes APIサーバー(Port: 6443)のバックエンドは
option ssl-hello-chk
のチェックのみ
(参考)
/etc/haproxy/haproxy.conf
の設定例
(global、defaultのセクションはデフォルトのまま)
(略)
frontend K8s-api
bind *:6443
option tcplog
mode tcp
default_backend api-6443
frontend Machine-config
bind *:22623
option tcplog
mode tcp
default_backend config-22623
frontend Ingress-http
bind *:80
option tcplog
mode tcp
default_backend http-80
frontend Ingress-https
bind *:443
option tcplog
mode tcp
default_backend https-443
backend api-6443
mode tcp
balance roundrobin
option ssl-hello-chk
# server bootstrap-01 bootstrap-01.test2.example.local:6443 check
server master-01 master-01.test2.example.local:6443 check
server master-02 master-02.test2.example.local:6443 check
server master-03 master-03.test2.example.local:6443 check
backend config-22623
mode tcp
balance roundrobin
# server bootstrap-01 bootstrap-01.test2.example.local:22623 check
server master-01 master-01.test2.example.local:22623 check
server master-02 master-02.test2.example.local:22623 check
server master-03 master-03.test2.example.local:22623 check
backend http-80
mode tcp
balance roundrobin
server infra-01 infra-01.test2.example.local:80 check
server infra-02 infra-02.test2.example.local:80 check
server infra-03 infra-03.test2.example.local:80 check
backend https-443
mode tcp
balance roundrobin
option ssl-hello-chk
server infra-01 infra-01.test2.example.local:443 check
server infra-02 infra-02.test2.example.local:443 check
server infra-03 infra-03.test2.example.local:443 check
今回の設定 (ヘルスチェックプローブの設定あり)
要件の確認
先ほども記載した様に、最近のOCP 4.6のドキュメントでは、Kubernetes APIサーバー(Port: 6443)用のAPIロードバランサーについては、ヘルスチェックのエンドポイントとして/readyz
の情報が追記されています。
(抜粋)
- API ロードバランサー: プラットフォームと対話およびプラットフォームを設定するためのユーザー向けの共通のエンドポイントを提供します。以下の条件を設定します。
- Layer 4 の負荷分散のみ。これは、Raw TCP、SSL パススルー、または SSL ブリッジモードと呼ばれます。
(略)
表1.20 API ロードバランサー
ポート バックエンドマシン (プールメンバー) 内部 外部 説明 6443 ブートストラップおよびコントロールプレーン。ブートストラップマシンがクラスターのコントロールプレーンを初期化した後に、ブートストラップマシンをロードバランサーから削除します。API サーバーのヘルスチェックプローブの /readyz
エンドポイントを設定する必要があります。X X Kubernetes API サーバー 22623 ブートストラップおよびコントロールプレーン。ブートストラップマシンがクラスターのコントロールプレーンを初期化した後に、ブートストラップマシンをロードバランサーから削除します。 X マシン設定サーバー
注記
ロードバランサーは、API サーバーが/readyz
エンドポイントをオフにしてからプールから API サーバーインスタンスを削除するまで最大 30 秒かかるように設定する必要があります。/readyz
の後の時間枠内でエラーが返されたり、正常になったりする場合は、エンドポイントが削除または追加されているはずです。5 秒または 10 秒ごとにプローブし、2 つの正常な要求が正常な状態になり、3 つの要求が正常な状態になりません。これらは十分にテストされた値です
(日本語の注記がよくわからない場合はちゃんと英語版のドキュメントも合わせて参照...)
NOTE
The load balancer must be configured to take a maximum of 30 seconds from the time the API server turns off the/readyz
endpoint to the removal of the API server instance from the pool. Within the time frame after/readyz
returns an error or becomes healthy, the endpoint must have been removed or added. Probing every 5 or 10 seconds, with two successful requests to become healthy and three to become unhealthy, are well-tested values.
設定方法
先ほどの記述だけだけだとHAProxyに具体的にどのように設定すればよいのかすぐにはわからなかったので、少し検索してみたところ、OpenShiftのinstallerのGitHubに参考になりそうな情報がありました。
(vSphereのUPIの場合のインストーラーのロードバランサーの設定のテンプレート??)
defaults
(略)
mode tcp
(略)
frontend api-server
bind ${lb_ip_address}:6443
default_backend api-server
(略)
backend api-server
option httpchk GET /readyz HTTP/1.0
option log-health-checks
balance roundrobin
%{ for addr in api ~}
server ${addr} ${addr}:6443 weight 1 verify none check check-ssl inter 1s fall 2 rise 3
%{ endfor ~}
(略)
-
mode
はtcp
(L4のロードバランサー) - ヘルスチェックのエンドポイント
/readyz
に関する設定として、option httpchk GET /readyz HTTP/1.0
の定義を追加 -
server
ではserver ${addr} ${addr}:6443 weight 1 verify none check check-ssl inter 1s fall 2 rise 3
と設定- バックエンドのサーバーに重みはつけないので全て
weight 1
と設定 - 自己署名証明書を使用するので
verify none
を追加 -
check
でヘルスチェックを有効にする -
option httpchk
とSSL checkを組み合わせて使用するため、check-ssl
オプションを追加 -
inter 1s fall 2 rise 3
では1秒ごとにヘルスチェックをし、失敗2回でエンドポイントを削除し、成功3回でエンドポイントを追加している様に思われる
- バックエンドのサーバーに重みはつけないので全て
今回の設定内容
上述の設定値は今回のOCPのドキュメントに記載があった設定値とは少し違いますが、設定項目は参考になると思いますので、上述の設定項目を参考に、今回のOCPのドキュメントに記載のロードバランサーの要件に従って、検証環境のHAProxyに以下の様に設定を追加してみました。
-
mode
はtcp
(L4のロードバランサー) - ヘルスチェックのエンドポイント
/readyz
に関する設定として、option httpchk GET /readyz HTTP/1.0
の定義を追加 -
server
ではserver ${addr} ${addr}:6443 weight 1 verify none check check-ssl inter [5|10]s fall 3 rise 2
と設定- バックエンドのサーバーに重みはつけないので全て
weight 1
と設定 - 自己署名証明書を使用するので
verify none
を追加 -
check
でヘルスチェックを有効になる。 -
option httpchk
とSSL checkを組み合わせて使用するため、check-ssl
オプションを追加 - OCPのドキュメントでは、ヘルスチェックの間隔は5秒または10秒で、2回成功でエンドポイントを追加し、3回失敗でエントポイントを削除するのが「これらは十分にテストされた値です」とのことなので、
inter [5|10]s fall 3 rise 2
と設定してみる - (最初は一旦10秒にしてみる)
- バックエンドのサーバーに重みはつけないので全て
inter 10 fall 3 rise 2
の場合の/etc/haproxy/haproxy.conf
の設定例
(global、defaultのセクションはデフォルトのまま)
(略)
frontend K8s-api
bind *:6443
option tcplog
mode tcp
default_backend api-6443
frontend Machine-config
bind *:22623
option tcplog
mode tcp
default_backend config-22623
frontend Ingress-http
bind *:80
option tcplog
mode tcp
default_backend http-80
frontend Ingress-https
bind *:443
option tcplog
mode tcp
default_backend https-443
backend api-6443
mode tcp
option httpchk GET /readyz HTTP/1.0
option log-health-checks
balance roundrobin
# server bootstrap-01 bootstrap-01.test2.example.local:6443 weight 1 verify none check check-ssl inter 10s fall 3 rise 2
server master-01 master-01.test2.example.local:6443 weight 1 verify none check check-ssl inter 10s fall 3 rise 2
server master-02 master-02.test2.example.local:6443 weight 1 verify none check check-ssl inter 10s fall 3 rise 2
server master-03 master-03.test2.example.local:6443 weight 1 verify none check check-ssl inter 10s fall 3 rise 2
backend config-22623
mode tcp
balance roundrobin
# server bootstrap-01 bootstrap-01.test2.example.local:22623 check
server master-01 master-01.test2.example.local:22623 check
server master-02 master-02.test2.example.local:22623 check
server master-03 master-03.test2.example.local:22623 check
backend http-80
mode tcp
balance roundrobin
server infra-01 infra-01.test2.example.local:80 check
server infra-02 infra-02.test2.example.local:80 check
server infra-03 infra-03.test2.example.local:80 check
backend https-443
mode tcp
balance roundrobin
option ssl-hello-chk
server infra-01 infra-01.test2.example.local:443 check
server infra-02 infra-02.test2.example.local:443 check
server infra-03 infra-03.test2.example.local:443 check
設定の反映(haproxyの再起動)
$ sudo systemctl restart haproxy
$ sudo systemctl status haproxy
稼働確認
任意のmaster nodeの1台に障害があっても、ロードバランサーが障害のあったnodeをエンドポイントから切り離し、ocコマンドなどは継続して実行できるというのがあるべき姿だと思います。
そこで、今までの設定(ヘルスチェックプローブの設定なし)の場合と、今回の設定(ヘルスチェックProbeの設定あり)の場合に、master nodeを1台再起動中にocコマンドを1秒毎に繰り返し実行して挙動を確認してみてみました。
確認手順
-
一秒ごとに
oc get node master-01
を実行し続ける。$ while true; do date; oc get node master-01; sleep 1; done
-
別terminalを開いてmaster-01を再起動する。
ssh -i .ssh/<ssh key> core@master-01 sudo shutdown -r now
-
oc get node
コマンドが実行できない時間を比較してみる。
今までの設定(ヘルスチェックプローブの設定なし)の場合
- master-01を再起動
[user01@bastion-01 ~]$ date; ssh -i .ssh/ocp_rsa core@master-01 sudo shutdown -r now
2020年 12月 30日 水曜日 20:05:10 JST
Connection to master-01 closed by remote host.
[user01@bastion-01 ~]$
-
oc get node master-01
の実行結果- ReadyからNotReadyになる際に、実行毎に30秒から1分ぐらいコマンドが返ってこず、
Unable to connect to the server: unexpected EOF
やError from server (Timeout): the server was unable to return a response in the time allotted, but may still be processing the request (get nodes master-01)
が表示されることがありました。 - NotReadyからReadyになる際は特に途切れはありませんでした。
- ReadyからNotReadyになる際に、実行毎に30秒から1分ぐらいコマンドが返ってこず、
(以下は50秒ぐらいでerror: You must be logged in to the server (Unauthorized)
が出力された例)
[user01@bastion-01 ~]$ while true; do date; oc get node master-01; sleep 1; done
(略)
2020年 12月 30日 水曜日 20:05:15 JST
NAME STATUS ROLES AGE VERSION
master-01 Ready master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 20:05:16 JST
error: You must be logged in to the server (Unauthorized)
2020年 12月 30日 水曜日 20:06:06 JST
NAME STATUS ROLES AGE VERSION
master-01 NotReady master 59d v1.17.1+c5fd4e8
(略)
2020年 12月 30日 水曜日 20:07:24 JST
NAME STATUS ROLES AGE VERSION
master-01 NotReady master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 20:07:25 JST
NAME STATUS ROLES AGE VERSION
master-01 NotReady master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 20:07:27 JST
NAME STATUS ROLES AGE VERSION
master-01 Ready master 59d v1.17.1+c5fd4e8
(以下は60秒ぐらいでError from server (Timeout): the server was unable to return a response in the time allotted, but may still be processing the request (get nodes master-01)
が出力された例)
2020年 12月 30日 水曜日 20:23:00 JST
NAME STATUS ROLES AGE VERSION
master-01 Ready master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 20:23:01 JST
Error from server (Timeout): the server was unable to return a response in the time allotted, but may still be processing the request (get nodes master-01)
2020年 12月 30日 水曜日 20:24:02 JST
NAME STATUS ROLES AGE VERSION
master-01 NotReady master 59d v1.17.1+c5fd4e8
今回の設定(ヘルスチェックプローブの設定あり)の場合
ヘルスチェック間隔10秒の場合
- master-01を再起動
[user01@bastion-01 ~]$ date; ssh -i .ssh/ocp_rsa core@master-01 sudo shutdown -r now
2020年 12月 30日 水曜日 19:35:46 JST
Connection to master-01 closed by remote host.
[user01@bastion-01 ~]$
-
oc get node master-01
の実行結果- ReadyからNotReadyになる際に、大体30秒ぐらいコマンドが返ってこず、1-2回
error: You must be logged in to the server (Unauthorized)
のメッセージが表示されました。 - NotReadyからReadyになる際は特に途切れはありませんでした。
- ReadyからNotReadyになる際に、大体30秒ぐらいコマンドが返ってこず、1-2回
(以下は30秒ぐらいでerror: You must be logged in to the server (Unauthorized)
が出力された例)
[user01@bastion-01 ~]$ while true; do date; oc get node master-01; sleep 1; done
(略)
2020年 12月 30日 水曜日 19:35:51 JST
NAME STATUS ROLES AGE VERSION
master-01 Ready master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 19:35:52 JST
NAME STATUS ROLES AGE VERSION
master-01 Ready master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 19:35:53 JST
NAME STATUS ROLES AGE VERSION
master-01 Ready master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 19:35:54 JST
error: You must be logged in to the server (Unauthorized)
2020年 12月 30日 水曜日 19:36:25 JST
NAME STATUS ROLES AGE VERSION
master-01 NotReady master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 19:36:26 JST
NAME STATUS ROLES AGE VERSION
master-01 NotReady master 59d v1.17.1+c5fd4e8
(略)
2020年 12月 30日 水曜日 19:38:00 JST
NAME STATUS ROLES AGE VERSION
master-01 NotReady master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 19:38:01 JST
NAME STATUS ROLES AGE VERSION
master-01 Ready master 59d v1.17.1+c5fd4e8
ヘルスチェック間隔5秒の場合
- master-01を再起動
[user01@bastion-01 ~]$ date; ssh -i .ssh/ocp_rsa core@master-01 sudo shutdown -r now
2020年 12月 30日 水曜日 22:45:56 JST
Connection to master-01 closed by remote host.
[user01@bastion-01 ~]$
-
oc get node master-01
の実行結果- ReadyからNotReadyになる辺りで、大体は30-50秒ぐらいコマンドが返ってこず、1-2回
error: You must be logged in to the server (Unauthorized)
のメッセージが表示されました。 - NotReadyからReadyになる際は特に途切れはありませんでした。
- ReadyからNotReadyになる辺りで、大体は30-50秒ぐらいコマンドが返ってこず、1-2回
(以下は30秒ちょっとでerror: You must be logged in to the server (Unauthorized)
が出力された例)
$ while true; do date; oc get node master-01; sleep 1; done
(略)
2020年 12月 30日 水曜日 22:46:04 JST
NAME STATUS ROLES AGE VERSION
master-01 Ready master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 22:46:06 JST
error: You must be logged in to the server (Unauthorized)
2020年 12月 30日 水曜日 22:46:39 JST
NAME STATUS ROLES AGE VERSION
master-01 NotReady master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 22:46:40 JST
NAME STATUS ROLES AGE VERSION
master-01 NotReady master 59d v1.17.1+c5fd4e8
(略)
2020年 12月 30日 水曜日 22:48:11 JST
NAME STATUS ROLES AGE VERSION
master-01 NotReady master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 22:48:12 JST
NAME STATUS ROLES AGE VERSION
master-01 Ready master 59d v1.17.1+c5fd4e8
2020年 12月 30日 水曜日 22:48:13 JST
NAME STATUS ROLES AGE VERSION
master-01 Ready master 59d v1.17.1+c5fd4e8
まとめ
OCPのドキュメントにあるKubernetes APIサーバー(Port: 6443)用のロードバランサーのヘルスチェックのエンドポイントとして/readyz
をHAProxyに設定してみました。
コマンドが戻ってこない時間などは以前と比べて多少は改善した(様な気がする)ものの、/readyz
へのヘルスチェックを間隔10秒、失敗3回、成功2回に設定した場合も、間隔5秒、失敗3回、成功2回にした場合のいずれも30秒程度コマンドが返ってこないタイミングがありました。
(やってみた感じでは、間隔5秒の場合はコマンドが返ってくるタイミングはまちまちでしたが、間隔10秒の場合は30秒程度でコマンドが返ってくる感じで、大体同じ挙動をしていました。)
もし、ocコマンドなどでステータスを取得するような運用スクリプトなどを作成している場合は、このあたりの検証結果を参考に、コマンドのリトライ間隔や回数などを検討する必要があると思います。